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.
15 #include "llvm/TableGen/Record.h"
19 void PredicateExpander::expandTrue(raw_ostream
&OS
) { OS
<< "true"; }
20 void PredicateExpander::expandFalse(raw_ostream
&OS
) { OS
<< "false"; }
22 void PredicateExpander::expandCheckImmOperand(raw_ostream
&OS
, int OpIndex
,
24 StringRef FunctionMapper
) {
25 if (!FunctionMapper
.empty())
26 OS
<< FunctionMapper
<< "(";
27 OS
<< "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
29 if (!FunctionMapper
.empty())
31 OS
<< (shouldNegate() ? " != " : " == ") << ImmVal
;
34 void PredicateExpander::expandCheckImmOperand(raw_ostream
&OS
, int OpIndex
,
36 StringRef FunctionMapper
) {
38 expandCheckImmOperandSimple(OS
, OpIndex
, FunctionMapper
);
40 if (!FunctionMapper
.empty())
41 OS
<< FunctionMapper
<< "(";
42 OS
<< "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
44 if (!FunctionMapper
.empty())
46 OS
<< (shouldNegate() ? " != " : " == ") << ImmVal
;
49 void PredicateExpander::expandCheckImmOperandSimple(raw_ostream
&OS
,
51 StringRef FunctionMapper
) {
54 if (!FunctionMapper
.empty())
55 OS
<< FunctionMapper
<< "(";
56 OS
<< "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
58 if (!FunctionMapper
.empty())
62 void PredicateExpander::expandCheckRegOperand(raw_ostream
&OS
, int OpIndex
,
64 StringRef FunctionMapper
) {
65 assert(Reg
->isSubClassOf("Register") && "Expected a register Record!");
67 if (!FunctionMapper
.empty())
68 OS
<< FunctionMapper
<< "(";
69 OS
<< "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
71 if (!FunctionMapper
.empty())
73 OS
<< (shouldNegate() ? " != " : " == ");
74 const StringRef Str
= Reg
->getValueAsString("Namespace");
81 void PredicateExpander::expandCheckRegOperandSimple(raw_ostream
&OS
,
83 StringRef FunctionMapper
) {
86 if (!FunctionMapper
.empty())
87 OS
<< FunctionMapper
<< "(";
88 OS
<< "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
90 if (!FunctionMapper
.empty())
94 void PredicateExpander::expandCheckInvalidRegOperand(raw_ostream
&OS
,
96 OS
<< "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
97 << ").getReg() " << (shouldNegate() ? "!= " : "== ") << "0";
100 void PredicateExpander::expandCheckSameRegOperand(raw_ostream
&OS
, int First
,
102 OS
<< "MI" << (isByRef() ? "." : "->") << "getOperand(" << First
103 << ").getReg() " << (shouldNegate() ? "!=" : "==") << " MI"
104 << (isByRef() ? "." : "->") << "getOperand(" << Second
<< ").getReg()";
107 void PredicateExpander::expandCheckNumOperands(raw_ostream
&OS
, int NumOps
) {
108 OS
<< "MI" << (isByRef() ? "." : "->") << "getNumOperands() "
109 << (shouldNegate() ? "!= " : "== ") << NumOps
;
112 void PredicateExpander::expandCheckOpcode(raw_ostream
&OS
, const Record
*Inst
) {
113 OS
<< "MI" << (isByRef() ? "." : "->") << "getOpcode() "
114 << (shouldNegate() ? "!= " : "== ") << Inst
->getValueAsString("Namespace")
115 << "::" << Inst
->getName();
118 void PredicateExpander::expandCheckOpcode(raw_ostream
&OS
,
119 const RecVec
&Opcodes
) {
120 assert(!Opcodes
.empty() && "Expected at least one opcode to check!");
123 if (Opcodes
.size() == 1) {
125 expandCheckOpcode(OS
, Opcodes
[0]);
131 increaseIndentLevel();
132 for (const Record
*Rec
: Opcodes
) {
134 OS
.indent(getIndentLevel() * 2);
136 OS
<< (shouldNegate() ? "&& " : "|| ");
138 expandCheckOpcode(OS
, Rec
);
143 decreaseIndentLevel();
144 OS
.indent(getIndentLevel() * 2);
148 void PredicateExpander::expandCheckPseudo(raw_ostream
&OS
,
149 const RecVec
&Opcodes
) {
150 if (shouldExpandForMC())
153 expandCheckOpcode(OS
, Opcodes
);
156 void PredicateExpander::expandPredicateSequence(raw_ostream
&OS
,
157 const RecVec
&Sequence
,
159 assert(!Sequence
.empty() && "Found an invalid empty predicate set!");
160 if (Sequence
.size() == 1)
161 return expandPredicate(OS
, Sequence
[0]);
163 // Okay, there is more than one predicate in the set.
165 OS
<< (shouldNegate() ? "!(" : "(");
166 increaseIndentLevel();
168 bool OldValue
= shouldNegate();
169 setNegatePredicate(false);
170 for (const Record
*Rec
: Sequence
) {
172 OS
.indent(getIndentLevel() * 2);
174 OS
<< (IsCheckAll
? "&& " : "|| ");
175 expandPredicate(OS
, Rec
);
179 decreaseIndentLevel();
180 OS
.indent(getIndentLevel() * 2);
182 setNegatePredicate(OldValue
);
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)");
192 void PredicateExpander::expandCheckIsRegOperand(raw_ostream
&OS
, int OpIndex
) {
193 OS
<< (shouldNegate() ? "!" : "") << "MI" << (isByRef() ? "." : "->")
194 << "getOperand(" << OpIndex
<< ").isReg() ";
197 void PredicateExpander::expandCheckIsImmOperand(raw_ostream
&OS
, int OpIndex
) {
198 OS
<< (shouldNegate() ? "!" : "") << "MI" << (isByRef() ? "." : "->")
199 << "getOperand(" << OpIndex
<< ").isImm() ";
202 void PredicateExpander::expandCheckFunctionPredicateWithTII(
203 raw_ostream
&OS
, StringRef MCInstFn
, StringRef MachineInstrFn
,
205 if (!shouldExpandForMC()) {
206 OS
<< (TIIPtr
.empty() ? "TII" : TIIPtr
) << "->" << MachineInstrFn
;
207 OS
<< (isByRef() ? "(MI)" : "(*MI)");
211 OS
<< MCInstFn
<< (isByRef() ? "(MI" : "(*MI") << ", MCII)";
214 void PredicateExpander::expandCheckFunctionPredicate(raw_ostream
&OS
,
216 StringRef MachineInstrFn
) {
217 OS
<< (shouldExpandForMC() ? MCInstFn
: MachineInstrFn
)
218 << (isByRef() ? "(MI)" : "(*MI)");
221 void PredicateExpander::expandCheckNonPortable(raw_ostream
&OS
,
223 if (shouldExpandForMC())
224 return expandFalse(OS
);
226 OS
<< '(' << Code
<< ')';
229 void PredicateExpander::expandReturnStatement(raw_ostream
&OS
,
232 raw_string_ostream
SS(Buffer
);
235 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";
282 void PredicateExpander::expandStatement(raw_ostream
&OS
, const Record
*Rec
) {
283 // Assume that padding has been added by the caller.
284 if (Rec
->isSubClassOf("MCOpcodeSwitchStatement")) {
285 expandOpcodeSwitchStatement(OS
, Rec
->getValueAsListOfDefs("Cases"),
286 Rec
->getValueAsDef("DefaultCase"));
290 if (Rec
->isSubClassOf("MCReturnStatement")) {
291 expandReturnStatement(OS
, Rec
->getValueAsDef("Pred"));
295 llvm_unreachable("No known rules to expand this MCStatement");
298 void PredicateExpander::expandPredicate(raw_ostream
&OS
, const Record
*Rec
) {
299 // Assume that padding has been added by the caller.
300 if (Rec
->isSubClassOf("MCTrue")) {
302 return expandFalse(OS
);
303 return expandTrue(OS
);
306 if (Rec
->isSubClassOf("MCFalse")) {
308 return expandTrue(OS
);
309 return expandFalse(OS
);
312 if (Rec
->isSubClassOf("CheckNot")) {
313 flipNegatePredicate();
314 expandPredicate(OS
, Rec
->getValueAsDef("Pred"));
315 flipNegatePredicate();
319 if (Rec
->isSubClassOf("CheckIsRegOperand"))
320 return expandCheckIsRegOperand(OS
, Rec
->getValueAsInt("OpIndex"));
322 if (Rec
->isSubClassOf("CheckIsImmOperand"))
323 return expandCheckIsImmOperand(OS
, Rec
->getValueAsInt("OpIndex"));
325 if (Rec
->isSubClassOf("CheckRegOperand"))
326 return expandCheckRegOperand(OS
, Rec
->getValueAsInt("OpIndex"),
327 Rec
->getValueAsDef("Reg"),
328 Rec
->getValueAsString("FunctionMapper"));
330 if (Rec
->isSubClassOf("CheckRegOperandSimple"))
331 return expandCheckRegOperandSimple(OS
, Rec
->getValueAsInt("OpIndex"),
332 Rec
->getValueAsString("FunctionMapper"));
334 if (Rec
->isSubClassOf("CheckInvalidRegOperand"))
335 return expandCheckInvalidRegOperand(OS
, Rec
->getValueAsInt("OpIndex"));
337 if (Rec
->isSubClassOf("CheckImmOperand"))
338 return expandCheckImmOperand(OS
, Rec
->getValueAsInt("OpIndex"),
339 Rec
->getValueAsInt("ImmVal"),
340 Rec
->getValueAsString("FunctionMapper"));
342 if (Rec
->isSubClassOf("CheckImmOperand_s"))
343 return expandCheckImmOperand(OS
, Rec
->getValueAsInt("OpIndex"),
344 Rec
->getValueAsString("ImmVal"),
345 Rec
->getValueAsString("FunctionMapper"));
347 if (Rec
->isSubClassOf("CheckImmOperandSimple"))
348 return expandCheckImmOperandSimple(OS
, Rec
->getValueAsInt("OpIndex"),
349 Rec
->getValueAsString("FunctionMapper"));
351 if (Rec
->isSubClassOf("CheckSameRegOperand"))
352 return expandCheckSameRegOperand(OS
, Rec
->getValueAsInt("FirstIndex"),
353 Rec
->getValueAsInt("SecondIndex"));
355 if (Rec
->isSubClassOf("CheckNumOperands"))
356 return expandCheckNumOperands(OS
, Rec
->getValueAsInt("NumOps"));
358 if (Rec
->isSubClassOf("CheckPseudo"))
359 return expandCheckPseudo(OS
, Rec
->getValueAsListOfDefs("ValidOpcodes"));
361 if (Rec
->isSubClassOf("CheckOpcode"))
362 return expandCheckOpcode(OS
, Rec
->getValueAsListOfDefs("ValidOpcodes"));
364 if (Rec
->isSubClassOf("CheckAll"))
365 return expandPredicateSequence(OS
, Rec
->getValueAsListOfDefs("Predicates"),
368 if (Rec
->isSubClassOf("CheckAny"))
369 return expandPredicateSequence(OS
, Rec
->getValueAsListOfDefs("Predicates"),
372 if (Rec
->isSubClassOf("CheckFunctionPredicate")) {
373 return expandCheckFunctionPredicate(
374 OS
, Rec
->getValueAsString("MCInstFnName"),
375 Rec
->getValueAsString("MachineInstrFnName"));
378 if (Rec
->isSubClassOf("CheckFunctionPredicateWithTII")) {
379 return expandCheckFunctionPredicateWithTII(
380 OS
, Rec
->getValueAsString("MCInstFnName"),
381 Rec
->getValueAsString("MachineInstrFnName"),
382 Rec
->getValueAsString("TIIPtrName"));
385 if (Rec
->isSubClassOf("CheckNonPortable"))
386 return expandCheckNonPortable(OS
, Rec
->getValueAsString("CodeBlock"));
388 if (Rec
->isSubClassOf("TIIPredicate"))
389 return expandTIIFunctionCall(OS
, Rec
->getValueAsString("FunctionName"));
391 llvm_unreachable("No known rules to expand this MCInstPredicate");
394 void STIPredicateExpander::expandHeader(raw_ostream
&OS
,
395 const STIPredicateFunction
&Fn
) {
396 const Record
*Rec
= Fn
.getDeclaration();
397 StringRef FunctionName
= Rec
->getValueAsString("Name");
399 OS
.indent(getIndentLevel() * 2);
401 if (shouldExpandDefinition())
402 OS
<< getClassPrefix() << "::";
403 OS
<< FunctionName
<< "(";
404 if (shouldExpandForMC())
405 OS
<< "const MCInst " << (isByRef() ? "&" : "*") << "MI";
407 OS
<< "const MachineInstr " << (isByRef() ? "&" : "*") << "MI";
408 if (Rec
->getValueAsBit("UpdatesOpcodeMask"))
409 OS
<< ", APInt &Mask";
410 OS
<< (shouldExpandForMC() ? ", unsigned ProcessorID) const " : ") const ");
411 if (shouldExpandDefinition()) {
416 if (Rec
->getValueAsBit("OverridesBaseClassMember"))
421 void STIPredicateExpander::expandPrologue(raw_ostream
&OS
,
422 const STIPredicateFunction
&Fn
) {
423 RecVec Delegates
= Fn
.getDeclaration()->getValueAsListOfDefs("Delegates");
424 bool UpdatesOpcodeMask
=
425 Fn
.getDeclaration()->getValueAsBit("UpdatesOpcodeMask");
427 increaseIndentLevel();
428 unsigned IndentLevel
= getIndentLevel();
429 for (const Record
*Delegate
: Delegates
) {
430 OS
.indent(IndentLevel
* 2);
431 OS
<< "if (" << Delegate
->getValueAsString("Name") << "(MI";
432 if (UpdatesOpcodeMask
)
434 if (shouldExpandForMC())
435 OS
<< ", ProcessorID";
437 OS
.indent((1 + IndentLevel
) * 2);
438 OS
<< "return true;\n\n";
441 if (shouldExpandForMC())
444 OS
.indent(IndentLevel
* 2);
445 OS
<< "unsigned ProcessorID = getSchedModel().getProcessorID();\n";
448 void STIPredicateExpander::expandOpcodeGroup(raw_ostream
&OS
, const OpcodeGroup
&Group
,
449 bool ShouldUpdateOpcodeMask
) {
450 const OpcodeInfo
&OI
= Group
.getOpcodeInfo();
451 for (const PredicateInfo
&PI
: OI
.getPredicates()) {
452 const APInt
&ProcModelMask
= PI
.ProcModelMask
;
453 bool FirstProcID
= true;
454 for (unsigned I
= 0, E
= ProcModelMask
.getActiveBits(); I
< E
; ++I
) {
455 if (!ProcModelMask
[I
])
459 OS
.indent(getIndentLevel() * 2);
460 OS
<< "if (ProcessorID == " << I
;
462 OS
<< " || ProcessorID == " << I
;
469 increaseIndentLevel();
470 OS
.indent(getIndentLevel() * 2);
471 if (ShouldUpdateOpcodeMask
) {
472 if (PI
.OperandMask
.isZero())
473 OS
<< "Mask.clearAllBits();\n";
475 OS
<< "Mask = " << PI
.OperandMask
<< ";\n";
476 OS
.indent(getIndentLevel() * 2);
479 expandPredicate(OS
, PI
.Predicate
);
481 decreaseIndentLevel();
482 OS
.indent(getIndentLevel() * 2);
487 void STIPredicateExpander::expandBody(raw_ostream
&OS
,
488 const STIPredicateFunction
&Fn
) {
489 bool UpdatesOpcodeMask
=
490 Fn
.getDeclaration()->getValueAsBit("UpdatesOpcodeMask");
492 unsigned IndentLevel
= getIndentLevel();
493 OS
.indent(IndentLevel
* 2);
494 OS
<< "switch(MI" << (isByRef() ? "." : "->") << "getOpcode()) {\n";
495 OS
.indent(IndentLevel
* 2);
497 OS
.indent(IndentLevel
* 2);
500 for (const OpcodeGroup
&Group
: Fn
.getGroups()) {
501 for (const Record
*Opcode
: Group
.getOpcodes()) {
503 OS
.indent(IndentLevel
* 2);
504 OS
<< "case " << getTargetName() << "::" << Opcode
->getName() << ":";
508 increaseIndentLevel();
509 expandOpcodeGroup(OS
, Group
, UpdatesOpcodeMask
);
511 OS
.indent(getIndentLevel() * 2);
513 decreaseIndentLevel();
516 OS
.indent(IndentLevel
* 2);
520 void STIPredicateExpander::expandEpilogue(raw_ostream
&OS
,
521 const STIPredicateFunction
&Fn
) {
523 OS
.indent(getIndentLevel() * 2);
525 expandPredicate(OS
, Fn
.getDefaultReturnPredicate());
528 decreaseIndentLevel();
529 OS
.indent(getIndentLevel() * 2);
530 StringRef FunctionName
= Fn
.getDeclaration()->getValueAsString("Name");
531 OS
<< "} // " << ClassPrefix
<< "::" << FunctionName
<< "\n\n";
534 void STIPredicateExpander::expandSTIPredicate(raw_ostream
&OS
,
535 const STIPredicateFunction
&Fn
) {
536 const Record
*Rec
= Fn
.getDeclaration();
537 if (shouldExpandForMC() && !Rec
->getValueAsBit("ExpandForMC"))
540 expandHeader(OS
, Fn
);
541 if (shouldExpandDefinition()) {
542 expandPrologue(OS
, Fn
);
544 expandEpilogue(OS
, Fn
);