@@ -50,51 +50,141 @@ template <typename Class> struct bind_ty {
50
50
}
51
51
};
52
52
53
+ // / Match a specified integer value or vector of all elements of that
54
+ // / value.
55
+ struct specific_intval {
56
+ APInt Val;
57
+
58
+ specific_intval (APInt V) : Val(std::move(V)) {}
59
+
60
+ bool match (VPValue *VPV) {
61
+ if (!VPV->isLiveIn ())
62
+ return false ;
63
+ Value *V = VPV->getLiveInIRValue ();
64
+ const auto *CI = dyn_cast<ConstantInt>(V);
65
+ if (!CI && V->getType ()->isVectorTy ())
66
+ if (const auto *C = dyn_cast<Constant>(V))
67
+ CI = dyn_cast_or_null<ConstantInt>(
68
+ C->getSplatValue (/* UndefsAllowed=*/ false ));
69
+
70
+ return CI && APInt::isSameValue (CI->getValue (), Val);
71
+ }
72
+ };
73
+
74
+ inline specific_intval m_SpecificInt (uint64_t V) {
75
+ return specific_intval (APInt (64 , V));
76
+ }
77
+
78
+ // / Matching combinators
79
+ template <typename LTy, typename RTy> struct match_combine_or {
80
+ LTy L;
81
+ RTy R;
82
+
83
+ match_combine_or (const LTy &Left, const RTy &Right) : L(Left), R(Right) {}
84
+
85
+ template <typename ITy> bool match (ITy *V) {
86
+ if (L.match (V))
87
+ return true ;
88
+ if (R.match (V))
89
+ return true ;
90
+ return false ;
91
+ }
92
+ };
93
+
94
+ template <typename LTy, typename RTy>
95
+ inline match_combine_or<LTy, RTy> m_CombineOr (const LTy &L, const RTy &R) {
96
+ return match_combine_or<LTy, RTy>(L, R);
97
+ }
98
+
53
99
// / Match a VPValue, capturing it if we match.
54
100
inline bind_ty<VPValue> m_VPValue (VPValue *&V) { return V; }
55
101
56
- template <typename Op0_t, unsigned Opcode> struct UnaryVPInstruction_match {
102
+ namespace detail {
103
+
104
+ // / A helper to match an opcode against multiple recipe types.
105
+ template <unsigned Opcode, typename ...> struct MatchRecipeAndOpcode {};
106
+
107
+ template <unsigned Opcode, typename RecipeTy>
108
+ struct MatchRecipeAndOpcode <Opcode, RecipeTy> {
109
+ static bool match (const VPRecipeBase *R) {
110
+ auto *DefR = dyn_cast<RecipeTy>(R);
111
+ return DefR && DefR->getOpcode () == Opcode;
112
+ }
113
+ };
114
+
115
+ template <unsigned Opcode, typename RecipeTy, typename ... RecipeTys>
116
+ struct MatchRecipeAndOpcode <Opcode, RecipeTy, RecipeTys...> {
117
+ static bool match (const VPRecipeBase *R) {
118
+ return MatchRecipeAndOpcode<Opcode, RecipeTy>::match (R) ||
119
+ MatchRecipeAndOpcode<Opcode, RecipeTys...>::match (R);
120
+ }
121
+ };
122
+ } // namespace detail
123
+
124
+ template <typename Op0_t, unsigned Opcode, typename ... RecipeTys>
125
+ struct UnaryRecipe_match {
57
126
Op0_t Op0;
58
127
59
- UnaryVPInstruction_match (Op0_t Op0) : Op0(Op0) {}
128
+ UnaryRecipe_match (Op0_t Op0) : Op0(Op0) {}
60
129
61
130
bool match (const VPValue *V) {
62
131
auto *DefR = V->getDefiningRecipe ();
63
132
return DefR && match (DefR);
64
133
}
65
134
66
135
bool match (const VPRecipeBase *R) {
67
- auto *DefR = dyn_cast<VPInstruction>(R);
68
- if (!DefR || DefR->getOpcode () != Opcode)
136
+ if (!detail::MatchRecipeAndOpcode<Opcode, RecipeTys...>::match (R))
69
137
return false ;
70
- assert (DefR ->getNumOperands () == 1 &&
138
+ assert (R ->getNumOperands () == 1 &&
71
139
" recipe with matched opcode does not have 1 operands" );
72
- return Op0.match (DefR ->getOperand (0 ));
140
+ return Op0.match (R ->getOperand (0 ));
73
141
}
74
142
};
75
143
76
- template <typename Op0_t, typename Op1_t, unsigned Opcode>
77
- struct BinaryVPInstruction_match {
144
+ template <typename Op0_t, unsigned Opcode>
145
+ using UnaryVPInstruction_match =
146
+ UnaryRecipe_match<Op0_t, Opcode, VPInstruction>;
147
+
148
+ template <typename Op0_t, unsigned Opcode>
149
+ using AllUnaryRecipe_match =
150
+ UnaryRecipe_match<Op0_t, Opcode, VPWidenRecipe, VPReplicateRecipe,
151
+ VPWidenCastRecipe, VPInstruction>;
152
+
153
+ template <typename Op0_t, typename Op1_t, unsigned Opcode,
154
+ typename ... RecipeTys>
155
+ struct BinaryRecipe_match {
78
156
Op0_t Op0;
79
157
Op1_t Op1;
80
158
81
- BinaryVPInstruction_match (Op0_t Op0, Op1_t Op1) : Op0(Op0), Op1(Op1) {}
159
+ BinaryRecipe_match (Op0_t Op0, Op1_t Op1) : Op0(Op0), Op1(Op1) {}
82
160
83
161
bool match (const VPValue *V) {
84
162
auto *DefR = V->getDefiningRecipe ();
85
163
return DefR && match (DefR);
86
164
}
87
165
166
+ bool match (const VPSingleDefRecipe *R) {
167
+ return match (static_cast <const VPRecipeBase *>(R));
168
+ }
169
+
88
170
bool match (const VPRecipeBase *R) {
89
- auto *DefR = dyn_cast<VPInstruction>(R);
90
- if (!DefR || DefR->getOpcode () != Opcode)
171
+ if (!detail::MatchRecipeAndOpcode<Opcode, RecipeTys...>::match (R))
91
172
return false ;
92
- assert (DefR ->getNumOperands () == 2 &&
173
+ assert (R ->getNumOperands () == 2 &&
93
174
" recipe with matched opcode does not have 2 operands" );
94
- return Op0.match (DefR ->getOperand (0 )) && Op1.match (DefR ->getOperand (1 ));
175
+ return Op0.match (R ->getOperand (0 )) && Op1.match (R ->getOperand (1 ));
95
176
}
96
177
};
97
178
179
+ template <typename Op0_t, typename Op1_t, unsigned Opcode>
180
+ using BinaryVPInstruction_match =
181
+ BinaryRecipe_match<Op0_t, Op1_t, Opcode, VPInstruction>;
182
+
183
+ template <typename Op0_t, typename Op1_t, unsigned Opcode>
184
+ using AllBinaryRecipe_match =
185
+ BinaryRecipe_match<Op0_t, Op1_t, Opcode, VPWidenRecipe, VPReplicateRecipe,
186
+ VPWidenCastRecipe, VPInstruction>;
187
+
98
188
template <unsigned Opcode, typename Op0_t>
99
189
inline UnaryVPInstruction_match<Op0_t, Opcode>
100
190
m_VPInstruction (const Op0_t &Op0) {
@@ -130,6 +220,47 @@ inline BinaryVPInstruction_match<Op0_t, Op1_t, VPInstruction::BranchOnCount>
130
220
m_BranchOnCount (const Op0_t &Op0, const Op1_t &Op1) {
131
221
return m_VPInstruction<VPInstruction::BranchOnCount>(Op0, Op1);
132
222
}
223
+
224
+ template <unsigned Opcode, typename Op0_t>
225
+ inline AllUnaryRecipe_match<Op0_t, Opcode> m_Unary (const Op0_t &Op0) {
226
+ return AllUnaryRecipe_match<Op0_t, Opcode>(Op0);
227
+ }
228
+
229
+ template <typename Op0_t>
230
+ inline AllUnaryRecipe_match<Op0_t, Instruction::Trunc>
231
+ m_Trunc (const Op0_t &Op0) {
232
+ return m_Unary<Instruction::Trunc, Op0_t>(Op0);
233
+ }
234
+
235
+ template <typename Op0_t>
236
+ inline AllUnaryRecipe_match<Op0_t, Instruction::ZExt> m_ZExt (const Op0_t &Op0) {
237
+ return m_Unary<Instruction::ZExt, Op0_t>(Op0);
238
+ }
239
+
240
+ template <typename Op0_t>
241
+ inline AllUnaryRecipe_match<Op0_t, Instruction::SExt> m_SExt (const Op0_t &Op0) {
242
+ return m_Unary<Instruction::SExt, Op0_t>(Op0);
243
+ }
244
+
245
+ template <typename Op0_t>
246
+ inline match_combine_or<AllUnaryRecipe_match<Op0_t, Instruction::ZExt>,
247
+ AllUnaryRecipe_match<Op0_t, Instruction::SExt>>
248
+ m_ZExtOrSExt (const Op0_t &Op0) {
249
+ return m_CombineOr (m_ZExt (Op0), m_SExt (Op0));
250
+ }
251
+
252
+ template <unsigned Opcode, typename Op0_t, typename Op1_t>
253
+ inline AllBinaryRecipe_match<Op0_t, Op1_t, Opcode> m_Binary (const Op0_t &Op0,
254
+ const Op1_t &Op1) {
255
+ return AllBinaryRecipe_match<Op0_t, Op1_t, Opcode>(Op0, Op1);
256
+ }
257
+
258
+ template <typename Op0_t, typename Op1_t>
259
+ inline AllBinaryRecipe_match<Op0_t, Op1_t, Instruction::Mul>
260
+ m_Mul (const Op0_t &Op0, const Op1_t &Op1) {
261
+ return m_Binary<Instruction::Mul, Op0_t, Op1_t>(Op0, Op1);
262
+ }
263
+
133
264
} // namespace VPlanPatternMatch
134
265
} // namespace llvm
135
266
0 commit comments