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