[RISCV][VLOPT] Add vector narrowing integer right shift instructions to isSupportedIn...
[llvm-project.git] / llvm / utils / TableGen / CompressInstEmitter.cpp
blob7ebfe50a86d0fb484aa9ba339c0b05fb59ed6a1c
1 //===-------- CompressInstEmitter.cpp - Generator for Compression ---------===//
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 // CompressInstEmitter implements a tablegen-driven CompressPat based
8 // Instruction Compression mechanism.
9 //
10 //===----------------------------------------------------------------------===//
12 // CompressInstEmitter implements a tablegen-driven CompressPat Instruction
13 // Compression mechanism for generating compressed instructions from the
14 // expanded instruction form.
16 // This tablegen backend processes CompressPat declarations in a
17 // td file and generates all the required checks to validate the pattern
18 // declarations; validate the input and output operands to generate the correct
19 // compressed instructions. The checks include validating different types of
20 // operands; register operands, immediate operands, fixed register and fixed
21 // immediate inputs.
23 // Example:
24 // /// Defines a Pat match between compressed and uncompressed instruction.
25 // /// The relationship and helper function generation are handled by
26 // /// CompressInstEmitter backend.
27 // class CompressPat<dag input, dag output, list<Predicate> predicates = []> {
28 // /// Uncompressed instruction description.
29 // dag Input = input;
30 // /// Compressed instruction description.
31 // dag Output = output;
32 // /// Predicates that must be true for this to match.
33 // list<Predicate> Predicates = predicates;
34 // /// Duplicate match when tied operand is just different.
35 // bit isCompressOnly = false;
36 // }
38 // let Predicates = [HasStdExtC] in {
39 // def : CompressPat<(ADD GPRNoX0:$rs1, GPRNoX0:$rs1, GPRNoX0:$rs2),
40 // (C_ADD GPRNoX0:$rs1, GPRNoX0:$rs2)>;
41 // }
43 // The <TargetName>GenCompressInstEmitter.inc is an auto-generated header
44 // file which exports two functions for compressing/uncompressing MCInst
45 // instructions, plus some helper functions:
47 // bool compressInst(MCInst &OutInst, const MCInst &MI,
48 // const MCSubtargetInfo &STI);
50 // bool uncompressInst(MCInst &OutInst, const MCInst &MI,
51 // const MCSubtargetInfo &STI);
53 // In addition, it exports a function for checking whether
54 // an instruction is compressable:
56 // bool isCompressibleInst(const MachineInstr& MI,
57 // const <TargetName>Subtarget &STI);
59 // The clients that include this auto-generated header file and
60 // invoke these functions can compress an instruction before emitting
61 // it in the target-specific ASM or ELF streamer or can uncompress
62 // an instruction before printing it when the expanded instruction
63 // format aliases is favored.
65 //===----------------------------------------------------------------------===//
67 #include "Common/CodeGenInstruction.h"
68 #include "Common/CodeGenRegisters.h"
69 #include "Common/CodeGenTarget.h"
70 #include "llvm/ADT/IndexedMap.h"
71 #include "llvm/ADT/SmallVector.h"
72 #include "llvm/ADT/StringMap.h"
73 #include "llvm/Support/Debug.h"
74 #include "llvm/Support/ErrorHandling.h"
75 #include "llvm/TableGen/Error.h"
76 #include "llvm/TableGen/Record.h"
77 #include "llvm/TableGen/TableGenBackend.h"
78 #include <set>
79 #include <vector>
80 using namespace llvm;
82 #define DEBUG_TYPE "compress-inst-emitter"
84 namespace {
85 class CompressInstEmitter {
86 struct OpData {
87 enum MapKind { Operand, Imm, Reg };
88 MapKind Kind;
89 union {
90 // Operand number mapped to.
91 unsigned Operand;
92 // Integer immediate value.
93 int64_t Imm;
94 // Physical register.
95 const Record *Reg;
96 } Data;
97 // Tied operand index within the instruction.
98 int TiedOpIdx = -1;
100 struct CompressPat {
101 // The source instruction definition.
102 CodeGenInstruction Source;
103 // The destination instruction to transform to.
104 CodeGenInstruction Dest;
105 // Required target features to enable pattern.
106 std::vector<const Record *> PatReqFeatures;
107 // Maps operands in the Source Instruction to
108 // the corresponding Dest instruction operand.
109 IndexedMap<OpData> SourceOperandMap;
110 // Maps operands in the Dest Instruction
111 // to the corresponding Source instruction operand.
112 IndexedMap<OpData> DestOperandMap;
114 bool IsCompressOnly;
115 CompressPat(const CodeGenInstruction &S, const CodeGenInstruction &D,
116 std::vector<const Record *> RF, IndexedMap<OpData> &SourceMap,
117 IndexedMap<OpData> &DestMap, bool IsCompressOnly)
118 : Source(S), Dest(D), PatReqFeatures(std::move(RF)),
119 SourceOperandMap(SourceMap), DestOperandMap(DestMap),
120 IsCompressOnly(IsCompressOnly) {}
122 enum EmitterType { Compress, Uncompress, CheckCompress };
123 const RecordKeeper &Records;
124 const CodeGenTarget Target;
125 SmallVector<CompressPat, 4> CompressPatterns;
127 void addDagOperandMapping(const Record *Rec, const DagInit *Dag,
128 const CodeGenInstruction &Inst,
129 IndexedMap<OpData> &OperandMap, bool IsSourceInst);
130 void evaluateCompressPat(const Record *Compress);
131 void emitCompressInstEmitter(raw_ostream &OS, EmitterType EType);
132 bool validateTypes(const Record *DagOpType, const Record *InstOpType,
133 bool IsSourceInst);
134 bool validateRegister(const Record *Reg, const Record *RegClass);
135 void createDagOperandMapping(const Record *Rec,
136 StringMap<unsigned> &SourceOperands,
137 StringMap<unsigned> &DestOperands,
138 const DagInit *SourceDag, const DagInit *DestDag,
139 IndexedMap<OpData> &SourceOperandMap);
141 void createInstOperandMapping(const Record *Rec, const DagInit *SourceDag,
142 const DagInit *DestDag,
143 IndexedMap<OpData> &SourceOperandMap,
144 IndexedMap<OpData> &DestOperandMap,
145 StringMap<unsigned> &SourceOperands,
146 const CodeGenInstruction &DestInst);
148 public:
149 CompressInstEmitter(const RecordKeeper &R) : Records(R), Target(R) {}
151 void run(raw_ostream &OS);
153 } // End anonymous namespace.
155 bool CompressInstEmitter::validateRegister(const Record *Reg,
156 const Record *RegClass) {
157 assert(Reg->isSubClassOf("Register") && "Reg record should be a Register");
158 assert(RegClass->isSubClassOf("RegisterClass") &&
159 "RegClass record should be a RegisterClass");
160 const CodeGenRegisterClass &RC = Target.getRegisterClass(RegClass);
161 const CodeGenRegister *R = Target.getRegisterByName(Reg->getName().lower());
162 assert(R != nullptr && "Register not defined!!");
163 return RC.contains(R);
166 bool CompressInstEmitter::validateTypes(const Record *DagOpType,
167 const Record *InstOpType,
168 bool IsSourceInst) {
169 if (DagOpType == InstOpType)
170 return true;
171 // Only source instruction operands are allowed to not match Input Dag
172 // operands.
173 if (!IsSourceInst)
174 return false;
176 if (DagOpType->isSubClassOf("RegisterClass") &&
177 InstOpType->isSubClassOf("RegisterClass")) {
178 const CodeGenRegisterClass &RC = Target.getRegisterClass(InstOpType);
179 const CodeGenRegisterClass &SubRC = Target.getRegisterClass(DagOpType);
180 return RC.hasSubClass(&SubRC);
183 // At this point either or both types are not registers, reject the pattern.
184 if (DagOpType->isSubClassOf("RegisterClass") ||
185 InstOpType->isSubClassOf("RegisterClass"))
186 return false;
188 // Let further validation happen when compress()/uncompress() functions are
189 // invoked.
190 LLVM_DEBUG(dbgs() << (IsSourceInst ? "Input" : "Output")
191 << " Dag Operand Type: '" << DagOpType->getName()
192 << "' and "
193 << "Instruction Operand Type: '" << InstOpType->getName()
194 << "' can't be checked at pattern validation time!\n");
195 return true;
198 /// The patterns in the Dag contain different types of operands:
199 /// Register operands, e.g.: GPRC:$rs1; Fixed registers, e.g: X1; Immediate
200 /// operands, e.g.: simm6:$imm; Fixed immediate operands, e.g.: 0. This function
201 /// maps Dag operands to its corresponding instruction operands. For register
202 /// operands and fixed registers it expects the Dag operand type to be contained
203 /// in the instantiated instruction operand type. For immediate operands and
204 /// immediates no validation checks are enforced at pattern validation time.
205 void CompressInstEmitter::addDagOperandMapping(const Record *Rec,
206 const DagInit *Dag,
207 const CodeGenInstruction &Inst,
208 IndexedMap<OpData> &OperandMap,
209 bool IsSourceInst) {
210 // TiedCount keeps track of the number of operands skipped in Inst
211 // operands list to get to the corresponding Dag operand. This is
212 // necessary because the number of operands in Inst might be greater
213 // than number of operands in the Dag due to how tied operands
214 // are represented.
215 unsigned TiedCount = 0;
216 for (unsigned I = 0, E = Inst.Operands.size(); I != E; ++I) {
217 int TiedOpIdx = Inst.Operands[I].getTiedRegister();
218 if (-1 != TiedOpIdx) {
219 // Set the entry in OperandMap for the tied operand we're skipping.
220 OperandMap[I].Kind = OperandMap[TiedOpIdx].Kind;
221 OperandMap[I].Data = OperandMap[TiedOpIdx].Data;
222 TiedCount++;
223 continue;
225 if (const DefInit *DI = dyn_cast<DefInit>(Dag->getArg(I - TiedCount))) {
226 if (DI->getDef()->isSubClassOf("Register")) {
227 // Check if the fixed register belongs to the Register class.
228 if (!validateRegister(DI->getDef(), Inst.Operands[I].Rec))
229 PrintFatalError(Rec->getLoc(),
230 "Error in Dag '" + Dag->getAsString() +
231 "'Register: '" + DI->getDef()->getName() +
232 "' is not in register class '" +
233 Inst.Operands[I].Rec->getName() + "'");
234 OperandMap[I].Kind = OpData::Reg;
235 OperandMap[I].Data.Reg = DI->getDef();
236 continue;
238 // Validate that Dag operand type matches the type defined in the
239 // corresponding instruction. Operands in the input Dag pattern are
240 // allowed to be a subclass of the type specified in corresponding
241 // instruction operand instead of being an exact match.
242 if (!validateTypes(DI->getDef(), Inst.Operands[I].Rec, IsSourceInst))
243 PrintFatalError(Rec->getLoc(),
244 "Error in Dag '" + Dag->getAsString() + "'. Operand '" +
245 Dag->getArgNameStr(I - TiedCount) + "' has type '" +
246 DI->getDef()->getName() +
247 "' which does not match the type '" +
248 Inst.Operands[I].Rec->getName() +
249 "' in the corresponding instruction operand!");
251 OperandMap[I].Kind = OpData::Operand;
252 } else if (const IntInit *II =
253 dyn_cast<IntInit>(Dag->getArg(I - TiedCount))) {
254 // Validate that corresponding instruction operand expects an immediate.
255 if (Inst.Operands[I].Rec->isSubClassOf("RegisterClass"))
256 PrintFatalError(
257 Rec->getLoc(),
258 "Error in Dag '" + Dag->getAsString() + "' Found immediate: '" +
259 II->getAsString() +
260 "' but corresponding instruction operand expected a register!");
261 // No pattern validation check possible for values of fixed immediate.
262 OperandMap[I].Kind = OpData::Imm;
263 OperandMap[I].Data.Imm = II->getValue();
264 LLVM_DEBUG(
265 dbgs() << " Found immediate '" << II->getValue() << "' at "
266 << (IsSourceInst ? "input " : "output ")
267 << "Dag. No validation time check possible for values of "
268 "fixed immediate.\n");
269 } else
270 llvm_unreachable("Unhandled CompressPat argument type!");
274 // Verify the Dag operand count is enough to build an instruction.
275 static bool verifyDagOpCount(const CodeGenInstruction &Inst, const DagInit *Dag,
276 bool IsSource) {
277 if (Dag->getNumArgs() == Inst.Operands.size())
278 return true;
279 // Source instructions are non compressed instructions and don't have tied
280 // operands.
281 if (IsSource)
282 PrintFatalError(Inst.TheDef->getLoc(),
283 "Input operands for Inst '" + Inst.TheDef->getName() +
284 "' and input Dag operand count mismatch");
285 // The Dag can't have more arguments than the Instruction.
286 if (Dag->getNumArgs() > Inst.Operands.size())
287 PrintFatalError(Inst.TheDef->getLoc(),
288 "Inst '" + Inst.TheDef->getName() +
289 "' and Dag operand count mismatch");
291 // The Instruction might have tied operands so the Dag might have
292 // a fewer operand count.
293 unsigned RealCount = Inst.Operands.size();
294 for (const auto &Operand : Inst.Operands)
295 if (Operand.getTiedRegister() != -1)
296 --RealCount;
298 if (Dag->getNumArgs() != RealCount)
299 PrintFatalError(Inst.TheDef->getLoc(),
300 "Inst '" + Inst.TheDef->getName() +
301 "' and Dag operand count mismatch");
302 return true;
305 static bool validateArgsTypes(const Init *Arg1, const Init *Arg2) {
306 return cast<DefInit>(Arg1)->getDef() == cast<DefInit>(Arg2)->getDef();
309 // Creates a mapping between the operand name in the Dag (e.g. $rs1) and
310 // its index in the list of Dag operands and checks that operands with the same
311 // name have the same types. For example in 'C_ADD $rs1, $rs2' we generate the
312 // mapping $rs1 --> 0, $rs2 ---> 1. If the operand appears twice in the (tied)
313 // same Dag we use the last occurrence for indexing.
314 void CompressInstEmitter::createDagOperandMapping(
315 const Record *Rec, StringMap<unsigned> &SourceOperands,
316 StringMap<unsigned> &DestOperands, const DagInit *SourceDag,
317 const DagInit *DestDag, IndexedMap<OpData> &SourceOperandMap) {
318 for (unsigned I = 0; I < DestDag->getNumArgs(); ++I) {
319 // Skip fixed immediates and registers, they were handled in
320 // addDagOperandMapping.
321 if ("" == DestDag->getArgNameStr(I))
322 continue;
323 DestOperands[DestDag->getArgNameStr(I)] = I;
326 for (unsigned I = 0; I < SourceDag->getNumArgs(); ++I) {
327 // Skip fixed immediates and registers, they were handled in
328 // addDagOperandMapping.
329 if ("" == SourceDag->getArgNameStr(I))
330 continue;
332 StringMap<unsigned>::iterator It =
333 SourceOperands.find(SourceDag->getArgNameStr(I));
334 if (It != SourceOperands.end()) {
335 // Operand sharing the same name in the Dag should be mapped as tied.
336 SourceOperandMap[I].TiedOpIdx = It->getValue();
337 if (!validateArgsTypes(SourceDag->getArg(It->getValue()),
338 SourceDag->getArg(I)))
339 PrintFatalError(Rec->getLoc(),
340 "Input Operand '" + SourceDag->getArgNameStr(I) +
341 "' has a mismatched tied operand!\n");
343 It = DestOperands.find(SourceDag->getArgNameStr(I));
344 if (It == DestOperands.end())
345 PrintFatalError(Rec->getLoc(), "Operand " + SourceDag->getArgNameStr(I) +
346 " defined in Input Dag but not used in"
347 " Output Dag!\n");
348 // Input Dag operand types must match output Dag operand type.
349 if (!validateArgsTypes(DestDag->getArg(It->getValue()),
350 SourceDag->getArg(I)))
351 PrintFatalError(Rec->getLoc(), "Type mismatch between Input and "
352 "Output Dag operand '" +
353 SourceDag->getArgNameStr(I) + "'!");
354 SourceOperands[SourceDag->getArgNameStr(I)] = I;
358 /// Map operand names in the Dag to their index in both corresponding input and
359 /// output instructions. Validate that operands defined in the input are
360 /// used in the output pattern while populating the maps.
361 void CompressInstEmitter::createInstOperandMapping(
362 const Record *Rec, const DagInit *SourceDag, const DagInit *DestDag,
363 IndexedMap<OpData> &SourceOperandMap, IndexedMap<OpData> &DestOperandMap,
364 StringMap<unsigned> &SourceOperands, const CodeGenInstruction &DestInst) {
365 // TiedCount keeps track of the number of operands skipped in Inst
366 // operands list to get to the corresponding Dag operand.
367 unsigned TiedCount = 0;
368 LLVM_DEBUG(dbgs() << " Operand mapping:\n Source Dest\n");
369 for (unsigned I = 0, E = DestInst.Operands.size(); I != E; ++I) {
370 int TiedInstOpIdx = DestInst.Operands[I].getTiedRegister();
371 if (TiedInstOpIdx != -1) {
372 ++TiedCount;
373 DestOperandMap[I].Data = DestOperandMap[TiedInstOpIdx].Data;
374 DestOperandMap[I].Kind = DestOperandMap[TiedInstOpIdx].Kind;
375 if (DestOperandMap[I].Kind == OpData::Operand)
376 // No need to fill the SourceOperandMap here since it was mapped to
377 // destination operand 'TiedInstOpIdx' in a previous iteration.
378 LLVM_DEBUG(dbgs() << " " << DestOperandMap[I].Data.Operand
379 << " ====> " << I
380 << " Dest operand tied with operand '"
381 << TiedInstOpIdx << "'\n");
382 continue;
384 // Skip fixed immediates and registers, they were handled in
385 // addDagOperandMapping.
386 if (DestOperandMap[I].Kind != OpData::Operand)
387 continue;
389 unsigned DagArgIdx = I - TiedCount;
390 StringMap<unsigned>::iterator SourceOp =
391 SourceOperands.find(DestDag->getArgNameStr(DagArgIdx));
392 if (SourceOp == SourceOperands.end())
393 PrintFatalError(Rec->getLoc(),
394 "Output Dag operand '" +
395 DestDag->getArgNameStr(DagArgIdx) +
396 "' has no matching input Dag operand.");
398 assert(DestDag->getArgNameStr(DagArgIdx) ==
399 SourceDag->getArgNameStr(SourceOp->getValue()) &&
400 "Incorrect operand mapping detected!\n");
401 DestOperandMap[I].Data.Operand = SourceOp->getValue();
402 SourceOperandMap[SourceOp->getValue()].Data.Operand = I;
403 LLVM_DEBUG(dbgs() << " " << SourceOp->getValue() << " ====> " << I
404 << "\n");
408 /// Validates the CompressPattern and create operand mapping.
409 /// These are the checks to validate a CompressPat pattern declarations.
410 /// Error out with message under these conditions:
411 /// - Dag Input opcode is an expanded instruction and Dag Output opcode is a
412 /// compressed instruction.
413 /// - Operands in Dag Input must be all used in Dag Output.
414 /// Register Operand type in Dag Input Type must be contained in the
415 /// corresponding Source Instruction type.
416 /// - Register Operand type in Dag Input must be the same as in Dag Ouput.
417 /// - Register Operand type in Dag Output must be the same as the
418 /// corresponding Destination Inst type.
419 /// - Immediate Operand type in Dag Input must be the same as in Dag Ouput.
420 /// - Immediate Operand type in Dag Ouput must be the same as the corresponding
421 /// Destination Instruction type.
422 /// - Fixed register must be contained in the corresponding Source Instruction
423 /// type.
424 /// - Fixed register must be contained in the corresponding Destination
425 /// Instruction type.
426 /// Warning message printed under these conditions:
427 /// - Fixed immediate in Dag Input or Dag Ouput cannot be checked at this time
428 /// and generate warning.
429 /// - Immediate operand type in Dag Input differs from the corresponding Source
430 /// Instruction type and generate a warning.
431 void CompressInstEmitter::evaluateCompressPat(const Record *Rec) {
432 // Validate input Dag operands.
433 const DagInit *SourceDag = Rec->getValueAsDag("Input");
434 assert(SourceDag && "Missing 'Input' in compress pattern!");
435 LLVM_DEBUG(dbgs() << "Input: " << *SourceDag << "\n");
437 // Checking we are transforming from compressed to uncompressed instructions.
438 const Record *SourceOperator = SourceDag->getOperatorAsDef(Rec->getLoc());
439 CodeGenInstruction SourceInst(SourceOperator);
440 verifyDagOpCount(SourceInst, SourceDag, true);
442 // Validate output Dag operands.
443 const DagInit *DestDag = Rec->getValueAsDag("Output");
444 assert(DestDag && "Missing 'Output' in compress pattern!");
445 LLVM_DEBUG(dbgs() << "Output: " << *DestDag << "\n");
447 const Record *DestOperator = DestDag->getOperatorAsDef(Rec->getLoc());
448 CodeGenInstruction DestInst(DestOperator);
449 verifyDagOpCount(DestInst, DestDag, false);
451 if (SourceOperator->getValueAsInt("Size") <=
452 DestOperator->getValueAsInt("Size"))
453 PrintFatalError(
454 Rec->getLoc(),
455 "Compressed instruction '" + DestOperator->getName() +
456 "'is not strictly smaller than the uncompressed instruction '" +
457 SourceOperator->getName() + "' !");
459 // Fill the mapping from the source to destination instructions.
461 IndexedMap<OpData> SourceOperandMap;
462 SourceOperandMap.grow(SourceInst.Operands.size());
463 // Create a mapping between source Dag operands and source Inst operands.
464 addDagOperandMapping(Rec, SourceDag, SourceInst, SourceOperandMap,
465 /*IsSourceInst*/ true);
467 IndexedMap<OpData> DestOperandMap;
468 DestOperandMap.grow(DestInst.Operands.size());
469 // Create a mapping between destination Dag operands and destination Inst
470 // operands.
471 addDagOperandMapping(Rec, DestDag, DestInst, DestOperandMap,
472 /*IsSourceInst*/ false);
474 StringMap<unsigned> SourceOperands;
475 StringMap<unsigned> DestOperands;
476 createDagOperandMapping(Rec, SourceOperands, DestOperands, SourceDag, DestDag,
477 SourceOperandMap);
478 // Create operand mapping between the source and destination instructions.
479 createInstOperandMapping(Rec, SourceDag, DestDag, SourceOperandMap,
480 DestOperandMap, SourceOperands, DestInst);
482 // Get the target features for the CompressPat.
483 std::vector<const Record *> PatReqFeatures;
484 std::vector<const Record *> RF = Rec->getValueAsListOfDefs("Predicates");
485 copy_if(RF, std::back_inserter(PatReqFeatures), [](const Record *R) {
486 return R->getValueAsBit("AssemblerMatcherPredicate");
489 CompressPatterns.push_back(CompressPat(
490 SourceInst, DestInst, std::move(PatReqFeatures), SourceOperandMap,
491 DestOperandMap, Rec->getValueAsBit("isCompressOnly")));
494 static void
495 getReqFeatures(std::set<std::pair<bool, StringRef>> &FeaturesSet,
496 std::set<std::set<std::pair<bool, StringRef>>> &AnyOfFeatureSets,
497 ArrayRef<const Record *> ReqFeatures) {
498 for (const Record *R : ReqFeatures) {
499 const DagInit *D = R->getValueAsDag("AssemblerCondDag");
500 std::string CombineType = D->getOperator()->getAsString();
501 if (CombineType != "any_of" && CombineType != "all_of")
502 PrintFatalError(R->getLoc(), "Invalid AssemblerCondDag!");
503 if (D->getNumArgs() == 0)
504 PrintFatalError(R->getLoc(), "Invalid AssemblerCondDag!");
505 bool IsOr = CombineType == "any_of";
506 std::set<std::pair<bool, StringRef>> AnyOfSet;
508 for (auto *Arg : D->getArgs()) {
509 bool IsNot = false;
510 if (auto *NotArg = dyn_cast<DagInit>(Arg)) {
511 if (NotArg->getOperator()->getAsString() != "not" ||
512 NotArg->getNumArgs() != 1)
513 PrintFatalError(R->getLoc(), "Invalid AssemblerCondDag!");
514 Arg = NotArg->getArg(0);
515 IsNot = true;
517 if (!isa<DefInit>(Arg) ||
518 !cast<DefInit>(Arg)->getDef()->isSubClassOf("SubtargetFeature"))
519 PrintFatalError(R->getLoc(), "Invalid AssemblerCondDag!");
520 if (IsOr)
521 AnyOfSet.insert({IsNot, cast<DefInit>(Arg)->getDef()->getName()});
522 else
523 FeaturesSet.insert({IsNot, cast<DefInit>(Arg)->getDef()->getName()});
526 if (IsOr)
527 AnyOfFeatureSets.insert(std::move(AnyOfSet));
531 static unsigned getPredicates(DenseMap<const Record *, unsigned> &PredicateMap,
532 std::vector<const Record *> &Predicates,
533 const Record *Rec, StringRef Name) {
534 unsigned &Entry = PredicateMap[Rec];
535 if (Entry)
536 return Entry;
538 if (!Rec->isValueUnset(Name)) {
539 Predicates.push_back(Rec);
540 Entry = Predicates.size();
541 return Entry;
544 PrintFatalError(Rec->getLoc(), "No " + Name +
545 " predicate on this operand at all: '" +
546 Rec->getName() + "'");
547 return 0;
550 static void printPredicates(ArrayRef<const Record *> Predicates, StringRef Name,
551 raw_ostream &OS) {
552 for (unsigned I = 0; I < Predicates.size(); ++I) {
553 StringRef Pred = Predicates[I]->getValueAsString(Name);
554 OS << " case " << I + 1 << ": {\n"
555 << " // " << Predicates[I]->getName() << "\n"
556 << " " << Pred << "\n"
557 << " }\n";
561 static void mergeCondAndCode(raw_ostream &CombinedStream, StringRef CondStr,
562 StringRef CodeStr) {
563 // Remove first indentation and last '&&'.
564 CondStr = CondStr.drop_front(6).drop_back(4);
565 CombinedStream.indent(4) << "if (" << CondStr << ") {\n";
566 CombinedStream << CodeStr;
567 CombinedStream.indent(4) << " return true;\n";
568 CombinedStream.indent(4) << "} // if\n";
571 void CompressInstEmitter::emitCompressInstEmitter(raw_ostream &OS,
572 EmitterType EType) {
573 const Record *AsmWriter = Target.getAsmWriter();
574 if (!AsmWriter->getValueAsInt("PassSubtarget"))
575 PrintFatalError(AsmWriter->getLoc(),
576 "'PassSubtarget' is false. SubTargetInfo object is needed "
577 "for target features.\n");
579 StringRef TargetName = Target.getName();
581 // Sort entries in CompressPatterns to handle instructions that can have more
582 // than one candidate for compression\uncompression, e.g ADD can be
583 // transformed to a C_ADD or a C_MV. When emitting 'uncompress()' function the
584 // source and destination are flipped and the sort key needs to change
585 // accordingly.
586 llvm::stable_sort(CompressPatterns, [EType](const CompressPat &LHS,
587 const CompressPat &RHS) {
588 if (EType == EmitterType::Compress || EType == EmitterType::CheckCompress)
589 return (LHS.Source.TheDef->getName() < RHS.Source.TheDef->getName());
590 return (LHS.Dest.TheDef->getName() < RHS.Dest.TheDef->getName());
593 // A list of MCOperandPredicates for all operands in use, and the reverse map.
594 std::vector<const Record *> MCOpPredicates;
595 DenseMap<const Record *, unsigned> MCOpPredicateMap;
596 // A list of ImmLeaf Predicates for all operands in use, and the reverse map.
597 std::vector<const Record *> ImmLeafPredicates;
598 DenseMap<const Record *, unsigned> ImmLeafPredicateMap;
600 std::string F;
601 std::string FH;
602 raw_string_ostream Func(F);
603 raw_string_ostream FuncH(FH);
605 if (EType == EmitterType::Compress)
606 OS << "\n#ifdef GEN_COMPRESS_INSTR\n"
607 << "#undef GEN_COMPRESS_INSTR\n\n";
608 else if (EType == EmitterType::Uncompress)
609 OS << "\n#ifdef GEN_UNCOMPRESS_INSTR\n"
610 << "#undef GEN_UNCOMPRESS_INSTR\n\n";
611 else if (EType == EmitterType::CheckCompress)
612 OS << "\n#ifdef GEN_CHECK_COMPRESS_INSTR\n"
613 << "#undef GEN_CHECK_COMPRESS_INSTR\n\n";
615 if (EType == EmitterType::Compress) {
616 FuncH << "static bool compressInst(MCInst &OutInst,\n";
617 FuncH.indent(25) << "const MCInst &MI,\n";
618 FuncH.indent(25) << "const MCSubtargetInfo &STI) {\n";
619 } else if (EType == EmitterType::Uncompress) {
620 FuncH << "static bool uncompressInst(MCInst &OutInst,\n";
621 FuncH.indent(27) << "const MCInst &MI,\n";
622 FuncH.indent(27) << "const MCSubtargetInfo &STI) {\n";
623 } else if (EType == EmitterType::CheckCompress) {
624 FuncH << "static bool isCompressibleInst(const MachineInstr &MI,\n";
625 FuncH.indent(31) << "const " << TargetName << "Subtarget &STI) {\n";
628 if (CompressPatterns.empty()) {
629 OS << FH;
630 OS.indent(2) << "return false;\n}\n";
631 if (EType == EmitterType::Compress)
632 OS << "\n#endif //GEN_COMPRESS_INSTR\n";
633 else if (EType == EmitterType::Uncompress)
634 OS << "\n#endif //GEN_UNCOMPRESS_INSTR\n\n";
635 else if (EType == EmitterType::CheckCompress)
636 OS << "\n#endif //GEN_CHECK_COMPRESS_INSTR\n\n";
637 return;
640 std::string CaseString;
641 raw_string_ostream CaseStream(CaseString);
642 StringRef PrevOp;
643 StringRef CurOp;
644 CaseStream << " switch (MI.getOpcode()) {\n";
645 CaseStream << " default: return false;\n";
647 bool CompressOrCheck =
648 EType == EmitterType::Compress || EType == EmitterType::CheckCompress;
649 bool CompressOrUncompress =
650 EType == EmitterType::Compress || EType == EmitterType::Uncompress;
651 std::string ValidatorName =
652 CompressOrUncompress
653 ? (TargetName + "ValidateMCOperandFor" +
654 (EType == EmitterType::Compress ? "Compress" : "Uncompress"))
655 .str()
656 : "";
658 for (auto &CompressPat : CompressPatterns) {
659 if (EType == EmitterType::Uncompress && CompressPat.IsCompressOnly)
660 continue;
662 std::string CondString;
663 std::string CodeString;
664 raw_string_ostream CondStream(CondString);
665 raw_string_ostream CodeStream(CodeString);
666 CodeGenInstruction &Source =
667 CompressOrCheck ? CompressPat.Source : CompressPat.Dest;
668 CodeGenInstruction &Dest =
669 CompressOrCheck ? CompressPat.Dest : CompressPat.Source;
670 IndexedMap<OpData> SourceOperandMap = CompressOrCheck
671 ? CompressPat.SourceOperandMap
672 : CompressPat.DestOperandMap;
673 IndexedMap<OpData> &DestOperandMap = CompressOrCheck
674 ? CompressPat.DestOperandMap
675 : CompressPat.SourceOperandMap;
677 CurOp = Source.TheDef->getName();
678 // Check current and previous opcode to decide to continue or end a case.
679 if (CurOp != PrevOp) {
680 if (!PrevOp.empty())
681 CaseStream.indent(6) << "break;\n } // case " + PrevOp + "\n";
682 CaseStream.indent(4) << "case " + TargetName + "::" + CurOp + ": {\n";
685 std::set<std::pair<bool, StringRef>> FeaturesSet;
686 std::set<std::set<std::pair<bool, StringRef>>> AnyOfFeatureSets;
687 // Add CompressPat required features.
688 getReqFeatures(FeaturesSet, AnyOfFeatureSets, CompressPat.PatReqFeatures);
690 // Add Dest instruction required features.
691 std::vector<const Record *> ReqFeatures;
692 std::vector<const Record *> RF =
693 Dest.TheDef->getValueAsListOfDefs("Predicates");
694 copy_if(RF, std::back_inserter(ReqFeatures), [](const Record *R) {
695 return R->getValueAsBit("AssemblerMatcherPredicate");
697 getReqFeatures(FeaturesSet, AnyOfFeatureSets, ReqFeatures);
699 // Emit checks for all required features.
700 for (auto &Op : FeaturesSet) {
701 StringRef Not = Op.first ? "!" : "";
702 CondStream.indent(6) << Not << "STI.getFeatureBits()[" << TargetName
703 << "::" << Op.second << "]"
704 << " &&\n";
707 // Emit checks for all required feature groups.
708 for (auto &Set : AnyOfFeatureSets) {
709 CondStream.indent(6) << "(";
710 for (auto &Op : Set) {
711 bool IsLast = &Op == &*Set.rbegin();
712 StringRef Not = Op.first ? "!" : "";
713 CondStream << Not << "STI.getFeatureBits()[" << TargetName
714 << "::" << Op.second << "]";
715 if (!IsLast)
716 CondStream << " || ";
718 CondStream << ") &&\n";
721 // Start Source Inst operands validation.
722 unsigned OpNo = 0;
723 for (OpNo = 0; OpNo < Source.Operands.size(); ++OpNo) {
724 if (SourceOperandMap[OpNo].TiedOpIdx != -1) {
725 if (Source.Operands[OpNo].Rec->isSubClassOf("RegisterClass"))
726 CondStream.indent(6)
727 << "(MI.getOperand(" << OpNo << ").isReg()) && (MI.getOperand("
728 << SourceOperandMap[OpNo].TiedOpIdx << ").isReg()) &&\n"
729 << " (MI.getOperand(" << OpNo
730 << ").getReg() == MI.getOperand("
731 << SourceOperandMap[OpNo].TiedOpIdx << ").getReg()) &&\n";
732 else
733 PrintFatalError("Unexpected tied operand types!\n");
735 // Check for fixed immediates\registers in the source instruction.
736 switch (SourceOperandMap[OpNo].Kind) {
737 case OpData::Operand:
738 // We don't need to do anything for source instruction operand checks.
739 break;
740 case OpData::Imm:
741 CondStream.indent(6)
742 << "(MI.getOperand(" << OpNo << ").isImm()) &&\n"
743 << " (MI.getOperand(" << OpNo
744 << ").getImm() == " << SourceOperandMap[OpNo].Data.Imm << ") &&\n";
745 break;
746 case OpData::Reg: {
747 const Record *Reg = SourceOperandMap[OpNo].Data.Reg;
748 CondStream.indent(6)
749 << "(MI.getOperand(" << OpNo << ").isReg()) &&\n"
750 << " (MI.getOperand(" << OpNo << ").getReg() == " << TargetName
751 << "::" << Reg->getName() << ") &&\n";
752 break;
756 CodeStream.indent(6) << "// " << Dest.AsmString << "\n";
757 if (CompressOrUncompress)
758 CodeStream.indent(6) << "OutInst.setOpcode(" << TargetName
759 << "::" << Dest.TheDef->getName() << ");\n";
760 OpNo = 0;
761 for (const auto &DestOperand : Dest.Operands) {
762 CodeStream.indent(6) << "// Operand: " << DestOperand.Name << "\n";
763 switch (DestOperandMap[OpNo].Kind) {
764 case OpData::Operand: {
765 unsigned OpIdx = DestOperandMap[OpNo].Data.Operand;
766 // Check that the operand in the Source instruction fits
767 // the type for the Dest instruction.
768 if (DestOperand.Rec->isSubClassOf("RegisterClass") ||
769 DestOperand.Rec->isSubClassOf("RegisterOperand")) {
770 auto *ClassRec = DestOperand.Rec->isSubClassOf("RegisterClass")
771 ? DestOperand.Rec
772 : DestOperand.Rec->getValueAsDef("RegClass");
773 // This is a register operand. Check the register class.
774 // Don't check register class if this is a tied operand, it was done
775 // for the operand its tied to.
776 if (DestOperand.getTiedRegister() == -1)
777 CondStream.indent(6)
778 << "(MI.getOperand(" << OpIdx << ").isReg()) &&\n"
779 << " (" << TargetName << "MCRegisterClasses[" << TargetName
780 << "::" << ClassRec->getName()
781 << "RegClassID].contains(MI.getOperand(" << OpIdx
782 << ").getReg())) &&\n";
784 if (CompressOrUncompress)
785 CodeStream.indent(6)
786 << "OutInst.addOperand(MI.getOperand(" << OpIdx << "));\n";
787 } else {
788 // Handling immediate operands.
789 if (CompressOrUncompress) {
790 unsigned Entry =
791 getPredicates(MCOpPredicateMap, MCOpPredicates, DestOperand.Rec,
792 "MCOperandPredicate");
793 CondStream.indent(6)
794 << ValidatorName << "("
795 << "MI.getOperand(" << OpIdx << "), STI, " << Entry << ") &&\n";
796 } else {
797 unsigned Entry =
798 getPredicates(ImmLeafPredicateMap, ImmLeafPredicates,
799 DestOperand.Rec, "ImmediateCode");
800 CondStream.indent(6)
801 << "MI.getOperand(" << OpIdx << ").isImm() &&\n";
802 CondStream.indent(6) << TargetName << "ValidateMachineOperand("
803 << "MI.getOperand(" << OpIdx << "), &STI, "
804 << Entry << ") &&\n";
806 if (CompressOrUncompress)
807 CodeStream.indent(6)
808 << "OutInst.addOperand(MI.getOperand(" << OpIdx << "));\n";
810 break;
812 case OpData::Imm: {
813 if (CompressOrUncompress) {
814 unsigned Entry = getPredicates(MCOpPredicateMap, MCOpPredicates,
815 DestOperand.Rec, "MCOperandPredicate");
816 CondStream.indent(6)
817 << ValidatorName << "("
818 << "MCOperand::createImm(" << DestOperandMap[OpNo].Data.Imm
819 << "), STI, " << Entry << ") &&\n";
820 } else {
821 unsigned Entry = getPredicates(ImmLeafPredicateMap, ImmLeafPredicates,
822 DestOperand.Rec, "ImmediateCode");
823 CondStream.indent(6)
824 << TargetName
825 << "ValidateMachineOperand(MachineOperand::CreateImm("
826 << DestOperandMap[OpNo].Data.Imm << "), &STI, " << Entry
827 << ") &&\n";
829 if (CompressOrUncompress)
830 CodeStream.indent(6) << "OutInst.addOperand(MCOperand::createImm("
831 << DestOperandMap[OpNo].Data.Imm << "));\n";
832 } break;
833 case OpData::Reg: {
834 if (CompressOrUncompress) {
835 // Fixed register has been validated at pattern validation time.
836 const Record *Reg = DestOperandMap[OpNo].Data.Reg;
837 CodeStream.indent(6)
838 << "OutInst.addOperand(MCOperand::createReg(" << TargetName
839 << "::" << Reg->getName() << "));\n";
841 } break;
843 ++OpNo;
845 if (CompressOrUncompress)
846 CodeStream.indent(6) << "OutInst.setLoc(MI.getLoc());\n";
847 mergeCondAndCode(CaseStream, CondString, CodeString);
848 PrevOp = CurOp;
850 Func << CaseString << "\n";
851 // Close brace for the last case.
852 Func.indent(4) << "} // case " << CurOp << "\n";
853 Func.indent(2) << "} // switch\n";
854 Func.indent(2) << "return false;\n}\n";
856 if (!MCOpPredicates.empty()) {
857 OS << "static bool " << ValidatorName << "(const MCOperand &MCOp,\n"
858 << " const MCSubtargetInfo &STI,\n"
859 << " unsigned PredicateIndex) {\n"
860 << " switch (PredicateIndex) {\n"
861 << " default:\n"
862 << " llvm_unreachable(\"Unknown MCOperandPredicate kind\");\n"
863 << " break;\n";
865 printPredicates(MCOpPredicates, "MCOperandPredicate", OS);
867 OS << " }\n"
868 << "}\n\n";
871 if (!ImmLeafPredicates.empty()) {
872 OS << "static bool " << TargetName
873 << "ValidateMachineOperand(const MachineOperand &MO,\n"
874 << " const " << TargetName << "Subtarget *Subtarget,\n"
875 << " unsigned PredicateIndex) {\n"
876 << " int64_t Imm = MO.getImm();\n"
877 << " switch (PredicateIndex) {\n"
878 << " default:\n"
879 << " llvm_unreachable(\"Unknown ImmLeaf Predicate kind\");\n"
880 << " break;\n";
882 printPredicates(ImmLeafPredicates, "ImmediateCode", OS);
884 OS << " }\n"
885 << "}\n\n";
888 OS << FH;
889 OS << F;
891 if (EType == EmitterType::Compress)
892 OS << "\n#endif //GEN_COMPRESS_INSTR\n";
893 else if (EType == EmitterType::Uncompress)
894 OS << "\n#endif //GEN_UNCOMPRESS_INSTR\n\n";
895 else if (EType == EmitterType::CheckCompress)
896 OS << "\n#endif //GEN_CHECK_COMPRESS_INSTR\n\n";
899 void CompressInstEmitter::run(raw_ostream &OS) {
900 // Process the CompressPat definitions, validating them as we do so.
901 for (const Record *Pat : Records.getAllDerivedDefinitions("CompressPat"))
902 evaluateCompressPat(Pat);
904 // Emit file header.
905 emitSourceFileHeader("Compress instruction Source Fragment", OS, Records);
906 // Generate compressInst() function.
907 emitCompressInstEmitter(OS, EmitterType::Compress);
908 // Generate uncompressInst() function.
909 emitCompressInstEmitter(OS, EmitterType::Uncompress);
910 // Generate isCompressibleInst() function.
911 emitCompressInstEmitter(OS, EmitterType::CheckCompress);
914 static TableGen::Emitter::OptClass<CompressInstEmitter>
915 X("gen-compress-inst-emitter", "Generate compressed instructions.");