[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