Skip to content

Commit 0c400e8

Browse files
committed
[InstCombine] fold icmp ult of offset value with constant
This is one sibling of the fold added with c7b658a . (X + C2) <u C --> X >s ~C2 (if C == C2 + SMIN) I'm still not sure how to describe it best, but we're translating 2 constants from an unsigned range comparison to signed because that eliminates the offset (add) op. This could be extended to handle the more general (non-constant) pattern too: https://alive2.llvm.org/ce/z/K-fMBf define i1 @src(i8 %a, i8 %c2) { %t = add i8 %a, %c2 %c = add i8 %c2, 128 ; SMIN %ov = icmp ult i8 %t, %c ret i1 %ov } define i1 @tgt(i8 %a, i8 %c2) { %not_c2 = xor i8 %c2, -1 %ov = icmp sgt i8 %a, %not_c2 ret i1 %ov }
1 parent b2fe025 commit 0c400e8

File tree

2 files changed

+11
-6
lines changed

2 files changed

+11
-6
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2640,11 +2640,16 @@ Instruction *InstCombinerImpl::foldICmpAddConstant(ICmpInst &Cmp,
26402640

26412641
// Fold an unsigned compare with offset to signed compare:
26422642
// (X + C2) >u C --> X <s -C2 (if C == C2 + SMAX)
2643-
// TODO: Find the ULT and signed predicate siblings.
2643+
// TODO: Find the signed predicate siblings.
26442644
if (Pred == CmpInst::ICMP_UGT &&
26452645
C == *C2 + APInt::getSignedMaxValue(Ty->getScalarSizeInBits()))
26462646
return new ICmpInst(ICmpInst::ICMP_SLT, X, ConstantInt::get(Ty, -(*C2)));
26472647

2648+
// (X + C2) <u C --> X >s ~C2 (if C == C2 + SMIN)
2649+
if (Pred == CmpInst::ICMP_ULT &&
2650+
C == *C2 + APInt::getSignedMinValue(Ty->getScalarSizeInBits()))
2651+
return new ICmpInst(ICmpInst::ICMP_SGT, X, ConstantInt::get(Ty, ~(*C2)));
2652+
26482653
// If the add does not wrap, we can always adjust the compare by subtracting
26492654
// the constants. Equality comparisons are handled elsewhere. SGE/SLE/UGE/ULE
26502655
// 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
@@ -796,8 +796,7 @@ define i1 @ugt_wrong_offset(i8 %a) {
796796

797797
define i1 @ult_offset(i8 %a) {
798798
; CHECK-LABEL: @ult_offset(
799-
; CHECK-NEXT: [[T:%.*]] = add i8 [[A:%.*]], -6
800-
; CHECK-NEXT: [[OV:%.*]] = icmp ult i8 [[T]], 122
799+
; CHECK-NEXT: [[OV:%.*]] = icmp sgt i8 [[A:%.*]], 5
801800
; CHECK-NEXT: ret i1 [[OV]]
802801
;
803802
%t = add i8 %a, 250
@@ -809,7 +808,7 @@ define i1 @ult_offset_use(i32 %a) {
809808
; CHECK-LABEL: @ult_offset_use(
810809
; CHECK-NEXT: [[T:%.*]] = add i32 [[A:%.*]], 42
811810
; CHECK-NEXT: call void @use(i32 [[T]])
812-
; CHECK-NEXT: [[OV:%.*]] = icmp ult i32 [[T]], -2147483606
811+
; CHECK-NEXT: [[OV:%.*]] = icmp sgt i32 [[A]], -43
813812
; CHECK-NEXT: ret i1 [[OV]]
814813
;
815814
%t = add i32 %a, 42
@@ -820,15 +819,16 @@ define i1 @ult_offset_use(i32 %a) {
820819

821820
define <2 x i1> @ult_offset_splat(<2 x i5> %a) {
822821
; CHECK-LABEL: @ult_offset_splat(
823-
; CHECK-NEXT: [[T:%.*]] = add <2 x i5> [[A:%.*]], <i5 9, i5 9>
824-
; CHECK-NEXT: [[OV:%.*]] = icmp ult <2 x i5> [[T]], <i5 -7, i5 -7>
822+
; CHECK-NEXT: [[OV:%.*]] = icmp sgt <2 x i5> [[A:%.*]], <i5 -10, i5 -10>
825823
; CHECK-NEXT: ret <2 x i1> [[OV]]
826824
;
827825
%t = add <2 x i5> %a, <i5 9, i5 9>
828826
%ov = icmp ult <2 x i5> %t, <i5 25, i5 25>
829827
ret <2 x i1> %ov
830828
}
831829

830+
; negative test - constants must differ by SMIN
831+
832832
define i1 @ult_wrong_offset(i8 %a) {
833833
; CHECK-LABEL: @ult_wrong_offset(
834834
; CHECK-NEXT: [[T:%.*]] = add i8 [[A:%.*]], -6

0 commit comments

Comments
 (0)