[llvm] 00808e3 - [InstSimplify] allow vector folds for (Pow2C << X) == NonPow2C
Sanjay Patel via llvm-commits
llvm-commits at lists.llvm.org
Sun Nov 8 07:07:39 PST 2020
Author: Sanjay Patel
Date: 2020-11-08T09:52:05-05:00
New Revision: 00808e321c724bd9f2a822bce87fe7fe87376371
URL: https://github.com/llvm/llvm-project/commit/00808e321c724bd9f2a822bce87fe7fe87376371
DIFF: https://github.com/llvm/llvm-project/commit/00808e321c724bd9f2a822bce87fe7fe87376371.diff
LOG: [InstSimplify] allow vector folds for (Pow2C << X) == NonPow2C
Existing pre-conditions seem to be correct:
https://rise4fun.com/Alive/lCLB
Name: non-zero C1
Pre: !isPowerOf2(C1) && isPowerOf2(C2) && C1 != 0
%sub = shl i8 C2, %X
%cmp = icmp eq i8 %sub, C1
=>
%cmp = false
Name: one == C2
Pre: !isPowerOf2(C1) && isPowerOf2(C2) && C2 == 1
%sub = shl i8 C2, %X
%cmp = icmp eq i8 %sub, C1
=>
%cmp = false
Name: nuw
Pre: !isPowerOf2(C1) && isPowerOf2(C2)
%sub = shl nuw i8 C2, %X
%cmp = icmp eq i8 %sub, C1
=>
%cmp = false
Name: nsw
Pre: !isPowerOf2(C1) && isPowerOf2(C2)
%sub = shl nsw i8 C2, %X
%cmp = icmp eq i8 %sub, C1
=>
%cmp = false
Added:
Modified:
llvm/lib/Analysis/InstructionSimplify.cpp
llvm/test/Transforms/InstSimplify/compare.ll
Removed:
################################################################################
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 44de7e9e40c1..813fb6c89863 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -2992,33 +2992,27 @@ static Value *simplifyICmpWithBinOp(CmpInst::Predicate Pred, Value *LHS,
}
}
- // handle:
- // CI2 << X == CI
- // CI2 << X != CI
- //
- // where CI2 is a power of 2 and CI isn't
- if (auto *CI = dyn_cast<ConstantInt>(RHS)) {
- const APInt *CI2Val, *CIVal = &CI->getValue();
- if (LBO && match(LBO, m_Shl(m_APInt(CI2Val), m_Value())) &&
- CI2Val->isPowerOf2()) {
- if (!CIVal->isPowerOf2()) {
- // CI2 << X can equal zero in some circumstances,
- // this simplification is unsafe if CI is zero.
- //
- // We know it is safe if:
- // - The shift is nsw, we can't shift out the one bit.
- // - The shift is nuw, we can't shift out the one bit.
- // - CI2 is one
- // - CI isn't zero
- if (Q.IIQ.hasNoSignedWrap(cast<OverflowingBinaryOperator>(LBO)) ||
- Q.IIQ.hasNoUnsignedWrap(cast<OverflowingBinaryOperator>(LBO)) ||
- CI2Val->isOneValue() || !CI->isZero()) {
- if (Pred == ICmpInst::ICMP_EQ)
- return ConstantInt::getFalse(RHS->getContext());
- if (Pred == ICmpInst::ICMP_NE)
- return ConstantInt::getTrue(RHS->getContext());
- }
- }
+ // If C2 is a power-of-2 and C is not:
+ // (C2 << X) == C --> false
+ // (C2 << X) != C --> true
+ const APInt *C;
+ if (match(LHS, m_Shl(m_Power2(), m_Value())) &&
+ match(RHS, m_APIntAllowUndef(C)) && !C->isPowerOf2()) {
+ // C2 << X can equal zero in some circumstances.
+ // This simplification might be unsafe if C is zero.
+ //
+ // We know it is safe if:
+ // - The shift is nsw. We can't shift out the one bit.
+ // - The shift is nuw. We can't shift out the one bit.
+ // - C2 is one.
+ // - C isn't zero.
+ if (Q.IIQ.hasNoSignedWrap(cast<OverflowingBinaryOperator>(LBO)) ||
+ Q.IIQ.hasNoUnsignedWrap(cast<OverflowingBinaryOperator>(LBO)) ||
+ match(LHS, m_Shl(m_One(), m_Value())) || !C->isNullValue()) {
+ if (Pred == ICmpInst::ICMP_EQ)
+ return ConstantInt::getFalse(GetCompareTy(RHS));
+ if (Pred == ICmpInst::ICMP_NE)
+ return ConstantInt::getTrue(GetCompareTy(RHS));
}
}
diff --git a/llvm/test/Transforms/InstSimplify/compare.ll b/llvm/test/Transforms/InstSimplify/compare.ll
index b31f3383bf79..834b0befac05 100644
--- a/llvm/test/Transforms/InstSimplify/compare.ll
+++ b/llvm/test/Transforms/InstSimplify/compare.ll
@@ -1542,9 +1542,7 @@ define i1 @shl_1_cmp_eq_nonpow2(i32 %x) {
define <2 x i1> @shl_1_cmp_eq_nonpow2_splat(<2 x i32> %x) {
; CHECK-LABEL: @shl_1_cmp_eq_nonpow2_splat(
-; CHECK-NEXT: [[S:%.*]] = shl <2 x i32> <i32 1, i32 1>, [[X:%.*]]
-; CHECK-NEXT: [[C:%.*]] = icmp eq <2 x i32> [[S]], <i32 31, i32 31>
-; CHECK-NEXT: ret <2 x i1> [[C]]
+; CHECK-NEXT: ret <2 x i1> zeroinitializer
;
%s = shl <2 x i32> <i32 1, i32 1>, %x
%c = icmp eq <2 x i32> %s, <i32 31, i32 31>
@@ -1553,9 +1551,7 @@ define <2 x i1> @shl_1_cmp_eq_nonpow2_splat(<2 x i32> %x) {
define <2 x i1> @shl_1_cmp_eq_nonpow2_splat_undef(<2 x i32> %x) {
; CHECK-LABEL: @shl_1_cmp_eq_nonpow2_splat_undef(
-; CHECK-NEXT: [[S:%.*]] = shl <2 x i32> <i32 1, i32 1>, [[X:%.*]]
-; CHECK-NEXT: [[C:%.*]] = icmp eq <2 x i32> [[S]], <i32 31, i32 undef>
-; CHECK-NEXT: ret <2 x i1> [[C]]
+; CHECK-NEXT: ret <2 x i1> zeroinitializer
;
%s = shl <2 x i32> <i32 1, i32 1>, %x
%c = icmp eq <2 x i32> %s, <i32 31, i32 undef>
@@ -1573,9 +1569,7 @@ define i1 @shl_1_cmp_ne_nonpow2(i32 %x) {
define <2 x i1> @shl_1_cmp_ne_nonpow2_splat(<2 x i32> %x) {
; CHECK-LABEL: @shl_1_cmp_ne_nonpow2_splat(
-; CHECK-NEXT: [[S:%.*]] = shl <2 x i32> <i32 1, i32 1>, [[X:%.*]]
-; CHECK-NEXT: [[C:%.*]] = icmp ne <2 x i32> [[S]], <i32 42, i32 42>
-; CHECK-NEXT: ret <2 x i1> [[C]]
+; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true>
;
%s = shl <2 x i32> <i32 1, i32 1>, %x
%c = icmp ne <2 x i32> %s, <i32 42, i32 42>
@@ -1584,9 +1578,7 @@ define <2 x i1> @shl_1_cmp_ne_nonpow2_splat(<2 x i32> %x) {
define <2 x i1> @shl_1_cmp_ne_nonpow2_splat_undef(<2 x i32> %x) {
; CHECK-LABEL: @shl_1_cmp_ne_nonpow2_splat_undef(
-; CHECK-NEXT: [[S:%.*]] = shl <2 x i32> <i32 undef, i32 1>, [[X:%.*]]
-; CHECK-NEXT: [[C:%.*]] = icmp ne <2 x i32> [[S]], <i32 42, i32 undef>
-; CHECK-NEXT: ret <2 x i1> [[C]]
+; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true>
;
%s = shl <2 x i32> <i32 undef, i32 1>, %x
%c = icmp ne <2 x i32> %s, <i32 42, i32 undef>
@@ -1604,15 +1596,15 @@ define i1 @shl_pow2_cmp_eq_nonpow2(i32 %x) {
define <2 x i1> @shl_pow21_cmp_ne_nonpow2_splat_undef(<2 x i32> %x) {
; CHECK-LABEL: @shl_pow21_cmp_ne_nonpow2_splat_undef(
-; CHECK-NEXT: [[S:%.*]] = shl <2 x i32> <i32 undef, i32 4>, [[X:%.*]]
-; CHECK-NEXT: [[C:%.*]] = icmp ne <2 x i32> [[S]], <i32 31, i32 undef>
-; CHECK-NEXT: ret <2 x i1> [[C]]
+; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true>
;
%s = shl <2 x i32> <i32 undef, i32 4>, %x
%c = icmp ne <2 x i32> %s, <i32 31, i32 undef>
ret <2 x i1> %c
}
+; Negative test - overflowing shift could be zero.
+
define i1 @shl_pow2_cmp_ne_zero(i32 %x) {
; CHECK-LABEL: @shl_pow2_cmp_ne_zero(
; CHECK-NEXT: [[S:%.*]] = shl i32 16, [[X:%.*]]
@@ -1624,6 +1616,8 @@ define i1 @shl_pow2_cmp_ne_zero(i32 %x) {
ret i1 %c
}
+; Negative test - overflowing shift could be zero.
+
define <2 x i1> @shl_pow2_cmp_ne_zero_splat(<2 x i32> %x) {
; CHECK-LABEL: @shl_pow2_cmp_ne_zero_splat(
; CHECK-NEXT: [[S:%.*]] = shl <2 x i32> <i32 16, i32 16>, [[X:%.*]]
@@ -1664,9 +1658,7 @@ define i1 @shl_pow2_cmp_ne_zero_nsw(i32 %x) {
define <2 x i1> @shl_pow2_cmp_eq_zero_nsw_splat_undef(<2 x i32> %x) {
; CHECK-LABEL: @shl_pow2_cmp_eq_zero_nsw_splat_undef(
-; CHECK-NEXT: [[S:%.*]] = shl nsw <2 x i32> <i32 undef, i32 16>, [[X:%.*]]
-; CHECK-NEXT: [[C:%.*]] = icmp eq <2 x i32> [[S]], <i32 0, i32 undef>
-; CHECK-NEXT: ret <2 x i1> [[C]]
+; CHECK-NEXT: ret <2 x i1> zeroinitializer
;
%s = shl nsw <2 x i32> <i32 undef, i32 16>, %x
%c = icmp eq <2 x i32> %s, <i32 0, i32 undef>
More information about the llvm-commits
mailing list