Skip to content

Commit 40b752d

Browse files
committed
[InstCombine] fold icmp slt/sgt of offset value with constant
This follows up patches for the unsigned siblings: 0c400e8 c7b658a We are translating an offset signed compare to its unsigned equivalent when one end of the range is at the limit (zero or unsigned max). (X + C2) >s C --> X <u (SMAX - C) (if C == C2 - 1) (X + C2) <s C --> X >u (C ^ SMAX) (if C == C2) This probably does not show up much in IR derived from C/C++ source because that would likely have 'nsw', and we have folds for that already. As with the previous unsigned transforms, the folds could be generalized to handle non-constant patterns: https://alive2.llvm.org/ce/z/Y8Xrrm ; sgt define i1 @src(i8 %a, i8 %c) { %c2 = add i8 %c, 1 %t = add i8 %a, %c2 %ov = icmp sgt i8 %t, %c ret i1 %ov } define i1 @tgt(i8 %a, i8 %c) { %c_off = sub i8 127, %c ; SMAX %ov = icmp ult i8 %a, %c_off ret i1 %ov } https://alive2.llvm.org/ce/z/c8uhnk ; slt define i1 @src(i8 %a, i8 %c) { %t = add i8 %a, %c %ov = icmp slt i8 %t, %c ret i1 %ov } define i1 @tgt(i8 %a, i8 %c) { %c_offnot = xor i8 %c, 127 ; SMAX %ov = icmp ugt i8 %a, %c_offnot ret i1 %ov }
1 parent 32dd914 commit 40b752d

File tree

2 files changed

+24
-17
lines changed

2 files changed

