[llvm] [InstCombine] Support division of numbers that can be converted to a shift (PR #88220)

via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 10 14:26:44 PDT 2024


================
@@ -1149,6 +1149,35 @@ Instruction *InstCombinerImpl::commonIDivTransforms(BinaryOperator &I) {
         Mul->setHasNoSignedWrap(OBO->hasNoSignedWrap());
         return Mul;
       }
+
+      // If we can reduce these functions so they can factor out to a shift or
+      // something similar Why not? i.e Reduce (X * 150/100) -> (X * 3) >> 1
+
+      // (X * C1)/C2 -> X * (C1/C3) >> log2(C2/C3) where C3 divides exactly C1
+      // and C2 and C2/C3 is a power of 2.
+      // This WILL require NUW, and if it is sdiv then it also requires NSW
+      if (Op0->hasOneUse() && C1->isStrictlyPositive() &&
+          C2->isStrictlyPositive()) {
+        APInt C3 = APIntOps::GreatestCommonDivisor(*C1, *C2);
+        APInt Q(C2->getBitWidth(), /*val=*/0ULL, IsSigned);
+
+        // Returns false if division by 0
+        if (isMultiple(*C2, C3, Q, IsSigned) && Q.isPowerOf2()) {
+          auto *OBO = cast<OverflowingBinaryOperator>(Op0);
+          if (OBO->hasNoUnsignedWrap() &&
+              (!IsSigned || OBO->hasNoSignedWrap())) {
+
+            APInt C4 = IsSigned ? C1->sdiv(C3) : C1->udiv(C3);
+            auto *Mul =
+                Builder.CreateMul(X, ConstantInt::get(Ty, C4), "", true, true);
----------------
goldsteinn wrote:

comment the `true, true`.

https://github.com/llvm/llvm-project/pull/88220


More information about the llvm-commits mailing list