Index: lib/Transforms/InstCombine/InstCombineAndOrXor.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -2266,6 +2266,33 @@ } } + // Change (or (X ? A : B), (!X ? C : D)) --> (X ? A : C), iff (B|D) == 0 + // That is, if the comparison is based on the results of two select + // instructions, check whether those conditions are inverse icmp instructions + // with zero operands. If so, simplify to a single select on one of the + // conditions. + { + Value *X = nullptr, *Y = nullptr; + // Match both: + // (or (X ? 0 : A), (!X ? 0 : C)) + // (or (X ? A : 0), (!X ? C : 0)) + if ((match(Op0, m_Select(m_Value(X), m_Value(A), m_Zero())) && + match(Op1, m_Select(m_Value(Y), m_Value(C), m_Zero()))) || + (match(Op0, m_Select(m_Value(X), m_Zero(), m_Value(A))) && + match(Op1, m_Select(m_Value(Y), m_Zero(), m_Value(C))))) { + // Only transform into a select if X and Y have inverted predicates + // with identical operands. + auto XCmp = dyn_cast(X); + auto YCmp = dyn_cast(Y); + if (XCmp && YCmp && + XCmp->getPredicate() == YCmp->getInversePredicate() && + XCmp->getOperand(0) == YCmp->getOperand(0) && + XCmp->getOperand(1) == YCmp->getOperand(1)) { + return SelectInst::Create(XCmp, A, C); + } + } + } + return Changed ? &I : nullptr; } Index: test/Transforms/InstCombine/logical-select.ll =================================================================== --- test/Transforms/InstCombine/logical-select.ll +++ test/Transforms/InstCombine/logical-select.ll @@ -62,6 +62,22 @@ ret i32 %t3 } +; PR32791 - https://bugs.llvm.org//show_bug.cgi?id=32791 +; Fold two selects with inverted predicates and zero operands. +define i32 @pal(i32 %a, i32 %b, i32 %c, i32 %d) { +; CHECK-LABEL: @pal( +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 %a, %b +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 %c, i32 %d +; CHECK-NEXT: ret i32 [[SEL]] +; + %cmp1 = icmp slt i32 %a, %b + %sel1 = select i1 %cmp1, i32 %c, i32 0 + %cmp2 = icmp sge i32 %a, %b + %sel2 = select i1 %cmp2, i32 %d, i32 0 + %or = or i32 %sel1, %sel2 + ret i32 %or +} + define i32 @par(i32 %a, i32 %b, i32 %c, i32 %d) { ; CHECK-LABEL: @par( ; CHECK-NEXT: [[T0:%.*]] = icmp slt i32 %a, %b