================ @@ -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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits