From 29ab236799f4fab8b4e57822de874a3d42beeed1 Mon Sep 17 00:00:00 2001 From: wermos <63574588+wermos@users.noreply.github.com> Date: Sat, 29 Nov 2025 01:55:58 +0530 Subject: [PATCH 1/2] Pre-commit tests --- llvm/test/Transforms/InstCombine/icmp-add.ll | 64 ++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/llvm/test/Transforms/InstCombine/icmp-add.ll b/llvm/test/Transforms/InstCombine/icmp-add.ll index 8449c7c5ea935..a9f7d36602dfb 100644 --- a/llvm/test/Transforms/InstCombine/icmp-add.ll +++ b/llvm/test/Transforms/InstCombine/icmp-add.ll @@ -3440,3 +3440,67 @@ define i1 @val_is_aligend_pred_mismatch(i32 %num) { %_0 = icmp sge i32 %num.masked, %num ret i1 %_0 } + +define i1 @icmp_samesign_with_nsw_add(i32 %arg0) { +; CHECK-LABEL: @icmp_samesign_with_nsw_add( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[ARG0:%.*]], -26 +; CHECK-NEXT: [[V1:%.*]] = icmp ult i32 [[TMP0]], -8 +; CHECK-NEXT: ret i1 [[V1]] +; +entry: + %v0 = add nsw i32 %arg0, -18 + %v1 = icmp samesign ugt i32 %v0, 7 + ret i1 %v1 +} + +; Shouldn't fire since -124 - 12 causes signed overflow +define i1 @icmp_samesign_with_nsw_add_no_fire(i8 %arg0) { +; CHECK-LABEL: @icmp_samesign_with_nsw_add_no_fire( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = add i8 [[ARG0:%.*]], -121 +; CHECK-NEXT: [[V1:%.*]] = icmp ult i8 [[TMP0]], 123 +; CHECK-NEXT: ret i1 [[V1]] +; +entry: + %v0 = add nsw i8 %arg0, 12 + %v1 = icmp samesign ugt i8 %v0, -124 + ret i1 %v1 +} + +define i1 @icmp_with_nuw_add(i32 %arg0) { +; CHECK-LABEL: @icmp_with_nuw_add( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[V1:%.*]] = icmp ugt i32 [[ARG0:%.*]], 11 +; CHECK-NEXT: ret i1 [[V1]] +; +entry: + %v0 = add nuw i32 %arg0, 7 + %v1 = icmp ugt i32 %v0, 18 + ret i1 %v1 +} + +define i1 @icmp_partial_negative_samesign_ult_to_slt(i8 range(i8 -1, 5) %x) { +; CHECK-LABEL: @icmp_partial_negative_samesign_ult_to_slt( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[ADD:%.*]] = add nsw i8 [[X:%.*]], -5 +; CHECK-NEXT: [[CMP:%.*]] = icmp samesign ult i8 [[ADD]], -3 +; CHECK-NEXT: ret i1 [[CMP]] +; +entry: + %add = add nsw i8 %x, -5 + %cmp = icmp samesign ult i8 %add, -3 + ret i1 %cmp +} + +define i1 @icmp_pos_samesign_slt_to_ult(i8 range(i8 1, 5) %x) { +; CHECK-LABEL: @icmp_pos_samesign_slt_to_ult( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP:%.*]] = icmp samesign ult i8 [[X:%.*]], 2 +; CHECK-NEXT: ret i1 [[CMP]] +; +entry: + %add = add nsw i8 %x, 1 + %cmp = icmp samesign slt i8 %add, 3 + ret i1 %cmp +} From 445fdd566f47f9889afc99cb1b9a5deea994caba Mon Sep 17 00:00:00 2001 From: wermos <63574588+wermos@users.noreply.github.com> Date: Sat, 29 Nov 2025 02:02:43 +0530 Subject: [PATCH 2/2] Fold `icmp samesign u{gt/lt} (add nsw X, C2), C` -> `icmp s{gt/lt} X, (C - C2)` whenever applicable. --- .../InstCombine/InstCombineCompares.cpp | 19 ++++++++++--------- llvm/test/Transforms/InstCombine/icmp-add.ll | 16 +++++++--------- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index 33eee8e059486..a7db4dec63075 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -3132,7 +3132,7 @@ Instruction *InstCombinerImpl::foldICmpAddConstant(ICmpInst &Cmp, Value *Op0, *Op1; Instruction *Ext0, *Ext1; - const CmpInst::Predicate Pred = Cmp.getPredicate(); + const CmpPredicate Pred(Cmp.getCmpPredicate()); if (match(Add, m_Add(m_CombineAnd(m_Instruction(Ext0), m_ZExtOrSExt(m_Value(Op0))), m_CombineAnd(m_Instruction(Ext1), @@ -3167,20 +3167,21 @@ Instruction *InstCombinerImpl::foldICmpAddConstant(ICmpInst &Cmp, // If the add does not wrap, we can always adjust the compare by subtracting // the constants. Equality comparisons are handled elsewhere. SGE/SLE/UGE/ULE - // are canonicalized to SGT/SLT/UGT/ULT. - if ((Add->hasNoSignedWrap() && - (Pred == ICmpInst::ICMP_SGT || Pred == ICmpInst::ICMP_SLT)) || - (Add->hasNoUnsignedWrap() && - (Pred == ICmpInst::ICMP_UGT || Pred == ICmpInst::ICMP_ULT))) { + // has been canonicalized to SGT/SLT/UGT/ULT. + CmpInst::Predicate ChosenPred = Pred.getPreferredSignedPredicate(); + if ((Add->hasNoSignedWrap() && (ChosenPred == ICmpInst::ICMP_SGT || + ChosenPred == ICmpInst::ICMP_SLT)) || + (Add->hasNoUnsignedWrap() && (ChosenPred == ICmpInst::ICMP_UGT || + ChosenPred == ICmpInst::ICMP_ULT))) { bool Overflow; - APInt NewC = - Cmp.isSigned() ? C.ssub_ov(*C2, Overflow) : C.usub_ov(*C2, Overflow); + APInt NewC = ICmpInst::isSigned(ChosenPred) ? C.ssub_ov(*C2, Overflow) + : C.usub_ov(*C2, Overflow); // If there is overflow, the result must be true or false. // TODO: Can we assert there is no overflow because InstSimplify always // handles those cases? if (!Overflow) // icmp Pred (add nsw X, C2), C --> icmp Pred X, (C - C2) - return new ICmpInst(Pred, X, ConstantInt::get(Ty, NewC)); + return new ICmpInst(ChosenPred, X, ConstantInt::get(Ty, NewC)); } if (ICmpInst::isUnsigned(Pred) && Add->hasNoSignedWrap() && diff --git a/llvm/test/Transforms/InstCombine/icmp-add.ll b/llvm/test/Transforms/InstCombine/icmp-add.ll index a9f7d36602dfb..e5b977fc60e6e 100644 --- a/llvm/test/Transforms/InstCombine/icmp-add.ll +++ b/llvm/test/Transforms/InstCombine/icmp-add.ll @@ -3444,8 +3444,7 @@ define i1 @val_is_aligend_pred_mismatch(i32 %num) { define i1 @icmp_samesign_with_nsw_add(i32 %arg0) { ; CHECK-LABEL: @icmp_samesign_with_nsw_add( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[ARG0:%.*]], -26 -; CHECK-NEXT: [[V1:%.*]] = icmp ult i32 [[TMP0]], -8 +; CHECK-NEXT: [[V1:%.*]] = icmp sgt i32 [[ARG0:%.*]], 25 ; CHECK-NEXT: ret i1 [[V1]] ; entry: @@ -3454,9 +3453,9 @@ entry: ret i1 %v1 } -; Shouldn't fire since -124 - 12 causes signed overflow -define i1 @icmp_samesign_with_nsw_add_no_fire(i8 %arg0) { -; CHECK-LABEL: @icmp_samesign_with_nsw_add_no_fire( +; Negative test; Fold shouldn't fire since -124 - 12 causes signed overflow +define i1 @icmp_samesign_with_nsw_add_neg(i8 %arg0) { +; CHECK-LABEL: @icmp_samesign_with_nsw_add_neg( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP0:%.*]] = add i8 [[ARG0:%.*]], -121 ; CHECK-NEXT: [[V1:%.*]] = icmp ult i8 [[TMP0]], 123 @@ -3471,20 +3470,19 @@ entry: define i1 @icmp_with_nuw_add(i32 %arg0) { ; CHECK-LABEL: @icmp_with_nuw_add( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[V1:%.*]] = icmp ugt i32 [[ARG0:%.*]], 11 +; CHECK-NEXT: [[V1:%.*]] = icmp ult i32 [[ARG0:%.*]], 11 ; CHECK-NEXT: ret i1 [[V1]] ; entry: %v0 = add nuw i32 %arg0, 7 - %v1 = icmp ugt i32 %v0, 18 + %v1 = icmp ult i32 %v0, 18 ret i1 %v1 } define i1 @icmp_partial_negative_samesign_ult_to_slt(i8 range(i8 -1, 5) %x) { ; CHECK-LABEL: @icmp_partial_negative_samesign_ult_to_slt( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[ADD:%.*]] = add nsw i8 [[X:%.*]], -5 -; CHECK-NEXT: [[CMP:%.*]] = icmp samesign ult i8 [[ADD]], -3 +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[X:%.*]], 2 ; CHECK-NEXT: ret i1 [[CMP]] ; entry: