Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / llvm / utils / TableGen / PredicateExpander.cpp
blob8f96d3307ded8beccd3bad1f973eae18889f978b
1 //===--------------------- PredicateExpander.cpp --------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 /// \file
9 /// Functionalities used by the Tablegen backends to expand machine predicates.
11 //===----------------------------------------------------------------------===//
13 #include "PredicateExpander.h"
14 #include "CodeGenSchedule.h" // Definition of STIPredicateFunction.
15 #include "llvm/TableGen/Record.h"
17 namespace llvm {
19 void PredicateExpander::expandTrue(raw_ostream &OS) { OS << "true"; }
20 void PredicateExpander::expandFalse(raw_ostream &OS) { OS << "false"; }
22 void PredicateExpander::expandCheckImmOperand(raw_ostream &OS, int OpIndex,
23 int ImmVal,
24 StringRef FunctionMapper) {
25 if (!FunctionMapper.empty())
26 OS << FunctionMapper << "(";
27 OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
28 << ").getImm()";
29 if (!FunctionMapper.empty())
30 OS << ")";
31 OS << (shouldNegate() ? " != " : " == ") << ImmVal;
34 void PredicateExpander::expandCheckImmOperand(raw_ostream &OS, int OpIndex,
35 StringRef ImmVal,
36 StringRef FunctionMapper) {
37 if (ImmVal.empty())
38 expandCheckImmOperandSimple(OS, OpIndex, FunctionMapper);
40 if (!FunctionMapper.empty())
41 OS << FunctionMapper << "(";
42 OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
43 << ").getImm()";
44 if (!FunctionMapper.empty())
45 OS << ")";
46 OS << (shouldNegate() ? " != " : " == ") << ImmVal;
49 void PredicateExpander::expandCheckImmOperandSimple(raw_ostream &OS,
50 int OpIndex,
51 StringRef FunctionMapper) {
52 if (shouldNegate())
53 OS << "!";
54 if (!FunctionMapper.empty())
55 OS << FunctionMapper << "(";
56 OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
57 << ").getImm()";
58 if (!FunctionMapper.empty())
59 OS << ")";
62 void PredicateExpander::expandCheckRegOperand(raw_ostream &OS, int OpIndex,
63 const Record *Reg,
64 StringRef FunctionMapper) {
65 assert(Reg->isSubClassOf("Register") && "Expected a register Record!");
67 if (!FunctionMapper.empty())
68 OS << FunctionMapper << "(";
69 OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
70 << ").getReg()";
71 if (!FunctionMapper.empty())
72 OS << ")";
73 OS << (shouldNegate() ? " != " : " == ");
74 const StringRef Str = Reg->getValueAsString("Namespace");
75 if (!Str.empty())
76 OS << Str << "::";
77 OS << Reg->getName();
81 void PredicateExpander::expandCheckRegOperandSimple(raw_ostream &OS,
82 int OpIndex,
83 StringRef FunctionMapper) {
84 if (shouldNegate())
85 OS << "!";
86 if (!FunctionMapper.empty())
87 OS << FunctionMapper << "(";
88 OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
89 << ").getReg()";
90 if (!FunctionMapper.empty())
91 OS << ")";
94 void PredicateExpander::expandCheckInvalidRegOperand(raw_ostream &OS,
95 int OpIndex) {
96 OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
97 << ").getReg() " << (shouldNegate() ? "!= " : "== ") << "0";
100 void PredicateExpander::expandCheckSameRegOperand(raw_ostream &OS, int First,
101 int Second) {
102 OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << First
103 << ").getReg() " << (shouldNegate() ? "!=" : "==") << " MI"
104 << (isByRef() ? "." : "->") << "getOperand(" << Second << ").getReg()";
107 void PredicateExpander::expandCheckNumOperands(raw_ostream &OS, int NumOps) {
108 OS << "MI" << (isByRef() ? "." : "->") << "getNumOperands() "
109 << (shouldNegate() ? "!= " : "== ") << NumOps;
112 void PredicateExpander::expandCheckOpcode(raw_ostream &OS, const Record *Inst) {
113 OS << "MI" << (isByRef() ? "." : "->") << "getOpcode() "
114 << (shouldNegate() ? "!= " : "== ") << Inst->getValueAsString("Namespace")
115 << "::" << Inst->getName();
118 void PredicateExpander::expandCheckOpcode(raw_ostream &OS,
119 const RecVec &Opcodes) {
120 assert(!Opcodes.empty() && "Expected at least one opcode to check!");
121 bool First = true;
123 if (Opcodes.size() == 1) {
124 OS << "( ";
125 expandCheckOpcode(OS, Opcodes[0]);
126 OS << " )";
127 return;
130 OS << '(';
131 increaseIndentLevel();
132 for (const Record *Rec : Opcodes) {
133 OS << '\n';
134 OS.indent(getIndentLevel() * 2);
135 if (!First)
136 OS << (shouldNegate() ? "&& " : "|| ");
138 expandCheckOpcode(OS, Rec);
139 First = false;
142 OS << '\n';
143 decreaseIndentLevel();
144 OS.indent(getIndentLevel() * 2);
145 OS << ')';
148 void PredicateExpander::expandCheckPseudo(raw_ostream &OS,
149 const RecVec &Opcodes) {
150 if (shouldExpandForMC())
151 expandFalse(OS);
152 else
153 expandCheckOpcode(OS, Opcodes);
156 void PredicateExpander::expandPredicateSequence(raw_ostream &OS,
157 const RecVec &Sequence,
158 bool IsCheckAll) {
159 assert(!Sequence.empty() && "Found an invalid empty predicate set!");
160 if (Sequence.size() == 1)
161 return expandPredicate(OS, Sequence[0]);
163 // Okay, there is more than one predicate in the set.
164 bool First = true;
165 OS << (shouldNegate() ? "!(" : "(");
166 increaseIndentLevel();
168 bool OldValue = shouldNegate();
169 setNegatePredicate(false);
170 for (const Record *Rec : Sequence) {
171 OS << '\n';
172 OS.indent(getIndentLevel() * 2);
173 if (!First)
174 OS << (IsCheckAll ? "&& " : "|| ");
175 expandPredicate(OS, Rec);
176 First = false;
178 OS << '\n';
179 decreaseIndentLevel();
180 OS.indent(getIndentLevel() * 2);
181 OS << ')';
182 setNegatePredicate(OldValue);
185 void PredicateExpander::expandTIIFunctionCall(raw_ostream &OS,
186 StringRef MethodName) {
187 OS << (shouldNegate() ? "!" : "");
188 OS << TargetName << (shouldExpandForMC() ? "_MC::" : "InstrInfo::");
189 OS << MethodName << (isByRef() ? "(MI)" : "(*MI)");
192 void PredicateExpander::expandCheckIsRegOperand(raw_ostream &OS, int OpIndex) {
193 OS << (shouldNegate() ? "!" : "") << "MI" << (isByRef() ? "." : "->")
194 << "getOperand(" << OpIndex << ").isReg() ";
197 void PredicateExpander::expandCheckIsImmOperand(raw_ostream &OS, int OpIndex) {
198 OS << (shouldNegate() ? "!" : "") << "MI" << (isByRef() ? "." : "->")
199 << "getOperand(" << OpIndex << ").isImm() ";
202 void PredicateExpander::expandCheckFunctionPredicateWithTII(
203 raw_ostream &OS, StringRef MCInstFn, StringRef MachineInstrFn,
204 StringRef TIIPtr) {
205 if (!shouldExpandForMC()) {
206 OS << (TIIPtr.empty() ? "TII" : TIIPtr) << "->" << MachineInstrFn;
207 OS << (isByRef() ? "(MI)" : "(*MI)");
208 return;
211 OS << MCInstFn << (isByRef() ? "(MI" : "(*MI") << ", MCII)";
214 void PredicateExpander::expandCheckFunctionPredicate(raw_ostream &OS,
215 StringRef MCInstFn,
216 StringRef MachineInstrFn) {
217 OS << (shouldExpandForMC() ? MCInstFn : MachineInstrFn)
218 << (isByRef() ? "(MI)" : "(*MI)");
221 void PredicateExpander::expandCheckNonPortable(raw_ostream &OS,
222 StringRef Code) {
223 if (shouldExpandForMC())
224 return expandFalse(OS);
226 OS << '(' << Code << ')';
229 void PredicateExpander::expandReturnStatement(raw_ostream &OS,
230 const Record *Rec) {
231 std::string Buffer;
232 raw_string_ostream SS(Buffer);
234 SS << "return ";
235 expandPredicate(SS, Rec);
236 SS << ";";
237 OS << Buffer;
240 void PredicateExpander::expandOpcodeSwitchCase(raw_ostream &OS,
241 const Record *Rec) {
242 const RecVec &Opcodes = Rec->getValueAsListOfDefs("Opcodes");
243 for (const Record *Opcode : Opcodes) {
244 OS.indent(getIndentLevel() * 2);
245 OS << "case " << Opcode->getValueAsString("Namespace")
246 << "::" << Opcode->getName() << ":\n";
249 increaseIndentLevel();
250 OS.indent(getIndentLevel() * 2);
251 expandStatement(OS, Rec->getValueAsDef("CaseStmt"));
252 decreaseIndentLevel();
255 void PredicateExpander::expandOpcodeSwitchStatement(raw_ostream &OS,
256 const RecVec &Cases,
257 const Record *Default) {
258 std::string Buffer;
259 raw_string_ostream SS(Buffer);
261 SS << "switch(MI" << (isByRef() ? "." : "->") << "getOpcode()) {\n";
262 for (const Record *Rec : Cases) {
263 expandOpcodeSwitchCase(SS, Rec);
264 SS << '\n';
267 // Expand the default case.
268 SS.indent(getIndentLevel() * 2);
269 SS << "default:\n";
271 increaseIndentLevel();
272 SS.indent(getIndentLevel() * 2);
273 expandStatement(SS, Default);
274 decreaseIndentLevel();
275 SS << '\n';
277 SS.indent(getIndentLevel() * 2);
278 SS << "} // end of switch-stmt";
279 OS << Buffer;
282 void PredicateExpander::expandStatement(raw_ostream &OS, const Record *Rec) {
283 // Assume that padding has been added by the caller.
284 if (Rec->isSubClassOf("MCOpcodeSwitchStatement")) {
285 expandOpcodeSwitchStatement(OS, Rec->getValueAsListOfDefs("Cases"),
286 Rec->getValueAsDef("DefaultCase"));
287 return;
290 if (Rec->isSubClassOf("MCReturnStatement")) {
291 expandReturnStatement(OS, Rec->getValueAsDef("Pred"));
292 return;
295 llvm_unreachable("No known rules to expand this MCStatement");
298 void PredicateExpander::expandPredicate(raw_ostream &OS, const Record *Rec) {
299 // Assume that padding has been added by the caller.
300 if (Rec->isSubClassOf("MCTrue")) {
301 if (shouldNegate())
302 return expandFalse(OS);
303 return expandTrue(OS);
306 if (Rec->isSubClassOf("MCFalse")) {
307 if (shouldNegate())
308 return expandTrue(OS);
309 return expandFalse(OS);
312 if (Rec->isSubClassOf("CheckNot")) {
313 flipNegatePredicate();
314 expandPredicate(OS, Rec->getValueAsDef("Pred"));
315 flipNegatePredicate();
316 return;
319 if (Rec->isSubClassOf("CheckIsRegOperand"))
320 return expandCheckIsRegOperand(OS, Rec->getValueAsInt("OpIndex"));
322 if (Rec->isSubClassOf("CheckIsImmOperand"))
323 return expandCheckIsImmOperand(OS, Rec->getValueAsInt("OpIndex"));
325 if (Rec->isSubClassOf("CheckRegOperand"))
326 return expandCheckRegOperand(OS, Rec->getValueAsInt("OpIndex"),
327 Rec->getValueAsDef("Reg"),
328 Rec->getValueAsString("FunctionMapper"));
330 if (Rec->isSubClassOf("CheckRegOperandSimple"))
331 return expandCheckRegOperandSimple(OS, Rec->getValueAsInt("OpIndex"),
332 Rec->getValueAsString("FunctionMapper"));
334 if (Rec->isSubClassOf("CheckInvalidRegOperand"))
335 return expandCheckInvalidRegOperand(OS, Rec->getValueAsInt("OpIndex"));
337 if (Rec->isSubClassOf("CheckImmOperand"))
338 return expandCheckImmOperand(OS, Rec->getValueAsInt("OpIndex"),
339 Rec->getValueAsInt("ImmVal"),
340 Rec->getValueAsString("FunctionMapper"));
342 if (Rec->isSubClassOf("CheckImmOperand_s"))
343 return expandCheckImmOperand(OS, Rec->getValueAsInt("OpIndex"),
344 Rec->getValueAsString("ImmVal"),
345 Rec->getValueAsString("FunctionMapper"));
347 if (Rec->isSubClassOf("CheckImmOperandSimple"))
348 return expandCheckImmOperandSimple(OS, Rec->getValueAsInt("OpIndex"),
349 Rec->getValueAsString("FunctionMapper"));
351 if (Rec->isSubClassOf("CheckSameRegOperand"))
352 return expandCheckSameRegOperand(OS, Rec->getValueAsInt("FirstIndex"),
353 Rec->getValueAsInt("SecondIndex"));
355 if (Rec->isSubClassOf("CheckNumOperands"))
356 return expandCheckNumOperands(OS, Rec->getValueAsInt("NumOps"));
358 if (Rec->isSubClassOf("CheckPseudo"))
359 return expandCheckPseudo(OS, Rec->getValueAsListOfDefs("ValidOpcodes"));
361 if (Rec->isSubClassOf("CheckOpcode"))
362 return expandCheckOpcode(OS, Rec->getValueAsListOfDefs("ValidOpcodes"));
364 if (Rec->isSubClassOf("CheckAll"))
365 return expandPredicateSequence(OS, Rec->getValueAsListOfDefs("Predicates"),
366 /* AllOf */ true);
368 if (Rec->isSubClassOf("CheckAny"))
369 return expandPredicateSequence(OS, Rec->getValueAsListOfDefs("Predicates"),
370 /* AllOf */ false);
372 if (Rec->isSubClassOf("CheckFunctionPredicate")) {
373 return expandCheckFunctionPredicate(
374 OS, Rec->getValueAsString("MCInstFnName"),
375 Rec->getValueAsString("MachineInstrFnName"));
378 if (Rec->isSubClassOf("CheckFunctionPredicateWithTII")) {
379 return expandCheckFunctionPredicateWithTII(
380 OS, Rec->getValueAsString("MCInstFnName"),
381 Rec->getValueAsString("MachineInstrFnName"),
382 Rec->getValueAsString("TIIPtrName"));
385 if (Rec->isSubClassOf("CheckNonPortable"))
386 return expandCheckNonPortable(OS, Rec->getValueAsString("CodeBlock"));
388 if (Rec->isSubClassOf("TIIPredicate"))
389 return expandTIIFunctionCall(OS, Rec->getValueAsString("FunctionName"));
391 llvm_unreachable("No known rules to expand this MCInstPredicate");
394 void STIPredicateExpander::expandHeader(raw_ostream &OS,
395 const STIPredicateFunction &Fn) {
396 const Record *Rec = Fn.getDeclaration();
397 StringRef FunctionName = Rec->getValueAsString("Name");
399 OS.indent(getIndentLevel() * 2);
400 OS << "bool ";
401 if (shouldExpandDefinition())
402 OS << getClassPrefix() << "::";
403 OS << FunctionName << "(";
404 if (shouldExpandForMC())
405 OS << "const MCInst " << (isByRef() ? "&" : "*") << "MI";
406 else
407 OS << "const MachineInstr " << (isByRef() ? "&" : "*") << "MI";
408 if (Rec->getValueAsBit("UpdatesOpcodeMask"))
409 OS << ", APInt &Mask";
410 OS << (shouldExpandForMC() ? ", unsigned ProcessorID) const " : ") const ");
411 if (shouldExpandDefinition()) {
412 OS << "{\n";
413 return;
416 if (Rec->getValueAsBit("OverridesBaseClassMember"))
417 OS << "override";
418 OS << ";\n";
421 void STIPredicateExpander::expandPrologue(raw_ostream &OS,
422 const STIPredicateFunction &Fn) {
423 RecVec Delegates = Fn.getDeclaration()->getValueAsListOfDefs("Delegates");
424 bool UpdatesOpcodeMask =
425 Fn.getDeclaration()->getValueAsBit("UpdatesOpcodeMask");
427 increaseIndentLevel();
428 unsigned IndentLevel = getIndentLevel();
429 for (const Record *Delegate : Delegates) {
430 OS.indent(IndentLevel * 2);
431 OS << "if (" << Delegate->getValueAsString("Name") << "(MI";
432 if (UpdatesOpcodeMask)
433 OS << ", Mask";
434 if (shouldExpandForMC())
435 OS << ", ProcessorID";
436 OS << "))\n";
437 OS.indent((1 + IndentLevel) * 2);
438 OS << "return true;\n\n";
441 if (shouldExpandForMC())
442 return;
444 OS.indent(IndentLevel * 2);
445 OS << "unsigned ProcessorID = getSchedModel().getProcessorID();\n";
448 void STIPredicateExpander::expandOpcodeGroup(raw_ostream &OS, const OpcodeGroup &Group,
449 bool ShouldUpdateOpcodeMask) {
450 const OpcodeInfo &OI = Group.getOpcodeInfo();
451 for (const PredicateInfo &PI : OI.getPredicates()) {
452 const APInt &ProcModelMask = PI.ProcModelMask;
453 bool FirstProcID = true;
454 for (unsigned I = 0, E = ProcModelMask.getActiveBits(); I < E; ++I) {
455 if (!ProcModelMask[I])
456 continue;
458 if (FirstProcID) {
459 OS.indent(getIndentLevel() * 2);
460 OS << "if (ProcessorID == " << I;
461 } else {
462 OS << " || ProcessorID == " << I;
464 FirstProcID = false;
467 OS << ") {\n";
469 increaseIndentLevel();
470 OS.indent(getIndentLevel() * 2);
471 if (ShouldUpdateOpcodeMask) {
472 if (PI.OperandMask.isZero())
473 OS << "Mask.clearAllBits();\n";
474 else
475 OS << "Mask = " << PI.OperandMask << ";\n";
476 OS.indent(getIndentLevel() * 2);
478 OS << "return ";
479 expandPredicate(OS, PI.Predicate);
480 OS << ";\n";
481 decreaseIndentLevel();
482 OS.indent(getIndentLevel() * 2);
483 OS << "}\n";
487 void STIPredicateExpander::expandBody(raw_ostream &OS,
488 const STIPredicateFunction &Fn) {
489 bool UpdatesOpcodeMask =
490 Fn.getDeclaration()->getValueAsBit("UpdatesOpcodeMask");
492 unsigned IndentLevel = getIndentLevel();
493 OS.indent(IndentLevel * 2);
494 OS << "switch(MI" << (isByRef() ? "." : "->") << "getOpcode()) {\n";
495 OS.indent(IndentLevel * 2);
496 OS << "default:\n";
497 OS.indent(IndentLevel * 2);
498 OS << " break;";
500 for (const OpcodeGroup &Group : Fn.getGroups()) {
501 for (const Record *Opcode : Group.getOpcodes()) {
502 OS << '\n';
503 OS.indent(IndentLevel * 2);
504 OS << "case " << getTargetName() << "::" << Opcode->getName() << ":";
507 OS << '\n';
508 increaseIndentLevel();
509 expandOpcodeGroup(OS, Group, UpdatesOpcodeMask);
511 OS.indent(getIndentLevel() * 2);
512 OS << "break;\n";
513 decreaseIndentLevel();
516 OS.indent(IndentLevel * 2);
517 OS << "}\n";
520 void STIPredicateExpander::expandEpilogue(raw_ostream &OS,
521 const STIPredicateFunction &Fn) {
522 OS << '\n';
523 OS.indent(getIndentLevel() * 2);
524 OS << "return ";
525 expandPredicate(OS, Fn.getDefaultReturnPredicate());
526 OS << ";\n";
528 decreaseIndentLevel();
529 OS.indent(getIndentLevel() * 2);
530 StringRef FunctionName = Fn.getDeclaration()->getValueAsString("Name");
531 OS << "} // " << ClassPrefix << "::" << FunctionName << "\n\n";
534 void STIPredicateExpander::expandSTIPredicate(raw_ostream &OS,
535 const STIPredicateFunction &Fn) {
536 const Record *Rec = Fn.getDeclaration();
537 if (shouldExpandForMC() && !Rec->getValueAsBit("ExpandForMC"))
538 return;
540 expandHeader(OS, Fn);
541 if (shouldExpandDefinition()) {
542 expandPrologue(OS, Fn);
543 expandBody(OS, Fn);
544 expandEpilogue(OS, Fn);
548 } // namespace llvm