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 "CodeGenInstruction.h"
68 #include "CodeGenRegisters.h"
69 #include "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
<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(CodeGenInstruction
&S
, CodeGenInstruction
&D
,
116 std::vector
<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 RecordKeeper
&Records
;
123 CodeGenTarget Target
;
124 SmallVector
<CompressPat
, 4> CompressPatterns
;
126 void addDagOperandMapping(Record
*Rec
, DagInit
*Dag
, CodeGenInstruction
&Inst
,
127 IndexedMap
<OpData
> &OperandMap
, bool IsSourceInst
);
128 void evaluateCompressPat(Record
*Compress
);
129 void emitCompressInstEmitter(raw_ostream
&OS
, EmitterType EType
);
130 bool validateTypes(Record
*SubType
, Record
*Type
, bool IsSourceInst
);
131 bool validateRegister(Record
*Reg
, Record
*RegClass
);
132 void createDagOperandMapping(Record
*Rec
, StringMap
<unsigned> &SourceOperands
,
133 StringMap
<unsigned> &DestOperands
,
134 DagInit
*SourceDag
, DagInit
*DestDag
,
135 IndexedMap
<OpData
> &SourceOperandMap
);
137 void createInstOperandMapping(Record
*Rec
, DagInit
*SourceDag
,
139 IndexedMap
<OpData
> &SourceOperandMap
,
140 IndexedMap
<OpData
> &DestOperandMap
,
141 StringMap
<unsigned> &SourceOperands
,
142 CodeGenInstruction
&DestInst
);
145 CompressInstEmitter(RecordKeeper
&R
) : Records(R
), Target(R
) {}
147 void run(raw_ostream
&OS
);
149 } // End anonymous namespace.
151 bool CompressInstEmitter::validateRegister(Record
*Reg
, Record
*RegClass
) {
152 assert(Reg
->isSubClassOf("Register") && "Reg record should be a Register");
153 assert(RegClass
->isSubClassOf("RegisterClass") &&
154 "RegClass record should be a RegisterClass");
155 const CodeGenRegisterClass
&RC
= Target
.getRegisterClass(RegClass
);
156 const CodeGenRegister
*R
= Target
.getRegisterByName(Reg
->getName().lower());
157 assert((R
!= nullptr) && "Register not defined!!");
158 return RC
.contains(R
);
161 bool CompressInstEmitter::validateTypes(Record
*DagOpType
, Record
*InstOpType
,
163 if (DagOpType
== InstOpType
)
165 // Only source instruction operands are allowed to not match Input Dag
170 if (DagOpType
->isSubClassOf("RegisterClass") &&
171 InstOpType
->isSubClassOf("RegisterClass")) {
172 const CodeGenRegisterClass
&RC
= Target
.getRegisterClass(InstOpType
);
173 const CodeGenRegisterClass
&SubRC
= Target
.getRegisterClass(DagOpType
);
174 return RC
.hasSubClass(&SubRC
);
177 // At this point either or both types are not registers, reject the pattern.
178 if (DagOpType
->isSubClassOf("RegisterClass") ||
179 InstOpType
->isSubClassOf("RegisterClass"))
182 // Let further validation happen when compress()/uncompress() functions are
184 LLVM_DEBUG(dbgs() << (IsSourceInst
? "Input" : "Output")
185 << " Dag Operand Type: '" << DagOpType
->getName()
187 << "Instruction Operand Type: '" << InstOpType
->getName()
188 << "' can't be checked at pattern validation time!\n");
192 /// The patterns in the Dag contain different types of operands:
193 /// Register operands, e.g.: GPRC:$rs1; Fixed registers, e.g: X1; Immediate
194 /// operands, e.g.: simm6:$imm; Fixed immediate operands, e.g.: 0. This function
195 /// maps Dag operands to its corresponding instruction operands. For register
196 /// operands and fixed registers it expects the Dag operand type to be contained
197 /// in the instantiated instruction operand type. For immediate operands and
198 /// immediates no validation checks are enforced at pattern validation time.
199 void CompressInstEmitter::addDagOperandMapping(Record
*Rec
, DagInit
*Dag
,
200 CodeGenInstruction
&Inst
,
201 IndexedMap
<OpData
> &OperandMap
,
203 // TiedCount keeps track of the number of operands skipped in Inst
204 // operands list to get to the corresponding Dag operand. This is
205 // necessary because the number of operands in Inst might be greater
206 // than number of operands in the Dag due to how tied operands
208 unsigned TiedCount
= 0;
209 for (unsigned I
= 0, E
= Inst
.Operands
.size(); I
!= E
; ++I
) {
210 int TiedOpIdx
= Inst
.Operands
[I
].getTiedRegister();
211 if (-1 != TiedOpIdx
) {
212 // Set the entry in OperandMap for the tied operand we're skipping.
213 OperandMap
[I
].Kind
= OperandMap
[TiedOpIdx
].Kind
;
214 OperandMap
[I
].Data
= OperandMap
[TiedOpIdx
].Data
;
218 if (DefInit
*DI
= dyn_cast
<DefInit
>(Dag
->getArg(I
- TiedCount
))) {
219 if (DI
->getDef()->isSubClassOf("Register")) {
220 // Check if the fixed register belongs to the Register class.
221 if (!validateRegister(DI
->getDef(), Inst
.Operands
[I
].Rec
))
222 PrintFatalError(Rec
->getLoc(),
223 "Error in Dag '" + Dag
->getAsString() +
224 "'Register: '" + DI
->getDef()->getName() +
225 "' is not in register class '" +
226 Inst
.Operands
[I
].Rec
->getName() + "'");
227 OperandMap
[I
].Kind
= OpData::Reg
;
228 OperandMap
[I
].Data
.Reg
= DI
->getDef();
231 // Validate that Dag operand type matches the type defined in the
232 // corresponding instruction. Operands in the input Dag pattern are
233 // allowed to be a subclass of the type specified in corresponding
234 // instruction operand instead of being an exact match.
235 if (!validateTypes(DI
->getDef(), Inst
.Operands
[I
].Rec
, IsSourceInst
))
236 PrintFatalError(Rec
->getLoc(),
237 "Error in Dag '" + Dag
->getAsString() + "'. Operand '" +
238 Dag
->getArgNameStr(I
- TiedCount
) + "' has type '" +
239 DI
->getDef()->getName() +
240 "' which does not match the type '" +
241 Inst
.Operands
[I
].Rec
->getName() +
242 "' in the corresponding instruction operand!");
244 OperandMap
[I
].Kind
= OpData::Operand
;
245 } else if (IntInit
*II
= dyn_cast
<IntInit
>(Dag
->getArg(I
- TiedCount
))) {
246 // Validate that corresponding instruction operand expects an immediate.
247 if (Inst
.Operands
[I
].Rec
->isSubClassOf("RegisterClass"))
250 "Error in Dag '" + Dag
->getAsString() + "' Found immediate: '" +
252 "' but corresponding instruction operand expected a register!");
253 // No pattern validation check possible for values of fixed immediate.
254 OperandMap
[I
].Kind
= OpData::Imm
;
255 OperandMap
[I
].Data
.Imm
= II
->getValue();
257 dbgs() << " Found immediate '" << II
->getValue() << "' at "
258 << (IsSourceInst
? "input " : "output ")
259 << "Dag. No validation time check possible for values of "
260 "fixed immediate.\n");
262 llvm_unreachable("Unhandled CompressPat argument type!");
266 // Verify the Dag operand count is enough to build an instruction.
267 static bool verifyDagOpCount(CodeGenInstruction
&Inst
, DagInit
*Dag
,
269 if (Dag
->getNumArgs() == Inst
.Operands
.size())
271 // Source instructions are non compressed instructions and don't have tied
274 PrintFatalError(Inst
.TheDef
->getLoc(),
275 "Input operands for Inst '" + Inst
.TheDef
->getName() +
276 "' and input Dag operand count mismatch");
277 // The Dag can't have more arguments than the Instruction.
278 if (Dag
->getNumArgs() > Inst
.Operands
.size())
279 PrintFatalError(Inst
.TheDef
->getLoc(),
280 "Inst '" + Inst
.TheDef
->getName() +
281 "' and Dag operand count mismatch");
283 // The Instruction might have tied operands so the Dag might have
284 // a fewer operand count.
285 unsigned RealCount
= Inst
.Operands
.size();
286 for (const auto &Operand
: Inst
.Operands
)
287 if (Operand
.getTiedRegister() != -1)
290 if (Dag
->getNumArgs() != RealCount
)
291 PrintFatalError(Inst
.TheDef
->getLoc(),
292 "Inst '" + Inst
.TheDef
->getName() +
293 "' and Dag operand count mismatch");
297 static bool validateArgsTypes(Init
*Arg1
, Init
*Arg2
) {
298 return cast
<DefInit
>(Arg1
)->getDef() == cast
<DefInit
>(Arg2
)->getDef();
301 // Creates a mapping between the operand name in the Dag (e.g. $rs1) and
302 // its index in the list of Dag operands and checks that operands with the same
303 // name have the same types. For example in 'C_ADD $rs1, $rs2' we generate the
304 // mapping $rs1 --> 0, $rs2 ---> 1. If the operand appears twice in the (tied)
305 // same Dag we use the last occurrence for indexing.
306 void CompressInstEmitter::createDagOperandMapping(
307 Record
*Rec
, StringMap
<unsigned> &SourceOperands
,
308 StringMap
<unsigned> &DestOperands
, DagInit
*SourceDag
, DagInit
*DestDag
,
309 IndexedMap
<OpData
> &SourceOperandMap
) {
310 for (unsigned I
= 0; I
< DestDag
->getNumArgs(); ++I
) {
311 // Skip fixed immediates and registers, they were handled in
312 // addDagOperandMapping.
313 if ("" == DestDag
->getArgNameStr(I
))
315 DestOperands
[DestDag
->getArgNameStr(I
)] = I
;
318 for (unsigned I
= 0; I
< SourceDag
->getNumArgs(); ++I
) {
319 // Skip fixed immediates and registers, they were handled in
320 // addDagOperandMapping.
321 if ("" == SourceDag
->getArgNameStr(I
))
324 StringMap
<unsigned>::iterator It
=
325 SourceOperands
.find(SourceDag
->getArgNameStr(I
));
326 if (It
!= SourceOperands
.end()) {
327 // Operand sharing the same name in the Dag should be mapped as tied.
328 SourceOperandMap
[I
].TiedOpIdx
= It
->getValue();
329 if (!validateArgsTypes(SourceDag
->getArg(It
->getValue()),
330 SourceDag
->getArg(I
)))
331 PrintFatalError(Rec
->getLoc(),
332 "Input Operand '" + SourceDag
->getArgNameStr(I
) +
333 "' has a mismatched tied operand!\n");
335 It
= DestOperands
.find(SourceDag
->getArgNameStr(I
));
336 if (It
== DestOperands
.end())
337 PrintFatalError(Rec
->getLoc(), "Operand " + SourceDag
->getArgNameStr(I
) +
338 " defined in Input Dag but not used in"
340 // Input Dag operand types must match output Dag operand type.
341 if (!validateArgsTypes(DestDag
->getArg(It
->getValue()),
342 SourceDag
->getArg(I
)))
343 PrintFatalError(Rec
->getLoc(), "Type mismatch between Input and "
344 "Output Dag operand '" +
345 SourceDag
->getArgNameStr(I
) + "'!");
346 SourceOperands
[SourceDag
->getArgNameStr(I
)] = I
;
350 /// Map operand names in the Dag to their index in both corresponding input and
351 /// output instructions. Validate that operands defined in the input are
352 /// used in the output pattern while populating the maps.
353 void CompressInstEmitter::createInstOperandMapping(
354 Record
*Rec
, DagInit
*SourceDag
, DagInit
*DestDag
,
355 IndexedMap
<OpData
> &SourceOperandMap
, IndexedMap
<OpData
> &DestOperandMap
,
356 StringMap
<unsigned> &SourceOperands
, CodeGenInstruction
&DestInst
) {
357 // TiedCount keeps track of the number of operands skipped in Inst
358 // operands list to get to the corresponding Dag operand.
359 unsigned TiedCount
= 0;
360 LLVM_DEBUG(dbgs() << " Operand mapping:\n Source Dest\n");
361 for (unsigned I
= 0, E
= DestInst
.Operands
.size(); I
!= E
; ++I
) {
362 int TiedInstOpIdx
= DestInst
.Operands
[I
].getTiedRegister();
363 if (TiedInstOpIdx
!= -1) {
365 DestOperandMap
[I
].Data
= DestOperandMap
[TiedInstOpIdx
].Data
;
366 DestOperandMap
[I
].Kind
= DestOperandMap
[TiedInstOpIdx
].Kind
;
367 if (DestOperandMap
[I
].Kind
== OpData::Operand
)
368 // No need to fill the SourceOperandMap here since it was mapped to
369 // destination operand 'TiedInstOpIdx' in a previous iteration.
370 LLVM_DEBUG(dbgs() << " " << DestOperandMap
[I
].Data
.Operand
372 << " Dest operand tied with operand '"
373 << TiedInstOpIdx
<< "'\n");
376 // Skip fixed immediates and registers, they were handled in
377 // addDagOperandMapping.
378 if (DestOperandMap
[I
].Kind
!= OpData::Operand
)
381 unsigned DagArgIdx
= I
- TiedCount
;
382 StringMap
<unsigned>::iterator SourceOp
=
383 SourceOperands
.find(DestDag
->getArgNameStr(DagArgIdx
));
384 if (SourceOp
== SourceOperands
.end())
385 PrintFatalError(Rec
->getLoc(),
386 "Output Dag operand '" +
387 DestDag
->getArgNameStr(DagArgIdx
) +
388 "' has no matching input Dag operand.");
390 assert(DestDag
->getArgNameStr(DagArgIdx
) ==
391 SourceDag
->getArgNameStr(SourceOp
->getValue()) &&
392 "Incorrect operand mapping detected!\n");
393 DestOperandMap
[I
].Data
.Operand
= SourceOp
->getValue();
394 SourceOperandMap
[SourceOp
->getValue()].Data
.Operand
= I
;
395 LLVM_DEBUG(dbgs() << " " << SourceOp
->getValue() << " ====> " << I
400 /// Validates the CompressPattern and create operand mapping.
401 /// These are the checks to validate a CompressPat pattern declarations.
402 /// Error out with message under these conditions:
403 /// - Dag Input opcode is an expanded instruction and Dag Output opcode is a
404 /// compressed instruction.
405 /// - Operands in Dag Input must be all used in Dag Output.
406 /// Register Operand type in Dag Input Type must be contained in the
407 /// corresponding Source Instruction type.
408 /// - Register Operand type in Dag Input must be the same as in Dag Ouput.
409 /// - Register Operand type in Dag Output must be the same as the
410 /// corresponding Destination Inst type.
411 /// - Immediate Operand type in Dag Input must be the same as in Dag Ouput.
412 /// - Immediate Operand type in Dag Ouput must be the same as the corresponding
413 /// Destination Instruction type.
414 /// - Fixed register must be contained in the corresponding Source Instruction
416 /// - Fixed register must be contained in the corresponding Destination
417 /// Instruction type.
418 /// Warning message printed under these conditions:
419 /// - Fixed immediate in Dag Input or Dag Ouput cannot be checked at this time
420 /// and generate warning.
421 /// - Immediate operand type in Dag Input differs from the corresponding Source
422 /// Instruction type and generate a warning.
423 void CompressInstEmitter::evaluateCompressPat(Record
*Rec
) {
424 // Validate input Dag operands.
425 DagInit
*SourceDag
= Rec
->getValueAsDag("Input");
426 assert(SourceDag
&& "Missing 'Input' in compress pattern!");
427 LLVM_DEBUG(dbgs() << "Input: " << *SourceDag
<< "\n");
429 // Checking we are transforming from compressed to uncompressed instructions.
430 Record
*SourceOperator
= SourceDag
->getOperatorAsDef(Rec
->getLoc());
431 CodeGenInstruction
SourceInst(SourceOperator
);
432 verifyDagOpCount(SourceInst
, SourceDag
, true);
434 // Validate output Dag operands.
435 DagInit
*DestDag
= Rec
->getValueAsDag("Output");
436 assert(DestDag
&& "Missing 'Output' in compress pattern!");
437 LLVM_DEBUG(dbgs() << "Output: " << *DestDag
<< "\n");
439 Record
*DestOperator
= DestDag
->getOperatorAsDef(Rec
->getLoc());
440 CodeGenInstruction
DestInst(DestOperator
);
441 verifyDagOpCount(DestInst
, DestDag
, false);
443 if (SourceOperator
->getValueAsInt("Size") <=
444 DestOperator
->getValueAsInt("Size"))
447 "Compressed instruction '" + DestOperator
->getName() +
448 "'is not strictly smaller than the uncompressed instruction '" +
449 SourceOperator
->getName() + "' !");
451 // Fill the mapping from the source to destination instructions.
453 IndexedMap
<OpData
> SourceOperandMap
;
454 SourceOperandMap
.grow(SourceInst
.Operands
.size());
455 // Create a mapping between source Dag operands and source Inst operands.
456 addDagOperandMapping(Rec
, SourceDag
, SourceInst
, SourceOperandMap
,
457 /*IsSourceInst*/ true);
459 IndexedMap
<OpData
> DestOperandMap
;
460 DestOperandMap
.grow(DestInst
.Operands
.size());
461 // Create a mapping between destination Dag operands and destination Inst
463 addDagOperandMapping(Rec
, DestDag
, DestInst
, DestOperandMap
,
464 /*IsSourceInst*/ false);
466 StringMap
<unsigned> SourceOperands
;
467 StringMap
<unsigned> DestOperands
;
468 createDagOperandMapping(Rec
, SourceOperands
, DestOperands
, SourceDag
, DestDag
,
470 // Create operand mapping between the source and destination instructions.
471 createInstOperandMapping(Rec
, SourceDag
, DestDag
, SourceOperandMap
,
472 DestOperandMap
, SourceOperands
, DestInst
);
474 // Get the target features for the CompressPat.
475 std::vector
<Record
*> PatReqFeatures
;
476 std::vector
<Record
*> RF
= Rec
->getValueAsListOfDefs("Predicates");
477 copy_if(RF
, std::back_inserter(PatReqFeatures
), [](Record
*R
) {
478 return R
->getValueAsBit("AssemblerMatcherPredicate");
481 CompressPatterns
.push_back(CompressPat(SourceInst
, DestInst
, PatReqFeatures
,
482 SourceOperandMap
, DestOperandMap
,
483 Rec
->getValueAsBit("isCompressOnly")));
487 getReqFeatures(std::set
<std::pair
<bool, StringRef
>> &FeaturesSet
,
488 std::set
<std::set
<std::pair
<bool, StringRef
>>> &AnyOfFeatureSets
,
489 const std::vector
<Record
*> &ReqFeatures
) {
490 for (auto &R
: ReqFeatures
) {
491 const DagInit
*D
= R
->getValueAsDag("AssemblerCondDag");
492 std::string CombineType
= D
->getOperator()->getAsString();
493 if (CombineType
!= "any_of" && CombineType
!= "all_of")
494 PrintFatalError(R
->getLoc(), "Invalid AssemblerCondDag!");
495 if (D
->getNumArgs() == 0)
496 PrintFatalError(R
->getLoc(), "Invalid AssemblerCondDag!");
497 bool IsOr
= CombineType
== "any_of";
498 std::set
<std::pair
<bool, StringRef
>> AnyOfSet
;
500 for (auto *Arg
: D
->getArgs()) {
502 if (auto *NotArg
= dyn_cast
<DagInit
>(Arg
)) {
503 if (NotArg
->getOperator()->getAsString() != "not" ||
504 NotArg
->getNumArgs() != 1)
505 PrintFatalError(R
->getLoc(), "Invalid AssemblerCondDag!");
506 Arg
= NotArg
->getArg(0);
509 if (!isa
<DefInit
>(Arg
) ||
510 !cast
<DefInit
>(Arg
)->getDef()->isSubClassOf("SubtargetFeature"))
511 PrintFatalError(R
->getLoc(), "Invalid AssemblerCondDag!");
513 AnyOfSet
.insert({IsNot
, cast
<DefInit
>(Arg
)->getDef()->getName()});
515 FeaturesSet
.insert({IsNot
, cast
<DefInit
>(Arg
)->getDef()->getName()});
519 AnyOfFeatureSets
.insert(AnyOfSet
);
523 static unsigned getPredicates(DenseMap
<const Record
*, unsigned> &PredicateMap
,
524 std::vector
<const Record
*> &Predicates
,
525 Record
*Rec
, StringRef Name
) {
526 unsigned &Entry
= PredicateMap
[Rec
];
530 if (!Rec
->isValueUnset(Name
)) {
531 Predicates
.push_back(Rec
);
532 Entry
= Predicates
.size();
536 PrintFatalError(Rec
->getLoc(), "No " + Name
+
537 " predicate on this operand at all: '" +
538 Rec
->getName() + "'");
542 static void printPredicates(const std::vector
<const Record
*> &Predicates
,
543 StringRef Name
, raw_ostream
&OS
) {
544 for (unsigned I
= 0; I
< Predicates
.size(); ++I
) {
545 StringRef Pred
= Predicates
[I
]->getValueAsString(Name
);
546 OS
<< " case " << I
+ 1 << ": {\n"
547 << " // " << Predicates
[I
]->getName() << "\n"
548 << " " << Pred
<< "\n"
553 static void mergeCondAndCode(raw_ostream
&CombinedStream
, StringRef CondStr
,
555 // Remove first indentation and last '&&'.
556 CondStr
= CondStr
.drop_front(6).drop_back(4);
557 CombinedStream
.indent(4) << "if (" << CondStr
<< ") {\n";
558 CombinedStream
<< CodeStr
;
559 CombinedStream
.indent(4) << " return true;\n";
560 CombinedStream
.indent(4) << "} // if\n";
563 void CompressInstEmitter::emitCompressInstEmitter(raw_ostream
&OS
,
565 Record
*AsmWriter
= Target
.getAsmWriter();
566 if (!AsmWriter
->getValueAsInt("PassSubtarget"))
567 PrintFatalError(AsmWriter
->getLoc(),
568 "'PassSubtarget' is false. SubTargetInfo object is needed "
569 "for target features.\n");
571 StringRef TargetName
= Target
.getName();
573 // Sort entries in CompressPatterns to handle instructions that can have more
574 // than one candidate for compression\uncompression, e.g ADD can be
575 // transformed to a C_ADD or a C_MV. When emitting 'uncompress()' function the
576 // source and destination are flipped and the sort key needs to change
578 llvm::stable_sort(CompressPatterns
, [EType
](const CompressPat
&LHS
,
579 const CompressPat
&RHS
) {
580 if (EType
== EmitterType::Compress
|| EType
== EmitterType::CheckCompress
)
581 return (LHS
.Source
.TheDef
->getName() < RHS
.Source
.TheDef
->getName());
582 return (LHS
.Dest
.TheDef
->getName() < RHS
.Dest
.TheDef
->getName());
585 // A list of MCOperandPredicates for all operands in use, and the reverse map.
586 std::vector
<const Record
*> MCOpPredicates
;
587 DenseMap
<const Record
*, unsigned> MCOpPredicateMap
;
588 // A list of ImmLeaf Predicates for all operands in use, and the reverse map.
589 std::vector
<const Record
*> ImmLeafPredicates
;
590 DenseMap
<const Record
*, unsigned> ImmLeafPredicateMap
;
594 raw_string_ostream
Func(F
);
595 raw_string_ostream
FuncH(FH
);
597 if (EType
== EmitterType::Compress
)
598 OS
<< "\n#ifdef GEN_COMPRESS_INSTR\n"
599 << "#undef GEN_COMPRESS_INSTR\n\n";
600 else if (EType
== EmitterType::Uncompress
)
601 OS
<< "\n#ifdef GEN_UNCOMPRESS_INSTR\n"
602 << "#undef GEN_UNCOMPRESS_INSTR\n\n";
603 else if (EType
== EmitterType::CheckCompress
)
604 OS
<< "\n#ifdef GEN_CHECK_COMPRESS_INSTR\n"
605 << "#undef GEN_CHECK_COMPRESS_INSTR\n\n";
607 if (EType
== EmitterType::Compress
) {
608 FuncH
<< "static bool compressInst(MCInst &OutInst,\n";
609 FuncH
.indent(25) << "const MCInst &MI,\n";
610 FuncH
.indent(25) << "const MCSubtargetInfo &STI) {\n";
611 } else if (EType
== EmitterType::Uncompress
) {
612 FuncH
<< "static bool uncompressInst(MCInst &OutInst,\n";
613 FuncH
.indent(27) << "const MCInst &MI,\n";
614 FuncH
.indent(27) << "const MCSubtargetInfo &STI) {\n";
615 } else if (EType
== EmitterType::CheckCompress
) {
616 FuncH
<< "static bool isCompressibleInst(const MachineInstr &MI,\n";
617 FuncH
.indent(31) << "const " << TargetName
<< "Subtarget &STI) {\n";
620 if (CompressPatterns
.empty()) {
622 OS
.indent(2) << "return false;\n}\n";
623 if (EType
== EmitterType::Compress
)
624 OS
<< "\n#endif //GEN_COMPRESS_INSTR\n";
625 else if (EType
== EmitterType::Uncompress
)
626 OS
<< "\n#endif //GEN_UNCOMPRESS_INSTR\n\n";
627 else if (EType
== EmitterType::CheckCompress
)
628 OS
<< "\n#endif //GEN_CHECK_COMPRESS_INSTR\n\n";
632 std::string CaseString
;
633 raw_string_ostream
CaseStream(CaseString
);
636 CaseStream
<< " switch (MI.getOpcode()) {\n";
637 CaseStream
<< " default: return false;\n";
639 bool CompressOrCheck
=
640 EType
== EmitterType::Compress
|| EType
== EmitterType::CheckCompress
;
641 bool CompressOrUncompress
=
642 EType
== EmitterType::Compress
|| EType
== EmitterType::Uncompress
;
643 std::string ValidatorName
=
645 ? (TargetName
+ "ValidateMCOperandFor" +
646 (EType
== EmitterType::Compress
? "Compress" : "Uncompress"))
650 for (auto &CompressPat
: CompressPatterns
) {
651 if (EType
== EmitterType::Uncompress
&& CompressPat
.IsCompressOnly
)
654 std::string CondString
;
655 std::string CodeString
;
656 raw_string_ostream
CondStream(CondString
);
657 raw_string_ostream
CodeStream(CodeString
);
658 CodeGenInstruction
&Source
=
659 CompressOrCheck
? CompressPat
.Source
: CompressPat
.Dest
;
660 CodeGenInstruction
&Dest
=
661 CompressOrCheck
? CompressPat
.Dest
: CompressPat
.Source
;
662 IndexedMap
<OpData
> SourceOperandMap
= CompressOrCheck
663 ? CompressPat
.SourceOperandMap
664 : CompressPat
.DestOperandMap
;
665 IndexedMap
<OpData
> &DestOperandMap
= CompressOrCheck
666 ? CompressPat
.DestOperandMap
667 : CompressPat
.SourceOperandMap
;
669 CurOp
= Source
.TheDef
->getName();
670 // Check current and previous opcode to decide to continue or end a case.
671 if (CurOp
!= PrevOp
) {
673 CaseStream
.indent(6) << "break;\n } // case " + PrevOp
+ "\n";
674 CaseStream
.indent(4) << "case " + TargetName
+ "::" + CurOp
+ ": {\n";
677 std::set
<std::pair
<bool, StringRef
>> FeaturesSet
;
678 std::set
<std::set
<std::pair
<bool, StringRef
>>> AnyOfFeatureSets
;
679 // Add CompressPat required features.
680 getReqFeatures(FeaturesSet
, AnyOfFeatureSets
, CompressPat
.PatReqFeatures
);
682 // Add Dest instruction required features.
683 std::vector
<Record
*> ReqFeatures
;
684 std::vector
<Record
*> RF
= Dest
.TheDef
->getValueAsListOfDefs("Predicates");
685 copy_if(RF
, std::back_inserter(ReqFeatures
), [](Record
*R
) {
686 return R
->getValueAsBit("AssemblerMatcherPredicate");
688 getReqFeatures(FeaturesSet
, AnyOfFeatureSets
, ReqFeatures
);
690 // Emit checks for all required features.
691 for (auto &Op
: FeaturesSet
) {
692 StringRef Not
= Op
.first
? "!" : "";
693 CondStream
.indent(6) << Not
<< "STI.getFeatureBits()[" << TargetName
694 << "::" << Op
.second
<< "]"
698 // Emit checks for all required feature groups.
699 for (auto &Set
: AnyOfFeatureSets
) {
700 CondStream
.indent(6) << "(";
701 for (auto &Op
: Set
) {
702 bool IsLast
= &Op
== &*Set
.rbegin();
703 StringRef Not
= Op
.first
? "!" : "";
704 CondStream
<< Not
<< "STI.getFeatureBits()[" << TargetName
705 << "::" << Op
.second
<< "]";
707 CondStream
<< " || ";
709 CondStream
<< ") &&\n";
712 // Start Source Inst operands validation.
714 for (OpNo
= 0; OpNo
< Source
.Operands
.size(); ++OpNo
) {
715 if (SourceOperandMap
[OpNo
].TiedOpIdx
!= -1) {
716 if (Source
.Operands
[OpNo
].Rec
->isSubClassOf("RegisterClass"))
718 << "(MI.getOperand(" << OpNo
<< ").isReg()) && (MI.getOperand("
719 << SourceOperandMap
[OpNo
].TiedOpIdx
<< ").isReg()) &&\n"
720 << " (MI.getOperand(" << OpNo
721 << ").getReg() == MI.getOperand("
722 << SourceOperandMap
[OpNo
].TiedOpIdx
<< ").getReg()) &&\n";
724 PrintFatalError("Unexpected tied operand types!\n");
726 // Check for fixed immediates\registers in the source instruction.
727 switch (SourceOperandMap
[OpNo
].Kind
) {
728 case OpData::Operand
:
729 // We don't need to do anything for source instruction operand checks.
733 << "(MI.getOperand(" << OpNo
<< ").isImm()) &&\n"
734 << " (MI.getOperand(" << OpNo
735 << ").getImm() == " << SourceOperandMap
[OpNo
].Data
.Imm
<< ") &&\n";
738 Record
*Reg
= SourceOperandMap
[OpNo
].Data
.Reg
;
740 << "(MI.getOperand(" << OpNo
<< ").isReg()) &&\n"
741 << " (MI.getOperand(" << OpNo
<< ").getReg() == " << TargetName
742 << "::" << Reg
->getName() << ") &&\n";
747 CodeStream
.indent(6) << "// " << Dest
.AsmString
<< "\n";
748 if (CompressOrUncompress
)
749 CodeStream
.indent(6) << "OutInst.setOpcode(" << TargetName
750 << "::" << Dest
.TheDef
->getName() << ");\n";
752 for (const auto &DestOperand
: Dest
.Operands
) {
753 CodeStream
.indent(6) << "// Operand: " << DestOperand
.Name
<< "\n";
754 switch (DestOperandMap
[OpNo
].Kind
) {
755 case OpData::Operand
: {
756 unsigned OpIdx
= DestOperandMap
[OpNo
].Data
.Operand
;
757 // Check that the operand in the Source instruction fits
758 // the type for the Dest instruction.
759 if (DestOperand
.Rec
->isSubClassOf("RegisterClass") ||
760 DestOperand
.Rec
->isSubClassOf("RegisterOperand")) {
761 auto *ClassRec
= DestOperand
.Rec
->isSubClassOf("RegisterClass")
763 : DestOperand
.Rec
->getValueAsDef("RegClass");
764 // This is a register operand. Check the register class.
765 // Don't check register class if this is a tied operand, it was done
766 // for the operand its tied to.
767 if (DestOperand
.getTiedRegister() == -1)
769 << "(MI.getOperand(" << OpIdx
<< ").isReg()) &&\n"
770 << " (" << TargetName
<< "MCRegisterClasses[" << TargetName
771 << "::" << ClassRec
->getName()
772 << "RegClassID].contains(MI.getOperand(" << OpIdx
773 << ").getReg())) &&\n";
775 if (CompressOrUncompress
)
777 << "OutInst.addOperand(MI.getOperand(" << OpIdx
<< "));\n";
779 // Handling immediate operands.
780 if (CompressOrUncompress
) {
782 getPredicates(MCOpPredicateMap
, MCOpPredicates
, DestOperand
.Rec
,
783 "MCOperandPredicate");
785 << ValidatorName
<< "("
786 << "MI.getOperand(" << OpIdx
<< "), STI, " << Entry
<< ") &&\n";
789 getPredicates(ImmLeafPredicateMap
, ImmLeafPredicates
,
790 DestOperand
.Rec
, "ImmediateCode");
792 << "MI.getOperand(" << OpIdx
<< ").isImm() &&\n";
793 CondStream
.indent(6) << TargetName
<< "ValidateMachineOperand("
794 << "MI.getOperand(" << OpIdx
<< "), &STI, "
795 << Entry
<< ") &&\n";
797 if (CompressOrUncompress
)
799 << "OutInst.addOperand(MI.getOperand(" << OpIdx
<< "));\n";
804 if (CompressOrUncompress
) {
805 unsigned Entry
= getPredicates(MCOpPredicateMap
, MCOpPredicates
,
806 DestOperand
.Rec
, "MCOperandPredicate");
808 << ValidatorName
<< "("
809 << "MCOperand::createImm(" << DestOperandMap
[OpNo
].Data
.Imm
810 << "), STI, " << Entry
<< ") &&\n";
812 unsigned Entry
= getPredicates(ImmLeafPredicateMap
, ImmLeafPredicates
,
813 DestOperand
.Rec
, "ImmediateCode");
816 << "ValidateMachineOperand(MachineOperand::CreateImm("
817 << DestOperandMap
[OpNo
].Data
.Imm
<< "), &STI, " << Entry
820 if (CompressOrUncompress
)
821 CodeStream
.indent(6) << "OutInst.addOperand(MCOperand::createImm("
822 << DestOperandMap
[OpNo
].Data
.Imm
<< "));\n";
825 if (CompressOrUncompress
) {
826 // Fixed register has been validated at pattern validation time.
827 Record
*Reg
= DestOperandMap
[OpNo
].Data
.Reg
;
829 << "OutInst.addOperand(MCOperand::createReg(" << TargetName
830 << "::" << Reg
->getName() << "));\n";
836 if (CompressOrUncompress
)
837 CodeStream
.indent(6) << "OutInst.setLoc(MI.getLoc());\n";
838 mergeCondAndCode(CaseStream
, CondStream
.str(), CodeStream
.str());
841 Func
<< CaseStream
.str() << "\n";
842 // Close brace for the last case.
843 Func
.indent(4) << "} // case " << CurOp
<< "\n";
844 Func
.indent(2) << "} // switch\n";
845 Func
.indent(2) << "return false;\n}\n";
847 if (!MCOpPredicates
.empty()) {
848 OS
<< "static bool " << ValidatorName
<< "(const MCOperand &MCOp,\n"
849 << " const MCSubtargetInfo &STI,\n"
850 << " unsigned PredicateIndex) {\n"
851 << " switch (PredicateIndex) {\n"
853 << " llvm_unreachable(\"Unknown MCOperandPredicate kind\");\n"
856 printPredicates(MCOpPredicates
, "MCOperandPredicate", OS
);
862 if (!ImmLeafPredicates
.empty()) {
863 OS
<< "static bool " << TargetName
864 << "ValidateMachineOperand(const MachineOperand &MO,\n"
865 << " const " << TargetName
<< "Subtarget *Subtarget,\n"
866 << " unsigned PredicateIndex) {\n"
867 << " int64_t Imm = MO.getImm();\n"
868 << " switch (PredicateIndex) {\n"
870 << " llvm_unreachable(\"Unknown ImmLeaf Predicate kind\");\n"
873 printPredicates(ImmLeafPredicates
, "ImmediateCode", OS
);
882 if (EType
== EmitterType::Compress
)
883 OS
<< "\n#endif //GEN_COMPRESS_INSTR\n";
884 else if (EType
== EmitterType::Uncompress
)
885 OS
<< "\n#endif //GEN_UNCOMPRESS_INSTR\n\n";
886 else if (EType
== EmitterType::CheckCompress
)
887 OS
<< "\n#endif //GEN_CHECK_COMPRESS_INSTR\n\n";
890 void CompressInstEmitter::run(raw_ostream
&OS
) {
891 std::vector
<Record
*> Insts
= Records
.getAllDerivedDefinitions("CompressPat");
893 // Process the CompressPat definitions, validating them as we do so.
894 for (unsigned I
= 0, E
= Insts
.size(); I
!= E
; ++I
)
895 evaluateCompressPat(Insts
[I
]);
898 emitSourceFileHeader("Compress instruction Source Fragment", OS
, Records
);
899 // Generate compressInst() function.
900 emitCompressInstEmitter(OS
, EmitterType::Compress
);
901 // Generate uncompressInst() function.
902 emitCompressInstEmitter(OS
, EmitterType::Uncompress
);
903 // Generate isCompressibleInst() function.
904 emitCompressInstEmitter(OS
, EmitterType::CheckCompress
);
907 static TableGen::Emitter::OptClass
<CompressInstEmitter
>
908 X("gen-compress-inst-emitter", "Generate compressed instructions.");