[llvm] [InstCombine] Implemented missed optimization in muldivrem (PR #140916)
Kshitij Paranjape via llvm-commits
llvm-commits at lists.llvm.org
Mon May 26 00:38:29 PDT 2025
https://github.com/kshitijvp updated https://github.com/llvm/llvm-project/pull/140916
>From 3bf8f46d9a26ead3d203f8a04ff2c0dfa71ab6e0 Mon Sep 17 00:00:00 2001
From: Kshitij Paranjape <kshitijvparanjape at gmail.com>
Date: Wed, 21 May 2025 11:07:50 +0530
Subject: [PATCH 1/2] [InstCombine] Implemented missed optimization in
muldivrem
Added pattern matching condition in
InstCombineMulDivRem.cpp for the missed optimization.
Fixes #122442
---
.../Transforms/InstCombine/InstCombineMulDivRem.cpp | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
index c7023eb79b04e..26839d4cafb11 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -1258,7 +1258,9 @@ static Value *foldIDivShl(BinaryOperator &I, InstCombiner::BuilderTy &Builder) {
/// Common integer divide/remainder transforms
Instruction *InstCombinerImpl::commonIDivRemTransforms(BinaryOperator &I) {
assert(I.isIntDivRem() && "Unexpected instruction");
- Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
+ const APInt *C1, *C2;
+ Value *X;
+ Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1), *Op2 = I.getOperand(2);
// If any element of a constant divisor fixed width vector is zero or undef
// the behavior is undefined and we can fold the whole op to poison.
@@ -1295,6 +1297,14 @@ Instruction *InstCombinerImpl::commonIDivRemTransforms(BinaryOperator &I) {
/*FoldWithMultiUse*/ true))
return R;
}
+ if (match(Op0, m_OneUse(m_Intrinsic<Intrinsic::smul_fix>(m_APInt(C1), m_APInt(C2)))) &&
+ match(Op1, m_OneUse(m_URem(m_Value(X), Op0))) &&
+ match(Op2, m_OneUse(m_UDiv(Op1, m_APInt(C2))))) {
+
+ Value *XDivC2 = Builder.CreateUDiv(X, ConstantInt::get(X->getType(), *C2));
+ Value *Result = Builder.CreateURem(XDivC2, ConstantInt::get(X->getType(), *C1));
+ return replaceInstUsesWith(I, Result);
+}
return nullptr;
}
>From dd1cd5a115aab6431623a5fa1a1d3db0d854b365 Mon Sep 17 00:00:00 2001
From: Kshitij Paranjape <kshitijvparanjape at gmail.com>
Date: Mon, 26 May 2025 13:06:30 +0530
Subject: [PATCH 2/2] Implemented missed optimization in commonIDivTransforms
---
.../InstCombine/InstCombineMulDivRem.cpp | 21 +++++++++----------
1 file changed, 10 insertions(+), 11 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
index 26839d4cafb11..f8eb403249bcb 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -1258,9 +1258,7 @@ static Value *foldIDivShl(BinaryOperator &I, InstCombiner::BuilderTy &Builder) {
/// Common integer divide/remainder transforms
Instruction *InstCombinerImpl::commonIDivRemTransforms(BinaryOperator &I) {
assert(I.isIntDivRem() && "Unexpected instruction");
- const APInt *C1, *C2;
- Value *X;
- Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1), *Op2 = I.getOperand(2);
+ Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
// If any element of a constant divisor fixed width vector is zero or undef
// the behavior is undefined and we can fold the whole op to poison.
@@ -1297,14 +1295,6 @@ Instruction *InstCombinerImpl::commonIDivRemTransforms(BinaryOperator &I) {
/*FoldWithMultiUse*/ true))
return R;
}
- if (match(Op0, m_OneUse(m_Intrinsic<Intrinsic::smul_fix>(m_APInt(C1), m_APInt(C2)))) &&
- match(Op1, m_OneUse(m_URem(m_Value(X), Op0))) &&
- match(Op2, m_OneUse(m_UDiv(Op1, m_APInt(C2))))) {
-
- Value *XDivC2 = Builder.CreateUDiv(X, ConstantInt::get(X->getType(), *C2));
- Value *Result = Builder.CreateURem(XDivC2, ConstantInt::get(X->getType(), *C1));
- return replaceInstUsesWith(I, Result);
-}
return nullptr;
}
@@ -1326,6 +1316,15 @@ Instruction *InstCombinerImpl::commonIDivTransforms(BinaryOperator &I) {
Value *X;
const APInt *C1;
+ // (X mod(C1 *C2)/C2) -> (X/C2) mod(C1)
+ if ((IsSigned && match(Op0, m_SRem(m_Value(X), m_NSWMul(m_APInt(C1), m_APInt(C2))))) ||
+ (!IsSigned && match(Op0, m_URem(m_Value(X), m_NUWMul(m_APInt(C1), m_APInt(C2)))))) {
+ Value *XDivC2 = Builder.CreateUDiv(X, ConstantInt::get(X->getType(), *C2));
+ Value *Result = Builder.CreateURem(XDivC2, ConstantInt::get(X->getType(), *C1));
+
+ return replaceInstUsesWith(I, Result);
+ }
+
// (X / C1) / C2 -> X / (C1*C2)
if ((IsSigned && match(Op0, m_SDiv(m_Value(X), m_APInt(C1)))) ||
(!IsSigned && match(Op0, m_UDiv(m_Value(X), m_APInt(C1))))) {
More information about the llvm-commits
mailing list