[llvm-branch-commits] [llvm] 288f3fc - [InstCombine] reduce icmp(ashr X, C1), C2 to sign-bit test
Sanjay Patel via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Mon Jan 11 12:57:56 PST 2021
Author: Sanjay Patel
Date: 2021-01-11T15:53:39-05:00
New Revision: 288f3fc5dfee0c51fc00fe10a985f93c505073eb
URL: https://github.com/llvm/llvm-project/commit/288f3fc5dfee0c51fc00fe10a985f93c505073eb
DIFF: https://github.com/llvm/llvm-project/commit/288f3fc5dfee0c51fc00fe10a985f93c505073eb.diff
LOG: [InstCombine] reduce icmp(ashr X, C1), C2 to sign-bit test
This is a more basic pattern that we should handle before trying to solve:
https://llvm.org/PR48640
There might be a better way to think about this because the pre-condition
that I came up with (number of sign bits in the compare constant) misses a
potential transform for each of ugt and ult as commented on in the test file.
Tried to model this is in Alive:
https://rise4fun.com/Alive/juX1
...but I couldn't get the ComputeNumSignBits() pre-condition to work as
expected, so replaced with leading 0/1 preconditions instead.
Name: ugt
Pre: countLeadingZeros(C2) <= C1 && countLeadingOnes(C2) <= C1
%a = ashr %x, C1
%r = icmp ugt i8 %a, C2
=>
%r = icmp slt i8 %x, 0
Name: ult
Pre: countLeadingZeros(C2) <= C1 && countLeadingOnes(C2) <= C1
%a = ashr %x, C1
%r = icmp ult i4 %a, C2
=>
%r = icmp sgt i4 %x, -1
Also approximated in Alive2:
https://alive2.llvm.org/ce/z/u5hCcz
https://alive2.llvm.org/ce/z/__szVL
Differential Revision: https://reviews.llvm.org/D94014
Added:
Modified:
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
llvm/test/Transforms/InstCombine/icmp-shr.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 852def699716..9b3cfb3bd754 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -2210,6 +2210,21 @@ Instruction *InstCombinerImpl::foldICmpShrConstant(ICmpInst &Cmp,
(ShiftedC + 1).ashr(ShAmtVal) == (C + 1))
return new ICmpInst(Pred, X, ConstantInt::get(ShrTy, ShiftedC));
}
+
+ // If the compare constant has significant bits above the lowest sign-bit,
+ // then convert an unsigned cmp to a test of the sign-bit:
+ // (ashr X, ShiftC) u> C --> X s< 0
+ // (ashr X, ShiftC) u< C --> X s> -1
+ if (C.getBitWidth() > 2 && C.getNumSignBits() <= ShAmtVal) {
+ if (Pred == CmpInst::ICMP_UGT) {
+ return new ICmpInst(CmpInst::ICMP_SLT, X,
+ ConstantInt::getNullValue(ShrTy));
+ }
+ if (Pred == CmpInst::ICMP_ULT) {
+ return new ICmpInst(CmpInst::ICMP_SGT, X,
+ ConstantInt::getAllOnesValue(ShrTy));
+ }
+ }
} else {
if (Pred == CmpInst::ICMP_ULT || (Pred == CmpInst::ICMP_UGT && IsExact)) {
// icmp ult (lshr X, ShAmtC), C --> icmp ult X, (C << ShAmtC)
diff --git a/llvm/test/Transforms/InstCombine/icmp-shr.ll b/llvm/test/Transforms/InstCombine/icmp-shr.ll
index 22f61d2d5e6a..ad3eb713aa19 100644
--- a/llvm/test/Transforms/InstCombine/icmp-shr.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-shr.ll
@@ -507,6 +507,10 @@ define <2 x i1> @exact_eq0_multiuse(<2 x i32> %x, <2 x i32> %y) {
ret <2 x i1> %cmp
}
+; Verify conversions of ashr+icmp to a sign-bit test.
+
+; negative test, but
diff erent transform possible
+
define i1 @ashr_ugt_0(i4 %x) {
; CHECK-LABEL: @ashr_ugt_0(
; CHECK-NEXT: [[R:%.*]] = icmp ugt i4 [[X:%.*]], 1
@@ -517,6 +521,8 @@ define i1 @ashr_ugt_0(i4 %x) {
ret i1 %r
}
+; negative test
+
define i1 @ashr_ugt_1(i4 %x) {
; CHECK-LABEL: @ashr_ugt_1(
; CHECK-NEXT: [[S:%.*]] = ashr i4 [[X:%.*]], 1
@@ -528,6 +534,8 @@ define i1 @ashr_ugt_1(i4 %x) {
ret i1 %r
}
+; negative test
+
define i1 @ashr_ugt_2(i4 %x) {
; CHECK-LABEL: @ashr_ugt_2(
; CHECK-NEXT: [[S:%.*]] = ashr i4 [[X:%.*]], 1
@@ -539,6 +547,9 @@ define i1 @ashr_ugt_2(i4 %x) {
ret i1 %r
}
+; negative test
+; TODO: This is a sign-bit test, but we don't recognize the pattern.
+
define i1 @ashr_ugt_3(i4 %x) {
; CHECK-LABEL: @ashr_ugt_3(
; CHECK-NEXT: [[S:%.*]] = ashr i4 [[X:%.*]], 1
@@ -552,8 +563,7 @@ define i1 @ashr_ugt_3(i4 %x) {
define i1 @ashr_ugt_4(i4 %x) {
; CHECK-LABEL: @ashr_ugt_4(
-; CHECK-NEXT: [[S:%.*]] = ashr i4 [[X:%.*]], 1
-; CHECK-NEXT: [[R:%.*]] = icmp ugt i4 [[S]], 4
+; CHECK-NEXT: [[R:%.*]] = icmp slt i4 [[X:%.*]], 0
; CHECK-NEXT: ret i1 [[R]]
;
%s = ashr i4 %x, 1
@@ -563,8 +573,7 @@ define i1 @ashr_ugt_4(i4 %x) {
define i1 @ashr_ugt_5(i4 %x) {
; CHECK-LABEL: @ashr_ugt_5(
-; CHECK-NEXT: [[S:%.*]] = ashr i4 [[X:%.*]], 1
-; CHECK-NEXT: [[R:%.*]] = icmp ugt i4 [[S]], 5
+; CHECK-NEXT: [[R:%.*]] = icmp slt i4 [[X:%.*]], 0
; CHECK-NEXT: ret i1 [[R]]
;
%s = ashr i4 %x, 1
@@ -574,8 +583,7 @@ define i1 @ashr_ugt_5(i4 %x) {
define i1 @ashr_ugt_6(i4 %x) {
; CHECK-LABEL: @ashr_ugt_6(
-; CHECK-NEXT: [[S:%.*]] = ashr i4 [[X:%.*]], 1
-; CHECK-NEXT: [[R:%.*]] = icmp ugt i4 [[S]], 6
+; CHECK-NEXT: [[R:%.*]] = icmp slt i4 [[X:%.*]], 0
; CHECK-NEXT: ret i1 [[R]]
;
%s = ashr i4 %x, 1
@@ -595,8 +603,7 @@ define i1 @ashr_ugt_7(i4 %x) {
define i1 @ashr_ugt_8(i4 %x) {
; CHECK-LABEL: @ashr_ugt_8(
-; CHECK-NEXT: [[S:%.*]] = ashr i4 [[X:%.*]], 1
-; CHECK-NEXT: [[R:%.*]] = icmp ugt i4 [[S]], -8
+; CHECK-NEXT: [[R:%.*]] = icmp slt i4 [[X:%.*]], 0
; CHECK-NEXT: ret i1 [[R]]
;
%s = ashr i4 %x, 1
@@ -606,8 +613,7 @@ define i1 @ashr_ugt_8(i4 %x) {
define i1 @ashr_ugt_9(i4 %x) {
; CHECK-LABEL: @ashr_ugt_9(
-; CHECK-NEXT: [[S:%.*]] = ashr i4 [[X:%.*]], 1
-; CHECK-NEXT: [[R:%.*]] = icmp ugt i4 [[S]], -7
+; CHECK-NEXT: [[R:%.*]] = icmp slt i4 [[X:%.*]], 0
; CHECK-NEXT: ret i1 [[R]]
;
%s = ashr i4 %x, 1
@@ -617,8 +623,7 @@ define i1 @ashr_ugt_9(i4 %x) {
define i1 @ashr_ugt_10(i4 %x) {
; CHECK-LABEL: @ashr_ugt_10(
-; CHECK-NEXT: [[S:%.*]] = ashr i4 [[X:%.*]], 1
-; CHECK-NEXT: [[R:%.*]] = icmp ugt i4 [[S]], -6
+; CHECK-NEXT: [[R:%.*]] = icmp slt i4 [[X:%.*]], 0
; CHECK-NEXT: ret i1 [[R]]
;
%s = ashr i4 %x, 1
@@ -628,8 +633,7 @@ define i1 @ashr_ugt_10(i4 %x) {
define i1 @ashr_ugt_11(i4 %x) {
; CHECK-LABEL: @ashr_ugt_11(
-; CHECK-NEXT: [[S:%.*]] = ashr i4 [[X:%.*]], 1
-; CHECK-NEXT: [[R:%.*]] = icmp ugt i4 [[S]], -5
+; CHECK-NEXT: [[R:%.*]] = icmp slt i4 [[X:%.*]], 0
; CHECK-NEXT: ret i1 [[R]]
;
%s = ashr i4 %x, 1
@@ -637,6 +641,8 @@ define i1 @ashr_ugt_11(i4 %x) {
ret i1 %r
}
+; negative test
+
define i1 @ashr_ugt_12(i4 %x) {
; CHECK-LABEL: @ashr_ugt_12(
; CHECK-NEXT: [[S:%.*]] = ashr i4 [[X:%.*]], 1
@@ -648,6 +654,8 @@ define i1 @ashr_ugt_12(i4 %x) {
ret i1 %r
}
+; negative test
+
define i1 @ashr_ugt_13(i4 %x) {
; CHECK-LABEL: @ashr_ugt_13(
; CHECK-NEXT: [[S:%.*]] = ashr i4 [[X:%.*]], 1
@@ -659,6 +667,8 @@ define i1 @ashr_ugt_13(i4 %x) {
ret i1 %r
}
+; negative test, but
diff erent transform possible
+
define i1 @ashr_ugt_14(i4 %x) {
; CHECK-LABEL: @ashr_ugt_14(
; CHECK-NEXT: [[R:%.*]] = icmp ugt i4 [[X:%.*]], -3
@@ -669,6 +679,8 @@ define i1 @ashr_ugt_14(i4 %x) {
ret i1 %r
}
+; negative test, but simplifies
+
define i1 @ashr_ugt_15(i4 %x) {
; CHECK-LABEL: @ashr_ugt_15(
; CHECK-NEXT: ret i1 false
@@ -678,6 +690,8 @@ define i1 @ashr_ugt_15(i4 %x) {
ret i1 %r
}
+; negative test, but simplifies
+
define i1 @ashr_ult_0(i4 %x) {
; CHECK-LABEL: @ashr_ult_0(
; CHECK-NEXT: ret i1 false
@@ -687,6 +701,8 @@ define i1 @ashr_ult_0(i4 %x) {
ret i1 %r
}
+; negative test, but
diff erent transform possible
+
define i1 @ashr_ult_1(i4 %x) {
; CHECK-LABEL: @ashr_ult_1(
; CHECK-NEXT: [[R:%.*]] = icmp ult i4 [[X:%.*]], 2
@@ -697,6 +713,8 @@ define i1 @ashr_ult_1(i4 %x) {
ret i1 %r
}
+; negative test
+
define i1 @ashr_ult_2(i4 %x) {
; CHECK-LABEL: @ashr_ult_2(
; CHECK-NEXT: [[S:%.*]] = ashr i4 [[X:%.*]], 1
@@ -708,6 +726,8 @@ define i1 @ashr_ult_2(i4 %x) {
ret i1 %r
}
+; negative test
+
define i1 @ashr_ult_3(i4 %x) {
; CHECK-LABEL: @ashr_ult_3(
; CHECK-NEXT: [[S:%.*]] = ashr i4 [[X:%.*]], 1
@@ -721,8 +741,7 @@ define i1 @ashr_ult_3(i4 %x) {
define i1 @ashr_ult_4(i4 %x) {
; CHECK-LABEL: @ashr_ult_4(
-; CHECK-NEXT: [[S:%.*]] = ashr i4 [[X:%.*]], 1
-; CHECK-NEXT: [[R:%.*]] = icmp ult i4 [[S]], 4
+; CHECK-NEXT: [[R:%.*]] = icmp sgt i4 [[X:%.*]], -1
; CHECK-NEXT: ret i1 [[R]]
;
%s = ashr i4 %x, 1
@@ -732,8 +751,7 @@ define i1 @ashr_ult_4(i4 %x) {
define i1 @ashr_ult_5(i4 %x) {
; CHECK-LABEL: @ashr_ult_5(
-; CHECK-NEXT: [[S:%.*]] = ashr i4 [[X:%.*]], 1
-; CHECK-NEXT: [[R:%.*]] = icmp ult i4 [[S]], 5
+; CHECK-NEXT: [[R:%.*]] = icmp sgt i4 [[X:%.*]], -1
; CHECK-NEXT: ret i1 [[R]]
;
%s = ashr i4 %x, 1
@@ -743,8 +761,7 @@ define i1 @ashr_ult_5(i4 %x) {
define i1 @ashr_ult_6(i4 %x) {
; CHECK-LABEL: @ashr_ult_6(
-; CHECK-NEXT: [[S:%.*]] = ashr i4 [[X:%.*]], 1
-; CHECK-NEXT: [[R:%.*]] = icmp ult i4 [[S]], 6
+; CHECK-NEXT: [[R:%.*]] = icmp sgt i4 [[X:%.*]], -1
; CHECK-NEXT: ret i1 [[R]]
;
%s = ashr i4 %x, 1
@@ -754,8 +771,7 @@ define i1 @ashr_ult_6(i4 %x) {
define i1 @ashr_ult_7(i4 %x) {
; CHECK-LABEL: @ashr_ult_7(
-; CHECK-NEXT: [[S:%.*]] = ashr i4 [[X:%.*]], 1
-; CHECK-NEXT: [[R:%.*]] = icmp ult i4 [[S]], 7
+; CHECK-NEXT: [[R:%.*]] = icmp sgt i4 [[X:%.*]], -1
; CHECK-NEXT: ret i1 [[R]]
;
%s = ashr i4 %x, 1
@@ -775,8 +791,7 @@ define i1 @ashr_ult_8(i4 %x) {
define i1 @ashr_ult_9(i4 %x) {
; CHECK-LABEL: @ashr_ult_9(
-; CHECK-NEXT: [[S:%.*]] = ashr i4 [[X:%.*]], 1
-; CHECK-NEXT: [[R:%.*]] = icmp ult i4 [[S]], -7
+; CHECK-NEXT: [[R:%.*]] = icmp sgt i4 [[X:%.*]], -1
; CHECK-NEXT: ret i1 [[R]]
;
%s = ashr i4 %x, 1
@@ -786,8 +801,7 @@ define i1 @ashr_ult_9(i4 %x) {
define i1 @ashr_ult_10(i4 %x) {
; CHECK-LABEL: @ashr_ult_10(
-; CHECK-NEXT: [[S:%.*]] = ashr i4 [[X:%.*]], 1
-; CHECK-NEXT: [[R:%.*]] = icmp ult i4 [[S]], -6
+; CHECK-NEXT: [[R:%.*]] = icmp sgt i4 [[X:%.*]], -1
; CHECK-NEXT: ret i1 [[R]]
;
%s = ashr i4 %x, 1
@@ -797,8 +811,7 @@ define i1 @ashr_ult_10(i4 %x) {
define i1 @ashr_ult_11(i4 %x) {
; CHECK-LABEL: @ashr_ult_11(
-; CHECK-NEXT: [[S:%.*]] = ashr i4 [[X:%.*]], 1
-; CHECK-NEXT: [[R:%.*]] = icmp ult i4 [[S]], -5
+; CHECK-NEXT: [[R:%.*]] = icmp sgt i4 [[X:%.*]], -1
; CHECK-NEXT: ret i1 [[R]]
;
%s = ashr i4 %x, 1
@@ -806,6 +819,9 @@ define i1 @ashr_ult_11(i4 %x) {
ret i1 %r
}
+; negative test
+; TODO: This is a sign-bit test, but we don't recognize the pattern.
+
define i1 @ashr_ult_12(i4 %x) {
; CHECK-LABEL: @ashr_ult_12(
; CHECK-NEXT: [[S:%.*]] = ashr i4 [[X:%.*]], 1
@@ -817,6 +833,8 @@ define i1 @ashr_ult_12(i4 %x) {
ret i1 %r
}
+; negative test
+
define i1 @ashr_ult_13(i4 %x) {
; CHECK-LABEL: @ashr_ult_13(
; CHECK-NEXT: [[S:%.*]] = ashr i4 [[X:%.*]], 1
@@ -828,6 +846,8 @@ define i1 @ashr_ult_13(i4 %x) {
ret i1 %r
}
+; negative test
+
define i1 @ashr_ult_14(i4 %x) {
; CHECK-LABEL: @ashr_ult_14(
; CHECK-NEXT: [[S:%.*]] = ashr i4 [[X:%.*]], 1
@@ -839,6 +859,8 @@ define i1 @ashr_ult_14(i4 %x) {
ret i1 %r
}
+; negative test, but
diff erent transform possible
+
define i1 @ashr_ult_15(i4 %x) {
; CHECK-LABEL: @ashr_ult_15(
; CHECK-NEXT: [[R:%.*]] = icmp ult i4 [[X:%.*]], -2
More information about the llvm-branch-commits
mailing list