@@ -235,8 +235,10 @@ class ConstantOffsetExtractor {
235235 // / \p GEP The given GEP
236236 // / \p UserChainTail Outputs the tail of UserChain so that we can
237237 // / garbage-collect unused instructions in UserChain.
238+ // / \p PreservesNUW Outputs whether the extraction allows preserving the
239+ // / GEP's nuw flag, if it has one.
238240 static Value *Extract (Value *Idx, GetElementPtrInst *GEP,
239- User *&UserChainTail);
241+ User *&UserChainTail, bool &PreservesNUW );
240242
241243 // / Looks for a constant offset from the given GEP index without extracting
242244 // / it. It returns the numeric value of the extracted constant offset (0 if
@@ -778,17 +780,45 @@ Value *ConstantOffsetExtractor::removeConstOffset(unsigned ChainIndex) {
778780 return NewBO;
779781}
780782
783+ // / A helper function to check if reassociating through an entry in the user
784+ // / chain would invalidate the GEP's nuw flag.
785+ static bool allowsPreservingNUW (const User *U) {
786+ if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(U)) {
787+ // Binary operations need to be effectively add nuw.
788+ auto Opcode = BO->getOpcode ();
789+ if (Opcode == BinaryOperator::Or) {
790+ // Ors are only considered here if they are disjoint. The addition that
791+ // they represent in this case is NUW.
792+ assert (cast<PossiblyDisjointInst>(BO)->isDisjoint ());
793+ return true ;
794+ }
795+ return Opcode == BinaryOperator::Add && BO->hasNoUnsignedWrap ();
796+ }
797+ // UserChain can only contain ConstantInt, CastInst, or BinaryOperator.
798+ // Among the possible CastInsts, only trunc without nuw is a problem: If it
799+ // is distributed through an add nuw, wrapping may occur:
800+ // "add nuw trunc(a), trunc(b)" is more poisonous than "trunc(add nuw a, b)"
801+ if (const TruncInst *TI = dyn_cast<TruncInst>(U))
802+ return TI->hasNoUnsignedWrap ();
803+ return isa<CastInst>(U) || isa<ConstantInt>(U);
804+ }
805+
781806Value *ConstantOffsetExtractor::Extract (Value *Idx, GetElementPtrInst *GEP,
782- User *&UserChainTail) {
807+ User *&UserChainTail,
808+ bool &PreservesNUW) {
783809 ConstantOffsetExtractor Extractor (GEP->getIterator ());
784810 // Find a non-zero constant offset first.
785811 APInt ConstantOffset =
786812 Extractor.find (Idx, /* SignExtended */ false , /* ZeroExtended */ false ,
787813 GEP->isInBounds ());
788814 if (ConstantOffset == 0 ) {
789815 UserChainTail = nullptr ;
816+ PreservesNUW = true ;
790817 return nullptr ;
791818 }
819+
820+ PreservesNUW = all_of (Extractor.UserChain , allowsPreservingNUW);
821+
792822 // Separates the constant offset from the GEP index.
793823 Value *IdxWithoutConstOffset = Extractor.rebuildWithoutConstOffset ();
794824 UserChainTail = Extractor.UserChain .back ();
@@ -1052,6 +1082,10 @@ bool SeparateConstOffsetFromGEP::splitGEP(GetElementPtrInst *GEP) {
10521082 }
10531083 }
10541084
1085+ // Track information for preserving GEP flags.
1086+ bool AllOffsetsNonNegative = AccumulativeByteOffset >= 0 ;
1087+ bool AllNUWPreserved = true ;
1088+
10551089 // Remove the constant offset in each sequential index. The resultant GEP
10561090 // computes the variadic base.
10571091 // Notice that we don't remove struct field indices here. If LowerGEP is
@@ -1070,15 +1104,19 @@ bool SeparateConstOffsetFromGEP::splitGEP(GetElementPtrInst *GEP) {
10701104 // uses the variadic part as the new index.
10711105 Value *OldIdx = GEP->getOperand (I);
10721106 User *UserChainTail;
1073- Value *NewIdx =
1074- ConstantOffsetExtractor::Extract (OldIdx, GEP, UserChainTail);
1107+ bool PreservesNUW;
1108+ Value *NewIdx = ConstantOffsetExtractor::Extract (
1109+ OldIdx, GEP, UserChainTail, PreservesNUW);
10751110 if (NewIdx != nullptr ) {
10761111 // Switches to the index with the constant offset removed.
10771112 GEP->setOperand (I, NewIdx);
10781113 // After switching to the new index, we can garbage-collect UserChain
10791114 // and the old index if they are not used.
10801115 RecursivelyDeleteTriviallyDeadInstructions (UserChainTail);
10811116 RecursivelyDeleteTriviallyDeadInstructions (OldIdx);
1117+ AllOffsetsNonNegative =
1118+ AllOffsetsNonNegative && isKnownNonNegative (NewIdx, *DL);
1119+ AllNUWPreserved &= PreservesNUW;
10821120 }
10831121 }
10841122 }
@@ -1099,12 +1137,35 @@ bool SeparateConstOffsetFromGEP::splitGEP(GetElementPtrInst *GEP) {
10991137 // inbounds keyword is not present, the offsets are added to the base
11001138 // address with silently-wrapping two's complement arithmetic".
11011139 // Therefore, the final code will be a semantically equivalent.
1102- //
1103- // TODO(jingyue): do some range analysis to keep as many inbounds as
1104- // possible. GEPs with inbounds are more friendly to alias analysis.
1105- // TODO(gep_nowrap): Preserve nuw at least.
11061140 GEPNoWrapFlags NewGEPFlags = GEPNoWrapFlags::none ();
1107- GEP->setNoWrapFlags (GEPNoWrapFlags::none ());
1141+
1142+ // If the initial GEP was inbounds/nusw and all variable indices and the
1143+ // accumulated offsets are non-negative, they can be added in any order and
1144+ // the intermediate results are in bounds and don't overflow in a nusw sense.
1145+ // So, we can preserve the inbounds/nusw flag for both GEPs.
1146+ bool CanPreserveInBoundsNUSW = AllOffsetsNonNegative;
1147+
1148+ // If the initial GEP was NUW and all operations that we reassociate were NUW
1149+ // additions, the resulting GEPs are also NUW.
1150+ if (GEP->hasNoUnsignedWrap () && AllNUWPreserved) {
1151+ NewGEPFlags |= GEPNoWrapFlags::noUnsignedWrap ();
1152+ // If the initial GEP additionally had NUSW (or inbounds, which implies
1153+ // NUSW), we know that the indices in the initial GEP must all have their
1154+ // signbit not set. For indices that are the result of NUW adds, the
1155+ // add-operands therefore also don't have their signbit set. Therefore, all
1156+ // indices of the resulting GEPs are non-negative -> we can preserve
1157+ // the inbounds/nusw flag.
1158+ CanPreserveInBoundsNUSW |= GEP->hasNoUnsignedSignedWrap ();
1159+ }
1160+
1161+ if (CanPreserveInBoundsNUSW) {
1162+ if (GEP->isInBounds ())
1163+ NewGEPFlags |= GEPNoWrapFlags::inBounds ();
1164+ else if (GEP->hasNoUnsignedSignedWrap ())
1165+ NewGEPFlags |= GEPNoWrapFlags::noUnsignedSignedWrap ();
1166+ }
1167+
1168+ GEP->setNoWrapFlags (NewGEPFlags);
11081169
11091170 // Lowers a GEP to either GEPs with a single index or arithmetic operations.
11101171 if (LowerGEP) {
0 commit comments