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