-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[ConstantFolding] Canonicalize constexpr GEPs to i8 #89872
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -869,7 +869,6 @@ Constant *SymbolicallyEvaluateGEP(const GEPOperator *GEP, | |||||||||||||||||
bool InBounds = GEP->isInBounds(); | ||||||||||||||||||
|
||||||||||||||||||
Type *SrcElemTy = GEP->getSourceElementType(); | ||||||||||||||||||
Type *ResElemTy = GEP->getResultElementType(); | ||||||||||||||||||
Type *ResTy = GEP->getType(); | ||||||||||||||||||
if (!SrcElemTy->isSized() || isa<ScalableVectorType>(SrcElemTy)) | ||||||||||||||||||
return nullptr; | ||||||||||||||||||
|
@@ -944,43 +943,18 @@ Constant *SymbolicallyEvaluateGEP(const GEPOperator *GEP, | |||||||||||||||||
return ConstantExpr::getIntToPtr(C, ResTy); | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
// Otherwise form a regular getelementptr. Recompute the indices so that | ||||||||||||||||||
// we eliminate over-indexing of the notional static type array bounds. | ||||||||||||||||||
// This makes it easy to determine if the getelementptr is "inbounds". | ||||||||||||||||||
|
||||||||||||||||||
// For GEPs of GlobalValues, use the value type, otherwise use an i8 GEP. | ||||||||||||||||||
if (auto *GV = dyn_cast<GlobalValue>(Ptr)) | ||||||||||||||||||
SrcElemTy = GV->getValueType(); | ||||||||||||||||||
else | ||||||||||||||||||
SrcElemTy = Type::getInt8Ty(Ptr->getContext()); | ||||||||||||||||||
|
||||||||||||||||||
if (!SrcElemTy->isSized()) | ||||||||||||||||||
return nullptr; | ||||||||||||||||||
|
||||||||||||||||||
Type *ElemTy = SrcElemTy; | ||||||||||||||||||
SmallVector<APInt> Indices = DL.getGEPIndicesForOffset(ElemTy, Offset); | ||||||||||||||||||
if (Offset != 0) | ||||||||||||||||||
return nullptr; | ||||||||||||||||||
|
||||||||||||||||||
// Try to add additional zero indices to reach the desired result element | ||||||||||||||||||
// type. | ||||||||||||||||||
// TODO: Should we avoid extra zero indices if ResElemTy can't be reached and | ||||||||||||||||||
// we'll have to insert a bitcast anyway? | ||||||||||||||||||
while (ElemTy != ResElemTy) { | ||||||||||||||||||
Type *NextTy = GetElementPtrInst::getTypeAtIndex(ElemTy, (uint64_t)0); | ||||||||||||||||||
if (!NextTy) | ||||||||||||||||||
break; | ||||||||||||||||||
|
||||||||||||||||||
Indices.push_back(APInt::getZero(isa<StructType>(ElemTy) ? 32 : BitWidth)); | ||||||||||||||||||
ElemTy = NextTy; | ||||||||||||||||||
// Try to infer inbounds for GEPs of globals. | ||||||||||||||||||
if (!InBounds && Offset.isNonNegative()) { | ||||||||||||||||||
bool CanBeNull, CanBeFreed; | ||||||||||||||||||
uint64_t DerefBytes = | ||||||||||||||||||
Ptr->getPointerDereferenceableBytes(DL, CanBeNull, CanBeFreed); | ||||||||||||||||||
InBounds = DerefBytes != 0 && !CanBeNull && Offset.sle(DerefBytes); | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've added this inference in this patch, because we lose out on this inference in the DataLayout-independent constant folding: llvm-project/llvm/lib/IR/ConstantFold.cpp Lines 1717 to 1724 in 88b6186
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can we remove the other constant folding? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think we'd want to remove it at this point as it's still used in some key places like initial IR construction in clang -- longer term, I'd like to get rid of the two separate constant folding implementations altogether. |
||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
SmallVector<Constant *, 32> NewIdxs; | ||||||||||||||||||
for (const APInt &Index : Indices) | ||||||||||||||||||
NewIdxs.push_back(ConstantInt::get( | ||||||||||||||||||
Type::getIntNTy(Ptr->getContext(), Index.getBitWidth()), Index)); | ||||||||||||||||||
|
||||||||||||||||||
return ConstantExpr::getGetElementPtr(SrcElemTy, Ptr, NewIdxs, InBounds, | ||||||||||||||||||
// Otherwise canonicalize this to a single ptradd. | ||||||||||||||||||
LLVMContext &Ctx = Ptr->getContext(); | ||||||||||||||||||
return ConstantExpr::getGetElementPtr(Type::getInt8Ty(Ctx), Ptr, | ||||||||||||||||||
ConstantInt::get(Ctx, Offset), InBounds, | ||||||||||||||||||
InRange); | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is there a test for the case where
!Offset.isNonNegative()
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://github.com/llvm/llvm-project/blob/main/llvm/test/Transforms/GlobalOpt/large-element-size.ll gets an incorrect inbounds without the check.