[LLVMdev] getelementptr on static const struct

Katsuhiro Ueno katsu at riec.tohoku.ac.jp
Wed Jan 29 07:42:40 PST 2014


Hi,

I found a mysterious behavior of LLVM optimizer.

I compiled the following code by clang -emit-llvm -S:

#include <stddef.h>
static const struct t {char t[4]; char s;} p = {{}, 'a'};
char f() {
    return ((char*)&p)[offsetof(struct t, s)];
}

then I obtained the following LLVM IR:

%struct.t = type { [4 x i8], i8 }
@p = constant %struct.t { [4 x i8] zeroinitializer, i8 97 }, align 1
define signext i8 @f() nounwind ssp uwtable {
  %1 = load i8* getelementptr inbounds (%struct.t* @p, i32 0, i32 0,
i64 4), align 1
  ret i8 %1
}

By applying the above code to opt -O1 of LLVM 3.4, I obtained:

%struct.t = type { [4 x i8], i8 }
@p = constant %struct.t { [4 x i8] zeroinitializer, i8 97 }, align 1
define signext i8 @f() nounwind readnone ssp uwtable {
  ret i8 0
}

The function "f" is eventually compiled into a function that always
returns 0, while I expect "f" returns 'a' (97).

Is this an intended behavior, or a bug?


By replacing the getelementptr expression in the clang output

  getelementptr inbounds (%struct.t* @p, i32 0, i32 0, i64 4)

with

  getelementptr inbounds (i8* bitcast (%struct.t* @p to i8*), i64 4)

opt -O1 generates the following code that is what I expected:

define signext i8 @f() nounwind readnone ssp uwtable {
  ret i8 97
}

I carefully read LLVM Language Reference Manual but I could not
understand the difference of these two getelementptr expressions.

Are these two getelementptr equivalent in the semantics of LLVM IR?

Thanks,

--
UENO, Katsuhiro



More information about the llvm-dev mailing list