[llvm] r219583 - InstCombine: Simplify commonIDivTransforms

David Majnemer david.majnemer at gmail.com
Sun Oct 12 01:34:24 PDT 2014


Author: majnemer
Date: Sun Oct 12 03:34:24 2014
New Revision: 219583

URL: http://llvm.org/viewvc/llvm-project?rev=219583&view=rev
Log:
InstCombine: Simplify commonIDivTransforms

A helper routine, MultiplyOverflows, was a less efficient
reimplementation of APInt's smul_ov and umul_ov.  While we are here,
clean up the code so it's more uniform.

No functionality change intended.

Modified:
    llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp

Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp?rev=219583&r1=219582&r2=219583&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp Sun Oct 12 03:34:24 2014
@@ -81,25 +81,15 @@ static Value *simplifyValueKnownNonZero(
 
 /// MultiplyOverflows - True if the multiply can not be expressed in an int
 /// this size.
-static bool MultiplyOverflows(ConstantInt *C1, ConstantInt *C2, bool sign) {
-  uint32_t W = C1->getBitWidth();
-  APInt LHSExt = C1->getValue(), RHSExt = C2->getValue();
-  if (sign) {
-    LHSExt = LHSExt.sext(W * 2);
-    RHSExt = RHSExt.sext(W * 2);
-  } else {
-    LHSExt = LHSExt.zext(W * 2);
-    RHSExt = RHSExt.zext(W * 2);
-  }
-
-  APInt MulExt = LHSExt * RHSExt;
-
-  if (!sign)
-    return MulExt.ugt(APInt::getLowBitsSet(W * 2, W));
+static bool MultiplyOverflows(const APInt &C1, const APInt &C2, APInt &Product,
+                              bool IsSigned) {
+  bool Overflow;
+  if (IsSigned)
+    Product = C1.smul_ov(C2, Overflow);
+  else
+    Product = C1.umul_ov(C2, Overflow);
 
-  APInt Min = APInt::getSignedMinValue(W).sext(W * 2);
-  APInt Max = APInt::getSignedMaxValue(W).sext(W * 2);
-  return MulExt.slt(Min) || MulExt.sgt(Max);
+  return Overflow;
 }
 
 /// \brief True if C2 is a multiple of C1. Quotient contains C2/C1.
@@ -722,83 +712,83 @@ Instruction *InstCombiner::commonIDivTra
   if (isa<SelectInst>(Op1) && SimplifyDivRemOfSelect(I))
     return &I;
 
-  if (ConstantInt *RHS = dyn_cast<ConstantInt>(Op1)) {
-    if (Instruction *LHS = dyn_cast<Instruction>(Op0)) {
+  if (Instruction *LHS = dyn_cast<Instruction>(Op0)) {
+    const APInt *C2;
+    if (match(Op1, m_APInt(C2))) {
+      Value *X;
+      const APInt *C1;
+      bool IsSigned = I.getOpcode() == Instruction::SDiv;
+
       // (X / C1) / C2  -> X / (C1*C2)
-      if (Instruction::BinaryOps(LHS->getOpcode()) == I.getOpcode())
-        if (ConstantInt *LHSRHS = dyn_cast<ConstantInt>(LHS->getOperand(1))) {
-          if (!MultiplyOverflows(RHS, LHSRHS,
-                                 I.getOpcode() == Instruction::SDiv))
-            return BinaryOperator::Create(I.getOpcode(), LHS->getOperand(0),
-                                          ConstantExpr::getMul(RHS, LHSRHS));
+      if ((IsSigned && match(LHS, m_SDiv(m_Value(X), m_APInt(C1)))) ||
+          (!IsSigned && match(LHS, m_UDiv(m_Value(X), m_APInt(C1))))) {
+        APInt Product(C1->getBitWidth(), /*Val=*/0ULL, IsSigned);
+        if (!MultiplyOverflows(*C1, *C2, Product, IsSigned))
+          return BinaryOperator::Create(I.getOpcode(), X,
+                                        ConstantInt::get(I.getType(), Product));
+      }
+
+      if ((IsSigned && match(LHS, m_NSWMul(m_Value(X), m_APInt(C1)))) ||
+          (!IsSigned && match(LHS, m_NUWMul(m_Value(X), m_APInt(C1))))) {
+        APInt Quotient(C1->getBitWidth(), /*Val=*/0ULL, IsSigned);
+
+        // (X * C1) / C2 -> X / (C2 / C1) if C2 is a multiple of C1.
+        if (IsMultiple(*C2, *C1, Quotient, IsSigned)) {
+          BinaryOperator *BO = BinaryOperator::Create(
+              I.getOpcode(), X, ConstantInt::get(X->getType(), Quotient));
+          BO->setIsExact(I.isExact());
+          return BO;
         }
 
-      Value *X;
-      const APInt *C1, *C2;
-      if (match(RHS, m_APInt(C2))) {
-        bool IsSigned = I.getOpcode() == Instruction::SDiv;
-        if ((IsSigned && match(LHS, m_NSWMul(m_Value(X), m_APInt(C1)))) ||
-            (!IsSigned && match(LHS, m_NUWMul(m_Value(X), m_APInt(C1))))) {
-          APInt Quotient(C1->getBitWidth(), /*Val=*/0ULL, IsSigned);
-
-          // (X * C1) / C2 -> X / (C2 / C1) if C2 is a multiple of C1.
-          if (IsMultiple(*C2, *C1, Quotient, IsSigned)) {
-            BinaryOperator *BO = BinaryOperator::Create(
-                I.getOpcode(), X, ConstantInt::get(X->getType(), Quotient));
-            BO->setIsExact(I.isExact());
-            return BO;
-          }
-
-          // (X * C1) / C2 -> X * (C1 / C2) if C1 is a multiple of C2.
-          if (IsMultiple(*C1, *C2, Quotient, IsSigned)) {
-            BinaryOperator *BO = BinaryOperator::Create(
-                Instruction::Mul, X, ConstantInt::get(X->getType(), Quotient));
-            BO->setHasNoUnsignedWrap(
-                !IsSigned &&
-                cast<OverflowingBinaryOperator>(LHS)->hasNoUnsignedWrap());
-            BO->setHasNoSignedWrap(
-                cast<OverflowingBinaryOperator>(LHS)->hasNoSignedWrap());
-            return BO;
-          }
+        // (X * C1) / C2 -> X * (C1 / C2) if C1 is a multiple of C2.
+        if (IsMultiple(*C1, *C2, Quotient, IsSigned)) {
+          BinaryOperator *BO = BinaryOperator::Create(
+              Instruction::Mul, X, ConstantInt::get(X->getType(), Quotient));
+          BO->setHasNoUnsignedWrap(
+              !IsSigned &&
+              cast<OverflowingBinaryOperator>(LHS)->hasNoUnsignedWrap());
+          BO->setHasNoSignedWrap(
+              cast<OverflowingBinaryOperator>(LHS)->hasNoSignedWrap());
+          return BO;
         }
+      }
 
-        if ((IsSigned && match(LHS, m_NSWShl(m_Value(X), m_APInt(C1))) &&
-             *C1 != C1->getBitWidth() - 1) ||
-            (!IsSigned && match(LHS, m_NUWShl(m_Value(X), m_APInt(C1))))) {
-          APInt Quotient(C1->getBitWidth(), /*Val=*/0ULL, IsSigned);
-          APInt C1Shifted = APInt::getOneBitSet(
-              C1->getBitWidth(), static_cast<unsigned>(C1->getLimitedValue()));
-
-          // (X << C1) / C2 -> X / (C2 >> C1) if C2 is a multiple of C1.
-          if (IsMultiple(*C2, C1Shifted, Quotient, IsSigned)) {
-            BinaryOperator *BO = BinaryOperator::Create(
-                I.getOpcode(), X, ConstantInt::get(X->getType(), Quotient));
-            BO->setIsExact(I.isExact());
-            return BO;
-          }
+      if ((IsSigned && match(LHS, m_NSWShl(m_Value(X), m_APInt(C1))) &&
+           *C1 != C1->getBitWidth() - 1) ||
+          (!IsSigned && match(LHS, m_NUWShl(m_Value(X), m_APInt(C1))))) {
+        APInt Quotient(C1->getBitWidth(), /*Val=*/0ULL, IsSigned);
+        APInt C1Shifted = APInt::getOneBitSet(
+            C1->getBitWidth(), static_cast<unsigned>(C1->getLimitedValue()));
+
+        // (X << C1) / C2 -> X / (C2 >> C1) if C2 is a multiple of C1.
+        if (IsMultiple(*C2, C1Shifted, Quotient, IsSigned)) {
+          BinaryOperator *BO = BinaryOperator::Create(
+              I.getOpcode(), X, ConstantInt::get(X->getType(), Quotient));
+          BO->setIsExact(I.isExact());
+          return BO;
+        }
 
-          // (X << C1) / C2 -> X * (C2 >> C1) if C1 is a multiple of C2.
-          if (IsMultiple(C1Shifted, *C2, Quotient, IsSigned)) {
-            BinaryOperator *BO = BinaryOperator::Create(
-                Instruction::Mul, X, ConstantInt::get(X->getType(), Quotient));
-            BO->setHasNoUnsignedWrap(
-                !IsSigned &&
-                cast<OverflowingBinaryOperator>(LHS)->hasNoUnsignedWrap());
-            BO->setHasNoSignedWrap(
-                cast<OverflowingBinaryOperator>(LHS)->hasNoSignedWrap());
-            return BO;
-          }
+        // (X << C1) / C2 -> X * (C2 >> C1) if C1 is a multiple of C2.
+        if (IsMultiple(C1Shifted, *C2, Quotient, IsSigned)) {
+          BinaryOperator *BO = BinaryOperator::Create(
+              Instruction::Mul, X, ConstantInt::get(X->getType(), Quotient));
+          BO->setHasNoUnsignedWrap(
+              !IsSigned &&
+              cast<OverflowingBinaryOperator>(LHS)->hasNoUnsignedWrap());
+          BO->setHasNoSignedWrap(
+              cast<OverflowingBinaryOperator>(LHS)->hasNoSignedWrap());
+          return BO;
         }
       }
-    }
 
-    if (!RHS->isZero()) { // avoid X udiv 0
-      if (SelectInst *SI = dyn_cast<SelectInst>(Op0))
-        if (Instruction *R = FoldOpIntoSelect(I, SI))
-          return R;
-      if (isa<PHINode>(Op0))
-        if (Instruction *NV = FoldOpIntoPhi(I))
-          return NV;
+      if (*C2 != 0) { // avoid X udiv 0
+        if (SelectInst *SI = dyn_cast<SelectInst>(Op0))
+          if (Instruction *R = FoldOpIntoSelect(I, SI))
+            return R;
+        if (isa<PHINode>(Op0))
+          if (Instruction *NV = FoldOpIntoPhi(I))
+            return NV;
+      }
     }
   }
 





More information about the llvm-commits mailing list