forked from OSchip/llvm-project
[InstCombine] Add a few more patterns for folding select of select
This is a patch that folds select of select to salvage some optimizations after select -> and/or folding is disabled. ``` select (select a, true, b), c, false -> select a, c, false select c, (select a, true, b), false -> select c, a, false if c implies that b is false (isImpliedCondition). ``` https://alive2.llvm.org/ce/z/ANatjt, https://alive2.llvm.org/ce/z/rv8zTB ``` sel (sel c, a, false), true, (sel !c, b, false) -> sel c, a, b sel (sel !c, a, false), true, (sel c, b, false) -> sel c, b, a ``` https://alive2.llvm.org/ce/z/U2kp-t, https://alive2.llvm.org/ce/z/bc88EE See D101191 Reviewed By: nikic Differential Revision: https://reviews.llvm.org/D101375
This commit is contained in:
parent
ecfe75eb74
commit
39eb2665d9
|
@ -2710,6 +2710,34 @@ Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) {
|
|||
return replaceInstUsesWith(SI, Op1);
|
||||
}
|
||||
}
|
||||
|
||||
// select (select a, true, b), c, false -> select a, c, false
|
||||
// select c, (select a, true, b), false -> select c, a, false
|
||||
// if c implies that b is false.
|
||||
if (match(CondVal, m_Select(m_Value(A), m_One(), m_Value(B))) &&
|
||||
match(FalseVal, m_Zero())) {
|
||||
Optional<bool> Res = isImpliedCondition(TrueVal, B, DL);
|
||||
if (Res && *Res == false)
|
||||
return replaceOperand(SI, 0, A);
|
||||
}
|
||||
if (match(TrueVal, m_Select(m_Value(A), m_One(), m_Value(B))) &&
|
||||
match(FalseVal, m_Zero())) {
|
||||
Optional<bool> Res = isImpliedCondition(CondVal, B, DL);
|
||||
if (Res && *Res == false)
|
||||
return replaceOperand(SI, 1, A);
|
||||
}
|
||||
|
||||
// sel (sel c, a, false), true, (sel !c, b, false) -> sel c, a, b
|
||||
// sel (sel !c, a, false), true, (sel c, b, false) -> sel c, b, a
|
||||
Value *C1, *C2;
|
||||
if (match(CondVal, m_Select(m_Value(C1), m_Value(A), m_Zero())) &&
|
||||
match(TrueVal, m_One()) &&
|
||||
match(FalseVal, m_Select(m_Value(C2), m_Value(B), m_Zero()))) {
|
||||
if (match(C2, m_Not(m_Specific(C1)))) // first case
|
||||
return SelectInst::Create(C1, A, B);
|
||||
else if (match(C1, m_Not(m_Specific(C2)))) // second case
|
||||
return SelectInst::Create(C2, B, A);
|
||||
}
|
||||
}
|
||||
|
||||
// Selecting between two integer or vector splat integer constants?
|
||||
|
|
|
@ -132,9 +132,7 @@ define <2 x i1> @xor_or3(<2 x i1> %c, <2 x i32> %X, <2 x i32> %Y) {
|
|||
define i1 @and_orn_cmp_1_logical(i32 %a, i32 %b, i1 %y) {
|
||||
; CHECK-LABEL: @and_orn_cmp_1_logical(
|
||||
; CHECK-NEXT: [[X:%.*]] = icmp sgt i32 [[A:%.*]], [[B:%.*]]
|
||||
; CHECK-NEXT: [[X_INV:%.*]] = icmp sle i32 [[A]], [[B]]
|
||||
; CHECK-NEXT: [[OR:%.*]] = select i1 [[Y:%.*]], i1 true, i1 [[X_INV]]
|
||||
; CHECK-NEXT: [[AND:%.*]] = select i1 [[X]], i1 [[OR]], i1 false
|
||||
; CHECK-NEXT: [[AND:%.*]] = select i1 [[X]], i1 [[Y:%.*]], i1 false
|
||||
; CHECK-NEXT: ret i1 [[AND]]
|
||||
;
|
||||
%x = icmp sgt i32 %a, %b
|
||||
|
@ -146,10 +144,8 @@ define i1 @and_orn_cmp_1_logical(i32 %a, i32 %b, i1 %y) {
|
|||
|
||||
define i1 @andn_or_cmp_2_logical(i16 %a, i16 %b, i1 %y) {
|
||||
; CHECK-LABEL: @andn_or_cmp_2_logical(
|
||||
; CHECK-NEXT: [[X:%.*]] = icmp sge i16 [[A:%.*]], [[B:%.*]]
|
||||
; CHECK-NEXT: [[X_INV:%.*]] = icmp slt i16 [[A]], [[B]]
|
||||
; CHECK-NEXT: [[OR:%.*]] = select i1 [[Y:%.*]], i1 true, i1 [[X]]
|
||||
; CHECK-NEXT: [[AND:%.*]] = select i1 [[OR]], i1 [[X_INV]], i1 false
|
||||
; CHECK-NEXT: [[X_INV:%.*]] = icmp slt i16 [[A:%.*]], [[B:%.*]]
|
||||
; CHECK-NEXT: [[AND:%.*]] = select i1 [[Y:%.*]], i1 [[X_INV]], i1 false
|
||||
; CHECK-NEXT: ret i1 [[AND]]
|
||||
;
|
||||
%x = icmp sge i16 %a, %b
|
||||
|
@ -161,10 +157,7 @@ define i1 @andn_or_cmp_2_logical(i16 %a, i16 %b, i1 %y) {
|
|||
|
||||
define i1 @bools_logical(i1 %a, i1 %b, i1 %c) {
|
||||
; CHECK-LABEL: @bools_logical(
|
||||
; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[C:%.*]], true
|
||||
; CHECK-NEXT: [[AND1:%.*]] = select i1 [[NOT]], i1 [[A:%.*]], i1 false
|
||||
; CHECK-NEXT: [[AND2:%.*]] = select i1 [[C]], i1 [[B:%.*]], i1 false
|
||||
; CHECK-NEXT: [[OR:%.*]] = select i1 [[AND1]], i1 true, i1 [[AND2]]
|
||||
; CHECK-NEXT: [[OR:%.*]] = select i1 [[C:%.*]], i1 [[B:%.*]], i1 [[A:%.*]]
|
||||
; CHECK-NEXT: ret i1 [[OR]]
|
||||
;
|
||||
%not = xor i1 %c, -1
|
||||
|
@ -176,10 +169,7 @@ define i1 @bools_logical(i1 %a, i1 %b, i1 %c) {
|
|||
|
||||
define i1 @bools2_logical(i1 %a, i1 %b, i1 %c) {
|
||||
; CHECK-LABEL: @bools2_logical(
|
||||
; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[C:%.*]], true
|
||||
; CHECK-NEXT: [[AND1:%.*]] = select i1 [[C]], i1 [[A:%.*]], i1 false
|
||||
; CHECK-NEXT: [[AND2:%.*]] = select i1 [[NOT]], i1 [[B:%.*]], i1 false
|
||||
; CHECK-NEXT: [[OR:%.*]] = select i1 [[AND1]], i1 true, i1 [[AND2]]
|
||||
; CHECK-NEXT: [[OR:%.*]] = select i1 [[C:%.*]], i1 [[A:%.*]], i1 [[B:%.*]]
|
||||
; CHECK-NEXT: ret i1 [[OR]]
|
||||
;
|
||||
%not = xor i1 %c, -1
|
||||
|
|
Loading…
Reference in New Issue