[llvm] 4f7dc1b - [InstCombine] Fold (add (add A, 1), (sext (icmp ne A, 0))) to call umax(A, 1) (#122491)

via llvm-commits llvm-commits at lists.llvm.org
Sun Jan 12 07:52:01 PST 2025


Author: Ruhung
Date: 2025-01-12T16:51:58+01:00
New Revision: 4f7dc1b55ae5b8ed1a36dd941ef4f9920bfdac8d

URL: https://github.com/llvm/llvm-project/commit/4f7dc1b55ae5b8ed1a36dd941ef4f9920bfdac8d
DIFF: https://github.com/llvm/llvm-project/commit/4f7dc1b55ae5b8ed1a36dd941ef4f9920bfdac8d.diff

LOG: [InstCombine] Fold (add (add A, 1), (sext (icmp ne A, 0))) to call umax(A, 1) (#122491)

Transform (add (add A, 1), (sext (icmp ne A, 0))) into call umax(A, 1).

Fixes #121853.

Alive2: https://alive2.llvm.org/ce/z/TweTan

Added: 
    llvm/test/Transforms/InstCombine/add-sext-icmp.ll

Modified: 
    llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
index 73876d00e73a7c..658bbbc5697660 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
@@ -1775,6 +1775,15 @@ Instruction *InstCombinerImpl::visitAdd(BinaryOperator &I) {
     }
   }
 
+  // (add (add A, 1), (sext (icmp ne A, 0))) => call umax(A, 1)
+  if (match(LHS, m_Add(m_Value(A), m_One())) &&
+      match(RHS, m_OneUse(m_SExt(m_OneUse(m_SpecificICmp(
+                     ICmpInst::ICMP_NE, m_Specific(A), m_ZeroInt())))))) {
+    Value *OneConst = ConstantInt::get(A->getType(), 1);
+    Value *UMax = Builder.CreateBinaryIntrinsic(Intrinsic::umax, A, OneConst);
+    return replaceInstUsesWith(I, UMax);
+  }
+
   if (Instruction *Ashr = foldAddToAshr(I))
     return Ashr;
 

diff  --git a/llvm/test/Transforms/InstCombine/add-sext-icmp.ll b/llvm/test/Transforms/InstCombine/add-sext-icmp.ll
new file mode 100644
index 00000000000000..26bfc56690cb30
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/add-sext-icmp.ll
@@ -0,0 +1,139 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt -S -passes=instcombine < %s | FileCheck %s
+
+; The pattern:
+;   add(add A, 1), (sext(icmp ne A, 0))
+; is transformed into:
+;   umax(A, 1)
+
+define i32 @add_sext_icmp(i32 %A) {
+; CHECK-LABEL: define i32 @add_sext_icmp(
+; CHECK-SAME: i32 [[A:%.*]]) {
+; CHECK-NEXT:    [[ADD2:%.*]] = call i32 @llvm.umax.i32(i32 [[A]], i32 1)
+; CHECK-NEXT:    ret i32 [[ADD2]]
+;
+  %add1 = add i32 %A, 1
+  %icmp = icmp ne i32 %A, 0
+  %sext = sext i1 %icmp to i32
+  %add2 = add i32 %add1, %sext
+  ret i32 %add2
+}
+
+define i32 @add_sext_icmp_commutative(i32 %A) {
+; CHECK-LABEL: define i32 @add_sext_icmp_commutative(
+; CHECK-SAME: i32 [[A:%.*]]) {
+; CHECK-NEXT:    [[ADD2:%.*]] = call i32 @llvm.umax.i32(i32 [[A]], i32 1)
+; CHECK-NEXT:    ret i32 [[ADD2]]
+;
+  %add1 = add i32 %A, 1
+  %icmp = icmp ne i32 %A, 0
+  %sext = sext i1 %icmp to i32
+  %add2 = add i32 %sext, %add1
+  ret i32 %add2
+}
+
+; Negative test
+
+define i32 @add_sext_icmp_negative_constant(i32 %A) {
+; CHECK-LABEL: define i32 @add_sext_icmp_negative_constant(
+; CHECK-SAME: i32 [[A:%.*]]) {
+; CHECK-NEXT:    [[ADD1:%.*]] = add i32 [[A]], 2
+; CHECK-NEXT:    [[ICMP:%.*]] = icmp ne i32 [[A]], 0
+; CHECK-NEXT:    [[SEXT:%.*]] = sext i1 [[ICMP]] to i32
+; CHECK-NEXT:    [[ADD2:%.*]] = add i32 [[ADD1]], [[SEXT]]
+; CHECK-NEXT:    ret i32 [[ADD2]]
+;
+  %add1 = add i32 %A, 2
+  %icmp = icmp ne i32 %A, 0
+  %sext = sext i1 %icmp to i32
+  %add2 = add i32 %add1, %sext
+  ret i32 %add2
+}
+
+define i32 @add_sext_icmp_negative_pred(i32 %A) {
+; CHECK-LABEL: define i32 @add_sext_icmp_negative_pred(
+; CHECK-SAME: i32 [[A:%.*]]) {
+; CHECK-NEXT:    [[ADD1:%.*]] = add i32 [[A]], 1
+; CHECK-NEXT:    [[ICMP:%.*]] = icmp eq i32 [[A]], 0
+; CHECK-NEXT:    [[SEXT:%.*]] = sext i1 [[ICMP]] to i32
+; CHECK-NEXT:    [[ADD2:%.*]] = add i32 [[ADD1]], [[SEXT]]
+; CHECK-NEXT:    ret i32 [[ADD2]]
+;
+  %add1 = add i32 %A, 1
+  %icmp = icmp eq i32 %A, 0
+  %sext = sext i1 %icmp to i32
+  %add2 = add i32 %add1, %sext
+  ret i32 %add2
+}
+
+; multi-use test
+
+define i32 @add_sext_icmp_multi_use_add2(i32 %A) {
+; CHECK-LABEL: define i32 @add_sext_icmp_multi_use_add2(
+; CHECK-SAME: i32 [[A:%.*]]) {
+; CHECK-NEXT:    [[ADD2:%.*]] = call i32 @llvm.umax.i32(i32 [[A]], i32 1)
+; CHECK-NEXT:    call void @use(i32 [[ADD2]])
+; CHECK-NEXT:    ret i32 [[ADD2]]
+;
+  %add1 = add i32 %A, 1
+  %icmp = icmp ne i32 %A, 0
+  %sext = sext i1 %icmp to i32
+  %add2 = add i32 %add1, %sext
+  call void @use(i32 %add2)
+  ret i32 %add2
+}
+
+define i32 @add_sext_icmp_multi_use_sext(i32 %A) {
+; CHECK-LABEL: define i32 @add_sext_icmp_multi_use_sext(
+; CHECK-SAME: i32 [[A:%.*]]) {
+; CHECK-NEXT:    [[ADD1:%.*]] = add i32 [[A]], 1
+; CHECK-NEXT:    [[ICMP:%.*]] = icmp ne i32 [[A]], 0
+; CHECK-NEXT:    [[SEXT:%.*]] = sext i1 [[ICMP]] to i32
+; CHECK-NEXT:    call void @use(i32 [[SEXT]])
+; CHECK-NEXT:    [[ADD2:%.*]] = add i32 [[ADD1]], [[SEXT]]
+; CHECK-NEXT:    ret i32 [[ADD2]]
+;
+  %add1 = add i32 %A, 1
+  %icmp = icmp ne i32 %A, 0
+  %sext = sext i1 %icmp to i32
+  call void @use(i32 %sext)
+  %add2 = add i32 %add1, %sext
+  ret i32 %add2
+}
+
+define i32 @add_sext_icmp_multi_use_icmp(i32 %A) {
+; CHECK-LABEL: define i32 @add_sext_icmp_multi_use_icmp(
+; CHECK-SAME: i32 [[A:%.*]]) {
+; CHECK-NEXT:    [[ADD1:%.*]] = add i32 [[A]], 1
+; CHECK-NEXT:    [[ICMP:%.*]] = icmp ne i32 [[A]], 0
+; CHECK-NEXT:    call void @use(i1 [[ICMP]])
+; CHECK-NEXT:    [[SEXT:%.*]] = sext i1 [[ICMP]] to i32
+; CHECK-NEXT:    [[ADD2:%.*]] = add i32 [[ADD1]], [[SEXT]]
+; CHECK-NEXT:    ret i32 [[ADD2]]
+;
+  %add1 = add i32 %A, 1
+  %icmp = icmp ne i32 %A, 0
+  call void @use(i1 %icmp)
+  %sext = sext i1 %icmp to i32
+  %add2 = add i32 %add1, %sext
+  ret i32 %add2
+}
+
+define i32 @add_sext_icmp_multi_use_add1(i32 %A) {
+; CHECK-LABEL: define i32 @add_sext_icmp_multi_use_add1(
+; CHECK-SAME: i32 [[A:%.*]]) {
+; CHECK-NEXT:    [[ADD1:%.*]] = add i32 [[A]], 1
+; CHECK-NEXT:    call void @use(i32 [[ADD1]])
+; CHECK-NEXT:    [[ADD2:%.*]] = call i32 @llvm.umax.i32(i32 [[A]], i32 1)
+; CHECK-NEXT:    ret i32 [[ADD2]]
+;
+  %add1 = add i32 %A, 1
+  call void @use(i32 %add1)
+  %icmp = icmp ne i32 %A, 0
+  %sext = sext i1 %icmp to i32
+  %add2 = add i32 %add1, %sext
+  ret i32 %add2
+}
+
+declare void @use(i32)
+


        


More information about the llvm-commits mailing list