[llvm] [InstCombine] simplify `(X * C0) / (X * C1)` into `C0 / C1`. (PR #73204)

Yingwei Zheng via llvm-commits llvm-commits at lists.llvm.org
Tue Dec 12 22:37:34 PST 2023


================
@@ -1207,6 +1207,47 @@ Instruction *InstCombinerImpl::commonIDivTransforms(BinaryOperator &I) {
     }
   }
 
+  // (X * Y) / (X * Z) --> Y / Z (and commuted variants)
+  if (match(Op0, m_Mul(m_Value(X), m_Value(Y)))) {
+    auto OB0HasNSW = cast<OverflowingBinaryOperator>(Op0)->hasNoSignedWrap();
+    auto OB0HasNUW = cast<OverflowingBinaryOperator>(Op0)->hasNoUnsignedWrap();
+
+    auto CreateDivOrNull = [&](Value *A, Value *B, Value *C) -> Instruction * {
+      auto OB1HasNSW = cast<OverflowingBinaryOperator>(Op1)->hasNoSignedWrap();
+      auto OB1HasNUW =
+          cast<OverflowingBinaryOperator>(Op1)->hasNoUnsignedWrap();
+      const APInt *C1, *C2;
+      if (IsSigned && OB0HasNSW) {
+        if (OB1HasNSW && match(B, m_APInt(C1)) && !C1->isAllOnes())
+          return BinaryOperator::CreateSDiv(A, B);
+        if (match(A, m_APInt(C1)) && match(B, m_APInt(C2)))
+          if (auto *V = simplifyMulInst(C, B, OB1HasNSW, OB1HasNUW,
+                                        SQ.getWithInstruction(&I))) {
+            const APInt *AV;
+            APInt Q, R;
+            APInt::sdivrem(*C1, *C2, Q, R);
+            if (match(V, m_APInt(AV)) && !AV->isSignMask() && R.isZero())
+              return replaceInstUsesWith(I, ConstantInt::get(A->getType(), Q));
+          }
+      }
+      if (!IsSigned && OB0HasNUW) {
+        if (OB1HasNUW)
+          return BinaryOperator::CreateUDiv(A, B);
+        if (match(A, m_APInt(C1)) && match(B, m_APInt(C2)) && C2->ule(*C1))
----------------
dtcxzyw wrote:

Could you please add a negative test?
```
define i4 @udiv_mul_nuw_mul_negative(i4 %a) {
  %add4 = mul i4 %a, 13
  %add5 = mul nuw i4 %a, 4
  %div = udiv i4 %add5, %add4
  ret i4 %div
}

```
Alive2: https://alive2.llvm.org/ce/z/K9Fann


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


More information about the llvm-commits mailing list