@@ -3086,13 +3086,47 @@ Instruction *InstCombinerImpl::visitGetElementPtrInst(GetElementPtrInst &GEP) {
3086
3086
if (GEPType->isVectorTy ())
3087
3087
return nullptr ;
3088
3088
3089
+ if (!GEP.isInBounds ()) {
3090
+ unsigned IdxWidth =
3091
+ DL.getIndexSizeInBits (PtrOp->getType ()->getPointerAddressSpace ());
3092
+ APInt BasePtrOffset (IdxWidth, 0 );
3093
+ Value *UnderlyingPtrOp =
3094
+ PtrOp->stripAndAccumulateInBoundsConstantOffsets (DL, BasePtrOffset);
3095
+ bool CanBeNull, CanBeFreed;
3096
+ uint64_t DerefBytes = UnderlyingPtrOp->getPointerDereferenceableBytes (
3097
+ DL, CanBeNull, CanBeFreed);
3098
+ if (!CanBeNull && !CanBeFreed && DerefBytes != 0 ) {
3099
+ if (GEP.accumulateConstantOffset (DL, BasePtrOffset) &&
3100
+ BasePtrOffset.isNonNegative ()) {
3101
+ APInt AllocSize (IdxWidth, DerefBytes);
3102
+ if (BasePtrOffset.ule (AllocSize)) {
3103
+ return GetElementPtrInst::CreateInBounds (
3104
+ GEP.getSourceElementType (), PtrOp, Indices, GEP.getName ());
3105
+ }
3106
+ }
3107
+ }
3108
+ }
3109
+
3110
+ // nusw + nneg -> nuw
3111
+ if (GEP.hasNoUnsignedSignedWrap () && !GEP.hasNoUnsignedWrap () &&
3112
+ all_of (GEP.indices (), [&](Value *Idx) {
3113
+ return isKnownNonNegative (Idx, SQ.getWithInstruction (&GEP));
3114
+ })) {
3115
+ GEP.setNoWrapFlags (GEP.getNoWrapFlags () | GEPNoWrapFlags::noUnsignedWrap ());
3116
+ return &GEP;
3117
+ }
3118
+
3119
+ // These rewrites are trying to preserve inbounds/nuw attributes. So we want
3120
+ // to do this after having tried to derive "nuw" above.
3089
3121
if (GEP.getNumIndices () == 1 ) {
3090
- // We can only preserve inbounds if the original gep is inbounds, the add
3091
- // is nsw, and the add operands are non-negative.
3092
- auto CanPreserveInBounds = [&](bool AddIsNSW, Value *Idx1, Value *Idx2) {
3093
- SimplifyQuery Q = SQ.getWithInstruction (&GEP);
3094
- return GEP.isInBounds () && AddIsNSW && isKnownNonNegative (Idx1, Q) &&
3095
- isKnownNonNegative (Idx2, Q);
3122
+ // Given (gep p, x+y) we want to determine the common nowrap flags for both
3123
+ // geps if transforming into (gep (gep p, x), y).
3124
+ auto GetPreservedNoWrapFlags = [&](bool AddIsNUW) {
3125
+ // We can preserve both "inbounds nuw", "nusw nuw" and "nuw" if we know
3126
+ // that x + y does not have unsigned wrap.
3127
+ if (GEP.hasNoUnsignedWrap () && AddIsNUW)
3128
+ return GEP.getNoWrapFlags ();
3129
+ return GEPNoWrapFlags::none ();
3096
3130
};
3097
3131
3098
3132
// Try to replace ADD + GEP with GEP + GEP.
@@ -3104,15 +3138,14 @@ Instruction *InstCombinerImpl::visitGetElementPtrInst(GetElementPtrInst &GEP) {
3104
3138
// as:
3105
3139
// %newptr = getelementptr i32, ptr %ptr, i64 %idx1
3106
3140
// %newgep = getelementptr i32, ptr %newptr, i64 %idx2
3107
- bool IsInBounds = CanPreserveInBounds (
3108
- cast<OverflowingBinaryOperator>(GEP.getOperand (1 ))->hasNoSignedWrap (),
3109
- Idx1, Idx2);
3141
+ bool NUW = match (GEP.getOperand (1 ), m_NUWAddLike (m_Value (), m_Value ()));
3142
+ GEPNoWrapFlags NWFlags = GetPreservedNoWrapFlags (NUW);
3110
3143
auto *NewPtr =
3111
3144
Builder.CreateGEP (GEP.getSourceElementType (), GEP.getPointerOperand (),
3112
- Idx1, " " , IsInBounds );
3113
- return replaceInstUsesWith (
3114
- GEP, Builder.CreateGEP (GEP.getSourceElementType (), NewPtr , Idx2, " " ,
3115
- IsInBounds ));
3145
+ Idx1, " " , NWFlags );
3146
+ return replaceInstUsesWith (GEP,
3147
+ Builder.CreateGEP (GEP.getSourceElementType (),
3148
+ NewPtr , Idx2, " " , NWFlags ));
3116
3149
}
3117
3150
ConstantInt *C;
3118
3151
if (match (GEP.getOperand (1 ), m_OneUse (m_SExtLike (m_OneUse (m_NSWAdd (
@@ -3123,51 +3156,20 @@ Instruction *InstCombinerImpl::visitGetElementPtrInst(GetElementPtrInst &GEP) {
3123
3156
// as:
3124
3157
// %newptr = getelementptr i32, ptr %ptr, i32 %idx1
3125
3158
// %newgep = getelementptr i32, ptr %newptr, i32 idx2
3126
- bool IsInBounds = CanPreserveInBounds (
3127
- /* IsNSW=*/ true , Idx1, C);
3159
+ bool NUW = match (GEP.getOperand (1 ),
3160
+ m_NNegZExt (m_NUWAddLike (m_Value (), m_Value ())));
3161
+ GEPNoWrapFlags NWFlags = GetPreservedNoWrapFlags (NUW);
3128
3162
auto *NewPtr = Builder.CreateGEP (
3129
3163
GEP.getSourceElementType (), GEP.getPointerOperand (),
3130
- Builder.CreateSExt (Idx1, GEP.getOperand (1 )->getType ()), " " ,
3131
- IsInBounds);
3164
+ Builder.CreateSExt (Idx1, GEP.getOperand (1 )->getType ()), " " , NWFlags);
3132
3165
return replaceInstUsesWith (
3133
3166
GEP,
3134
3167
Builder.CreateGEP (GEP.getSourceElementType (), NewPtr ,
3135
3168
Builder.CreateSExt (C, GEP.getOperand (1 )->getType ()),
3136
- " " , IsInBounds ));
3169
+ " " , NWFlags ));
3137
3170
}
3138
3171
}
3139
3172
3140
- if (!GEP.isInBounds ()) {
3141
- unsigned IdxWidth =
3142
- DL.getIndexSizeInBits (PtrOp->getType ()->getPointerAddressSpace ());
3143
- APInt BasePtrOffset (IdxWidth, 0 );
3144
- Value *UnderlyingPtrOp =
3145
- PtrOp->stripAndAccumulateInBoundsConstantOffsets (DL,
3146
- BasePtrOffset);
3147
- bool CanBeNull, CanBeFreed;
3148
- uint64_t DerefBytes = UnderlyingPtrOp->getPointerDereferenceableBytes (
3149
- DL, CanBeNull, CanBeFreed);
3150
- if (!CanBeNull && !CanBeFreed && DerefBytes != 0 ) {
3151
- if (GEP.accumulateConstantOffset (DL, BasePtrOffset) &&
3152
- BasePtrOffset.isNonNegative ()) {
3153
- APInt AllocSize (IdxWidth, DerefBytes);
3154
- if (BasePtrOffset.ule (AllocSize)) {
3155
- return GetElementPtrInst::CreateInBounds (
3156
- GEP.getSourceElementType (), PtrOp, Indices, GEP.getName ());
3157
- }
3158
- }
3159
- }
3160
- }
3161
-
3162
- // nusw + nneg -> nuw
3163
- if (GEP.hasNoUnsignedSignedWrap () && !GEP.hasNoUnsignedWrap () &&
3164
- all_of (GEP.indices (), [&](Value *Idx) {
3165
- return isKnownNonNegative (Idx, SQ.getWithInstruction (&GEP));
3166
- })) {
3167
- GEP.setNoWrapFlags (GEP.getNoWrapFlags () | GEPNoWrapFlags::noUnsignedWrap ());
3168
- return &GEP;
3169
- }
3170
-
3171
3173
if (Instruction *R = foldSelectGEP (GEP, Builder))
3172
3174
return R;
3173
3175
0 commit comments