[llvm] [InstCombine] Add freeze for lshr (mul (X, 2^N + 1)), N -> add (X, lshr(X, N)) (PR #96324)

via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 17 12:29:54 PDT 2024


https://github.com/AtariDreams updated https://github.com/llvm/llvm-project/pull/96324

>From a6695a4446e39aa68081fc483ae8d7e4e213f966 Mon Sep 17 00:00:00 2001
From: Rose <gfunni234 at gmail.com>
Date: Fri, 21 Jun 2024 11:37:49 -0400
Subject: [PATCH] [InstCombine] Add freeze for lshr (mul (X, 2^N + 1)), N ->
 add (X, lshr(X, N))

---
 .../InstCombine/InstCombineShifts.cpp         |  5 +-
 llvm/test/Transforms/InstCombine/ashr-lshr.ll | 53 ++++++++++++-------
 llvm/test/Transforms/InstCombine/lshr.ll      |  2 +-
 3 files changed, 37 insertions(+), 23 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
index 38f8a41214b68..90e97b020b9fe 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
@@ -1499,7 +1499,7 @@ Instruction *InstCombinerImpl::visitLShr(BinaryOperator &I) {
           return replaceInstUsesWith(I, X);
 
         // lshr (mul nuw (X, 2^N + 1)), N -> add nuw (X, lshr(X, N))
-        if (Op0->hasOneUse()) {
+        if (Op0->hasOneUse() && isGuaranteedNotToBeUndef(X, &AC, &I, &DT)) {
           auto *NewAdd = BinaryOperator::CreateNUWAdd(
               X, Builder.CreateLShr(X, ConstantInt::get(Ty, ShAmtC), "",
                                     I.isExact()));
@@ -1528,7 +1528,8 @@ Instruction *InstCombinerImpl::visitLShr(BinaryOperator &I) {
     }
 
     // lshr (mul nsw (X, 2^N + 1)), N -> add nsw (X, lshr(X, N))
-    if (match(Op0, m_OneUse(m_NSWMul(m_Value(X), m_APInt(MulC))))) {
+    if (match(Op0, m_OneUse(m_NSWMul(m_Value(X), m_APInt(MulC)))) &&
+        isGuaranteedNotToBeUndef(X, &AC, &I, &DT)) {
       if (BitWidth > 2 && (*MulC - 1).isPowerOf2() &&
           MulC->logBase2() == ShAmtC) {
         return BinaryOperator::CreateNSWAdd(
diff --git a/llvm/test/Transforms/InstCombine/ashr-lshr.ll b/llvm/test/Transforms/InstCombine/ashr-lshr.ll
index c2a4f35412670..5ac3435994655 100644
--- a/llvm/test/Transforms/InstCombine/ashr-lshr.ll
+++ b/llvm/test/Transforms/InstCombine/ashr-lshr.ll
@@ -605,7 +605,7 @@ define <2 x i8> @ashr_known_pos_exact_vec(<2 x i8> %x, <2 x i8> %y) {
   ret <2 x i8> %r
 }
 
-define i32 @lshr_mul_times_3_div_2(i32 %0) {
+define i32 @lshr_mul_times_3_div_2(i32 noundef %0) {
 ; CHECK-LABEL: @lshr_mul_times_3_div_2(
 ; CHECK-NEXT:    [[TMP2:%.*]] = lshr i32 [[TMP0:%.*]], 1
 ; CHECK-NEXT:    [[LSHR:%.*]] = add nuw nsw i32 [[TMP2]], [[TMP0]]
@@ -616,7 +616,20 @@ define i32 @lshr_mul_times_3_div_2(i32 %0) {
   ret i32 %lshr
 }
 
-define i32 @lshr_mul_times_3_div_2_exact(i32 %x) {
+; Negative test
+
+define i32 @lshr_mul_times_3_div_2_noudef(i32 %0) {
+; CHECK-LABEL: @lshr_mul_times_3_div_2_noudef(
+; CHECK-NEXT:    [[MUL:%.*]] = mul nuw nsw i32 [[TMP0:%.*]], 3
+; CHECK-NEXT:    [[LSHR:%.*]] = lshr i32 [[MUL]], 1
+; CHECK-NEXT:    ret i32 [[LSHR]]
+;
+  %mul = mul nsw nuw i32 %0, 3
+  %lshr = lshr i32 %mul, 1
+  ret i32 %lshr
+}
+
+define i32 @lshr_mul_times_3_div_2_exact(i32 noundef %x) {
 ; CHECK-LABEL: @lshr_mul_times_3_div_2_exact(
 ; CHECK-NEXT:    [[TMP1:%.*]] = lshr exact i32 [[X:%.*]], 1
 ; CHECK-NEXT:    [[LSHR:%.*]] = add nsw i32 [[TMP1]], [[X]]
@@ -629,7 +642,7 @@ define i32 @lshr_mul_times_3_div_2_exact(i32 %x) {
 
 ; Negative test
 
-define i32 @lshr_mul_times_3_div_2_no_flags(i32 %0) {
+define i32 @lshr_mul_times_3_div_2_no_flags(i32 noundef %0) {
 ; CHECK-LABEL: @lshr_mul_times_3_div_2_no_flags(
 ; CHECK-NEXT:    [[MUL:%.*]] = mul i32 [[TMP0:%.*]], 3
 ; CHECK-NEXT:    [[LSHR:%.*]] = lshr i32 [[MUL]], 1
@@ -642,7 +655,7 @@ define i32 @lshr_mul_times_3_div_2_no_flags(i32 %0) {
 
 ; Negative test
 
-define i32 @mul_times_3_div_2_multiuse_lshr(i32 %x) {
+define i32 @mul_times_3_div_2_multiuse_lshr(i32 noundef %x) {
 ; CHECK-LABEL: @mul_times_3_div_2_multiuse_lshr(
 ; CHECK-NEXT:    [[MUL:%.*]] = mul nuw i32 [[X:%.*]], 3
 ; CHECK-NEXT:    [[RES:%.*]] = lshr i32 [[MUL]], 1
@@ -655,7 +668,7 @@ define i32 @mul_times_3_div_2_multiuse_lshr(i32 %x) {
   ret i32 %res
 }
 
-define i32 @lshr_mul_times_3_div_2_exact_2(i32 %x) {
+define i32 @lshr_mul_times_3_div_2_exact_2(i32 noundef %x) {
 ; CHECK-LABEL: @lshr_mul_times_3_div_2_exact_2(
 ; CHECK-NEXT:    [[TMP1:%.*]] = lshr exact i32 [[X:%.*]], 1
 ; CHECK-NEXT:    [[LSHR:%.*]] = add nuw i32 [[TMP1]], [[X]]
@@ -666,7 +679,7 @@ define i32 @lshr_mul_times_3_div_2_exact_2(i32 %x) {
   ret i32 %lshr
 }
 
-define i32 @lshr_mul_times_5_div_4(i32 %0) {
+define i32 @lshr_mul_times_5_div_4(i32 noundef %0) {
 ; CHECK-LABEL: @lshr_mul_times_5_div_4(
 ; CHECK-NEXT:    [[TMP2:%.*]] = lshr i32 [[TMP0:%.*]], 2
 ; CHECK-NEXT:    [[LSHR:%.*]] = add nuw nsw i32 [[TMP2]], [[TMP0]]
@@ -677,7 +690,7 @@ define i32 @lshr_mul_times_5_div_4(i32 %0) {
   ret i32 %lshr
 }
 
-define i32 @lshr_mul_times_5_div_4_exact(i32 %x) {
+define i32 @lshr_mul_times_5_div_4_exact(i32 noundef %x) {
 ; CHECK-LABEL: @lshr_mul_times_5_div_4_exact(
 ; CHECK-NEXT:    [[TMP1:%.*]] = lshr exact i32 [[X:%.*]], 2
 ; CHECK-NEXT:    [[LSHR:%.*]] = add nsw i32 [[TMP1]], [[X]]
@@ -690,7 +703,7 @@ define i32 @lshr_mul_times_5_div_4_exact(i32 %x) {
 
 ; Negative test
 
-define i32 @lshr_mul_times_5_div_4_no_flags(i32 %0) {
+define i32 @lshr_mul_times_5_div_4_no_flags(i32 noundef %0) {
 ; CHECK-LABEL: @lshr_mul_times_5_div_4_no_flags(
 ; CHECK-NEXT:    [[MUL:%.*]] = mul i32 [[TMP0:%.*]], 5
 ; CHECK-NEXT:    [[LSHR:%.*]] = lshr i32 [[MUL]], 2
@@ -703,7 +716,7 @@ define i32 @lshr_mul_times_5_div_4_no_flags(i32 %0) {
 
 ; Negative test
 
-define i32 @mul_times_5_div_4_multiuse_lshr(i32 %x) {
+define i32 @mul_times_5_div_4_multiuse_lshr(i32 noundef %x) {
 ; CHECK-LABEL: @mul_times_5_div_4_multiuse_lshr(
 ; CHECK-NEXT:    [[MUL:%.*]] = mul nuw i32 [[X:%.*]], 5
 ; CHECK-NEXT:    [[RES:%.*]] = lshr i32 [[MUL]], 2
@@ -716,7 +729,7 @@ define i32 @mul_times_5_div_4_multiuse_lshr(i32 %x) {
   ret i32 %res
 }
 
-define i32 @lshr_mul_times_5_div_4_exact_2(i32 %x) {
+define i32 @lshr_mul_times_5_div_4_exact_2(i32 noundef %x) {
 ; CHECK-LABEL: @lshr_mul_times_5_div_4_exact_2(
 ; CHECK-NEXT:    [[TMP1:%.*]] = lshr exact i32 [[X:%.*]], 2
 ; CHECK-NEXT:    [[LSHR:%.*]] = add nuw i32 [[TMP1]], [[X]]
@@ -727,7 +740,7 @@ define i32 @lshr_mul_times_5_div_4_exact_2(i32 %x) {
   ret i32 %lshr
 }
 
-define i32 @ashr_mul_times_3_div_2(i32 %0) {
+define i32 @ashr_mul_times_3_div_2(i32 noundef %0) {
 ; CHECK-LABEL: @ashr_mul_times_3_div_2(
 ; CHECK-NEXT:    [[TMP2:%.*]] = ashr i32 [[TMP0:%.*]], 1
 ; CHECK-NEXT:    [[ASHR:%.*]] = add nuw nsw i32 [[TMP2]], [[TMP0]]
@@ -738,7 +751,7 @@ define i32 @ashr_mul_times_3_div_2(i32 %0) {
   ret i32 %ashr
 }
 
-define i32 @ashr_mul_times_3_div_2_exact(i32 %x) {
+define i32 @ashr_mul_times_3_div_2_exact(i32 noundef %x) {
 ; CHECK-LABEL: @ashr_mul_times_3_div_2_exact(
 ; CHECK-NEXT:    [[TMP1:%.*]] = ashr exact i32 [[X:%.*]], 1
 ; CHECK-NEXT:    [[ASHR:%.*]] = add nsw i32 [[TMP1]], [[X]]
@@ -751,7 +764,7 @@ define i32 @ashr_mul_times_3_div_2_exact(i32 %x) {
 
 ; Negative test
 
-define i32 @ashr_mul_times_3_div_2_no_flags(i32 %0) {
+define i32 @ashr_mul_times_3_div_2_no_flags(i32 noundef %0) {
 ; CHECK-LABEL: @ashr_mul_times_3_div_2_no_flags(
 ; CHECK-NEXT:    [[MUL:%.*]] = mul i32 [[TMP0:%.*]], 3
 ; CHECK-NEXT:    [[ASHR:%.*]] = ashr i32 [[MUL]], 1
@@ -764,7 +777,7 @@ define i32 @ashr_mul_times_3_div_2_no_flags(i32 %0) {
 
 ; Negative test
 
-define i32 @ashr_mul_times_3_div_2_no_nsw(i32 %0) {
+define i32 @ashr_mul_times_3_div_2_no_nsw(i32 noundef %0) {
 ; CHECK-LABEL: @ashr_mul_times_3_div_2_no_nsw(
 ; CHECK-NEXT:    [[MUL:%.*]] = mul nuw i32 [[TMP0:%.*]], 3
 ; CHECK-NEXT:    [[ASHR:%.*]] = ashr i32 [[MUL]], 1
@@ -777,7 +790,7 @@ define i32 @ashr_mul_times_3_div_2_no_nsw(i32 %0) {
 
 ; Negative test
 
-define i32 @mul_times_3_div_2_multiuse_ashr(i32 %x) {
+define i32 @mul_times_3_div_2_multiuse_ashr(i32 noundef %x) {
 ; CHECK-LABEL: @mul_times_3_div_2_multiuse_ashr(
 ; CHECK-NEXT:    [[MUL:%.*]] = mul nsw i32 [[X:%.*]], 3
 ; CHECK-NEXT:    [[RES:%.*]] = ashr i32 [[MUL]], 1
@@ -790,7 +803,7 @@ define i32 @mul_times_3_div_2_multiuse_ashr(i32 %x) {
   ret i32 %res
 }
 
-define i32 @ashr_mul_times_3_div_2_exact_2(i32 %x) {
+define i32 @ashr_mul_times_3_div_2_exact_2(i32 noundef %x) {
 ; CHECK-LABEL: @ashr_mul_times_3_div_2_exact_2(
 ; CHECK-NEXT:    [[TMP1:%.*]] = ashr exact i32 [[X:%.*]], 1
 ; CHECK-NEXT:    [[ASHR:%.*]] = add nsw i32 [[TMP1]], [[X]]
@@ -801,7 +814,7 @@ define i32 @ashr_mul_times_3_div_2_exact_2(i32 %x) {
   ret i32 %ashr
 }
 
-define i32 @ashr_mul_times_5_div_4(i32 %0) {
+define i32 @ashr_mul_times_5_div_4(i32 noundef %0) {
 ; CHECK-LABEL: @ashr_mul_times_5_div_4(
 ; CHECK-NEXT:    [[TMP2:%.*]] = ashr i32 [[TMP0:%.*]], 2
 ; CHECK-NEXT:    [[ASHR:%.*]] = add nuw nsw i32 [[TMP2]], [[TMP0]]
@@ -825,7 +838,7 @@ define i32 @ashr_mul_times_5_div_4_exact(i32 %x) {
 
 ; Negative test
 
-define i32 @ashr_mul_times_5_div_4_no_flags(i32 %0) {
+define i32 @ashr_mul_times_5_div_4_no_flags(i32 noundef %0) {
 ; CHECK-LABEL: @ashr_mul_times_5_div_4_no_flags(
 ; CHECK-NEXT:    [[MUL:%.*]] = mul i32 [[TMP0:%.*]], 5
 ; CHECK-NEXT:    [[ASHR:%.*]] = ashr i32 [[MUL]], 2
@@ -838,7 +851,7 @@ define i32 @ashr_mul_times_5_div_4_no_flags(i32 %0) {
 
 ; Negative test
 
-define i32 @mul_times_5_div_4_multiuse_ashr(i32 %x) {
+define i32 @mul_times_5_div_4_multiuse_ashr(i32 noundef %x) {
 ; CHECK-LABEL: @mul_times_5_div_4_multiuse_ashr(
 ; CHECK-NEXT:    [[MUL:%.*]] = mul nsw i32 [[X:%.*]], 5
 ; CHECK-NEXT:    [[RES:%.*]] = ashr i32 [[MUL]], 2
@@ -851,7 +864,7 @@ define i32 @mul_times_5_div_4_multiuse_ashr(i32 %x) {
   ret i32 %res
 }
 
-define i32 @ashr_mul_times_5_div_4_exact_2(i32 %x) {
+define i32 @ashr_mul_times_5_div_4_exact_2(i32 noundef %x) {
 ; CHECK-LABEL: @ashr_mul_times_5_div_4_exact_2(
 ; CHECK-NEXT:    [[TMP1:%.*]] = ashr exact i32 [[X:%.*]], 2
 ; CHECK-NEXT:    [[ASHR:%.*]] = add nsw i32 [[TMP1]], [[X]]
diff --git a/llvm/test/Transforms/InstCombine/lshr.ll b/llvm/test/Transforms/InstCombine/lshr.ll
index 01e07985ba6ab..51a2982f16f34 100644
--- a/llvm/test/Transforms/InstCombine/lshr.ll
+++ b/llvm/test/Transforms/InstCombine/lshr.ll
@@ -739,7 +739,7 @@ define i32 @mul_splat_fold_wrong_lshr_const(i32 %x) {
   ret i32 %t
 }
 
-define i32 @mul_splat_fold_no_nuw(i32 %x) {
+define i32 @mul_splat_fold_no_nuw(i32 noundef %x) {
 ; CHECK-LABEL: @mul_splat_fold_no_nuw(
 ; CHECK-NEXT:    [[TMP1:%.*]] = lshr i32 [[X:%.*]], 16
 ; CHECK-NEXT:    [[T:%.*]] = add nsw i32 [[TMP1]], [[X]]



More information about the llvm-commits mailing list