@@ -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