1336809Sdim//===--------------------- PredicateExpander.cpp --------------------------===//
2336809Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6336809Sdim//
7336809Sdim//===----------------------------------------------------------------------===//
8336809Sdim/// \file
9336809Sdim/// Functionalities used by the Tablegen backends to expand machine predicates.
10336809Sdim//
11336809Sdim//===----------------------------------------------------------------------===//
12336809Sdim
13336809Sdim#include "PredicateExpander.h"
14344779Sdim#include "CodeGenSchedule.h" // Definition of STIPredicateFunction.
15336809Sdim
16336809Sdimnamespace llvm {
17336809Sdim
18344779Sdimvoid PredicateExpander::expandTrue(raw_ostream &OS) { OS << "true"; }
19344779Sdimvoid PredicateExpander::expandFalse(raw_ostream &OS) { OS << "false"; }
20344779Sdim
21344779Sdimvoid PredicateExpander::expandCheckImmOperand(raw_ostream &OS, int OpIndex,
22344779Sdim                                              int ImmVal,
23344779Sdim                                              StringRef FunctionMapper) {
24344779Sdim  if (!FunctionMapper.empty())
25344779Sdim    OS << FunctionMapper << "(";
26344779Sdim  OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
27344779Sdim     << ").getImm()";
28344779Sdim  if (!FunctionMapper.empty())
29344779Sdim    OS << ")";
30344779Sdim  OS << (shouldNegate() ? " != " : " == ") << ImmVal;
31336809Sdim}
32336809Sdim
33344779Sdimvoid PredicateExpander::expandCheckImmOperand(raw_ostream &OS, int OpIndex,
34344779Sdim                                              StringRef ImmVal,
35344779Sdim                                              StringRef FunctionMapper) {
36344779Sdim  if (ImmVal.empty())
37344779Sdim    expandCheckImmOperandSimple(OS, OpIndex, FunctionMapper);
38344779Sdim
39344779Sdim  if (!FunctionMapper.empty())
40344779Sdim    OS << FunctionMapper << "(";
41336809Sdim  OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
42344779Sdim     << ").getImm()";
43344779Sdim  if (!FunctionMapper.empty())
44344779Sdim    OS << ")";
45344779Sdim  OS << (shouldNegate() ? " != " : " == ") << ImmVal;
46336809Sdim}
47336809Sdim
48344779Sdimvoid PredicateExpander::expandCheckImmOperandSimple(raw_ostream &OS,
49344779Sdim                                                    int OpIndex,
50344779Sdim                                                    StringRef FunctionMapper) {
51344779Sdim  if (shouldNegate())
52344779Sdim    OS << "!";
53344779Sdim  if (!FunctionMapper.empty())
54344779Sdim    OS << FunctionMapper << "(";
55336809Sdim  OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
56344779Sdim     << ").getImm()";
57344779Sdim  if (!FunctionMapper.empty())
58344779Sdim    OS << ")";
59336809Sdim}
60336809Sdim
61344779Sdimvoid PredicateExpander::expandCheckRegOperand(raw_ostream &OS, int OpIndex,
62344779Sdim                                              const Record *Reg,
63344779Sdim                                              StringRef FunctionMapper) {
64336809Sdim  assert(Reg->isSubClassOf("Register") && "Expected a register Record!");
65336809Sdim
66344779Sdim  if (!FunctionMapper.empty())
67344779Sdim    OS << FunctionMapper << "(";
68336809Sdim  OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
69344779Sdim     << ").getReg()";
70344779Sdim  if (!FunctionMapper.empty())
71344779Sdim    OS << ")";
72344779Sdim  OS << (shouldNegate() ? " != " : " == ");
73336809Sdim  const StringRef Str = Reg->getValueAsString("Namespace");
74336809Sdim  if (!Str.empty())
75336809Sdim    OS << Str << "::";
76336809Sdim  OS << Reg->getName();
77336809Sdim}
78336809Sdim
79344779Sdim
80344779Sdimvoid PredicateExpander::expandCheckRegOperandSimple(raw_ostream &OS,
81344779Sdim                                                    int OpIndex,
82344779Sdim                                                    StringRef FunctionMapper) {
83344779Sdim  if (shouldNegate())
84344779Sdim    OS << "!";
85344779Sdim  if (!FunctionMapper.empty())
86344779Sdim    OS << FunctionMapper << "(";
87344779Sdim  OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
88344779Sdim     << ").getReg()";
89344779Sdim  if (!FunctionMapper.empty())
90344779Sdim    OS << ")";
91344779Sdim}
92344779Sdim
93344779Sdimvoid PredicateExpander::expandCheckInvalidRegOperand(raw_ostream &OS,
94336809Sdim                                                     int OpIndex) {
95336809Sdim  OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
96336809Sdim     << ").getReg() " << (shouldNegate() ? "!= " : "== ") << "0";
97336809Sdim}
98336809Sdim
99344779Sdimvoid PredicateExpander::expandCheckSameRegOperand(raw_ostream &OS, int First,
100344779Sdim                                                  int Second) {
101336809Sdim  OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << First
102336809Sdim     << ").getReg() " << (shouldNegate() ? "!=" : "==") << " MI"
103336809Sdim     << (isByRef() ? "." : "->") << "getOperand(" << Second << ").getReg()";
104336809Sdim}
105336809Sdim
106344779Sdimvoid PredicateExpander::expandCheckNumOperands(raw_ostream &OS, int NumOps) {
107336809Sdim  OS << "MI" << (isByRef() ? "." : "->") << "getNumOperands() "
108336809Sdim     << (shouldNegate() ? "!= " : "== ") << NumOps;
109336809Sdim}
110336809Sdim
111344779Sdimvoid PredicateExpander::expandCheckOpcode(raw_ostream &OS, const Record *Inst) {
112336809Sdim  OS << "MI" << (isByRef() ? "." : "->") << "getOpcode() "
113336809Sdim     << (shouldNegate() ? "!= " : "== ") << Inst->getValueAsString("Namespace")
114336809Sdim     << "::" << Inst->getName();
115336809Sdim}
116336809Sdim
117344779Sdimvoid PredicateExpander::expandCheckOpcode(raw_ostream &OS,
118336809Sdim                                          const RecVec &Opcodes) {
119336809Sdim  assert(!Opcodes.empty() && "Expected at least one opcode to check!");
120336809Sdim  bool First = true;
121336809Sdim
122336809Sdim  if (Opcodes.size() == 1) {
123336809Sdim    OS << "( ";
124336809Sdim    expandCheckOpcode(OS, Opcodes[0]);
125336809Sdim    OS << " )";
126336809Sdim    return;
127336809Sdim  }
128336809Sdim
129336809Sdim  OS << '(';
130336809Sdim  increaseIndentLevel();
131336809Sdim  for (const Record *Rec : Opcodes) {
132336809Sdim    OS << '\n';
133344779Sdim    OS.indent(getIndentLevel() * 2);
134336809Sdim    if (!First)
135336809Sdim      OS << (shouldNegate() ? "&& " : "|| ");
136336809Sdim
137336809Sdim    expandCheckOpcode(OS, Rec);
138336809Sdim    First = false;
139336809Sdim  }
140336809Sdim
141336809Sdim  OS << '\n';
142336809Sdim  decreaseIndentLevel();
143344779Sdim  OS.indent(getIndentLevel() * 2);
144336809Sdim  OS << ')';
145336809Sdim}
146336809Sdim
147344779Sdimvoid PredicateExpander::expandCheckPseudo(raw_ostream &OS,
148336809Sdim                                          const RecVec &Opcodes) {
149336809Sdim  if (shouldExpandForMC())
150336809Sdim    expandFalse(OS);
151336809Sdim  else
152336809Sdim    expandCheckOpcode(OS, Opcodes);
153336809Sdim}
154336809Sdim
155344779Sdimvoid PredicateExpander::expandPredicateSequence(raw_ostream &OS,
156336809Sdim                                                const RecVec &Sequence,
157336809Sdim                                                bool IsCheckAll) {
158336809Sdim  assert(!Sequence.empty() && "Found an invalid empty predicate set!");
159336809Sdim  if (Sequence.size() == 1)
160336809Sdim    return expandPredicate(OS, Sequence[0]);
161336809Sdim
162336809Sdim  // Okay, there is more than one predicate in the set.
163336809Sdim  bool First = true;
164336809Sdim  OS << (shouldNegate() ? "!(" : "(");
165336809Sdim  increaseIndentLevel();
166336809Sdim
167336809Sdim  bool OldValue = shouldNegate();
168336809Sdim  setNegatePredicate(false);
169336809Sdim  for (const Record *Rec : Sequence) {
170336809Sdim    OS << '\n';
171344779Sdim    OS.indent(getIndentLevel() * 2);
172336809Sdim    if (!First)
173336809Sdim      OS << (IsCheckAll ? "&& " : "|| ");
174336809Sdim    expandPredicate(OS, Rec);
175336809Sdim    First = false;
176336809Sdim  }
177336809Sdim  OS << '\n';
178336809Sdim  decreaseIndentLevel();
179344779Sdim  OS.indent(getIndentLevel() * 2);
180336809Sdim  OS << ')';
181336809Sdim  setNegatePredicate(OldValue);
182336809Sdim}
183336809Sdim
184344779Sdimvoid PredicateExpander::expandTIIFunctionCall(raw_ostream &OS,
185336809Sdim                                              StringRef MethodName) {
186336809Sdim  OS << (shouldNegate() ? "!" : "");
187344779Sdim  OS << TargetName << (shouldExpandForMC() ? "_MC::" : "InstrInfo::");
188336809Sdim  OS << MethodName << (isByRef() ? "(MI)" : "(*MI)");
189336809Sdim}
190336809Sdim
191344779Sdimvoid PredicateExpander::expandCheckIsRegOperand(raw_ostream &OS, int OpIndex) {
192336809Sdim  OS << (shouldNegate() ? "!" : "") << "MI" << (isByRef() ? "." : "->")
193336809Sdim     << "getOperand(" << OpIndex << ").isReg() ";
194336809Sdim}
195336809Sdim
196344779Sdimvoid PredicateExpander::expandCheckIsImmOperand(raw_ostream &OS, int OpIndex) {
197336809Sdim  OS << (shouldNegate() ? "!" : "") << "MI" << (isByRef() ? "." : "->")
198336809Sdim     << "getOperand(" << OpIndex << ").isImm() ";
199336809Sdim}
200336809Sdim
201344779Sdimvoid PredicateExpander::expandCheckFunctionPredicate(raw_ostream &OS,
202336809Sdim                                                     StringRef MCInstFn,
203336809Sdim                                                     StringRef MachineInstrFn) {
204336809Sdim  OS << (shouldExpandForMC() ? MCInstFn : MachineInstrFn)
205336809Sdim     << (isByRef() ? "(MI)" : "(*MI)");
206336809Sdim}
207336809Sdim
208344779Sdimvoid PredicateExpander::expandCheckNonPortable(raw_ostream &OS,
209336809Sdim                                               StringRef Code) {
210336809Sdim  if (shouldExpandForMC())
211336809Sdim    return expandFalse(OS);
212336809Sdim
213336809Sdim  OS << '(' << Code << ')';
214336809Sdim}
215336809Sdim
216344779Sdimvoid PredicateExpander::expandReturnStatement(raw_ostream &OS,
217344779Sdim                                              const Record *Rec) {
218344779Sdim  std::string Buffer;
219344779Sdim  raw_string_ostream SS(Buffer);
220336809Sdim
221344779Sdim  SS << "return ";
222344779Sdim  expandPredicate(SS, Rec);
223344779Sdim  SS << ";";
224344779Sdim  SS.flush();
225344779Sdim  OS << Buffer;
226344779Sdim}
227344779Sdim
228344779Sdimvoid PredicateExpander::expandOpcodeSwitchCase(raw_ostream &OS,
229344779Sdim                                               const Record *Rec) {
230344779Sdim  const RecVec &Opcodes = Rec->getValueAsListOfDefs("Opcodes");
231344779Sdim  for (const Record *Opcode : Opcodes) {
232344779Sdim    OS.indent(getIndentLevel() * 2);
233344779Sdim    OS << "case " << Opcode->getValueAsString("Namespace")
234344779Sdim       << "::" << Opcode->getName() << ":\n";
235344779Sdim  }
236344779Sdim
237344779Sdim  increaseIndentLevel();
238344779Sdim  OS.indent(getIndentLevel() * 2);
239344779Sdim  expandStatement(OS, Rec->getValueAsDef("CaseStmt"));
240344779Sdim  decreaseIndentLevel();
241344779Sdim}
242344779Sdim
243344779Sdimvoid PredicateExpander::expandOpcodeSwitchStatement(raw_ostream &OS,
244344779Sdim                                                    const RecVec &Cases,
245344779Sdim                                                    const Record *Default) {
246344779Sdim  std::string Buffer;
247344779Sdim  raw_string_ostream SS(Buffer);
248344779Sdim
249344779Sdim  SS << "switch(MI" << (isByRef() ? "." : "->") << "getOpcode()) {\n";
250344779Sdim  for (const Record *Rec : Cases) {
251344779Sdim    expandOpcodeSwitchCase(SS, Rec);
252344779Sdim    SS << '\n';
253344779Sdim  }
254344779Sdim
255344779Sdim  // Expand the default case.
256344779Sdim  SS.indent(getIndentLevel() * 2);
257344779Sdim  SS << "default:\n";
258344779Sdim
259344779Sdim  increaseIndentLevel();
260344779Sdim  SS.indent(getIndentLevel() * 2);
261344779Sdim  expandStatement(SS, Default);
262344779Sdim  decreaseIndentLevel();
263344779Sdim  SS << '\n';
264344779Sdim
265344779Sdim  SS.indent(getIndentLevel() * 2);
266344779Sdim  SS << "} // end of switch-stmt";
267344779Sdim  SS.flush();
268344779Sdim  OS << Buffer;
269344779Sdim}
270344779Sdim
271344779Sdimvoid PredicateExpander::expandStatement(raw_ostream &OS, const Record *Rec) {
272344779Sdim  // Assume that padding has been added by the caller.
273344779Sdim  if (Rec->isSubClassOf("MCOpcodeSwitchStatement")) {
274344779Sdim    expandOpcodeSwitchStatement(OS, Rec->getValueAsListOfDefs("Cases"),
275344779Sdim                                Rec->getValueAsDef("DefaultCase"));
276344779Sdim    return;
277344779Sdim  }
278344779Sdim
279344779Sdim  if (Rec->isSubClassOf("MCReturnStatement")) {
280344779Sdim    expandReturnStatement(OS, Rec->getValueAsDef("Pred"));
281344779Sdim    return;
282344779Sdim  }
283344779Sdim
284344779Sdim  llvm_unreachable("No known rules to expand this MCStatement");
285344779Sdim}
286344779Sdim
287344779Sdimvoid PredicateExpander::expandPredicate(raw_ostream &OS, const Record *Rec) {
288344779Sdim  // Assume that padding has been added by the caller.
289336809Sdim  if (Rec->isSubClassOf("MCTrue")) {
290336809Sdim    if (shouldNegate())
291336809Sdim      return expandFalse(OS);
292336809Sdim    return expandTrue(OS);
293336809Sdim  }
294336809Sdim
295336809Sdim  if (Rec->isSubClassOf("MCFalse")) {
296336809Sdim    if (shouldNegate())
297336809Sdim      return expandTrue(OS);
298336809Sdim    return expandFalse(OS);
299336809Sdim  }
300336809Sdim
301336809Sdim  if (Rec->isSubClassOf("CheckNot")) {
302336809Sdim    flipNegatePredicate();
303336809Sdim    expandPredicate(OS, Rec->getValueAsDef("Pred"));
304336809Sdim    flipNegatePredicate();
305336809Sdim    return;
306336809Sdim  }
307336809Sdim
308336809Sdim  if (Rec->isSubClassOf("CheckIsRegOperand"))
309336809Sdim    return expandCheckIsRegOperand(OS, Rec->getValueAsInt("OpIndex"));
310336809Sdim
311336809Sdim  if (Rec->isSubClassOf("CheckIsImmOperand"))
312336809Sdim    return expandCheckIsImmOperand(OS, Rec->getValueAsInt("OpIndex"));
313336809Sdim
314336809Sdim  if (Rec->isSubClassOf("CheckRegOperand"))
315336809Sdim    return expandCheckRegOperand(OS, Rec->getValueAsInt("OpIndex"),
316344779Sdim                                 Rec->getValueAsDef("Reg"),
317344779Sdim                                 Rec->getValueAsString("FunctionMapper"));
318336809Sdim
319344779Sdim  if (Rec->isSubClassOf("CheckRegOperandSimple"))
320344779Sdim    return expandCheckRegOperandSimple(OS, Rec->getValueAsInt("OpIndex"),
321344779Sdim                                       Rec->getValueAsString("FunctionMapper"));
322344779Sdim
323336809Sdim  if (Rec->isSubClassOf("CheckInvalidRegOperand"))
324336809Sdim    return expandCheckInvalidRegOperand(OS, Rec->getValueAsInt("OpIndex"));
325336809Sdim
326336809Sdim  if (Rec->isSubClassOf("CheckImmOperand"))
327336809Sdim    return expandCheckImmOperand(OS, Rec->getValueAsInt("OpIndex"),
328344779Sdim                                 Rec->getValueAsInt("ImmVal"),
329344779Sdim                                 Rec->getValueAsString("FunctionMapper"));
330336809Sdim
331336809Sdim  if (Rec->isSubClassOf("CheckImmOperand_s"))
332336809Sdim    return expandCheckImmOperand(OS, Rec->getValueAsInt("OpIndex"),
333344779Sdim                                 Rec->getValueAsString("ImmVal"),
334344779Sdim                                 Rec->getValueAsString("FunctionMapper"));
335336809Sdim
336344779Sdim  if (Rec->isSubClassOf("CheckImmOperandSimple"))
337344779Sdim    return expandCheckImmOperandSimple(OS, Rec->getValueAsInt("OpIndex"),
338344779Sdim                                       Rec->getValueAsString("FunctionMapper"));
339344779Sdim
340336809Sdim  if (Rec->isSubClassOf("CheckSameRegOperand"))
341336809Sdim    return expandCheckSameRegOperand(OS, Rec->getValueAsInt("FirstIndex"),
342336809Sdim                                     Rec->getValueAsInt("SecondIndex"));
343336809Sdim
344336809Sdim  if (Rec->isSubClassOf("CheckNumOperands"))
345336809Sdim    return expandCheckNumOperands(OS, Rec->getValueAsInt("NumOps"));
346336809Sdim
347336809Sdim  if (Rec->isSubClassOf("CheckPseudo"))
348336809Sdim    return expandCheckPseudo(OS, Rec->getValueAsListOfDefs("ValidOpcodes"));
349336809Sdim
350336809Sdim  if (Rec->isSubClassOf("CheckOpcode"))
351336809Sdim    return expandCheckOpcode(OS, Rec->getValueAsListOfDefs("ValidOpcodes"));
352336809Sdim
353336809Sdim  if (Rec->isSubClassOf("CheckAll"))
354336809Sdim    return expandPredicateSequence(OS, Rec->getValueAsListOfDefs("Predicates"),
355336809Sdim                                   /* AllOf */ true);
356336809Sdim
357336809Sdim  if (Rec->isSubClassOf("CheckAny"))
358336809Sdim    return expandPredicateSequence(OS, Rec->getValueAsListOfDefs("Predicates"),
359336809Sdim                                   /* AllOf */ false);
360336809Sdim
361336809Sdim  if (Rec->isSubClassOf("CheckFunctionPredicate"))
362336809Sdim    return expandCheckFunctionPredicate(
363336809Sdim        OS, Rec->getValueAsString("MCInstFnName"),
364336809Sdim        Rec->getValueAsString("MachineInstrFnName"));
365336809Sdim
366336809Sdim  if (Rec->isSubClassOf("CheckNonPortable"))
367336809Sdim    return expandCheckNonPortable(OS, Rec->getValueAsString("CodeBlock"));
368336809Sdim
369336809Sdim  if (Rec->isSubClassOf("TIIPredicate"))
370344779Sdim    return expandTIIFunctionCall(OS, Rec->getValueAsString("FunctionName"));
371336809Sdim
372336809Sdim  llvm_unreachable("No known rules to expand this MCInstPredicate");
373336809Sdim}
374336809Sdim
375344779Sdimvoid STIPredicateExpander::expandHeader(raw_ostream &OS,
376344779Sdim                                        const STIPredicateFunction &Fn) {
377344779Sdim  const Record *Rec = Fn.getDeclaration();
378344779Sdim  StringRef FunctionName = Rec->getValueAsString("Name");
379344779Sdim
380344779Sdim  OS.indent(getIndentLevel() * 2);
381344779Sdim  OS << "bool ";
382344779Sdim  if (shouldExpandDefinition())
383344779Sdim    OS << getClassPrefix() << "::";
384344779Sdim  OS << FunctionName << "(";
385344779Sdim  if (shouldExpandForMC())
386344779Sdim    OS << "const MCInst " << (isByRef() ? "&" : "*") << "MI";
387344779Sdim  else
388344779Sdim    OS << "const MachineInstr " << (isByRef() ? "&" : "*") << "MI";
389344779Sdim  if (Rec->getValueAsBit("UpdatesOpcodeMask"))
390344779Sdim    OS << ", APInt &Mask";
391344779Sdim  OS << (shouldExpandForMC() ? ", unsigned ProcessorID) const " : ") const ");
392344779Sdim  if (shouldExpandDefinition()) {
393344779Sdim    OS << "{\n";
394344779Sdim    return;
395344779Sdim  }
396344779Sdim
397344779Sdim  if (Rec->getValueAsBit("OverridesBaseClassMember"))
398344779Sdim    OS << "override";
399344779Sdim  OS << ";\n";
400344779Sdim}
401344779Sdim
402344779Sdimvoid STIPredicateExpander::expandPrologue(raw_ostream &OS,
403344779Sdim                                          const STIPredicateFunction &Fn) {
404344779Sdim  RecVec Delegates = Fn.getDeclaration()->getValueAsListOfDefs("Delegates");
405344779Sdim  bool UpdatesOpcodeMask =
406344779Sdim      Fn.getDeclaration()->getValueAsBit("UpdatesOpcodeMask");
407344779Sdim
408344779Sdim  increaseIndentLevel();
409344779Sdim  unsigned IndentLevel = getIndentLevel();
410344779Sdim  for (const Record *Delegate : Delegates) {
411344779Sdim    OS.indent(IndentLevel * 2);
412344779Sdim    OS << "if (" << Delegate->getValueAsString("Name") << "(MI";
413344779Sdim    if (UpdatesOpcodeMask)
414344779Sdim      OS << ", Mask";
415344779Sdim    if (shouldExpandForMC())
416344779Sdim      OS << ", ProcessorID";
417344779Sdim    OS << "))\n";
418344779Sdim    OS.indent((1 + IndentLevel) * 2);
419344779Sdim    OS << "return true;\n\n";
420344779Sdim  }
421344779Sdim
422344779Sdim  if (shouldExpandForMC())
423344779Sdim    return;
424344779Sdim
425344779Sdim  OS.indent(IndentLevel * 2);
426344779Sdim  OS << "unsigned ProcessorID = getSchedModel().getProcessorID();\n";
427344779Sdim}
428344779Sdim
429344779Sdimvoid STIPredicateExpander::expandOpcodeGroup(raw_ostream &OS, const OpcodeGroup &Group,
430344779Sdim                                             bool ShouldUpdateOpcodeMask) {
431344779Sdim  const OpcodeInfo &OI = Group.getOpcodeInfo();
432344779Sdim  for (const PredicateInfo &PI : OI.getPredicates()) {
433344779Sdim    const APInt &ProcModelMask = PI.ProcModelMask;
434344779Sdim    bool FirstProcID = true;
435344779Sdim    for (unsigned I = 0, E = ProcModelMask.getActiveBits(); I < E; ++I) {
436344779Sdim      if (!ProcModelMask[I])
437344779Sdim        continue;
438344779Sdim
439344779Sdim      if (FirstProcID) {
440344779Sdim        OS.indent(getIndentLevel() * 2);
441344779Sdim        OS << "if (ProcessorID == " << I;
442344779Sdim      } else {
443344779Sdim        OS << " || ProcessorID == " << I;
444344779Sdim      }
445344779Sdim      FirstProcID = false;
446344779Sdim    }
447344779Sdim
448344779Sdim    OS << ") {\n";
449344779Sdim
450344779Sdim    increaseIndentLevel();
451344779Sdim    OS.indent(getIndentLevel() * 2);
452344779Sdim    if (ShouldUpdateOpcodeMask) {
453344779Sdim      if (PI.OperandMask.isNullValue())
454344779Sdim        OS << "Mask.clearAllBits();\n";
455344779Sdim      else
456344779Sdim        OS << "Mask = " << PI.OperandMask << ";\n";
457344779Sdim      OS.indent(getIndentLevel() * 2);
458344779Sdim    }
459344779Sdim    OS << "return ";
460344779Sdim    expandPredicate(OS, PI.Predicate);
461344779Sdim    OS << ";\n";
462344779Sdim    decreaseIndentLevel();
463344779Sdim    OS.indent(getIndentLevel() * 2);
464344779Sdim    OS << "}\n";
465344779Sdim  }
466344779Sdim}
467344779Sdim
468344779Sdimvoid STIPredicateExpander::expandBody(raw_ostream &OS,
469344779Sdim                                      const STIPredicateFunction &Fn) {
470344779Sdim  bool UpdatesOpcodeMask =
471344779Sdim      Fn.getDeclaration()->getValueAsBit("UpdatesOpcodeMask");
472344779Sdim
473344779Sdim  unsigned IndentLevel = getIndentLevel();
474344779Sdim  OS.indent(IndentLevel * 2);
475344779Sdim  OS << "switch(MI" << (isByRef() ? "." : "->") << "getOpcode()) {\n";
476344779Sdim  OS.indent(IndentLevel * 2);
477344779Sdim  OS << "default:\n";
478344779Sdim  OS.indent(IndentLevel * 2);
479344779Sdim  OS << "  break;";
480344779Sdim
481344779Sdim  for (const OpcodeGroup &Group : Fn.getGroups()) {
482344779Sdim    for (const Record *Opcode : Group.getOpcodes()) {
483344779Sdim      OS << '\n';
484344779Sdim      OS.indent(IndentLevel * 2);
485344779Sdim      OS << "case " << getTargetName() << "::" << Opcode->getName() << ":";
486344779Sdim    }
487344779Sdim
488344779Sdim    OS << '\n';
489344779Sdim    increaseIndentLevel();
490344779Sdim    expandOpcodeGroup(OS, Group, UpdatesOpcodeMask);
491344779Sdim
492344779Sdim    OS.indent(getIndentLevel() * 2);
493344779Sdim    OS << "break;\n";
494344779Sdim    decreaseIndentLevel();
495344779Sdim  }
496344779Sdim
497344779Sdim  OS.indent(IndentLevel * 2);
498344779Sdim  OS << "}\n";
499344779Sdim}
500344779Sdim
501344779Sdimvoid STIPredicateExpander::expandEpilogue(raw_ostream &OS,
502344779Sdim                                          const STIPredicateFunction &Fn) {
503344779Sdim  OS << '\n';
504344779Sdim  OS.indent(getIndentLevel() * 2);
505344779Sdim  OS << "return ";
506344779Sdim  expandPredicate(OS, Fn.getDefaultReturnPredicate());
507344779Sdim  OS << ";\n";
508344779Sdim
509344779Sdim  decreaseIndentLevel();
510344779Sdim  OS.indent(getIndentLevel() * 2);
511344779Sdim  StringRef FunctionName = Fn.getDeclaration()->getValueAsString("Name");
512344779Sdim  OS << "} // " << ClassPrefix << "::" << FunctionName << "\n\n";
513344779Sdim}
514344779Sdim
515344779Sdimvoid STIPredicateExpander::expandSTIPredicate(raw_ostream &OS,
516344779Sdim                                              const STIPredicateFunction &Fn) {
517344779Sdim  const Record *Rec = Fn.getDeclaration();
518344779Sdim  if (shouldExpandForMC() && !Rec->getValueAsBit("ExpandForMC"))
519344779Sdim    return;
520344779Sdim
521344779Sdim  expandHeader(OS, Fn);
522344779Sdim  if (shouldExpandDefinition()) {
523344779Sdim    expandPrologue(OS, Fn);
524344779Sdim    expandBody(OS, Fn);
525344779Sdim    expandEpilogue(OS, Fn);
526344779Sdim  }
527344779Sdim}
528344779Sdim
529336809Sdim} // namespace llvm
530