[LLVMdev] Cross-module function inlining

Nick Lewycky nicholas at mxc.ca
Wed Jan 13 21:20:23 PST 2010


Mark Muir wrote:
>
> On 13 Jan 2010, at 20:34, Nick Lewycky wrote:
>
>> On 13 January 2010 12:05, Mark Muir <mark.i.r.muir at gmail.com
>> <mailto:mark.i.r.muir at gmail.com>> wrote:
>>
>>
>>     But... now there's a small problem with library calls. Symbols
>>     such as 'memset', 'malloc', etc. are being removed by global dead
>>     code elimination. They are implemented in one of the bitcode
>>     modules that are linked together (implementations are based on
>>     newlib).
>>
>>
>> And what problems does that cause? If malloc is linked in, we're free
>> to inline it everywhere and delete the symbol. If you meant for it to
>> be visible to the optimizers but you don't want it to be part of the
>> code generated for your program (ie., you'll link it against newlib
>> later), you should mark the functions with available_externally linkage.
>
> Sorry, I should've been more clear - the calls to _malloc and _free
> weren't being inlined (see example below). I'm not sure why (happens
> with or without -simplify-libcalls). So, the resulting .bc file from
> 'opt' contains live references to symbols that were in its input .bc,
> but for some reason it stripped them.

Okay. Could you post an .ll (run 'llvm-dis < foo.bc') example of where 
this happens? Just the input and opt commands to run is fine. It's very 
frustrating to look at C and assembly when the problem is in the IR -> 
IR transform itself.

Nick

>     #include <stdlib.h>
>
>     int entries = 3;
>     int result;
>
>     int main()
>     {
>     int i;
>
>     // Allocate and populate the initial array.
>     int* values = malloc(entries * sizeof(int));
>     for (i = 0; i < entries; i ++)
>     values[i] = i + 1;
>
>     // Calculate the sum, using a dynamically allocated accumulator.
>     int* acc = malloc(sizeof(int));
>     *acc = 0;
>     for (i = 0; i < entries; i ++)
>     *acc += values[i];
>     result = *acc;
>
>     // Deallocate the memory.
>     free(values);
>     free(acc);
>
>     return 0;
>     }
>
>
> Here's a fragment of the final machine assembly (with -O3):
>
> _main:
> ADDCOMP out=r1 in1=r1 in2=4 conf=`ADDCOMP_SUB
> WMEM in=r2 in_addr=r1 conf=`WMEM_SI
> CONST_16B out=r3 conf=12
> JUMP nl_out=r2/*RA*/ addr_in=&_malloc conf=`JUMP_ALWAYS_ABS // Call
>
>
> In case this is important, here is the relevant declarations from the
> 'stdlib.h' that is in use:
>
>     _PTR _EXFUN(malloc,(size_t __size));
>     _VOID _EXFUN(free,(_PTR));
>
>
> where:
>
>     #define _PTR void *
>     #define _EXFUN(name, proto) name proto
>
>
> and from 'newlib.c':
>
>     void *
>     malloc (size_t sz)
>     {
>     ...
>     }
>
>
> i.e. They look like any other function call, which is why I suspect it
> has something to do with special behaviour given to built-ins.
>
>>
>> Alternately, if you wanted malloc, memset and friends to be externally
>> visible (compiled as part of your program and dlsym'able), you could
>> create a public api file which contains a one per line list of the
>> names of the functions that may not be marked internal linkage by
>> internalize. Pass that in to opt with -internalize-public-api-file
>> filename ...other flags...
>>
>
> I saw that. I was thinking of only using that option as a last resort,
> due to maintainability.
>
>>
>>     I guess I need help with the concept of built-ins, and what code
>>     is related to them in the Clang driver and back-end.
>
> Thanks.
>
> - Mark
>
>
>
> _______________________________________________
> 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