[llvm] 191a6e9 - optimize icmp-ugt-ashr
Nadav Rotem via llvm-commits
llvm-commits at lists.llvm.org
Thu Jan 20 09:31:54 PST 2022
Author: Nadav Rotem
Date: 2022-01-20T09:31:46-08:00
New Revision: 191a6e9dfa1a54b616e12bde2efa849ad8e03f48
URL: https://github.com/llvm/llvm-project/commit/191a6e9dfa1a54b616e12bde2efa849ad8e03f48
DIFF: https://github.com/llvm/llvm-project/commit/191a6e9dfa1a54b616e12bde2efa849ad8e03f48.diff
LOG: optimize icmp-ugt-ashr
This diff optimizes the sequence icmp-ugt(ashr,C_1) C_2. InstCombine
already implements this optimization for sgt, and this patch adds
support ugt. This patch adds the check for UGT.
@craig.topper came up with the idea and proof:
define i1 @src(i8 %x, i8 %y, i8 %c) {
%cp1 = add i8 %c, 1
%i = shl i8 %cp1, %y
%i.2 = ashr i8 %i, %y
%cmp = icmp eq i8 %cp1, %i.2
;Assume: C + 1 == (((C + 1) << y) >> y)
call void @llvm.assume(i1 %cmp)
; uncomment for the sgt case
%j = shl i8 %cp1, %y
%j.2 = sub i8 %j, 1
%cmp2 = icmp ne i8 %j.2, 127
;Assume (((c + 1 ) << y) - 1) != 127
call void @llvm.assume(i1 %cmp2)
%s = ashr i8 %x, %y
%r = icmp sgt i8 %s, %c
ret i1 %r
}
define i1 @tgt(i8 %x, i8 %y, i8 %c) {
%cp1 = add i8 %c, 1
%j = shl i8 %cp1, %y
%j.2 = sub i8 %j, 1
%r = icmp sgt i8 %x, %j.2
ret i1 %r
}
declare void @llvm.assume(i1)
This change is related to the optimizations in D117252.
Differential Revision: https://reviews.llvm.org/D117365
Added:
Modified:
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
llvm/test/Transforms/InstCombine/icmp-shr-lt-gt.ll
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 7dc9ae1d9d064..fd58a44504b3c 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -2239,7 +2239,7 @@ Instruction *InstCombinerImpl::foldICmpShrConstant(ICmpInst &Cmp,
// those conditions rather than checking them. This is
diff icult because of
// undef/poison (PR34838).
if (IsAShr) {
- if (Pred == CmpInst::ICMP_SLT || Pred == CmpInst::ICMP_ULT || IsExact) {
+ if (IsExact || Pred == CmpInst::ICMP_SLT || Pred == CmpInst::ICMP_ULT) {
// When ShAmtC can be shifted losslessly:
// icmp PRED (ashr exact X, ShAmtC), C --> icmp PRED X, (C << ShAmtC)
// icmp slt/ult (ashr X, ShAmtC), C --> icmp slt/ult X, (C << ShAmtC)
@@ -2254,6 +2254,12 @@ Instruction *InstCombinerImpl::foldICmpShrConstant(ICmpInst &Cmp,
(ShiftedC + 1).ashr(ShAmtVal) == (C + 1))
return new ICmpInst(Pred, X, ConstantInt::get(ShrTy, ShiftedC));
}
+ if (Pred == CmpInst::ICMP_UGT) {
+ // icmp ugt (ashr X, ShAmtC), C --> icmp ugt X, ((C + 1) << ShAmtC) - 1
+ APInt ShiftedC = (C + 1).shl(ShAmtVal) - 1;
+ if ((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:
diff --git a/llvm/test/Transforms/InstCombine/icmp-shr-lt-gt.ll b/llvm/test/Transforms/InstCombine/icmp-shr-lt-gt.ll
index a9fb4b1f217d4..82f5a6dad7608 100644
--- a/llvm/test/Transforms/InstCombine/icmp-shr-lt-gt.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-shr-lt-gt.ll
@@ -2344,8 +2344,7 @@ define i1 @ashr_ne_noexact(i8 %x) {
define i1 @ashr_ugt_noexact(i8 %x) {
; CHECK-LABEL: @ashr_ugt_noexact(
-; CHECK-NEXT: [[S:%.*]] = ashr i8 [[X:%.*]], 3
-; CHECK-NEXT: [[C:%.*]] = icmp ugt i8 [[S]], 10
+; CHECK-NEXT: [[C:%.*]] = icmp ugt i8 [[X:%.*]], 87
; CHECK-NEXT: ret i1 [[C]]
;
%s = ashr i8 %x, 3
@@ -2356,8 +2355,7 @@ define i1 @ashr_ugt_noexact(i8 %x) {
define i1 @ashr_uge_noexact(i8 %x) {
; CHECK-LABEL: @ashr_uge_noexact(
-; CHECK-NEXT: [[S:%.*]] = ashr i8 [[X:%.*]], 3
-; CHECK-NEXT: [[C:%.*]] = icmp ugt i8 [[S]], 9
+; CHECK-NEXT: [[C:%.*]] = icmp ugt i8 [[X:%.*]], 79
; CHECK-NEXT: ret i1 [[C]]
;
%s = ashr i8 %x, 3
@@ -2451,6 +2449,15 @@ define <4 x i1> @ashr_00_00_vec(<4 x i8> %x) {
ret <4 x i1> %c
}
+define i1 @ashr_sgt_overflow(i8 %x) {
+; CHECK-LABEL: @ashr_sgt_overflow(
+; CHECK-NEXT: ret i1 false
+;
+ %s = ashr i8 %x, 1
+ %c = icmp sgt i8 %s, 63
+ ret i1 %c
+}
+
define i1 @lshrult_01_00_exact(i4 %x) {
; CHECK-LABEL: @lshrult_01_00_exact(
; CHECK-NEXT: ret i1 false
diff --git a/llvm/test/Transforms/InstCombine/icmp-shr.ll b/llvm/test/Transforms/InstCombine/icmp-shr.ll
index 09732fea5e38f..168aa81874f68 100644
--- a/llvm/test/Transforms/InstCombine/icmp-shr.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-shr.ll
@@ -574,12 +574,9 @@ 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
-; CHECK-NEXT: [[R:%.*]] = icmp ugt i4 [[S]], 1
+; CHECK-NEXT: [[R:%.*]] = icmp ugt i4 [[X:%.*]], 3
; CHECK-NEXT: ret i1 [[R]]
;
%s = ashr i4 %x, 1
@@ -587,12 +584,9 @@ 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
-; CHECK-NEXT: [[R:%.*]] = icmp ugt i4 [[S]], 2
+; CHECK-NEXT: [[R:%.*]] = icmp ugt i4 [[X:%.*]], 5
; CHECK-NEXT: ret i1 [[R]]
;
%s = ashr i4 %x, 1
@@ -694,12 +688,9 @@ 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
-; CHECK-NEXT: [[R:%.*]] = icmp ugt i4 [[S]], -4
+; CHECK-NEXT: [[R:%.*]] = icmp ugt i4 [[X:%.*]], -7
; CHECK-NEXT: ret i1 [[R]]
;
%s = ashr i4 %x, 1
@@ -707,12 +698,9 @@ 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
-; CHECK-NEXT: [[R:%.*]] = icmp ugt i4 [[S]], -3
+; CHECK-NEXT: [[R:%.*]] = icmp ugt i4 [[X:%.*]], -5
; CHECK-NEXT: ret i1 [[R]]
;
%s = ashr i4 %x, 1
More information about the llvm-commits
mailing list