[llvm] [InstCombine] simplify `(X * C0) / (X * C1)` into `C0 / C1`. (PR #73204)
Yingwei Zheng via llvm-commits
llvm-commits at lists.llvm.org
Thu Dec 7 22:49:25 PST 2023
================
@@ -1207,6 +1207,48 @@ Instruction *InstCombinerImpl::commonIDivTransforms(BinaryOperator &I) {
}
}
+ // (X * Y) / (X * Z) --> Y / X (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) -> Instruction * {
+ auto OB1HasNSW = cast<OverflowingBinaryOperator>(Op1)->hasNoSignedWrap();
+ auto OB1HasNUW =
+ cast<OverflowingBinaryOperator>(Op1)->hasNoUnsignedWrap();
+ const APInt *C;
+ if (IsSigned && OB0HasNSW) {
+ if (OB1HasNSW && (match(B, m_APInt(C))) && (!C->isAllOnes()))
+ return BinaryOperator::CreateSDiv(A, B);
+ if (auto *SV = simplifySDivInst(A, B, /*IsExact*/ true,
+ SQ.getWithInstruction(&I))) {
+ if (auto *CV = dyn_cast<Constant>(SV);
+ CV && !(isa<PoisonValue>(CV) || CV->containsPoisonElement()))
+ if (match(B, m_APInt(C)) && !C->isSignMask())
+ return replaceInstUsesWith(I, SV);
+ }
+ }
+ if (!IsSigned && OB0HasNUW) {
+ if (OB1HasNUW)
+ return BinaryOperator::CreateUDiv(A, B);
+ if (auto *SV = simplifyUDivInst(A, B, /*IsExact*/ true,
+ SQ.getWithInstruction(&I)))
+ if (auto *CV = dyn_cast<Constant>(SV);
+ CV && !(isa<PoisonValue>(CV) || CV->containsPoisonElement()))
+ return replaceInstUsesWith(I, CV);
----------------
dtcxzyw wrote:
```suggestion
if (match(A, m_APInt(C1)) && match(B, m_APInt(C2))) {
APInt Q, R;
APInt::udivrem(*C1, *C2, Q, R);
if (R->isZero())
return replaceInstUsesWith(I, ConstantInt::get(A->getType(), Q));
}
```
https://github.com/llvm/llvm-project/pull/73204
More information about the llvm-commits
mailing list