From 467eec09109f37646ada72a4fbb1ef99eec8bb09 Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Mon, 9 Mar 2020 17:24:11 -0400 Subject: [PATCH] [InstCombine] fold gep-of-select-of-constants (PR45084) As shown in: https://bugs.llvm.org/show_bug.cgi?id=45084 ...we failed to combine a gep with constant indexes with a pointer operand that is a select of constants. Differential Revision: https://reviews.llvm.org/D75807 --- .../InstCombine/InstructionCombining.cpp | 30 ++++++++++++++++++++++ llvm/test/Transforms/InstCombine/getelementptr.ll | 5 ++-- llvm/test/Transforms/InstCombine/mem-gep-zidx.ll | 4 +-- 3 files changed, 33 insertions(+), 6 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp index 66fb988..e0063eb 100644 --- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -1803,6 +1803,33 @@ static bool isMergedGEPInBounds(GEPOperator &GEP1, GEPOperator &GEP2) { (GEP2.isInBounds() || GEP2.hasAllZeroIndices()); } +/// Thread a GEP operation with constant indices through the constant true/false +/// arms of a select. +static Instruction *foldSelectGEP(GetElementPtrInst &GEP, + InstCombiner::BuilderTy &Builder) { + if (!GEP.hasAllConstantIndices()) + return nullptr; + + Instruction *Sel; + Value *Cond; + Constant *TrueC, *FalseC; + if (!match(GEP.getPointerOperand(), m_Instruction(Sel)) || + !match(Sel, + m_Select(m_Value(Cond), m_Constant(TrueC), m_Constant(FalseC)))) + return nullptr; + + // gep (select Cond, TrueC, FalseC), IndexC --> select Cond, TrueC', FalseC' + // Propagate 'inbounds' and metadata from existing instructions. + // Note: using IRBuilder to create the constants for efficiency. + SmallVector IndexC(GEP.idx_begin(), GEP.idx_end()); + bool IsInBounds = GEP.isInBounds(); + Value *NewTrueC = IsInBounds ? Builder.CreateInBoundsGEP(TrueC, IndexC) + : Builder.CreateGEP(TrueC, IndexC); + Value *NewFalseC = IsInBounds ? Builder.CreateInBoundsGEP(FalseC, IndexC) + : Builder.CreateGEP(FalseC, IndexC); + return SelectInst::Create(Cond, NewTrueC, NewFalseC, "", nullptr, Sel); +} + Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) { SmallVector Ops(GEP.op_begin(), GEP.op_end()); Type *GEPType = GEP.getType(); @@ -2446,6 +2473,9 @@ Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) { } } + if (Instruction *R = foldSelectGEP(GEP, Builder)) + return R; + return nullptr; } diff --git a/llvm/test/Transforms/InstCombine/getelementptr.ll b/llvm/test/Transforms/InstCombine/getelementptr.ll index 04a85f7..0257725 100644 --- a/llvm/test/Transforms/InstCombine/getelementptr.ll +++ b/llvm/test/Transforms/InstCombine/getelementptr.ll @@ -1216,8 +1216,7 @@ define i32* @test_gep_inbounds_of_gep(i32* %base) { define i32* @PR45084(i1 %cond) { ; CHECK-LABEL: @PR45084( -; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], %struct.f* @g0, %struct.f* @g1, !prof !0 -; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds [[STRUCT_F:%.*]], %struct.f* [[SEL]], i64 0, i32 0 +; CHECK-NEXT: [[GEP:%.*]] = select i1 [[COND:%.*]], i32* getelementptr inbounds (%struct.f, %struct.f* @g0, i64 0, i32 0), i32* getelementptr inbounds (%struct.f, %struct.f* @g1, i64 0, i32 0), !prof !0 ; CHECK-NEXT: ret i32* [[GEP]] ; %sel = select i1 %cond, %struct.f* @g0, %struct.f* @g1, !prof !0 @@ -1229,7 +1228,7 @@ define i32* @PR45084_extra_use(i1 %cond, %struct.f** %p) { ; CHECK-LABEL: @PR45084_extra_use( ; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], %struct.f* @g0, %struct.f* @g1 ; CHECK-NEXT: store %struct.f* [[SEL]], %struct.f** [[P:%.*]], align 8 -; CHECK-NEXT: [[GEP:%.*]] = getelementptr [[STRUCT_F:%.*]], %struct.f* [[SEL]], i64 0, i32 0 +; CHECK-NEXT: [[GEP:%.*]] = select i1 [[COND]], i32* getelementptr inbounds (%struct.f, %struct.f* @g0, i64 0, i32 0), i32* getelementptr inbounds (%struct.f, %struct.f* @g1, i64 0, i32 0) ; CHECK-NEXT: ret i32* [[GEP]] ; %sel = select i1 %cond, %struct.f* @g0, %struct.f* @g1 diff --git a/llvm/test/Transforms/InstCombine/mem-gep-zidx.ll b/llvm/test/Transforms/InstCombine/mem-gep-zidx.ll index cc2feaa..db86c83 100644 --- a/llvm/test/Transforms/InstCombine/mem-gep-zidx.ll +++ b/llvm/test/Transforms/InstCombine/mem-gep-zidx.ll @@ -35,9 +35,7 @@ define void @test2(i32 signext %x, i64 %v) #0 { define signext i32 @test3(i32 signext %x, i1 %y) #0 { ; CHECK-LABEL: @test3( -; CHECK-NEXT: [[P:%.*]] = select i1 [[Y:%.*]], [1 x i32]* @f.a, [1 x i32]* @f.b -; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds [1 x i32], [1 x i32]* [[P]], i64 0, i64 0 -; CHECK-NEXT: [[R:%.*]] = load i32, i32* [[TMP1]], align 4 +; CHECK-NEXT: [[R:%.*]] = select i1 [[Y:%.*]], i32 12, i32 55 ; CHECK-NEXT: ret i32 [[R]] ; %idxprom = sext i32 %x to i64 -- 2.7.4