Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
wants to merge 2 commits into from

Conversation

AtariDreams
Copy link
Contributor

No description provided.

@llvmbot
Copy link
Collaborator

llvmbot commented Apr 10, 2024

@llvm/pr-subscribers-llvm-transforms

Author: AtariDreams (AtariDreams)

Changes

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

2 Files Affected:

  • (modified) llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp (+26)
  • (modified) llvm/test/Transforms/InstCombine/div.ll (+24)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
index 8c698e52b5a0e6..9e062aebc4a6e1 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -1149,6 +1149,32 @@ 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
+      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);
+
+          Instruction *Shift = BinaryOperator::CreateLShr(
+              Mul, ConstantInt::get(Ty, Q.logBase2()));
+          Shift->setIsExact(I.isExact());
+          return Shift;
+        }
+      }
     }
 
     if ((IsSigned && match(Op0, m_NSWShl(m_Value(X), m_APInt(C1))) &&
diff --git a/llvm/test/Transforms/InstCombine/div.ll b/llvm/test/Transforms/InstCombine/div.ll
index e8a25ff44d0296..0b8a9ba8009089 100644
--- a/llvm/test/Transforms/InstCombine/div.ll
+++ b/llvm/test/Transforms/InstCombine/div.ll
@@ -1638,6 +1638,30 @@ define i32 @sdiv_mul_sub_nsw(i32 %x, i32 %y) {
   ret i32 %d
 }
 
+  define i32 @mul_by_150_udiv_by_100 (i32 %0) {
+; CHECK-LABEL: @mul_by_150_udiv_by_100(
+; CHECK-NEXT:    [[TMP2:%.*]] = mul nuw nsw i32 [[TMP0:%.*]], 3
+; CHECK-NEXT:    [[TMP3:%.*]] = lshr i32 [[TMP2]], 1
+; CHECK-NEXT:    ret i32 [[TMP3]]
+;
+  %2 = mul nuw i32 %0, 150
+  %3 = udiv i32 %2, 100
+  ret i32 %3
+}
+
+;negative case, no nuw
+
+  define i32 @mul_by_150_sdiv_by_100 (i32 %0) {
+; CHECK-LABEL: @mul_by_150_sdiv_by_100(
+; CHECK-NEXT:    [[TMP2:%.*]] = mul nsw i32 [[TMP0:%.*]], 150
+; CHECK-NEXT:    [[TMP3:%.*]] = sdiv i32 [[TMP2]], 100
+; CHECK-NEXT:    ret i32 [[TMP3]]
+;
+  %2 = mul nsw i32 %0, 150
+  %3 = sdiv i32 %2, 100
+  ret i32 %3
+}
+
 define i32 @sdiv_mul_nsw_sub_nsw(i32 %x, i32 %y) {
 ; CHECK-LABEL: @sdiv_mul_nsw_sub_nsw(
 ; CHECK-NEXT:    ret i32 -1

@AtariDreams AtariDreams force-pushed the division branch 4 times, most recently from 6860d31 to f4c4644 Compare April 11, 2024 02:07
@AtariDreams AtariDreams marked this pull request as draft April 11, 2024 02:35
Copy link

github-actions bot commented Apr 11, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

@AtariDreams AtariDreams force-pushed the division branch 2 times, most recently from 3b8603a to 4ff0eb4 Compare April 13, 2024 21:13
@AtariDreams
Copy link
Contributor Author

Closed in favor of #92949

@AtariDreams AtariDreams deleted the division branch June 5, 2024 16:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants