LLVM constant propagation optimization question

Hi all,

I’m writting following LLVM assembly:

; ModuleID = ‘structaccess.ll’

%struct._anon0 = type <{ i32, i32, i32 }>

@s = common global %struct._anon0 zeroinitializer

define arm_aapcscc void @foo() nounwind {
L.entry:
store i32 5, i32* getelementptr inbounds (%struct._anon0* @s, i32 0, i32 0)
store i32 10, i32* getelementptr inbounds (%struct._anon0* @s, i32 0, i32 1)
%0 = load i32* getelementptr inbounds (%struct._anon0* @s, i32 0, i32 0)
%1 = load i32* getelementptr inbounds (%struct._anon0* @s, i32 0, i32 1)
%2 = add i32 %0, %1
store i32 %2, i32* getelementptr inbounds (%struct._anon0* @s, i32 0, i32 2)
ret void
}

Using ‘opt’ utility as follows :

opt -O2 structaccess.ll -S -o structaccess-opt.ll

I’ve got following code for structaccess-opt.ll file:

; ModuleID = ‘structaccess.ll’

%struct._anon0 = type <{ i32, i32, i32 }>

@s = common global %struct._anon0 zeroinitializer

define arm_aapcscc void @foo() nounwind {
L.entry:
store i32 5, i32* getelementptr inbounds (%struct._anon0* @s, i32 0, i32 0)
store i32 10, i32* getelementptr inbounds (%struct._anon0* @s, i32 0, i32 1)
%0 = load i32* getelementptr inbounds (%struct._anon0* @s, i32 0, i32 0)
%1 = add i32 %0, 10
store i32 %1, i32* getelementptr inbounds (%struct._anon0* @s, i32 0, i32 2)
ret void
}

I would have expected constant 5 to be propagated by ‘opt’ to its use and thus LLVM assembly after opt to be :

; ModuleID = ‘structaccess.ll’

%struct._anon0 = type <{ i32, i32, i32 }>

@s = common global %struct._anon0 zeroinitializer

define arm_aapcscc void @foo() nounwind {
L.entry:
store i32 5, i32* getelementptr inbounds (%struct._anon0* @s, i32 0, i32 0)
store i32 10, i32* getelementptr inbounds (%struct._anon0* @s, i32 0, i32 1)
store i32 15, i32* getelementptr inbounds (%struct._anon0* @s, i32 0, i32 2)
ret void
}

Can someone explain me why this is not the case ?

Note that C equivalent would be something like:

struct {
int x, y, z;
} s;

void foo()
{
s.x = 5 ;
s.y = 10 ;
s.z = s.x + s.y ;
}

Hi Seb,

I'm writting following LLVM assembly:

; ModuleID = 'structaccess.ll'

not having a data layout string in your module disables many optimizations.

Ciao, Duncan.

Hi Duncan,

What do you mean by “a data layout string in your module” ?
Best Regards
Seb

2011/10/18 Duncan Sands <baldrick@free.fr>

Duncan,

Forgot my previous e-mail I figured out by myself that adding:

target datalayout = “e-p:32:32:32”

to my orignal code helps ‘opt’ to generate :

; ModuleID = ‘structaccess2.ll’
target datalayout = “e-p:32:32:32”

%struct._anon0 = type <{ i32, i32, i32 }>

@s = common global %struct._anon0 zeroinitializer, align 4

define arm_aapcscc void @foo() nounwind {
L.entry:
store i32 5, i32* getelementptr inbounds (%struct._anon0* @s, i32 0, i32 0), align 4
store i32 10, i32* getelementptr inbounds (%struct._anon0* @s, i32 0, i32 1), align 4
store i32 15, i32* getelementptr inbounds (%struct._anon0* @s, i32 0, i32 2), align 4
ret void
}

Why is exactly what I expected, thanks for pointing me at this !
Best Regards
Seb

2011/10/18 Seb <babslachem@gmail.com>

Hi Seb,

What do you mean by "a data layout string in your module" ?

something like this:

target datalayout = "e-p:64:64:64-S128-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-f128:128:128-n8:16:32:64"
target triple = "x86_64--linux-gnu"

Ciao, duncan.

What do you mean by "a data layout string in your module" ?

http://llvm.org/docs/LangRef.html#datalayout