[LLVMdev] Inlining
Dustin Laurence
dllaurence at dslextreme.com
Fri Jan 8 13:52:45 PST 2010
OK, I wanted to understand function inlining in LLVM but had avoided
going to the effort of finding out if the inlining was really happening.
The advice I got to "use the assembly source, Luke" suggested I go
ahead and investigate inlining for a bit of practice, since (so I
figured) even a monkey with really weak x86-fu could tell whether a
function call was happening or not.
If this monkey can tell, it isn't happening. :-) I'll try to provide
all useful information.
For my null test, I attempted to specify no inlining in a little program
that computes a Very Important Number :-) :
---
define fastcc i32 @foo(i32 %arg) noinline
{
%result = mul i32 %arg, 7
ret i32 %result
}
define i32
@main(i32 %argc, i8 **%argv)
{
%retVal = call fastcc i32 @foo(i32 6) noinline
ret i32 %retVal
}
---
and after my Makefile executed the following commands:
gemini:~/Projects/Nil/nil(0)$ make testInline.s testInline
llvm-as testInline.ll
llc -O0 -f testInline.bc
cc testInline.s -o testInline
rm testInline.bc
gemini:~/Projects/Nil/nil(0)$
we can compute that Very Important Number
gemini:~/Projects/Nil/nil(0)$ ./testInline ; echo $?
42
gemini:~/Projects/Nil/nil(0)$
and the generated assembly (with much red tape snipped for now):
---
.file "testInline.bc"
.text
.align 16
.globl foo
.type foo, at function
foo: # @foo
.Leh_func_begin1:
.LBB1_0:
imull $7, %edi, %eax
ret
.size foo, .-foo
.Leh_func_end1:
.align 16
.globl main
.type main, at function
main: # @main
.Leh_func_begin2:
.LBB2_0:
subq $8, %rsp
.Llabel1:
movl $6, %edi
call foo
addq $8, %rsp
ret
.size main, .-main
.Leh_func_end2:
---
Even this monkey (thinks he) can see the constant 6 being passed to foo
in %edi. So far so good.
Now I tried to get it to inline, without much luck. Putting together
everything I tried into one test, I changed 'noinline' to 'alwaysinline'
(and changing the linkage, as I gather that would be appropriate for
multiple files)
---
; testInline.ll -- test code for inlining.
define linkonce fastcc i32 @foo(i32 %arg) alwaysinline
{
%result = mul i32 %arg, 7
ret i32 %result
}
define i32
@main(i32 %argc, i8 **%argv)
{
%retVal = call fastcc i32 @foo(i32 6) alwaysinline
ret i32 %retVal
}
---
and bumped up the optimization level to O3:
rm -f nil c_defs c_defs.llh *.bc *.s *.o testInline # *.ll
gemini:~/Projects/Nil/nil(0)$ make testInline.s testInline
llvm-as testInline.ll
llc -O3 -f testInline.bc
cc testInline.s -o testInline
rm testInline.bc
gemini:~/Projects/Nil/nil(0)$
which generates
---
.file "testInline.bc"
.section .gnu.linkonce.t.foo,"ax", at progbits
.align 16
.weak foo
.type foo, at function
foo: # @foo
.Leh_func_begin1:
.LBB1_0:
imull $7, %edi, %eax
ret
.size foo, .-foo
.Leh_func_end1:
.text
.align 16
.globl main
.type main, at function
main: # @main
.Leh_func_begin2:
.LBB2_0:
subq $8, %rsp
.Llabel1:
movl $6, %edi
call foo
addq $8, %rsp
ret
.size main, .-main
.Leh_func_end2:
---
Which only differs in putting foo in a linkonce section instead of in
.text and in specifying (what I think is) .weak linkage instead of
.globl, so apparently the multiplication was not inlined.
There are no other differences in the snipped red-tape, I checked with diff.
What did monkey do wrong?
Dustin
More information about the llvm-dev
mailing list