[llvm] [VPlan] Use parameter packs to avoid unary/binary/ternary matchers. NFC (PR #152272)
Luke Lau via llvm-commits
llvm-commits at lists.llvm.org
Wed Aug 6 05:55:06 PDT 2025
https://github.com/lukel97 updated https://github.com/llvm/llvm-project/pull/152272
>From 836f0f495aba4a2537e88f976f94a1491ae37d7d Mon Sep 17 00:00:00 2001
From: Luke Lau <luke at igalia.com>
Date: Wed, 6 Aug 2025 16:55:51 +0800
Subject: [PATCH 1/4] [VPlan] Use parameter packs for m_VPInstruction. NFC
Instead of defining unary/binary/ternary/4ary overloads of each matcher, we can use parameter packs to support arbitrary numbers of operands.
This allows us to remove some otherwise unused definitions like UnaryRecipe_match and TernaryRecipe_match.
We need to rewrite Recipe_match's constructor to use a parameter pack too, otherwise we end up with ambiguous overloads.
---
.../Transforms/Vectorize/VPlanPatternMatch.h | 97 ++++---------------
1 file changed, 20 insertions(+), 77 deletions(-)
diff --git a/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h b/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h
index d133610ef4f75..e6fee7a625efe 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h
+++ b/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h
@@ -200,15 +200,9 @@ template <typename Ops_t, unsigned Opcode, bool Commutative,
struct Recipe_match {
Ops_t Ops;
- Recipe_match() : Ops() {
- static_assert(std::tuple_size<Ops_t>::value == 0 &&
- "constructor can only be used with zero operands");
- }
- Recipe_match(Ops_t Ops) : Ops(Ops) {}
- template <typename A_t, typename B_t>
- Recipe_match(A_t A, B_t B) : Ops({A, B}) {
- static_assert(std::tuple_size<Ops_t>::value == 2 &&
- "constructor can only be used for binary matcher");
+ template <typename... OpTy> Recipe_match(OpTy... Ops) : Ops(Ops...) {
+ static_assert(std::tuple_size<Ops_t>::value == sizeof...(Ops) &&
+ "number of operands in constructor doesn't match Ops_t");
}
bool match(const VPValue *V) const {
@@ -274,42 +268,19 @@ template <unsigned Opcode, typename... RecipeTys>
using ZeroOpRecipe_match =
Recipe_match<std::tuple<>, Opcode, false, RecipeTys...>;
-template <typename Op0_t, unsigned Opcode, typename... RecipeTys>
-using UnaryRecipe_match =
- Recipe_match<std::tuple<Op0_t>, Opcode, false, RecipeTys...>;
-
-template <typename Op0_t, unsigned Opcode>
-using UnaryVPInstruction_match =
- UnaryRecipe_match<Op0_t, Opcode, VPInstruction>;
-
template <unsigned Opcode>
using ZeroOpVPInstruction_match = ZeroOpRecipe_match<Opcode, VPInstruction>;
template <typename Op0_t, unsigned Opcode>
using AllUnaryRecipe_match =
- UnaryRecipe_match<Op0_t, Opcode, VPWidenRecipe, VPReplicateRecipe,
- VPWidenCastRecipe, VPInstruction>;
+ Recipe_match<std::tuple<Op0_t>, Opcode, /*Commutative*/ false, VPWidenRecipe, VPReplicateRecipe,
+ VPWidenCastRecipe, VPInstruction>;
template <typename Op0_t, typename Op1_t, unsigned Opcode, bool Commutative,
typename... RecipeTys>
using BinaryRecipe_match =
Recipe_match<std::tuple<Op0_t, Op1_t>, Opcode, Commutative, RecipeTys...>;
-template <typename Op0_t, typename Op1_t, unsigned Opcode>
-using BinaryVPInstruction_match =
- BinaryRecipe_match<Op0_t, Op1_t, Opcode, /*Commutative*/ false,
- VPInstruction>;
-
-template <typename Op0_t, typename Op1_t, typename Op2_t, unsigned Opcode,
- bool Commutative, typename... RecipeTys>
-using TernaryRecipe_match = Recipe_match<std::tuple<Op0_t, Op1_t, Op2_t>,
- Opcode, Commutative, RecipeTys...>;
-
-template <typename Op0_t, typename Op1_t, typename Op2_t, unsigned Opcode>
-using TernaryVPInstruction_match =
- TernaryRecipe_match<Op0_t, Op1_t, Op2_t, Opcode, /*Commutative*/ false,
- VPInstruction>;
-
template <typename Op0_t, typename Op1_t, unsigned Opcode,
bool Commutative = false>
using AllBinaryRecipe_match =
@@ -322,70 +293,42 @@ inline ZeroOpVPInstruction_match<VPInstruction::BuildVector> m_BuildVector() {
return ZeroOpVPInstruction_match<VPInstruction::BuildVector>();
}
-template <unsigned Opcode, typename Op0_t>
-inline UnaryVPInstruction_match<Op0_t, Opcode>
-m_VPInstruction(const Op0_t &Op0) {
- return UnaryVPInstruction_match<Op0_t, Opcode>(Op0);
-}
+template <unsigned Opcode, typename... OpTys>
+using VPInstruction_match =
+ Recipe_match<std::tuple<OpTys...>, Opcode, /*Commutative*/ false, VPInstruction>;
-template <unsigned Opcode, typename Op0_t, typename Op1_t>
-inline BinaryVPInstruction_match<Op0_t, Op1_t, Opcode>
-m_VPInstruction(const Op0_t &Op0, const Op1_t &Op1) {
- return BinaryVPInstruction_match<Op0_t, Op1_t, Opcode>(Op0, Op1);
+template <unsigned Opcode, typename... OpTys>
+inline VPInstruction_match<Opcode, OpTys...>
+m_VPInstruction(const OpTys &... Ops) {
+ return VPInstruction_match<Opcode, OpTys...>(Ops...);
}
-template <unsigned Opcode, typename Op0_t, typename Op1_t, typename Op2_t>
-inline TernaryVPInstruction_match<Op0_t, Op1_t, Op2_t, Opcode>
-m_VPInstruction(const Op0_t &Op0, const Op1_t &Op1, const Op2_t &Op2) {
- return TernaryVPInstruction_match<Op0_t, Op1_t, Op2_t, Opcode>(
- {Op0, Op1, Op2});
-}
-
-template <typename Op0_t, typename Op1_t, typename Op2_t, typename Op3_t,
- unsigned Opcode, bool Commutative, typename... RecipeTys>
-using Recipe4Op_match = Recipe_match<std::tuple<Op0_t, Op1_t, Op2_t, Op3_t>,
- Opcode, Commutative, RecipeTys...>;
-
-template <typename Op0_t, typename Op1_t, typename Op2_t, typename Op3_t,
- unsigned Opcode>
-using VPInstruction4Op_match =
- Recipe4Op_match<Op0_t, Op1_t, Op2_t, Op3_t, Opcode, /*Commutative*/ false,
- VPInstruction>;
-
-template <unsigned Opcode, typename Op0_t, typename Op1_t, typename Op2_t,
- typename Op3_t>
-inline VPInstruction4Op_match<Op0_t, Op1_t, Op2_t, Op3_t, Opcode>
-m_VPInstruction(const Op0_t &Op0, const Op1_t &Op1, const Op2_t &Op2,
- const Op3_t &Op3) {
- return VPInstruction4Op_match<Op0_t, Op1_t, Op2_t, Op3_t, Opcode>(
- {Op0, Op1, Op2, Op3});
-}
template <typename Op0_t>
-inline UnaryVPInstruction_match<Op0_t, Instruction::Freeze>
+inline VPInstruction_match<Instruction::Freeze, Op0_t>
m_Freeze(const Op0_t &Op0) {
return m_VPInstruction<Instruction::Freeze>(Op0);
}
template <typename Op0_t>
-inline UnaryVPInstruction_match<Op0_t, VPInstruction::BranchOnCond>
+inline VPInstruction_match<VPInstruction::BranchOnCond, Op0_t>
m_BranchOnCond(const Op0_t &Op0) {
return m_VPInstruction<VPInstruction::BranchOnCond>(Op0);
}
template <typename Op0_t>
-inline UnaryVPInstruction_match<Op0_t, VPInstruction::Broadcast>
+inline VPInstruction_match<VPInstruction::Broadcast, Op0_t>
m_Broadcast(const Op0_t &Op0) {
return m_VPInstruction<VPInstruction::Broadcast>(Op0);
}
template <typename Op0_t, typename Op1_t>
-inline BinaryVPInstruction_match<Op0_t, Op1_t, VPInstruction::ActiveLaneMask>
+inline VPInstruction_match<VPInstruction::ActiveLaneMask, Op0_t, Op1_t>
m_ActiveLaneMask(const Op0_t &Op0, const Op1_t &Op1) {
return m_VPInstruction<VPInstruction::ActiveLaneMask>(Op0, Op1);
}
template <typename Op0_t, typename Op1_t>
-inline BinaryVPInstruction_match<Op0_t, Op1_t, VPInstruction::BranchOnCount>
+inline VPInstruction_match<VPInstruction::BranchOnCount, Op0_t, Op1_t>
m_BranchOnCount(const Op0_t &Op0, const Op1_t &Op1) {
return m_VPInstruction<VPInstruction::BranchOnCount>(Op0, Op1);
}
@@ -486,7 +429,7 @@ m_Select(const Op0_t &Op0, const Op1_t &Op1, const Op2_t &Op2) {
}
template <typename Op0_t>
-inline match_combine_or<UnaryVPInstruction_match<Op0_t, VPInstruction::Not>,
+inline match_combine_or<VPInstruction_match<VPInstruction::Not, Op0_t>,
AllBinaryRecipe_match<int_pred_ty<is_all_ones>, Op0_t,
Instruction::Xor, true>>
m_Not(const Op0_t &Op0) {
@@ -496,7 +439,7 @@ m_Not(const Op0_t &Op0) {
template <typename Op0_t, typename Op1_t>
inline match_combine_or<
- BinaryVPInstruction_match<Op0_t, Op1_t, VPInstruction::LogicalAnd>,
+ VPInstruction_match<VPInstruction::LogicalAnd, Op0_t, Op1_t>,
AllTernaryRecipe_match<Op0_t, Op1_t, specific_intval<1>,
Instruction::Select>>
m_LogicalAnd(const Op0_t &Op0, const Op1_t &Op1) {
@@ -514,7 +457,7 @@ m_LogicalOr(const Op0_t &Op0, const Op1_t &Op1) {
template <typename Op0_t, typename Op1_t, typename Op2_t>
using VPScalarIVSteps_match =
- TernaryRecipe_match<Op0_t, Op1_t, Op2_t, 0, false, VPScalarIVStepsRecipe>;
+ Recipe_match<std::tuple<Op0_t, Op1_t, Op2_t>, 0, false, VPScalarIVStepsRecipe>;
template <typename Op0_t, typename Op1_t, typename Op2_t>
inline VPScalarIVSteps_match<Op0_t, Op1_t, Op2_t>
>From 5171b12633e02cb4491792a181b22521be488202 Mon Sep 17 00:00:00 2001
From: Luke Lau <luke at igalia.com>
Date: Wed, 6 Aug 2025 17:16:56 +0800
Subject: [PATCH 2/4] clang-format
---
llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h b/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h
index e6fee7a625efe..6e837175bee49 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h
+++ b/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h
@@ -273,8 +273,9 @@ using ZeroOpVPInstruction_match = ZeroOpRecipe_match<Opcode, VPInstruction>;
template <typename Op0_t, unsigned Opcode>
using AllUnaryRecipe_match =
- Recipe_match<std::tuple<Op0_t>, Opcode, /*Commutative*/ false, VPWidenRecipe, VPReplicateRecipe,
- VPWidenCastRecipe, VPInstruction>;
+ Recipe_match<std::tuple<Op0_t>, Opcode, /*Commutative*/ false,
+ VPWidenRecipe, VPReplicateRecipe, VPWidenCastRecipe,
+ VPInstruction>;
template <typename Op0_t, typename Op1_t, unsigned Opcode, bool Commutative,
typename... RecipeTys>
@@ -294,12 +295,12 @@ inline ZeroOpVPInstruction_match<VPInstruction::BuildVector> m_BuildVector() {
}
template <unsigned Opcode, typename... OpTys>
-using VPInstruction_match =
- Recipe_match<std::tuple<OpTys...>, Opcode, /*Commutative*/ false, VPInstruction>;
+using VPInstruction_match = Recipe_match<std::tuple<OpTys...>, Opcode,
+ /*Commutative*/ false, VPInstruction>;
template <unsigned Opcode, typename... OpTys>
inline VPInstruction_match<Opcode, OpTys...>
-m_VPInstruction(const OpTys &... Ops) {
+m_VPInstruction(const OpTys &...Ops) {
return VPInstruction_match<Opcode, OpTys...>(Ops...);
}
@@ -456,8 +457,8 @@ m_LogicalOr(const Op0_t &Op0, const Op1_t &Op1) {
}
template <typename Op0_t, typename Op1_t, typename Op2_t>
-using VPScalarIVSteps_match =
- Recipe_match<std::tuple<Op0_t, Op1_t, Op2_t>, 0, false, VPScalarIVStepsRecipe>;
+using VPScalarIVSteps_match = Recipe_match<std::tuple<Op0_t, Op1_t, Op2_t>, 0,
+ false, VPScalarIVStepsRecipe>;
template <typename Op0_t, typename Op1_t, typename Op2_t>
inline VPScalarIVSteps_match<Op0_t, Op1_t, Op2_t>
>From 7c860258e6c99ec55c74d3c97807dd3478df673b Mon Sep 17 00:00:00 2001
From: Luke Lau <luke at igalia.com>
Date: Wed, 6 Aug 2025 18:36:58 +0800
Subject: [PATCH 3/4] Remove unary/binary/ternary recipe matchers
---
.../Transforms/Vectorize/VPlanPatternMatch.h | 104 +++++++-----------
1 file changed, 40 insertions(+), 64 deletions(-)
diff --git a/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h b/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h
index 6e837175bee49..c82fdfc3af554 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h
+++ b/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h
@@ -248,7 +248,6 @@ struct Recipe_match {
// Check for recipes that do not have opcodes.
if constexpr (std::is_same<RecipeTy, VPScalarIVStepsRecipe>::value ||
std::is_same<RecipeTy, VPCanonicalIVPHIRecipe>::value ||
- std::is_same<RecipeTy, VPWidenSelectRecipe>::value ||
std::is_same<RecipeTy, VPDerivedIVRecipe>::value ||
std::is_same<RecipeTy, VPWidenGEPRecipe>::value)
return DefR;
@@ -264,35 +263,11 @@ struct Recipe_match {
}
};
-template <unsigned Opcode, typename... RecipeTys>
-using ZeroOpRecipe_match =
- Recipe_match<std::tuple<>, Opcode, false, RecipeTys...>;
-
-template <unsigned Opcode>
-using ZeroOpVPInstruction_match = ZeroOpRecipe_match<Opcode, VPInstruction>;
-
-template <typename Op0_t, unsigned Opcode>
-using AllUnaryRecipe_match =
- Recipe_match<std::tuple<Op0_t>, Opcode, /*Commutative*/ false,
- VPWidenRecipe, VPReplicateRecipe, VPWidenCastRecipe,
- VPInstruction>;
-
-template <typename Op0_t, typename Op1_t, unsigned Opcode, bool Commutative,
- typename... RecipeTys>
-using BinaryRecipe_match =
- Recipe_match<std::tuple<Op0_t, Op1_t>, Opcode, Commutative, RecipeTys...>;
-
-template <typename Op0_t, typename Op1_t, unsigned Opcode,
- bool Commutative = false>
-using AllBinaryRecipe_match =
- BinaryRecipe_match<Op0_t, Op1_t, Opcode, Commutative, VPWidenRecipe,
- VPReplicateRecipe, VPWidenCastRecipe, VPInstruction>;
-
-/// BuildVector is matches only its opcode, w/o matching its operands as the
-/// number of operands is not fixed.
-inline ZeroOpVPInstruction_match<VPInstruction::BuildVector> m_BuildVector() {
- return ZeroOpVPInstruction_match<VPInstruction::BuildVector>();
-}
+template <unsigned Opcode, bool Commutative = false, typename... OpTys>
+using AllRecipe_match =
+ Recipe_match<std::tuple<OpTys...>, Opcode, Commutative, VPWidenRecipe,
+ VPReplicateRecipe, VPWidenCastRecipe, VPInstruction,
+ VPWidenSelectRecipe>;
template <unsigned Opcode, typename... OpTys>
using VPInstruction_match = Recipe_match<std::tuple<OpTys...>, Opcode,
@@ -304,6 +279,12 @@ m_VPInstruction(const OpTys &...Ops) {
return VPInstruction_match<Opcode, OpTys...>(Ops...);
}
+/// BuildVector is matches only its opcode, w/o matching its operands as the
+/// number of operands is not fixed.
+inline VPInstruction_match<VPInstruction::BuildVector> m_BuildVector() {
+ return m_VPInstruction<VPInstruction::BuildVector>();
+}
+
template <typename Op0_t>
inline VPInstruction_match<Instruction::Freeze, Op0_t>
m_Freeze(const Op0_t &Op0) {
@@ -335,55 +316,56 @@ m_BranchOnCount(const Op0_t &Op0, const Op1_t &Op1) {
}
template <unsigned Opcode, typename Op0_t>
-inline AllUnaryRecipe_match<Op0_t, Opcode> m_Unary(const Op0_t &Op0) {
- return AllUnaryRecipe_match<Op0_t, Opcode>(Op0);
+inline AllRecipe_match<Opcode, false, Op0_t> m_Unary(const Op0_t &Op0) {
+ return AllRecipe_match<Opcode, false, Op0_t>(Op0);
}
template <typename Op0_t>
-inline AllUnaryRecipe_match<Op0_t, Instruction::Trunc>
+inline AllRecipe_match<Instruction::Trunc, false, Op0_t>
m_Trunc(const Op0_t &Op0) {
return m_Unary<Instruction::Trunc, Op0_t>(Op0);
}
template <typename Op0_t>
-inline AllUnaryRecipe_match<Op0_t, Instruction::ZExt> m_ZExt(const Op0_t &Op0) {
+inline AllRecipe_match<Instruction::ZExt, false, Op0_t>
+m_ZExt(const Op0_t &Op0) {
return m_Unary<Instruction::ZExt, Op0_t>(Op0);
}
template <typename Op0_t>
-inline AllUnaryRecipe_match<Op0_t, Instruction::SExt> m_SExt(const Op0_t &Op0) {
+inline AllRecipe_match<Instruction::SExt, false, Op0_t>
+m_SExt(const Op0_t &Op0) {
return m_Unary<Instruction::SExt, Op0_t>(Op0);
}
template <typename Op0_t>
-inline match_combine_or<AllUnaryRecipe_match<Op0_t, Instruction::ZExt>,
- AllUnaryRecipe_match<Op0_t, Instruction::SExt>>
+inline match_combine_or<AllRecipe_match<Instruction::ZExt, false, Op0_t>,
+ AllRecipe_match<Instruction::SExt, false, Op0_t>>
m_ZExtOrSExt(const Op0_t &Op0) {
return m_CombineOr(m_ZExt(Op0), m_SExt(Op0));
}
template <unsigned Opcode, typename Op0_t, typename Op1_t,
bool Commutative = false>
-inline AllBinaryRecipe_match<Op0_t, Op1_t, Opcode, Commutative>
+inline AllRecipe_match<Opcode, Commutative, Op0_t, Op1_t>
m_Binary(const Op0_t &Op0, const Op1_t &Op1) {
- return AllBinaryRecipe_match<Op0_t, Op1_t, Opcode, Commutative>(Op0, Op1);
+ return AllRecipe_match<Opcode, Commutative, Op0_t, Op1_t>(Op0, Op1);
}
template <unsigned Opcode, typename Op0_t, typename Op1_t>
-inline AllBinaryRecipe_match<Op0_t, Op1_t, Opcode, true>
+inline AllRecipe_match<Opcode, /*Commutative*/ true, Op0_t, Op1_t>
m_c_Binary(const Op0_t &Op0, const Op1_t &Op1) {
- return AllBinaryRecipe_match<Op0_t, Op1_t, Opcode, true>(Op0, Op1);
+ return AllRecipe_match<Opcode, true, Op0_t, Op1_t>(Op0, Op1);
}
template <typename Op0_t, typename Op1_t>
-inline AllBinaryRecipe_match<Op0_t, Op1_t, Instruction::Mul>
+inline AllRecipe_match<Instruction::Mul, /*Commutative*/ false, Op0_t, Op1_t>
m_Mul(const Op0_t &Op0, const Op1_t &Op1) {
return m_Binary<Instruction::Mul, Op0_t, Op1_t>(Op0, Op1);
}
template <typename Op0_t, typename Op1_t>
-inline AllBinaryRecipe_match<Op0_t, Op1_t, Instruction::Mul,
- /* Commutative =*/true>
+inline AllRecipe_match<Instruction::Mul, /*Commutative*/ true, Op0_t, Op1_t>
m_c_Mul(const Op0_t &Op0, const Op1_t &Op1) {
return m_Binary<Instruction::Mul, Op0_t, Op1_t, true>(Op0, Op1);
}
@@ -393,23 +375,22 @@ m_c_Mul(const Op0_t &Op0, const Op1_t &Op1) {
/// IR-based pattern matching infrastructure. Use m_c_BinaryOr for a commutative
/// version of the matcher.
template <typename Op0_t, typename Op1_t, bool Commutative = false>
-inline AllBinaryRecipe_match<Op0_t, Op1_t, Instruction::Or, Commutative>
+inline AllRecipe_match<Instruction::Or, Commutative, Op0_t, Op1_t>
m_BinaryOr(const Op0_t &Op0, const Op1_t &Op1) {
return m_Binary<Instruction::Or, Op0_t, Op1_t, Commutative>(Op0, Op1);
}
template <typename Op0_t, typename Op1_t>
-inline AllBinaryRecipe_match<Op0_t, Op1_t, Instruction::Or,
- /*Commutative*/ true>
+inline AllRecipe_match<Instruction::Or, /*Commutative*/ true, Op0_t, Op1_t>
m_c_BinaryOr(const Op0_t &Op0, const Op1_t &Op1) {
return m_BinaryOr<Op0_t, Op1_t, /*Commutative*/ true>(Op0, Op1);
}
template <typename Op0_t, typename Op1_t>
using GEPLikeRecipe_match =
- BinaryRecipe_match<Op0_t, Op1_t, Instruction::GetElementPtr, false,
- VPWidenRecipe, VPReplicateRecipe, VPWidenGEPRecipe,
- VPInstruction>;
+ Recipe_match<std::tuple<Op0_t, Op1_t>, Instruction::GetElementPtr, false,
+ VPWidenRecipe, VPReplicateRecipe, VPWidenGEPRecipe,
+ VPInstruction>;
template <typename Op0_t, typename Op1_t>
inline GEPLikeRecipe_match<Op0_t, Op1_t> m_GetElementPtr(const Op0_t &Op0,
@@ -417,22 +398,17 @@ inline GEPLikeRecipe_match<Op0_t, Op1_t> m_GetElementPtr(const Op0_t &Op0,
return GEPLikeRecipe_match<Op0_t, Op1_t>(Op0, Op1);
}
-template <typename Op0_t, typename Op1_t, typename Op2_t, unsigned Opcode>
-using AllTernaryRecipe_match =
- Recipe_match<std::tuple<Op0_t, Op1_t, Op2_t>, Opcode, false,
- VPReplicateRecipe, VPInstruction, VPWidenSelectRecipe>;
-
template <typename Op0_t, typename Op1_t, typename Op2_t>
-inline AllTernaryRecipe_match<Op0_t, Op1_t, Op2_t, Instruction::Select>
+inline AllRecipe_match<Instruction::Select, false, Op0_t, Op1_t, Op2_t>
m_Select(const Op0_t &Op0, const Op1_t &Op1, const Op2_t &Op2) {
- return AllTernaryRecipe_match<Op0_t, Op1_t, Op2_t, Instruction::Select>(
+ return AllRecipe_match<Instruction::Select, false, Op0_t, Op1_t, Op2_t>(
{Op0, Op1, Op2});
}
template <typename Op0_t>
-inline match_combine_or<VPInstruction_match<VPInstruction::Not, Op0_t>,
- AllBinaryRecipe_match<int_pred_ty<is_all_ones>, Op0_t,
- Instruction::Xor, true>>
+inline match_combine_or<
+ VPInstruction_match<VPInstruction::Not, Op0_t>,
+ AllRecipe_match<Instruction::Xor, true, int_pred_ty<is_all_ones>, Op0_t>>
m_Not(const Op0_t &Op0) {
return m_CombineOr(m_VPInstruction<VPInstruction::Not>(Op0),
m_c_Binary<Instruction::Xor>(m_AllOnes(), Op0));
@@ -441,8 +417,8 @@ m_Not(const Op0_t &Op0) {
template <typename Op0_t, typename Op1_t>
inline match_combine_or<
VPInstruction_match<VPInstruction::LogicalAnd, Op0_t, Op1_t>,
- AllTernaryRecipe_match<Op0_t, Op1_t, specific_intval<1>,
- Instruction::Select>>
+ AllRecipe_match<Instruction::Select, false, Op0_t, Op1_t,
+ specific_intval<1>>>
m_LogicalAnd(const Op0_t &Op0, const Op1_t &Op1) {
return m_CombineOr(
m_VPInstruction<VPInstruction::LogicalAnd, Op0_t, Op1_t>(Op0, Op1),
@@ -450,8 +426,8 @@ m_LogicalAnd(const Op0_t &Op0, const Op1_t &Op1) {
}
template <typename Op0_t, typename Op1_t>
-inline AllTernaryRecipe_match<Op0_t, specific_intval<1>, Op1_t,
- Instruction::Select>
+inline AllRecipe_match<Instruction::Select, false, Op0_t, specific_intval<1>,
+ Op1_t>
m_LogicalOr(const Op0_t &Op0, const Op1_t &Op1) {
return m_Select(Op0, m_True(), Op1);
}
>From 9d4ab2b654077194cf579f362383ee92b09d7ea5 Mon Sep 17 00:00:00 2001
From: Luke Lau <luke at igalia.com>
Date: Wed, 6 Aug 2025 20:54:26 +0800
Subject: [PATCH 4/4] Add AllRecipes_commutative_match, remove commutative
template argument
---
.../Transforms/Vectorize/VPlanPatternMatch.h | 75 ++++++++++---------
1 file changed, 38 insertions(+), 37 deletions(-)
diff --git a/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h b/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h
index c82fdfc3af554..015770ec16c4c 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h
+++ b/llvm/lib/Transforms/Vectorize/VPlanPatternMatch.h
@@ -203,6 +203,8 @@ struct Recipe_match {
template <typename... OpTy> Recipe_match(OpTy... Ops) : Ops(Ops...) {
static_assert(std::tuple_size<Ops_t>::value == sizeof...(Ops) &&
"number of operands in constructor doesn't match Ops_t");
+ static_assert(!(Commutative && std::tuple_size<Ops_t>::value != 2) &&
+ "only binary ops can be commutative");
}
bool match(const VPValue *V) const {
@@ -263,12 +265,17 @@ struct Recipe_match {
}
};
-template <unsigned Opcode, bool Commutative = false, typename... OpTys>
+template <unsigned Opcode, typename... OpTys>
using AllRecipe_match =
- Recipe_match<std::tuple<OpTys...>, Opcode, Commutative, VPWidenRecipe,
+ Recipe_match<std::tuple<OpTys...>, Opcode, false, VPWidenRecipe,
VPReplicateRecipe, VPWidenCastRecipe, VPInstruction,
VPWidenSelectRecipe>;
+template <unsigned Opcode, typename... OpTys>
+using AllRecipe_commutative_match =
+ Recipe_match<std::tuple<OpTys...>, Opcode, true, VPWidenRecipe,
+ VPReplicateRecipe, VPInstruction>;
+
template <unsigned Opcode, typename... OpTys>
using VPInstruction_match = Recipe_match<std::tuple<OpTys...>, Opcode,
/*Commutative*/ false, VPInstruction>;
@@ -316,74 +323,70 @@ m_BranchOnCount(const Op0_t &Op0, const Op1_t &Op1) {
}
template <unsigned Opcode, typename Op0_t>
-inline AllRecipe_match<Opcode, false, Op0_t> m_Unary(const Op0_t &Op0) {
- return AllRecipe_match<Opcode, false, Op0_t>(Op0);
+inline AllRecipe_match<Opcode, Op0_t> m_Unary(const Op0_t &Op0) {
+ return AllRecipe_match<Opcode, Op0_t>(Op0);
}
template <typename Op0_t>
-inline AllRecipe_match<Instruction::Trunc, false, Op0_t>
-m_Trunc(const Op0_t &Op0) {
+inline AllRecipe_match<Instruction::Trunc, Op0_t> m_Trunc(const Op0_t &Op0) {
return m_Unary<Instruction::Trunc, Op0_t>(Op0);
}
template <typename Op0_t>
-inline AllRecipe_match<Instruction::ZExt, false, Op0_t>
-m_ZExt(const Op0_t &Op0) {
+inline AllRecipe_match<Instruction::ZExt, Op0_t> m_ZExt(const Op0_t &Op0) {
return m_Unary<Instruction::ZExt, Op0_t>(Op0);
}
template <typename Op0_t>
-inline AllRecipe_match<Instruction::SExt, false, Op0_t>
-m_SExt(const Op0_t &Op0) {
+inline AllRecipe_match<Instruction::SExt, Op0_t> m_SExt(const Op0_t &Op0) {
return m_Unary<Instruction::SExt, Op0_t>(Op0);
}
template <typename Op0_t>
-inline match_combine_or<AllRecipe_match<Instruction::ZExt, false, Op0_t>,
- AllRecipe_match<Instruction::SExt, false, Op0_t>>
+inline match_combine_or<AllRecipe_match<Instruction::ZExt, Op0_t>,
+ AllRecipe_match<Instruction::SExt, Op0_t>>
m_ZExtOrSExt(const Op0_t &Op0) {
return m_CombineOr(m_ZExt(Op0), m_SExt(Op0));
}
-template <unsigned Opcode, typename Op0_t, typename Op1_t,
- bool Commutative = false>
-inline AllRecipe_match<Opcode, Commutative, Op0_t, Op1_t>
-m_Binary(const Op0_t &Op0, const Op1_t &Op1) {
- return AllRecipe_match<Opcode, Commutative, Op0_t, Op1_t>(Op0, Op1);
+template <unsigned Opcode, typename Op0_t, typename Op1_t>
+inline AllRecipe_match<Opcode, Op0_t, Op1_t> m_Binary(const Op0_t &Op0,
+ const Op1_t &Op1) {
+ return AllRecipe_match<Opcode, Op0_t, Op1_t>(Op0, Op1);
}
template <unsigned Opcode, typename Op0_t, typename Op1_t>
-inline AllRecipe_match<Opcode, /*Commutative*/ true, Op0_t, Op1_t>
+inline AllRecipe_commutative_match<Opcode, Op0_t, Op1_t>
m_c_Binary(const Op0_t &Op0, const Op1_t &Op1) {
- return AllRecipe_match<Opcode, true, Op0_t, Op1_t>(Op0, Op1);
+ return AllRecipe_commutative_match<Opcode, Op0_t, Op1_t>(Op0, Op1);
}
template <typename Op0_t, typename Op1_t>
-inline AllRecipe_match<Instruction::Mul, /*Commutative*/ false, Op0_t, Op1_t>
-m_Mul(const Op0_t &Op0, const Op1_t &Op1) {
+inline AllRecipe_match<Instruction::Mul, Op0_t, Op1_t> m_Mul(const Op0_t &Op0,
+ const Op1_t &Op1) {
return m_Binary<Instruction::Mul, Op0_t, Op1_t>(Op0, Op1);
}
template <typename Op0_t, typename Op1_t>
-inline AllRecipe_match<Instruction::Mul, /*Commutative*/ true, Op0_t, Op1_t>
+inline AllRecipe_commutative_match<Instruction::Mul, Op0_t, Op1_t>
m_c_Mul(const Op0_t &Op0, const Op1_t &Op1) {
- return m_Binary<Instruction::Mul, Op0_t, Op1_t, true>(Op0, Op1);
+ return m_c_Binary<Instruction::Mul, Op0_t, Op1_t>(Op0, Op1);
}
/// Match a binary OR operation. Note that while conceptually the operands can
/// be matched commutatively, \p Commutative defaults to false in line with the
/// IR-based pattern matching infrastructure. Use m_c_BinaryOr for a commutative
/// version of the matcher.
-template <typename Op0_t, typename Op1_t, bool Commutative = false>
-inline AllRecipe_match<Instruction::Or, Commutative, Op0_t, Op1_t>
+template <typename Op0_t, typename Op1_t>
+inline AllRecipe_match<Instruction::Or, Op0_t, Op1_t>
m_BinaryOr(const Op0_t &Op0, const Op1_t &Op1) {
- return m_Binary<Instruction::Or, Op0_t, Op1_t, Commutative>(Op0, Op1);
+ return m_Binary<Instruction::Or, Op0_t, Op1_t>(Op0, Op1);
}
template <typename Op0_t, typename Op1_t>
-inline AllRecipe_match<Instruction::Or, /*Commutative*/ true, Op0_t, Op1_t>
+inline AllRecipe_commutative_match<Instruction::Or, Op0_t, Op1_t>
m_c_BinaryOr(const Op0_t &Op0, const Op1_t &Op1) {
- return m_BinaryOr<Op0_t, Op1_t, /*Commutative*/ true>(Op0, Op1);
+ return m_c_Binary<Instruction::Or, Op0_t, Op1_t>(Op0, Op1);
}
template <typename Op0_t, typename Op1_t>
@@ -399,16 +402,16 @@ inline GEPLikeRecipe_match<Op0_t, Op1_t> m_GetElementPtr(const Op0_t &Op0,
}
template <typename Op0_t, typename Op1_t, typename Op2_t>
-inline AllRecipe_match<Instruction::Select, false, Op0_t, Op1_t, Op2_t>
+inline AllRecipe_match<Instruction::Select, Op0_t, Op1_t, Op2_t>
m_Select(const Op0_t &Op0, const Op1_t &Op1, const Op2_t &Op2) {
- return AllRecipe_match<Instruction::Select, false, Op0_t, Op1_t, Op2_t>(
+ return AllRecipe_match<Instruction::Select, Op0_t, Op1_t, Op2_t>(
{Op0, Op1, Op2});
}
template <typename Op0_t>
-inline match_combine_or<
- VPInstruction_match<VPInstruction::Not, Op0_t>,
- AllRecipe_match<Instruction::Xor, true, int_pred_ty<is_all_ones>, Op0_t>>
+inline match_combine_or<VPInstruction_match<VPInstruction::Not, Op0_t>,
+ AllRecipe_commutative_match<
+ Instruction::Xor, int_pred_ty<is_all_ones>, Op0_t>>
m_Not(const Op0_t &Op0) {
return m_CombineOr(m_VPInstruction<VPInstruction::Not>(Op0),
m_c_Binary<Instruction::Xor>(m_AllOnes(), Op0));
@@ -417,8 +420,7 @@ m_Not(const Op0_t &Op0) {
template <typename Op0_t, typename Op1_t>
inline match_combine_or<
VPInstruction_match<VPInstruction::LogicalAnd, Op0_t, Op1_t>,
- AllRecipe_match<Instruction::Select, false, Op0_t, Op1_t,
- specific_intval<1>>>
+ AllRecipe_match<Instruction::Select, Op0_t, Op1_t, specific_intval<1>>>
m_LogicalAnd(const Op0_t &Op0, const Op1_t &Op1) {
return m_CombineOr(
m_VPInstruction<VPInstruction::LogicalAnd, Op0_t, Op1_t>(Op0, Op1),
@@ -426,8 +428,7 @@ m_LogicalAnd(const Op0_t &Op0, const Op1_t &Op1) {
}
template <typename Op0_t, typename Op1_t>
-inline AllRecipe_match<Instruction::Select, false, Op0_t, specific_intval<1>,
- Op1_t>
+inline AllRecipe_match<Instruction::Select, Op0_t, specific_intval<1>, Op1_t>
m_LogicalOr(const Op0_t &Op0, const Op1_t &Op1) {
return m_Select(Op0, m_True(), Op1);
}
More information about the llvm-commits
mailing list