[llvm] [InstSimplify] Add simplification for `({u,s}rem (mul {nuw,nsw} X, C1), C0)` (PR #97037)

via llvm-commits llvm-commits at lists.llvm.org
Fri Jun 28 09:42:54 PDT 2024


https://github.com/goldsteinn updated https://github.com/llvm/llvm-project/pull/97037

>From e6e5c815a39468b4b081d4ee9a15c23a657cf8ed Mon Sep 17 00:00:00 2001
From: Noah Goldstein <goldstein.w.n at gmail.com>
Date: Fri, 28 Jun 2024 18:39:49 +0800
Subject: [PATCH 1/2] [InstSimplify] Add test for simplifying `({u,s}rem (mul
 {nuw,nsw} X, C1), C0)`; NFC

---
 llvm/test/Transforms/InstSimplify/rem.ll | 57 +++++++++++++++++++++++-
 1 file changed, 56 insertions(+), 1 deletion(-)

diff --git a/llvm/test/Transforms/InstSimplify/rem.ll b/llvm/test/Transforms/InstSimplify/rem.ll
index a46db0342042f..ad9cb21a12cc9 100644
--- a/llvm/test/Transforms/InstSimplify/rem.ll
+++ b/llvm/test/Transforms/InstSimplify/rem.ll
@@ -265,7 +265,7 @@ define i32 @rem4() {
 ; CHECK-NEXT:    [[CALL:%.*]] = call i32 @external(), !range [[RNG0:![0-9]+]]
 ; CHECK-NEXT:    ret i32 [[CALL]]
 ;
-  %call = call i32 @external(), !range !0
+  %call = call i32 @external() , !range !0
   %urem = urem i32 %call, 3
   ret i32 %urem
 }
@@ -488,3 +488,58 @@ define i8 @urem_mul_sdiv(i8 %x, i8 %y) {
   %mod = urem i8 %mul, %y
   ret i8 %mod
 }
+
+define <2 x i8> @simplfy_srem_of_mul(<2 x i8> %x) {
+; CHECK-LABEL: @simplfy_srem_of_mul(
+; CHECK-NEXT:    [[MUL:%.*]] = mul nsw <2 x i8> [[X:%.*]], <i8 20, i8 10>
+; CHECK-NEXT:    [[R:%.*]] = srem <2 x i8> [[MUL]], <i8 5, i8 5>
+; CHECK-NEXT:    ret <2 x i8> [[R]]
+;
+  %mul = mul nsw <2 x i8> %x, <i8 20, i8 10>
+  %r = srem <2 x i8> %mul, <i8 5, i8 5>
+  ret <2 x i8> %r
+}
+
+define <2 x i8> @simplfy_srem_of_mul_fail_bad_mod(<2 x i8> %x) {
+; CHECK-LABEL: @simplfy_srem_of_mul_fail_bad_mod(
+; CHECK-NEXT:    [[MUL:%.*]] = mul nsw <2 x i8> [[X:%.*]], <i8 20, i8 11>
+; CHECK-NEXT:    [[R:%.*]] = srem <2 x i8> [[MUL]], <i8 5, i8 5>
+; CHECK-NEXT:    ret <2 x i8> [[R]]
+;
+  %mul = mul nsw <2 x i8> %x, <i8 20, i8 11>
+  %r = srem <2 x i8> %mul, <i8 5, i8 5>
+  ret <2 x i8> %r
+}
+
+define i8 @simplfy_urem_of_mul(i8 %x) {
+; CHECK-LABEL: @simplfy_urem_of_mul(
+; CHECK-NEXT:    [[MUL:%.*]] = mul nuw i8 [[X:%.*]], 30
+; CHECK-NEXT:    [[R:%.*]] = urem i8 [[MUL]], 10
+; CHECK-NEXT:    ret i8 [[R]]
+;
+  %mul = mul nuw i8 %x, 30
+  %r = urem i8 %mul, 10
+  ret i8 %r
+}
+
+define i8 @simplfy_urem_of_mul_fail_bad_flag(i8 %x) {
+; CHECK-LABEL: @simplfy_urem_of_mul_fail_bad_flag(
+; CHECK-NEXT:    [[MUL:%.*]] = mul nsw i8 [[X:%.*]], 30
+; CHECK-NEXT:    [[R:%.*]] = urem i8 [[MUL]], 10
+; CHECK-NEXT:    ret i8 [[R]]
+;
+  %mul = mul nsw i8 %x, 30
+  %r = urem i8 %mul, 10
+  ret i8 %r
+}
+
+define i8 @simplfy_urem_of_mul_fail_bad_mod(i8 %x) {
+; CHECK-LABEL: @simplfy_urem_of_mul_fail_bad_mod(
+; CHECK-NEXT:    [[MUL:%.*]] = mul nuw i8 [[X:%.*]], 31
+; CHECK-NEXT:    [[R:%.*]] = urem i8 [[MUL]], 10
+; CHECK-NEXT:    ret i8 [[R]]
+;
+  %mul = mul nuw i8 %x, 31
+  %r = urem i8 %mul, 10
+  ret i8 %r
+}

>From 92f85d9cfe9e9e960c037de4e3a9fc520731a32b Mon Sep 17 00:00:00 2001
From: Noah Goldstein <goldstein.w.n at gmail.com>
Date: Fri, 28 Jun 2024 18:40:08 +0800
Subject: [PATCH 2/2] [InstSimplify] Add simplification for `({u,s}rem (mul
 {nuw,nsw} X, C1), C0)`

We can simplify these to `0` if `C1 % C0 == 0`

Proofs: https://alive2.llvm.org/ce/z/EejAdk
---
 llvm/lib/Analysis/InstructionSimplify.cpp | 28 ++++++++++++++++++-----
 llvm/test/Transforms/InstSimplify/rem.ll  |  8 ++-----
 2 files changed, 24 insertions(+), 12 deletions(-)

diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index cdcc40c596b77..1b72f151e3692 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -1226,13 +1226,29 @@ static Value *simplifyRem(Instruction::BinaryOps Opcode, Value *Op0, Value *Op1,
     return V;
 
   // (X << Y) % X -> 0
-  if (Q.IIQ.UseInstrInfo &&
-      ((Opcode == Instruction::SRem &&
-        match(Op0, m_NSWShl(m_Specific(Op1), m_Value()))) ||
-       (Opcode == Instruction::URem &&
-        match(Op0, m_NUWShl(m_Specific(Op1), m_Value())))))
-    return Constant::getNullValue(Op0->getType());
+  if (Q.IIQ.UseInstrInfo) {
+    if ((Opcode == Instruction::SRem &&
+         match(Op0, m_NSWShl(m_Specific(Op1), m_Value()))) ||
+        (Opcode == Instruction::URem &&
+         match(Op0, m_NUWShl(m_Specific(Op1), m_Value()))))
+      return Constant::getNullValue(Op0->getType());
 
+    const APInt *C0;
+    if (match(Op1, m_APInt(C0))) {
+      // (srem (mul nsw X, C1), C0) -> 0 if C1 s% C0 == 0
+      // (urem (mul nuw X, C1), C0) -> 0 if C1 u% C0 == 0
+      if (Opcode == Instruction::SRem
+              ? match(Op0,
+                      m_NSWMul(m_Value(), m_CheckedInt([C0](const APInt &C) {
+                                 return C.srem(*C0).isZero();
+                               })))
+              : match(Op0,
+                      m_NUWMul(m_Value(), m_CheckedInt([C0](const APInt &C) {
+                                 return C.urem(*C0).isZero();
+                               }))))
+        return Constant::getNullValue(Op0->getType());
+    }
+  }
   return nullptr;
 }
 
diff --git a/llvm/test/Transforms/InstSimplify/rem.ll b/llvm/test/Transforms/InstSimplify/rem.ll
index ad9cb21a12cc9..aceb7cb12185d 100644
--- a/llvm/test/Transforms/InstSimplify/rem.ll
+++ b/llvm/test/Transforms/InstSimplify/rem.ll
@@ -491,9 +491,7 @@ define i8 @urem_mul_sdiv(i8 %x, i8 %y) {
 
 define <2 x i8> @simplfy_srem_of_mul(<2 x i8> %x) {
 ; CHECK-LABEL: @simplfy_srem_of_mul(
-; CHECK-NEXT:    [[MUL:%.*]] = mul nsw <2 x i8> [[X:%.*]], <i8 20, i8 10>
-; CHECK-NEXT:    [[R:%.*]] = srem <2 x i8> [[MUL]], <i8 5, i8 5>
-; CHECK-NEXT:    ret <2 x i8> [[R]]
+; CHECK-NEXT:    ret <2 x i8> zeroinitializer
 ;
   %mul = mul nsw <2 x i8> %x, <i8 20, i8 10>
   %r = srem <2 x i8> %mul, <i8 5, i8 5>
@@ -513,9 +511,7 @@ define <2 x i8> @simplfy_srem_of_mul_fail_bad_mod(<2 x i8> %x) {
 
 define i8 @simplfy_urem_of_mul(i8 %x) {
 ; CHECK-LABEL: @simplfy_urem_of_mul(
-; CHECK-NEXT:    [[MUL:%.*]] = mul nuw i8 [[X:%.*]], 30
-; CHECK-NEXT:    [[R:%.*]] = urem i8 [[MUL]], 10
-; CHECK-NEXT:    ret i8 [[R]]
+; CHECK-NEXT:    ret i8 0
 ;
   %mul = mul nuw i8 %x, 30
   %r = urem i8 %mul, 10



More information about the llvm-commits mailing list