[llvm] [InstCombine] Fold umax(nuw_mul(x, C0), x + 1) into (x == 0 ? 1 : nuw_mul(x, C0)) (PR #123468)

via llvm-commits llvm-commits at lists.llvm.org
Sat Jan 18 08:49:50 PST 2025


https://github.com/Ruhung created https://github.com/llvm/llvm-project/pull/123468

This PR introduces the following transformations:

- If C0 is not 0:  
umax(nuw_shl(x, C0), x + 1) -> x == 0 ? 1 : nuw_shl(x, C0)  
- If C0 is not 0 or 1:  
umax(nuw_mul(x, C0), x + 1) -> x == 0 ? 1 : nuw_mul(x, C0)  

Fixes : #122388 
Alive2 proof : https://alive2.llvm.org/ce/z/rkp_8U


>From 60dae2c8888bd6c50904c1579c12add985db22b0 Mon Sep 17 00:00:00 2001
From: Ruhung <jhlee at pllab.cs.nthu.edu.tw>
Date: Sat, 18 Jan 2025 23:37:14 +0800
Subject: [PATCH 1/2] [InstCombine] Pre-commit tests

---
 .../InstCombine/add-shl-mul-umax.ll           | 300 ++++++++++++++++++
 1 file changed, 300 insertions(+)
 create mode 100644 llvm/test/Transforms/InstCombine/add-shl-mul-umax.ll

diff --git a/llvm/test/Transforms/InstCombine/add-shl-mul-umax.ll b/llvm/test/Transforms/InstCombine/add-shl-mul-umax.ll
new file mode 100644
index 00000000000000..88a69e3dc6384e
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/add-shl-mul-umax.ll
@@ -0,0 +1,300 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt -S -passes=instcombine < %s | FileCheck %s
+
+; When C0 is neither 0 nor 1:
+;   umax(nuw_mul(x, C0), x + 1) is optimized to:
+;   x == 0 ? 1 : nuw_mul(x, C0)
+; When C0 is not 0:
+;   umax(nuw_shl(x, C0), x + 1) is optimized to:
+;   x == 0 ? 1 : nuw_shl(x, C0)
+
+; Positive Test Cases for `shl`
+
+define i64 @test_shl_by_2(i64 %x) {
+; CHECK-LABEL: define i64 @test_shl_by_2(
+; CHECK-SAME: i64 [[X:%.*]]) {
+; CHECK-NEXT:    [[X1:%.*]] = add i64 [[X]], 1
+; CHECK-NEXT:    [[TMP2:%.*]] = shl nuw i64 [[X]], 2
+; CHECK-NEXT:    [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[TMP2]], i64 [[X1]])
+; CHECK-NEXT:    ret i64 [[MAX]]
+;
+  %x1 = add i64 %x, 1
+  %shl = shl nuw i64 %x, 2
+  %max = call i64 @llvm.umax.i64(i64 %shl, i64 %x1)
+  ret i64 %max
+}
+
+define i64 @test_shl_by_5(i64 %x) {
+; CHECK-LABEL: define i64 @test_shl_by_5(
+; CHECK-SAME: i64 [[X:%.*]]) {
+; CHECK-NEXT:    [[X1:%.*]] = add i64 [[X]], 1
+; CHECK-NEXT:    [[TMP2:%.*]] = shl nuw i64 [[X]], 5
+; CHECK-NEXT:    [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[TMP2]], i64 [[X1]])
+; CHECK-NEXT:    ret i64 [[MAX]]
+;
+  %x1 = add i64 %x, 1
+  %shl = shl nuw i64 %x, 5
+  %max = call i64 @llvm.umax.i64(i64 %shl, i64 %x1)
+  ret i64 %max
+}
+
+; Commuted Test Cases for `shl`
+
+define i64 @test_shl_umax_commuted(i64 %x) {
+; CHECK-LABEL: define i64 @test_shl_umax_commuted(
+; CHECK-SAME: i64 [[X:%.*]]) {
+; CHECK-NEXT:    [[X1:%.*]] = add i64 [[X]], 1
+; CHECK-NEXT:    [[SHL:%.*]] = shl nuw i64 [[X]], 2
+; CHECK-NEXT:    [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[X1]], i64 [[SHL]])
+; CHECK-NEXT:    ret i64 [[MAX]]
+;
+  %x1 = add i64 %x, 1
+  %shl = shl nuw i64 %x, 2
+  %max = call i64 @llvm.umax.i64(i64 %x1, i64 %shl)
+  ret i64 %max
+}
+
+; Negative Test Cases for `shl`
+
+define i64 @test_shl_by_zero(i64 %x) {
+; CHECK-LABEL: define i64 @test_shl_by_zero(
+; CHECK-SAME: i64 [[X:%.*]]) {
+; CHECK-NEXT:    [[X1:%.*]] = add i64 [[X]], 1
+; CHECK-NEXT:    [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[X]], i64 [[X1]])
+; CHECK-NEXT:    ret i64 [[MAX]]
+;
+  %x1 = add i64 %x, 1
+  %shl = shl nuw i64 %x, 0
+  %max = call i64 @llvm.umax.i64(i64 %shl, i64 %x1)
+  ret i64 %max
+}
+
+define i64 @test_shl_add_by_2(i64 %x) {
+; CHECK-LABEL: define i64 @test_shl_add_by_2(
+; CHECK-SAME: i64 [[X:%.*]]) {
+; CHECK-NEXT:    [[X1:%.*]] = add i64 [[X]], 2
+; CHECK-NEXT:    [[SHL:%.*]] = shl nuw i64 [[X]], 2
+; CHECK-NEXT:    [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[SHL]], i64 [[X1]])
+; CHECK-NEXT:    ret i64 [[MAX]]
+;
+  %x1 = add i64 %x, 2
+  %shl = shl nuw i64 %x, 2
+  %max = call i64 @llvm.umax.i64(i64 %shl, i64 %x1)
+  ret i64 %max
+}
+
+define i64 @test_shl_without_nuw(i64 %x) {
+; CHECK-LABEL: define i64 @test_shl_without_nuw(
+; CHECK-SAME: i64 [[X:%.*]]) {
+; CHECK-NEXT:    [[X1:%.*]] = add i64 [[X]], 1
+; CHECK-NEXT:    [[SHL:%.*]] = shl i64 [[X]], 2
+; CHECK-NEXT:    [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[SHL]], i64 [[X1]])
+; CHECK-NEXT:    ret i64 [[MAX]]
+;
+  %x1 = add i64 %x, 1
+  %shl = shl i64 %x, 2
+  %max = call i64 @llvm.umax.i64(i64 %shl, i64 %x1)
+  ret i64 %max
+}
+
+; Multi-use Test Cases for `shl`
+declare void @use(i64)
+
+define i64 @test_shl_multi_use_add(i64 %x) {
+; CHECK-LABEL: define i64 @test_shl_multi_use_add(
+; CHECK-SAME: i64 [[X:%.*]]) {
+; CHECK-NEXT:    [[X1:%.*]] = add i64 [[X]], 1
+; CHECK-NEXT:    call void @use(i64 [[X1]])
+; CHECK-NEXT:    [[TMP2:%.*]] = shl nuw i64 [[X]], 3
+; CHECK-NEXT:    [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[TMP2]], i64 [[X1]])
+; CHECK-NEXT:    ret i64 [[MAX]]
+;
+  %x1 = add i64 %x, 1
+  call void @use(i64 %x1)
+  %shl = shl nuw i64 %x, 3
+  %max = call i64 @llvm.umax.i64(i64 %shl, i64 %x1)
+  ret i64 %max
+}
+
+define i64 @test_shl_multi_use_shl(i64 %x) {
+; CHECK-LABEL: define i64 @test_shl_multi_use_shl(
+; CHECK-SAME: i64 [[X:%.*]]) {
+; CHECK-NEXT:    [[X1:%.*]] = add i64 [[X]], 1
+; CHECK-NEXT:    [[SHL:%.*]] = shl nuw i64 [[X]], 2
+; CHECK-NEXT:    call void @use(i64 [[SHL]])
+; CHECK-NEXT:    [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[SHL]], i64 [[X1]])
+; CHECK-NEXT:    ret i64 [[MAX]]
+;
+  %x1 = add i64 %x, 1
+  %shl = shl nuw i64 %x, 2
+  call void @use(i64 %shl)
+  %max = call i64 @llvm.umax.i64(i64 %shl, i64 %x1)
+  ret i64 %max
+}
+
+define i64 @test_shl_multi_use_max(i64 %x) {
+; CHECK-LABEL: define i64 @test_shl_multi_use_max(
+; CHECK-SAME: i64 [[X:%.*]]) {
+; CHECK-NEXT:    [[X1:%.*]] = add i64 [[X]], 1
+; CHECK-NEXT:    [[TMP2:%.*]] = shl nuw i64 [[X]], 3
+; CHECK-NEXT:    [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[TMP2]], i64 [[X1]])
+; CHECK-NEXT:    call void @use(i64 [[MAX]])
+; CHECK-NEXT:    ret i64 [[MAX]]
+;
+  %x1 = add i64 %x, 1
+  %shl = shl nuw i64 %x, 3
+  %max = call i64 @llvm.umax.i64(i64 %shl, i64 %x1)
+  call void @use(i64 %max)
+  ret i64 %max
+}
+
+; Positive Test Cases for `mul`
+
+define i64 @test_mul_by_2(i64 %x) {
+; CHECK-LABEL: define i64 @test_mul_by_2(
+; CHECK-SAME: i64 [[X:%.*]]) {
+; CHECK-NEXT:    [[X1:%.*]] = add i64 [[X]], 1
+; CHECK-NEXT:    [[TMP2:%.*]] = shl nuw i64 [[X]], 1
+; CHECK-NEXT:    [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[TMP2]], i64 [[X1]])
+; CHECK-NEXT:    ret i64 [[MAX]]
+;
+  %x1 = add i64 %x, 1
+  %mul = mul nuw i64 %x, 2
+  %max = call i64 @llvm.umax.i64(i64 %mul, i64 %x1)
+  ret i64 %max
+}
+
+define i64 @test_mul_by_5(i64 %x) {
+; CHECK-LABEL: define i64 @test_mul_by_5(
+; CHECK-SAME: i64 [[X:%.*]]) {
+; CHECK-NEXT:    [[X1:%.*]] = add i64 [[X]], 1
+; CHECK-NEXT:    [[MUL:%.*]] = mul nuw i64 [[X]], 5
+; CHECK-NEXT:    [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[MUL]], i64 [[X1]])
+; CHECK-NEXT:    ret i64 [[MAX]]
+;
+  %x1 = add i64 %x, 1
+  %mul = mul nuw i64 %x, 5
+  %max = call i64 @llvm.umax.i64(i64 %mul, i64 %x1)
+  ret i64 %max
+}
+
+; Commuted Test Cases for `mul`
+
+define i64 @test_mul_max_commuted(i64 %x) {
+; CHECK-LABEL: define i64 @test_mul_max_commuted(
+; CHECK-SAME: i64 [[X:%.*]]) {
+; CHECK-NEXT:    [[X1:%.*]] = add i64 [[X]], 1
+; CHECK-NEXT:    [[MUL:%.*]] = shl nuw i64 [[X]], 1
+; CHECK-NEXT:    [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[X1]], i64 [[MUL]])
+; CHECK-NEXT:    ret i64 [[MAX]]
+;
+  %x1 = add i64 %x, 1
+  %mul = mul nuw i64 %x, 2
+  %max = call i64 @llvm.umax.i64(i64 %x1, i64 %mul)
+  ret i64 %max
+}
+
+; Negative Test Cases for `mul`
+
+define i64 @test_mul_by_zero(i64 %x) {
+; CHECK-LABEL: define i64 @test_mul_by_zero(
+; CHECK-SAME: i64 [[X:%.*]]) {
+; CHECK-NEXT:    [[X1:%.*]] = add i64 [[X]], 1
+; CHECK-NEXT:    ret i64 [[X1]]
+;
+  %x1 = add i64 %x, 1
+  %mul = mul nuw i64 %x, 0
+  %max = call i64 @llvm.umax.i64(i64 %mul, i64 %x1)
+  ret i64 %max
+}
+
+define i64 @test_mul_by_1(i64 %x) {
+; CHECK-LABEL: define i64 @test_mul_by_1(
+; CHECK-SAME: i64 [[X:%.*]]) {
+; CHECK-NEXT:    [[X1:%.*]] = add i64 [[X]], 1
+; CHECK-NEXT:    [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[X]], i64 [[X1]])
+; CHECK-NEXT:    ret i64 [[MAX]]
+;
+  %x1 = add i64 %x, 1
+  %mul = mul nuw i64 %x, 1
+  %max = call i64 @llvm.umax.i64(i64 %mul, i64 %x1)
+  ret i64 %max
+}
+
+define i64 @test_mul_add_by_2(i64 %x) {
+; CHECK-LABEL: define i64 @test_mul_add_by_2(
+; CHECK-SAME: i64 [[X:%.*]]) {
+; CHECK-NEXT:    [[X1:%.*]] = add i64 [[X]], 2
+; CHECK-NEXT:    [[MUL:%.*]] = shl nuw i64 [[X]], 1
+; CHECK-NEXT:    [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[MUL]], i64 [[X1]])
+; CHECK-NEXT:    ret i64 [[MAX]]
+;
+  %x1 = add i64 %x, 2
+  %mul = mul nuw i64 %x, 2
+  %max = call i64 @llvm.umax.i64(i64 %mul, i64 %x1)
+  ret i64 %max
+}
+
+define i64 @test_mul_without_nuw(i64 %x) {
+; CHECK-LABEL: define i64 @test_mul_without_nuw(
+; CHECK-SAME: i64 [[X:%.*]]) {
+; CHECK-NEXT:    [[X1:%.*]] = add i64 [[X]], 1
+; CHECK-NEXT:    [[MUL:%.*]] = shl i64 [[X]], 1
+; CHECK-NEXT:    [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[MUL]], i64 [[X1]])
+; CHECK-NEXT:    ret i64 [[MAX]]
+;
+  %x1 = add i64 %x, 1
+  %mul = mul i64 %x, 2
+  %max = call i64 @llvm.umax.i64(i64 %mul, i64 %x1)
+  ret i64 %max
+}
+
+; Multi-use Test Cases for `mul`
+
+define i64 @test_mul_multi_use_add(i64 %x) {
+; CHECK-LABEL: define i64 @test_mul_multi_use_add(
+; CHECK-SAME: i64 [[X:%.*]]) {
+; CHECK-NEXT:    [[X1:%.*]] = add i64 [[X]], 1
+; CHECK-NEXT:    call void @use(i64 [[X1]])
+; CHECK-NEXT:    [[TMP2:%.*]] = shl nuw i64 [[X]], 1
+; CHECK-NEXT:    [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[TMP2]], i64 [[X1]])
+; CHECK-NEXT:    ret i64 [[MAX]]
+;
+  %x1 = add i64 %x, 1
+  call void @use(i64 %x1)
+  %mul = mul nuw i64 %x, 2
+  %max = call i64 @llvm.umax.i64(i64 %mul, i64 %x1)
+  ret i64 %max
+}
+
+define i64 @test_mul_multi_use_mul(i64 %x) {
+; CHECK-LABEL: define i64 @test_mul_multi_use_mul(
+; CHECK-SAME: i64 [[X:%.*]]) {
+; CHECK-NEXT:    [[X1:%.*]] = add i64 [[X]], 1
+; CHECK-NEXT:    [[MUL:%.*]] = shl nuw i64 [[X]], 1
+; CHECK-NEXT:    call void @use(i64 [[MUL]])
+; CHECK-NEXT:    [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[MUL]], i64 [[X1]])
+; CHECK-NEXT:    ret i64 [[MAX]]
+;
+  %x1 = add i64 %x, 1
+  %mul = mul nuw i64 %x, 2
+  call void @use(i64 %mul)
+  %max = call i64 @llvm.umax.i64(i64 %mul, i64 %x1)
+  ret i64 %max
+}
+
+define i64 @test_mul_multi_use_max(i64 %x) {
+; CHECK-LABEL: define i64 @test_mul_multi_use_max(
+; CHECK-SAME: i64 [[X:%.*]]) {
+; CHECK-NEXT:    [[X1:%.*]] = add i64 [[X]], 1
+; CHECK-NEXT:    [[TMP2:%.*]] = shl nuw i64 [[X]], 1
+; CHECK-NEXT:    [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[TMP2]], i64 [[X1]])
+; CHECK-NEXT:    call void @use(i64 [[MAX]])
+; CHECK-NEXT:    ret i64 [[MAX]]
+;
+  %x1 = add i64 %x, 1
+  %mul = mul nuw i64 %x, 2
+  %max = call i64 @llvm.umax.i64(i64 %mul, i64 %x1)
+  call void @use(i64 %max)
+  ret i64 %max
+}

>From 5da19e8bf0aa8f50181aa30d3ff778de32b7b798 Mon Sep 17 00:00:00 2001
From: Ruhung <jhlee at pllab.cs.nthu.edu.tw>
Date: Sat, 18 Jan 2025 23:48:29 +0800
Subject: [PATCH 2/2] [InstCombine] Fold umax(nuw_mul(x, C0), x + 1) into (x ==
 0 ? 1 : nuw_mul(x, C0))

---
 .../InstCombine/InstCombineCalls.cpp          | 31 ++++++++++++++++++
 .../InstCombine/add-shl-mul-umax.ll           | 32 +++++++++----------
 2 files changed, 47 insertions(+), 16 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index c55c40c88bc845..0db7d8818fbd0b 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -1847,6 +1847,37 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
         return CastInst::Create(Instruction::ZExt, NarrowMaxMin, II->getType());
       }
     }
