15
15
#include " llvm/Support/CommandLine.h"
16
16
#include " llvm/Support/Timer.h"
17
17
#include " llvm/TableGen/Error.h"
18
+ #include " llvm/TableGen/StringMatcher.h"
18
19
#include " llvm/TableGen/TableGenBackend.h"
19
20
#include " CodeGenTarget.h"
20
21
#include " GlobalISel/CodeExpander.h"
@@ -75,6 +76,8 @@ class CombineRule {
75
76
bool parseDefs ();
76
77
bool parseMatcher (const CodeGenTarget &Target);
77
78
79
+ RuleID getID () const { return ID; }
80
+ StringRef getName () const { return TheDef.getName (); }
78
81
const Record &getDef () const { return TheDef; }
79
82
const CodeInit *getMatchingFixupCode () const { return MatchingFixupCode; }
80
83
size_t getNumRoots () const { return Roots.size (); }
@@ -202,6 +205,9 @@ class GICombinerEmitter {
202
205
}
203
206
void run (raw_ostream &OS);
204
207
208
+ // / Emit the name matcher (guarded by #ifndef NDEBUG) used to disable rules in
209
+ // / response to the generated cl::opt.
210
+ void emitNameMatcher (raw_ostream &OS) const ;
205
211
void generateCodeForRule (raw_ostream &OS, const CombineRule *Rule,
206
212
StringRef Indent) const ;
207
213
};
@@ -211,6 +217,32 @@ GICombinerEmitter::GICombinerEmitter(RecordKeeper &RK,
211
217
StringRef Name, Record *Combiner)
212
218
: Name(Name), Target(Target), Combiner(Combiner) {}
213
219
220
+ void GICombinerEmitter::emitNameMatcher (raw_ostream &OS) const {
221
+ std::vector<std::pair<std::string, std::string>> Cases;
222
+ Cases.reserve (Rules.size ());
223
+
224
+ for (const CombineRule &EnumeratedRule : make_pointee_range (Rules)) {
225
+ std::string Code;
226
+ raw_string_ostream SS (Code);
227
+ SS << " return " << EnumeratedRule.getID () << " ;\n " ;
228
+ Cases.push_back (std::make_pair (EnumeratedRule.getName (), SS.str ()));
229
+ }
230
+
231
+ OS << " #ifndef NDEBUG\n "
232
+ << " static Optional<uint64_t> getRuleIdxForIdentifier(StringRef "
233
+ " RuleIdentifier) {\n "
234
+ << " uint64_t I;\n "
235
+ << " // getAtInteger(...) returns false on success\n "
236
+ << " bool Parsed = !RuleIdentifier.getAsInteger(0, I);\n "
237
+ << " if (Parsed)\n "
238
+ << " return I;\n\n " ;
239
+ StringMatcher Matcher (" RuleIdentifier" , Cases, OS);
240
+ Matcher.Emit ();
241
+ OS << " return None;\n "
242
+ << " }\n "
243
+ << " #endif // ifndef NDEBUG\n\n " ;
244
+ }
245
+
214
246
std::unique_ptr<CombineRule>
215
247
GICombinerEmitter::makeCombineRule (const Record &TheDef) {
216
248
std::unique_ptr<CombineRule> Rule =
@@ -254,7 +286,7 @@ void GICombinerEmitter::generateCodeForRule(raw_ostream &OS,
254
286
const Record &RuleDef = Rule->getDef ();
255
287
256
288
OS << Indent << " // Rule: " << RuleDef.getName () << " \n "
257
- << Indent << " {\n " ;
289
+ << Indent << " if (!isRuleDisabled( " << Rule-> getID () << " )) {\n " ;
258
290
259
291
CodeExpansions Expansions;
260
292
for (const RootInfo &Root : Rule->roots ()) {
@@ -309,21 +341,83 @@ void GICombinerEmitter::run(raw_ostream &OS) {
309
341
" Code Generation" , " Time spent generating code" ,
310
342
TimeRegions);
311
343
OS << " #ifdef " << Name.upper () << " _GENCOMBINERHELPER_DEPS\n "
344
+ << " #include \" llvm/ADT/SparseBitVector.h\"\n "
345
+ << " namespace llvm {\n "
346
+ << " extern cl::OptionCategory GICombinerOptionCategory;\n "
347
+ << " } // end namespace llvm\n "
312
348
<< " #endif // ifdef " << Name.upper () << " _GENCOMBINERHELPER_DEPS\n\n " ;
313
349
314
350
OS << " #ifdef " << Name.upper () << " _GENCOMBINERHELPER_H\n "
315
351
<< " class " << getClassName () << " {\n "
352
+ << " SparseBitVector<> DisabledRules;\n "
353
+ << " \n "
316
354
<< " public:\n "
355
+ << " bool parseCommandLineOption();\n "
356
+ << " bool isRuleDisabled(unsigned ID) const;\n "
357
+ << " bool setRuleDisabled(StringRef RuleIdentifier);\n "
358
+ << " \n "
317
359
<< " bool tryCombineAll(\n "
318
360
<< " GISelChangeObserver &Observer,\n "
319
361
<< " MachineInstr &MI,\n "
320
362
<< " MachineIRBuilder &B) const;\n "
321
- << " };\n " ;
363
+ << " };\n\n " ;
364
+
365
+ emitNameMatcher (OS);
366
+
367
+ OS << " bool " << getClassName ()
368
+ << " ::setRuleDisabled(StringRef RuleIdentifier) {\n "
369
+ << " std::pair<StringRef, StringRef> RangePair = "
370
+ " RuleIdentifier.split('-');\n "
371
+ << " if (!RangePair.second.empty()) {\n "
372
+ << " const auto First = getRuleIdxForIdentifier(RangePair.first);\n "
373
+ << " const auto Last = getRuleIdxForIdentifier(RangePair.second);\n "
374
+ << " if (!First.hasValue() || !Last.hasValue())\n "
375
+ << " return false;\n "
376
+ << " if (First >= Last)\n "
377
+ << " report_fatal_error(\" Beginning of range should be before end of "
378
+ " range\" );\n "
379
+ << " for (auto I = First.getValue(); I < Last.getValue(); ++I)\n "
380
+ << " DisabledRules.set(I);\n "
381
+ << " return true;\n "
382
+ << " }\n "
383
+ << " #ifndef NDEBUG\n "
384
+ << " else {\n "
385
+ << " const auto I = getRuleIdxForIdentifier(RangePair.first);\n "
386
+ << " if (!I.hasValue())\n "
387
+ << " return false;\n "
388
+ << " DisabledRules.set(I.getValue());\n "
389
+ << " return true;\n "
390
+ << " }\n "
391
+ << " #else // ifndef NDEBUG\n "
392
+ << " llvm_unreachable(\" Cannot disable rules in non-asserts builds\" );\n "
393
+ << " return false;\n "
394
+ << " #endif // ifndef NDEBUG\n\n "
395
+ << " }\n " ;
396
+
397
+ OS << " bool " << getClassName ()
398
+ << " ::isRuleDisabled(unsigned RuleID) const {\n "
399
+ << " return DisabledRules.test(RuleID);\n "
400
+ << " }\n " ;
322
401
OS << " #endif // ifdef " << Name.upper () << " _GENCOMBINERHELPER_H\n\n " ;
323
402
324
403
OS << " #ifdef " << Name.upper () << " _GENCOMBINERHELPER_CPP\n "
325
404
<< " \n "
326
- << " bool " << getClassName () << " ::tryCombineAll(\n "
405
+ << " cl::list<std::string> " << Name << " Option(\n "
406
+ << " \" " << Name.lower () << " -disable-rule\" ,\n "
407
+ << " cl::desc(\" Disable one or more combiner rules temporarily in "
408
+ << " the " << Name << " pass\" ),\n "
409
+ << " cl::CommaSeparated,\n "
410
+ << " cl::Hidden,\n "
411
+ << " cl::cat(GICombinerOptionCategory));\n "
412
+ << " \n "
413
+ << " bool " << getClassName () << " ::parseCommandLineOption() {\n "
414
+ << " for (const auto &Identifier : " << Name << " Option)\n "
415
+ << " if (!setRuleDisabled(Identifier))\n "
416
+ << " return false;\n "
417
+ << " return true;\n "
418
+ << " }\n\n " ;
419
+
420
+ OS << " bool " << getClassName () << " ::tryCombineAll(\n "
327
421
<< " GISelChangeObserver &Observer,\n "
328
422
<< " MachineInstr &MI,\n "
329
423
<< " MachineIRBuilder &B) const {\n "
0 commit comments