[LLVMdev] Need a clue to improve the optimization of some C code
Philip Reames
listmail at philipreames.com
Tue Mar 3 10:49:18 PST 2015
You'll need to prove a bit more information to get any useful response.
Questions:
1) What's you're use case? Are you using clang to compile C code? Are
you manually generating LLVM IR?
2) Are you tracking ToT? If you're not, you should be.
Depending on your use case, you might find this document useful:
http://llvm.org/docs/Frontend/PerformanceTips.html
On 03/03/2015 06:06 AM, Nat! wrote:
> Hi
>
> I have some inline function C code, that llvm could be optimizing better.
> Since I am new to this, I wonder if someone could give me a few pointers, how to approach this in LLVM.
>
> Should I try to change the IR code -somehow- to get the code generator to generate better code, or should I rather go to the code generator and try to add an optimization pass ?
>
> Thanks for any feedback.
>
> Ciao
> Nat!
>
>
> P.S. In case someone is interested, here is the assembler code and the IR that produced it.
>
>
>
> Relevant LLVM generated x86_64 assembler portion with -Os
> ~~~
> testq %r12, %r12
> je LBB0_5
> ## BB#1:
> movq -8(%r12), %rcx
> movq (%rcx), %rax
> movq -8(%rax), %rdx
> andq %r15, %rdx
> cmpq %r15, (%rax,%rdx)
> je LBB0_2
> ## BB#3:
> addq $8, %rcx
> jmp LBB0_4
> LBB0_2:
> leaq 8(%rdx,%rax), %rcx
> LBB0_4:
> movq %r12, %rdi
> movq %r15, %rsi
> movq %r14, %rdx
> callq *(%rcx)
> movq %rax, %rbx
> LBB0_5:
> ~~~
>
> Better/tighter assembler code would be (saves 2 instructions, one jump less)
> ~~~
> testq %r12, %r12
> je LBB0_5
>
> movq -8(%r12), %rcx
> movq (%rcx), %rax
> movq -8(%rax), %rdx
> andq %r15, %rdx
> cmpq %r15, (%rax,%rdx)
> jne LBB0_4
>
> leaq 0(%rdx,%rax), %rcx
> LBB0_4:
> movq %r12, %rdi
> movq %r15, %rsi
> movq %r14, %rdx
> callq *8(%rcx)
> movq %rax, %rbx
> LBB0_5:
> ~~~
>
>
> This is the IR code, which produces above:
> ~~~
> ; Function Attrs: inlinehint nounwind
> define internal %struct._foo* @call(%struct._foo* %foo, i8* %key, i8* %value) #2 {
> %1 = alloca %struct._foo*, align 8
> %2 = alloca %struct._foo*, align 8
> %3 = alloca i8*, align 8
> %4 = alloca i8*, align 8
> %dispatch = alloca %struct._dispatch*, align 8
> %table = alloca %struct._table*, align 8
> %entrys = alloca %struct._entry*, align 8
> %entry = alloca %struct._entry*, align 8
> %offset = alloca i64, align 8
> %mask = alloca i64, align 8
> %f = alloca %struct._foo* (%struct._foo*, i8*, i8*)*, align 8
> store %struct._foo* %foo, %struct._foo** %2, align 8
> store i8* %key, i8** %3, align 8
> store i8* %value, i8** %4, align 8
> %5 = load %struct._foo** %2, align 8
> %6 = icmp ne %struct._foo* %5, null
> br i1 %6, label %9, label %7
>
> ; <label>:7 ; preds = %0
> %8 = load %struct._foo** %2, align 8
> store %struct._foo* %8, %struct._foo** %1
> br label %50
>
> ; <label>:9 ; preds = %0
> %10 = load %struct._foo** %2, align 8
> %11 = call %struct._dispatch** @_dispatch_p_from_foo(%struct._foo* %10)
> %12 = load %struct._dispatch** %11, align 8
> store %struct._dispatch* %12, %struct._dispatch** %dispatch, align 8
> %13 = load %struct._dispatch** %dispatch, align 8
> %14 = getelementptr inbounds %struct._dispatch* %13, i32 0, i32 0
> %15 = load %struct._entry** %14, align 8
> store %struct._entry* %15, %struct._entry** %entrys, align 8
> %16 = load %struct._entry** %entrys, align 8
> %17 = call %struct._table* @_table_from_entrys(%struct._entry* %16)
> store %struct._table* %17, %struct._table** %table, align 8
> %18 = load %struct._table** %table, align 8
> %19 = getelementptr inbounds %struct._table* %18, i32 0, i32 2
> %20 = load i64* %19, align 8
> store i64 %20, i64* %mask, align 8
> %21 = load i8** %3, align 8
> %22 = ptrtoint i8* %21 to i64
> %23 = load i64* %mask, align 8
> %24 = and i64 %22, %23
> store i64 %24, i64* %offset, align 8
> %25 = load i64* %offset, align 8
> %26 = load %struct._entry** %entrys, align 8
> %27 = bitcast %struct._entry* %26 to i8*
> %28 = getelementptr inbounds i8* %27, i64 %25
> %29 = bitcast i8* %28 to %struct._entry*
> store %struct._entry* %29, %struct._entry** %entry, align 8
> %30 = load %struct._entry** %entry, align 8
> %31 = getelementptr inbounds %struct._entry* %30, i32 0, i32 0
> %32 = load i8** %31, align 8
> %33 = load i8** %3, align 8
> %34 = icmp eq i8* %32, %33
> br i1 %34, label %35, label %39
>
> ; <label>:35 ; preds = %9
> %36 = load %struct._entry** %entry, align 8
> %37 = getelementptr inbounds %struct._entry* %36, i32 0, i32 1
> %38 = load %struct._foo* (%struct._foo*, i8*, i8*)** %37, align 8
> br label %43
>
> ; <label>:39 ; preds = %9
> %40 = load %struct._dispatch** %dispatch, align 8
> %41 = getelementptr inbounds %struct._dispatch* %40, i32 0, i32 1
> %42 = load %struct._foo* (%struct._foo*, i8*, i8*)** %41, align 8
> br label %43
>
> ; <label>:43 ; preds = %39, %35
> %44 = phi %struct._foo* (%struct._foo*, i8*, i8*)* [ %38, %35 ], [ %42, %39 ]
> store %struct._foo* (%struct._foo*, i8*, i8*)* %44, %struct._foo* (%struct._foo*, i8*, i8*)** %f, align 8
> %45 = load %struct._foo* (%struct._foo*, i8*, i8*)** %f, align 8
> %46 = load %struct._foo** %2, align 8
> %47 = load i8** %3, align 8
> %48 = load i8** %4, align 8
> %49 = call %struct._foo* %45(%struct._foo* %46, i8* %47, i8* %48)
> store %struct._foo* %49, %struct._foo** %1
> br label %50
>
> ; <label>:50 ; preds = %43, %7
> %51 = load %struct._foo** %1
> ret %struct._foo* %51
> }
>
> ~~~
>
> ------------------------------------------------------
> When vanity and rivalry disappear, all the lines go
> out of your stomach and you slow down and coast
> slowly to a stop in the middle. -- DLR
>
>
> _______________________________________________
> 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