Skip to content

Commit 76d614b

Browse files
authored
[InstSimplify] Extend icmp-of-add simplification to sle/sgt/sge (#168900)
When comparing additions with the same base where one has `nsw`, the following simplification can be performed: ```llvm icmp slt/sgt/sle/sge (x + C1), (x +nsw C2) => icmp slt/sgt/sle/sge C1, C2 ``` Previously this was only done for `slt`. This patch extends it to the `sgt`, `sle`, and `sge` predicates when either of the conditions hold: - `C1 <= C2 && C1 >= 0`, or - `C2 <= C1 && C1 <= 0` This patch also handles the `C1 == C2` case, which was previously excluded. Proof: https://alive2.llvm.org/ce/z/LtmY4f
1 parent 04acac2 commit 76d614b

File tree

2 files changed

+110
-20
lines changed

2 files changed

+110
-20
lines changed

llvm/lib/Analysis/InstructionSimplify.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3261,20 +3261,20 @@ static Value *simplifyICmpWithBinOpOnLHS(CmpPredicate Pred, BinaryOperator *LBO,
32613261

32623262
// If only one of the icmp's operands has NSW flags, try to prove that:
32633263
//
3264-
// icmp slt (x + C1), (x +nsw C2)
3264+
// icmp slt/sgt/sle/sge (x + C1), (x +nsw C2)
32653265
//
32663266
// is equivalent to:
32673267
//
3268-
// icmp slt C1, C2
3268+
// icmp slt/sgt/sle/sge C1, C2
32693269
//
32703270
// which is true if x + C2 has the NSW flags set and:
3271-
// *) C1 < C2 && C1 >= 0, or
3272-
// *) C2 < C1 && C1 <= 0.
3271+
// *) C1 <= C2 && C1 >= 0, or
3272+
// *) C2 <= C1 && C1 <= 0.
32733273
//
32743274
static bool trySimplifyICmpWithAdds(CmpPredicate Pred, Value *LHS, Value *RHS,
32753275
const InstrInfoQuery &IIQ) {
3276-
// TODO: only support icmp slt for now.
3277-
if (Pred != CmpInst::ICMP_SLT || !IIQ.UseInstrInfo)
3276+
// TODO: support other predicates.
3277+
if (!ICmpInst::isSigned(Pred) || !IIQ.UseInstrInfo)
32783278
return false;
32793279

32803280
// Canonicalize nsw add as RHS.
@@ -3289,8 +3289,8 @@ static bool trySimplifyICmpWithAdds(CmpPredicate Pred, Value *LHS, Value *RHS,
32893289
!match(RHS, m_Add(m_Specific(X), m_APInt(C2))))
32903290
return false;
32913291

3292-
return (C1->slt(*C2) && C1->isNonNegative()) ||
3293-
(C2->slt(*C1) && C1->isNonPositive());
3292+
return (C1->sle(*C2) && C1->isNonNegative()) ||
3293+
(C2->sle(*C1) && C1->isNonPositive());
32943294
}
32953295

32963296
/// TODO: A large part of this logic is duplicated in InstCombine's

llvm/test/Transforms/InstSimplify/compare.ll

Lines changed: 102 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2687,10 +2687,7 @@ define i1 @icmp_nsw_false_2(i32 %V) {
26872687

26882688
define i1 @icmp_nsw_false_3(i32 %V) {
26892689
; CHECK-LABEL: @icmp_nsw_false_3(
2690-
; CHECK-NEXT: [[ADD5:%.*]] = add nsw i32 [[V:%.*]], 5
2691-
; CHECK-NEXT: [[ADD6:%.*]] = add i32 [[V]], 5
2692-
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[ADD5]], [[ADD6]]
2693-
; CHECK-NEXT: ret i1 [[CMP]]
2690+
; CHECK-NEXT: ret i1 false
26942691
;
26952692
%add5 = add nsw i32 %V, 5
26962693
%add6 = add i32 %V, 5
@@ -2724,6 +2721,45 @@ define i1 @icmp_nsw_false_5(i8 %V) {
27242721
ret i1 %cmp
27252722
}
27262723

2724+
define i1 @icmp_nsw_false_6(i8 %V) {
2725+
; CHECK-LABEL: @icmp_nsw_false_6(
2726+
; CHECK-NEXT: [[ADD:%.*]] = add i8 [[V:%.*]], 6
2727+
; CHECK-NEXT: [[ADDNSW:%.*]] = add nsw i8 [[V]], -1
2728+
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[ADD]], [[ADDNSW]]
2729+
; CHECK-NEXT: ret i1 [[CMP]]
2730+
;
2731+
%add = add i8 %V, 6
2732+
%addnsw = add nsw i8 %V, -1
2733+
%cmp = icmp sgt i8 %add, %addnsw
2734+
ret i1 %cmp
2735+
}
2736+
2737+
define i1 @icmp_nsw_false_7(i8 %V) {
2738+
; CHECK-LABEL: @icmp_nsw_false_7(
2739+
; CHECK-NEXT: [[ADD:%.*]] = add i8 [[V:%.*]], -1
2740+
; CHECK-NEXT: [[ADDNSW:%.*]] = add nsw i8 [[V]], 3
2741+
; CHECK-NEXT: [[CMP:%.*]] = icmp sle i8 [[ADD]], [[ADDNSW]]
2742+
; CHECK-NEXT: ret i1 [[CMP]]
2743+
;
2744+
%add = add i8 %V, -1
2745+
%addnsw = add nsw i8 %V, 3
2746+
%cmp = icmp sle i8 %add, %addnsw
2747+
ret i1 %cmp
2748+
}
2749+
2750+
define i1 @icmp_nsw_false_8(i8 %V) {
2751+
; CHECK-LABEL: @icmp_nsw_false_8(
2752+
; CHECK-NEXT: [[ADD:%.*]] = add i8 [[V:%.*]], -15
2753+
; CHECK-NEXT: [[ADDNSW:%.*]] = add nsw i8 [[V]], 42
2754+
; CHECK-NEXT: [[CMP:%.*]] = icmp sge i8 [[ADD]], [[ADDNSW]]
2755+
; CHECK-NEXT: ret i1 [[CMP]]
2756+
;
2757+
%add = add i8 %V, -15
2758+
%addnsw = add nsw i8 %V, 42
2759+
%cmp = icmp sge i8 %add, %addnsw
2760+
ret i1 %cmp
2761+
}
2762+
27272763
define i1 @icmp_nsw_i8(i8 %V) {
27282764
; CHECK-LABEL: @icmp_nsw_i8(
27292765
; CHECK-NEXT: ret i1 true
@@ -2766,10 +2802,7 @@ define <4 x i1> @icmp_nsw_vec(<4 x i32> %V) {
27662802

27672803
define i1 @icmp_nsw_3(i32 %V) {
27682804
; CHECK-LABEL: @icmp_nsw_3(
2769-
; CHECK-NEXT: [[ADD5:%.*]] = add i32 [[V:%.*]], 5
2770-
; CHECK-NEXT: [[ADD5_2:%.*]] = add nsw i32 [[V]], 5
2771-
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[ADD5]], [[ADD5_2]]
2772-
; CHECK-NEXT: ret i1 [[CMP]]
2805+
; CHECK-NEXT: ret i1 false
27732806
;
27742807
%add5 = add i32 %V, 5
27752808
%add5_2 = add nsw i32 %V, 5
@@ -2844,10 +2877,7 @@ define i1 @icmp_nsw_9(i32 %V1, i32 %V2) {
28442877

28452878
define i1 @icmp_nsw_10(i32 %V) {
28462879
; CHECK-LABEL: @icmp_nsw_10(
2847-
; CHECK-NEXT: [[ADD5:%.*]] = add i32 [[V:%.*]], 5
2848-
; CHECK-NEXT: [[ADD6:%.*]] = add nsw i32 [[V]], 6
2849-
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[ADD6]], [[ADD5]]
2850-
; CHECK-NEXT: ret i1 [[CMP]]
2880+
; CHECK-NEXT: ret i1 true
28512881
;
28522882
%add5 = add i32 %V, 5
28532883
%add6 = add nsw i32 %V, 6
@@ -2868,6 +2898,36 @@ define i1 @icmp_nsw_11(i32 %V) {
28682898
ret i1 %cmp
28692899
}
28702900

2901+
define i1 @icmp_nsw_12(i32 %V) {
2902+
; CHECK-LABEL: @icmp_nsw_12(
2903+
; CHECK-NEXT: ret i1 true
2904+
;
2905+
%add5 = add i32 %V, 2
2906+
%add6 = add nsw i32 %V, 3
2907+
%cmp = icmp slt i32 %add5, %add6
2908+
ret i1 %cmp
2909+
}
2910+
2911+
define i1 @icmp_nsw_13(i32 %V) {
2912+
; CHECK-LABEL: @icmp_nsw_13(
2913+
; CHECK-NEXT: ret i1 true
2914+
;
2915+
%add5 = add i32 %V, 7
2916+
%add6 = add nsw i32 %V, 10
2917+
%cmp = icmp sle i32 %add5, %add6
2918+
ret i1 %cmp
2919+
}
2920+
2921+
define i1 @icmp_nsw_14(i32 %V) {
2922+
; CHECK-LABEL: @icmp_nsw_14(
2923+
; CHECK-NEXT: ret i1 false
2924+
;
2925+
%add5 = add i32 %V, 7
2926+
%add6 = add nsw i32 %V, 10
2927+
%cmp = icmp sge i32 %add5, %add6
2928+
ret i1 %cmp
2929+
}
2930+
28712931
define i1 @icmp_nsw_nonpos(i32 %V) {
28722932
; CHECK-LABEL: @icmp_nsw_nonpos(
28732933
; CHECK-NEXT: ret i1 false
@@ -2890,6 +2950,36 @@ define i1 @icmp_nsw_nonpos2(i32 %V) {
28902950
ret i1 %cmp
28912951
}
28922952

2953+
define i1 @icmp_nsw_nonpos3(i32 %V) {
2954+
; CHECK-LABEL: @icmp_nsw_nonpos3(
2955+
; CHECK-NEXT: ret i1 false
2956+
;
2957+
%add5 = add i32 %V, -2
2958+
%add6 = add nsw i32 %V, -5
2959+
%cmp = icmp sle i32 %add5, %add6
2960+
ret i1 %cmp
2961+
}
2962+
2963+
define i1 @icmp_nsw_nonpos4(i32 %V) {
2964+
; CHECK-LABEL: @icmp_nsw_nonpos4(
2965+
; CHECK-NEXT: ret i1 true
2966+
;
2967+
%add5 = add i32 %V, -10
2968+
%add6 = add nsw i32 %V, -30
2969+
%cmp = icmp sgt i32 %add5, %add6
2970+
ret i1 %cmp
2971+
}
2972+
2973+
define i1 @icmp_nsw_nonpos5(i32 %V) {
2974+
; CHECK-LABEL: @icmp_nsw_nonpos5(
2975+
; CHECK-NEXT: ret i1 true
2976+
;
2977+
%add5 = add i32 %V, -15
2978+
%add6 = add nsw i32 %V, -100
2979+
%cmp = icmp sge i32 %add5, %add6
2980+
ret i1 %cmp
2981+
}
2982+
28932983
declare i11 @llvm.ctpop.i11(i11)
28942984
declare i73 @llvm.ctpop.i73(i73)
28952985
declare <2 x i13> @llvm.ctpop.v2i13(<2 x i13>)

0 commit comments

Comments
 (0)