[llvm] r308105 - [InstCombine] improve (1 << x) & 1 --> zext(x == 0) folding
Sanjay Patel via llvm-commits
llvm-commits at lists.llvm.org
Sat Jul 15 10:26:02 PDT 2017
Author: spatel
Date: Sat Jul 15 10:26:01 2017
New Revision: 308105
URL: http://llvm.org/viewvc/llvm-project?rev=308105&view=rev
Log:
[InstCombine] improve (1 << x) & 1 --> zext(x == 0) folding
1. Add a one-use check to prevent increasing instruction count.
2. Generalize the pattern matching to include vector types.
Modified:
llvm/trunk/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
llvm/trunk/test/Transforms/InstCombine/and2.ll
Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp?rev=308105&r1=308104&r2=308105&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp Sat Jul 15 10:26:01 2017
@@ -1284,10 +1284,19 @@ Instruction *InstCombiner::visitAnd(Bina
if (Value *V = SimplifyBSwap(I, Builder))
return replaceInstUsesWith(I, V);
- // (0 - x) & 1 --> x & 1
- Value *X;
- if (match(Op1, m_One()) && match(Op0, m_Sub(m_Zero(), m_Value(X))))
- return BinaryOperator::CreateAnd(X, Op1);
+ if (match(Op1, m_One())) {
+ Value *X;
+ // (0 - x) & 1 --> x & 1
+ if (match(Op0, m_Sub(m_Zero(), m_Value(X))))
+ return BinaryOperator::CreateAnd(X, Op1);
+
+ // (1 << x) & 1 --> zext(x == 0)
+ // (1 >> x) & 1 --> zext(x == 0)
+ if (match(Op0, m_OneUse(m_LogicalShift(m_One(), m_Value(X))))) {
+ Value *IsZero = Builder.CreateICmpEQ(X, ConstantInt::get(I.getType(), 0));
+ return new ZExtInst(IsZero, I.getType());
+ }
+ }
if (ConstantInt *AndRHS = dyn_cast<ConstantInt>(Op1)) {
const APInt &AndRHSMask = AndRHS->getValue();
@@ -1320,17 +1329,6 @@ Instruction *InstCombiner::visitAnd(Bina
break;
}
-
- case Instruction::Shl:
- case Instruction::LShr:
- // (1 << x) & 1 --> zext(x == 0)
- // (1 >> x) & 1 --> zext(x == 0)
- if (AndRHSMask.isOneValue() && Op0LHS == AndRHS) {
- Value *NewICmp =
- Builder.CreateICmpEQ(Op0RHS, Constant::getNullValue(I.getType()));
- return new ZExtInst(NewICmp, I.getType());
- }
- break;
}
// ((C1 OP zext(X)) & C2) -> zext((C1-X) & C2) if C2 fits in the bitwidth
Modified: llvm/trunk/test/Transforms/InstCombine/and2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/and2.ll?rev=308105&r1=308104&r2=308105&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/and2.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/and2.ll Sat Jul 15 10:26:01 2017
@@ -118,6 +118,8 @@ define i64 @test10(i64 %x) {
ret i64 %add
}
+; (1 << x) & 1 --> zext(x == 0)
+
define i8 @and1_shl1_is_cmp_eq_0(i8 %x) {
; CHECK-LABEL: @and1_shl1_is_cmp_eq_0(
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i8 %x, 0
@@ -129,11 +131,12 @@ define i8 @and1_shl1_is_cmp_eq_0(i8 %x)
ret i8 %and
}
+; Don't do it if the shift has another use.
+
define i8 @and1_shl1_is_cmp_eq_0_multiuse(i8 %x) {
; CHECK-LABEL: @and1_shl1_is_cmp_eq_0_multiuse(
; CHECK-NEXT: [[SH:%.*]] = shl i8 1, %x
-; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i8 %x, 0
-; CHECK-NEXT: [[AND:%.*]] = zext i1 [[TMP1]] to i8
+; CHECK-NEXT: [[AND:%.*]] = and i8 [[SH]], 1
; CHECK-NEXT: [[ADD:%.*]] = add i8 [[SH]], [[AND]]
; CHECK-NEXT: ret i8 [[ADD]]
;
@@ -143,10 +146,12 @@ define i8 @and1_shl1_is_cmp_eq_0_multius
ret i8 %add
}
+; (1 << x) & 1 --> zext(x == 0)
+
define <2 x i8> @and1_shl1_is_cmp_eq_0_vec(<2 x i8> %x) {
; CHECK-LABEL: @and1_shl1_is_cmp_eq_0_vec(
-; CHECK-NEXT: [[SH:%.*]] = shl <2 x i8> <i8 1, i8 1>, %x
-; CHECK-NEXT: [[AND:%.*]] = and <2 x i8> [[SH]], <i8 1, i8 1>
+; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <2 x i8> %x, zeroinitializer
+; CHECK-NEXT: [[AND:%.*]] = zext <2 x i1> [[TMP1]] to <2 x i8>
; CHECK-NEXT: ret <2 x i8> [[AND]]
;
%sh = shl <2 x i8> <i8 1, i8 1>, %x
@@ -154,6 +159,8 @@ define <2 x i8> @and1_shl1_is_cmp_eq_0_v
ret <2 x i8> %and
}
+; (1 >> x) & 1 --> zext(x == 0)
+
define i8 @and1_lshr1_is_cmp_eq_0(i8 %x) {
; CHECK-LABEL: @and1_lshr1_is_cmp_eq_0(
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i8 %x, 0
@@ -165,11 +172,12 @@ define i8 @and1_lshr1_is_cmp_eq_0(i8 %x)
ret i8 %and
}
+; Don't do it if the shift has another use.
+
define i8 @and1_lshr1_is_cmp_eq_0_multiuse(i8 %x) {
; CHECK-LABEL: @and1_lshr1_is_cmp_eq_0_multiuse(
; CHECK-NEXT: [[SH:%.*]] = lshr i8 1, %x
-; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i8 %x, 0
-; CHECK-NEXT: [[AND:%.*]] = zext i1 [[TMP1]] to i8
+; CHECK-NEXT: [[AND:%.*]] = and i8 [[SH]], 1
; CHECK-NEXT: [[ADD:%.*]] = add i8 [[SH]], [[AND]]
; CHECK-NEXT: ret i8 [[ADD]]
;
@@ -179,10 +187,12 @@ define i8 @and1_lshr1_is_cmp_eq_0_multiu
ret i8 %add
}
+; (1 >> x) & 1 --> zext(x == 0)
+
define <2 x i8> @and1_lshr1_is_cmp_eq_0_vec(<2 x i8> %x) {
; CHECK-LABEL: @and1_lshr1_is_cmp_eq_0_vec(
-; CHECK-NEXT: [[SH:%.*]] = lshr <2 x i8> <i8 1, i8 1>, %x
-; CHECK-NEXT: [[AND:%.*]] = and <2 x i8> [[SH]], <i8 1, i8 1>
+; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <2 x i8> %x, zeroinitializer
+; CHECK-NEXT: [[AND:%.*]] = zext <2 x i1> [[TMP1]] to <2 x i8>
; CHECK-NEXT: ret <2 x i8> [[AND]]
;
%sh = lshr <2 x i8> <i8 1, i8 1>, %x
More information about the llvm-commits
mailing list