+24
-17
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2636,20 +2636,27 @@ Instruction *InstCombinerImpl::foldICmpAddConstant(ICmpInst &Cmp,
26362636
// Fold icmp pred (add X, C2), C.
26372637
Value *X = Add->getOperand(0);
26382638
Type *Ty = Add->getType();
2639-
CmpInst::Predicate Pred = Cmp.getPredicate();
2639+
const CmpInst::Predicate Pred = Cmp.getPredicate();
2640+
const APInt SMax = APInt::getSignedMaxValue(Ty->getScalarSizeInBits());
2641+
const APInt SMin = APInt::getSignedMinValue(Ty->getScalarSizeInBits());
26402642

2641-
// Fold an unsigned compare with offset to signed compare:
2643+
// Fold compare with offset to opposite sign compare if it eliminates offset:
26422644
// (X + C2) >u C --> X <s -C2 (if C == C2 + SMAX)
2643-
// TODO: Find the signed predicate siblings.
2644-
if (Pred == CmpInst::ICMP_UGT &&
2645-
C == *C2 + APInt::getSignedMaxValue(Ty->getScalarSizeInBits()))
2645+
if (Pred == CmpInst::ICMP_UGT && C == *C2 + SMax)
26462646
return new ICmpInst(ICmpInst::ICMP_SLT, X, ConstantInt::get(Ty, -(*C2)));
26472647

26482648
// (X + C2) <u C --> X >s ~C2 (if C == C2 + SMIN)
2649-
if (Pred == CmpInst::ICMP_ULT &&
2650-
C == *C2 + APInt::getSignedMinValue(Ty->getScalarSizeInBits()))
2649+
if (Pred == CmpInst::ICMP_ULT && C == *C2 + SMin)
26512650
return new ICmpInst(ICmpInst::ICMP_SGT, X, ConstantInt::get(Ty, ~(*C2)));
26522651

2652+
// (X + C2) >s C --> X <u (SMAX - C) (if C == C2 - 1)
2653+
if (Pred == CmpInst::ICMP_SGT && C == *C2 - 1)
2654+
return new ICmpInst(ICmpInst::ICMP_ULT, X, ConstantInt::get(Ty, SMax - C));
2655+
2656+
// (X + C2) <s C --> X >u (C ^ SMAX) (if C == C2)
2657+
if (Pred == CmpInst::ICMP_SLT && C == *C2)
2658+
return new ICmpInst(ICmpInst::ICMP_UGT, X, ConstantInt::get(Ty, C ^ SMax));
2659+
26532660
// If the add does not wrap, we can always adjust the compare by subtracting
26542661
// the constants. Equality comparisons are handled elsewhere. SGE/SLE/UGE/ULE
26552662
// are canonicalized to SGT/SLT/UGT/ULT.

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

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -842,8 +842,7 @@ define i1 @ult_wrong_offset(i8 %a) {
842842

843843
define i1 @sgt_offset(i8 %a) {
844844
; CHECK-LABEL: @sgt_offset(
845-
; CHECK-NEXT: [[T:%.*]] = add i8 [[A:%.*]], -6
846-
; CHECK-NEXT: [[OV:%.*]] = icmp sgt i8 [[T]], -7
845+
; CHECK-NEXT: [[OV:%.*]] = icmp ult i8 [[A:%.*]], -122
847846
; CHECK-NEXT: ret i1 [[OV]]
848847
;
849848
%t = add i8 %a, -6
@@ -855,7 +854,7 @@ define i1 @sgt_offset_use(i32 %a) {
855854
; CHECK-LABEL: @sgt_offset_use(
856855
; CHECK-NEXT: [[T:%.*]] = add i32 [[A:%.*]], 42
857856
; CHECK-NEXT: call void @use(i32 [[T]])
858-
; CHECK-NEXT: [[OV:%.*]] = icmp sgt i32 [[T]], 41
857+
; CHECK-NEXT: [[OV:%.*]] = icmp ult i32 [[A]], 2147483606
859858
; CHECK-NEXT: ret i1 [[OV]]
860859
;
861860
%t = add i32 %a, 42
@@ -866,15 +865,16 @@ define i1 @sgt_offset_use(i32 %a) {
866865

867866
define <2 x i1> @sgt_offset_splat(<2 x i5> %a) {
868867
; CHECK-LABEL: @sgt_offset_splat(
869-
; CHECK-NEXT: [[T:%.*]] = add <2 x i5> [[A:%.*]], <i5 9, i5 9>
870-
; CHECK-NEXT: [[OV:%.*]] = icmp sgt <2 x i5> [[T]], <i5 8, i5 8>
868+
; CHECK-NEXT: [[OV:%.*]] = icmp ult <2 x i5> [[A:%.*]], <i5 7, i5 7>
871869
; CHECK-NEXT: ret <2 x i1> [[OV]]
872870
;
873871
%t = add <2 x i5> %a, <i5 9, i5 9>
874872
%ov = icmp sgt <2 x i5> %t, <i5 8, i5 8>
875873
ret <2 x i1> %ov
876874
}
877875

876+
; negative test - constants must differ by 1
877+
878878
define i1 @sgt_wrong_offset(i8 %a) {
879879
; CHECK-LABEL: @sgt_wrong_offset(
880880
; CHECK-NEXT: [[T:%.*]] = add i8 [[A:%.*]], -7
@@ -888,8 +888,7 @@ define i1 @sgt_wrong_offset(i8 %a) {
888888

889889
define i1 @slt_offset(i8 %a) {
890890
; CHECK-LABEL: @slt_offset(
891-
; CHECK-NEXT: [[T:%.*]] = add i8 [[A:%.*]], -6
892-
; CHECK-NEXT: [[OV:%.*]] = icmp slt i8 [[T]], -6
891+
; CHECK-NEXT: [[OV:%.*]] = icmp ugt i8 [[A:%.*]], -123
893892
; CHECK-NEXT: ret i1 [[OV]]
894893
;
895894
%t = add i8 %a, -6
@@ -901,7 +900,7 @@ define i1 @slt_offset_use(i32 %a) {
901900
; CHECK-LABEL: @slt_offset_use(
902901
; CHECK-NEXT: [[T:%.*]] = add i32 [[A:%.*]], 42
903902
; CHECK-NEXT: call void @use(i32 [[T]])
904-
; CHECK-NEXT: [[OV:%.*]] = icmp slt i32 [[T]], 42
903+
; CHECK-NEXT: [[OV:%.*]] = icmp ugt i32 [[A]], 2147483605
905904
; CHECK-NEXT: ret i1 [[OV]]
906905
;
907906
%t = add i32 %a, 42
@@ -912,15 +911,16 @@ define i1 @slt_offset_use(i32 %a) {
912911

913912
define <2 x i1> @slt_offset_splat(<2 x i5> %a) {
914913
; CHECK-LABEL: @slt_offset_splat(
915-
; CHECK-NEXT: [[T:%.*]] = add <2 x i5> [[A:%.*]], <i5 9, i5 9>
916-
; CHECK-NEXT: [[OV:%.*]] = icmp slt <2 x i5> [[T]], <i5 9, i5 9>
914+
; CHECK-NEXT: [[OV:%.*]] = icmp ugt <2 x i5> [[A:%.*]], <i5 6, i5 6>
917915
; CHECK-NEXT: ret <2 x i1> [[OV]]
918916
;
919917
%t = add <2 x i5> %a, <i5 9, i5 9>
920918
%ov = icmp slt <2 x i5> %t, <i5 9, i5 9>
921919
ret <2 x i1> %ov
922920
}
923921

922+
; negative test - constants must be equal
923+
924924
define i1 @slt_wrong_offset(i8 %a) {
925925
; CHECK-LABEL: @slt_wrong_offset(
926926
; CHECK-NEXT: [[T:%.*]] = add i8 [[A:%.*]], -6

0 commit comments

Comments
 (0)