Skip to content

Commit c7b658a

Browse files
committed
[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.
1 parent 36bd25d commit c7b658a

File tree

2 files changed

+12
-5
lines changed

2 files changed

+12
-5
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2638,6 +2638,13 @@ Instruction *InstCombinerImpl::foldICmpAddConstant(ICmpInst &Cmp,
26382638
Type *Ty = Add->getType();
26392639
CmpInst::Predicate Pred = Cmp.getPredicate();
26402640

2641+
// Fold an unsigned compare with offset to signed compare:
2642+
// (X + C2) >u C --> X <s -C2 (if C == C2 + SMAX)
2643+
// TODO: Find the ULT and signed predicate siblings.
2644+
if (Pred == CmpInst::ICMP_UGT &&
2645+
C == *C2 + APInt::getSignedMaxValue(Ty->getScalarSizeInBits()))
2646+
return new ICmpInst(ICmpInst::ICMP_SLT, X, ConstantInt::get(Ty, -(*C2)));
2647+
26412648
// If the add does not wrap, we can always adjust the compare by subtracting
26422649
// the constants. Equality comparisons are handled elsewhere. SGE/SLE/UGE/ULE
26432650
// are canonicalized to SGT/SLT/UGT/ULT.

llvm/test/Transforms/InstCombine/icmp-add.ll

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -750,8 +750,7 @@ define i1 @with_nuw_large_negative(i8 %x, i8 %y) {
750750

751751
define i1 @ugt_offset(i8 %a) {
752752
; CHECK-LABEL: @ugt_offset(
753-
; CHECK-NEXT: [[T:%.*]] = add i8 [[A:%.*]], 124
754-
; CHECK-NEXT: [[OV:%.*]] = icmp ugt i8 [[T]], -5
753+
; CHECK-NEXT: [[OV:%.*]] = icmp slt i8 [[A:%.*]], -124
755754
; CHECK-NEXT: ret i1 [[OV]]
756755
;
757756
%t = add i8 %a, 124
@@ -763,7 +762,7 @@ define i1 @ugt_offset_use(i32 %a) {
763762
; CHECK-LABEL: @ugt_offset_use(
764763
; CHECK-NEXT: [[T:%.*]] = add i32 [[A:%.*]], 42
765764
; CHECK-NEXT: call void @use(i32 [[T]])
766-
; CHECK-NEXT: [[OV:%.*]] = icmp ugt i32 [[T]], -2147483607
765+
; CHECK-NEXT: [[OV:%.*]] = icmp slt i32 [[A]], -42
767766
; CHECK-NEXT: ret i1 [[OV]]
768767
;
769768
%t = add i32 %a, 42
@@ -774,15 +773,16 @@ define i1 @ugt_offset_use(i32 %a) {
774773

775774
define <2 x i1> @ugt_offset_splat(<2 x i5> %a) {
776775
; CHECK-LABEL: @ugt_offset_splat(
777-
; CHECK-NEXT: [[T:%.*]] = add <2 x i5> [[A:%.*]], <i5 9, i5 9>
778-
; CHECK-NEXT: [[OV:%.*]] = icmp ugt <2 x i5> [[T]], <i5 -8, i5 -8>
776+
; CHECK-NEXT: [[OV:%.*]] = icmp slt <2 x i5> [[A:%.*]], <i5 -9, i5 -9>
779777
; CHECK-NEXT: ret <2 x i1> [[OV]]
780778
;
781779
%t = add <2 x i5> %a, <i5 9, i5 9>
782780
%ov = icmp ugt <2 x i5> %t, <i5 24, i5 24>
783781
ret <2 x i1> %ov
784782
}
785783

784+
; negative test - constants must differ by SMAX
785+
786786
define i1 @ugt_wrong_offset(i8 %a) {
787787
; CHECK-LABEL: @ugt_wrong_offset(
788788
; CHECK-NEXT: [[T:%.*]] = add i8 [[A:%.*]], 123

0 commit comments

Comments
 (0)