[llvm] [InstCombine] Reducing multiplications means we can have nsw and nuw tags. (PR #92980)

via llvm-commits llvm-commits at lists.llvm.org
Tue May 21 18:51:41 PDT 2024


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

>From 65feebd3717c002b7dede454e3e9db3d0614d1a6 Mon Sep 17 00:00:00 2001
From: Rose <gfunni234 at gmail.com>
Date: Tue, 21 May 2024 14:09:05 -0400
Subject: [PATCH] [InstCombine] Reducing multiplications means we can have nsw
 and nuw tags

Alive2 Proofs:
https://alive2.llvm.org/ce/z/-36zkQ
https://alive2.llvm.org/ce/z/H4vGV7
https://alive2.llvm.org/ce/z/aRosSr
https://alive2.llvm.org/ce/z/2wWpyv
https://alive2.llvm.org/ce/z/oMsBg9
https://alive2.llvm.org/ce/z/xnoYh_
---
 .../InstCombine/InstCombineMulDivRem.cpp      | 40 +++++++++++++++----
 llvm/test/Transforms/InstCombine/div.ll       |  2 +-
 2 files changed, 33 insertions(+), 9 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
index ca1b1921404d8..cceda67a45987 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -1057,8 +1057,11 @@ static Value *foldIDivShl(BinaryOperator &I, InstCombiner::BuilderTy &Builder) {
 
     // (X * Y) s/ (X << Z) --> Y s/ (1 << Z)
     if (IsSigned && HasNSW && (Op0->hasOneUse() || Op1->hasOneUse())) {
-      Value *Shl = Builder.CreateShl(ConstantInt::get(Ty, 1), Z);
-      return Builder.CreateSDiv(Y, Shl, "", I.isExact());
+      // These operands are intentionally swapped. See:
+      // https://alive2.llvm.org/ce/z/H4vGV7
+      Value *NewShl = Builder.CreateShl(ConstantInt::get(Ty, 1), Z, "", true,
+                                        Shl->hasNoUnsignedWrap());
+      return Builder.CreateSDiv(Y, NewShl, "", I.isExact());
     }
   }
 
@@ -1172,8 +1175,9 @@ Instruction *InstCombinerImpl::commonIDivTransforms(BinaryOperator &I) {
         auto *Mul = BinaryOperator::Create(Instruction::Mul, X,
                                            ConstantInt::get(Ty, Quotient));
         auto *OBO = cast<OverflowingBinaryOperator>(Op0);
-        Mul->setHasNoUnsignedWrap(!IsSigned && OBO->hasNoUnsignedWrap());
-        Mul->setHasNoSignedWrap(OBO->hasNoSignedWrap());
+        Mul->setHasNoUnsignedWrap(
+            !IsSigned || (OBO->hasNoUnsignedWrap() && OBO->hasNoSignedWrap()));
+        Mul->setHasNoSignedWrap(IsSigned || OBO->hasNoSignedWrap());
         return Mul;
       }
     }
@@ -1198,8 +1202,8 @@ Instruction *InstCombinerImpl::commonIDivTransforms(BinaryOperator &I) {
         auto *Mul = BinaryOperator::Create(Instruction::Mul, X,
                                            ConstantInt::get(Ty, Quotient));
         auto *OBO = cast<OverflowingBinaryOperator>(Op0);
-        Mul->setHasNoUnsignedWrap(!IsSigned && OBO->hasNoUnsignedWrap());
-        Mul->setHasNoSignedWrap(OBO->hasNoSignedWrap());
+        Mul->setHasNoUnsignedWrap(OBO->hasNoUnsignedWrap());
+        Mul->setHasNoSignedWrap(!IsSigned || OBO->hasNoSignedWrap());
         return Mul;
       }
     }
@@ -1273,17 +1277,37 @@ Instruction *InstCombinerImpl::commonIDivTransforms(BinaryOperator &I) {
   }
 
   // (X << Z) / (X * Y) -> (1 << Z) / Y
-  // TODO: Handle sdiv.
   if (!IsSigned && Op1->hasOneUse() &&
       match(Op0, m_NUWShl(m_Value(X), m_Value(Z))) &&
       match(Op1, m_c_Mul(m_Specific(X), m_Value(Y))))
     if (cast<OverflowingBinaryOperator>(Op1)->hasNoUnsignedWrap()) {
       Instruction *NewDiv = BinaryOperator::CreateUDiv(
-          Builder.CreateShl(ConstantInt::get(Ty, 1), Z, "", /*NUW*/ true), Y);
+          Builder.CreateShl(
+              ConstantInt::get(Ty, 1), Z, "", /*NUW*/ true,
+              /*NSW*/ cast<OverflowingBinaryOperator>(Op0)->hasNoSignedWrap()),
+          Y);
       NewDiv->setIsExact(I.isExact());
       return NewDiv;
     }
 
+  // (X << Z) / (X * Y) -> (1 << Z) / Y
+  if (IsSigned && Op1->hasOneUse() &&
+      match(Op0, m_NSWShl(m_Value(X), m_Value(Z))) &&
+      match(Op1, m_c_Mul(m_Specific(X), m_Value(Y))))
+    if (cast<OverflowingBinaryOperator>(Op1)->hasNoSignedWrap()) {
+      if (cast<OverflowingBinaryOperator>(Op0)->hasNoUnsignedWrap()) {
+        if (cast<OverflowingBinaryOperator>(Op1)->hasNoUnsignedWrap()) {
+          Instruction *NewDiv = BinaryOperator::CreateSDiv(
+              Builder.CreateShl(ConstantInt::get(Ty, 1), Z, "",
+                                /*NUW*/ true,
+                                /*NSW*/ true),
+              Y);
+          NewDiv->setIsExact(I.isExact());
+          return NewDiv;
+        }
+      }
+    }
+
   if (Value *R = foldIDivShl(I, Builder))
     return replaceInstUsesWith(I, R);
 
diff --git a/llvm/test/Transforms/InstCombine/div.ll b/llvm/test/Transforms/InstCombine/div.ll
index e8a25ff44d029..662d91b97a58d 100644
--- a/llvm/test/Transforms/InstCombine/div.ll
+++ b/llvm/test/Transforms/InstCombine/div.ll
@@ -380,7 +380,7 @@ define i32 @test26(i32 %a) {
 
 define i32 @test27(i32 %a) {
 ; CHECK-LABEL: @test27(
-; CHECK-NEXT:    [[DIV:%.*]] = shl nuw i32 [[A:%.*]], 1
+; CHECK-NEXT:    [[DIV:%.*]] = shl nuw nsw i32 [[A:%.*]], 1
 ; CHECK-NEXT:    ret i32 [[DIV]]
 ;
   %shl = shl nuw i32 %a, 2



More information about the llvm-commits mailing list