[llvm] f2734aa - [InstCombine] fold icmp with add/sub instructions having the same operands (#143241)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Jun 16 08:05:33 PDT 2025
Author: Acthinks Yang
Date: 2025-06-16T17:05:30+02:00
New Revision: f2734aa25e808e8c1967f7125fdea6c8b2dab9e1
URL: https://github.com/llvm/llvm-project/commit/f2734aa25e808e8c1967f7125fdea6c8b2dab9e1
DIFF: https://github.com/llvm/llvm-project/commit/f2734aa25e808e8c1967f7125fdea6c8b2dab9e1.diff
LOG: [InstCombine] fold icmp with add/sub instructions having the same operands (#143241)
Closes #143211.
Added:
llvm/test/Transforms/InstCombine/icmp-subadd.ll
Modified:
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index c112fae351817..084e7fbaa268a 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -7728,6 +7728,30 @@ Instruction *InstCombinerImpl::visitICmpInst(ICmpInst &I) {
}
}
+ // icmp slt (sub nsw x, y), (add nsw x, y) --> icmp sgt y, 0
+ // icmp ult (sub nuw x, y), (add nuw x, y) --> icmp ugt y, 0
+ // icmp eq (sub nsw/nuw x, y), (add nsw/nuw x, y) --> icmp eq y, 0
+ {
+ Value *A, *B;
+ CmpPredicate CmpPred;
+ if (match(&I, m_c_ICmp(CmpPred, m_Sub(m_Value(A), m_Value(B)),
+ m_c_Add(m_Deferred(A), m_Deferred(B))))) {
+ auto *I0 = cast<OverflowingBinaryOperator>(Op0);
+ auto *I1 = cast<OverflowingBinaryOperator>(Op1);
+ bool I0NUW = I0->hasNoUnsignedWrap();
+ bool I1NUW = I1->hasNoUnsignedWrap();
+ bool I0NSW = I0->hasNoSignedWrap();
+ bool I1NSW = I1->hasNoSignedWrap();
+ if ((ICmpInst::isUnsigned(Pred) && I0NUW && I1NUW) ||
+ (ICmpInst::isSigned(Pred) && I0NSW && I1NSW) ||
+ (ICmpInst::isEquality(Pred) &&
+ ((I0NUW || I0NSW) && (I1NUW || I1NSW)))) {
+ return new ICmpInst(CmpPredicate::getSwapped(CmpPred), B,
+ ConstantInt::get(Op0->getType(), 0));
+ }
+ }
+ }
+
// Try to optimize equality comparisons against alloca-based pointers.
if (Op0->getType()->isPointerTy() && I.isEquality()) {
assert(Op1->getType()->isPointerTy() &&
diff --git a/llvm/test/Transforms/InstCombine/icmp-subadd.ll b/llvm/test/Transforms/InstCombine/icmp-subadd.ll
new file mode 100644
index 0000000000000..fd7e1250d893f
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/icmp-subadd.ll
@@ -0,0 +1,111 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt < %s -passes=instcombine -S | FileCheck %s
+
+define i1 @test-same-operands-sub-add-nsw-icmp-sgt(i8 %a, i8 %b) {
+; CHECK-LABEL: define i1 @test-same-operands-sub-add-nsw-icmp-sgt(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]]) {
+; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[B]], 0
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %sub = sub nsw i8 %a, %b
+ %add = add nsw i8 %a, %b
+ %cmp = icmp sgt i8 %sub, %add
+ ret i1 %cmp
+}
+
+define i1 @test-same-operands-sub-add-nsw-icmp-slt(i8 %a, i8 %b) {
+; CHECK-LABEL: define i1 @test-same-operands-sub-add-nsw-icmp-slt(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]]) {
+; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[B]], 0
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %sub = sub nsw i8 %a, %b
+ %add = add nsw i8 %a, %b
+ %cmp = icmp slt i8 %sub, %add
+ ret i1 %cmp
+}
+
+define i1 @test-same-operands-sub-add-nsw-icmp-sle(i8 %a, i8 %b) {
+; CHECK-LABEL: define i1 @test-same-operands-sub-add-nsw-icmp-sle(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]]) {
+; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[B]], -1
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %sub = sub nsw i8 %a, %b
+ %add = add nsw i8 %a, %b
+ %cmp = icmp sle i8 %sub, %add
+ ret i1 %cmp
+}
+
+define i1 @test-same-operands-sub-add-nsw-nuw-icmp-eq(i8 %a, i8 %b) {
+; CHECK-LABEL: define i1 @test-same-operands-sub-add-nsw-nuw-icmp-eq(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]]) {
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[B]], 0
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %sub = sub nsw i8 %a, %b
+ %add = add nuw i8 %a, %b
+ %cmp = icmp eq i8 %sub, %add
+ ret i1 %cmp
+}
+
+define i1 @test-same-operands-sub-add-nsw-icmp-eq(i8 %a, i8 %b) {
+; CHECK-LABEL: define i1 @test-same-operands-sub-add-nsw-icmp-eq(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]]) {
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[B]], 0
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %sub = sub nsw i8 %a, %b
+ %add = add nsw i8 %a, %b
+ %cmp = icmp eq i8 %sub, %add
+ ret i1 %cmp
+}
+
+define i1 @test-add-sub-nsw-icmp-sgt(i8 %a, i8 %b) {
+; CHECK-LABEL: define i1 @test-add-sub-nsw-icmp-sgt(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]]) {
+; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[B]], 0
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %sub = sub nsw i8 %a, %b
+ %add = add nsw i8 %a, %b
+ %cmp = icmp sgt i8 %add, %sub
+ ret i1 %cmp
+}
+
+define i1 @test-add-sub-nuw-icmp-uge(i8 %a, i8 %b) {
+; CHECK-LABEL: define i1 @test-add-sub-nuw-icmp-uge(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]]) {
+; CHECK-NEXT: ret i1 true
+;
+ %sub = sub nuw i8 %a, %b
+ %add = add nuw i8 %a, %b
+ %cmp = icmp uge i8 %add, %sub
+ ret i1 %cmp
+}
+
+; Check not folded
+define i1 @test-add-sub-nuw-icmp-sge(i8 %a, i8 %b) {
+; CHECK-LABEL: define i1 @test-add-sub-nuw-icmp-sge(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]]) {
+; CHECK-NEXT: [[SUB:%.*]] = sub nuw i8 [[A]], [[B]]
+; CHECK-NEXT: [[ADD:%.*]] = add nuw i8 [[A]], [[B]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp sge i8 [[ADD]], [[SUB]]
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %sub = sub nuw i8 %a, %b
+ %add = add nuw i8 %a, %b
+ %cmp = icmp sge i8 %add, %sub
+ ret i1 %cmp
+}
+
+define i1 @test-add-swap-sub-nuw-icmp-uge(i8 %a, i8 %b) {
+; CHECK-LABEL: define i1 @test-add-swap-sub-nuw-icmp-uge(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]]) {
+; CHECK-NEXT: ret i1 true
+;
+ %sub = sub nuw i8 %a, %b
+ %add = add nuw i8 %b, %a
+ %cmp = icmp uge i8 %add, %sub
+ ret i1 %cmp
+}
More information about the llvm-commits
mailing list