Skip to content

Commit 21f47f3

Browse files
committed
[SeparateConstOffsetFromGEP] propogate const offset through GEP chains
1 parent 58e8791 commit 21f47f3

File tree

2 files changed

+86
-84
lines changed

2 files changed

+86
-84
lines changed

llvm/lib/Transforms/Scalar/SeparateConstOffsetFromGEP.cpp

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1039,19 +1039,31 @@ bool SeparateConstOffsetFromGEP::splitGEP(GetElementPtrInst *GEP) {
10391039
if (GEP->getType()->isVectorTy())
10401040
return false;
10411041

1042+
// If the base of this GEP is a ptradd of a constant, lets pass the constant
1043+
// along. This ensures that when we have a chain of GEPs the constant
1044+
// offset from each is accumulated.
1045+
Value *NewBase;
1046+
const APInt *BaseOffset;
1047+
const bool ExtractBase =
1048+
match(GEP->getPointerOperand(),
1049+
m_PtrAdd(m_Value(NewBase), m_APInt(BaseOffset)));
1050+
1051+
const int64_t BaseByteOffset = ExtractBase ? BaseOffset->getSExtValue() : 0;
1052+
10421053
// The backend can already nicely handle the case where all indices are
10431054
// constant.
1044-
if (GEP->hasAllConstantIndices())
1055+
if (GEP->hasAllConstantIndices() && !ExtractBase)
10451056
return false;
10461057

10471058
bool Changed = canonicalizeArrayIndicesToIndexSize(GEP);
10481059

10491060
bool NeedsExtraction;
1050-
int64_t AccumulativeByteOffset = accumulateByteOffset(GEP, NeedsExtraction);
1061+
int64_t AccumulativeByteOffset =
1062+
BaseByteOffset + accumulateByteOffset(GEP, NeedsExtraction);
10511063

10521064
TargetTransformInfo &TTI = GetTTI(*GEP->getFunction());
10531065

1054-
if (!NeedsExtraction) {
1066+
if (!NeedsExtraction && !ExtractBase) {
10551067
Changed |= reorderGEP(GEP, TTI);
10561068
return Changed;
10571069
}
@@ -1075,7 +1087,9 @@ bool SeparateConstOffsetFromGEP::splitGEP(GetElementPtrInst *GEP) {
10751087

10761088
// Track information for preserving GEP flags.
10771089
bool AllOffsetsNonNegative = AccumulativeByteOffset >= 0;
1078-
bool AllNUWPreserved = true;
1090+
bool AllNUWPreserved = GEP->hasNoUnsignedWrap();
1091+
bool NewGEPInBounds = GEP->isInBounds();
1092+
bool NewGEPNUSW = GEP->hasNoUnsignedSignedWrap();
10791093

10801094
// Remove the constant offset in each sequential index. The resultant GEP
10811095
// computes the variadic base.
@@ -1111,6 +1125,16 @@ bool SeparateConstOffsetFromGEP::splitGEP(GetElementPtrInst *GEP) {
11111125
}
11121126
}
11131127
}
1128+
if (ExtractBase) {
1129+
GEPOperator *Base = cast<GEPOperator>(GEP->getPointerOperand());
1130+
AllNUWPreserved &= Base->hasNoUnsignedWrap();
1131+
NewGEPInBounds &= Base->isInBounds();
1132+
NewGEPNUSW &= Base->hasNoUnsignedSignedWrap();
1133+
AllOffsetsNonNegative &= BaseByteOffset >= 0;
1134+
1135+
GEP->setOperand(0, NewBase);
1136+
RecursivelyDeleteTriviallyDeadInstructions(Base);
1137+
}
11141138

11151139
// Clear the inbounds attribute because the new index may be off-bound.
11161140
// e.g.,
@@ -1138,21 +1162,21 @@ bool SeparateConstOffsetFromGEP::splitGEP(GetElementPtrInst *GEP) {
11381162

11391163
// If the initial GEP was NUW and all operations that we reassociate were NUW
11401164
// additions, the resulting GEPs are also NUW.
1141-
if (GEP->hasNoUnsignedWrap() && AllNUWPreserved) {
1165+
if (AllNUWPreserved) {
11421166
NewGEPFlags |= GEPNoWrapFlags::noUnsignedWrap();
11431167
// If the initial GEP additionally had NUSW (or inbounds, which implies
11441168
// NUSW), we know that the indices in the initial GEP must all have their
11451169
// signbit not set. For indices that are the result of NUW adds, the
11461170
// add-operands therefore also don't have their signbit set. Therefore, all
11471171
// indices of the resulting GEPs are non-negative -> we can preserve
11481172
// the inbounds/nusw flag.
1149-
CanPreserveInBoundsNUSW |= GEP->hasNoUnsignedSignedWrap();
1173+
CanPreserveInBoundsNUSW |= NewGEPNUSW;
11501174
}
11511175

11521176
if (CanPreserveInBoundsNUSW) {
1153-
if (GEP->isInBounds())
1177+
if (NewGEPInBounds)
11541178
NewGEPFlags |= GEPNoWrapFlags::inBounds();
1155-
else if (GEP->hasNoUnsignedSignedWrap())
1179+
else if (NewGEPNUSW)
11561180
NewGEPFlags |= GEPNoWrapFlags::noUnsignedSignedWrap();
11571181
}
11581182

@@ -1220,11 +1244,13 @@ bool SeparateConstOffsetFromGEP::run(Function &F) {
12201244

12211245
DL = &F.getDataLayout();
12221246
bool Changed = false;
1223-
for (BasicBlock &B : F) {
1224-
if (!DT->isReachableFromEntry(&B))
1247+
1248+
ReversePostOrderTraversal<Function *> RPOT(&F);
1249+
for (BasicBlock *B : RPOT) {
1250+
if (!DT->isReachableFromEntry(B))
12251251
continue;
12261252

1227-
for (Instruction &I : llvm::make_early_inc_range(B))
1253+
for (Instruction &I : llvm::make_early_inc_range(*B))
12281254
if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(&I))
12291255
Changed |= splitGEP(GEP);
12301256
// No need to split GEP ConstantExprs because all its indices are constant

0 commit comments

Comments
 (0)