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.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "PredicateExpander.h"
14 #include "CodeGenSchedule.h" // Definition of STIPredicateFunction.
15 #include "llvm/TableGen/Record.h"
16 
17 namespace llvm {
18 
19 void PredicateExpander::expandTrue(raw_ostream &OS) { OS << "true"; }
20 void PredicateExpander::expandFalse(raw_ostream &OS) { OS << "false"; }
21 
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;
32 }
33 
34 void PredicateExpander::expandCheckImmOperand(raw_ostream &OS, int OpIndex,
35                                               StringRef ImmVal,
36                                               StringRef FunctionMapper) {
37   if (ImmVal.empty())
38     expandCheckImmOperandSimple(OS, OpIndex, FunctionMapper);
39 
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;
47 }
48 
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 << ")";
60 }
61 
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!");
66 
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();
78 }
79 
80 
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 << ")";
92 }
93 
94 void PredicateExpander::expandCheckInvalidRegOperand(raw_ostream &OS,
95                                                      int OpIndex) {
96   OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
97      << ").getReg() " << (shouldNegate() ? "!= " : "== ") << "0";
98 }
99 
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()";
105 }
106 
107 void PredicateExpander::expandCheckNumOperands(raw_ostream &OS, int NumOps) {
108   OS << "MI" << (isByRef() ? "." : "->") << "getNumOperands() "
109      << (shouldNegate() ? "!= " : "== ") << NumOps;
110 }
111 
112 void PredicateExpander::expandCheckOpcode(raw_ostream &OS, const Record *Inst) {
113   OS << "MI" << (isByRef() ? "." : "->") << "getOpcode() "
114      << (shouldNegate() ? "!= " : "== ") << Inst->getValueAsString("Namespace")
115      << "::" << Inst->getName();
116 }
117 
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;
122 
123   if (Opcodes.size() == 1) {
124     OS << "( ";
125     expandCheckOpcode(OS, Opcodes[0]);
126     OS << " )";
127     return;
128   }
129 
130   OS << '(';
131   increaseIndentLevel();
132   for (const Record *Rec : Opcodes) {
133     OS << '\n';
134     OS.indent(getIndentLevel() * 2);
135     if (!First)
136       OS << (shouldNegate() ? "&& " : "|| ");
137 
138     expandCheckOpcode(OS, Rec);
139     First = false;
140   }
141 
142   OS << '\n';
143   decreaseIndentLevel();
144   OS.indent(getIndentLevel() * 2);
145   OS << ')';
146 }
147 
148 void PredicateExpander::expandCheckPseudo(raw_ostream &OS,
149                                           const RecVec &Opcodes) {
150   if (shouldExpandForMC())
151     expandFalse(OS);
152   else
153     expandCheckOpcode(OS, Opcodes);
154 }
155 
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]);
162 
163   // Okay, there is more than one predicate in the set.
164   bool First = true;
165   OS << (shouldNegate() ? "!(" : "(");
166   increaseIndentLevel();
167 
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;
177   }
178   OS << '\n';
179   decreaseIndentLevel();
180   OS.indent(getIndentLevel() * 2);
181   OS << ')';
182   setNegatePredicate(OldValue);
183 }
184 
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)");
190 }
191 
192 void PredicateExpander::expandCheckIsRegOperand(raw_ostream &OS, int OpIndex) {
193   OS << (shouldNegate() ? "!" : "") << "MI" << (isByRef() ? "." : "->")
194      << "getOperand(" << OpIndex << ").isReg() ";
195 }
196 
197 void PredicateExpander::expandCheckIsVRegOperand(raw_ostream &OS, int OpIndex) {
198   OS << (shouldNegate() ? "!" : "") << "MI" << (isByRef() ? "." : "->")
199      << "getOperand(" << OpIndex << ").getReg().isVirtual()";
200 }
201 
202 void PredicateExpander::expandCheckIsImmOperand(raw_ostream &OS, int OpIndex) {
203   OS << (shouldNegate() ? "!" : "") << "MI" << (isByRef() ? "." : "->")
204      << "getOperand(" << OpIndex << ").isImm() ";
205 }
206 
207 void PredicateExpander::expandCheckFunctionPredicateWithTII(
208     raw_ostream &OS, StringRef MCInstFn, StringRef MachineInstrFn,
209     StringRef TIIPtr) {
210   if (!shouldExpandForMC()) {
211     OS << (TIIPtr.empty() ? "TII" : TIIPtr) << "->" << MachineInstrFn;
212     OS << (isByRef() ? "(MI)" : "(*MI)");
213     return;
214   }
215 
216   OS << MCInstFn << (isByRef() ? "(MI" : "(*MI") << ", MCII)";
217 }
218 
219 void PredicateExpander::expandCheckFunctionPredicate(raw_ostream &OS,
220                                                      StringRef MCInstFn,
221                                                      StringRef MachineInstrFn) {
222   OS << (shouldExpandForMC() ? MCInstFn : MachineInstrFn)
223      << (isByRef() ? "(MI)" : "(*MI)");
224 }
225 
226 void PredicateExpander::expandCheckNonPortable(raw_ostream &OS,
227                                                StringRef Code) {
228   if (shouldExpandForMC())
229     return expandFalse(OS);
230 
231   OS << '(' << Code << ')';
232 }
233 
234 void PredicateExpander::expandReturnStatement(raw_ostream &OS,
235                                               const Record *Rec) {
236   std::string Buffer;
237   raw_string_ostream SS(Buffer);
238 
239   SS << "return ";
240   expandPredicate(SS, Rec);
241   SS << ";";
242   OS << Buffer;
243 }
244 
245 void PredicateExpander::expandOpcodeSwitchCase(raw_ostream &OS,
246                                                const Record *Rec) {
247   const RecVec &Opcodes = Rec->getValueAsListOfDefs("Opcodes");
248   for (const Record *Opcode : Opcodes) {
249     OS.indent(getIndentLevel() * 2);
250     OS << "case " << Opcode->getValueAsString("Namespace")
251        << "::" << Opcode->getName() << ":\n";
252   }
253 
254   increaseIndentLevel();
255   OS.indent(getIndentLevel() * 2);
256   expandStatement(OS, Rec->getValueAsDef("CaseStmt"));
257   decreaseIndentLevel();
258 }
259 
260 void PredicateExpander::expandOpcodeSwitchStatement(raw_ostream &OS,
261                                                     const RecVec &Cases,
262                                                     const Record *Default) {
263   std::string Buffer;
264   raw_string_ostream SS(Buffer);
265 
266   SS << "switch(MI" << (isByRef() ? "." : "->") << "getOpcode()) {\n";
267   for (const Record *Rec : Cases) {
268     expandOpcodeSwitchCase(SS, Rec);
269     SS << '\n';
270   }
271 
272   // Expand the default case.
273   SS.indent(getIndentLevel() * 2);
274   SS << "default:\n";
275 
276   increaseIndentLevel();
277   SS.indent(getIndentLevel() * 2);
278   expandStatement(SS, Default);
279   decreaseIndentLevel();
280   SS << '\n';
281 
282   SS.indent(getIndentLevel() * 2);
283   SS << "} // end of switch-stmt";
284   OS << Buffer;
285 }
286 
287 void PredicateExpander::expandStatement(raw_ostream &OS, const Record *Rec) {
288   // Assume that padding has been added by the caller.
289   if (Rec->isSubClassOf("MCOpcodeSwitchStatement")) {
290     expandOpcodeSwitchStatement(OS, Rec->getValueAsListOfDefs("Cases"),
291                                 Rec->getValueAsDef("DefaultCase"));
292     return;
293   }
294 
295   if (Rec->isSubClassOf("MCReturnStatement")) {
296     expandReturnStatement(OS, Rec->getValueAsDef("Pred"));
297     return;
298   }
299 
300   llvm_unreachable("No known rules to expand this MCStatement");
301 }
302 
303 void PredicateExpander::expandPredicate(raw_ostream &OS, const Record *Rec) {
304   // Assume that padding has been added by the caller.
305   if (Rec->isSubClassOf("MCTrue")) {
306     if (shouldNegate())
307       return expandFalse(OS);
308     return expandTrue(OS);
309   }
310 
311   if (Rec->isSubClassOf("MCFalse")) {
312     if (shouldNegate())
313       return expandTrue(OS);
314     return expandFalse(OS);
315   }
316 
317   if (Rec->isSubClassOf("CheckNot")) {
318     flipNegatePredicate();
319     expandPredicate(OS, Rec->getValueAsDef("Pred"));
320     flipNegatePredicate();
321     return;
322   }
323 
324   if (Rec->isSubClassOf("CheckIsRegOperand"))
325     return expandCheckIsRegOperand(OS, Rec->getValueAsInt("OpIndex"));
326 
327   if (Rec->isSubClassOf("CheckIsVRegOperand"))
328     return expandCheckIsVRegOperand(OS, Rec->getValueAsInt("OpIndex"));
329 
330   if (Rec->isSubClassOf("CheckIsImmOperand"))
331     return expandCheckIsImmOperand(OS, Rec->getValueAsInt("OpIndex"));
332 
333   if (Rec->isSubClassOf("CheckRegOperand"))
334     return expandCheckRegOperand(OS, Rec->getValueAsInt("OpIndex"),
335                                  Rec->getValueAsDef("Reg"),
336                                  Rec->getValueAsString("FunctionMapper"));
337 
338   if (Rec->isSubClassOf("CheckRegOperandSimple"))
339     return expandCheckRegOperandSimple(OS, Rec->getValueAsInt("OpIndex"),
340                                        Rec->getValueAsString("FunctionMapper"));
341 
342   if (Rec->isSubClassOf("CheckInvalidRegOperand"))
343     return expandCheckInvalidRegOperand(OS, Rec->getValueAsInt("OpIndex"));
344 
345   if (Rec->isSubClassOf("CheckImmOperand"))
346     return expandCheckImmOperand(OS, Rec->getValueAsInt("OpIndex"),
347                                  Rec->getValueAsInt("ImmVal"),
348                                  Rec->getValueAsString("FunctionMapper"));
349 
350   if (Rec->isSubClassOf("CheckImmOperand_s"))
351     return expandCheckImmOperand(OS, Rec->getValueAsInt("OpIndex"),
352                                  Rec->getValueAsString("ImmVal"),
353                                  Rec->getValueAsString("FunctionMapper"));
354 
355   if (Rec->isSubClassOf("CheckImmOperandSimple"))
356     return expandCheckImmOperandSimple(OS, Rec->getValueAsInt("OpIndex"),
357                                        Rec->getValueAsString("FunctionMapper"));
358 
359   if (Rec->isSubClassOf("CheckSameRegOperand"))
360     return expandCheckSameRegOperand(OS, Rec->getValueAsInt("FirstIndex"),
361                                      Rec->getValueAsInt("SecondIndex"));
362 
363   if (Rec->isSubClassOf("CheckNumOperands"))
364     return expandCheckNumOperands(OS, Rec->getValueAsInt("NumOps"));
365 
366   if (Rec->isSubClassOf("CheckPseudo"))
367     return expandCheckPseudo(OS, Rec->getValueAsListOfDefs("ValidOpcodes"));
368 
369   if (Rec->isSubClassOf("CheckOpcode"))
370     return expandCheckOpcode(OS, Rec->getValueAsListOfDefs("ValidOpcodes"));
371 
372   if (Rec->isSubClassOf("CheckAll"))
373     return expandPredicateSequence(OS, Rec->getValueAsListOfDefs("Predicates"),
374                                    /* AllOf */ true);
375 
376   if (Rec->isSubClassOf("CheckAny"))
377     return expandPredicateSequence(OS, Rec->getValueAsListOfDefs("Predicates"),
378                                    /* AllOf */ false);
379 
380   if (Rec->isSubClassOf("CheckFunctionPredicate")) {
381     return expandCheckFunctionPredicate(
382         OS, Rec->getValueAsString("MCInstFnName"),
383         Rec->getValueAsString("MachineInstrFnName"));
384   }
385 
386   if (Rec->isSubClassOf("CheckFunctionPredicateWithTII")) {
387     return expandCheckFunctionPredicateWithTII(
388         OS, Rec->getValueAsString("MCInstFnName"),
389         Rec->getValueAsString("MachineInstrFnName"),
390         Rec->getValueAsString("TIIPtrName"));
391   }
392 
393   if (Rec->isSubClassOf("CheckNonPortable"))
394     return expandCheckNonPortable(OS, Rec->getValueAsString("CodeBlock"));
395 
396   if (Rec->isSubClassOf("TIIPredicate"))
397     return expandTIIFunctionCall(OS, Rec->getValueAsString("FunctionName"));
398 
399   llvm_unreachable("No known rules to expand this MCInstPredicate");
400 }
401 
402 void STIPredicateExpander::expandHeader(raw_ostream &OS,
403                                         const STIPredicateFunction &Fn) {
404   const Record *Rec = Fn.getDeclaration();
405   StringRef FunctionName = Rec->getValueAsString("Name");
406 
407   OS.indent(getIndentLevel() * 2);
408   OS << "bool ";
409   if (shouldExpandDefinition())
410     OS << getClassPrefix() << "::";
411   OS << FunctionName << "(";
412   if (shouldExpandForMC())
413     OS << "const MCInst " << (isByRef() ? "&" : "*") << "MI";
414   else
415     OS << "const MachineInstr " << (isByRef() ? "&" : "*") << "MI";
416   if (Rec->getValueAsBit("UpdatesOpcodeMask"))
417     OS << ", APInt &Mask";
418   OS << (shouldExpandForMC() ? ", unsigned ProcessorID) const " : ") const ");
419   if (shouldExpandDefinition()) {
420     OS << "{\n";
421     return;
422   }
423 
424   if (Rec->getValueAsBit("OverridesBaseClassMember"))
425     OS << "override";
426   OS << ";\n";
427 }
428 
429 void STIPredicateExpander::expandPrologue(raw_ostream &OS,
430                                           const STIPredicateFunction &Fn) {
431   RecVec Delegates = Fn.getDeclaration()->getValueAsListOfDefs("Delegates");
432   bool UpdatesOpcodeMask =
433       Fn.getDeclaration()->getValueAsBit("UpdatesOpcodeMask");
434 
435   increaseIndentLevel();
436   unsigned IndentLevel = getIndentLevel();
437   for (const Record *Delegate : Delegates) {
438     OS.indent(IndentLevel * 2);
439     OS << "if (" << Delegate->getValueAsString("Name") << "(MI";
440     if (UpdatesOpcodeMask)
441       OS << ", Mask";
442     if (shouldExpandForMC())
443       OS << ", ProcessorID";
444     OS << "))\n";
445     OS.indent((1 + IndentLevel) * 2);
446     OS << "return true;\n\n";
447   }
448 
449   if (shouldExpandForMC())
450     return;
451 
452   OS.indent(IndentLevel * 2);
453   OS << "unsigned ProcessorID = getSchedModel().getProcessorID();\n";
454 }
455 
456 void STIPredicateExpander::expandOpcodeGroup(raw_ostream &OS, const OpcodeGroup &Group,
457                                              bool ShouldUpdateOpcodeMask) {
458   const OpcodeInfo &OI = Group.getOpcodeInfo();
459   for (const PredicateInfo &PI : OI.getPredicates()) {
460     const APInt &ProcModelMask = PI.ProcModelMask;
461     bool FirstProcID = true;
462     for (unsigned I = 0, E = ProcModelMask.getActiveBits(); I < E; ++I) {
463       if (!ProcModelMask[I])
464         continue;
465 
466       if (FirstProcID) {
467         OS.indent(getIndentLevel() * 2);
468         OS << "if (ProcessorID == " << I;
469       } else {
470         OS << " || ProcessorID == " << I;
471       }
472       FirstProcID = false;
473     }
474 
475     OS << ") {\n";
476 
477     increaseIndentLevel();
478     OS.indent(getIndentLevel() * 2);
479     if (ShouldUpdateOpcodeMask) {
480       if (PI.OperandMask.isZero())
481         OS << "Mask.clearAllBits();\n";
482       else
483         OS << "Mask = " << PI.OperandMask << ";\n";
484       OS.indent(getIndentLevel() * 2);
485     }
486     OS << "return ";
487     expandPredicate(OS, PI.Predicate);
488     OS << ";\n";
489     decreaseIndentLevel();
490     OS.indent(getIndentLevel() * 2);
491     OS << "}\n";
492   }
493 }
494 
495 void STIPredicateExpander::expandBody(raw_ostream &OS,
496                                       const STIPredicateFunction &Fn) {
497   bool UpdatesOpcodeMask =
498       Fn.getDeclaration()->getValueAsBit("UpdatesOpcodeMask");
499 
500   unsigned IndentLevel = getIndentLevel();
501   OS.indent(IndentLevel * 2);
502   OS << "switch(MI" << (isByRef() ? "." : "->") << "getOpcode()) {\n";
503   OS.indent(IndentLevel * 2);
504   OS << "default:\n";
505   OS.indent(IndentLevel * 2);
506   OS << "  break;";
507 
508   for (const OpcodeGroup &Group : Fn.getGroups()) {
509     for (const Record *Opcode : Group.getOpcodes()) {
510       OS << '\n';
511       OS.indent(IndentLevel * 2);
512       OS << "case " << getTargetName() << "::" << Opcode->getName() << ":";
513     }
514 
515     OS << '\n';
516     increaseIndentLevel();
517     expandOpcodeGroup(OS, Group, UpdatesOpcodeMask);
518 
519     OS.indent(getIndentLevel() * 2);
520     OS << "break;\n";
521     decreaseIndentLevel();
522   }
523 
524   OS.indent(IndentLevel * 2);
525   OS << "}\n";
526 }
527 
528 void STIPredicateExpander::expandEpilogue(raw_ostream &OS,
529                                           const STIPredicateFunction &Fn) {
530   OS << '\n';
531   OS.indent(getIndentLevel() * 2);
532   OS << "return ";
533   expandPredicate(OS, Fn.getDefaultReturnPredicate());
534   OS << ";\n";
535 
536   decreaseIndentLevel();
537   OS.indent(getIndentLevel() * 2);
538   StringRef FunctionName = Fn.getDeclaration()->getValueAsString("Name");
539   OS << "} // " << ClassPrefix << "::" << FunctionName << "\n\n";
540 }
541 
542 void STIPredicateExpander::expandSTIPredicate(raw_ostream &OS,
543                                               const STIPredicateFunction &Fn) {
544   const Record *Rec = Fn.getDeclaration();
545   if (shouldExpandForMC() && !Rec->getValueAsBit("ExpandForMC"))
546     return;
547 
548   expandHeader(OS, Fn);
549   if (shouldExpandDefinition()) {
550     expandPrologue(OS, Fn);
551     expandBody(OS, Fn);
552     expandEpilogue(OS, Fn);
553   }
554 }
555 
556 } // namespace llvm
557