1 //===--------------------- PredicateExpander.cpp --------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 /// \file
10 /// Functionalities used by the Tablegen backends to expand machine predicates.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "PredicateExpander.h"
15 #include "CodeGenSchedule.h" // Definition of STIPredicateFunction.
16 
17 namespace llvm {
18 
expandTrue(raw_ostream & OS)19 void PredicateExpander::expandTrue(raw_ostream &OS) { OS << "true"; }
expandFalse(raw_ostream & OS)20 void PredicateExpander::expandFalse(raw_ostream &OS) { OS << "false"; }
21 
expandCheckImmOperand(raw_ostream & OS,int OpIndex,int ImmVal,StringRef FunctionMapper)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 
expandCheckImmOperand(raw_ostream & OS,int OpIndex,StringRef ImmVal,StringRef FunctionMapper)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 
expandCheckImmOperandSimple(raw_ostream & OS,int OpIndex,StringRef FunctionMapper)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 
expandCheckRegOperand(raw_ostream & OS,int OpIndex,const Record * Reg,StringRef FunctionMapper)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 
expandCheckRegOperandSimple(raw_ostream & OS,int OpIndex,StringRef FunctionMapper)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 
expandCheckInvalidRegOperand(raw_ostream & OS,int OpIndex)94 void PredicateExpander::expandCheckInvalidRegOperand(raw_ostream &OS,
95                                                      int OpIndex) {
96   OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
97      << ").getReg() " << (shouldNegate() ? "!= " : "== ") << "0";
98 }
99 
expandCheckSameRegOperand(raw_ostream & OS,int First,int Second)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 
expandCheckNumOperands(raw_ostream & OS,int NumOps)107 void PredicateExpander::expandCheckNumOperands(raw_ostream &OS, int NumOps) {
108   OS << "MI" << (isByRef() ? "." : "->") << "getNumOperands() "
109      << (shouldNegate() ? "!= " : "== ") << NumOps;
110 }
111 
expandCheckOpcode(raw_ostream & OS,const Record * Inst)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 
expandCheckOpcode(raw_ostream & OS,const RecVec & Opcodes)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 
expandCheckPseudo(raw_ostream & OS,const RecVec & Opcodes)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 
expandPredicateSequence(raw_ostream & OS,const RecVec & Sequence,bool IsCheckAll)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 
expandTIIFunctionCall(raw_ostream & OS,StringRef MethodName)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 
expandCheckIsRegOperand(raw_ostream & OS,int OpIndex)192 void PredicateExpander::expandCheckIsRegOperand(raw_ostream &OS, int OpIndex) {
193   OS << (shouldNegate() ? "!" : "") << "MI" << (isByRef() ? "." : "->")
194      << "getOperand(" << OpIndex << ").isReg() ";
195 }
196 
expandCheckIsImmOperand(raw_ostream & OS,int OpIndex)197 void PredicateExpander::expandCheckIsImmOperand(raw_ostream &OS, int OpIndex) {
198   OS << (shouldNegate() ? "!" : "") << "MI" << (isByRef() ? "." : "->")
199      << "getOperand(" << OpIndex << ").isImm() ";
200 }
201 
expandCheckFunctionPredicate(raw_ostream & OS,StringRef MCInstFn,StringRef MachineInstrFn)202 void PredicateExpander::expandCheckFunctionPredicate(raw_ostream &OS,
203                                                      StringRef MCInstFn,
204                                                      StringRef MachineInstrFn) {
205   OS << (shouldExpandForMC() ? MCInstFn : MachineInstrFn)
206      << (isByRef() ? "(MI)" : "(*MI)");
207 }
208 
expandCheckNonPortable(raw_ostream & OS,StringRef Code)209 void PredicateExpander::expandCheckNonPortable(raw_ostream &OS,
210                                                StringRef Code) {
211   if (shouldExpandForMC())
212     return expandFalse(OS);
213 
214   OS << '(' << Code << ')';
215 }
216 
expandReturnStatement(raw_ostream & OS,const Record * Rec)217 void PredicateExpander::expandReturnStatement(raw_ostream &OS,
218                                               const Record *Rec) {
219   std::string Buffer;
220   raw_string_ostream SS(Buffer);
221 
222   SS << "return ";
223   expandPredicate(SS, Rec);
224   SS << ";";
225   SS.flush();
226   OS << Buffer;
227 }
228 
expandOpcodeSwitchCase(raw_ostream & OS,const Record * Rec)229 void PredicateExpander::expandOpcodeSwitchCase(raw_ostream &OS,
230                                                const Record *Rec) {
231   const RecVec &Opcodes = Rec->getValueAsListOfDefs("Opcodes");
232   for (const Record *Opcode : Opcodes) {
233     OS.indent(getIndentLevel() * 2);
234     OS << "case " << Opcode->getValueAsString("Namespace")
235        << "::" << Opcode->getName() << ":\n";
236   }
237 
238   increaseIndentLevel();
239   OS.indent(getIndentLevel() * 2);
240   expandStatement(OS, Rec->getValueAsDef("CaseStmt"));
241   decreaseIndentLevel();
242 }
243 
expandOpcodeSwitchStatement(raw_ostream & OS,const RecVec & Cases,const Record * Default)244 void PredicateExpander::expandOpcodeSwitchStatement(raw_ostream &OS,
245                                                     const RecVec &Cases,
246                                                     const Record *Default) {
247   std::string Buffer;
248   raw_string_ostream SS(Buffer);
249 
250   SS << "switch(MI" << (isByRef() ? "." : "->") << "getOpcode()) {\n";
251   for (const Record *Rec : Cases) {
252     expandOpcodeSwitchCase(SS, Rec);
253     SS << '\n';
254   }
255 
256   // Expand the default case.
257   SS.indent(getIndentLevel() * 2);
258   SS << "default:\n";
259 
260   increaseIndentLevel();
261   SS.indent(getIndentLevel() * 2);
262   expandStatement(SS, Default);
263   decreaseIndentLevel();
264   SS << '\n';
265 
266   SS.indent(getIndentLevel() * 2);
267   SS << "} // end of switch-stmt";
268   SS.flush();
269   OS << Buffer;
270 }
271 
expandStatement(raw_ostream & OS,const Record * Rec)272 void PredicateExpander::expandStatement(raw_ostream &OS, const Record *Rec) {
273   // Assume that padding has been added by the caller.
274   if (Rec->isSubClassOf("MCOpcodeSwitchStatement")) {
275     expandOpcodeSwitchStatement(OS, Rec->getValueAsListOfDefs("Cases"),
276                                 Rec->getValueAsDef("DefaultCase"));
277     return;
278   }
279 
280   if (Rec->isSubClassOf("MCReturnStatement")) {
281     expandReturnStatement(OS, Rec->getValueAsDef("Pred"));
282     return;
283   }
284 
285   llvm_unreachable("No known rules to expand this MCStatement");
286 }
287 
expandPredicate(raw_ostream & OS,const Record * Rec)288 void PredicateExpander::expandPredicate(raw_ostream &OS, const Record *Rec) {
289   // Assume that padding has been added by the caller.
290   if (Rec->isSubClassOf("MCTrue")) {
291     if (shouldNegate())
292       return expandFalse(OS);
293     return expandTrue(OS);
294   }
295 
296   if (Rec->isSubClassOf("MCFalse")) {
297     if (shouldNegate())
298       return expandTrue(OS);
299     return expandFalse(OS);
300   }
301 
302   if (Rec->isSubClassOf("CheckNot")) {
303     flipNegatePredicate();
304     expandPredicate(OS, Rec->getValueAsDef("Pred"));
305     flipNegatePredicate();
306     return;
307   }
308 
309   if (Rec->isSubClassOf("CheckIsRegOperand"))
310     return expandCheckIsRegOperand(OS, Rec->getValueAsInt("OpIndex"));
311 
312   if (Rec->isSubClassOf("CheckIsImmOperand"))
313     return expandCheckIsImmOperand(OS, Rec->getValueAsInt("OpIndex"));
314 
315   if (Rec->isSubClassOf("CheckRegOperand"))
316     return expandCheckRegOperand(OS, Rec->getValueAsInt("OpIndex"),
317                                  Rec->getValueAsDef("Reg"),
318                                  Rec->getValueAsString("FunctionMapper"));
319 
320   if (Rec->isSubClassOf("CheckRegOperandSimple"))
321     return expandCheckRegOperandSimple(OS, Rec->getValueAsInt("OpIndex"),
322                                        Rec->getValueAsString("FunctionMapper"));
323 
324   if (Rec->isSubClassOf("CheckInvalidRegOperand"))
325     return expandCheckInvalidRegOperand(OS, Rec->getValueAsInt("OpIndex"));
326 
327   if (Rec->isSubClassOf("CheckImmOperand"))
328     return expandCheckImmOperand(OS, Rec->getValueAsInt("OpIndex"),
329                                  Rec->getValueAsInt("ImmVal"),
330                                  Rec->getValueAsString("FunctionMapper"));
331 
332   if (Rec->isSubClassOf("CheckImmOperand_s"))
333     return expandCheckImmOperand(OS, Rec->getValueAsInt("OpIndex"),
334                                  Rec->getValueAsString("ImmVal"),
335                                  Rec->getValueAsString("FunctionMapper"));
336 
337   if (Rec->isSubClassOf("CheckImmOperandSimple"))
338     return expandCheckImmOperandSimple(OS, Rec->getValueAsInt("OpIndex"),
339                                        Rec->getValueAsString("FunctionMapper"));
340 
341   if (Rec->isSubClassOf("CheckSameRegOperand"))
342     return expandCheckSameRegOperand(OS, Rec->getValueAsInt("FirstIndex"),
343                                      Rec->getValueAsInt("SecondIndex"));
344 
345   if (Rec->isSubClassOf("CheckNumOperands"))
346     return expandCheckNumOperands(OS, Rec->getValueAsInt("NumOps"));
347 
348   if (Rec->isSubClassOf("CheckPseudo"))
349     return expandCheckPseudo(OS, Rec->getValueAsListOfDefs("ValidOpcodes"));
350 
351   if (Rec->isSubClassOf("CheckOpcode"))
352     return expandCheckOpcode(OS, Rec->getValueAsListOfDefs("ValidOpcodes"));
353 
354   if (Rec->isSubClassOf("CheckAll"))
355     return expandPredicateSequence(OS, Rec->getValueAsListOfDefs("Predicates"),
356                                    /* AllOf */ true);
357 
358   if (Rec->isSubClassOf("CheckAny"))
359     return expandPredicateSequence(OS, Rec->getValueAsListOfDefs("Predicates"),
360                                    /* AllOf */ false);
361 
362   if (Rec->isSubClassOf("CheckFunctionPredicate"))
363     return expandCheckFunctionPredicate(
364         OS, Rec->getValueAsString("MCInstFnName"),
365         Rec->getValueAsString("MachineInstrFnName"));
366 
367   if (Rec->isSubClassOf("CheckNonPortable"))
368     return expandCheckNonPortable(OS, Rec->getValueAsString("CodeBlock"));
369 
370   if (Rec->isSubClassOf("TIIPredicate"))
371     return expandTIIFunctionCall(OS, Rec->getValueAsString("FunctionName"));
372 
373   llvm_unreachable("No known rules to expand this MCInstPredicate");
374 }
375 
expandHeader(raw_ostream & OS,const STIPredicateFunction & Fn)376 void STIPredicateExpander::expandHeader(raw_ostream &OS,
377                                         const STIPredicateFunction &Fn) {
378   const Record *Rec = Fn.getDeclaration();
379   StringRef FunctionName = Rec->getValueAsString("Name");
380 
381   OS.indent(getIndentLevel() * 2);
382   OS << "bool ";
383   if (shouldExpandDefinition())
384     OS << getClassPrefix() << "::";
385   OS << FunctionName << "(";
386   if (shouldExpandForMC())
387     OS << "const MCInst " << (isByRef() ? "&" : "*") << "MI";
388   else
389     OS << "const MachineInstr " << (isByRef() ? "&" : "*") << "MI";
390   if (Rec->getValueAsBit("UpdatesOpcodeMask"))
391     OS << ", APInt &Mask";
392   OS << (shouldExpandForMC() ? ", unsigned ProcessorID) const " : ") const ");
393   if (shouldExpandDefinition()) {
394     OS << "{\n";
395     return;
396   }
397 
398   if (Rec->getValueAsBit("OverridesBaseClassMember"))
399     OS << "override";
400   OS << ";\n";
401 }
402 
expandPrologue(raw_ostream & OS,const STIPredicateFunction & Fn)403 void STIPredicateExpander::expandPrologue(raw_ostream &OS,
404                                           const STIPredicateFunction &Fn) {
405   RecVec Delegates = Fn.getDeclaration()->getValueAsListOfDefs("Delegates");
406   bool UpdatesOpcodeMask =
407       Fn.getDeclaration()->getValueAsBit("UpdatesOpcodeMask");
408 
409   increaseIndentLevel();
410   unsigned IndentLevel = getIndentLevel();
411   for (const Record *Delegate : Delegates) {
412     OS.indent(IndentLevel * 2);
413     OS << "if (" << Delegate->getValueAsString("Name") << "(MI";
414     if (UpdatesOpcodeMask)
415       OS << ", Mask";
416     if (shouldExpandForMC())
417       OS << ", ProcessorID";
418     OS << "))\n";
419     OS.indent((1 + IndentLevel) * 2);
420     OS << "return true;\n\n";
421   }
422 
423   if (shouldExpandForMC())
424     return;
425 
426   OS.indent(IndentLevel * 2);
427   OS << "unsigned ProcessorID = getSchedModel().getProcessorID();\n";
428 }
429 
expandOpcodeGroup(raw_ostream & OS,const OpcodeGroup & Group,bool ShouldUpdateOpcodeMask)430 void STIPredicateExpander::expandOpcodeGroup(raw_ostream &OS, const OpcodeGroup &Group,
431                                              bool ShouldUpdateOpcodeMask) {
432   const OpcodeInfo &OI = Group.getOpcodeInfo();
433   for (const PredicateInfo &PI : OI.getPredicates()) {
434     const APInt &ProcModelMask = PI.ProcModelMask;
435     bool FirstProcID = true;
436     for (unsigned I = 0, E = ProcModelMask.getActiveBits(); I < E; ++I) {
437       if (!ProcModelMask[I])
438         continue;
439 
440       if (FirstProcID) {
441         OS.indent(getIndentLevel() * 2);
442         OS << "if (ProcessorID == " << I;
443       } else {
444         OS << " || ProcessorID == " << I;
445       }
446       FirstProcID = false;
447     }
448 
449     OS << ") {\n";
450 
451     increaseIndentLevel();
452     OS.indent(getIndentLevel() * 2);
453     if (ShouldUpdateOpcodeMask) {
454       if (PI.OperandMask.isNullValue())
455         OS << "Mask.clearAllBits();\n";
456       else
457         OS << "Mask = " << PI.OperandMask << ";\n";
458       OS.indent(getIndentLevel() * 2);
459     }
460     OS << "return ";
461     expandPredicate(OS, PI.Predicate);
462     OS << ";\n";
463     decreaseIndentLevel();
464     OS.indent(getIndentLevel() * 2);
465     OS << "}\n";
466   }
467 }
468 
expandBody(raw_ostream & OS,const STIPredicateFunction & Fn)469 void STIPredicateExpander::expandBody(raw_ostream &OS,
470                                       const STIPredicateFunction &Fn) {
471   bool UpdatesOpcodeMask =
472       Fn.getDeclaration()->getValueAsBit("UpdatesOpcodeMask");
473 
474   unsigned IndentLevel = getIndentLevel();
475   OS.indent(IndentLevel * 2);
476   OS << "switch(MI" << (isByRef() ? "." : "->") << "getOpcode()) {\n";
477   OS.indent(IndentLevel * 2);
478   OS << "default:\n";
479   OS.indent(IndentLevel * 2);
480   OS << "  break;";
481 
482   for (const OpcodeGroup &Group : Fn.getGroups()) {
483     for (const Record *Opcode : Group.getOpcodes()) {
484       OS << '\n';
485       OS.indent(IndentLevel * 2);
486       OS << "case " << getTargetName() << "::" << Opcode->getName() << ":";
487     }
488 
489     OS << '\n';
490     increaseIndentLevel();
491     expandOpcodeGroup(OS, Group, UpdatesOpcodeMask);
492 
493     OS.indent(getIndentLevel() * 2);
494     OS << "break;\n";
495     decreaseIndentLevel();
496   }
497 
498   OS.indent(IndentLevel * 2);
499   OS << "}\n";
500 }
501 
expandEpilogue(raw_ostream & OS,const STIPredicateFunction & Fn)502 void STIPredicateExpander::expandEpilogue(raw_ostream &OS,
503                                           const STIPredicateFunction &Fn) {
504   OS << '\n';
505   OS.indent(getIndentLevel() * 2);
506   OS << "return ";
507   expandPredicate(OS, Fn.getDefaultReturnPredicate());
508   OS << ";\n";
509 
510   decreaseIndentLevel();
511   OS.indent(getIndentLevel() * 2);
512   StringRef FunctionName = Fn.getDeclaration()->getValueAsString("Name");
513   OS << "} // " << ClassPrefix << "::" << FunctionName << "\n\n";
514 }
515 
expandSTIPredicate(raw_ostream & OS,const STIPredicateFunction & Fn)516 void STIPredicateExpander::expandSTIPredicate(raw_ostream &OS,
517                                               const STIPredicateFunction &Fn) {
518   const Record *Rec = Fn.getDeclaration();
519   if (shouldExpandForMC() && !Rec->getValueAsBit("ExpandForMC"))
520     return;
521 
522   expandHeader(OS, Fn);
523   if (shouldExpandDefinition()) {
524     expandPrologue(OS, Fn);
525     expandBody(OS, Fn);
526     expandEpilogue(OS, Fn);
527   }
528 }
529 
530 } // namespace llvm
531