[llvm] c7b658a - [InstCombine] fold icmp of offset value with constant
Sanjay Patel via llvm-commits
llvm-commits at lists.llvm.org
Wed Jun 30 10:45:24 PDT 2021
Author: Sanjay Patel
Date: 2021-06-30T13:37:31-04:00
New Revision: c7b658aeb526c3e68b0cea89f0746f45b5366827
URL: https://github.com/llvm/llvm-project/commit/c7b658aeb526c3e68b0cea89f0746f45b5366827
DIFF: https://github.com/llvm/llvm-project/commit/c7b658aeb526c3e68b0cea89f0746f45b5366827.diff
LOG: [InstCombine] fold icmp of offset value with constant
There must be a better way to describe this pattern in words?
(X + C2) >u C --> X <s -C2 (if C == C2 + SMAX)
This could be extended to handle the more general (non-constant)
pattern too:
https://alive2.llvm.org/ce/z/rdfNFP
define i1 @src(i8 %a, i8 %c1) {
%t = add i8 %a, %c1
%c2 = add i8 %c1, 127 ; SMAX
%ov = icmp ugt i8 %t, %c2
ret i1 %ov
}
define i1 @tgt(i8 %a, i8 %c1) {
%neg_c1 = sub i8 0, %c1
%ov = icmp slt i8 %a, %neg_c1
ret i1 %ov
}
The pattern was noticed as a by-product of D104932.
Added:
Modified:
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
llvm/test/Transforms/InstCombine/icmp-add.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index e5a1b8eaf24f..f2be0bef999e 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -2638,6 +2638,13 @@ Instruction *InstCombinerImpl::foldICmpAddConstant(ICmpInst &Cmp,
Type *Ty = Add->getType();
CmpInst::Predicate Pred = Cmp.getPredicate();
+ // Fold an unsigned compare with offset to signed compare:
+ // (X + C2) >u C --> X <s -C2 (if C == C2 + SMAX)
+ // TODO: Find the ULT and signed predicate siblings.
+ if (Pred == CmpInst::ICMP_UGT &&
+ C == *C2 + APInt::getSignedMaxValue(Ty->getScalarSizeInBits()))
+ return new ICmpInst(ICmpInst::ICMP_SLT, X, ConstantInt::get(Ty, -(*C2)));
+
// If the add does not wrap, we can always adjust the compare by subtracting
// the constants. Equality comparisons are handled elsewhere. SGE/SLE/UGE/ULE
// are canonicalized to SGT/SLT/UGT/ULT.
diff --git a/llvm/test/Transforms/InstCombine/icmp-add.ll b/llvm/test/Transforms/InstCombine/icmp-add.ll
index e6cd8e74d7a9..d611a80027cf 100644
--- a/llvm/test/Transforms/InstCombine/icmp-add.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-add.ll
@@ -750,8 +750,7 @@ define i1 @with_nuw_large_negative(i8 %x, i8 %y) {
define i1 @ugt_offset(i8 %a) {
; CHECK-LABEL: @ugt_offset(
-; CHECK-NEXT: [[T:%.*]] = add i8 [[A:%.*]], 124
-; CHECK-NEXT: [[OV:%.*]] = icmp ugt i8 [[T]], -5
+; CHECK-NEXT: [[OV:%.*]] = icmp slt i8 [[A:%.*]], -124
; CHECK-NEXT: ret i1 [[OV]]
;
%t = add i8 %a, 124
@@ -763,7 +762,7 @@ define i1 @ugt_offset_use(i32 %a) {
; CHECK-LABEL: @ugt_offset_use(
; CHECK-NEXT: [[T:%.*]] = add i32 [[A:%.*]], 42
; CHECK-NEXT: call void @use(i32 [[T]])
-; CHECK-NEXT: [[OV:%.*]] = icmp ugt i32 [[T]], -2147483607
+; CHECK-NEXT: [[OV:%.*]] = icmp slt i32 [[A]], -42
; CHECK-NEXT: ret i1 [[OV]]
;
%t = add i32 %a, 42
@@ -774,8 +773,7 @@ define i1 @ugt_offset_use(i32 %a) {
define <2 x i1> @ugt_offset_splat(<2 x i5> %a) {
; CHECK-LABEL: @ugt_offset_splat(
-; CHECK-NEXT: [[T:%.*]] = add <2 x i5> [[A:%.*]], <i5 9, i5 9>
-; CHECK-NEXT: [[OV:%.*]] = icmp ugt <2 x i5> [[T]], <i5 -8, i5 -8>
+; CHECK-NEXT: [[OV:%.*]] = icmp slt <2 x i5> [[A:%.*]], <i5 -9, i5 -9>
; CHECK-NEXT: ret <2 x i1> [[OV]]
;
%t = add <2 x i5> %a, <i5 9, i5 9>
@@ -783,6 +781,8 @@ define <2 x i1> @ugt_offset_splat(<2 x i5> %a) {
ret <2 x i1> %ov
}
+; negative test - constants must
diff er by SMAX
+
define i1 @ugt_wrong_offset(i8 %a) {
; CHECK-LABEL: @ugt_wrong_offset(
; CHECK-NEXT: [[T:%.*]] = add i8 [[A:%.*]], 123
More information about the llvm-commits
mailing list