[LLVMdev] nested GEP in a static initializer fails

Frits van Bommel fvbommel at gmail.com
Thu Oct 28 09:05:25 PDT 2010


On Thu, Oct 28, 2010 at 3:47 PM, Joel E. Denny
<jdenny at etinternational.com> wrote:
> For example, for my platform, llc folds the add but not the getelementptr
> in:
>
>  @a = global i8* getelementptr (i8* null, i64 add (i64 3, i64 2))

This gets folded when it's read in; there's no other way to represent
a constant 'i64 add (i64 3, i64 2)' in LLVM than 'i64 5'. (i.e. if you
try to create the add() constant manually you get i64 5 automatically)

You can see easily see this by running this command from a terminal:
  echo "@a = global i8* getelementptr (i8* null, i64 add (i64 3, i64
2))" | llvm-as | llvm-dis
which outputs
  @a = global i8* getelementptr (i8* null, i64 5)

The getelementptr expression can't be folded like this in general
because it depends on the sizes and alignments of types, which depend
on targetdata. This is probably not really the case for i8*, but there
could be a platform where i8 has a size > 1 (unless LLVM defines this
problem away by explicitly not supporting that).

> so we get:
>
>  .quad 0+5
>
> However, it folds neither of those in:
>
>  @b = global i64 add (i64 ptrtoint (i8* getelementptr (i8* null, i64 3) to i64), i64 2)
>
> so we get:
>
>  .quad ((0+1)*3)+2
>
> In other words, it seems llc knows when it must fold an add, but it
> doesn't do it if it doesn't have to.  Why can't it use the same logic for
> getelementptr?  For example, if a getelementptr invocation has the
> following form:
>
>  <result> = getelementptr (<pty>* null{, <ty> <idx>}*)
>
> where every idx is a constant, is there any reason this getelementptr
> cannot be folded?  This would allow more flexibility in building
> expressions that use getelementptr to compute sizeof or offsetof.
>
> In case it isn't clear, my goal is more about understanding constant
> folding in LLVM than in seeing this particular functionality implemented.

It could certainly be folded if you happen to have the TargetData for
the relevant target architecture at hand.
I know there's llvm/Support/TargetFolder.h for use with IRBuilder,
which uses ConstantFoldConstantExpression() from
llvm/Analysis/ConstantFolding.h. That handles GEPs of null pointers.
As for transformation passes, grepping for
ConstantFoldConstantExpression tells me that instruction combining
(-instcombine) calls this method on all operands of instructions, and
-globalopt seems to calls it on initializers of globals. (But in a
quick test with opt -globalopt it didn't fold, so perhaps it prefers
not to create a inttoptr constant?)




More information about the llvm-dev mailing list