@@ -235,8 +235,10 @@ class ConstantOffsetExtractor {
235
235
// / \p GEP The given GEP
236
236
// / \p UserChainTail Outputs the tail of UserChain so that we can
237
237
// / 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.
238
240
static Value *Extract (Value *Idx, GetElementPtrInst *GEP,
239
- User *&UserChainTail);
241
+ User *&UserChainTail, bool &PreservesNUW );
240
242
241
243
// / Looks for a constant offset from the given GEP index without extracting
242
244
// / it. It returns the numeric value of the extracted constant offset (0 if
@@ -778,17 +780,45 @@ Value *ConstantOffsetExtractor::removeConstOffset(unsigned ChainIndex) {
778
780
return NewBO;
779
781
}
780
782
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
+
781
806
Value *ConstantOffsetExtractor::Extract (Value *Idx, GetElementPtrInst *GEP,
782
- User *&UserChainTail) {
807
+ User *&UserChainTail,
808
+ bool &PreservesNUW) {
783
809
ConstantOffsetExtractor Extractor (GEP->getIterator ());
784
810
// Find a non-zero constant offset first.
785
811
APInt ConstantOffset =
786
812
Extractor.find (Idx, /* SignExtended */ false , /* ZeroExtended */ false ,
787
813
GEP->isInBounds ());
788
814
if (ConstantOffset == 0 ) {
789
815
UserChainTail = nullptr ;
816
+ PreservesNUW = true ;
790
817
return nullptr ;
791
818
}
819
+
820
+ PreservesNUW = all_of (Extractor.UserChain , allowsPreservingNUW);
821
+
792
822
// Separates the constant offset from the GEP index.
793
823
Value *IdxWithoutConstOffset = Extractor.rebuildWithoutConstOffset ();
794
824
UserChainTail = Extractor.UserChain .back ();
@@ -1052,6 +1082,10 @@ bool SeparateConstOffsetFromGEP::splitGEP(GetElementPtrInst *GEP) {
1052
1082
}
1053
1083
}
1054
1084
1085
+ // Track information for preserving GEP flags.
1086
+ bool AllOffsetsNonNegative = AccumulativeByteOffset >= 0 ;
1087
+ bool AllNUWPreserved = true ;
1088
+
1055
1089
// Remove the constant offset in each sequential index. The resultant GEP
1056
1090
// computes the variadic base.
1057
1091
// Notice that we don't remove struct field indices here. If LowerGEP is
@@ -1070,15 +1104,19 @@ bool SeparateConstOffsetFromGEP::splitGEP(GetElementPtrInst *GEP) {
1070
1104
// uses the variadic part as the new index.
1071
1105
Value *OldIdx = GEP->getOperand (I);
1072
1106
User *UserChainTail;
1073
- Value *NewIdx =
1074
- ConstantOffsetExtractor::Extract (OldIdx, GEP, UserChainTail);
1107
+ bool PreservesNUW;
1108
+ Value *NewIdx = ConstantOffsetExtractor::Extract (
1109
+ OldIdx, GEP, UserChainTail, PreservesNUW);
1075
1110
if (NewIdx != nullptr ) {
1076
1111
// Switches to the index with the constant offset removed.
1077
1112
GEP->setOperand (I, NewIdx);
1078
1113
// After switching to the new index, we can garbage-collect UserChain
1079
1114
// and the old index if they are not used.
1080
1115
RecursivelyDeleteTriviallyDeadInstructions (UserChainTail);
1081
1116
RecursivelyDeleteTriviallyDeadInstructions (OldIdx);
1117
+ AllOffsetsNonNegative =
1118
+ AllOffsetsNonNegative && isKnownNonNegative (NewIdx, *DL);
1119
+ AllNUWPreserved &= PreservesNUW;
1082
1120
}
1083
1121
}
1084
1122
}
@@ -1099,12 +1137,35 @@ bool SeparateConstOffsetFromGEP::splitGEP(GetElementPtrInst *GEP) {
1099
1137
// inbounds keyword is not present, the offsets are added to the base
1100
1138
// address with silently-wrapping two's complement arithmetic".
1101
1139
// 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.
1106
1140
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);
1108
1169
1109
1170
// Lowers a GEP to either GEPs with a single index or arithmetic operations.
1110
1171
if (LowerGEP) {
0 commit comments