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