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