@@ -120,7 +120,12 @@ template <unsigned Opcode, typename RecipeTy>
120
120
struct MatchRecipeAndOpcode <Opcode, RecipeTy> {
121
121
static bool match (const VPRecipeBase *R) {
122
122
auto *DefR = dyn_cast<RecipeTy>(R);
123
- return DefR && DefR->getOpcode () == Opcode;
123
+ // Check for recipes that do not have opcodes.
124
+ if constexpr (std::is_same<RecipeTy, VPScalarIVStepsRecipe>::value ||
125
+ std::is_same<RecipeTy, VPCanonicalIVPHIRecipe>::value)
126
+ return DefR;
127
+ else
128
+ return DefR && DefR->getOpcode () == Opcode;
124
129
}
125
130
};
126
131
@@ -131,13 +136,34 @@ struct MatchRecipeAndOpcode<Opcode, RecipeTy, RecipeTys...> {
131
136
MatchRecipeAndOpcode<Opcode, RecipeTys...>::match (R);
132
137
}
133
138
};
139
+ template <typename TupleTy, typename Fn, std::size_t ... Is>
140
+ bool CheckTupleElements (const TupleTy &Ops, Fn P, std::index_sequence<Is...>) {
141
+ return (P (std::get<Is>(Ops), Is) && ...);
142
+ }
143
+
144
+ // / Helper to check if predicate \p P holds on all tuple elements in \p Ops
145
+ template <typename TupleTy, typename Fn>
146
+ bool all_of_tuple_elements (const TupleTy &Ops, Fn P) {
147
+ return CheckTupleElements (
148
+ Ops, P, std::make_index_sequence<std::tuple_size<TupleTy>::value>{});
149
+ }
134
150
} // namespace detail
135
151
136
- template <typename Op0_t, unsigned Opcode, typename ... RecipeTys>
137
- struct UnaryRecipe_match {
138
- Op0_t Op0;
152
+ template <typename Ops_t, unsigned Opcode, bool Commutative,
153
+ typename ... RecipeTys>
154
+ struct Recipe_match {
155
+ Ops_t Ops;
139
156
140
- UnaryRecipe_match (Op0_t Op0) : Op0(Op0) {}
157
+ Recipe_match () : Ops() {
158
+ static_assert (std::tuple_size<Ops_t>::value == 0 &&
159
+ " constructor can only be used with zero operands" );
160
+ }
161
+ Recipe_match (Ops_t Ops) : Ops(Ops) {}
162
+ template <typename A_t, typename B_t>
163
+ Recipe_match (A_t A, B_t B) : Ops({A, B}) {
164
+ static_assert (std::tuple_size<Ops_t>::value == 2 &&
165
+ " constructor can only be used for binary matcher" );
166
+ }
141
167
142
168
bool match (const VPValue *V) const {
143
169
auto *DefR = V->getDefiningRecipe ();
@@ -151,12 +177,25 @@ struct UnaryRecipe_match {
151
177
bool match (const VPRecipeBase *R) const {
152
178
if (!detail::MatchRecipeAndOpcode<Opcode, RecipeTys...>::match (R))
153
179
return false ;
154
- assert (R->getNumOperands () == 1 &&
155
- " recipe with matched opcode does not have 1 operands" );
156
- return Op0.match (R->getOperand (0 ));
180
+ assert (R->getNumOperands () == std::tuple_size<Ops_t>::value &&
181
+ " recipe with matched opcode the expected number of operands" );
182
+
183
+ if (detail::all_of_tuple_elements (Ops, [R](auto Op, unsigned Idx) {
184
+ return Op.match (R->getOperand (Idx));
185
+ }))
186
+ return true ;
187
+
188
+ return Commutative &&
189
+ detail::all_of_tuple_elements (Ops, [R](auto Op, unsigned Idx) {
190
+ return Op.match (R->getOperand (R->getNumOperands () - Idx - 1 ));
191
+ });
157
192
}
158
193
};
159
194
195
+ template <typename Op0_t, unsigned Opcode, typename ... RecipeTys>
196
+ using UnaryRecipe_match =
197
+ Recipe_match<std::tuple<Op0_t>, Opcode, false , RecipeTys...>;
198
+
160
199
template <typename Op0_t, unsigned Opcode>
161
200
using UnaryVPInstruction_match =
162
201
UnaryRecipe_match<Op0_t, Opcode, VPInstruction>;
@@ -168,32 +207,8 @@ using AllUnaryRecipe_match =
168
207
169
208
template <typename Op0_t, typename Op1_t, unsigned Opcode, bool Commutative,
170
209
typename ... RecipeTys>
171
- struct BinaryRecipe_match {
172
- Op0_t Op0;
173
- Op1_t Op1;
174
-
175
- BinaryRecipe_match (Op0_t Op0, Op1_t Op1) : Op0(Op0), Op1(Op1) {}
176
-
177
- bool match (const VPValue *V) const {
178
- auto *DefR = V->getDefiningRecipe ();
179
- return DefR && match (DefR);
180
- }
181
-
182
- bool match (const VPSingleDefRecipe *R) const {
183
- return match (static_cast <const VPRecipeBase *>(R));
184
- }
185
-
186
- bool match (const VPRecipeBase *R) const {
187
- if (!detail::MatchRecipeAndOpcode<Opcode, RecipeTys...>::match (R))
188
- return false ;
189
- assert (R->getNumOperands () == 2 &&
190
- " recipe with matched opcode does not have 2 operands" );
191
- if (Op0.match (R->getOperand (0 )) && Op1.match (R->getOperand (1 )))
192
- return true ;
193
- return Commutative && Op0.match (R->getOperand (1 )) &&
194
- Op1.match (R->getOperand (0 ));
195
- }
196
- };
210
+ using BinaryRecipe_match =
211
+ Recipe_match<std::tuple<Op0_t, Op1_t>, Opcode, Commutative, RecipeTys...>;
197
212
198
213
template <typename Op0_t, typename Op1_t, unsigned Opcode>
199
214
using BinaryVPInstruction_match =
@@ -313,40 +328,16 @@ m_LogicalAnd(const Op0_t &Op0, const Op1_t &Op1) {
313
328
return m_VPInstruction<VPInstruction::LogicalAnd, Op0_t, Op1_t>(Op0, Op1);
314
329
}
315
330
316
- struct VPCanonicalIVPHI_match {
317
- bool match (const VPValue *V) const {
318
- auto *DefR = V->getDefiningRecipe ();
319
- return DefR && match (DefR);
320
- }
321
-
322
- bool match (const VPRecipeBase *R) const {
323
- return isa<VPCanonicalIVPHIRecipe>(R);
324
- }
325
- };
331
+ using VPCanonicalIVPHI_match =
332
+ Recipe_match<std::tuple<>, 0 , false , VPCanonicalIVPHIRecipe>;
326
333
327
334
inline VPCanonicalIVPHI_match m_CanonicalIV () {
328
335
return VPCanonicalIVPHI_match ();
329
336
}
330
337
331
- template <typename Op0_t, typename Op1_t> struct VPScalarIVSteps_match {
332
- Op0_t Op0;
333
- Op1_t Op1;
334
-
335
- VPScalarIVSteps_match (Op0_t Op0, Op1_t Op1) : Op0(Op0), Op1(Op1) {}
336
-
337
- bool match (const VPValue *V) const {
338
- auto *DefR = V->getDefiningRecipe ();
339
- return DefR && match (DefR);
340
- }
341
-
342
- bool match (const VPRecipeBase *R) const {
343
- if (!isa<VPScalarIVStepsRecipe>(R))
344
- return false ;
345
- assert (R->getNumOperands () == 2 &&
346
- " VPScalarIVSteps must have exactly 2 operands" );
347
- return Op0.match (R->getOperand (0 )) && Op1.match (R->getOperand (1 ));
348
- }
349
- };
338
+ template <typename Op0_t, typename Op1_t>
339
+ using VPScalarIVSteps_match =
340
+ Recipe_match<std::tuple<Op0_t, Op1_t>, 0 , false , VPScalarIVStepsRecipe>;
350
341
351
342
template <typename Op0_t, typename Op1_t>
352
343
inline VPScalarIVSteps_match<Op0_t, Op1_t> m_ScalarIVSteps (const Op0_t &Op0,
0 commit comments