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.
10//
11//===----------------------------------------------------------------------===//
12
13#include "PredicateExpander.h"
14#include "CodeGenSchedule.h" // Definition of STIPredicateFunction.
15#include "llvm/TableGen/Record.h"
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::expandCheckImmOperandLT(raw_ostream &OS, int OpIndex,
63 int ImmVal,
64 StringRef FunctionMapper) {
65 if (!FunctionMapper.empty())
66 OS << FunctionMapper << "(";
67 OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
68 << ").getImm()";
69 if (!FunctionMapper.empty())
70 OS << ")";
71 OS << (shouldNegate() ? " >= " : " < ") << ImmVal;
72}
73
74void PredicateExpander::expandCheckImmOperandGT(raw_ostream &OS, int OpIndex,
75 int ImmVal,
76 StringRef FunctionMapper) {
77 if (!FunctionMapper.empty())
78 OS << FunctionMapper << "(";
79 OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
80 << ").getImm()";
81 if (!FunctionMapper.empty())
82 OS << ")";
83 OS << (shouldNegate() ? " <= " : " > ") << ImmVal;
84}
85
86void PredicateExpander::expandCheckRegOperand(raw_ostream &OS, int OpIndex,
87 const Record *Reg,
88 StringRef FunctionMapper) {
89 assert(Reg->isSubClassOf("Register") && "Expected a register Record!");
90
91 if (!FunctionMapper.empty())
92 OS << FunctionMapper << "(";
93 OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
94 << ").getReg()";
95 if (!FunctionMapper.empty())
96 OS << ")";
97 OS << (shouldNegate() ? " != " : " == ");
98 const StringRef Str = Reg->getValueAsString(FieldName: "Namespace");
99 if (!Str.empty())
100 OS << Str << "::";
101 OS << Reg->getName();
102}
103
104void PredicateExpander::expandCheckRegOperandSimple(raw_ostream &OS,
105 int OpIndex,
106 StringRef FunctionMapper) {
107 if (shouldNegate())
108 OS << "!";
109 if (!FunctionMapper.empty())
110 OS << FunctionMapper << "(";
111 OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
112 << ").getReg()";
113 if (!FunctionMapper.empty())
114 OS << ")";
115}
116
117void PredicateExpander::expandCheckInvalidRegOperand(raw_ostream &OS,
118 int OpIndex) {
119 if (!shouldNegate())
120 OS << "!";
121 OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
122 << ").getReg().isValid()";
123}
124
125void PredicateExpander::expandCheckSameRegOperand(raw_ostream &OS, int First,
126 int Second) {
127 OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << First
128 << ").getReg() " << (shouldNegate() ? "!=" : "==") << " MI"
129 << (isByRef() ? "." : "->") << "getOperand(" << Second << ").getReg()";
130}
131
132void PredicateExpander::expandCheckNumOperands(raw_ostream &OS, int NumOps) {
133 OS << "MI" << (isByRef() ? "." : "->") << "getNumOperands() "
134 << (shouldNegate() ? "!= " : "== ") << NumOps;
135}
136
137void PredicateExpander::expandCheckOpcode(raw_ostream &OS, const Record *Inst) {
138 OS << "MI" << (isByRef() ? "." : "->") << "getOpcode() "
139 << (shouldNegate() ? "!= " : "== ") << Inst->getValueAsString(FieldName: "Namespace")
140 << "::" << Inst->getName();
141}
142
143void PredicateExpander::expandCheckOpcode(raw_ostream &OS,
144 ArrayRef<const Record *> Opcodes) {
145 assert(!Opcodes.empty() && "Expected at least one opcode to check!");
146
147 if (Opcodes.size() == 1) {
148 OS << "( ";
149 expandCheckOpcode(OS, Inst: Opcodes[0]);
150 OS << " )";
151 return;
152 }
153
154 if (shouldNegate())
155 OS << '!';
156 OS << "llvm::is_contained(";
157 ListSeparator Sep;
158 OS << '{';
159 for (const Record *Inst : Opcodes)
160 OS << Sep << Inst->getValueAsString(FieldName: "Namespace") << "::" << Inst->getName();
161 OS << '}';
162 OS << ", MI" << (isByRef() ? "." : "->") << "getOpcode())";
163}
164
165void PredicateExpander::expandCheckPseudo(raw_ostream &OS,
166 ArrayRef<const Record *> Opcodes) {
167 if (shouldExpandForMC())
168 expandFalse(OS);
169 else
170 expandCheckOpcode(OS, Opcodes);
171}
172
173void PredicateExpander::expandPredicateSequence(
174 raw_ostream &OS, ArrayRef<const Record *> Sequence, bool IsCheckAll) {
175 assert(!Sequence.empty() && "Found an invalid empty predicate set!");
176 if (Sequence.size() == 1)
177 return expandPredicate(OS, Rec: Sequence[0]);
178
179 // Okay, there is more than one predicate in the set.
180 bool First = true;
181 OS << (shouldNegate() ? "!(" : "(");
182 ++Indent;
183
184 bool OldValue = shouldNegate();
185 setNegatePredicate(false);
186 for (const Record *Rec : Sequence) {
187 OS << '\n' << Indent;
188 if (!First)
189 OS << (IsCheckAll ? "&& " : "|| ");
190 expandPredicate(OS, Rec);
191 First = false;
192 }
193 --Indent;
194 OS << '\n' << Indent << ')';
195 setNegatePredicate(OldValue);
196}
197
198void PredicateExpander::expandTIIFunctionCall(raw_ostream &OS,
199 StringRef MethodName) {
200 OS << (shouldNegate() ? "!" : "");
201 OS << TargetName << (shouldExpandForMC() ? "_MC::" : "InstrInfo::");
202 OS << MethodName << (isByRef() ? "(MI)" : "(*MI)");
203}
204
205void PredicateExpander::expandCheckIsRegOperand(raw_ostream &OS, int OpIndex) {
206 OS << (shouldNegate() ? "!" : "") << "MI" << (isByRef() ? "." : "->")
207 << "getOperand(" << OpIndex << ").isReg() ";
208}
209
210void PredicateExpander::expandCheckIsVRegOperand(raw_ostream &OS, int OpIndex) {
211 OS << (shouldNegate() ? "!" : "") << "MI" << (isByRef() ? "." : "->")
212 << "getOperand(" << OpIndex << ").getReg().isVirtual()";
213}
214
215void PredicateExpander::expandCheckIsImmOperand(raw_ostream &OS, int OpIndex) {
216 OS << (shouldNegate() ? "!" : "") << "MI" << (isByRef() ? "." : "->")
217 << "getOperand(" << OpIndex << ").isImm() ";
218}
219
220void PredicateExpander::expandCheckFunctionPredicateWithTII(
221 raw_ostream &OS, StringRef MCInstFn, StringRef MachineInstrFn,
222 StringRef TIIPtr) {
223 if (!shouldExpandForMC()) {
224 OS << (TIIPtr.empty() ? "TII" : TIIPtr) << "->" << MachineInstrFn;
225 OS << (isByRef() ? "(MI)" : "(*MI)");
226 return;
227 }
228
229 OS << MCInstFn << (isByRef() ? "(MI" : "(*MI") << ", MCII)";
230}
231
232void PredicateExpander::expandCheckFunctionPredicate(raw_ostream &OS,
233 StringRef MCInstFn,
234 StringRef MachineInstrFn) {
235 OS << (shouldExpandForMC() ? MCInstFn : MachineInstrFn)
236 << (isByRef() ? "(MI)" : "(*MI)");
237}
238
239void PredicateExpander::expandCheckNonPortable(raw_ostream &OS,
240 StringRef Code) {
241 if (shouldExpandForMC())
242 return expandFalse(OS);
243
244 OS << '(' << Code << ')';
245}
246
247void PredicateExpander::expandReturnStatement(raw_ostream &OS,
248 const Record *Rec) {
249 std::string Buffer;
250 raw_string_ostream SS(Buffer);
251
252 SS << "return ";
253 expandPredicate(OS&: SS, Rec);
254 SS << ";";
255 OS << Buffer;
256}
257
258void PredicateExpander::expandOpcodeSwitchCase(raw_ostream &OS,
259 const Record *Rec) {
260 for (const Record *Opcode : Rec->getValueAsListOfDefs(FieldName: "Opcodes")) {
261 OS << Indent << "case " << Opcode->getValueAsString(FieldName: "Namespace")
262 << "::" << Opcode->getName() << ":\n";
263 }
264
265 ++Indent;
266 OS << Indent;
267 expandStatement(OS, Rec: Rec->getValueAsDef(FieldName: "CaseStmt"));
268 --Indent;
269}
270
271void PredicateExpander::expandOpcodeSwitchStatement(
272 raw_ostream &OS, ArrayRef<const Record *> Cases, const Record *Default) {
273 std::string Buffer;
274 raw_string_ostream SS(Buffer);
275
276 SS << "switch(MI" << (isByRef() ? "." : "->") << "getOpcode()) {\n";
277 for (const Record *Rec : Cases) {
278 expandOpcodeSwitchCase(OS&: SS, Rec);
279 SS << '\n';
280 }
281
282 // Expand the default case.
283 SS << Indent << "default:\n";
284
285 ++Indent;
286 SS << Indent;
287 expandStatement(OS&: SS, Rec: Default);
288 SS << '\n' << Indent << "} // end of switch-stmt";
289 OS << Buffer;
290}
291
292void PredicateExpander::expandStatement(raw_ostream &OS, const Record *Rec) {
293 // Assume that padding has been added by the caller.
294 if (Rec->isSubClassOf(Name: "MCOpcodeSwitchStatement")) {
295 expandOpcodeSwitchStatement(OS, Cases: Rec->getValueAsListOfDefs(FieldName: "Cases"),
296 Default: Rec->getValueAsDef(FieldName: "DefaultCase"));
297 return;
298 }
299
300 if (Rec->isSubClassOf(Name: "MCReturnStatement")) {
301 expandReturnStatement(OS, Rec: Rec->getValueAsDef(FieldName: "Pred"));
302 return;
303 }
304
305 llvm_unreachable("No known rules to expand this MCStatement");
306}
307
308void PredicateExpander::expandPredicate(raw_ostream &OS, const Record *Rec) {
309 // Assume that padding has been added by the caller.
310 if (Rec->isSubClassOf(Name: "MCTrue")) {
311 if (shouldNegate())
312 return expandFalse(OS);
313 return expandTrue(OS);
314 }
315
316 if (Rec->isSubClassOf(Name: "MCFalse")) {
317 if (shouldNegate())
318 return expandTrue(OS);
319 return expandFalse(OS);
320 }
321
322 if (Rec->isSubClassOf(Name: "CheckNot")) {
323 flipNegatePredicate();
324 expandPredicate(OS, Rec: Rec->getValueAsDef(FieldName: "Pred"));
325 flipNegatePredicate();
326 return;
327 }
328
329 if (Rec->isSubClassOf(Name: "CheckIsRegOperand"))
330 return expandCheckIsRegOperand(OS, OpIndex: Rec->getValueAsInt(FieldName: "OpIndex"));
331
332 if (Rec->isSubClassOf(Name: "CheckIsVRegOperand"))
333 return expandCheckIsVRegOperand(OS, OpIndex: Rec->getValueAsInt(FieldName: "OpIndex"));
334
335 if (Rec->isSubClassOf(Name: "CheckIsImmOperand"))
336 return expandCheckIsImmOperand(OS, OpIndex: Rec->getValueAsInt(FieldName: "OpIndex"));
337
338 if (Rec->isSubClassOf(Name: "CheckRegOperand"))
339 return expandCheckRegOperand(OS, OpIndex: Rec->getValueAsInt(FieldName: "OpIndex"),
340 Reg: Rec->getValueAsDef(FieldName: "Reg"),
341 FunctionMapper: Rec->getValueAsString(FieldName: "FunctionMapper"));
342
343 if (Rec->isSubClassOf(Name: "CheckRegOperandSimple"))
344 return expandCheckRegOperandSimple(OS, OpIndex: Rec->getValueAsInt(FieldName: "OpIndex"),
345 FunctionMapper: Rec->getValueAsString(FieldName: "FunctionMapper"));
346
347 if (Rec->isSubClassOf(Name: "CheckInvalidRegOperand"))
348 return expandCheckInvalidRegOperand(OS, OpIndex: Rec->getValueAsInt(FieldName: "OpIndex"));
349
350 if (Rec->isSubClassOf(Name: "CheckImmOperand"))
351 return expandCheckImmOperand(OS, OpIndex: Rec->getValueAsInt(FieldName: "OpIndex"),
352 ImmVal: Rec->getValueAsInt(FieldName: "ImmVal"),
353 FunctionMapper: Rec->getValueAsString(FieldName: "FunctionMapper"));
354
355 if (Rec->isSubClassOf(Name: "CheckImmOperand_s"))
356 return expandCheckImmOperand(OS, OpIndex: Rec->getValueAsInt(FieldName: "OpIndex"),
357 ImmVal: Rec->getValueAsString(FieldName: "ImmVal"),
358 FunctionMapper: Rec->getValueAsString(FieldName: "FunctionMapper"));
359
360 if (Rec->isSubClassOf(Name: "CheckImmOperandLT"))
361 return expandCheckImmOperandLT(OS, OpIndex: Rec->getValueAsInt(FieldName: "OpIndex"),
362 ImmVal: Rec->getValueAsInt(FieldName: "ImmVal"),
363 FunctionMapper: Rec->getValueAsString(FieldName: "FunctionMapper"));
364
365 if (Rec->isSubClassOf(Name: "CheckImmOperandGT"))
366 return expandCheckImmOperandGT(OS, OpIndex: Rec->getValueAsInt(FieldName: "OpIndex"),
367 ImmVal: Rec->getValueAsInt(FieldName: "ImmVal"),
368 FunctionMapper: Rec->getValueAsString(FieldName: "FunctionMapper"));
369
370 if (Rec->isSubClassOf(Name: "CheckImmOperandSimple"))
371 return expandCheckImmOperandSimple(OS, OpIndex: Rec->getValueAsInt(FieldName: "OpIndex"),
372 FunctionMapper: Rec->getValueAsString(FieldName: "FunctionMapper"));
373
374 if (Rec->isSubClassOf(Name: "CheckSameRegOperand"))
375 return expandCheckSameRegOperand(OS, First: Rec->getValueAsInt(FieldName: "FirstIndex"),
376 Second: Rec->getValueAsInt(FieldName: "SecondIndex"));
377
378 if (Rec->isSubClassOf(Name: "CheckNumOperands"))
379 return expandCheckNumOperands(OS, NumOps: Rec->getValueAsInt(FieldName: "NumOps"));
380
381 if (Rec->isSubClassOf(Name: "CheckPseudo"))
382 return expandCheckPseudo(OS, Opcodes: Rec->getValueAsListOfDefs(FieldName: "ValidOpcodes"));
383
384 if (Rec->isSubClassOf(Name: "CheckOpcode"))
385 return expandCheckOpcode(OS, Opcodes: Rec->getValueAsListOfDefs(FieldName: "ValidOpcodes"));
386
387 if (Rec->isSubClassOf(Name: "CheckAll"))
388 return expandPredicateSequence(OS, Sequence: Rec->getValueAsListOfDefs(FieldName: "Predicates"),
389 /* AllOf */ IsCheckAll: true);
390
391 if (Rec->isSubClassOf(Name: "CheckAny"))
392 return expandPredicateSequence(OS, Sequence: Rec->getValueAsListOfDefs(FieldName: "Predicates"),
393 /* AllOf */ IsCheckAll: false);
394
395 if (Rec->isSubClassOf(Name: "CheckFunctionPredicate")) {
396 return expandCheckFunctionPredicate(
397 OS, MCInstFn: Rec->getValueAsString(FieldName: "MCInstFnName"),
398 MachineInstrFn: Rec->getValueAsString(FieldName: "MachineInstrFnName"));
399 }
400
401 if (Rec->isSubClassOf(Name: "CheckFunctionPredicateWithTII")) {
402 return expandCheckFunctionPredicateWithTII(
403 OS, MCInstFn: Rec->getValueAsString(FieldName: "MCInstFnName"),
404 MachineInstrFn: Rec->getValueAsString(FieldName: "MachineInstrFnName"),
405 TIIPtr: Rec->getValueAsString(FieldName: "TIIPtrName"));
406 }
407
408 if (Rec->isSubClassOf(Name: "CheckNonPortable"))
409 return expandCheckNonPortable(OS, Code: Rec->getValueAsString(FieldName: "CodeBlock"));
410
411 if (Rec->isSubClassOf(Name: "TIIPredicate"))
412 return expandTIIFunctionCall(OS, MethodName: Rec->getValueAsString(FieldName: "FunctionName"));
413
414 llvm_unreachable("No known rules to expand this MCInstPredicate");
415}
416
417void STIPredicateExpander::expandHeader(raw_ostream &OS,
418 const STIPredicateFunction &Fn) {
419 const Record *Rec = Fn.getDeclaration();
420 StringRef FunctionName = Rec->getValueAsString(FieldName: "Name");
421
422 OS << Indent << "bool ";
423 if (shouldExpandDefinition())
424 OS << getClassPrefix() << "::";
425 OS << FunctionName << "(";
426 if (shouldExpandForMC())
427 OS << "const MCInst " << (isByRef() ? "&" : "*") << "MI";
428 else
429 OS << "const MachineInstr " << (isByRef() ? "&" : "*") << "MI";
430 if (Rec->getValueAsBit(FieldName: "UpdatesOpcodeMask"))
431 OS << ", APInt &Mask";
432 OS << (shouldExpandForMC() ? ", unsigned ProcessorID) const " : ") const ");
433 if (shouldExpandDefinition()) {
434 OS << "{\n";
435 return;
436 }
437
438 if (Rec->getValueAsBit(FieldName: "OverridesBaseClassMember"))
439 OS << "override";
440 OS << ";\n";
441}
442
443void STIPredicateExpander::expandPrologue(raw_ostream &OS,
444 const STIPredicateFunction &Fn) {
445 bool UpdatesOpcodeMask =
446 Fn.getDeclaration()->getValueAsBit(FieldName: "UpdatesOpcodeMask");
447
448 ++Indent;
449 for (const Record *Delegate :
450 Fn.getDeclaration()->getValueAsListOfDefs(FieldName: "Delegates")) {
451 OS << Indent << "if (" << Delegate->getValueAsString(FieldName: "Name") << "(MI";
452 if (UpdatesOpcodeMask)
453 OS << ", Mask";
454 if (shouldExpandForMC())
455 OS << ", ProcessorID";
456 OS << "))\n";
457 OS << Indent + 1 << "return true;\n\n";
458 }
459
460 if (shouldExpandForMC())
461 return;
462
463 OS << Indent << "unsigned ProcessorID = getSchedModel().getProcessorID();\n";
464}
465
466void STIPredicateExpander::expandOpcodeGroup(raw_ostream &OS,
467 const OpcodeGroup &Group,
468 bool ShouldUpdateOpcodeMask) {
469 const OpcodeInfo &OI = Group.getOpcodeInfo();
470 for (const PredicateInfo &PI : OI.getPredicates()) {
471 const APInt &ProcModelMask = PI.ProcModelMask;
472 bool FirstProcID = true;
473 for (unsigned I = 0, E = ProcModelMask.getActiveBits(); I < E; ++I) {
474 if (!ProcModelMask[I])
475 continue;
476
477 if (FirstProcID) {
478 OS << Indent << "if (ProcessorID == " << I;
479 } else {
480 OS << " || ProcessorID == " << I;
481 }
482 FirstProcID = false;
483 }
484
485 OS << ") {\n";
486
487 ++Indent;
488 OS << Indent;
489 if (ShouldUpdateOpcodeMask) {
490 if (PI.OperandMask.isZero())
491 OS << "Mask.clearAllBits();\n";
492 else
493 OS << "Mask = " << PI.OperandMask << ";\n";
494 OS << Indent;
495 }
496 OS << "return ";
497 expandPredicate(OS, Rec: PI.Predicate);
498 OS << ";\n";
499 --Indent;
500 OS << Indent << "}\n";
501 }
502}
503
504void STIPredicateExpander::expandBody(raw_ostream &OS,
505 const STIPredicateFunction &Fn) {
506 bool UpdatesOpcodeMask =
507 Fn.getDeclaration()->getValueAsBit(FieldName: "UpdatesOpcodeMask");
508
509 OS << Indent << "switch(MI" << (isByRef() ? "." : "->") << "getOpcode()) {\n";
510 OS << Indent << "default:\n";
511 OS << Indent << " break;";
512
513 for (const OpcodeGroup &Group : Fn.getGroups()) {
514 for (const Record *Opcode : Group.getOpcodes()) {
515 OS << '\n'
516 << Indent << "case " << getTargetName() << "::" << Opcode->getName()
517 << ":";
518 }
519
520 OS << '\n';
521 ++Indent;
522 expandOpcodeGroup(OS, Group, ShouldUpdateOpcodeMask: UpdatesOpcodeMask);
523
524 OS << Indent << "break;\n";
525 --Indent;
526 }
527
528 OS << Indent << "}\n";
529}
530
531void STIPredicateExpander::expandEpilogue(raw_ostream &OS,
532 const STIPredicateFunction &Fn) {
533 OS << '\n' << Indent;
534 OS << "return ";
535 expandPredicate(OS, Rec: Fn.getDefaultReturnPredicate());
536 OS << ";\n";
537
538 --Indent;
539 StringRef FunctionName = Fn.getDeclaration()->getValueAsString(FieldName: "Name");
540 OS << Indent << "} // " << ClassPrefix << "::" << FunctionName << "\n\n";
541}
542
543void STIPredicateExpander::expandSTIPredicate(raw_ostream &OS,
544 const STIPredicateFunction &Fn) {
545 const Record *Rec = Fn.getDeclaration();
546 if (shouldExpandForMC() && !Rec->getValueAsBit(FieldName: "ExpandForMC"))
547 return;
548
549 expandHeader(OS, Fn);
550 if (shouldExpandDefinition()) {
551 expandPrologue(OS, Fn);
552 expandBody(OS, Fn);
553 expandEpilogue(OS, Fn);
554 }
555}
556
557} // namespace llvm
558