InstCombine strips the inBounds attribute in GetElementPtr ConstantExpr

I can’t upload my program due to confidentiality, but the problem is obvious.

At lib/Analysis/ConstantFolding.cpp:646

Constant *C = ConstantExpr::getGetElementPtr(Ops[0], NewIdxs);
if (ConstantExpr *CE = dyn_cast(C)) {
if (Constant *Folded = ConstantFoldConstantExpression(CE, TD, TLI))
C = Folded;

The generated ConstantExpr C doesn’t inherit the inBounds attribute of the original GEP.

FYI, the callstack is

#0 CastGEPIndices (Ops=…, ResultTy=0x2fb2850, TD=0x2fc8830, TLI=0x2feb390)
at ConstantFolding.cpp:623
#1 0x0000000001892dd1 in llvm::ConstantFoldInstOperands (Opcode=29,
DestTy=0x2fb2850, Ops=…, TD=0x2fc8830, TLI=0x2feb390)
at ConstantFolding.cpp:1040
#2 0x0000000001892647 in ConstantFoldConstantExpressionImpl (CE=0x2fcb0f8,
TD=0x2fc8830, TLI=0x2feb390, FoldedOps=…) at ConstantFolding.cpp:931
#3 0x00000000018926d5 in llvm::ConstantFoldConstantExpression (CE=0x2fcb0f8,
TD=0x2fc8830, TLI=0x2feb390) at ConstantFolding.cpp:941
#4 0x0000000001892226 in llvm::ConstantFoldInstruction (I=0x2fcb208,
TLI=0x2feb390) at ConstantFolding.cpp:883
#5 0x000000000171284e in AddReachableCodeToWorklist (BB=0x2fca970, Visited=…,
IC=…, DL=0x2fc8830, TLI=0x2feb390) at InstructionCombining.cpp:2283
#6 0x0000000001712e91 in llvm::InstCombiner::DoOneIteration (this=0x2ff3be0,
Iteration=0) at InstructionCombining.cpp:2369
#7 0x0000000001713bf2 in llvm::InstCombiner::runOnFunction (this=0x2ff3be0,
at InstructionCombining.cpp:2568


A reduced test case would still help, and should go into any fix to ensure
we don't regress here...

Sure, Chandler. I was running late yesterday, and didn’t get a chance to reduce it.

Attached is a reduced test. One more thing I found is, to trigger this issue, the base of the GEP mustn’t be a GlobalVariable; otherwise, LLVM will go to ConstantFold.cpp:2131 and generate an inbounds GEP ConstantExpr.

2127 // If all indices are known integers and normalized, we can do a simple
2128 // check for the “inbounds” property.
2129 if (!Unknown && !inBounds &&
2130 isa(C) && isInBoundsIndices(Idxs))
2131 return ConstantExpr::getInBoundsGetElementPtr(C, Idxs);

My attached test is reduced from a CUDA program that declares the global array as shared. Therefore, the base of the GEP is an addrspacecast from the global array.

One possible fix is to pass IsInBounds to ConstantFoldInstOperands and CastGEPIndices, so that CastGEPIndices can inherit this attribute. Are there better ways?

Let me know if you need more information.


inbounds.ll (367 Bytes)

I forgot to mention how to reproduce this issue:

Simply run “opt inbounds.ll -o inbounds.opt.ll -instcombine -S”. The result is attached.


inbounds.opt.ll (320 Bytes)