1 //===-------- CompressInstEmitter.cpp - Generator for Compression ---------===//
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
7 // CompressInstEmitter implements a tablegen-driven CompressPat based
8 // Instruction Compression mechanism.
10 //===----------------------------------------------------------------------===//
12 // CompressInstEmitter implements a tablegen-driven CompressPat Instruction
13 // Compression mechanism for generating compressed instructions from the
14 // expanded instruction form.
16 // This tablegen backend processes CompressPat declarations in a
17 // td file and generates all the required checks to validate the pattern
18 // declarations; validate the input and output operands to generate the correct
19 // compressed instructions. The checks include validating different types of
20 // operands; register operands, immediate operands, fixed register and fixed
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.
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;
38 // let Predicates = [HasStdExtC] in {
39 // def : CompressPat<(ADD GPRNoX0:$rs1, GPRNoX0:$rs1, GPRNoX0:$rs2),
40 // (C_ADD GPRNoX0:$rs1, GPRNoX0:$rs2)>;
43 // The <TargetName>GenCompressInstEmitter.inc is an auto-generated header
44 // file which exports two functions for compressing/uncompressing MCInst
45 // instructions, plus some helper functions:
47 // bool compressInst(MCInst &OutInst, const MCInst &MI,
48 // const MCSubtargetInfo &STI);
50 // bool uncompressInst(MCInst &OutInst, const MCInst &MI,
51 // const MCSubtargetInfo &STI);
53 // In addition, it exports a function for checking whether
54 // an instruction is compressable:
56 // bool isCompressibleInst(const MachineInstr& MI,
57 // const <TargetName>Subtarget &STI);
59 // The clients that include this auto-generated header file and
60 // invoke these functions can compress an instruction before emitting
61 // it in the target-specific ASM or ELF streamer or can uncompress
62 // an instruction before printing it when the expanded instruction
63 // format aliases is favored.
65 //===----------------------------------------------------------------------===//
67 #include "Common/CodeGenInstruction.h"
68 #include "Common/CodeGenRegisters.h"
69 #include "Common/CodeGenTarget.h"
70 #include "llvm/ADT/IndexedMap.h"
71 #include "llvm/ADT/SmallVector.h"
72 #include "llvm/ADT/StringMap.h"
73 #include "llvm/Support/Debug.h"
74 #include "llvm/Support/ErrorHandling.h"
75 #include "llvm/TableGen/Error.h"
76 #include "llvm/TableGen/Record.h"
77 #include "llvm/TableGen/TableGenBackend.h"
82 #define DEBUG_TYPE "compress-inst-emitter"
85 class CompressInstEmitter
{
87 enum MapKind
{ Operand
, Imm
, Reg
};
90 // Operand number mapped to.
92 // Integer immediate value.
97 // Tied operand index within the instruction.
101 // The source instruction definition.
102 CodeGenInstruction Source
;
103 // The destination instruction to transform to.
104 CodeGenInstruction Dest
;
105 // Required target features to enable pattern.
106 std::vector
<const Record
*> PatReqFeatures
;
107 // Maps operands in the Source Instruction to
108 // the corresponding Dest instruction operand.
109 IndexedMap
<OpData
> SourceOperandMap
;
110 // Maps operands in the Dest Instruction
111 // to the corresponding Source instruction operand.
112 IndexedMap
<OpData
> DestOperandMap
;
115 CompressPat(const CodeGenInstruction
&S
, const CodeGenInstruction
&D
,
116 std::vector
<const Record
*> RF
, IndexedMap
<OpData
> &SourceMap
,
117 IndexedMap
<OpData
> &DestMap
, bool IsCompressOnly
)
118 : Source(S
), Dest(D
), PatReqFeatures(RF
), SourceOperandMap(SourceMap
),
119 DestOperandMap(DestMap
), IsCompressOnly(IsCompressOnly
) {}
121 enum EmitterType
{ Compress
, Uncompress
, CheckCompress
};
122 const RecordKeeper
&Records
;
123 const CodeGenTarget Target
;
124 SmallVector
<CompressPat
, 4> CompressPatterns
;
126 void addDagOperandMapping(const Record
*Rec
, const DagInit
*Dag
,
127 const CodeGenInstruction
&Inst
,
128 IndexedMap
<OpData
> &OperandMap
, bool IsSourceInst
);
129 void evaluateCompressPat(const Record
*Compress
);
130 void emitCompressInstEmitter(raw_ostream
&OS
, EmitterType EType
);
131 bool validateTypes(const Record
*DagOpType
, const Record
*InstOpType
,
133 bool validateRegister(const Record
*Reg
, const Record
*RegClass
);
134 void createDagOperandMapping(const Record
*Rec
,
135 StringMap
<unsigned> &SourceOperands
,
136 StringMap
<unsigned> &DestOperands
,
137 const DagInit
*SourceDag
, const DagInit
*DestDag
,
138 IndexedMap
<OpData
> &SourceOperandMap
);
140 void createInstOperandMapping(const Record
*Rec
, const DagInit
*SourceDag
,
141 const DagInit
*DestDag
,
142 IndexedMap
<OpData
> &SourceOperandMap
,
143 IndexedMap
<OpData
> &DestOperandMap
,
144 StringMap
<unsigned> &SourceOperands
,
145 const CodeGenInstruction
&DestInst
);
148 CompressInstEmitter(const RecordKeeper
&R
) : Records(R
), Target(R
) {}
150 void run(raw_ostream
&OS
);
152 } // End anonymous namespace.
154 bool CompressInstEmitter::validateRegister(const Record
*Reg
,
155 const Record
*RegClass
) {
156 assert(Reg
->isSubClassOf("Register") && "Reg record should be a Register");
157 assert(RegClass
->isSubClassOf("RegisterClass") &&
158 "RegClass record should be a RegisterClass");
159 const CodeGenRegisterClass
&RC
= Target
.getRegisterClass(RegClass
);
160 const CodeGenRegister
*R
= Target
.getRegisterByName(Reg
->getName().lower());
161 assert(R
!= nullptr && "Register not defined!!");
162 return RC
.contains(R
);
165 bool CompressInstEmitter::validateTypes(const Record
*DagOpType
,
166 const Record
*InstOpType
,
168 if (DagOpType
== InstOpType
)
170 // Only source instruction operands are allowed to not match Input Dag
175 if (DagOpType
->isSubClassOf("RegisterClass") &&
176 InstOpType
->isSubClassOf("RegisterClass")) {
177 const CodeGenRegisterClass
&RC
= Target
.getRegisterClass(InstOpType
);
178 const CodeGenRegisterClass
&SubRC
= Target
.getRegisterClass(DagOpType
);
179 return RC
.hasSubClass(&SubRC
);
182 // At this point either or both types are not registers, reject the pattern.
183 if (DagOpType
->isSubClassOf("RegisterClass") ||
184 InstOpType
->isSubClassOf("RegisterClass"))
187 // Let further validation happen when compress()/uncompress() functions are
189 LLVM_DEBUG(dbgs() << (IsSourceInst
? "Input" : "Output")
190 << " Dag Operand Type: '" << DagOpType
->getName()
192 << "Instruction Operand Type: '" << InstOpType
->getName()
193 << "' can't be checked at pattern validation time!\n");
197 /// The patterns in the Dag contain different types of operands:
198 /// Register operands, e.g.: GPRC:$rs1; Fixed registers, e.g: X1; Immediate
199 /// operands, e.g.: simm6:$imm; Fixed immediate operands, e.g.: 0. This function
200 /// maps Dag operands to its corresponding instruction operands. For register
201 /// operands and fixed registers it expects the Dag operand type to be contained
202 /// in the instantiated instruction operand type. For immediate operands and
203 /// immediates no validation checks are enforced at pattern validation time.
204 void CompressInstEmitter::addDagOperandMapping(const Record
*Rec
,
206 const CodeGenInstruction
&Inst
,
207 IndexedMap
<OpData
> &OperandMap
,
209 // TiedCount keeps track of the number of operands skipped in Inst
210 // operands list to get to the corresponding Dag operand. This is
211 // necessary because the number of operands in Inst might be greater
212 // than number of operands in the Dag due to how tied operands
214 unsigned TiedCount
= 0;
215 for (unsigned I
= 0, E
= Inst
.Operands
.size(); I
!= E
; ++I
) {
216 int TiedOpIdx
= Inst
.Operands
[I
].getTiedRegister();
217 if (-1 != TiedOpIdx
) {
218 // Set the entry in OperandMap for the tied operand we're skipping.
219 OperandMap
[I
].Kind
= OperandMap
[TiedOpIdx
].Kind
;
220 OperandMap
[I
].Data
= OperandMap
[TiedOpIdx
].Data
;
224 if (const DefInit
*DI
= dyn_cast
<DefInit
>(Dag
->getArg(I
- TiedCount
))) {
225 if (DI
->getDef()->isSubClassOf("Register")) {
226 // Check if the fixed register belongs to the Register class.
227 if (!validateRegister(DI
->getDef(), Inst
.Operands
[I
].Rec
))
228 PrintFatalError(Rec
->getLoc(),
229 "Error in Dag '" + Dag
->getAsString() +
230 "'Register: '" + DI
->getDef()->getName() +
231 "' is not in register class '" +
232 Inst
.Operands
[I
].Rec
->getName() + "'");
233 OperandMap
[I
].Kind
= OpData::Reg
;
234 OperandMap
[I
].Data
.Reg
= DI
->getDef();
237 // Validate that Dag operand type matches the type defined in the
238 // corresponding instruction. Operands in the input Dag pattern are
239 // allowed to be a subclass of the type specified in corresponding
240 // instruction operand instead of being an exact match.
241 if (!validateTypes(DI
->getDef(), Inst
.Operands
[I
].Rec
, IsSourceInst
))
242 PrintFatalError(Rec
->getLoc(),
243 "Error in Dag '" + Dag
->getAsString() + "'. Operand '" +
244 Dag
->getArgNameStr(I
- TiedCount
) + "' has type '" +
245 DI
->getDef()->getName() +
246 "' which does not match the type '" +
247 Inst
.Operands
[I
].Rec
->getName() +
248 "' in the corresponding instruction operand!");
250 OperandMap
[I
].Kind
= OpData::Operand
;
251 } else if (const IntInit
*II
=
252 dyn_cast
<IntInit
>(Dag
->getArg(I
- TiedCount
))) {
253 // Validate that corresponding instruction operand expects an immediate.
254 if (Inst
.Operands
[I
].Rec
->isSubClassOf("RegisterClass"))
257 "Error in Dag '" + Dag
->getAsString() + "' Found immediate: '" +
259 "' but corresponding instruction operand expected a register!");
260 // No pattern validation check possible for values of fixed immediate.
261 OperandMap
[I
].Kind
= OpData::Imm
;
262 OperandMap
[I
].Data
.Imm
= II
->getValue();
264 dbgs() << " Found immediate '" << II
->getValue() << "' at "
265 << (IsSourceInst
? "input " : "output ")
266 << "Dag. No validation time check possible for values of "
267 "fixed immediate.\n");
269 llvm_unreachable("Unhandled CompressPat argument type!");
273 // Verify the Dag operand count is enough to build an instruction.
274 static bool verifyDagOpCount(const CodeGenInstruction
&Inst
, const DagInit
*Dag
,
276 if (Dag
->getNumArgs() == Inst
.Operands
.size())
278 // Source instructions are non compressed instructions and don't have tied
281 PrintFatalError(Inst
.TheDef
->getLoc(),
282 "Input operands for Inst '" + Inst
.TheDef
->getName() +
283 "' and input Dag operand count mismatch");
284 // The Dag can't have more arguments than the Instruction.
285 if (Dag
->getNumArgs() > Inst
.Operands
.size())
286 PrintFatalError(Inst
.TheDef
->getLoc(),
287 "Inst '" + Inst
.TheDef
->getName() +
288 "' and Dag operand count mismatch");
290 // The Instruction might have tied operands so the Dag might have
291 // a fewer operand count.
292 unsigned RealCount
= Inst
.Operands
.size();
293 for (const auto &Operand
: Inst
.Operands
)
294 if (Operand
.getTiedRegister() != -1)
297 if (Dag
->getNumArgs() != RealCount
)
298 PrintFatalError(Inst
.TheDef
->getLoc(),
299 "Inst '" + Inst
.TheDef
->getName() +
300 "' and Dag operand count mismatch");
304 static bool validateArgsTypes(const Init
*Arg1
, const Init
*Arg2
) {
305 return cast
<DefInit
>(Arg1
)->getDef() == cast
<DefInit
>(Arg2
)->getDef();
308 // Creates a mapping between the operand name in the Dag (e.g. $rs1) and
309 // its index in the list of Dag operands and checks that operands with the same
310 // name have the same types. For example in 'C_ADD $rs1, $rs2' we generate the
311 // mapping $rs1 --> 0, $rs2 ---> 1. If the operand appears twice in the (tied)
312 // same Dag we use the last occurrence for indexing.
313 void CompressInstEmitter::createDagOperandMapping(
314 const Record
*Rec
, StringMap
<unsigned> &SourceOperands
,
315 StringMap
<unsigned> &DestOperands
, const DagInit
*SourceDag
,
316 const DagInit
*DestDag
, IndexedMap
<OpData
> &SourceOperandMap
) {
317 for (unsigned I
= 0; I
< DestDag
->getNumArgs(); ++I
) {
318 // Skip fixed immediates and registers, they were handled in
319 // addDagOperandMapping.
320 if ("" == DestDag
->getArgNameStr(I
))
322 DestOperands
[DestDag
->getArgNameStr(I
)] = I
;
325 for (unsigned I
= 0; I
< SourceDag
->getNumArgs(); ++I
) {
326 // Skip fixed immediates and registers, they were handled in
327 // addDagOperandMapping.
328 if ("" == SourceDag
->getArgNameStr(I
))
331 StringMap
<unsigned>::iterator It
=
332 SourceOperands
.find(SourceDag
->getArgNameStr(I
));
333 if (It
!= SourceOperands
.end()) {
334 // Operand sharing the same name in the Dag should be mapped as tied.
335 SourceOperandMap
[I
].TiedOpIdx
= It
->getValue();
336 if (!validateArgsTypes(SourceDag
->getArg(It
->getValue()),
337 SourceDag
->getArg(I
)))
338 PrintFatalError(Rec
->getLoc(),
339 "Input Operand '" + SourceDag
->getArgNameStr(I
) +
340 "' has a mismatched tied operand!\n");
342 It
= DestOperands
.find(SourceDag
->getArgNameStr(I
));
343 if (It
== DestOperands
.end())
344 PrintFatalError(Rec
->getLoc(), "Operand " + SourceDag
->getArgNameStr(I
) +
345 " defined in Input Dag but not used in"
347 // Input Dag operand types must match output Dag operand type.
348 if (!validateArgsTypes(DestDag
->getArg(It
->getValue()),
349 SourceDag
->getArg(I
)))
350 PrintFatalError(Rec
->getLoc(), "Type mismatch between Input and "
351 "Output Dag operand '" +
352 SourceDag
->getArgNameStr(I
) + "'!");
353 SourceOperands
[SourceDag
->getArgNameStr(I
)] = I
;
357 /// Map operand names in the Dag to their index in both corresponding input and
358 /// output instructions. Validate that operands defined in the input are
359 /// used in the output pattern while populating the maps.
360 void CompressInstEmitter::createInstOperandMapping(
361 const Record
*Rec
, const DagInit
*SourceDag
, const DagInit
*DestDag
,
362 IndexedMap
<OpData
> &SourceOperandMap
, IndexedMap
<OpData
> &DestOperandMap
,
363 StringMap
<unsigned> &SourceOperands
, const CodeGenInstruction
&DestInst
) {
364 // TiedCount keeps track of the number of operands skipped in Inst
365 // operands list to get to the corresponding Dag operand.
366 unsigned TiedCount
= 0;
367 LLVM_DEBUG(dbgs() << " Operand mapping:\n Source Dest\n");
368 for (unsigned I
= 0, E
= DestInst
.Operands
.size(); I
!= E
; ++I
) {
369 int TiedInstOpIdx
= DestInst
.Operands
[I
].getTiedRegister();
370 if (TiedInstOpIdx
!= -1) {
372 DestOperandMap
[I
].Data
= DestOperandMap
[TiedInstOpIdx
].Data
;
373 DestOperandMap
[I
].Kind
= DestOperandMap
[TiedInstOpIdx
].Kind
;
374 if (DestOperandMap
[I
].Kind
== OpData::Operand
)
375 // No need to fill the SourceOperandMap here since it was mapped to
376 // destination operand 'TiedInstOpIdx' in a previous iteration.
377 LLVM_DEBUG(dbgs() << " " << DestOperandMap
[I
].Data
.Operand
379 << " Dest operand tied with operand '"
380 << TiedInstOpIdx
<< "'\n");
383 // Skip fixed immediates and registers, they were handled in
384 // addDagOperandMapping.
385 if (DestOperandMap
[I
].Kind
!= OpData::Operand
)
388 unsigned DagArgIdx
= I
- TiedCount
;
389 StringMap
<unsigned>::iterator SourceOp
=
390 SourceOperands
.find(DestDag
->getArgNameStr(DagArgIdx
));
391 if (SourceOp
== SourceOperands
.end())
392 PrintFatalError(Rec
->getLoc(),
393 "Output Dag operand '" +
394 DestDag
->getArgNameStr(DagArgIdx
) +
395 "' has no matching input Dag operand.");
397 assert(DestDag
->getArgNameStr(DagArgIdx
) ==
398 SourceDag
->getArgNameStr(SourceOp
->getValue()) &&
399 "Incorrect operand mapping detected!\n");
400 DestOperandMap
[I
].Data
.Operand
= SourceOp
->getValue();
401 SourceOperandMap
[SourceOp
->getValue()].Data
.Operand
= I
;
402 LLVM_DEBUG(dbgs() << " " << SourceOp
->getValue() << " ====> " << I
407 /// Validates the CompressPattern and create operand mapping.
408 /// These are the checks to validate a CompressPat pattern declarations.
409 /// Error out with message under these conditions:
410 /// - Dag Input opcode is an expanded instruction and Dag Output opcode is a
411 /// compressed instruction.
412 /// - Operands in Dag Input must be all used in Dag Output.
413 /// Register Operand type in Dag Input Type must be contained in the
414 /// corresponding Source Instruction type.
415 /// - Register Operand type in Dag Input must be the same as in Dag Ouput.
416 /// - Register Operand type in Dag Output must be the same as the
417 /// corresponding Destination Inst type.
418 /// - Immediate Operand type in Dag Input must be the same as in Dag Ouput.
419 /// - Immediate Operand type in Dag Ouput must be the same as the corresponding
420 /// Destination Instruction type.
421 /// - Fixed register must be contained in the corresponding Source Instruction
423 /// - Fixed register must be contained in the corresponding Destination
424 /// Instruction type.
425 /// Warning message printed under these conditions:
426 /// - Fixed immediate in Dag Input or Dag Ouput cannot be checked at this time
427 /// and generate warning.
428 /// - Immediate operand type in Dag Input differs from the corresponding Source
429 /// Instruction type and generate a warning.
430 void CompressInstEmitter::evaluateCompressPat(const Record
*Rec
) {
431 // Validate input Dag operands.
432 const DagInit
*SourceDag
= Rec
->getValueAsDag("Input");
433 assert(SourceDag
&& "Missing 'Input' in compress pattern!");
434 LLVM_DEBUG(dbgs() << "Input: " << *SourceDag
<< "\n");
436 // Checking we are transforming from compressed to uncompressed instructions.
437 const Record
*SourceOperator
= SourceDag
->getOperatorAsDef(Rec
->getLoc());
438 CodeGenInstruction
SourceInst(SourceOperator
);
439 verifyDagOpCount(SourceInst
, SourceDag
, true);
441 // Validate output Dag operands.
442 const DagInit
*DestDag
= Rec
->getValueAsDag("Output");
443 assert(DestDag
&& "Missing 'Output' in compress pattern!");
444 LLVM_DEBUG(dbgs() << "Output: " << *DestDag
<< "\n");
446 const Record
*DestOperator
= DestDag
->getOperatorAsDef(Rec
->getLoc());
447 CodeGenInstruction
DestInst(DestOperator
);
448 verifyDagOpCount(DestInst
, DestDag
, false);
450 if (SourceOperator
->getValueAsInt("Size") <=
451 DestOperator
->getValueAsInt("Size"))
454 "Compressed instruction '" + DestOperator
->getName() +
455 "'is not strictly smaller than the uncompressed instruction '" +
456 SourceOperator
->getName() + "' !");
458 // Fill the mapping from the source to destination instructions.
460 IndexedMap
<OpData
> SourceOperandMap
;
461 SourceOperandMap
.grow(SourceInst
.Operands
.size());
462 // Create a mapping between source Dag operands and source Inst operands.
463 addDagOperandMapping(Rec
, SourceDag
, SourceInst
, SourceOperandMap
,
464 /*IsSourceInst*/ true);
466 IndexedMap
<OpData
> DestOperandMap
;
467 DestOperandMap
.grow(DestInst
.Operands
.size());
468 // Create a mapping between destination Dag operands and destination Inst
470 addDagOperandMapping(Rec
, DestDag
, DestInst
, DestOperandMap
,
471 /*IsSourceInst*/ false);
473 StringMap
<unsigned> SourceOperands
;
474 StringMap
<unsigned> DestOperands
;
475 createDagOperandMapping(Rec
, SourceOperands
, DestOperands
, SourceDag
, DestDag
,
477 // Create operand mapping between the source and destination instructions.
478 createInstOperandMapping(Rec
, SourceDag
, DestDag
, SourceOperandMap
,
479 DestOperandMap
, SourceOperands
, DestInst
);
481 // Get the target features for the CompressPat.
482 std::vector
<const Record
*> PatReqFeatures
;
483 std::vector
<const Record
*> RF
= Rec
->getValueAsListOfDefs("Predicates");
484 copy_if(RF
, std::back_inserter(PatReqFeatures
), [](const Record
*R
) {
485 return R
->getValueAsBit("AssemblerMatcherPredicate");
488 CompressPatterns
.push_back(CompressPat(SourceInst
, DestInst
, PatReqFeatures
,
489 SourceOperandMap
, DestOperandMap
,
490 Rec
->getValueAsBit("isCompressOnly")));
494 getReqFeatures(std::set
<std::pair
<bool, StringRef
>> &FeaturesSet
,
495 std::set
<std::set
<std::pair
<bool, StringRef
>>> &AnyOfFeatureSets
,
496 ArrayRef
<const Record
*> ReqFeatures
) {
497 for (const Record
*R
: ReqFeatures
) {
498 const DagInit
*D
= R
->getValueAsDag("AssemblerCondDag");
499 std::string CombineType
= D
->getOperator()->getAsString();
500 if (CombineType
!= "any_of" && CombineType
!= "all_of")
501 PrintFatalError(R
->getLoc(), "Invalid AssemblerCondDag!");
502 if (D
->getNumArgs() == 0)
503 PrintFatalError(R
->getLoc(), "Invalid AssemblerCondDag!");
504 bool IsOr
= CombineType
== "any_of";
505 std::set
<std::pair
<bool, StringRef
>> AnyOfSet
;
507 for (auto *Arg
: D
->getArgs()) {
509 if (auto *NotArg
= dyn_cast
<DagInit
>(Arg
)) {
510 if (NotArg
->getOperator()->getAsString() != "not" ||
511 NotArg
->getNumArgs() != 1)
512 PrintFatalError(R
->getLoc(), "Invalid AssemblerCondDag!");
513 Arg
= NotArg
->getArg(0);
516 if (!isa
<DefInit
>(Arg
) ||
517 !cast
<DefInit
>(Arg
)->getDef()->isSubClassOf("SubtargetFeature"))
518 PrintFatalError(R
->getLoc(), "Invalid AssemblerCondDag!");
520 AnyOfSet
.insert({IsNot
, cast
<DefInit
>(Arg
)->getDef()->getName()});
522 FeaturesSet
.insert({IsNot
, cast
<DefInit
>(Arg
)->getDef()->getName()});
526 AnyOfFeatureSets
.insert(AnyOfSet
);
530 static unsigned getPredicates(DenseMap
<const Record
*, unsigned> &PredicateMap
,
531 std::vector
<const Record
*> &Predicates
,
532 const Record
*Rec
, StringRef Name
) {
533 unsigned &Entry
= PredicateMap
[Rec
];
537 if (!Rec
->isValueUnset(Name
)) {
538 Predicates
.push_back(Rec
);
539 Entry
= Predicates
.size();
543 PrintFatalError(Rec
->getLoc(), "No " + Name
+
544 " predicate on this operand at all: '" +
545 Rec
->getName() + "'");
549 static void printPredicates(ArrayRef
<const Record
*> Predicates
, StringRef Name
,
551 for (unsigned I
= 0; I
< Predicates
.size(); ++I
) {
552 StringRef Pred
= Predicates
[I
]->getValueAsString(Name
);
553 OS
<< " case " << I
+ 1 << ": {\n"
554 << " // " << Predicates
[I
]->getName() << "\n"
555 << " " << Pred
<< "\n"
560 static void mergeCondAndCode(raw_ostream
&CombinedStream
, StringRef CondStr
,
562 // Remove first indentation and last '&&'.
563 CondStr
= CondStr
.drop_front(6).drop_back(4);
564 CombinedStream
.indent(4) << "if (" << CondStr
<< ") {\n";
565 CombinedStream
<< CodeStr
;
566 CombinedStream
.indent(4) << " return true;\n";
567 CombinedStream
.indent(4) << "} // if\n";
570 void CompressInstEmitter::emitCompressInstEmitter(raw_ostream
&OS
,
572 const Record
*AsmWriter
= Target
.getAsmWriter();
573 if (!AsmWriter
->getValueAsInt("PassSubtarget"))
574 PrintFatalError(AsmWriter
->getLoc(),
575 "'PassSubtarget' is false. SubTargetInfo object is needed "
576 "for target features.\n");
578 StringRef TargetName
= Target
.getName();
580 // Sort entries in CompressPatterns to handle instructions that can have more
581 // than one candidate for compression\uncompression, e.g ADD can be
582 // transformed to a C_ADD or a C_MV. When emitting 'uncompress()' function the
583 // source and destination are flipped and the sort key needs to change
585 llvm::stable_sort(CompressPatterns
, [EType
](const CompressPat
&LHS
,
586 const CompressPat
&RHS
) {
587 if (EType
== EmitterType::Compress
|| EType
== EmitterType::CheckCompress
)
588 return (LHS
.Source
.TheDef
->getName() < RHS
.Source
.TheDef
->getName());
589 return (LHS
.Dest
.TheDef
->getName() < RHS
.Dest
.TheDef
->getName());
592 // A list of MCOperandPredicates for all operands in use, and the reverse map.
593 std::vector
<const Record
*> MCOpPredicates
;
594 DenseMap
<const Record
*, unsigned> MCOpPredicateMap
;
595 // A list of ImmLeaf Predicates for all operands in use, and the reverse map.
596 std::vector
<const Record
*> ImmLeafPredicates
;
597 DenseMap
<const Record
*, unsigned> ImmLeafPredicateMap
;
601 raw_string_ostream
Func(F
);
602 raw_string_ostream
FuncH(FH
);
604 if (EType
== EmitterType::Compress
)
605 OS
<< "\n#ifdef GEN_COMPRESS_INSTR\n"
606 << "#undef GEN_COMPRESS_INSTR\n\n";
607 else if (EType
== EmitterType::Uncompress
)
608 OS
<< "\n#ifdef GEN_UNCOMPRESS_INSTR\n"
609 << "#undef GEN_UNCOMPRESS_INSTR\n\n";
610 else if (EType
== EmitterType::CheckCompress
)
611 OS
<< "\n#ifdef GEN_CHECK_COMPRESS_INSTR\n"
612 << "#undef GEN_CHECK_COMPRESS_INSTR\n\n";
614 if (EType
== EmitterType::Compress
) {
615 FuncH
<< "static bool compressInst(MCInst &OutInst,\n";
616 FuncH
.indent(25) << "const MCInst &MI,\n";
617 FuncH
.indent(25) << "const MCSubtargetInfo &STI) {\n";
618 } else if (EType
== EmitterType::Uncompress
) {
619 FuncH
<< "static bool uncompressInst(MCInst &OutInst,\n";
620 FuncH
.indent(27) << "const MCInst &MI,\n";
621 FuncH
.indent(27) << "const MCSubtargetInfo &STI) {\n";
622 } else if (EType
== EmitterType::CheckCompress
) {
623 FuncH
<< "static bool isCompressibleInst(const MachineInstr &MI,\n";
624 FuncH
.indent(31) << "const " << TargetName
<< "Subtarget &STI) {\n";
627 if (CompressPatterns
.empty()) {
629 OS
.indent(2) << "return false;\n}\n";
630 if (EType
== EmitterType::Compress
)
631 OS
<< "\n#endif //GEN_COMPRESS_INSTR\n";
632 else if (EType
== EmitterType::Uncompress
)
633 OS
<< "\n#endif //GEN_UNCOMPRESS_INSTR\n\n";
634 else if (EType
== EmitterType::CheckCompress
)
635 OS
<< "\n#endif //GEN_CHECK_COMPRESS_INSTR\n\n";
639 std::string CaseString
;
640 raw_string_ostream
CaseStream(CaseString
);
643 CaseStream
<< " switch (MI.getOpcode()) {\n";
644 CaseStream
<< " default: return false;\n";
646 bool CompressOrCheck
=
647 EType
== EmitterType::Compress
|| EType
== EmitterType::CheckCompress
;
648 bool CompressOrUncompress
=
649 EType
== EmitterType::Compress
|| EType
== EmitterType::Uncompress
;
650 std::string ValidatorName
=
652 ? (TargetName
+ "ValidateMCOperandFor" +
653 (EType
== EmitterType::Compress
? "Compress" : "Uncompress"))
657 for (auto &CompressPat
: CompressPatterns
) {
658 if (EType
== EmitterType::Uncompress
&& CompressPat
.IsCompressOnly
)
661 std::string CondString
;
662 std::string CodeString
;
663 raw_string_ostream
CondStream(CondString
);
664 raw_string_ostream
CodeStream(CodeString
);
665 CodeGenInstruction
&Source
=
666 CompressOrCheck
? CompressPat
.Source
: CompressPat
.Dest
;
667 CodeGenInstruction
&Dest
=
668 CompressOrCheck
? CompressPat
.Dest
: CompressPat
.Source
;
669 IndexedMap
<OpData
> SourceOperandMap
= CompressOrCheck
670 ? CompressPat
.SourceOperandMap
671 : CompressPat
.DestOperandMap
;
672 IndexedMap
<OpData
> &DestOperandMap
= CompressOrCheck
673 ? CompressPat
.DestOperandMap
674 : CompressPat
.SourceOperandMap
;
676 CurOp
= Source
.TheDef
->getName();
677 // Check current and previous opcode to decide to continue or end a case.
678 if (CurOp
!= PrevOp
) {
680 CaseStream
.indent(6) << "break;\n } // case " + PrevOp
+ "\n";
681 CaseStream
.indent(4) << "case " + TargetName
+ "::" + CurOp
+ ": {\n";
684 std::set
<std::pair
<bool, StringRef
>> FeaturesSet
;
685 std::set
<std::set
<std::pair
<bool, StringRef
>>> AnyOfFeatureSets
;
686 // Add CompressPat required features.
687 getReqFeatures(FeaturesSet
, AnyOfFeatureSets
, CompressPat
.PatReqFeatures
);
689 // Add Dest instruction required features.
690 std::vector
<const Record
*> ReqFeatures
;
691 std::vector
<const Record
*> RF
=
692 Dest
.TheDef
->getValueAsListOfDefs("Predicates");
693 copy_if(RF
, std::back_inserter(ReqFeatures
), [](const Record
*R
) {
694 return R
->getValueAsBit("AssemblerMatcherPredicate");
696 getReqFeatures(FeaturesSet
, AnyOfFeatureSets
, ReqFeatures
);
698 // Emit checks for all required features.
699 for (auto &Op
: FeaturesSet
) {
700 StringRef Not
= Op
.first
? "!" : "";
701 CondStream
.indent(6) << Not
<< "STI.getFeatureBits()[" << TargetName
702 << "::" << Op
.second
<< "]"
706 // Emit checks for all required feature groups.
707 for (auto &Set
: AnyOfFeatureSets
) {
708 CondStream
.indent(6) << "(";
709 for (auto &Op
: Set
) {
710 bool IsLast
= &Op
== &*Set
.rbegin();
711 StringRef Not
= Op
.first
? "!" : "";
712 CondStream
<< Not
<< "STI.getFeatureBits()[" << TargetName
713 << "::" << Op
.second
<< "]";
715 CondStream
<< " || ";
717 CondStream
<< ") &&\n";
720 // Start Source Inst operands validation.
722 for (OpNo
= 0; OpNo
< Source
.Operands
.size(); ++OpNo
) {
723 if (SourceOperandMap
[OpNo
].TiedOpIdx
!= -1) {
724 if (Source
.Operands
[OpNo
].Rec
->isSubClassOf("RegisterClass"))
726 << "(MI.getOperand(" << OpNo
<< ").isReg()) && (MI.getOperand("
727 << SourceOperandMap
[OpNo
].TiedOpIdx
<< ").isReg()) &&\n"
728 << " (MI.getOperand(" << OpNo
729 << ").getReg() == MI.getOperand("
730 << SourceOperandMap
[OpNo
].TiedOpIdx
<< ").getReg()) &&\n";
732 PrintFatalError("Unexpected tied operand types!\n");
734 // Check for fixed immediates\registers in the source instruction.
735 switch (SourceOperandMap
[OpNo
].Kind
) {
736 case OpData::Operand
:
737 // We don't need to do anything for source instruction operand checks.
741 << "(MI.getOperand(" << OpNo
<< ").isImm()) &&\n"
742 << " (MI.getOperand(" << OpNo
743 << ").getImm() == " << SourceOperandMap
[OpNo
].Data
.Imm
<< ") &&\n";
746 const Record
*Reg
= SourceOperandMap
[OpNo
].Data
.Reg
;
748 << "(MI.getOperand(" << OpNo
<< ").isReg()) &&\n"
749 << " (MI.getOperand(" << OpNo
<< ").getReg() == " << TargetName
750 << "::" << Reg
->getName() << ") &&\n";
755 CodeStream
.indent(6) << "// " << Dest
.AsmString
<< "\n";
756 if (CompressOrUncompress
)
757 CodeStream
.indent(6) << "OutInst.setOpcode(" << TargetName
758 << "::" << Dest
.TheDef
->getName() << ");\n";
760 for (const auto &DestOperand
: Dest
.Operands
) {
761 CodeStream
.indent(6) << "// Operand: " << DestOperand
.Name
<< "\n";
762 switch (DestOperandMap
[OpNo
].Kind
) {
763 case OpData::Operand
: {
764 unsigned OpIdx
= DestOperandMap
[OpNo
].Data
.Operand
;
765 // Check that the operand in the Source instruction fits
766 // the type for the Dest instruction.
767 if (DestOperand
.Rec
->isSubClassOf("RegisterClass") ||
768 DestOperand
.Rec
->isSubClassOf("RegisterOperand")) {
769 auto *ClassRec
= DestOperand
.Rec
->isSubClassOf("RegisterClass")
771 : DestOperand
.Rec
->getValueAsDef("RegClass");
772 // This is a register operand. Check the register class.
773 // Don't check register class if this is a tied operand, it was done
774 // for the operand its tied to.
775 if (DestOperand
.getTiedRegister() == -1)
777 << "(MI.getOperand(" << OpIdx
<< ").isReg()) &&\n"
778 << " (" << TargetName
<< "MCRegisterClasses[" << TargetName
779 << "::" << ClassRec
->getName()
780 << "RegClassID].contains(MI.getOperand(" << OpIdx
781 << ").getReg())) &&\n";
783 if (CompressOrUncompress
)
785 << "OutInst.addOperand(MI.getOperand(" << OpIdx
<< "));\n";
787 // Handling immediate operands.
788 if (CompressOrUncompress
) {
790 getPredicates(MCOpPredicateMap
, MCOpPredicates
, DestOperand
.Rec
,
791 "MCOperandPredicate");
793 << ValidatorName
<< "("
794 << "MI.getOperand(" << OpIdx
<< "), STI, " << Entry
<< ") &&\n";
797 getPredicates(ImmLeafPredicateMap
, ImmLeafPredicates
,
798 DestOperand
.Rec
, "ImmediateCode");
800 << "MI.getOperand(" << OpIdx
<< ").isImm() &&\n";
801 CondStream
.indent(6) << TargetName
<< "ValidateMachineOperand("
802 << "MI.getOperand(" << OpIdx
<< "), &STI, "
803 << Entry
<< ") &&\n";
805 if (CompressOrUncompress
)
807 << "OutInst.addOperand(MI.getOperand(" << OpIdx
<< "));\n";
812 if (CompressOrUncompress
) {
813 unsigned Entry
= getPredicates(MCOpPredicateMap
, MCOpPredicates
,
814 DestOperand
.Rec
, "MCOperandPredicate");
816 << ValidatorName
<< "("
817 << "MCOperand::createImm(" << DestOperandMap
[OpNo
].Data
.Imm
818 << "), STI, " << Entry
<< ") &&\n";
820 unsigned Entry
= getPredicates(ImmLeafPredicateMap
, ImmLeafPredicates
,
821 DestOperand
.Rec
, "ImmediateCode");
824 << "ValidateMachineOperand(MachineOperand::CreateImm("
825 << DestOperandMap
[OpNo
].Data
.Imm
<< "), &STI, " << Entry
828 if (CompressOrUncompress
)
829 CodeStream
.indent(6) << "OutInst.addOperand(MCOperand::createImm("
830 << DestOperandMap
[OpNo
].Data
.Imm
<< "));\n";
833 if (CompressOrUncompress
) {
834 // Fixed register has been validated at pattern validation time.
835 const Record
*Reg
= DestOperandMap
[OpNo
].Data
.Reg
;
837 << "OutInst.addOperand(MCOperand::createReg(" << TargetName
838 << "::" << Reg
->getName() << "));\n";
844 if (CompressOrUncompress
)
845 CodeStream
.indent(6) << "OutInst.setLoc(MI.getLoc());\n";
846 mergeCondAndCode(CaseStream
, CondString
, CodeString
);
849 Func
<< CaseString
<< "\n";
850 // Close brace for the last case.
851 Func
.indent(4) << "} // case " << CurOp
<< "\n";
852 Func
.indent(2) << "} // switch\n";
853 Func
.indent(2) << "return false;\n}\n";
855 if (!MCOpPredicates
.empty()) {
856 OS
<< "static bool " << ValidatorName
<< "(const MCOperand &MCOp,\n"
857 << " const MCSubtargetInfo &STI,\n"
858 << " unsigned PredicateIndex) {\n"
859 << " switch (PredicateIndex) {\n"
861 << " llvm_unreachable(\"Unknown MCOperandPredicate kind\");\n"
864 printPredicates(MCOpPredicates
, "MCOperandPredicate", OS
);
870 if (!ImmLeafPredicates
.empty()) {
871 OS
<< "static bool " << TargetName
872 << "ValidateMachineOperand(const MachineOperand &MO,\n"
873 << " const " << TargetName
<< "Subtarget *Subtarget,\n"
874 << " unsigned PredicateIndex) {\n"
875 << " int64_t Imm = MO.getImm();\n"
876 << " switch (PredicateIndex) {\n"
878 << " llvm_unreachable(\"Unknown ImmLeaf Predicate kind\");\n"
881 printPredicates(ImmLeafPredicates
, "ImmediateCode", OS
);
890 if (EType
== EmitterType::Compress
)
891 OS
<< "\n#endif //GEN_COMPRESS_INSTR\n";
892 else if (EType
== EmitterType::Uncompress
)
893 OS
<< "\n#endif //GEN_UNCOMPRESS_INSTR\n\n";
894 else if (EType
== EmitterType::CheckCompress
)
895 OS
<< "\n#endif //GEN_CHECK_COMPRESS_INSTR\n\n";
898 void CompressInstEmitter::run(raw_ostream
&OS
) {
899 // Process the CompressPat definitions, validating them as we do so.
900 for (const Record
*Pat
: Records
.getAllDerivedDefinitions("CompressPat"))
901 evaluateCompressPat(Pat
);
904 emitSourceFileHeader("Compress instruction Source Fragment", OS
, Records
);
905 // Generate compressInst() function.
906 emitCompressInstEmitter(OS
, EmitterType::Compress
);
907 // Generate uncompressInst() function.
908 emitCompressInstEmitter(OS
, EmitterType::Uncompress
);
909 // Generate isCompressibleInst() function.
910 emitCompressInstEmitter(OS
, EmitterType::CheckCompress
);
913 static TableGen::Emitter::OptClass
<CompressInstEmitter
>
914 X("gen-compress-inst-emitter", "Generate compressed instructions.");