Index: llvm/lib/Transforms/InstCombine/InstructionCombining.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -1649,6 +1649,11 @@ return CastInst::Create(CastOpc, NarrowBO, BO.getType()); } +bool isMergedGEPInBounds(GEPOperator &GEP1, GEPOperator &GEP2) { + // TODO: Special case zero-index GEPs. + return GEP1.isInBounds() && GEP2.isInBounds(); +} + Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) { SmallVector Ops(GEP.op_begin(), GEP.op_end()); Type *GEPType = GEP.getType(); @@ -1922,6 +1927,7 @@ // Update the GEP in place if possible. if (Src->getNumOperands() == 2) { + GEP.setIsInBounds(isMergedGEPInBounds(*Src, *cast(&GEP))); GEP.setOperand(0, Src->getOperand(0)); GEP.setOperand(1, Sum); return &GEP; @@ -1938,7 +1944,7 @@ } if (!Indices.empty()) - return GEP.isInBounds() && Src->isInBounds() + return isMergedGEPInBounds(*Src, *cast(&GEP)) ? GetElementPtrInst::CreateInBounds( Src->getSourceElementType(), Src->getOperand(0), Indices, GEP.getName()) Index: llvm/test/Transforms/InstCombine/getelementptr.ll =================================================================== --- llvm/test/Transforms/InstCombine/getelementptr.ll +++ llvm/test/Transforms/InstCombine/getelementptr.ll @@ -1201,7 +1201,7 @@ define i32* @test_gep_inbounds_of_gep(i32* %base) { ; CHECK-LABEL: @test_gep_inbounds_of_gep( -; CHECK-NEXT: [[PTR2:%.*]] = getelementptr inbounds i32, i32* [[BASE:%.*]], i64 8 +; CHECK-NEXT: [[PTR2:%.*]] = getelementptr i32, i32* [[BASE:%.*]], i64 8 ; CHECK-NEXT: ret i32* [[PTR2]] ; %ptr1 = getelementptr i32, i32* %base, i64 4 Index: llvm/test/Transforms/InstCombine/phi-equal-incoming-pointers.ll =================================================================== --- llvm/test/Transforms/InstCombine/phi-equal-incoming-pointers.ll +++ llvm/test/Transforms/InstCombine/phi-equal-incoming-pointers.ll @@ -528,7 +528,7 @@ ; ALL-NEXT: call void @foo.i32(i32* nonnull [[PTR1_TYPED]]) ; ALL-NEXT: br label [[EXIT:%.*]] ; ALL: bb2: -; ALL-NEXT: [[PTR2_1:%.*]] = getelementptr inbounds i8, i8* [[OBJ]], i64 16 +; ALL-NEXT: [[PTR2_1:%.*]] = getelementptr i8, i8* [[OBJ]], i64 16 ; ALL-NEXT: [[PTR2_TYPED:%.*]] = bitcast i8* [[PTR2_1]] to i32* ; ALL-NEXT: [[RES2:%.*]] = load i32, i32* [[PTR2_TYPED]], align 4 ; ALL-NEXT: call void @foo.i32(i32* nonnull [[PTR2_TYPED]]) Index: llvm/test/Transforms/InstCombine/pr26992.ll =================================================================== --- llvm/test/Transforms/InstCombine/pr26992.ll +++ llvm/test/Transforms/InstCombine/pr26992.ll @@ -9,7 +9,7 @@ ; CHECK-NEXT: invoke void @may_throw() ; CHECK-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[CATCH_DISPATCH:%.*]] ; CHECK: invoke.cont: -; CHECK-NEXT: [[B:%.*]] = getelementptr inbounds i8, i8* [[P]], i64 2 +; CHECK-NEXT: [[B:%.*]] = getelementptr i8, i8* [[P]], i64 2 ; CHECK-NEXT: invoke void @may_throw() ; CHECK-NEXT: to label [[EXIT:%.*]] unwind label [[CATCH_DISPATCH]] ; CHECK: catch.dispatch: