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