diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp --- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -1649,6 +1649,15 @@ return CastInst::Create(CastOpc, NarrowBO, BO.getType()); } +bool isMergedGEPInBounds(GEPOperator &GEP1, GEPOperator &GEP2) { + // At least one GEP must be inbounds. + if (!GEP1.isInBounds() && !GEP2.isInBounds()) + return false; + + return (GEP1.isInBounds() || GEP1.hasAllZeroIndices()) && + (GEP2.isInBounds() || GEP2.hasAllZeroIndices()); +} + Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) { SmallVector Ops(GEP.op_begin(), GEP.op_end()); Type *GEPType = GEP.getType(); @@ -1922,7 +1931,7 @@ // Update the GEP in place if possible. if (Src->getNumOperands() == 2) { - GEP.setIsInBounds(GEP.isInBounds() && Src->isInBounds()); + GEP.setIsInBounds(isMergedGEPInBounds(*Src, *cast(&GEP))); GEP.setOperand(0, Src->getOperand(0)); GEP.setOperand(1, Sum); return &GEP; @@ -1939,7 +1948,7 @@ } if (!Indices.empty()) - return GEP.isInBounds() && Src->isInBounds() + return isMergedGEPInBounds(*Src, *cast(&GEP)) ? GetElementPtrInst::CreateInBounds( Src->getSourceElementType(), Src->getOperand(0), Indices, GEP.getName()) diff --git a/llvm/test/Transforms/InstCombine/getelementptr.ll b/llvm/test/Transforms/InstCombine/getelementptr.ll --- a/llvm/test/Transforms/InstCombine/getelementptr.ll +++ b/llvm/test/Transforms/InstCombine/getelementptr.ll @@ -1171,7 +1171,7 @@ define i32* @test_bitcast_nzgep([1 x i32]* %base, i64 %idx) { ; CHECK-LABEL: @test_bitcast_nzgep( -; CHECK-NEXT: [[PTR:%.*]] = getelementptr [1 x i32], [1 x i32]* [[BASE:%.*]], i64 0, i64 [[IDX:%.*]] +; CHECK-NEXT: [[PTR:%.*]] = getelementptr inbounds [1 x i32], [1 x i32]* [[BASE:%.*]], i64 0, i64 [[IDX:%.*]] ; CHECK-NEXT: ret i32* [[PTR]] ; %base2 = bitcast [1 x i32]* %base to i32* @@ -1181,7 +1181,7 @@ define i32* @test_zgep_nzgep([1 x i32]* %base, i64 %idx) { ; CHECK-LABEL: @test_zgep_nzgep( -; CHECK-NEXT: [[PTR:%.*]] = getelementptr [1 x i32], [1 x i32]* [[BASE:%.*]], i64 0, i64 [[IDX:%.*]] +; CHECK-NEXT: [[PTR:%.*]] = getelementptr inbounds [1 x i32], [1 x i32]* [[BASE:%.*]], i64 0, i64 [[IDX:%.*]] ; CHECK-NEXT: ret i32* [[PTR]] ; %base2 = getelementptr [1 x i32], [1 x i32]* %base, i64 0, i64 0 @@ -1191,7 +1191,7 @@ define i32* @test_nzgep_zgep([1 x i32]* %base, i64 %idx) { ; CHECK-LABEL: @test_nzgep_zgep( -; CHECK-NEXT: [[PTR:%.*]] = getelementptr [1 x i32], [1 x i32]* [[BASE:%.*]], i64 [[IDX:%.*]], i64 0 +; CHECK-NEXT: [[PTR:%.*]] = getelementptr inbounds [1 x i32], [1 x i32]* [[BASE:%.*]], i64 [[IDX:%.*]], i64 0 ; CHECK-NEXT: ret i32* [[PTR]] ; %base2 = getelementptr inbounds [1 x i32], [1 x i32]* %base, i64 %idx