@@ -3086,13 +3086,47 @@ Instruction *InstCombinerImpl::visitGetElementPtrInst(GetElementPtrInst &GEP) {
30863086 if (GEPType->isVectorTy ())
30873087 return nullptr ;
30883088
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.
30893121 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 ();
30963130 };
30973131
30983132 // Try to replace ADD + GEP with GEP + GEP.
@@ -3104,15 +3138,14 @@ Instruction *InstCombinerImpl::visitGetElementPtrInst(GetElementPtrInst &GEP) {
31043138 // as:
31053139 // %newptr = getelementptr i32, ptr %ptr, i64 %idx1
31063140 // %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);
31103143 auto *NewPtr =
31113144 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 ));
31163149 }
31173150 ConstantInt *C;
31183151 if (match (GEP.getOperand (1 ), m_OneUse (m_SExtLike (m_OneUse (m_NSWAdd (
@@ -3123,51 +3156,20 @@ Instruction *InstCombinerImpl::visitGetElementPtrInst(GetElementPtrInst &GEP) {
31233156 // as:
31243157 // %newptr = getelementptr i32, ptr %ptr, i32 %idx1
31253158 // %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);
31283162 auto *NewPtr = Builder.CreateGEP (
31293163 GEP.getSourceElementType (), GEP.getPointerOperand (),
3130- Builder.CreateSExt (Idx1, GEP.getOperand (1 )->getType ()), " " ,
3131- IsInBounds);
3164+ Builder.CreateSExt (Idx1, GEP.getOperand (1 )->getType ()), " " , NWFlags);
31323165 return replaceInstUsesWith (
31333166 GEP,
31343167 Builder.CreateGEP (GEP.getSourceElementType (), NewPtr,
31353168 Builder.CreateSExt (C, GEP.getOperand (1 )->getType ()),
3136- " " , IsInBounds ));
3169+ " " , NWFlags ));
31373170 }
31383171 }
31393172
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-
31713173 if (Instruction *R = foldSelectGEP (GEP, Builder))
31723174 return R;
31733175
0 commit comments