diff --git a/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp index c1e60d4c427..bf065fe8173 100644 --- a/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ b/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -1245,6 +1245,34 @@ Instruction *InstCombiner::visitAnd(BinaryOperator &I) { } } + { + Value *X = 0; + bool OpsSwapped = false; + // Canonicalize SExt or Not to the LHS + if (match(Op1, m_SExt(m_Value())) || + match(Op1, m_Not(m_Value()))) { + std::swap(Op0, Op1); + OpsSwapped = true; + } + + // Fold (and (sext bool to A), B) --> (select bool, B, 0) + if (match(Op0, m_SExt(m_Value(X))) && + X->getType()->getScalarType()->isIntegerTy(1)) { + Value *Zero = Constant::getNullValue(Op1->getType()); + return SelectInst::Create(X, Op1, Zero); + } + + // Fold (and ~(sext bool to A), B) --> (select bool, 0, B) + if (match(Op0, m_Not(m_SExt(m_Value(X)))) && + X->getType()->getScalarType()->isIntegerTy(1)) { + Value *Zero = Constant::getNullValue(Op0->getType()); + return SelectInst::Create(X, Zero, Op1); + } + + if (OpsSwapped) + std::swap(Op0, Op1); + } + return Changed ? &I : 0; } diff --git a/test/Transforms/InstCombine/logical-select.ll b/test/Transforms/InstCombine/logical-select.ll index bb59817a4f6..07a326b47f0 100644 --- a/test/Transforms/InstCombine/logical-select.ll +++ b/test/Transforms/InstCombine/logical-select.ll @@ -10,8 +10,10 @@ define i32 @foo(i32 %a, i32 %b, i32 %c, i32 %d) nounwind { %j = or i32 %g, %i ret i32 %j ; CHECK: %e = icmp slt i32 %a, %b -; CHECK: %j = select i1 %e, i32 %c, i32 %d -; CHECK: ret i32 %j +; CHECK-NEXT: %g = select i1 %e, i32 %c, i32 0 +; CHECK-NEXT: %i = select i1 %e, i32 0, i32 %d +; CHECK-NEXT: %j = or i32 %g, %i +; CHECK-NEXT: ret i32 %j } define i32 @bar(i32 %a, i32 %b, i32 %c, i32 %d) nounwind { %e = icmp slt i32 %a, %b @@ -22,8 +24,10 @@ define i32 @bar(i32 %a, i32 %b, i32 %c, i32 %d) nounwind { %j = or i32 %i, %g ret i32 %j ; CHECK: %e = icmp slt i32 %a, %b -; CHECK: %j = select i1 %e, i32 %c, i32 %d -; CHECK: ret i32 %j +; CHECK-NEXT: %g = select i1 %e, i32 %c, i32 0 +; CHECK-NEXT: %i = select i1 %e, i32 0, i32 %d +; CHECK-NEXT: %j = or i32 %i, %g +; CHECK-NEXT: ret i32 %j } define i32 @goo(i32 %a, i32 %b, i32 %c, i32 %d) nounwind { @@ -36,8 +40,10 @@ entry: %3 = or i32 %1, %2 ret i32 %3 ; CHECK: %0 = icmp slt i32 %a, %b -; CHECK: %1 = select i1 %0, i32 %c, i32 %d -; CHECK: ret i32 %1 +; CHECK-NEXT: %1 = select i1 %0, i32 %c, i32 0 +; CHECK-NEXT: %2 = select i1 %0, i32 0, i32 %d +; CHECK-NEXT: %3 = or i32 %1, %2 +; CHECK-NEXT: ret i32 %3 } define i32 @poo(i32 %a, i32 %b, i32 %c, i32 %d) nounwind { entry: @@ -49,8 +55,10 @@ entry: %3 = or i32 %1, %2 ret i32 %3 ; CHECK: %0 = icmp slt i32 %a, %b -; CHECK: %1 = select i1 %0, i32 %c, i32 %d -; CHECK: ret i32 %1 +; CHECK-NEXT: %1 = select i1 %0, i32 %c, i32 0 +; CHECK-NEXT: %2 = select i1 %0, i32 0, i32 %d +; CHECK-NEXT: %3 = or i32 %1, %2 +; CHECK-NEXT: ret i32 %3 } define i32 @par(i32 %a, i32 %b, i32 %c, i32 %d) nounwind { @@ -63,6 +71,8 @@ entry: %3 = or i32 %1, %2 ret i32 %3 ; CHECK: %0 = icmp slt i32 %a, %b -; CHECK: %1 = select i1 %0, i32 %c, i32 %d -; CHECK: ret i32 %1 +; CHECK-NEXT: %1 = select i1 %0, i32 %c, i32 0 +; CHECK-NEXT: %2 = select i1 %0, i32 0, i32 %d +; CHECK-NEXT: %3 = or i32 %1, %2 +; CHECK-NEXT: ret i32 %3 } diff --git a/test/Transforms/InstCombine/mul.ll b/test/Transforms/InstCombine/mul.ll index 34ce088e293..16213b8628c 100644 --- a/test/Transforms/InstCombine/mul.ll +++ b/test/Transforms/InstCombine/mul.ll @@ -138,9 +138,8 @@ define i32 @test16(i32 %b, i1 %c) { ; e = b & (a >> 31) %e = mul i32 %d, %b ; [#uses=1] ret i32 %e -; CHECK: [[TEST16:%.*]] = sext i1 %c to i32 -; CHECK-NEXT: %e = and i32 %1, %b -; CHECK-NEXT: ret i32 %e +; CHECK: [[TEST16:%.*]] = select i1 %c, i32 %b, i32 0 +; CHECK-NEXT: ret i32 [[TEST16]] } ; X * Y (when Y is 0 or 1) --> x & (0-Y) diff --git a/test/Transforms/InstCombine/vector-casts.ll b/test/Transforms/InstCombine/vector-casts.ll index 7bbf53c270f..2f2990b7b05 100644 --- a/test/Transforms/InstCombine/vector-casts.ll +++ b/test/Transforms/InstCombine/vector-casts.ll @@ -64,7 +64,8 @@ entry: ; CHECK: @test5 ; CHECK: sext <4 x i1> %cmp to <4 x i32> -; CHECK: sext <4 x i1> %cmp4 to <4 x i32> +; The sext-and pair is canonicalized to a select. +; CHECK: select <4 x i1> %cmp4, <4 x i32> %sext, <4 x i32> zeroinitializer }