Index: lib/Transforms/InstCombine/InstCombineAndOrXor.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -2266,6 +2266,26 @@ } } + // If the comparison is with the results of two select instructions, check + // whether those conditions are inverse icmp instructions. If so, simplify to + // a single select on one of the conditions. + { + auto Op0Select = dyn_cast(Op0); + auto Op1Select = dyn_cast(Op1); + if (Op0Select && Op1Select) { + auto Op0Cmp = dyn_cast(Op0Select->getCondition()); + auto Op1Cmp = dyn_cast(Op1Select->getCondition()); + if (Op0Cmp && Op1Cmp && + Op0Cmp->getPredicate() == Op1Cmp->getInversePredicate() && + Op0Cmp->getOperand(0) == Op1Cmp->getOperand(0) && + Op0Cmp->getOperand(1) == Op1Cmp->getOperand(1)) { + return SelectInst::Create(Op0Select->getCondition(), + Op0Select->getTrueValue(), + Op1Select->getTrueValue()); + } + } + } + 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