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(std::move(RF
)),
119 SourceOperandMap(SourceMap
), DestOperandMap(DestMap
),
120 IsCompressOnly(IsCompressOnly
) {}
122 enum EmitterType
{ Compress
, Uncompress
, CheckCompress
};
123 const RecordKeeper
&Records
;
124 const CodeGenTarget Target
;
125 SmallVector
<CompressPat
, 4> CompressPatterns
;
127 void addDagOperandMapping(const Record
*Rec
, const DagInit
*Dag
,
128 const CodeGenInstruction
&Inst
,
129 IndexedMap
<OpData
> &OperandMap
, bool IsSourceInst
);
130 void evaluateCompressPat(const Record
*Compress
);
131 void emitCompressInstEmitter(raw_ostream
&OS
, EmitterType EType
);
132 bool validateTypes(const Record
*DagOpType
, const Record
*InstOpType
,
134 bool validateRegister(const Record
*Reg
, const Record
*RegClass
);
135 void createDagOperandMapping(const Record
*Rec
,
136 StringMap
<unsigned> &SourceOperands
,
137 StringMap
<unsigned> &DestOperands
,
138 const DagInit
*SourceDag
, const DagInit
*DestDag
,
139 IndexedMap
<OpData
> &SourceOperandMap
);
141 void createInstOperandMapping(const Record
*Rec
, const DagInit
*SourceDag
,
142 const DagInit
*DestDag
,
143 IndexedMap
<OpData
> &SourceOperandMap
,
144 IndexedMap
<OpData
> &DestOperandMap
,
145 StringMap
<unsigned> &SourceOperands
,
146 const CodeGenInstruction
&DestInst
);
149 CompressInstEmitter(const RecordKeeper
&R
) : Records(R
), Target(R
) {}
151 void run(raw_ostream
&OS
);
153 } // End anonymous namespace.
155 bool CompressInstEmitter::validateRegister(const Record
*Reg
,
156 const Record
*RegClass
) {
157 assert(Reg
->isSubClassOf("Register") && "Reg record should be a Register");
158 assert(RegClass
->isSubClassOf("RegisterClass") &&
159 "RegClass record should be a RegisterClass");
160 const CodeGenRegisterClass
&RC
= Target
.getRegisterClass(RegClass
);
161 const CodeGenRegister
*R
= Target
.getRegisterByName(Reg
->getName().lower());
162 assert(R
!= nullptr && "Register not defined!!");
163 return RC
.contains(R
);
166 bool CompressInstEmitter::validateTypes(const Record
*DagOpType
,
167 const Record
*InstOpType
,
169 if (DagOpType
== InstOpType
)
171 // Only source instruction operands are allowed to not match Input Dag
176 if (DagOpType
->isSubClassOf("RegisterClass") &&
177 InstOpType
->isSubClassOf("RegisterClass")) {
178 const CodeGenRegisterClass
&RC
= Target
.getRegisterClass(InstOpType
);
179 const CodeGenRegisterClass
&SubRC
= Target
.getRegisterClass(DagOpType
);
180 return RC
.hasSubClass(&SubRC
);
183 // At this point either or both types are not registers, reject the pattern.
184 if (DagOpType
->isSubClassOf("RegisterClass") ||
185 InstOpType
->isSubClassOf("RegisterClass"))
188 // Let further validation happen when compress()/uncompress() functions are
190 LLVM_DEBUG(dbgs() << (IsSourceInst
? "Input" : "Output")
191 << " Dag Operand Type: '" << DagOpType
->getName()
193 << "Instruction Operand Type: '" << InstOpType
->getName()
194 << "' can't be checked at pattern validation time!\n");
198 /// The patterns in the Dag contain different types of operands:
199 /// Register operands, e.g.: GPRC:$rs1; Fixed registers, e.g: X1; Immediate
200 /// operands, e.g.: simm6:$imm; Fixed immediate operands, e.g.: 0. This function
201 /// maps Dag operands to its corresponding instruction operands. For register
202 /// operands and fixed registers it expects the Dag operand type to be contained
203 /// in the instantiated instruction operand type. For immediate operands and
204 /// immediates no validation checks are enforced at pattern validation time.
205 void CompressInstEmitter::addDagOperandMapping(const Record
*Rec
,
207 const CodeGenInstruction
&Inst
,
208 IndexedMap
<OpData
> &OperandMap
,
210 // TiedCount keeps track of the number of operands skipped in Inst
211 // operands list to get to the corresponding Dag operand. This is
212 // necessary because the number of operands in Inst might be greater
213 // than number of operands in the Dag due to how tied operands
215 unsigned TiedCount
= 0;
216 for (unsigned I
= 0, E
= Inst
.Operands
.size(); I
!= E
; ++I
) {
217 int TiedOpIdx
= Inst
.Operands
[I
].getTiedRegister();
218 if (-1 != TiedOpIdx
) {
219 // Set the entry in OperandMap for the tied operand we're skipping.
220 OperandMap
[I
].Kind
= OperandMap
[TiedOpIdx
].Kind
;
221 OperandMap
[I
].Data
= OperandMap
[TiedOpIdx
].Data
;
225 if (const DefInit
*DI
= dyn_cast
<DefInit
>(Dag
->getArg(I
- TiedCount
))) {
226 if (DI
->getDef()->isSubClassOf("Register")) {
227 // Check if the fixed register belongs to the Register class.
228 if (!validateRegister(DI
->getDef(), Inst
.Operands
[I
].Rec
))
229 PrintFatalError(Rec
->getLoc(),
230 "Error in Dag '" + Dag
->getAsString() +
231 "'Register: '" + DI
->getDef()->getName() +
232 "' is not in register class '" +
233 Inst
.Operands
[I
].Rec
->getName() + "'");
234 OperandMap
[I
].Kind
= OpData::Reg
;
235 OperandMap
[I
].Data
.Reg
= DI
->getDef();
238 // Validate that Dag operand type matches the type defined in the
239 // corresponding instruction. Operands in the input Dag pattern are
240 // allowed to be a subclass of the type specified in corresponding
241 // instruction operand instead of being an exact match.
242 if (!validateTypes(DI
->getDef(), Inst
.Operands
[I
].Rec
, IsSourceInst
))
243 PrintFatalError(Rec
->getLoc(),
244 "Error in Dag '" + Dag
->getAsString() + "'. Operand '" +
245 Dag
->getArgNameStr(I
- TiedCount
) + "' has type '" +
246 DI
->getDef()->getName() +
247 "' which does not match the type '" +
248 Inst
.Operands
[I
].Rec
->getName() +
249 "' in the corresponding instruction operand!");
251 OperandMap
[I
].Kind
= OpData::Operand
;
252 } else if (const IntInit
*II
=
253 dyn_cast
<IntInit
>(Dag
->getArg(I
- TiedCount
))) {
254 // Validate that corresponding instruction operand expects an immediate.
255 if (Inst
.Operands
[I
].Rec
->isSubClassOf("RegisterClass"))
258 "Error in Dag '" + Dag
->getAsString() + "' Found immediate: '" +
260 "' but corresponding instruction operand expected a register!");
261 // No pattern validation check possible for values of fixed immediate.
262 OperandMap
[I
].Kind
= OpData::Imm
;
263 OperandMap
[I
].Data
.Imm
= II
->getValue();
265 dbgs() << " Found immediate '" << II
->getValue() << "' at "
266 << (IsSourceInst
? "input " : "output ")
267 << "Dag. No validation time check possible for values of "
268 "fixed immediate.\n");
270 llvm_unreachable("Unhandled CompressPat argument type!");
274 // Verify the Dag operand count is enough to build an instruction.
275 static bool verifyDagOpCount(const CodeGenInstruction
&Inst
, const DagInit
*Dag
,
277 if (Dag
->getNumArgs() == Inst
.Operands
.size())
279 // Source instructions are non compressed instructions and don't have tied
282 PrintFatalError(Inst
.TheDef
->getLoc(),
283 "Input operands for Inst '" + Inst
.TheDef
->getName() +
284 "' and input Dag operand count mismatch");
285 // The Dag can't have more arguments than the Instruction.
286 if (Dag
->getNumArgs() > Inst
.Operands
.size())
287 PrintFatalError(Inst
.TheDef
->getLoc(),
288 "Inst '" + Inst
.TheDef
->getName() +
289 "' and Dag operand count mismatch");
291 // The Instruction might have tied operands so the Dag might have
292 // a fewer operand count.
293 unsigned RealCount
= Inst
.Operands
.size();
294 for (const auto &Operand
: Inst
.Operands
)
295 if (Operand
.getTiedRegister() != -1)
298 if (Dag
->getNumArgs() != RealCount
)
299 PrintFatalError(Inst
.TheDef
->getLoc(),
300 "Inst '" + Inst
.TheDef
->getName() +
301 "' and Dag operand count mismatch");
305 static bool validateArgsTypes(const Init
*Arg1
, const Init
*Arg2
) {
306 return cast
<DefInit
>(Arg1
)->getDef() == cast
<DefInit
>(Arg2
)->getDef();
309 // Creates a mapping between the operand name in the Dag (e.g. $rs1) and
310 // its index in the list of Dag operands and checks that operands with the same
311 // name have the same types. For example in 'C_ADD $rs1, $rs2' we generate the
312 // mapping $rs1 --> 0, $rs2 ---> 1. If the operand appears twice in the (tied)
313 // same Dag we use the last occurrence for indexing.
314 void CompressInstEmitter::createDagOperandMapping(
315 const Record
*Rec
, StringMap
<unsigned> &SourceOperands
,
316 StringMap
<unsigned> &DestOperands
, const DagInit
*SourceDag
,
317 const DagInit
*DestDag
, IndexedMap
<OpData
> &SourceOperandMap
) {
318 for (unsigned I
= 0; I
< DestDag
->getNumArgs(); ++I
) {
319 // Skip fixed immediates and registers, they were handled in
320 // addDagOperandMapping.
321 if ("" == DestDag
->getArgNameStr(I
))
323 DestOperands
[DestDag
->getArgNameStr(I
)] = I
;
326 for (unsigned I
= 0; I
< SourceDag
->getNumArgs(); ++I
) {
327 // Skip fixed immediates and registers, they were handled in
328 // addDagOperandMapping.
329 if ("" == SourceDag
->getArgNameStr(I
))
332 StringMap
<unsigned>::iterator It
=
333 SourceOperands
.find(SourceDag
->getArgNameStr(I
));
334 if (It
!= SourceOperands
.end()) {
335 // Operand sharing the same name in the Dag should be mapped as tied.
336 SourceOperandMap
[I
].TiedOpIdx
= It
->getValue();
337 if (!validateArgsTypes(SourceDag
->getArg(It
->getValue()),
338 SourceDag
->getArg(I
)))
339 PrintFatalError(Rec
->getLoc(),
340 "Input Operand '" + SourceDag
->getArgNameStr(I
) +
341 "' has a mismatched tied operand!\n");
343 It
= DestOperands
.find(SourceDag
->getArgNameStr(I
));
344 if (It
== DestOperands
.end())
345 PrintFatalError(Rec
->getLoc(), "Operand " + SourceDag
->getArgNameStr(I
) +
346 " defined in Input Dag but not used in"
348 // Input Dag operand types must match output Dag operand type.
349 if (!validateArgsTypes(DestDag
->getArg(It
->getValue()),
350 SourceDag
->getArg(I
)))
351 PrintFatalError(Rec
->getLoc(), "Type mismatch between Input and "
352 "Output Dag operand '" +
353 SourceDag
->getArgNameStr(I
) + "'!");
354 SourceOperands
[SourceDag
->getArgNameStr(I
)] = I
;
358 /// Map operand names in the Dag to their index in both corresponding input and
359 /// output instructions. Validate that operands defined in the input are
360 /// used in the output pattern while populating the maps.
361 void CompressInstEmitter::createInstOperandMapping(
362 const Record
*Rec
, const DagInit
*SourceDag
, const DagInit
*DestDag
,
363 IndexedMap
<OpData
> &SourceOperandMap
, IndexedMap
<OpData
> &DestOperandMap
,
364 StringMap
<unsigned> &SourceOperands
, const CodeGenInstruction
&DestInst
) {
365 // TiedCount keeps track of the number of operands skipped in Inst
366 // operands list to get to the corresponding Dag operand.
367 unsigned TiedCount
= 0;
368 LLVM_DEBUG(dbgs() << " Operand mapping:\n Source Dest\n");
369 for (unsigned I
= 0, E
= DestInst
.Operands
.size(); I
!= E
; ++I
) {
370 int TiedInstOpIdx
= DestInst
.Operands
[I
].getTiedRegister();
371 if (TiedInstOpIdx
!= -1) {
373 DestOperandMap
[I
].Data
= DestOperandMap
[TiedInstOpIdx
].Data
;
374 DestOperandMap
[I
].Kind
= DestOperandMap
[TiedInstOpIdx
].Kind
;
375 if (DestOperandMap
[I
].Kind
== OpData::Operand
)
376 // No need to fill the SourceOperandMap here since it was mapped to
377 // destination operand 'TiedInstOpIdx' in a previous iteration.
378 LLVM_DEBUG(dbgs() << " " << DestOperandMap
[I
].Data
.Operand
380 << " Dest operand tied with operand '"
381 << TiedInstOpIdx
<< "'\n");
384 // Skip fixed immediates and registers, they were handled in
385 // addDagOperandMapping.
386 if (DestOperandMap
[I
].Kind
!= OpData::Operand
)
389 unsigned DagArgIdx
= I
- TiedCount
;
390 StringMap
<unsigned>::iterator SourceOp
=
391 SourceOperands
.find(DestDag
->getArgNameStr(DagArgIdx
));
392 if (SourceOp
== SourceOperands
.end())
393 PrintFatalError(Rec
->getLoc(),
394 "Output Dag operand '" +
395 DestDag
->getArgNameStr(DagArgIdx
) +
396 "' has no matching input Dag operand.");
398 assert(DestDag
->getArgNameStr(DagArgIdx
) ==
399 SourceDag
->getArgNameStr(SourceOp
->getValue()) &&
400 "Incorrect operand mapping detected!\n");
401 DestOperandMap
[I
].Data
.Operand
= SourceOp
->getValue();
402 SourceOperandMap
[SourceOp
->getValue()].Data
.Operand
= I
;
403 LLVM_DEBUG(dbgs() << " " << SourceOp
->getValue() << " ====> " << I
408 /// Validates the CompressPattern and create operand mapping.
409 /// These are the checks to validate a CompressPat pattern declarations.
410 /// Error out with message under these conditions:
411 /// - Dag Input opcode is an expanded instruction and Dag Output opcode is a
412 /// compressed instruction.
413 /// - Operands in Dag Input must be all used in Dag Output.
414 /// Register Operand type in Dag Input Type must be contained in the
415 /// corresponding Source Instruction type.
416 /// - Register Operand type in Dag Input must be the same as in Dag Ouput.
417 /// - Register Operand type in Dag Output must be the same as the
418 /// corresponding Destination Inst type.
419 /// - Immediate Operand type in Dag Input must be the same as in Dag Ouput.
420 /// - Immediate Operand type in Dag Ouput must be the same as the corresponding
421 /// Destination Instruction type.
422 /// - Fixed register must be contained in the corresponding Source Instruction
424 /// - Fixed register must be contained in the corresponding Destination
425 /// Instruction type.
426 /// Warning message printed under these conditions:
427 /// - Fixed immediate in Dag Input or Dag Ouput cannot be checked at this time
428 /// and generate warning.
429 /// - Immediate operand type in Dag Input differs from the corresponding Source
430 /// Instruction type and generate a warning.
431 void CompressInstEmitter::evaluateCompressPat(const Record
*Rec
) {
432 // Validate input Dag operands.
433 const DagInit
*SourceDag
= Rec
->getValueAsDag("Input");
434 assert(SourceDag
&& "Missing 'Input' in compress pattern!");
435 LLVM_DEBUG(dbgs() << "Input: " << *SourceDag
<< "\n");
437 // Checking we are transforming from compressed to uncompressed instructions.
438 const Record
*SourceOperator
= SourceDag
->getOperatorAsDef(Rec
->getLoc());
439 CodeGenInstruction
SourceInst(SourceOperator
);
440 verifyDagOpCount(SourceInst
, SourceDag
, true);
442 // Validate output Dag operands.
443 const DagInit
*DestDag
= Rec
->getValueAsDag("Output");
444 assert(DestDag
&& "Missing 'Output' in compress pattern!");
445 LLVM_DEBUG(dbgs() << "Output: " << *DestDag
<< "\n");
447 const Record
*DestOperator
= DestDag
->getOperatorAsDef(Rec
->getLoc());
448 CodeGenInstruction
DestInst(DestOperator
);
449 verifyDagOpCount(DestInst
, DestDag
, false);
451 if (SourceOperator
->getValueAsInt("Size") <=
452 DestOperator
->getValueAsInt("Size"))
455 "Compressed instruction '" + DestOperator
->getName() +
456 "'is not strictly smaller than the uncompressed instruction '" +
457 SourceOperator
->getName() + "' !");
459 // Fill the mapping from the source to destination instructions.
461 IndexedMap
<OpData
> SourceOperandMap
;
462 SourceOperandMap
.grow(SourceInst
.Operands
.size());
463 // Create a mapping between source Dag operands and source Inst operands.
464 addDagOperandMapping(Rec
, SourceDag
, SourceInst
, SourceOperandMap
,
465 /*IsSourceInst*/ true);
467 IndexedMap
<OpData
> DestOperandMap
;
468 DestOperandMap
.grow(DestInst
.Operands
.size());
469 // Create a mapping between destination Dag operands and destination Inst
471 addDagOperandMapping(Rec
, DestDag
, DestInst
, DestOperandMap
,
472 /*IsSourceInst*/ false);
474 StringMap
<unsigned> SourceOperands
;
475 StringMap
<unsigned> DestOperands
;
476 createDagOperandMapping(Rec
, SourceOperands
, DestOperands
, SourceDag
, DestDag
,
478 // Create operand mapping between the source and destination instructions.
479 createInstOperandMapping(Rec
, SourceDag
, DestDag
, SourceOperandMap
,
480 DestOperandMap
, SourceOperands
, DestInst
);
482 // Get the target features for the CompressPat.
483 std::vector
<const Record
*> PatReqFeatures
;
484 std::vector
<const Record
*> RF
= Rec
->getValueAsListOfDefs("Predicates");
485 copy_if(RF
, std::back_inserter(PatReqFeatures
), [](const Record
*R
) {
486 return R
->getValueAsBit("AssemblerMatcherPredicate");
489 CompressPatterns
.push_back(CompressPat(
490 SourceInst
, DestInst
, std::move(PatReqFeatures
), SourceOperandMap
,
491 DestOperandMap
, Rec
->getValueAsBit("isCompressOnly")));
495 getReqFeatures(std::set
<std::pair
<bool, StringRef
>> &FeaturesSet
,
496 std::set
<std::set
<std::pair
<bool, StringRef
>>> &AnyOfFeatureSets
,
497 ArrayRef
<const Record
*> ReqFeatures
) {
498 for (const Record
*R
: ReqFeatures
) {
499 const DagInit
*D
= R
->getValueAsDag("AssemblerCondDag");
500 std::string CombineType
= D
->getOperator()->getAsString();
501 if (CombineType
!= "any_of" && CombineType
!= "all_of")
502 PrintFatalError(R
->getLoc(), "Invalid AssemblerCondDag!");
503 if (D
->getNumArgs() == 0)
504 PrintFatalError(R
->getLoc(), "Invalid AssemblerCondDag!");
505 bool IsOr
= CombineType
== "any_of";
506 std::set
<std::pair
<bool, StringRef
>> AnyOfSet
;
508 for (auto *Arg
: D
->getArgs()) {
510 if (auto *NotArg
= dyn_cast
<DagInit
>(Arg
)) {
511 if (NotArg
->getOperator()->getAsString() != "not" ||
512 NotArg
->getNumArgs() != 1)
513 PrintFatalError(R
->getLoc(), "Invalid AssemblerCondDag!");
514 Arg
= NotArg
->getArg(0);
517 if (!isa
<DefInit
>(Arg
) ||
518 !cast
<DefInit
>(Arg
)->getDef()->isSubClassOf("SubtargetFeature"))
519 PrintFatalError(R
->getLoc(), "Invalid AssemblerCondDag!");
521 AnyOfSet
.insert({IsNot
, cast
<DefInit
>(Arg
)->getDef()->getName()});
523 FeaturesSet
.insert({IsNot
, cast
<DefInit
>(Arg
)->getDef()->getName()});
527 AnyOfFeatureSets
.insert(std::move(AnyOfSet
));
531 static unsigned getPredicates(DenseMap
<const Record
*, unsigned> &PredicateMap
,
532 std::vector
<const Record
*> &Predicates
,
533 const Record
*Rec
, StringRef Name
) {
534 unsigned &Entry
= PredicateMap
[Rec
];
538 if (!Rec
->isValueUnset(Name
)) {
539 Predicates
.push_back(Rec
);
540 Entry
= Predicates
.size();
544 PrintFatalError(Rec
->getLoc(), "No " + Name
+
545 " predicate on this operand at all: '" +
546 Rec
->getName() + "'");
550 static void printPredicates(ArrayRef
<const Record
*> Predicates
, StringRef Name
,
552 for (unsigned I
= 0; I
< Predicates
.size(); ++I
) {
553 StringRef Pred
= Predicates
[I
]->getValueAsString(Name
);
554 OS
<< " case " << I
+ 1 << ": {\n"
555 << " // " << Predicates
[I
]->getName() << "\n"
556 << " " << Pred
<< "\n"
561 static void mergeCondAndCode(raw_ostream
&CombinedStream
, StringRef CondStr
,
563 // Remove first indentation and last '&&'.
564 CondStr
= CondStr
.drop_front(6).drop_back(4);
565 CombinedStream
.indent(4) << "if (" << CondStr
<< ") {\n";
566 CombinedStream
<< CodeStr
;
567 CombinedStream
.indent(4) << " return true;\n";
568 CombinedStream
.indent(4) << "} // if\n";
571 void CompressInstEmitter::emitCompressInstEmitter(raw_ostream
&OS
,
573 const Record
*AsmWriter
= Target
.getAsmWriter();
574 if (!AsmWriter
->getValueAsInt("PassSubtarget"))
575 PrintFatalError(AsmWriter
->getLoc(),
576 "'PassSubtarget' is false. SubTargetInfo object is needed "
577 "for target features.\n");
579 StringRef TargetName
= Target
.getName();
581 // Sort entries in CompressPatterns to handle instructions that can have more
582 // than one candidate for compression\uncompression, e.g ADD can be
583 // transformed to a C_ADD or a C_MV. When emitting 'uncompress()' function the
584 // source and destination are flipped and the sort key needs to change
586 llvm::stable_sort(CompressPatterns
, [EType
](const CompressPat
&LHS
,
587 const CompressPat
&RHS
) {
588 if (EType
== EmitterType::Compress
|| EType
== EmitterType::CheckCompress
)
589 return (LHS
.Source
.TheDef
->getName() < RHS
.Source
.TheDef
->getName());
590 return (LHS
.Dest
.TheDef
->getName() < RHS
.Dest
.TheDef
->getName());
593 // A list of MCOperandPredicates for all operands in use, and the reverse map.
594 std::vector
<const Record
*> MCOpPredicates
;
595 DenseMap
<const Record
*, unsigned> MCOpPredicateMap
;
596 // A list of ImmLeaf Predicates for all operands in use, and the reverse map.
597 std::vector
<const Record
*> ImmLeafPredicates
;
598 DenseMap
<const Record
*, unsigned> ImmLeafPredicateMap
;
602 raw_string_ostream
Func(F
);
603 raw_string_ostream
FuncH(FH
);
605 if (EType
== EmitterType::Compress
)
606 OS
<< "\n#ifdef GEN_COMPRESS_INSTR\n"
607 << "#undef GEN_COMPRESS_INSTR\n\n";
608 else if (EType
== EmitterType::Uncompress
)
609 OS
<< "\n#ifdef GEN_UNCOMPRESS_INSTR\n"
610 << "#undef GEN_UNCOMPRESS_INSTR\n\n";
611 else if (EType
== EmitterType::CheckCompress
)
612 OS
<< "\n#ifdef GEN_CHECK_COMPRESS_INSTR\n"
613 << "#undef GEN_CHECK_COMPRESS_INSTR\n\n";
615 if (EType
== EmitterType::Compress
) {
616 FuncH
<< "static bool compressInst(MCInst &OutInst,\n";
617 FuncH
.indent(25) << "const MCInst &MI,\n";
618 FuncH
.indent(25) << "const MCSubtargetInfo &STI) {\n";
619 } else if (EType
== EmitterType::Uncompress
) {
620 FuncH
<< "static bool uncompressInst(MCInst &OutInst,\n";
621 FuncH
.indent(27) << "const MCInst &MI,\n";
622 FuncH
.indent(27) << "const MCSubtargetInfo &STI) {\n";
623 } else if (EType
== EmitterType::CheckCompress
) {
624 FuncH
<< "static bool isCompressibleInst(const MachineInstr &MI,\n";
625 FuncH
.indent(31) << "const " << TargetName
<< "Subtarget &STI) {\n";
628 if (CompressPatterns
.empty()) {
630 OS
.indent(2) << "return false;\n}\n";
631 if (EType
== EmitterType::Compress
)
632 OS
<< "\n#endif //GEN_COMPRESS_INSTR\n";
633 else if (EType
== EmitterType::Uncompress
)
634 OS
<< "\n#endif //GEN_UNCOMPRESS_INSTR\n\n";
635 else if (EType
== EmitterType::CheckCompress
)
636 OS
<< "\n#endif //GEN_CHECK_COMPRESS_INSTR\n\n";
640 std::string CaseString
;
641 raw_string_ostream
CaseStream(CaseString
);
644 CaseStream
<< " switch (MI.getOpcode()) {\n";
645 CaseStream
<< " default: return false;\n";
647 bool CompressOrCheck
=
648 EType
== EmitterType::Compress
|| EType
== EmitterType::CheckCompress
;
649 bool CompressOrUncompress
=
650 EType
== EmitterType::Compress
|| EType
== EmitterType::Uncompress
;
651 std::string ValidatorName
=
653 ? (TargetName
+ "ValidateMCOperandFor" +
654 (EType
== EmitterType::Compress
? "Compress" : "Uncompress"))
658 for (auto &CompressPat
: CompressPatterns
) {
659 if (EType
== EmitterType::Uncompress
&& CompressPat
.IsCompressOnly
)
662 std::string CondString
;
663 std::string CodeString
;
664 raw_string_ostream
CondStream(CondString
);
665 raw_string_ostream
CodeStream(CodeString
);
666 CodeGenInstruction
&Source
=
667 CompressOrCheck
? CompressPat
.Source
: CompressPat
.Dest
;
668 CodeGenInstruction
&Dest
=
669 CompressOrCheck
? CompressPat
.Dest
: CompressPat
.Source
;
670 IndexedMap
<OpData
> SourceOperandMap
= CompressOrCheck
671 ? CompressPat
.SourceOperandMap
672 : CompressPat
.DestOperandMap
;
673 IndexedMap
<OpData
> &DestOperandMap
= CompressOrCheck
674 ? CompressPat
.DestOperandMap
675 : CompressPat
.SourceOperandMap
;
677 CurOp
= Source
.TheDef
->getName();
678 // Check current and previous opcode to decide to continue or end a case.
679 if (CurOp
!= PrevOp
) {
681 CaseStream
.indent(6) << "break;\n } // case " + PrevOp
+ "\n";
682 CaseStream
.indent(4) << "case " + TargetName
+ "::" + CurOp
+ ": {\n";
685 std::set
<std::pair
<bool, StringRef
>> FeaturesSet
;
686 std::set
<std::set
<std::pair
<bool, StringRef
>>> AnyOfFeatureSets
;
687 // Add CompressPat required features.
688 getReqFeatures(FeaturesSet
, AnyOfFeatureSets
, CompressPat
.PatReqFeatures
);
690 // Add Dest instruction required features.
691 std::vector
<const Record
*> ReqFeatures
;
692 std::vector
<const Record
*> RF
=
693 Dest
.TheDef
->getValueAsListOfDefs("Predicates");
694 copy_if(RF
, std::back_inserter(ReqFeatures
), [](const Record
*R
) {
695 return R
->getValueAsBit("AssemblerMatcherPredicate");
697 getReqFeatures(FeaturesSet
, AnyOfFeatureSets
, ReqFeatures
);
699 // Emit checks for all required features.
700 for (auto &Op
: FeaturesSet
) {
701 StringRef Not
= Op
.first
? "!" : "";
702 CondStream
.indent(6) << Not
<< "STI.getFeatureBits()[" << TargetName
703 << "::" << Op
.second
<< "]"
707 // Emit checks for all required feature groups.
708 for (auto &Set
: AnyOfFeatureSets
) {
709 CondStream
.indent(6) << "(";
710 for (auto &Op
: Set
) {
711 bool IsLast
= &Op
== &*Set
.rbegin();
712 StringRef Not
= Op
.first
? "!" : "";
713 CondStream
<< Not
<< "STI.getFeatureBits()[" << TargetName
714 << "::" << Op
.second
<< "]";
716 CondStream
<< " || ";
718 CondStream
<< ") &&\n";
721 // Start Source Inst operands validation.
723 for (OpNo
= 0; OpNo
< Source
.Operands
.size(); ++OpNo
) {
724 if (SourceOperandMap
[OpNo
].TiedOpIdx
!= -1) {
725 if (Source
.Operands
[OpNo
].Rec
->isSubClassOf("RegisterClass"))
727 << "(MI.getOperand(" << OpNo
<< ").isReg()) && (MI.getOperand("
728 << SourceOperandMap
[OpNo
].TiedOpIdx
<< ").isReg()) &&\n"
729 << " (MI.getOperand(" << OpNo
730 << ").getReg() == MI.getOperand("
731 << SourceOperandMap
[OpNo
].TiedOpIdx
<< ").getReg()) &&\n";
733 PrintFatalError("Unexpected tied operand types!\n");
735 // Check for fixed immediates\registers in the source instruction.
736 switch (SourceOperandMap
[OpNo
].Kind
) {
737 case OpData::Operand
:
738 // We don't need to do anything for source instruction operand checks.
742 << "(MI.getOperand(" << OpNo
<< ").isImm()) &&\n"
743 << " (MI.getOperand(" << OpNo
744 << ").getImm() == " << SourceOperandMap
[OpNo
].Data
.Imm
<< ") &&\n";
747 const Record
*Reg
= SourceOperandMap
[OpNo
].Data
.Reg
;
749 << "(MI.getOperand(" << OpNo
<< ").isReg()) &&\n"
750 << " (MI.getOperand(" << OpNo
<< ").getReg() == " << TargetName
751 << "::" << Reg
->getName() << ") &&\n";
756 CodeStream
.indent(6) << "// " << Dest
.AsmString
<< "\n";
757 if (CompressOrUncompress
)
758 CodeStream
.indent(6) << "OutInst.setOpcode(" << TargetName
759 << "::" << Dest
.TheDef
->getName() << ");\n";
761 for (const auto &DestOperand
: Dest
.Operands
) {
762 CodeStream
.indent(6) << "// Operand: " << DestOperand
.Name
<< "\n";
763 switch (DestOperandMap
[OpNo
].Kind
) {
764 case OpData::Operand
: {
765 unsigned OpIdx
= DestOperandMap
[OpNo
].Data
.Operand
;
766 // Check that the operand in the Source instruction fits
767 // the type for the Dest instruction.
768 if (DestOperand
.Rec
->isSubClassOf("RegisterClass") ||
769 DestOperand
.Rec
->isSubClassOf("RegisterOperand")) {
770 auto *ClassRec
= DestOperand
.Rec
->isSubClassOf("RegisterClass")
772 : DestOperand
.Rec
->getValueAsDef("RegClass");
773 // This is a register operand. Check the register class.
774 // Don't check register class if this is a tied operand, it was done
775 // for the operand its tied to.
776 if (DestOperand
.getTiedRegister() == -1)
778 << "(MI.getOperand(" << OpIdx
<< ").isReg()) &&\n"
779 << " (" << TargetName
<< "MCRegisterClasses[" << TargetName
780 << "::" << ClassRec
->getName()
781 << "RegClassID].contains(MI.getOperand(" << OpIdx
782 << ").getReg())) &&\n";
784 if (CompressOrUncompress
)
786 << "OutInst.addOperand(MI.getOperand(" << OpIdx
<< "));\n";
788 // Handling immediate operands.
789 if (CompressOrUncompress
) {
791 getPredicates(MCOpPredicateMap
, MCOpPredicates
, DestOperand
.Rec
,
792 "MCOperandPredicate");
794 << ValidatorName
<< "("
795 << "MI.getOperand(" << OpIdx
<< "), STI, " << Entry
<< ") &&\n";
798 getPredicates(ImmLeafPredicateMap
, ImmLeafPredicates
,
799 DestOperand
.Rec
, "ImmediateCode");
801 << "MI.getOperand(" << OpIdx
<< ").isImm() &&\n";
802 CondStream
.indent(6) << TargetName
<< "ValidateMachineOperand("
803 << "MI.getOperand(" << OpIdx
<< "), &STI, "
804 << Entry
<< ") &&\n";
806 if (CompressOrUncompress
)
808 << "OutInst.addOperand(MI.getOperand(" << OpIdx
<< "));\n";
813 if (CompressOrUncompress
) {
814 unsigned Entry
= getPredicates(MCOpPredicateMap
, MCOpPredicates
,
815 DestOperand
.Rec
, "MCOperandPredicate");
817 << ValidatorName
<< "("
818 << "MCOperand::createImm(" << DestOperandMap
[OpNo
].Data
.Imm
819 << "), STI, " << Entry
<< ") &&\n";
821 unsigned Entry
= getPredicates(ImmLeafPredicateMap
, ImmLeafPredicates
,
822 DestOperand
.Rec
, "ImmediateCode");
825 << "ValidateMachineOperand(MachineOperand::CreateImm("
826 << DestOperandMap
[OpNo
].Data
.Imm
<< "), &STI, " << Entry
829 if (CompressOrUncompress
)
830 CodeStream
.indent(6) << "OutInst.addOperand(MCOperand::createImm("
831 << DestOperandMap
[OpNo
].Data
.Imm
<< "));\n";
834 if (CompressOrUncompress
) {
835 // Fixed register has been validated at pattern validation time.
836 const Record
*Reg
= DestOperandMap
[OpNo
].Data
.Reg
;
838 << "OutInst.addOperand(MCOperand::createReg(" << TargetName
839 << "::" << Reg
->getName() << "));\n";
845 if (CompressOrUncompress
)
846 CodeStream
.indent(6) << "OutInst.setLoc(MI.getLoc());\n";
847 mergeCondAndCode(CaseStream
, CondString
, CodeString
);
850 Func
<< CaseString
<< "\n";
851 // Close brace for the last case.
852 Func
.indent(4) << "} // case " << CurOp
<< "\n";
853 Func
.indent(2) << "} // switch\n";
854 Func
.indent(2) << "return false;\n}\n";
856 if (!MCOpPredicates
.empty()) {
857 OS
<< "static bool " << ValidatorName
<< "(const MCOperand &MCOp,\n"
858 << " const MCSubtargetInfo &STI,\n"
859 << " unsigned PredicateIndex) {\n"
860 << " switch (PredicateIndex) {\n"
862 << " llvm_unreachable(\"Unknown MCOperandPredicate kind\");\n"
865 printPredicates(MCOpPredicates
, "MCOperandPredicate", OS
);
871 if (!ImmLeafPredicates
.empty()) {
872 OS
<< "static bool " << TargetName
873 << "ValidateMachineOperand(const MachineOperand &MO,\n"
874 << " const " << TargetName
<< "Subtarget *Subtarget,\n"
875 << " unsigned PredicateIndex) {\n"
876 << " int64_t Imm = MO.getImm();\n"
877 << " switch (PredicateIndex) {\n"
879 << " llvm_unreachable(\"Unknown ImmLeaf Predicate kind\");\n"
882 printPredicates(ImmLeafPredicates
, "ImmediateCode", OS
);
891 if (EType
== EmitterType::Compress
)
892 OS
<< "\n#endif //GEN_COMPRESS_INSTR\n";
893 else if (EType
== EmitterType::Uncompress
)
894 OS
<< "\n#endif //GEN_UNCOMPRESS_INSTR\n\n";
895 else if (EType
== EmitterType::CheckCompress
)
896 OS
<< "\n#endif //GEN_CHECK_COMPRESS_INSTR\n\n";
899 void CompressInstEmitter::run(raw_ostream
&OS
) {
900 // Process the CompressPat definitions, validating them as we do so.
901 for (const Record
*Pat
: Records
.getAllDerivedDefinitions("CompressPat"))
902 evaluateCompressPat(Pat
);
905 emitSourceFileHeader("Compress instruction Source Fragment", OS
, Records
);
906 // Generate compressInst() function.
907 emitCompressInstEmitter(OS
, EmitterType::Compress
);
908 // Generate uncompressInst() function.
909 emitCompressInstEmitter(OS
, EmitterType::Uncompress
);
910 // Generate isCompressibleInst() function.
911 emitCompressInstEmitter(OS
, EmitterType::CheckCompress
);
914 static TableGen::Emitter::OptClass
<CompressInstEmitter
>
915 X("gen-compress-inst-emitter", "Generate compressed instructions.");