From c9a2887052acf4d16f273db397ae5576565dc917 Mon Sep 17 00:00:00 2001 From: Pedro Lobo Date: Thu, 20 Nov 2025 16:01:03 +0000 Subject: [PATCH 1/3] Pre-commit tests --- llvm/test/Transforms/InstSimplify/compare.ll | 114 +++++++++++++++++++ 1 file changed, 114 insertions(+) diff --git a/llvm/test/Transforms/InstSimplify/compare.ll b/llvm/test/Transforms/InstSimplify/compare.ll index 97ac8f2ea47ea..dc05ceaab385a 100644 --- a/llvm/test/Transforms/InstSimplify/compare.ll +++ b/llvm/test/Transforms/InstSimplify/compare.ll @@ -2724,6 +2724,45 @@ define i1 @icmp_nsw_false_5(i8 %V) { ret i1 %cmp } +define i1 @icmp_nsw_false_6(i8 %V) { +; CHECK-LABEL: @icmp_nsw_false_6( +; CHECK-NEXT: [[ADD:%.*]] = add i8 [[V:%.*]], 6 +; CHECK-NEXT: [[ADDNSW:%.*]] = add nsw i8 [[V]], -1 +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[ADD]], [[ADDNSW]] +; CHECK-NEXT: ret i1 [[CMP]] +; + %add = add i8 %V, 6 + %addnsw = add nsw i8 %V, -1 + %cmp = icmp sgt i8 %add, %addnsw + ret i1 %cmp +} + +define i1 @icmp_nsw_false_7(i8 %V) { +; CHECK-LABEL: @icmp_nsw_false_7( +; CHECK-NEXT: [[ADD:%.*]] = add i8 [[V:%.*]], -1 +; CHECK-NEXT: [[ADDNSW:%.*]] = add nsw i8 [[V]], 3 +; CHECK-NEXT: [[CMP:%.*]] = icmp sle i8 [[ADD]], [[ADDNSW]] +; CHECK-NEXT: ret i1 [[CMP]] +; + %add = add i8 %V, -1 + %addnsw = add nsw i8 %V, 3 + %cmp = icmp sle i8 %add, %addnsw + ret i1 %cmp +} + +define i1 @icmp_nsw_false_8(i8 %V) { +; CHECK-LABEL: @icmp_nsw_false_8( +; CHECK-NEXT: [[ADD:%.*]] = add i8 [[V:%.*]], -15 +; CHECK-NEXT: [[ADDNSW:%.*]] = add nsw i8 [[V]], 42 +; CHECK-NEXT: [[CMP:%.*]] = icmp sge i8 [[ADD]], [[ADDNSW]] +; CHECK-NEXT: ret i1 [[CMP]] +; + %add = add i8 %V, -15 + %addnsw = add nsw i8 %V, 42 + %cmp = icmp sge i8 %add, %addnsw + ret i1 %cmp +} + define i1 @icmp_nsw_i8(i8 %V) { ; CHECK-LABEL: @icmp_nsw_i8( ; CHECK-NEXT: ret i1 true @@ -2868,6 +2907,42 @@ define i1 @icmp_nsw_11(i32 %V) { ret i1 %cmp } +define i1 @icmp_nsw_12(i32 %V) { +; CHECK-LABEL: @icmp_nsw_12( +; CHECK-NEXT: ret i1 true +; + %add5 = add i32 %V, 2 + %add6 = add nsw i32 %V, 3 + %cmp = icmp slt i32 %add5, %add6 + ret i1 %cmp +} + +define i1 @icmp_nsw_13(i32 %V) { +; CHECK-LABEL: @icmp_nsw_13( +; CHECK-NEXT: [[ADD5:%.*]] = add i32 [[V:%.*]], 7 +; CHECK-NEXT: [[ADD6:%.*]] = add nsw i32 [[V]], 10 +; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[ADD5]], [[ADD6]] +; CHECK-NEXT: ret i1 [[CMP]] +; + %add5 = add i32 %V, 7 + %add6 = add nsw i32 %V, 10 + %cmp = icmp sle i32 %add5, %add6 + ret i1 %cmp +} + +define i1 @icmp_nsw_14(i32 %V) { +; CHECK-LABEL: @icmp_nsw_14( +; CHECK-NEXT: [[ADD5:%.*]] = add i32 [[V:%.*]], 7 +; CHECK-NEXT: [[ADD6:%.*]] = add nsw i32 [[V]], 10 +; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[ADD5]], [[ADD6]] +; CHECK-NEXT: ret i1 [[CMP]] +; + %add5 = add i32 %V, 7 + %add6 = add nsw i32 %V, 10 + %cmp = icmp sge i32 %add5, %add6 + ret i1 %cmp +} + define i1 @icmp_nsw_nonpos(i32 %V) { ; CHECK-LABEL: @icmp_nsw_nonpos( ; CHECK-NEXT: ret i1 false @@ -2890,6 +2965,45 @@ define i1 @icmp_nsw_nonpos2(i32 %V) { ret i1 %cmp } +define i1 @icmp_nsw_nonpos3(i32 %V) { +; CHECK-LABEL: @icmp_nsw_nonpos3( +; CHECK-NEXT: [[ADD5:%.*]] = add i32 [[V:%.*]], -2 +; CHECK-NEXT: [[ADD6:%.*]] = add nsw i32 [[V]], -5 +; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[ADD5]], [[ADD6]] +; CHECK-NEXT: ret i1 [[CMP]] +; + %add5 = add i32 %V, -2 + %add6 = add nsw i32 %V, -5 + %cmp = icmp sle i32 %add5, %add6 + ret i1 %cmp +} + +define i1 @icmp_nsw_nonpos4(i32 %V) { +; CHECK-LABEL: @icmp_nsw_nonpos4( +; CHECK-NEXT: [[ADD5:%.*]] = add i32 [[V:%.*]], -10 +; CHECK-NEXT: [[ADD6:%.*]] = add nsw i32 [[V]], -30 +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[ADD5]], [[ADD6]] +; CHECK-NEXT: ret i1 [[CMP]] +; + %add5 = add i32 %V, -10 + %add6 = add nsw i32 %V, -30 + %cmp = icmp sgt i32 %add5, %add6 + ret i1 %cmp +} + +define i1 @icmp_nsw_nonpos5(i32 %V) { +; CHECK-LABEL: @icmp_nsw_nonpos5( +; CHECK-NEXT: [[ADD5:%.*]] = add i32 [[V:%.*]], -15 +; CHECK-NEXT: [[ADD6:%.*]] = add nsw i32 [[V]], -100 +; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[ADD5]], [[ADD6]] +; CHECK-NEXT: ret i1 [[CMP]] +; + %add5 = add i32 %V, -15 + %add6 = add nsw i32 %V, -100 + %cmp = icmp sge i32 %add5, %add6 + ret i1 %cmp +} + declare i11 @llvm.ctpop.i11(i11) declare i73 @llvm.ctpop.i73(i73) declare <2 x i13> @llvm.ctpop.v2i13(<2 x i13>) From 9fee32d25261bae3cbb7f2f87449faf8c044cae9 Mon Sep 17 00:00:00 2001 From: Pedro Lobo Date: Thu, 20 Nov 2025 16:10:03 +0000 Subject: [PATCH 2/3] [InstSimplify] Extend icmp-of-add simplification to sle/sgt/sge 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 --- llvm/lib/Analysis/InstructionSimplify.cpp | 18 +++++---- llvm/test/Transforms/InstSimplify/compare.ll | 40 ++++---------------- 2 files changed, 18 insertions(+), 40 deletions(-) diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index 8968f6b934d77..452cba23e3309 100644 --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -3261,20 +3261,22 @@ static Value *simplifyICmpWithBinOpOnLHS(CmpPredicate Pred, BinaryOperator *LBO, // If only one of the icmp's operands has NSW flags, try to prove that: // -// icmp slt (x + C1), (x +nsw C2) +// icmp slt/sgt/sle/sge (x + C1), (x +nsw C2) // // is equivalent to: // -// icmp slt C1, C2 +// icmp slt/sgt/sle/sge C1, C2 // // which is true if x + C2 has the NSW flags set and: -// *) C1 < C2 && C1 >= 0, or -// *) C2 < C1 && C1 <= 0. +// *) C1 <= C2 && C1 >= 0, or +// *) C2 <= C1 && C1 <= 0. // static bool trySimplifyICmpWithAdds(CmpPredicate Pred, Value *LHS, Value *RHS, const InstrInfoQuery &IIQ) { - // TODO: only support icmp slt for now. - if (Pred != CmpInst::ICMP_SLT || !IIQ.UseInstrInfo) + // TODO: support other predicates. + if ((Pred != CmpInst::ICMP_SLT && Pred != CmpInst::ICMP_SGT && + Pred != CmpInst::ICMP_SLE && Pred != CmpInst::ICMP_SGE) || + !IIQ.UseInstrInfo) return false; // Canonicalize nsw add as RHS. @@ -3289,8 +3291,8 @@ static bool trySimplifyICmpWithAdds(CmpPredicate Pred, Value *LHS, Value *RHS, !match(RHS, m_Add(m_Specific(X), m_APInt(C2)))) return false; - return (C1->slt(*C2) && C1->isNonNegative()) || - (C2->slt(*C1) && C1->isNonPositive()); + return (C1->sle(*C2) && C1->isNonNegative()) || + (C2->sle(*C1) && C1->isNonPositive()); } /// TODO: A large part of this logic is duplicated in InstCombine's diff --git a/llvm/test/Transforms/InstSimplify/compare.ll b/llvm/test/Transforms/InstSimplify/compare.ll index dc05ceaab385a..ba10ea532a34a 100644 --- a/llvm/test/Transforms/InstSimplify/compare.ll +++ b/llvm/test/Transforms/InstSimplify/compare.ll @@ -2687,10 +2687,7 @@ define i1 @icmp_nsw_false_2(i32 %V) { define i1 @icmp_nsw_false_3(i32 %V) { ; CHECK-LABEL: @icmp_nsw_false_3( -; CHECK-NEXT: [[ADD5:%.*]] = add nsw i32 [[V:%.*]], 5 -; CHECK-NEXT: [[ADD6:%.*]] = add i32 [[V]], 5 -; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[ADD5]], [[ADD6]] -; CHECK-NEXT: ret i1 [[CMP]] +; CHECK-NEXT: ret i1 false ; %add5 = add nsw i32 %V, 5 %add6 = add i32 %V, 5 @@ -2805,10 +2802,7 @@ define <4 x i1> @icmp_nsw_vec(<4 x i32> %V) { define i1 @icmp_nsw_3(i32 %V) { ; CHECK-LABEL: @icmp_nsw_3( -; CHECK-NEXT: [[ADD5:%.*]] = add i32 [[V:%.*]], 5 -; CHECK-NEXT: [[ADD5_2:%.*]] = add nsw i32 [[V]], 5 -; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[ADD5]], [[ADD5_2]] -; CHECK-NEXT: ret i1 [[CMP]] +; CHECK-NEXT: ret i1 false ; %add5 = add i32 %V, 5 %add5_2 = add nsw i32 %V, 5 @@ -2883,10 +2877,7 @@ define i1 @icmp_nsw_9(i32 %V1, i32 %V2) { define i1 @icmp_nsw_10(i32 %V) { ; CHECK-LABEL: @icmp_nsw_10( -; CHECK-NEXT: [[ADD5:%.*]] = add i32 [[V:%.*]], 5 -; CHECK-NEXT: [[ADD6:%.*]] = add nsw i32 [[V]], 6 -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[ADD6]], [[ADD5]] -; CHECK-NEXT: ret i1 [[CMP]] +; CHECK-NEXT: ret i1 true ; %add5 = add i32 %V, 5 %add6 = add nsw i32 %V, 6 @@ -2919,10 +2910,7 @@ define i1 @icmp_nsw_12(i32 %V) { define i1 @icmp_nsw_13(i32 %V) { ; CHECK-LABEL: @icmp_nsw_13( -; CHECK-NEXT: [[ADD5:%.*]] = add i32 [[V:%.*]], 7 -; CHECK-NEXT: [[ADD6:%.*]] = add nsw i32 [[V]], 10 -; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[ADD5]], [[ADD6]] -; CHECK-NEXT: ret i1 [[CMP]] +; CHECK-NEXT: ret i1 true ; %add5 = add i32 %V, 7 %add6 = add nsw i32 %V, 10 @@ -2932,10 +2920,7 @@ define i1 @icmp_nsw_13(i32 %V) { define i1 @icmp_nsw_14(i32 %V) { ; CHECK-LABEL: @icmp_nsw_14( -; CHECK-NEXT: [[ADD5:%.*]] = add i32 [[V:%.*]], 7 -; CHECK-NEXT: [[ADD6:%.*]] = add nsw i32 [[V]], 10 -; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[ADD5]], [[ADD6]] -; CHECK-NEXT: ret i1 [[CMP]] +; CHECK-NEXT: ret i1 false ; %add5 = add i32 %V, 7 %add6 = add nsw i32 %V, 10 @@ -2967,10 +2952,7 @@ define i1 @icmp_nsw_nonpos2(i32 %V) { define i1 @icmp_nsw_nonpos3(i32 %V) { ; CHECK-LABEL: @icmp_nsw_nonpos3( -; CHECK-NEXT: [[ADD5:%.*]] = add i32 [[V:%.*]], -2 -; CHECK-NEXT: [[ADD6:%.*]] = add nsw i32 [[V]], -5 -; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[ADD5]], [[ADD6]] -; CHECK-NEXT: ret i1 [[CMP]] +; CHECK-NEXT: ret i1 false ; %add5 = add i32 %V, -2 %add6 = add nsw i32 %V, -5 @@ -2980,10 +2962,7 @@ define i1 @icmp_nsw_nonpos3(i32 %V) { define i1 @icmp_nsw_nonpos4(i32 %V) { ; CHECK-LABEL: @icmp_nsw_nonpos4( -; CHECK-NEXT: [[ADD5:%.*]] = add i32 [[V:%.*]], -10 -; CHECK-NEXT: [[ADD6:%.*]] = add nsw i32 [[V]], -30 -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[ADD5]], [[ADD6]] -; CHECK-NEXT: ret i1 [[CMP]] +; CHECK-NEXT: ret i1 true ; %add5 = add i32 %V, -10 %add6 = add nsw i32 %V, -30 @@ -2993,10 +2972,7 @@ define i1 @icmp_nsw_nonpos4(i32 %V) { define i1 @icmp_nsw_nonpos5(i32 %V) { ; CHECK-LABEL: @icmp_nsw_nonpos5( -; CHECK-NEXT: [[ADD5:%.*]] = add i32 [[V:%.*]], -15 -; CHECK-NEXT: [[ADD6:%.*]] = add nsw i32 [[V]], -100 -; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[ADD5]], [[ADD6]] -; CHECK-NEXT: ret i1 [[CMP]] +; CHECK-NEXT: ret i1 true ; %add5 = add i32 %V, -15 %add6 = add nsw i32 %V, -100 From 4bf9e8abc92910b13991a0e3a204ba843770cebd Mon Sep 17 00:00:00 2001 From: Pedro Lobo Date: Thu, 20 Nov 2025 18:05:13 +0000 Subject: [PATCH 3/3] Use `!ICmpInst::isSigned` --- llvm/lib/Analysis/InstructionSimplify.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index 452cba23e3309..59a213b47825a 100644 --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -3274,9 +3274,7 @@ static Value *simplifyICmpWithBinOpOnLHS(CmpPredicate Pred, BinaryOperator *LBO, static bool trySimplifyICmpWithAdds(CmpPredicate Pred, Value *LHS, Value *RHS, const InstrInfoQuery &IIQ) { // TODO: support other predicates. - if ((Pred != CmpInst::ICMP_SLT && Pred != CmpInst::ICMP_SGT && - Pred != CmpInst::ICMP_SLE && Pred != CmpInst::ICMP_SGE) || - !IIQ.UseInstrInfo) + if (!ICmpInst::isSigned(Pred) || !IIQ.UseInstrInfo) return false; // Canonicalize nsw add as RHS.