1 //===--------------------- PredicateExpander.cpp --------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 /// Functionalities used by the Tablegen backends to expand machine predicates.
11 //===----------------------------------------------------------------------===//
13 #include "PredicateExpander.h"
14 #include "CodeGenSchedule.h" // Definition of STIPredicateFunction.
18 void PredicateExpander::expandTrue(raw_ostream
&OS
) { OS
<< "true"; }
19 void PredicateExpander::expandFalse(raw_ostream
&OS
) { OS
<< "false"; }
21 void PredicateExpander::expandCheckImmOperand(raw_ostream
&OS
, int OpIndex
,
23 StringRef FunctionMapper
) {
24 if (!FunctionMapper
.empty())
25 OS
<< FunctionMapper
<< "(";
26 OS
<< "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
28 if (!FunctionMapper
.empty())
30 OS
<< (shouldNegate() ? " != " : " == ") << ImmVal
;
33 void PredicateExpander::expandCheckImmOperand(raw_ostream
&OS
, int OpIndex
,
35 StringRef FunctionMapper
) {
37 expandCheckImmOperandSimple(OS
, OpIndex
, FunctionMapper
);
39 if (!FunctionMapper
.empty())
40 OS
<< FunctionMapper
<< "(";
41 OS
<< "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
43 if (!FunctionMapper
.empty())
45 OS
<< (shouldNegate() ? " != " : " == ") << ImmVal
;
48 void PredicateExpander::expandCheckImmOperandSimple(raw_ostream
&OS
,
50 StringRef FunctionMapper
) {
53 if (!FunctionMapper
.empty())
54 OS
<< FunctionMapper
<< "(";
55 OS
<< "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
57 if (!FunctionMapper
.empty())
61 void PredicateExpander::expandCheckRegOperand(raw_ostream
&OS
, int OpIndex
,
63 StringRef FunctionMapper
) {
64 assert(Reg
->isSubClassOf("Register") && "Expected a register Record!");
66 if (!FunctionMapper
.empty())
67 OS
<< FunctionMapper
<< "(";
68 OS
<< "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
70 if (!FunctionMapper
.empty())
72 OS
<< (shouldNegate() ? " != " : " == ");
73 const StringRef Str
= Reg
->getValueAsString("Namespace");
80 void PredicateExpander::expandCheckRegOperandSimple(raw_ostream
&OS
,
82 StringRef FunctionMapper
) {
85 if (!FunctionMapper
.empty())
86 OS
<< FunctionMapper
<< "(";
87 OS
<< "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
89 if (!FunctionMapper
.empty())
93 void PredicateExpander::expandCheckInvalidRegOperand(raw_ostream
&OS
,
95 OS
<< "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
96 << ").getReg() " << (shouldNegate() ? "!= " : "== ") << "0";
99 void PredicateExpander::expandCheckSameRegOperand(raw_ostream
&OS
, int First
,
101 OS
<< "MI" << (isByRef() ? "." : "->") << "getOperand(" << First
102 << ").getReg() " << (shouldNegate() ? "!=" : "==") << " MI"
103 << (isByRef() ? "." : "->") << "getOperand(" << Second
<< ").getReg()";
106 void PredicateExpander::expandCheckNumOperands(raw_ostream
&OS
, int NumOps
) {
107 OS
<< "MI" << (isByRef() ? "." : "->") << "getNumOperands() "
108 << (shouldNegate() ? "!= " : "== ") << NumOps
;
111 void PredicateExpander::expandCheckOpcode(raw_ostream
&OS
, const Record
*Inst
) {
112 OS
<< "MI" << (isByRef() ? "." : "->") << "getOpcode() "
113 << (shouldNegate() ? "!= " : "== ") << Inst
->getValueAsString("Namespace")
114 << "::" << Inst
->getName();
117 void PredicateExpander::expandCheckOpcode(raw_ostream
&OS
,
118 const RecVec
&Opcodes
) {
119 assert(!Opcodes
.empty() && "Expected at least one opcode to check!");
122 if (Opcodes
.size() == 1) {
124 expandCheckOpcode(OS
, Opcodes
[0]);
130 increaseIndentLevel();
131 for (const Record
*Rec
: Opcodes
) {
133 OS
.indent(getIndentLevel() * 2);
135 OS
<< (shouldNegate() ? "&& " : "|| ");
137 expandCheckOpcode(OS
, Rec
);
142 decreaseIndentLevel();
143 OS
.indent(getIndentLevel() * 2);
147 void PredicateExpander::expandCheckPseudo(raw_ostream
&OS
,
148 const RecVec
&Opcodes
) {
149 if (shouldExpandForMC())
152 expandCheckOpcode(OS
, Opcodes
);
155 void PredicateExpander::expandPredicateSequence(raw_ostream
&OS
,
156 const RecVec
&Sequence
,
158 assert(!Sequence
.empty() && "Found an invalid empty predicate set!");
159 if (Sequence
.size() == 1)
160 return expandPredicate(OS
, Sequence
[0]);
162 // Okay, there is more than one predicate in the set.
164 OS
<< (shouldNegate() ? "!(" : "(");
165 increaseIndentLevel();
167 bool OldValue
= shouldNegate();
168 setNegatePredicate(false);
169 for (const Record
*Rec
: Sequence
) {
171 OS
.indent(getIndentLevel() * 2);
173 OS
<< (IsCheckAll
? "&& " : "|| ");
174 expandPredicate(OS
, Rec
);
178 decreaseIndentLevel();
179 OS
.indent(getIndentLevel() * 2);
181 setNegatePredicate(OldValue
);
184 void PredicateExpander::expandTIIFunctionCall(raw_ostream
&OS
,
185 StringRef MethodName
) {
186 OS
<< (shouldNegate() ? "!" : "");
187 OS
<< TargetName
<< (shouldExpandForMC() ? "_MC::" : "InstrInfo::");
188 OS
<< MethodName
<< (isByRef() ? "(MI)" : "(*MI)");
191 void PredicateExpander::expandCheckIsRegOperand(raw_ostream
&OS
, int OpIndex
) {
192 OS
<< (shouldNegate() ? "!" : "") << "MI" << (isByRef() ? "." : "->")
193 << "getOperand(" << OpIndex
<< ").isReg() ";
196 void PredicateExpander::expandCheckIsImmOperand(raw_ostream
&OS
, int OpIndex
) {
197 OS
<< (shouldNegate() ? "!" : "") << "MI" << (isByRef() ? "." : "->")
198 << "getOperand(" << OpIndex
<< ").isImm() ";
201 void PredicateExpander::expandCheckFunctionPredicateWithTII(
202 raw_ostream
&OS
, StringRef MCInstFn
, StringRef MachineInstrFn
,
204 if (!shouldExpandForMC()) {
205 OS
<< (TIIPtr
.empty() ? "TII" : TIIPtr
) << "->" << MachineInstrFn
;
206 OS
<< (isByRef() ? "(MI)" : "(*MI)");
210 OS
<< MCInstFn
<< (isByRef() ? "(MI" : "(*MI") << ", MCII)";
213 void PredicateExpander::expandCheckFunctionPredicate(raw_ostream
&OS
,
215 StringRef MachineInstrFn
) {
216 OS
<< (shouldExpandForMC() ? MCInstFn
: MachineInstrFn
)
217 << (isByRef() ? "(MI)" : "(*MI)");
220 void PredicateExpander::expandCheckNonPortable(raw_ostream
&OS
,
222 if (shouldExpandForMC())
223 return expandFalse(OS
);
225 OS
<< '(' << Code
<< ')';
228 void PredicateExpander::expandReturnStatement(raw_ostream
&OS
,
231 raw_string_ostream
SS(Buffer
);
234 expandPredicate(SS
, Rec
);
240 void PredicateExpander::expandOpcodeSwitchCase(raw_ostream
&OS
,
242 const RecVec
&Opcodes
= Rec
->getValueAsListOfDefs("Opcodes");
243 for (const Record
*Opcode
: Opcodes
) {
244 OS
.indent(getIndentLevel() * 2);
245 OS
<< "case " << Opcode
->getValueAsString("Namespace")
246 << "::" << Opcode
->getName() << ":\n";
249 increaseIndentLevel();
250 OS
.indent(getIndentLevel() * 2);
251 expandStatement(OS
, Rec
->getValueAsDef("CaseStmt"));
252 decreaseIndentLevel();
255 void PredicateExpander::expandOpcodeSwitchStatement(raw_ostream
&OS
,
257 const Record
*Default
) {
259 raw_string_ostream
SS(Buffer
);
261 SS
<< "switch(MI" << (isByRef() ? "." : "->") << "getOpcode()) {\n";
262 for (const Record
*Rec
: Cases
) {
263 expandOpcodeSwitchCase(SS
, Rec
);
267 // Expand the default case.
268 SS
.indent(getIndentLevel() * 2);
271 increaseIndentLevel();
272 SS
.indent(getIndentLevel() * 2);
273 expandStatement(SS
, Default
);
274 decreaseIndentLevel();
277 SS
.indent(getIndentLevel() * 2);
278 SS
<< "} // end of switch-stmt";
283 void PredicateExpander::expandStatement(raw_ostream
&OS
, const Record
*Rec
) {
284 // Assume that padding has been added by the caller.
285 if (Rec
->isSubClassOf("MCOpcodeSwitchStatement")) {
286 expandOpcodeSwitchStatement(OS
, Rec
->getValueAsListOfDefs("Cases"),
287 Rec
->getValueAsDef("DefaultCase"));
291 if (Rec
->isSubClassOf("MCReturnStatement")) {
292 expandReturnStatement(OS
, Rec
->getValueAsDef("Pred"));
296 llvm_unreachable("No known rules to expand this MCStatement");
299 void PredicateExpander::expandPredicate(raw_ostream
&OS
, const Record
*Rec
) {
300 // Assume that padding has been added by the caller.
301 if (Rec
->isSubClassOf("MCTrue")) {
303 return expandFalse(OS
);
304 return expandTrue(OS
);
307 if (Rec
->isSubClassOf("MCFalse")) {
309 return expandTrue(OS
);
310 return expandFalse(OS
);
313 if (Rec
->isSubClassOf("CheckNot")) {
314 flipNegatePredicate();
315 expandPredicate(OS
, Rec
->getValueAsDef("Pred"));
316 flipNegatePredicate();
320 if (Rec
->isSubClassOf("CheckIsRegOperand"))
321 return expandCheckIsRegOperand(OS
, Rec
->getValueAsInt("OpIndex"));
323 if (Rec
->isSubClassOf("CheckIsImmOperand"))
324 return expandCheckIsImmOperand(OS
, Rec
->getValueAsInt("OpIndex"));
326 if (Rec
->isSubClassOf("CheckRegOperand"))
327 return expandCheckRegOperand(OS
, Rec
->getValueAsInt("OpIndex"),
328 Rec
->getValueAsDef("Reg"),
329 Rec
->getValueAsString("FunctionMapper"));
331 if (Rec
->isSubClassOf("CheckRegOperandSimple"))
332 return expandCheckRegOperandSimple(OS
, Rec
->getValueAsInt("OpIndex"),
333 Rec
->getValueAsString("FunctionMapper"));
335 if (Rec
->isSubClassOf("CheckInvalidRegOperand"))
336 return expandCheckInvalidRegOperand(OS
, Rec
->getValueAsInt("OpIndex"));
338 if (Rec
->isSubClassOf("CheckImmOperand"))
339 return expandCheckImmOperand(OS
, Rec
->getValueAsInt("OpIndex"),
340 Rec
->getValueAsInt("ImmVal"),
341 Rec
->getValueAsString("FunctionMapper"));
343 if (Rec
->isSubClassOf("CheckImmOperand_s"))
344 return expandCheckImmOperand(OS
, Rec
->getValueAsInt("OpIndex"),
345 Rec
->getValueAsString("ImmVal"),
346 Rec
->getValueAsString("FunctionMapper"));
348 if (Rec
->isSubClassOf("CheckImmOperandSimple"))
349 return expandCheckImmOperandSimple(OS
, Rec
->getValueAsInt("OpIndex"),
350 Rec
->getValueAsString("FunctionMapper"));
352 if (Rec
->isSubClassOf("CheckSameRegOperand"))
353 return expandCheckSameRegOperand(OS
, Rec
->getValueAsInt("FirstIndex"),
354 Rec
->getValueAsInt("SecondIndex"));
356 if (Rec
->isSubClassOf("CheckNumOperands"))
357 return expandCheckNumOperands(OS
, Rec
->getValueAsInt("NumOps"));
359 if (Rec
->isSubClassOf("CheckPseudo"))
360 return expandCheckPseudo(OS
, Rec
->getValueAsListOfDefs("ValidOpcodes"));
362 if (Rec
->isSubClassOf("CheckOpcode"))
363 return expandCheckOpcode(OS
, Rec
->getValueAsListOfDefs("ValidOpcodes"));
365 if (Rec
->isSubClassOf("CheckAll"))
366 return expandPredicateSequence(OS
, Rec
->getValueAsListOfDefs("Predicates"),
369 if (Rec
->isSubClassOf("CheckAny"))
370 return expandPredicateSequence(OS
, Rec
->getValueAsListOfDefs("Predicates"),
373 if (Rec
->isSubClassOf("CheckFunctionPredicate")) {
374 return expandCheckFunctionPredicate(
375 OS
, Rec
->getValueAsString("MCInstFnName"),
376 Rec
->getValueAsString("MachineInstrFnName"));
379 if (Rec
->isSubClassOf("CheckFunctionPredicateWithTII")) {
380 return expandCheckFunctionPredicateWithTII(
381 OS
, Rec
->getValueAsString("MCInstFnName"),
382 Rec
->getValueAsString("MachineInstrFnName"),
383 Rec
->getValueAsString("TIIPtrName"));
386 if (Rec
->isSubClassOf("CheckNonPortable"))
387 return expandCheckNonPortable(OS
, Rec
->getValueAsString("CodeBlock"));
389 if (Rec
->isSubClassOf("TIIPredicate"))
390 return expandTIIFunctionCall(OS
, Rec
->getValueAsString("FunctionName"));
392 llvm_unreachable("No known rules to expand this MCInstPredicate");
395 void STIPredicateExpander::expandHeader(raw_ostream
&OS
,
396 const STIPredicateFunction
&Fn
) {
397 const Record
*Rec
= Fn
.getDeclaration();
398 StringRef FunctionName
= Rec
->getValueAsString("Name");
400 OS
.indent(getIndentLevel() * 2);
402 if (shouldExpandDefinition())
403 OS
<< getClassPrefix() << "::";
404 OS
<< FunctionName
<< "(";
405 if (shouldExpandForMC())
406 OS
<< "const MCInst " << (isByRef() ? "&" : "*") << "MI";
408 OS
<< "const MachineInstr " << (isByRef() ? "&" : "*") << "MI";
409 if (Rec
->getValueAsBit("UpdatesOpcodeMask"))
410 OS
<< ", APInt &Mask";
411 OS
<< (shouldExpandForMC() ? ", unsigned ProcessorID) const " : ") const ");
412 if (shouldExpandDefinition()) {
417 if (Rec
->getValueAsBit("OverridesBaseClassMember"))
422 void STIPredicateExpander::expandPrologue(raw_ostream
&OS
,
423 const STIPredicateFunction
&Fn
) {
424 RecVec Delegates
= Fn
.getDeclaration()->getValueAsListOfDefs("Delegates");
425 bool UpdatesOpcodeMask
=
426 Fn
.getDeclaration()->getValueAsBit("UpdatesOpcodeMask");
428 increaseIndentLevel();
429 unsigned IndentLevel
= getIndentLevel();
430 for (const Record
*Delegate
: Delegates
) {
431 OS
.indent(IndentLevel
* 2);
432 OS
<< "if (" << Delegate
->getValueAsString("Name") << "(MI";
433 if (UpdatesOpcodeMask
)
435 if (shouldExpandForMC())
436 OS
<< ", ProcessorID";
438 OS
.indent((1 + IndentLevel
) * 2);
439 OS
<< "return true;\n\n";
442 if (shouldExpandForMC())
445 OS
.indent(IndentLevel
* 2);
446 OS
<< "unsigned ProcessorID = getSchedModel().getProcessorID();\n";
449 void STIPredicateExpander::expandOpcodeGroup(raw_ostream
&OS
, const OpcodeGroup
&Group
,
450 bool ShouldUpdateOpcodeMask
) {
451 const OpcodeInfo
&OI
= Group
.getOpcodeInfo();
452 for (const PredicateInfo
&PI
: OI
.getPredicates()) {
453 const APInt
&ProcModelMask
= PI
.ProcModelMask
;
454 bool FirstProcID
= true;
455 for (unsigned I
= 0, E
= ProcModelMask
.getActiveBits(); I
< E
; ++I
) {
456 if (!ProcModelMask
[I
])
460 OS
.indent(getIndentLevel() * 2);
461 OS
<< "if (ProcessorID == " << I
;
463 OS
<< " || ProcessorID == " << I
;
470 increaseIndentLevel();
471 OS
.indent(getIndentLevel() * 2);
472 if (ShouldUpdateOpcodeMask
) {
473 if (PI
.OperandMask
.isNullValue())
474 OS
<< "Mask.clearAllBits();\n";
476 OS
<< "Mask = " << PI
.OperandMask
<< ";\n";
477 OS
.indent(getIndentLevel() * 2);
480 expandPredicate(OS
, PI
.Predicate
);
482 decreaseIndentLevel();
483 OS
.indent(getIndentLevel() * 2);
488 void STIPredicateExpander::expandBody(raw_ostream
&OS
,
489 const STIPredicateFunction
&Fn
) {
490 bool UpdatesOpcodeMask
=
491 Fn
.getDeclaration()->getValueAsBit("UpdatesOpcodeMask");
493 unsigned IndentLevel
= getIndentLevel();
494 OS
.indent(IndentLevel
* 2);
495 OS
<< "switch(MI" << (isByRef() ? "." : "->") << "getOpcode()) {\n";
496 OS
.indent(IndentLevel
* 2);
498 OS
.indent(IndentLevel
* 2);
501 for (const OpcodeGroup
&Group
: Fn
.getGroups()) {
502 for (const Record
*Opcode
: Group
.getOpcodes()) {
504 OS
.indent(IndentLevel
* 2);
505 OS
<< "case " << getTargetName() << "::" << Opcode
->getName() << ":";
509 increaseIndentLevel();
510 expandOpcodeGroup(OS
, Group
, UpdatesOpcodeMask
);
512 OS
.indent(getIndentLevel() * 2);
514 decreaseIndentLevel();
517 OS
.indent(IndentLevel
* 2);
521 void STIPredicateExpander::expandEpilogue(raw_ostream
&OS
,
522 const STIPredicateFunction
&Fn
) {
524 OS
.indent(getIndentLevel() * 2);
526 expandPredicate(OS
, Fn
.getDefaultReturnPredicate());
529 decreaseIndentLevel();
530 OS
.indent(getIndentLevel() * 2);
531 StringRef FunctionName
= Fn
.getDeclaration()->getValueAsString("Name");
532 OS
<< "} // " << ClassPrefix
<< "::" << FunctionName
<< "\n\n";
535 void STIPredicateExpander::expandSTIPredicate(raw_ostream
&OS
,
536 const STIPredicateFunction
&Fn
) {
537 const Record
*Rec
= Fn
.getDeclaration();
538 if (shouldExpandForMC() && !Rec
->getValueAsBit("ExpandForMC"))
541 expandHeader(OS
, Fn
);
542 if (shouldExpandDefinition()) {
543 expandPrologue(OS
, Fn
);
545 expandEpilogue(OS
, Fn
);