PredicateExpander.cpp revision 344779
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
17namespace llvm {
18
19void PredicateExpander::expandTrue(raw_ostream &OS) { OS << "true"; }
20void PredicateExpander::expandFalse(raw_ostream &OS) { OS << "false"; }
21
22void 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
34void 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
49void 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
62void 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
81void 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
94void PredicateExpander::expandCheckInvalidRegOperand(raw_ostream &OS,
95                                                     int OpIndex) {
96  OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
97     << ").getReg() " << (shouldNegate() ? "!= " : "== ") << "0";
98}
99
100void 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
107void PredicateExpander::expandCheckNumOperands(raw_ostream &OS, int NumOps) {
108  OS << "MI" << (isByRef() ? "." : "->") << "getNumOperands() "
109     << (shouldNegate() ? "!= " : "== ") << NumOps;
110}
111
112void PredicateExpander::expandCheckOpcode(raw_ostream &OS, const Record *Inst) {
113  OS << "MI" << (isByRef() ? "." : "->") << "getOpcode() "
114     << (shouldNegate() ? "!= " : "== ") << Inst->getValueAsString("Namespace")
115     << "::" << Inst->getName();
116}
117
118void 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
148void PredicateExpander::expandCheckPseudo(raw_ostream &OS,
149                                          const RecVec &Opcodes) {
150  if (shouldExpandForMC())
151    expandFalse(OS);
152  else
153    expandCheckOpcode(OS, Opcodes);
154}
155
156void 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
185void 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
192void PredicateExpander::expandCheckIsRegOperand(raw_ostream &OS, int OpIndex) {
193  OS << (shouldNegate() ? "!" : "") << "MI" << (isByRef() ? "." : "->")
194     << "getOperand(" << OpIndex << ").isReg() ";
195}
196
197void PredicateExpander::expandCheckIsImmOperand(raw_ostream &OS, int OpIndex) {
198  OS << (shouldNegate() ? "!" : "") << "MI" << (isByRef() ? "." : "->")
199     << "getOperand(" << OpIndex << ").isImm() ";
200}
201
202void PredicateExpander::expandCheckFunctionPredicate(raw_ostream &OS,
203                                                     StringRef MCInstFn,
204                                                     StringRef MachineInstrFn) {
205  OS << (shouldExpandForMC() ? MCInstFn : MachineInstrFn)
206     << (isByRef() ? "(MI)" : "(*MI)");
207}
208
209void PredicateExpander::expandCheckNonPortable(raw_ostream &OS,
210                                               StringRef Code) {
211  if (shouldExpandForMC())
212    return expandFalse(OS);
213
214  OS << '(' << Code << ')';
215}
216
217void 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
229void 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
244void 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
272void 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
288void 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
376void 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
403void 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
430void 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
469void 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
502void 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
516void 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