[LLVMdev] Implementing platform specific library call simplification

John Criswell criswell at illinois.edu
Thu Feb 24 00:41:07 PST 2011


On 2/24/2011 1:21 AM, Chris Lattner wrote:
> On Feb 13, 2011, at 12:24 AM, Chris Lattner wrote:
>
>> On Feb 2, 2011, at 10:11 AM, Richard Osborne wrote:
>>> The newlib C library provides iprintf(), a restricted version of printf
>>> without support for floating-point formatting. I'd like to add an
>>> optimization which turns calls to printf() into calls to iprintf() if
>>> the format string has no floating point specifiers.
>> Cool, ok.  I can see how this would be very useful for a variety of embedded systems.
>>
>>> At the moment I've got this working locally by adding code to the
>>> simplify-libcalls pass. However this will break on targets where
>>> iprintf() isn't available. Is there a sensible place to add information
>>> about which library functions are available for a particular target?
>> I'd suggest adding a bool argument (HasIPrintf) to the createSimplifyLibCallsPass function and the pass constructor.  Then clang (or whatever is setting up the pass manager) can query the appropriate target info to pass down this flag.

Sorry to jump into something midstream, but I just happened to read the 
above paragraph and thought I should comment.  Adding a boolean argument 
to a pass's constructor method is one of the things I have learned not 
to do.  If I ever give a "How Not to Write an LLVM Pass" talk, this will 
be one of the things in the list.

The problem with boolean default arguments in pass constructors is that 
they make a pass more difficult to use within the opt and bugpoint 
tools.  Inevitably you'll find some bug that only occurs when the flag 
is set to a non-default value, you'll fire up bugpoint, pass in the 
arguments printed by your tool's -debug-pass=Arguments option, and then 
wonder why the bug doesn't trigger.  Eventually you find out that it's 
due to the boolean flag you put into the constructor not being set the 
way you want.  You then have to manually change the constructor in the 
source code, recompile, run bugpoint, and then remember to change it 
back before committing your fix.

Perhaps you can escape this problem because you're working on a pass 
that is hard-coded into opt and bugpoint, but it'll only work if opt and 
bugpoint and whatever special tool that this pass is incorporated into 
all set that boolean in the same way under the same conditions.  If 
someone uses it in a tool that sets it using some non-standard criteria, 
then you run into this problem.

We went through this with Automatic Pool Allocation and SAFECode: it was 
one of several things that made bugpoint inconvenient or impossible to use.

I have not actually fixed this problem in Poolalloc/SAFECode yet, but 
I've got the following ideas to try:

1) Create one version of your pass that sets the boolean flag to true 
and another version of your pass that sets the boolean flag to false.  
You can probably use C++ templates or inheritance to do this.  Register 
each pass as a separate pass and have your tool pick which pass to run 
based upon whatever conditions you want.

For example, the Poolalloc pass has to use either EQTDDataStructures or 
EQBUDataStructures pass depending on whether it is used for SAFECode.  
Right now it picks one based on a boolean constructor.  Instead, I would 
have the Poolalloc pass be a template that takes the name of the pass to 
use as input and create two passes:Poolalloc<EQTDDataStructures> and 
Poolalloc<EQBUDataStructures>.  SAFECode would use 
Poolalloc<EQTDDataStructures>.

2) Create an analysis group that tells your pass what to do (i.e., your 
pass calls a method on the analysis group to get the boolean flag).  
Create two immutable passes belonging to the group and return different 
values for the boolean flag.

Either of these techniques will ensure that any PassManager based tool 
can print out a string with -debug-pass=Arguments that can be fed into 
opt or bugpoint to reproduce the same behavior.

My 4 cents.

-- John T.

>> Longer term, I'd like to introduce a simple interface (via TargetRegistry) for exposing target libcall info.  This would be useful to eliminate the HAVE_FLOORF etc #defines in simplifylibcalls, which break cross compilation.
> Hi Richard,
>
> Just to close the loop on this, I went ahead and added a new llvm/Target/TargetLibraryInfo.h and added it to simplifylibcalls.  TargetLibraryInfo doesn't handle all the libcalls that SimplifyLibCalls handles yet, but it should provide a starting point for iprintf: just add an iprintf enum to TargetLibraryInfo and make your transformation predicated on TLI->has(LibFunc::iprintf).
>
> It would be great to see this go into mainline,
>
> -Chris
>
>
> _______________________________________________
> LLVM Developers mailing list
> LLVMdev at cs.uiuc.edu         http://llvm.cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev




More information about the llvm-dev mailing list