+    // If C0 is not 0:
+    //   umax(nuw_shl(x, C0), x + 1) -> x == 0 ? 1 : nuw_shl(x, C0)
+    // If C0 is not 0 or 1:
+    //   umax(nuw_mul(x, C0), x + 1) -> x == 0 ? 1 : nuw_mul(x, C0)
+    ConstantInt *C0;
+    bool isShl = false;
+    BinaryOperator *Op = nullptr;
+    auto matchShiftOrMul = [&](Value *I) {
+      if (match(I, m_OneUse(m_NUWShl(m_Value(X), m_ConstantInt(C0))))) {
+        isShl = true;
+        return true;
+      } else if (match(I, m_OneUse(m_NUWMul(m_Value(X), m_ConstantInt(C0)))) &&
+                 C0 && !C0->isOne()) {
+        isShl = false;
+        return true;
+      }
+      return false;
+    };
+    if (((matchShiftOrMul(I0) &&
+          match(I1, m_OneUse(m_Add(m_Specific(X), m_One())))) ||
+         (matchShiftOrMul(I1) &&
+          match(I0, m_OneUse(m_Add(m_Specific(X), m_One()))))) &&
+        C0 && !C0->isZero()) {
+      Op = isShl ? BinaryOperator::CreateNUWShl(X, C0)
+                 : BinaryOperator::CreateNUWMul(X, C0);
+      Builder.Insert(Op);
+      Value *Cmp = Builder.CreateICmpEQ(X, ConstantInt::get(X->getType(), 0));
+      Value *NewSelect =
+          Builder.CreateSelect(Cmp, ConstantInt::get(X->getType(), 1), Op);
+      return replaceInstUsesWith(*II, NewSelect);
+    }
     // If both operands of unsigned min/max are sign-extended, it is still ok
     // to narrow the operation.
     [[fallthrough]];
