[InstCombine] Signed saturation tests. NFC
[llvm-complete.git] / utils / TableGen / PredicateExpander.cpp
blob9f7f40db2626cd7fc0eafbb24ccbab2eeca1486b
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.
11 //===----------------------------------------------------------------------===//
13 #include "PredicateExpander.h"
14 #include "CodeGenSchedule.h" // Definition of STIPredicateFunction.
16 namespace llvm {
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,
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;
33 void PredicateExpander::expandCheckImmOperand(raw_ostream &OS, int OpIndex,
34 StringRef ImmVal,
35 StringRef FunctionMapper) {
36 if (ImmVal.empty())
37 expandCheckImmOperandSimple(OS, OpIndex, FunctionMapper);
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;
48 void 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 << ")";
61 void PredicateExpander::expandCheckRegOperand(raw_ostream &OS, int OpIndex,
62 const Record *Reg,
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
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();
80 void 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 << ")";
93 void PredicateExpander::expandCheckInvalidRegOperand(raw_ostream &OS,
94 int OpIndex) {
95 OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
96 << ").getReg() " << (shouldNegate() ? "!= " : "== ") << "0";
99 void 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()";
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!");
120 bool First = true;
122 if (Opcodes.size() == 1) {
123 OS << "( ";
124 expandCheckOpcode(OS, Opcodes[0]);
125 OS << " )";
126 return;
129 OS << '(';
130 increaseIndentLevel();
131 for (const Record *Rec : Opcodes) {
132 OS << '\n';
133 OS.indent(getIndentLevel() * 2);
134 if (!First)
135 OS << (shouldNegate() ? "&& " : "|| ");
137 expandCheckOpcode(OS, Rec);
138 First = false;
141 OS << '\n';
142 decreaseIndentLevel();
143 OS.indent(getIndentLevel() * 2);
144 OS << ')';
147 void PredicateExpander::expandCheckPseudo(raw_ostream &OS,
148 const RecVec &Opcodes) {
149 if (shouldExpandForMC())
150 expandFalse(OS);
151 else
152 expandCheckOpcode(OS, Opcodes);
155 void 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]);
162 // Okay, there is more than one predicate in the set.
163 bool First = true;
164 OS << (shouldNegate() ? "!(" : "(");
165 increaseIndentLevel();
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;
177 OS << '\n';
178 decreaseIndentLevel();
179 OS.indent(getIndentLevel() * 2);
180 OS << ')';
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::expandCheckFunctionPredicate(raw_ostream &OS,
202 StringRef MCInstFn,
203 StringRef MachineInstrFn) {
204 OS << (shouldExpandForMC() ? MCInstFn : MachineInstrFn)
205 << (isByRef() ? "(MI)" : "(*MI)");
208 void PredicateExpander::expandCheckNonPortable(raw_ostream &OS,
209 StringRef Code) {
210 if (shouldExpandForMC())
211 return expandFalse(OS);
213 OS << '(' << Code << ')';
216 void PredicateExpander::expandReturnStatement(raw_ostream &OS,
217 const Record *Rec) {
218 std::string Buffer;
219 raw_string_ostream SS(Buffer);
221 SS << "return ";
222 expandPredicate(SS, Rec);
223 SS << ";";
224 SS.flush();
225 OS << Buffer;
228 void 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";
237 increaseIndentLevel();
238 OS.indent(getIndentLevel() * 2);
239 expandStatement(OS, Rec->getValueAsDef("CaseStmt"));
240 decreaseIndentLevel();
243 void PredicateExpander::expandOpcodeSwitchStatement(raw_ostream &OS,
244 const RecVec &Cases,
245 const Record *Default) {
246 std::string Buffer;
247 raw_string_ostream SS(Buffer);
249 SS << "switch(MI" << (isByRef() ? "." : "->") << "getOpcode()) {\n";
250 for (const Record *Rec : Cases) {
251 expandOpcodeSwitchCase(SS, Rec);
252 SS << '\n';
255 // Expand the default case.
256 SS.indent(getIndentLevel() * 2);
257 SS << "default:\n";
259 increaseIndentLevel();
260 SS.indent(getIndentLevel() * 2);
261 expandStatement(SS, Default);
262 decreaseIndentLevel();
263 SS << '\n';
265 SS.indent(getIndentLevel() * 2);
266 SS << "} // end of switch-stmt";
267 SS.flush();
268 OS << Buffer;
271 void 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;
279 if (Rec->isSubClassOf("MCReturnStatement")) {
280 expandReturnStatement(OS, Rec->getValueAsDef("Pred"));
281 return;
284 llvm_unreachable("No known rules to expand this MCStatement");
287 void 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);
295 if (Rec->isSubClassOf("MCFalse")) {
296 if (shouldNegate())
297 return expandTrue(OS);
298 return expandFalse(OS);
301 if (Rec->isSubClassOf("CheckNot")) {
302 flipNegatePredicate();
303 expandPredicate(OS, Rec->getValueAsDef("Pred"));
304 flipNegatePredicate();
305 return;
308 if (Rec->isSubClassOf("CheckIsRegOperand"))
309 return expandCheckIsRegOperand(OS, Rec->getValueAsInt("OpIndex"));
311 if (Rec->isSubClassOf("CheckIsImmOperand"))
312 return expandCheckIsImmOperand(OS, Rec->getValueAsInt("OpIndex"));
314 if (Rec->isSubClassOf("CheckRegOperand"))
315 return expandCheckRegOperand(OS, Rec->getValueAsInt("OpIndex"),
316 Rec->getValueAsDef("Reg"),
317 Rec->getValueAsString("FunctionMapper"));
319 if (Rec->isSubClassOf("CheckRegOperandSimple"))
320 return expandCheckRegOperandSimple(OS, Rec->getValueAsInt("OpIndex"),
321 Rec->getValueAsString("FunctionMapper"));
323 if (Rec->isSubClassOf("CheckInvalidRegOperand"))
324 return expandCheckInvalidRegOperand(OS, Rec->getValueAsInt("OpIndex"));
326 if (Rec->isSubClassOf("CheckImmOperand"))
327 return expandCheckImmOperand(OS, Rec->getValueAsInt("OpIndex"),
328 Rec->getValueAsInt("ImmVal"),
329 Rec->getValueAsString("FunctionMapper"));
331 if (Rec->isSubClassOf("CheckImmOperand_s"))
332 return expandCheckImmOperand(OS, Rec->getValueAsInt("OpIndex"),
333 Rec->getValueAsString("ImmVal"),
334 Rec->getValueAsString("FunctionMapper"));
336 if (Rec->isSubClassOf("CheckImmOperandSimple"))
337 return expandCheckImmOperandSimple(OS, Rec->getValueAsInt("OpIndex"),
338 Rec->getValueAsString("FunctionMapper"));
340 if (Rec->isSubClassOf("CheckSameRegOperand"))
341 return expandCheckSameRegOperand(OS, Rec->getValueAsInt("FirstIndex"),
342 Rec->getValueAsInt("SecondIndex"));
344 if (Rec->isSubClassOf("CheckNumOperands"))
345 return expandCheckNumOperands(OS, Rec->getValueAsInt("NumOps"));
347 if (Rec->isSubClassOf("CheckPseudo"))
348 return expandCheckPseudo(OS, Rec->getValueAsListOfDefs("ValidOpcodes"));
350 if (Rec->isSubClassOf("CheckOpcode"))
351 return expandCheckOpcode(OS, Rec->getValueAsListOfDefs("ValidOpcodes"));
353 if (Rec->isSubClassOf("CheckAll"))
354 return expandPredicateSequence(OS, Rec->getValueAsListOfDefs("Predicates"),
355 /* AllOf */ true);
357 if (Rec->isSubClassOf("CheckAny"))
358 return expandPredicateSequence(OS, Rec->getValueAsListOfDefs("Predicates"),
359 /* AllOf */ false);
361 if (Rec->isSubClassOf("CheckFunctionPredicate"))
362 return expandCheckFunctionPredicate(
363 OS, Rec->getValueAsString("MCInstFnName"),
364 Rec->getValueAsString("MachineInstrFnName"));
366 if (Rec->isSubClassOf("CheckNonPortable"))
367 return expandCheckNonPortable(OS, Rec->getValueAsString("CodeBlock"));
369 if (Rec->isSubClassOf("TIIPredicate"))
370 return expandTIIFunctionCall(OS, Rec->getValueAsString("FunctionName"));
372 llvm_unreachable("No known rules to expand this MCInstPredicate");
375 void STIPredicateExpander::expandHeader(raw_ostream &OS,
376 const STIPredicateFunction &Fn) {
377 const Record *Rec = Fn.getDeclaration();
378 StringRef FunctionName = Rec->getValueAsString("Name");
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;
397 if (Rec->getValueAsBit("OverridesBaseClassMember"))
398 OS << "override";
399 OS << ";\n";
402 void STIPredicateExpander::expandPrologue(raw_ostream &OS,
403 const STIPredicateFunction &Fn) {
404 RecVec Delegates = Fn.getDeclaration()->getValueAsListOfDefs("Delegates");
405 bool UpdatesOpcodeMask =
406 Fn.getDeclaration()->getValueAsBit("UpdatesOpcodeMask");
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";
422 if (shouldExpandForMC())
423 return;
425 OS.indent(IndentLevel * 2);
426 OS << "unsigned ProcessorID = getSchedModel().getProcessorID();\n";
429 void 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;
439 if (FirstProcID) {
440 OS.indent(getIndentLevel() * 2);
441 OS << "if (ProcessorID == " << I;
442 } else {
443 OS << " || ProcessorID == " << I;
445 FirstProcID = false;
448 OS << ") {\n";
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);
459 OS << "return ";
460 expandPredicate(OS, PI.Predicate);
461 OS << ";\n";
462 decreaseIndentLevel();
463 OS.indent(getIndentLevel() * 2);
464 OS << "}\n";
468 void STIPredicateExpander::expandBody(raw_ostream &OS,
469 const STIPredicateFunction &Fn) {
470 bool UpdatesOpcodeMask =
471 Fn.getDeclaration()->getValueAsBit("UpdatesOpcodeMask");
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;";
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() << ":";
488 OS << '\n';
489 increaseIndentLevel();
490 expandOpcodeGroup(OS, Group, UpdatesOpcodeMask);
492 OS.indent(getIndentLevel() * 2);
493 OS << "break;\n";
494 decreaseIndentLevel();
497 OS.indent(IndentLevel * 2);
498 OS << "}\n";
501 void 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";
509 decreaseIndentLevel();
510 OS.indent(getIndentLevel() * 2);
511 StringRef FunctionName = Fn.getDeclaration()->getValueAsString("Name");
512 OS << "} // " << ClassPrefix << "::" << FunctionName << "\n\n";
515 void STIPredicateExpander::expandSTIPredicate(raw_ostream &OS,
516 const STIPredicateFunction &Fn) {
517 const Record *Rec = Fn.getDeclaration();
518 if (shouldExpandForMC() && !Rec->getValueAsBit("ExpandForMC"))
519 return;
521 expandHeader(OS, Fn);
522 if (shouldExpandDefinition()) {
523 expandPrologue(OS, Fn);
524 expandBody(OS, Fn);
525 expandEpilogue(OS, Fn);
529 } // namespace llvm