[clang] [lld] [llvm] [IR] Change representation of getelementptr inrange (PR #84341)
Nikita Popov via cfe-commits
cfe-commits at lists.llvm.org
Tue Mar 19 10:48:07 PDT 2024
================
@@ -47,28 +47,66 @@ static bool splitGlobal(GlobalVariable &GV) {
if (!Init)
return false;
- // Verify that each user of the global is an inrange getelementptr constant.
- // From this it follows that any loads from or stores to that global must use
- // a pointer derived from an inrange getelementptr constant, which is
- // sufficient to allow us to apply the splitting transform.
+ const DataLayout &DL = GV.getParent()->getDataLayout();
+ const StructLayout *SL = DL.getStructLayout(Init->getType());
+ ArrayRef<TypeSize> MemberOffsets = SL->getMemberOffsets();
+ unsigned IndexWidth = DL.getIndexTypeSizeInBits(GV.getType());
+
+ // Verify that each user of the global is an inrange getelementptr constant,
+ // and collect information on how it relates to the global.
+ struct GEPInfo {
+ GEPOperator *GEP;
+ unsigned MemberIndex;
+ APInt MemberRelativeOffset;
+
+ GEPInfo(GEPOperator *GEP, unsigned MemberIndex, APInt MemberRelativeOffset)
+ : GEP(GEP), MemberIndex(MemberIndex),
+ MemberRelativeOffset(std::move(MemberRelativeOffset)) {}
+ };
+ SmallVector<GEPInfo> Infos;
for (User *U : GV.users()) {
- if (!isa<Constant>(U))
+ auto *GEP = dyn_cast<GEPOperator>(U);
+ if (!GEP)
return false;
- auto *GEP = dyn_cast<GEPOperator>(U);
- if (!GEP || !GEP->getInRangeIndex() || *GEP->getInRangeIndex() != 1 ||
- !isa<ConstantInt>(GEP->getOperand(1)) ||
- !cast<ConstantInt>(GEP->getOperand(1))->isZero() ||
- !isa<ConstantInt>(GEP->getOperand(2)))
+ std::optional<ConstantRange> InRange = GEP->getInRange();
+ if (!InRange)
+ return false;
+
+ APInt Offset(IndexWidth, 0);
+ if (!GEP->accumulateConstantOffset(DL, Offset))
+ return false;
+
+ // Determine source-relative inrange.
+ ConstantRange SrcInRange = InRange->sextOrTrunc(IndexWidth).add(Offset);
+
+ // Check that the GEP offset is in the range (treating upper bound as
+ // inclusive here).
+ if (!SrcInRange.contains(Offset) && SrcInRange.getUpper() != Offset)
+ return false;
+
+ // Find which struct member the range corresponds to.
+ if (SrcInRange.getLower().uge(SL->getSizeInBytes()))
return false;
+
+ unsigned MemberIndex =
+ SL->getElementContainingOffset(SrcInRange.getLower().getZExtValue());
----------------
nikic wrote:
I think this is already implied by the check directly before this (note that it uses uge rather than sge, so will also reject negative numbers -- unless the struct size becomes negative, of course...).
https://github.com/llvm/llvm-project/pull/84341
More information about the cfe-commits
mailing list