Eli Bendersky
2013-Feb-01 20:11 UTC
[LLVMdev] Question about compilation result - taking address of input array member
Hello,
I'm playing around with some LEA-related code generation on x86-64
(trunk LLVM & Clang), and I run into a case I don't understand:
$ cat takeaddr.c
int* bar(int table[10]) {
return &table[2];
}
$ clang -cc1 -emit-llvm takeaddr.c
$ cat takeaddr.ll
; ModuleID = 'takeaddr.c'
target datalayout
"e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
define i32* @bar(i32* %table) nounwind {
entry:
%table.addr = alloca i32*, align 8
store i32* %table, i32** %table.addr, align 8
%0 = load i32** %table.addr, align 8
%arrayidx = getelementptr inbounds i32* %0, i64 2
ret i32* %arrayidx
}
$ llc -O3 takeaddr.ll -o -
.file "takeaddr.ll"
.text
.globl bar
.align 16, 0x90
.type bar, at function
bar: # @bar
# BB#0: # %entry
movq %rdi, -8(%rsp)
leaq 8(%rdi), %rax
ret
.Ltmp0:
.size bar, .Ltmp0-bar
.section ".note.GNU-stack","", at progbits
The first instruction in "bar" is not clear. Why is it needed? It
seems harmless, but does it serve any purpose? Alignment? ISTM that
the leaq suffices to pefrorm the actual task of the function. Is this
a missed optimization of some sort?
Thanks in advance,
Eli
Eli Bendersky
2013-Feb-01 20:14 UTC
[LLVMdev] Question about compilation result - taking address of input array member
On Fri, Feb 1, 2013 at 12:11 PM, Eli Bendersky <eliben at google.com> wrote:> Hello, > > I'm playing around with some LEA-related code generation on x86-64 > (trunk LLVM & Clang), and I run into a case I don't understand: > > $ cat takeaddr.c > int* bar(int table[10]) { > return &table[2]; > } > > $ clang -cc1 -emit-llvm takeaddr.c > $ cat takeaddr.ll > ; ModuleID = 'takeaddr.c' > target datalayout > "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" > target triple = "x86_64-unknown-linux-gnu" > > define i32* @bar(i32* %table) nounwind { > entry: > %table.addr = alloca i32*, align 8 > store i32* %table, i32** %table.addr, align 8 > %0 = load i32** %table.addr, align 8 > %arrayidx = getelementptr inbounds i32* %0, i64 2 > ret i32* %arrayidx > } > > $ llc -O3 takeaddr.ll -o - > .file "takeaddr.ll" > .text > .globl bar > .align 16, 0x90 > .type bar, at function > bar: # @bar > # BB#0: # %entry > movq %rdi, -8(%rsp) > leaq 8(%rdi), %rax > ret > .Ltmp0: > .size bar, .Ltmp0-bar > > > .section ".note.GNU-stack","", at progbits > > The first instruction in "bar" is not clear. Why is it needed? It > seems harmless, but does it serve any purpose? Alignment? ISTM that > the leaq suffices to pefrorm the actual task of the function. Is this > a missed optimization of some sort? >I should add that if I manually hack takeaddr.ll to avoid the alloca and store, instead using %table directly in the GEP, the movq goes away and only leaq remains. Eli
Lang Hames
2013-Feb-14 05:21 UTC
[LLVMdev] Question about compilation result - taking address of input array member
Hi Eli,
I'm not sure if this is the answer you're looking for, but the alloca,
store and load can be removed by the mem2reg pass, which isn't run by
codegen prepare in llc. If you invoke clang with -O1 or above it will run
mem2reg, producing IR that contains only the gep, and that produces the
assembly you're looking for:
$ clang -cc1 -emit-llvm -O1 takeaddr.c
$ cat takeaddr.ll
define i32* @bar(i32* %table) nounwind readnone {
entry:
%arrayidx = getelementptr inbounds i32* %table, i64 2
ret i32* %arrayidx
}
$ llc takeaddr.ll
$ cat takeaddr.s
<snip>
_bar: ## @bar
## BB#0: ## %entry
leaq 8(%rdi), %rax
ret
Cheers,
Lang.
On Fri, Feb 1, 2013 at 12:14 PM, Eli Bendersky <eliben at google.com>
wrote:
> On Fri, Feb 1, 2013 at 12:11 PM, Eli Bendersky <eliben at google.com>
wrote:
> > Hello,
> >
> > I'm playing around with some LEA-related code generation on x86-64
> > (trunk LLVM & Clang), and I run into a case I don't
understand:
> >
> > $ cat takeaddr.c
> > int* bar(int table[10]) {
> > return &table[2];
> > }
> >
> > $ clang -cc1 -emit-llvm takeaddr.c
> > $ cat takeaddr.ll
> > ; ModuleID = 'takeaddr.c'
> > target datalayout > >
>
"e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
> > target triple = "x86_64-unknown-linux-gnu"
> >
> > define i32* @bar(i32* %table) nounwind {
> > entry:
> > %table.addr = alloca i32*, align 8
> > store i32* %table, i32** %table.addr, align 8
> > %0 = load i32** %table.addr, align 8
> > %arrayidx = getelementptr inbounds i32* %0, i64 2
> > ret i32* %arrayidx
> > }
> >
> > $ llc -O3 takeaddr.ll -o -
> > .file "takeaddr.ll"
> > .text
> > .globl bar
> > .align 16, 0x90
> > .type bar, at function
> > bar: # @bar
> > # BB#0: # %entry
> > movq %rdi, -8(%rsp)
> > leaq 8(%rdi), %rax
> > ret
> > .Ltmp0:
> > .size bar, .Ltmp0-bar
> >
> >
> > .section ".note.GNU-stack","", at progbits
> >
> > The first instruction in "bar" is not clear. Why is it
needed? It
> > seems harmless, but does it serve any purpose? Alignment? ISTM that
> > the leaq suffices to pefrorm the actual task of the function. Is this
> > a missed optimization of some sort?
> >
>
> I should add that if I manually hack takeaddr.ll to avoid the alloca
> and store, instead using %table directly in the GEP, the movq goes
> away and only leaq remains.
>
> Eli
> _______________________________________________
> LLVM Developers mailing list
> LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<http://lists.llvm.org/pipermail/llvm-dev/attachments/20130213/d7b65eaf/attachment.html>
Possibly Parallel Threads
- [LLVMdev] Question about compilation result - taking address of input array member
- [LLVMdev] Question about compilation result - taking address of input array member
- Expected constant simplification not happening
- Expected constant simplification not happening
- [LLVMdev] LLVMdev Digest, Vol 85, Issue 50