@@ -3086,23 +3086,51 @@ 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,
3095
+ BasePtrOffset);
3096
+ bool CanBeNull, CanBeFreed;
3097
+ uint64_t DerefBytes = UnderlyingPtrOp->getPointerDereferenceableBytes (
3098
+ DL, CanBeNull, CanBeFreed);
3099
+ if (!CanBeNull && !CanBeFreed && DerefBytes != 0 ) {
3100
+ if (GEP.accumulateConstantOffset (DL, BasePtrOffset) &&
3101
+ BasePtrOffset.isNonNegative ()) {
3102
+ APInt AllocSize (IdxWidth, DerefBytes);
3103
+ if (BasePtrOffset.ule (AllocSize)) {
3104
+ return GetElementPtrInst::CreateInBounds (
3105
+ GEP.getSourceElementType (), PtrOp, Indices, GEP.getName ());
3106
+ }
3107
+ }
3108
+ }
3109
+ }
3110
+
3111
+ // nusw + nneg -> nuw
3112
+ if (GEP.hasNoUnsignedSignedWrap () && !GEP.hasNoUnsignedWrap () &&
3113
+ all_of (GEP.indices (), [&](Value *Idx) {
3114
+ return isKnownNonNegative (Idx, SQ.getWithInstruction (&GEP));
3115
+ })) {
3116
+ GEP.setNoWrapFlags (GEP.getNoWrapFlags () | GEPNoWrapFlags::noUnsignedWrap ());
3117
+ return &GEP;
3118
+ }
3119
+
3120
+ // These rewrites is trying to preserve inbounds/nuw attributes. So we want to
3121
+ // do this after having tried to derive "nuw" above.
3089
3122
if (GEP.getNumIndices () == 1 ) {
3090
- auto CanPreserveNoWrapFlags = [&](bool AddIsNSW, bool AddIsNUW, Value *Idx1,
3091
- Value *Idx2) {
3092
- // Preserve "inbounds nuw" if the original gep is "inbounds nuw",
3093
- // and the add is "nuw".
3094
- if (GEP.isInBounds () && GEP.hasNoUnsignedWrap () && AddIsNUW)
3095
- return GEPNoWrapFlags::inBounds () | GEPNoWrapFlags::noUnsignedWrap ();
3096
- // Preserve "inbounds" if the original gep is "inbounds", the add
3097
- // is "nsw", and the add operands are non-negative.
3098
- SimplifyQuery Q = SQ.getWithInstruction (&GEP);
3099
- if (GEP.isInBounds () && AddIsNSW && isKnownNonNegative (Idx1, Q) &&
3100
- isKnownNonNegative (Idx2, Q))
3101
- return GEPNoWrapFlags::inBounds ();
3102
- // Preserve "nuw" if the original gep is "nuw", and the add is "nuw".
3103
- if (GEP.hasNoUnsignedWrap () && AddIsNUW)
3104
- return GEPNoWrapFlags::noUnsignedWrap ();
3105
- return GEPNoWrapFlags::none ();
3123
+ auto GetPreservedNoWrapFlags = [&](bool AddIsNUW, Value *Idx1, Value *Idx2) {
3124
+ // Preserve "inbounds nuw" if the original gep is "inbounds nuw", and the
3125
+ // add is "nuw". Preserve "nuw" if the original gep is "nuw", and the add
3126
+ // is "nuw".
3127
+ GEPNoWrapFlags Flags = GEPNoWrapFlags::none ();
3128
+ if (GEP.hasNoUnsignedWrap () && AddIsNUW) {
3129
+ Flags |= GEPNoWrapFlags::noUnsignedWrap ();
3130
+ if (GEP.isInBounds ())
3131
+ Flags |= GEPNoWrapFlags::inBounds ();
3132
+ }
3133
+ return Flags;
3106
3134
};
3107
3135
3108
3136
// Try to replace ADD + GEP with GEP + GEP.
@@ -3114,9 +3142,8 @@ Instruction *InstCombinerImpl::visitGetElementPtrInst(GetElementPtrInst &GEP) {
3114
3142
// as:
3115
3143
// %newptr = getelementptr i32, ptr %ptr, i64 %idx1
3116
3144
// %newgep = getelementptr i32, ptr %newptr, i64 %idx2
3117
- bool NSW = match (GEP.getOperand (1 ), m_NSWAddLike (m_Value (), m_Value ()));
3118
3145
bool NUW = match (GEP.getOperand (1 ), m_NUWAddLike (m_Value (), m_Value ()));
3119
- GEPNoWrapFlags NWFlags = CanPreserveNoWrapFlags (NSW, NUW, Idx1, Idx2);
3146
+ GEPNoWrapFlags NWFlags = GetPreservedNoWrapFlags ( NUW, Idx1, Idx2);
3120
3147
auto *NewPtr =
3121
3148
Builder.CreateGEP (GEP.getSourceElementType (), GEP.getPointerOperand (),
3122
3149
Idx1, " " , NWFlags);
@@ -3133,8 +3160,9 @@ Instruction *InstCombinerImpl::visitGetElementPtrInst(GetElementPtrInst &GEP) {
3133
3160
// as:
3134
3161
// %newptr = getelementptr i32, ptr %ptr, i32 %idx1
3135
3162
// %newgep = getelementptr i32, ptr %newptr, i32 idx2
3136
- GEPNoWrapFlags NWFlags = CanPreserveNoWrapFlags (
3137
- /* IsNSW=*/ true , /* IsNUW=*/ false , Idx1, C);
3163
+ bool NUW = match (GEP.getOperand (1 ), m_NNegZExt (m_NUWAddLike (m_Value (),
3164
+ m_Value ())));
3165
+ GEPNoWrapFlags NWFlags = GetPreservedNoWrapFlags (NUW, Idx1, C);
3138
3166
auto *NewPtr = Builder.CreateGEP (
3139
3167
GEP.getSourceElementType (), GEP.getPointerOperand (),
3140
3168
Builder.CreateSExt (Idx1, GEP.getOperand (1 )->getType ()), " " , NWFlags);
@@ -3146,37 +3174,6 @@ Instruction *InstCombinerImpl::visitGetElementPtrInst(GetElementPtrInst &GEP) {
3146
3174
}
3147
3175
}
3148
3176
3149
- if (!GEP.isInBounds ()) {
3150
- unsigned IdxWidth =
3151
- DL.getIndexSizeInBits (PtrOp->getType ()->getPointerAddressSpace ());
3152
- APInt BasePtrOffset (IdxWidth, 0 );
3153
- Value *UnderlyingPtrOp =
3154
- PtrOp->stripAndAccumulateInBoundsConstantOffsets (DL,
3155
- BasePtrOffset);
3156
- bool CanBeNull, CanBeFreed;
3157
- uint64_t DerefBytes = UnderlyingPtrOp->getPointerDereferenceableBytes (
3158
- DL, CanBeNull, CanBeFreed);
3159
- if (!CanBeNull && !CanBeFreed && DerefBytes != 0 ) {
3160
- if (GEP.accumulateConstantOffset (DL, BasePtrOffset) &&
3161
- BasePtrOffset.isNonNegative ()) {
3162
- APInt AllocSize (IdxWidth, DerefBytes);
3163
- if (BasePtrOffset.ule (AllocSize)) {
3164
- return GetElementPtrInst::CreateInBounds (
3165
- GEP.getSourceElementType (), PtrOp, Indices, GEP.getName ());
3166
- }
3167
- }
3168
- }
3169
- }
3170
-
3171
- // nusw + nneg -> nuw
3172
- if (GEP.hasNoUnsignedSignedWrap () && !GEP.hasNoUnsignedWrap () &&
3173
- all_of (GEP.indices (), [&](Value *Idx) {
3174
- return isKnownNonNegative (Idx, SQ.getWithInstruction (&GEP));
3175
- })) {
3176
- GEP.setNoWrapFlags (GEP.getNoWrapFlags () | GEPNoWrapFlags::noUnsignedWrap ());
3177
- return &GEP;
3178
- }
3179
-
3180
3177
if (Instruction *R = foldSelectGEP (GEP, Builder))
3181
3178
return R;
3182
3179
0 commit comments