diff --git a/llvm/test/Transforms/InstCombine/add-shl-mul-umax.ll b/llvm/test/Transforms/InstCombine/add-shl-mul-umax.ll
index 88a69e3dc6384e..86ce5dc06ce031 100644
--- a/llvm/test/Transforms/InstCombine/add-shl-mul-umax.ll
+++ b/llvm/test/Transforms/InstCombine/add-shl-mul-umax.ll
@@ -13,9 +13,9 @@
 define i64 @test_shl_by_2(i64 %x) {
 ; CHECK-LABEL: define i64 @test_shl_by_2(
 ; CHECK-SAME: i64 [[X:%.*]]) {
-; CHECK-NEXT:    [[X1:%.*]] = add i64 [[X]], 1
 ; CHECK-NEXT:    [[TMP2:%.*]] = shl nuw i64 [[X]], 2
-; CHECK-NEXT:    [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[TMP2]], i64 [[X1]])
+; CHECK-NEXT:    [[TMP3:%.*]] = icmp eq i64 [[X]], 0
+; CHECK-NEXT:    [[MAX:%.*]] = select i1 [[TMP3]], i64 1, i64 [[TMP2]]
 ; CHECK-NEXT:    ret i64 [[MAX]]
 ;
   %x1 = add i64 %x, 1
@@ -27,9 +27,9 @@ define i64 @test_shl_by_2(i64 %x) {
 define i64 @test_shl_by_5(i64 %x) {
 ; CHECK-LABEL: define i64 @test_shl_by_5(
 ; CHECK-SAME: i64 [[X:%.*]]) {
-; CHECK-NEXT:    [[X1:%.*]] = add i64 [[X]], 1
 ; CHECK-NEXT:    [[TMP2:%.*]] = shl nuw i64 [[X]], 5
-; CHECK-NEXT:    [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[TMP2]], i64 [[X1]])
+; CHECK-NEXT:    [[TMP3:%.*]] = icmp eq i64 [[X]], 0
+; CHECK-NEXT:    [[MAX:%.*]] = select i1 [[TMP3]], i64 1, i64 [[TMP2]]
 ; CHECK-NEXT:    ret i64 [[MAX]]
 ;
   %x1 = add i64 %x, 1
@@ -43,9 +43,9 @@ define i64 @test_shl_by_5(i64 %x) {
 define i64 @test_shl_umax_commuted(i64 %x) {
 ; CHECK-LABEL: define i64 @test_shl_umax_commuted(
 ; CHECK-SAME: i64 [[X:%.*]]) {
-; CHECK-NEXT:    [[X1:%.*]] = add i64 [[X]], 1
 ; CHECK-NEXT:    [[SHL:%.*]] = shl nuw i64 [[X]], 2
-; CHECK-NEXT:    [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[X1]], i64 [[SHL]])
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i64 [[X]], 0
+; CHECK-NEXT:    [[MAX:%.*]] = select i1 [[TMP2]], i64 1, i64 [[SHL]]
 ; CHECK-NEXT:    ret i64 [[MAX]]
 ;
   %x1 = add i64 %x, 1
@@ -135,9 +135,9 @@ define i64 @test_shl_multi_use_shl(i64 %x) {
 define i64 @test_shl_multi_use_max(i64 %x) {
 ; CHECK-LABEL: define i64 @test_shl_multi_use_max(
 ; CHECK-SAME: i64 [[X:%.*]]) {
-; CHECK-NEXT:    [[X1:%.*]] = add i64 [[X]], 1
 ; CHECK-NEXT:    [[TMP2:%.*]] = shl nuw i64 [[X]], 3
-; CHECK-NEXT:    [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[TMP2]], i64 [[X1]])
+; CHECK-NEXT:    [[TMP3:%.*]] = icmp eq i64 [[X]], 0
+; CHECK-NEXT:    [[MAX:%.*]] = select i1 [[TMP3]], i64 1, i64 [[TMP2]]
 ; CHECK-NEXT:    call void @use(i64 [[MAX]])
 ; CHECK-NEXT:    ret i64 [[MAX]]
 ;
@@ -153,9 +153,9 @@ define i64 @test_shl_multi_use_max(i64 %x) {
 define i64 @test_mul_by_2(i64 %x) {
 ; CHECK-LABEL: define i64 @test_mul_by_2(
 ; CHECK-SAME: i64 [[X:%.*]]) {
-; CHECK-NEXT:    [[X1:%.*]] = add i64 [[X]], 1
 ; CHECK-NEXT:    [[TMP2:%.*]] = shl nuw i64 [[X]], 1
-; CHECK-NEXT:    [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[TMP2]], i64 [[X1]])
+; CHECK-NEXT:    [[TMP3:%.*]] = icmp eq i64 [[X]], 0
+; CHECK-NEXT:    [[MAX:%.*]] = select i1 [[TMP3]], i64 1, i64 [[TMP2]]
 ; CHECK-NEXT:    ret i64 [[MAX]]
 ;
   %x1 = add i64 %x, 1
@@ -167,9 +167,9 @@ define i64 @test_mul_by_2(i64 %x) {
 define i64 @test_mul_by_5(i64 %x) {
 ; CHECK-LABEL: define i64 @test_mul_by_5(
 ; CHECK-SAME: i64 [[X:%.*]]) {
-; CHECK-NEXT:    [[X1:%.*]] = add i64 [[X]], 1
 ; CHECK-NEXT:    [[MUL:%.*]] = mul nuw i64 [[X]], 5
-; CHECK-NEXT:    [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[MUL]], i64 [[X1]])
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i64 [[X]], 0
+; CHECK-NEXT:    [[MAX:%.*]] = select i1 [[TMP2]], i64 1, i64 [[MUL]]
 ; CHECK-NEXT:    ret i64 [[MAX]]
 ;
   %x1 = add i64 %x, 1
@@ -183,9 +183,9 @@ define i64 @test_mul_by_5(i64 %x) {
 define i64 @test_mul_max_commuted(i64 %x) {
 ; CHECK-LABEL: define i64 @test_mul_max_commuted(
 ; CHECK-SAME: i64 [[X:%.*]]) {
-; CHECK-NEXT:    [[X1:%.*]] = add i64 [[X]], 1
 ; CHECK-NEXT:    [[MUL:%.*]] = shl nuw i64 [[X]], 1
-; CHECK-NEXT:    [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[X1]], i64 [[MUL]])
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i64 [[X]], 0
+; CHECK-NEXT:    [[MAX:%.*]] = select i1 [[TMP2]], i64 1, i64 [[MUL]]
 ; CHECK-NEXT:    ret i64 [[MAX]]
 ;
   %x1 = add i64 %x, 1
@@ -286,9 +286,9 @@ define i64 @test_mul_multi_use_mul(i64 %x) {
 define i64 @test_mul_multi_use_max(i64 %x) {
 ; CHECK-LABEL: define i64 @test_mul_multi_use_max(
 ; CHECK-SAME: i64 [[X:%.*]]) {
-; CHECK-NEXT:    [[X1:%.*]] = add i64 [[X]], 1
 ; CHECK-NEXT:    [[TMP2:%.*]] = shl nuw i64 [[X]], 1
-; CHECK-NEXT:    [[MAX:%.*]] = call i64 @llvm.umax.i64(i64 [[TMP2]], i64 [[X1]])
+; CHECK-NEXT:    [[TMP3:%.*]] = icmp eq i64 [[X]], 0
+; CHECK-NEXT:    [[MAX:%.*]] = select i1 [[TMP3]], i64 1, i64 [[TMP2]]
 ; CHECK-NEXT:    call void @use(i64 [[MAX]])
 ; CHECK-NEXT:    ret i64 [[MAX]]
 ;



More information about the llvm-commits mailing list