@@ -110,16 +110,6 @@ static bool isTrivialOperatorNode(const TreePatternNode *N) {
110
110
111
111
// ===- Matchers -----------------------------------------------------------===//
112
112
113
- struct Matcher {
114
- virtual ~Matcher () {}
115
- virtual void emit (raw_ostream &OS) const = 0;
116
- };
117
-
118
- raw_ostream &operator <<(raw_ostream &S, const Matcher &M) {
119
- M.emit (S);
120
- return S;
121
- }
122
-
123
113
struct MatchAction {
124
114
virtual ~MatchAction () {}
125
115
virtual void emit (raw_ostream &OS) const = 0;
@@ -130,46 +120,211 @@ raw_ostream &operator<<(raw_ostream &S, const MatchAction &A) {
130
120
return S;
131
121
}
132
122
133
- struct MatchOpcode : public Matcher {
134
- MatchOpcode (const CodeGenInstruction *I) : I(I) {}
135
- const CodeGenInstruction *I;
123
+ template <class PredicateTy > class PredicateListMatcher {
124
+ private:
125
+ typedef std::vector<std::unique_ptr<PredicateTy>> PredicateVec;
126
+ PredicateVec Predicates;
136
127
137
- virtual void emit (raw_ostream &OS) const {
138
- OS << " I.getOpcode() == " << I->Namespace << " ::" << I->TheDef ->getName ();
128
+ public:
129
+ // / Construct a new operand predicate and add it to the matcher.
130
+ template <class Kind , class ... Args>
131
+ Kind &addPredicate (Args&&... args) {
132
+ Predicates.emplace_back (make_unique<Kind>(std::forward<Args...>(args)...));
133
+ return *static_cast <Kind *>(Predicates.back ().get ());
134
+ }
135
+
136
+ typename PredicateVec::const_iterator predicates_begin () const { return Predicates.begin (); }
137
+ typename PredicateVec::const_iterator predicates_end () const { return Predicates.end (); }
138
+ iterator_range<typename PredicateVec::const_iterator> predicates () const {
139
+ return make_range (predicates_begin (), predicates_end ());
139
140
}
141
+
142
+ #if 0
143
+ /// Emit a C++ expression that tests whether all the predicates are met.
144
+ template <class... Args>
145
+ void emitCxxPredicatesExpr(raw_ostream &OS, Args&&... args) const {
146
+ if (Predicates.empty()) {
147
+ OS << "true";
148
+ return;
149
+ }
150
+
151
+ StringRef Separator = "";
152
+ for (const auto &Predicate : predicates()) {
153
+ OS << Separator << "(";
154
+ Predicate->emitCxxPredicateExpr(OS, std::forward<Args...>(args)...);
155
+ OS << ")";
156
+ Separator = " && ";
157
+ }
158
+ }
159
+ #else
160
+ // / Emit a C++ expression that tests whether all the predicates are met.
161
+ template <class Arg1 >
162
+ void emitCxxPredicatesExpr (raw_ostream &OS, Arg1&& arg1) const {
163
+ if (Predicates.empty ()) {
164
+ OS << " true" ;
165
+ return ;
166
+ }
167
+
168
+ StringRef Separator = " " ;
169
+ for (const auto &Predicate : predicates ()) {
170
+ OS << Separator << " (" ;
171
+ Predicate->emitCxxPredicateExpr (OS, std::forward<Arg1>(arg1));
172
+ OS << " )" ;
173
+ Separator = " && " ;
174
+ }
175
+ }
176
+
177
+ template <class Arg1 , class Arg2 >
178
+ void emitCxxPredicatesExpr (raw_ostream &OS, Arg1&& arg1, Arg2&& arg2) const {
179
+ if (Predicates.empty ()) {
180
+ OS << " true" ;
181
+ return ;
182
+ }
183
+
184
+ StringRef Separator = " " ;
185
+ for (const auto &Predicate : predicates ()) {
186
+ OS << Separator << " (" ;
187
+ Predicate->emitCxxPredicateExpr (OS, std::forward<Arg1>(arg1),
188
+ std::forward<Arg2>(arg2));
189
+ OS << " )" ;
190
+ Separator = " && " ;
191
+ }
192
+ }
193
+ #endif
140
194
};
141
195
142
- struct MatchRegOpType : public Matcher {
143
- MatchRegOpType (unsigned OpIdx, std::string Ty)
144
- : OpIdx(OpIdx), Ty(Ty) {}
145
- unsigned OpIdx;
196
+ // / Generates code to check a predicate of an operand.
197
+ // /
198
+ // / Typical predicates include:
199
+ // / * Operand is a particular register.
200
+ // / * Operand is assigned a particular register bank.
201
+ // / * Operand is an MBB.
202
+ class OperandPredicateMatcher {
203
+ public:
204
+ virtual ~OperandPredicateMatcher () {}
205
+
206
+ // / Emit a C++ expression that checks the predicate for the OpIdx operand of
207
+ // / the instruction given in InsnVarName.
208
+ virtual void emitCxxPredicateExpr (raw_ostream &OS,
209
+ const StringRef InsnVarName,
210
+ unsigned OpIdx) const = 0;
211
+ };
212
+
213
+ // / Generates code to check that an operand is a particular LLT.
214
+ class LLTOperandMatcher : public OperandPredicateMatcher {
215
+ protected:
146
216
std::string Ty;
147
217
148
- virtual void emit (raw_ostream &OS) const {
149
- OS << " MRI.getType(I.getOperand(" << OpIdx << " ).getReg()) == (" << Ty
150
- << " )" ;
218
+ public:
219
+ LLTOperandMatcher (std::string Ty) : Ty(Ty) {}
220
+
221
+ void emitCxxPredicateExpr (raw_ostream &OS, const StringRef InsnVarName,
222
+ unsigned OpIdx) const override {
223
+ OS << " MRI.getType(" << InsnVarName << " .getOperand(" << OpIdx
224
+ << " ).getReg()) == (" << Ty << " )" ;
151
225
}
152
226
};
153
227
154
- struct MatchRegOpBank : public Matcher {
155
- MatchRegOpBank (unsigned OpIdx, const CodeGenRegisterClass &RC)
156
- : OpIdx(OpIdx), RC(RC) {}
157
- unsigned OpIdx;
228
+ // / Generates code to check that an operand is in a particular register bank.
229
+ class RegisterBankOperandMatcher : public OperandPredicateMatcher {
230
+ protected:
158
231
const CodeGenRegisterClass &RC;
159
232
160
- virtual void emit (raw_ostream &OS) const {
233
+ public:
234
+ RegisterBankOperandMatcher (const CodeGenRegisterClass &RC) : RC(RC) {}
235
+
236
+ void emitCxxPredicateExpr (raw_ostream &OS, const StringRef InsnVarName,
237
+ unsigned OpIdx) const override {
161
238
OS << " (&RBI.getRegBankFromRegClass(" << RC.getQualifiedName ()
162
- << " RegClass) == RBI.getRegBank(I.getOperand( " << OpIdx
163
- << " ).getReg(), MRI, TRI))" ;
239
+ << " RegClass) == RBI.getRegBank(" << InsnVarName << " .getOperand( "
240
+ << OpIdx << " ).getReg(), MRI, TRI))" ;
164
241
}
165
242
};
166
243
167
- struct MatchMBBOp : public Matcher {
168
- MatchMBBOp (unsigned OpIdx) : OpIdx(OpIdx) {}
244
+ // / Generates code to check that an operand is a basic block.
245
+ class MBBOperandMatcher : public OperandPredicateMatcher {
246
+ public:
247
+ void emitCxxPredicateExpr (raw_ostream &OS, const StringRef InsnVarName,
248
+ unsigned OpIdx) const override {
249
+ OS << InsnVarName << " .getOperand(" << OpIdx << " ).isMBB()" ;
250
+ }
251
+ };
252
+
253
+ // / Generates code to check that a set of predicates match for a particular
254
+ // / operand.
255
+ class OperandMatcher : public PredicateListMatcher <OperandPredicateMatcher> {
256
+ protected:
169
257
unsigned OpIdx;
170
258
171
- virtual void emit (raw_ostream &OS) const {
172
- OS << " I.getOperand(" << OpIdx << " ).isMBB()" ;
259
+ public:
260
+ OperandMatcher (unsigned OpIdx) : OpIdx(OpIdx) {}
261
+
262
+ // / Emit a C++ expression that tests whether the instruction named in
263
+ // / InsnVarName matches all the predicate and all the operands.
264
+ void emitCxxPredicateExpr (raw_ostream &OS, const StringRef InsnVarName) const {
265
+ OS << " (" ;
266
+ emitCxxPredicatesExpr (OS, InsnVarName, OpIdx);
267
+ OS << " )" ;
268
+ }
269
+ };
270
+
271
+ // / Generates code to check a predicate on an instruction.
272
+ // /
273
+ // / Typical predicates include:
274
+ // / * The opcode of the instruction is a particular value.
275
+ // / * The nsw/nuw flag is/isn't set.
276
+ class InstructionPredicateMatcher {
277
+ public:
278
+ virtual ~InstructionPredicateMatcher () {}
279
+
280
+ // / Emit a C++ expression that tests whether the instruction named in
281
+ // / InsnVarName matches the predicate.
282
+ virtual void emitCxxPredicateExpr (raw_ostream &OS,
283
+ const StringRef InsnVarName) const = 0;
284
+ };
285
+
286
+ // / Generates code to check the opcode of an instruction.
287
+ class InstructionOpcodeMatcher : public InstructionPredicateMatcher {
288
+ protected:
289
+ const CodeGenInstruction *I;
290
+
291
+ public:
292
+ InstructionOpcodeMatcher (const CodeGenInstruction *I) : I(I) {}
293
+
294
+ void emitCxxPredicateExpr (raw_ostream &OS,
295
+ const StringRef InsnVarName) const override {
296
+ OS << InsnVarName << " .getOpcode() == " << I->Namespace
297
+ << " ::" << I->TheDef ->getName ();
298
+ }
299
+ };
300
+
301
+ // / Generates code to check that a set of predicates and operands match for a
302
+ // / particular instruction.
303
+ // /
304
+ // / Typical predicates include:
305
+ // / * Has a specific opcode.
306
+ // / * Has an nsw/nuw flag or doesn't.
307
+ class InstructionMatcher
308
+ : public PredicateListMatcher<InstructionPredicateMatcher> {
309
+ protected:
310
+ std::vector<OperandMatcher> Operands;
311
+
312
+ public:
313
+ // / Add an operand to the matcher.
314
+ OperandMatcher &addOperand (unsigned OpIdx) {
315
+ Operands.emplace_back (OpIdx);
316
+ return Operands.back ();
317
+ }
318
+
319
+ // / Emit a C++ expression that tests whether the instruction named in
320
+ // / InsnVarName matches all the predicates and all the operands.
321
+ void emitCxxPredicateExpr (raw_ostream &OS, const StringRef InsnVarName) const {
322
+ emitCxxPredicatesExpr (OS, InsnVarName);
323
+ for (const auto &Operand : Operands) {
324
+ OS << " && (" ;
325
+ Operand.emitCxxPredicateExpr (OS, InsnVarName);
326
+ OS << " )" ;
327
+ }
173
328
}
174
329
};
175
330
@@ -183,14 +338,25 @@ struct MutateOpcode : public MatchAction {
183
338
}
184
339
};
185
340
186
- class MatcherEmitter {
341
+ // / Generates code to check that a match rule matches.
342
+ // /
343
+ // / This currently supports a single match position but could be extended to
344
+ // / support multiple positions to support div/rem fusion or load-multiple
345
+ // / instructions.
346
+ class RuleMatcher {
187
347
const PatternToMatch &P;
188
348
349
+ std::vector<std::unique_ptr<InstructionMatcher>> Matchers;
350
+
189
351
public:
190
- std::vector<std::unique_ptr<Matcher>> Matchers;
191
352
std::vector<std::unique_ptr<MatchAction>> Actions;
192
353
193
- MatcherEmitter (const PatternToMatch &P) : P(P) {}
354
+ RuleMatcher (const PatternToMatch &P) : P(P) {}
355
+
356
+ InstructionMatcher &addInstructionMatcher () {
357
+ Matchers.emplace_back (new InstructionMatcher ());
358
+ return *Matchers.back ();
359
+ }
194
360
195
361
void emit (raw_ostream &OS) {
196
362
if (Matchers.empty ())
@@ -199,9 +365,18 @@ class MatcherEmitter {
199
365
OS << " // Src: " << *P.getSrcPattern () << " \n "
200
366
<< " // Dst: " << *P.getDstPattern () << " \n " ;
201
367
202
- OS << " if ((" << *Matchers.front () << " )" ;
203
- for (auto &MA : makeArrayRef (Matchers).drop_front ())
204
- OS << " &&\n (" << *MA << " )" ;
368
+ // The representation supports rules that require multiple roots such as:
369
+ // %ptr(p0) = ...
370
+ // %elt0(s32) = G_LOAD %ptr
371
+ // %1(p0) = G_ADD %ptr, 4
372
+ // %elt1(s32) = G_LOAD p0 %1
373
+ // which could be usefully folded into:
374
+ // %ptr(p0) = ...
375
+ // %elt0(s32), %elt1(s32) = TGT_LOAD_PAIR %ptr
376
+ // on some targets but we don't need to make use of that yet.
377
+ assert (Matchers.size () == 1 && " Cannot handle multi-root matchers yet" );
378
+ OS << " if (" ;
379
+ Matchers.front ()->emitCxxPredicateExpr (OS, " I" );
205
380
OS << " ) {\n " ;
206
381
207
382
for (auto &MA : Actions)
@@ -235,7 +410,7 @@ Optional<GlobalISelEmitter::SkipReason>
235
410
GlobalISelEmitter::runOnPattern (const PatternToMatch &P, raw_ostream &OS) {
236
411
237
412
// Keep track of the matchers and actions to emit.
238
- MatcherEmitter M (P);
413
+ RuleMatcher M (P);
239
414
240
415
// First, analyze the whole pattern.
241
416
// If the entire pattern has a predicate (e.g., target features), ignore it.
@@ -268,7 +443,8 @@ GlobalISelEmitter::runOnPattern(const PatternToMatch &P, raw_ostream &OS) {
268
443
auto &SrcGI = *SrcGIOrNull;
269
444
270
445
// The operators look good: match the opcode and mutate it to the new one.
271
- M.Matchers .emplace_back (new MatchOpcode (&SrcGI));
446
+ InstructionMatcher &InsnMatcher = M.addInstructionMatcher ();
447
+ InsnMatcher.addPredicate <InstructionOpcodeMatcher>(&SrcGI);
272
448
M.Actions .emplace_back (new MutateOpcode (&DstI));
273
449
274
450
// Next, analyze the children, only accepting patterns that don't require
@@ -291,9 +467,10 @@ GlobalISelEmitter::runOnPattern(const PatternToMatch &P, raw_ostream &OS) {
291
467
if (!OpTyOrNone)
292
468
return SkipReason{" Dst operand has an unsupported type" };
293
469
294
- M.Matchers .emplace_back (new MatchRegOpType (OpIdx, *OpTyOrNone));
295
- M.Matchers .emplace_back (
296
- new MatchRegOpBank (OpIdx, Target.getRegisterClass (DstIOpRec)));
470
+ OperandMatcher &OM = InsnMatcher.addOperand (OpIdx);
471
+ OM.addPredicate <LLTOperandMatcher>(*OpTyOrNone);
472
+ OM.addPredicate <RegisterBankOperandMatcher>(
473
+ Target.getRegisterClass (DstIOpRec));
297
474
++OpIdx;
298
475
}
299
476
@@ -316,7 +493,7 @@ GlobalISelEmitter::runOnPattern(const PatternToMatch &P, raw_ostream &OS) {
316
493
if (SrcChild->getOperator ()->isSubClassOf (" SDNode" )) {
317
494
auto &ChildSDNI = CGP.getSDNodeInfo (SrcChild->getOperator ());
318
495
if (ChildSDNI.getSDClassName () == " BasicBlockSDNode" ) {
319
- M. Matchers . emplace_back ( new MatchMBBOp ( OpIdx++));
496
+ InsnMatcher. addOperand ( OpIdx++). addPredicate <MBBOperandMatcher>( );
320
497
continue ;
321
498
}
322
499
}
@@ -341,9 +518,10 @@ GlobalISelEmitter::runOnPattern(const PatternToMatch &P, raw_ostream &OS) {
341
518
if (!OpTyOrNone)
342
519
return SkipReason{" Src operand has an unsupported type" };
343
520
344
- M.Matchers .emplace_back (new MatchRegOpType (OpIdx, *OpTyOrNone));
345
- M.Matchers .emplace_back (
346
- new MatchRegOpBank (OpIdx, Target.getRegisterClass (ChildRec)));
521
+ OperandMatcher &OM = InsnMatcher.addOperand (OpIdx);
522
+ OM.addPredicate <LLTOperandMatcher>(*OpTyOrNone);
523
+ OM.addPredicate <RegisterBankOperandMatcher>(
524
+ Target.getRegisterClass (ChildRec));
347
525
++OpIdx;
348
526
}
349
527
0 commit comments