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