forked from OSchip/llvm-project
[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
This commit is contained in:
parent
5b465ad290
commit
467eec0910
|
@ -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<Value *, 4> 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<Value*, 8> 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue