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,@function
bar: # @bar
# BB#0: # %entry
movq %rdi, -8(%rsp)
leaq 8(%rdi), %rax
ret
.Ltmp0:
.size bar, .Ltmp0-bar

.section ".note.GNU-stack","",@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

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

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

_bar: ## @bar ## BB#0: ## %entry leaq 8(%rdi), %rax ret

Cheers,
Lang.

Hi Lang,

Thanks for taking the time to reply. This makes sense, since my
question disregards the division in responsibility between opt and llc
in running IR passes. A colleague pointed this out to me after I sent
the question, but I was waiting for additional input and then forgot
to say that the mystery is solved.

Eli