diff --git a/lib/Transforms/InstCombine/InstCombineSelect.cpp b/lib/Transforms/InstCombine/InstCombineSelect.cpp index 82ce31128c8..c15378bc742 100644 --- a/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -195,7 +195,10 @@ static bool isSelect01(Constant *C1, Constant *C2) { ConstantInt *C2I = dyn_cast(C2); if (!C2I) return false; - return (C1I->isZero() || C1I->isOne()) && (C2I->isZero() || C2I->isOne()); + if (!C1I->isZero() && !C2I->isZero()) // One side must be zero. + return false; + return C1I->isOne() || C1I->isAllOnesValue() || + C2I->isOne() || C2I->isAllOnesValue(); } /// FoldSelectIntoOp - Try fold the select into one of the operands to @@ -219,7 +222,7 @@ Instruction *InstCombiner::FoldSelectIntoOp(SelectInst &SI, Value *TrueVal, Constant *C = GetSelectFoldableConstant(TVI); Value *OOp = TVI->getOperand(2-OpToFold); // Avoid creating select between 2 constants unless it's selecting - // between 0 and 1. + // between 0, 1 and -1. if (!isa(OOp) || isSelect01(C, cast(OOp))) { Instruction *NewSel = SelectInst::Create(SI.getCondition(), OOp, C); InsertNewInstBefore(NewSel, SI); @@ -248,7 +251,7 @@ Instruction *InstCombiner::FoldSelectIntoOp(SelectInst &SI, Value *TrueVal, Constant *C = GetSelectFoldableConstant(FVI); Value *OOp = FVI->getOperand(2-OpToFold); // Avoid creating select between 2 constants unless it's selecting - // between 0 and 1. + // between 0, 1 and -1. if (!isa(OOp) || isSelect01(C, cast(OOp))) { Instruction *NewSel = SelectInst::Create(SI.getCondition(), C, OOp); InsertNewInstBefore(NewSel, SI); diff --git a/test/Transforms/InstCombine/select.ll b/test/Transforms/InstCombine/select.ll index 772299c29f9..fd3937d3da2 100644 --- a/test/Transforms/InstCombine/select.ll +++ b/test/Transforms/InstCombine/select.ll @@ -584,3 +584,15 @@ define i32 @test41(i1 %cond, i32 %x, i32 %y) { ; CHECK-NEXT: and i32 %x, %y ; CHECK-NEXT: ret i32 } + +define i32 @test42(i32 %x, i32 %y) { + %b = add i32 %y, -1 + %cond = icmp eq i32 %x, 0 + %c = select i1 %cond, i32 %b, i32 %y + ret i32 %c +; CHECK: @test42 +; CHECK-NEXT: %cond = icmp eq i32 %x, 0 +; CHECK-NEXT: %b = sext i1 %cond to i32 +; CHECK-NEXT: %c = add i32 %b, %y +; CHECK-NEXT: ret i32 %c +}