@@ -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
@@ -267,6 +269,13 @@ class ConstantOffsetExtractor {
267269 APInt findInEitherOperand (BinaryOperator *BO, bool SignExtended,
268270 bool ZeroExtended);
269271
272+ // / A helper function to check if a subsequent call to rebuildWithoutConst
273+ // / will allow preserving the GEP's nuw flag. That is the case if all
274+ // / reassociated binary operations are add nuw and no non-nuw trunc is
275+ // / distributed through an add.
276+ // / Can only be called after find has populated the UserChain.
277+ bool checkRebuildingPreservesNUW () const ;
278+
270279 // / After finding the constant offset C from the GEP index I, we build a new
271280 // / index I' s.t. I' + C = I. This function builds and returns the new
272281 // / index I' according to UserChain produced by function "find".
@@ -676,6 +685,30 @@ Value *ConstantOffsetExtractor::applyExts(Value *V) {
676685 return Current;
677686}
678687
688+ bool ConstantOffsetExtractor::checkRebuildingPreservesNUW () const {
689+ auto AllowsPreservingNUW = [](User *U) {
690+ if (BinaryOperator *BO = dyn_cast<BinaryOperator>(U)) {
691+ auto Opcode = BO->getOpcode ();
692+ if (Opcode == BinaryOperator::Or) {
693+ // Ors are only considered here if they are disjoint. The addition that
694+ // they represent in this case is NUW.
695+ assert (cast<PossiblyDisjointInst>(BO)->isDisjoint ());
696+ return true ;
697+ }
698+ return Opcode == BinaryOperator::Add && BO->hasNoUnsignedWrap ();
699+ }
700+ // UserChain can only contain ConstantInt, CastInst, or BinaryOperator.
701+ // Among the possible CastInsts, only trunc without nuw is a problem: If it
702+ // is distributed through an add nuw, wrapping may occur:
703+ // "add nuw trunc(a), trunc(b)" is more poisonous than "trunc(add nuw a, b)"
704+ if (TruncInst *TI = dyn_cast<TruncInst>(U))
705+ return TI->hasNoUnsignedWrap ();
706+ return true ;
707+ };
708+
709+ return all_of (UserChain, AllowsPreservingNUW);
710+ }
711+
679712Value *ConstantOffsetExtractor::rebuildWithoutConstOffset () {
680713 distributeExtsAndCloneChain (UserChain.size () - 1 );
681714 // Remove all nullptrs (used to be s/zext) from UserChain.
@@ -779,16 +812,21 @@ Value *ConstantOffsetExtractor::removeConstOffset(unsigned ChainIndex) {
779812}
780813
781814Value *ConstantOffsetExtractor::Extract (Value *Idx, GetElementPtrInst *GEP,
782- User *&UserChainTail) {
815+ User *&UserChainTail,
816+ bool &PreservesNUW) {
783817 ConstantOffsetExtractor Extractor (GEP->getIterator ());
784818 // Find a non-zero constant offset first.
785819 APInt ConstantOffset =
786820 Extractor.find (Idx, /* SignExtended */ false , /* ZeroExtended */ false ,
787821 GEP->isInBounds ());
788822 if (ConstantOffset == 0 ) {
789823 UserChainTail = nullptr ;
824+ PreservesNUW = true ;
790825 return nullptr ;
791826 }
827+
828+ PreservesNUW = Extractor.checkRebuildingPreservesNUW ();
829+
792830 // Separates the constant offset from the GEP index.
793831 Value *IdxWithoutConstOffset = Extractor.rebuildWithoutConstOffset ();
794832 UserChainTail = Extractor.UserChain .back ();
@@ -1052,7 +1090,9 @@ bool SeparateConstOffsetFromGEP::splitGEP(GetElementPtrInst *GEP) {
10521090 }
10531091 }
10541092
1055- bool MayRecoverInbounds = AccumulativeByteOffset >= 0 && GEP->isInBounds ();
1093+ // Track information for preserving GEP flags.
1094+ bool AllOffsetsNonNegative = AccumulativeByteOffset >= 0 ;
1095+ bool AllNUWPreserved = true ;
10561096
10571097 // Remove the constant offset in each sequential index. The resultant GEP
10581098 // computes the variadic base.
@@ -1072,20 +1112,19 @@ bool SeparateConstOffsetFromGEP::splitGEP(GetElementPtrInst *GEP) {
10721112 // uses the variadic part as the new index.
10731113 Value *OldIdx = GEP->getOperand (I);
10741114 User *UserChainTail;
1075- Value *NewIdx =
1076- ConstantOffsetExtractor::Extract (OldIdx, GEP, UserChainTail);
1115+ bool PreservesNUW;
1116+ Value *NewIdx = ConstantOffsetExtractor::Extract (
1117+ OldIdx, GEP, UserChainTail, PreservesNUW);
10771118 if (NewIdx != nullptr ) {
10781119 // Switches to the index with the constant offset removed.
10791120 GEP->setOperand (I, NewIdx);
10801121 // After switching to the new index, we can garbage-collect UserChain
10811122 // and the old index if they are not used.
10821123 RecursivelyDeleteTriviallyDeadInstructions (UserChainTail);
10831124 RecursivelyDeleteTriviallyDeadInstructions (OldIdx);
1084- MayRecoverInbounds =
1085- MayRecoverInbounds &&
1086- isKnownNonNegative (
1087- NewIdx,
1088- SimplifyQuery (*DL, TLI, DT, /* AC=*/ nullptr , /* CXTI=*/ GEP));
1125+ AllOffsetsNonNegative =
1126+ AllOffsetsNonNegative && isKnownNonNegative (NewIdx, *DL);
1127+ AllNUWPreserved &= PreservesNUW;
10891128 }
10901129 }
10911130 }
@@ -1106,15 +1145,34 @@ bool SeparateConstOffsetFromGEP::splitGEP(GetElementPtrInst *GEP) {
11061145 // inbounds keyword is not present, the offsets are added to the base
11071146 // address with silently-wrapping two's complement arithmetic".
11081147 // Therefore, the final code will be a semantically equivalent.
1109- //
1110- // If the initial GEP was inbounds and all variable indices and the
1148+ GEPNoWrapFlags NewGEPFlags = GEPNoWrapFlags::none ();
1149+
1150+ // If the initial GEP was inbounds/nusw and all variable indices and the
11111151 // accumulated offsets are non-negative, they can be added in any order and
1112- // the intermediate results are in bounds. So, we can preserve the inbounds
1113- // flag for both GEPs. GEPs with inbounds are more friendly to alias analysis.
1114- //
1115- // TODO(gep_nowrap): Preserve nuw?
1116- GEPNoWrapFlags NewGEPFlags =
1117- MayRecoverInbounds ? GEPNoWrapFlags::inBounds () : GEPNoWrapFlags::none ();
1152+ // the intermediate results are in bounds and don't overflow in a nusw sense.
1153+ // So, we can preserve the inbounds/nusw flag for both GEPs.
1154+ bool CanPreserveInBoundsNUSW = AllOffsetsNonNegative;
1155+
1156+ // If the initial GEP was NUW and all operations that we reassociate were NUW
1157+ // additions, the resulting GEPs are also NUW.
1158+ if (GEP->hasNoUnsignedWrap () && AllNUWPreserved) {
1159+ NewGEPFlags |= GEPNoWrapFlags::noUnsignedWrap ();
1160+ // If the initial GEP additionally had NUSW (or inbounds, which implies
1161+ // NUSW), we know that the indices in the initial GEP must all have their
1162+ // signbit not set. For indices that are the result of NUW adds, the
1163+ // add-operands therefore also don't have their signbit set. Therefore, all
1164+ // indices of the resulting GEPs are non-negative -> we can preserve
1165+ // the inbounds/nusw flag.
1166+ CanPreserveInBoundsNUSW |= GEP->hasNoUnsignedSignedWrap ();
1167+ }
1168+
1169+ if (CanPreserveInBoundsNUSW) {
1170+ if (GEP->isInBounds ())
1171+ NewGEPFlags |= GEPNoWrapFlags::inBounds ();
1172+ else if (GEP->hasNoUnsignedSignedWrap ())
1173+ NewGEPFlags |= GEPNoWrapFlags::noUnsignedSignedWrap ();
1174+ }
1175+
11181176 GEP->setNoWrapFlags (NewGEPFlags);
11191177
11201178 // Lowers a GEP to either GEPs with a single index or arithmetic operations.
0 commit comments