diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -2710,6 +2710,34 @@ 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 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 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? diff --git a/llvm/test/Transforms/InstCombine/select-safe-transforms.ll b/llvm/test/Transforms/InstCombine/select-safe-transforms.ll --- a/llvm/test/Transforms/InstCombine/select-safe-transforms.ll +++ b/llvm/test/Transforms/InstCombine/select-safe-transforms.ll @@ -132,9 +132,7 @@ 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 @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 @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 @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