xref: /llvm-project/llvm/utils/TableGen/CompressInstEmitter.cpp (revision 726cfc67b69633119279a6369263491421861b1d)
124d1673cSZi Xuan Wu //===-------- CompressInstEmitter.cpp - Generator for Compression ---------===//
224d1673cSZi Xuan Wu //
324d1673cSZi Xuan Wu // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
424d1673cSZi Xuan Wu // See https://llvm.org/LICENSE.txt for license information.
524d1673cSZi Xuan Wu // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
624d1673cSZi Xuan Wu //
724d1673cSZi Xuan Wu // CompressInstEmitter implements a tablegen-driven CompressPat based
824d1673cSZi Xuan Wu // Instruction Compression mechanism.
924d1673cSZi Xuan Wu //
1024d1673cSZi Xuan Wu //===----------------------------------------------------------------------===//
1124d1673cSZi Xuan Wu //
1224d1673cSZi Xuan Wu // CompressInstEmitter implements a tablegen-driven CompressPat Instruction
1324d1673cSZi Xuan Wu // Compression mechanism for generating compressed instructions from the
1424d1673cSZi Xuan Wu // expanded instruction form.
1524d1673cSZi Xuan Wu 
1624d1673cSZi Xuan Wu // This tablegen backend processes CompressPat declarations in a
1724d1673cSZi Xuan Wu // td file and generates all the required checks to validate the pattern
1824d1673cSZi Xuan Wu // declarations; validate the input and output operands to generate the correct
1924d1673cSZi Xuan Wu // compressed instructions. The checks include validating different types of
2024d1673cSZi Xuan Wu // operands; register operands, immediate operands, fixed register and fixed
2124d1673cSZi Xuan Wu // immediate inputs.
2224d1673cSZi Xuan Wu //
2324d1673cSZi Xuan Wu // Example:
2424d1673cSZi Xuan Wu // /// Defines a Pat match between compressed and uncompressed instruction.
2524d1673cSZi Xuan Wu // /// The relationship and helper function generation are handled by
2624d1673cSZi Xuan Wu // /// CompressInstEmitter backend.
2724d1673cSZi Xuan Wu // class CompressPat<dag input, dag output, list<Predicate> predicates = []> {
2824d1673cSZi Xuan Wu //   /// Uncompressed instruction description.
2924d1673cSZi Xuan Wu //   dag Input = input;
3024d1673cSZi Xuan Wu //   /// Compressed instruction description.
3124d1673cSZi Xuan Wu //   dag Output = output;
3224d1673cSZi Xuan Wu //   /// Predicates that must be true for this to match.
3324d1673cSZi Xuan Wu //   list<Predicate> Predicates = predicates;
3424d1673cSZi Xuan Wu //   /// Duplicate match when tied operand is just different.
3524d1673cSZi Xuan Wu //   bit isCompressOnly = false;
3624d1673cSZi Xuan Wu // }
3724d1673cSZi Xuan Wu //
3824d1673cSZi Xuan Wu // let Predicates = [HasStdExtC] in {
3924d1673cSZi Xuan Wu // def : CompressPat<(ADD GPRNoX0:$rs1, GPRNoX0:$rs1, GPRNoX0:$rs2),
4024d1673cSZi Xuan Wu //                   (C_ADD GPRNoX0:$rs1, GPRNoX0:$rs2)>;
4124d1673cSZi Xuan Wu // }
4224d1673cSZi Xuan Wu //
4324d1673cSZi Xuan Wu // The <TargetName>GenCompressInstEmitter.inc is an auto-generated header
4424d1673cSZi Xuan Wu // file which exports two functions for compressing/uncompressing MCInst
4524d1673cSZi Xuan Wu // instructions, plus some helper functions:
4624d1673cSZi Xuan Wu //
4724d1673cSZi Xuan Wu // bool compressInst(MCInst &OutInst, const MCInst &MI,
480b38636fSCraig Topper //                   const MCSubtargetInfo &STI);
4924d1673cSZi Xuan Wu //
5024d1673cSZi Xuan Wu // bool uncompressInst(MCInst &OutInst, const MCInst &MI,
5124d1673cSZi Xuan Wu //                     const MCSubtargetInfo &STI);
5224d1673cSZi Xuan Wu //
5324d1673cSZi Xuan Wu // In addition, it exports a function for checking whether
5424d1673cSZi Xuan Wu // an instruction is compressable:
5524d1673cSZi Xuan Wu //
5624d1673cSZi Xuan Wu // bool isCompressibleInst(const MachineInstr& MI,
57a971ce70SCraig Topper //                         const <TargetName>Subtarget &STI);
5824d1673cSZi Xuan Wu //
5924d1673cSZi Xuan Wu // The clients that include this auto-generated header file and
6024d1673cSZi Xuan Wu // invoke these functions can compress an instruction before emitting
6124d1673cSZi Xuan Wu // it in the target-specific ASM or ELF streamer or can uncompress
6224d1673cSZi Xuan Wu // an instruction before printing it when the expanded instruction
6324d1673cSZi Xuan Wu // format aliases is favored.
6424d1673cSZi Xuan Wu 
6524d1673cSZi Xuan Wu //===----------------------------------------------------------------------===//
6624d1673cSZi Xuan Wu 
67fa3d789dSPierre van Houtryve #include "Common/CodeGenInstruction.h"
68fa3d789dSPierre van Houtryve #include "Common/CodeGenRegisters.h"
69fa3d789dSPierre van Houtryve #include "Common/CodeGenTarget.h"
7024d1673cSZi Xuan Wu #include "llvm/ADT/IndexedMap.h"
7124d1673cSZi Xuan Wu #include "llvm/ADT/SmallVector.h"
7224d1673cSZi Xuan Wu #include "llvm/ADT/StringMap.h"
7324d1673cSZi Xuan Wu #include "llvm/Support/Debug.h"
7424d1673cSZi Xuan Wu #include "llvm/Support/ErrorHandling.h"
7524d1673cSZi Xuan Wu #include "llvm/TableGen/Error.h"
7624d1673cSZi Xuan Wu #include "llvm/TableGen/Record.h"
7724d1673cSZi Xuan Wu #include "llvm/TableGen/TableGenBackend.h"
7824d1673cSZi Xuan Wu #include <set>
7924d1673cSZi Xuan Wu #include <vector>
8024d1673cSZi Xuan Wu using namespace llvm;
8124d1673cSZi Xuan Wu 
8224d1673cSZi Xuan Wu #define DEBUG_TYPE "compress-inst-emitter"
8324d1673cSZi Xuan Wu 
8424d1673cSZi Xuan Wu namespace {
8524d1673cSZi Xuan Wu class CompressInstEmitter {
8624d1673cSZi Xuan Wu   struct OpData {
8724d1673cSZi Xuan Wu     enum MapKind { Operand, Imm, Reg };
8824d1673cSZi Xuan Wu     MapKind Kind;
8924d1673cSZi Xuan Wu     union {
9024d1673cSZi Xuan Wu       // Operand number mapped to.
9124d1673cSZi Xuan Wu       unsigned Operand;
9224d1673cSZi Xuan Wu       // Integer immediate value.
9324d1673cSZi Xuan Wu       int64_t Imm;
9424d1673cSZi Xuan Wu       // Physical register.
952c966709SRahul Joshi       const Record *Reg;
9624d1673cSZi Xuan Wu     } Data;
9724d1673cSZi Xuan Wu     // Tied operand index within the instruction.
9824d1673cSZi Xuan Wu     int TiedOpIdx = -1;
9924d1673cSZi Xuan Wu   };
10024d1673cSZi Xuan Wu   struct CompressPat {
10124d1673cSZi Xuan Wu     // The source instruction definition.
10224d1673cSZi Xuan Wu     CodeGenInstruction Source;
10324d1673cSZi Xuan Wu     // The destination instruction to transform to.
10424d1673cSZi Xuan Wu     CodeGenInstruction Dest;
10524d1673cSZi Xuan Wu     // Required target features to enable pattern.
1062c966709SRahul Joshi     std::vector<const Record *> PatReqFeatures;
10724d1673cSZi Xuan Wu     // Maps operands in the Source Instruction to
10824d1673cSZi Xuan Wu     // the corresponding Dest instruction operand.
10944193a05SWang Pengcheng     IndexedMap<OpData> SourceOperandMap;
11024d1673cSZi Xuan Wu     // Maps operands in the Dest Instruction
11124d1673cSZi Xuan Wu     // to the corresponding Source instruction operand.
11224d1673cSZi Xuan Wu     IndexedMap<OpData> DestOperandMap;
11324d1673cSZi Xuan Wu 
11424d1673cSZi Xuan Wu     bool IsCompressOnly;
1152c966709SRahul Joshi     CompressPat(const CodeGenInstruction &S, const CodeGenInstruction &D,
1162c966709SRahul Joshi                 std::vector<const Record *> RF, IndexedMap<OpData> &SourceMap,
11724d1673cSZi Xuan Wu                 IndexedMap<OpData> &DestMap, bool IsCompressOnly)
11831ce47b5Sabhishek-kaushik22         : Source(S), Dest(D), PatReqFeatures(std::move(RF)),
11931ce47b5Sabhishek-kaushik22           SourceOperandMap(SourceMap), DestOperandMap(DestMap),
12031ce47b5Sabhishek-kaushik22           IsCompressOnly(IsCompressOnly) {}
12124d1673cSZi Xuan Wu   };
12224d1673cSZi Xuan Wu   enum EmitterType { Compress, Uncompress, CheckCompress };
1232c966709SRahul Joshi   const RecordKeeper &Records;
1242c966709SRahul Joshi   const CodeGenTarget Target;
12524d1673cSZi Xuan Wu   SmallVector<CompressPat, 4> CompressPatterns;
12624d1673cSZi Xuan Wu 
1272c966709SRahul Joshi   void addDagOperandMapping(const Record *Rec, const DagInit *Dag,
1282c966709SRahul Joshi                             const CodeGenInstruction &Inst,
12924d1673cSZi Xuan Wu                             IndexedMap<OpData> &OperandMap, bool IsSourceInst);
1302c966709SRahul Joshi   void evaluateCompressPat(const Record *Compress);
13144193a05SWang Pengcheng   void emitCompressInstEmitter(raw_ostream &OS, EmitterType EType);
132bdf02249SRahul Joshi   bool validateTypes(const Record *DagOpType, const Record *InstOpType,
133bdf02249SRahul Joshi                      bool IsSourceInst);
134bdf02249SRahul Joshi   bool validateRegister(const Record *Reg, const Record *RegClass);
1352c966709SRahul Joshi   void createDagOperandMapping(const Record *Rec,
1362c966709SRahul Joshi                                StringMap<unsigned> &SourceOperands,
13724d1673cSZi Xuan Wu                                StringMap<unsigned> &DestOperands,
1382c966709SRahul Joshi                                const DagInit *SourceDag, const DagInit *DestDag,
13924d1673cSZi Xuan Wu                                IndexedMap<OpData> &SourceOperandMap);
14024d1673cSZi Xuan Wu 
1412c966709SRahul Joshi   void createInstOperandMapping(const Record *Rec, const DagInit *SourceDag,
1422c966709SRahul Joshi                                 const DagInit *DestDag,
14324d1673cSZi Xuan Wu                                 IndexedMap<OpData> &SourceOperandMap,
14424d1673cSZi Xuan Wu                                 IndexedMap<OpData> &DestOperandMap,
14524d1673cSZi Xuan Wu                                 StringMap<unsigned> &SourceOperands,
1462c966709SRahul Joshi                                 const CodeGenInstruction &DestInst);
14724d1673cSZi Xuan Wu 
14824d1673cSZi Xuan Wu public:
1492c966709SRahul Joshi   CompressInstEmitter(const RecordKeeper &R) : Records(R), Target(R) {}
15024d1673cSZi Xuan Wu 
15144193a05SWang Pengcheng   void run(raw_ostream &OS);
15224d1673cSZi Xuan Wu };
15324d1673cSZi Xuan Wu } // End anonymous namespace.
15424d1673cSZi Xuan Wu 
155bdf02249SRahul Joshi bool CompressInstEmitter::validateRegister(const Record *Reg,
156bdf02249SRahul Joshi                                            const Record *RegClass) {
15724d1673cSZi Xuan Wu   assert(Reg->isSubClassOf("Register") && "Reg record should be a Register");
15824d1673cSZi Xuan Wu   assert(RegClass->isSubClassOf("RegisterClass") &&
15924d1673cSZi Xuan Wu          "RegClass record should be a RegisterClass");
16024d1673cSZi Xuan Wu   const CodeGenRegisterClass &RC = Target.getRegisterClass(RegClass);
16124d1673cSZi Xuan Wu   const CodeGenRegister *R = Target.getRegisterByName(Reg->getName().lower());
1622c966709SRahul Joshi   assert(R != nullptr && "Register not defined!!");
16324d1673cSZi Xuan Wu   return RC.contains(R);
16424d1673cSZi Xuan Wu }
16524d1673cSZi Xuan Wu 
166bdf02249SRahul Joshi bool CompressInstEmitter::validateTypes(const Record *DagOpType,
167bdf02249SRahul Joshi                                         const Record *InstOpType,
16824d1673cSZi Xuan Wu                                         bool IsSourceInst) {
16924d1673cSZi Xuan Wu   if (DagOpType == InstOpType)
17024d1673cSZi Xuan Wu     return true;
17124d1673cSZi Xuan Wu   // Only source instruction operands are allowed to not match Input Dag
17224d1673cSZi Xuan Wu   // operands.
17324d1673cSZi Xuan Wu   if (!IsSourceInst)
17424d1673cSZi Xuan Wu     return false;
17524d1673cSZi Xuan Wu 
17624d1673cSZi Xuan Wu   if (DagOpType->isSubClassOf("RegisterClass") &&
17724d1673cSZi Xuan Wu       InstOpType->isSubClassOf("RegisterClass")) {
17824d1673cSZi Xuan Wu     const CodeGenRegisterClass &RC = Target.getRegisterClass(InstOpType);
17924d1673cSZi Xuan Wu     const CodeGenRegisterClass &SubRC = Target.getRegisterClass(DagOpType);
18024d1673cSZi Xuan Wu     return RC.hasSubClass(&SubRC);
18124d1673cSZi Xuan Wu   }
18224d1673cSZi Xuan Wu 
18324d1673cSZi Xuan Wu   // At this point either or both types are not registers, reject the pattern.
18424d1673cSZi Xuan Wu   if (DagOpType->isSubClassOf("RegisterClass") ||
18524d1673cSZi Xuan Wu       InstOpType->isSubClassOf("RegisterClass"))
18624d1673cSZi Xuan Wu     return false;
18724d1673cSZi Xuan Wu 
18824d1673cSZi Xuan Wu   // Let further validation happen when compress()/uncompress() functions are
18924d1673cSZi Xuan Wu   // invoked.
19024d1673cSZi Xuan Wu   LLVM_DEBUG(dbgs() << (IsSourceInst ? "Input" : "Output")
19124d1673cSZi Xuan Wu                     << " Dag Operand Type: '" << DagOpType->getName()
19224d1673cSZi Xuan Wu                     << "' and "
19324d1673cSZi Xuan Wu                     << "Instruction Operand Type: '" << InstOpType->getName()
19424d1673cSZi Xuan Wu                     << "' can't be checked at pattern validation time!\n");
19524d1673cSZi Xuan Wu   return true;
19624d1673cSZi Xuan Wu }
19724d1673cSZi Xuan Wu 
19824d1673cSZi Xuan Wu /// The patterns in the Dag contain different types of operands:
19924d1673cSZi Xuan Wu /// Register operands, e.g.: GPRC:$rs1; Fixed registers, e.g: X1; Immediate
20024d1673cSZi Xuan Wu /// operands, e.g.: simm6:$imm; Fixed immediate operands, e.g.: 0. This function
20124d1673cSZi Xuan Wu /// maps Dag operands to its corresponding instruction operands. For register
20224d1673cSZi Xuan Wu /// operands and fixed registers it expects the Dag operand type to be contained
20324d1673cSZi Xuan Wu /// in the instantiated instruction operand type. For immediate operands and
20424d1673cSZi Xuan Wu /// immediates no validation checks are enforced at pattern validation time.
2052c966709SRahul Joshi void CompressInstEmitter::addDagOperandMapping(const Record *Rec,
2062c966709SRahul Joshi                                                const DagInit *Dag,
2072c966709SRahul Joshi                                                const CodeGenInstruction &Inst,
20824d1673cSZi Xuan Wu                                                IndexedMap<OpData> &OperandMap,
20924d1673cSZi Xuan Wu                                                bool IsSourceInst) {
21024d1673cSZi Xuan Wu   // TiedCount keeps track of the number of operands skipped in Inst
21124d1673cSZi Xuan Wu   // operands list to get to the corresponding Dag operand. This is
21224d1673cSZi Xuan Wu   // necessary because the number of operands in Inst might be greater
21324d1673cSZi Xuan Wu   // than number of operands in the Dag due to how tied operands
21424d1673cSZi Xuan Wu   // are represented.
21524d1673cSZi Xuan Wu   unsigned TiedCount = 0;
21644193a05SWang Pengcheng   for (unsigned I = 0, E = Inst.Operands.size(); I != E; ++I) {
21744193a05SWang Pengcheng     int TiedOpIdx = Inst.Operands[I].getTiedRegister();
21824d1673cSZi Xuan Wu     if (-1 != TiedOpIdx) {
21924d1673cSZi Xuan Wu       // Set the entry in OperandMap for the tied operand we're skipping.
22044193a05SWang Pengcheng       OperandMap[I].Kind = OperandMap[TiedOpIdx].Kind;
22144193a05SWang Pengcheng       OperandMap[I].Data = OperandMap[TiedOpIdx].Data;
22224d1673cSZi Xuan Wu       TiedCount++;
22324d1673cSZi Xuan Wu       continue;
22424d1673cSZi Xuan Wu     }
2252c966709SRahul Joshi     if (const DefInit *DI = dyn_cast<DefInit>(Dag->getArg(I - TiedCount))) {
22624d1673cSZi Xuan Wu       if (DI->getDef()->isSubClassOf("Register")) {
22724d1673cSZi Xuan Wu         // Check if the fixed register belongs to the Register class.
22844193a05SWang Pengcheng         if (!validateRegister(DI->getDef(), Inst.Operands[I].Rec))
22924d1673cSZi Xuan Wu           PrintFatalError(Rec->getLoc(),
23024d1673cSZi Xuan Wu                           "Error in Dag '" + Dag->getAsString() +
23124d1673cSZi Xuan Wu                               "'Register: '" + DI->getDef()->getName() +
23224d1673cSZi Xuan Wu                               "' is not in register class '" +
23344193a05SWang Pengcheng                               Inst.Operands[I].Rec->getName() + "'");
23444193a05SWang Pengcheng         OperandMap[I].Kind = OpData::Reg;
23544193a05SWang Pengcheng         OperandMap[I].Data.Reg = DI->getDef();
23624d1673cSZi Xuan Wu         continue;
23724d1673cSZi Xuan Wu       }
23824d1673cSZi Xuan Wu       // Validate that Dag operand type matches the type defined in the
23924d1673cSZi Xuan Wu       // corresponding instruction. Operands in the input Dag pattern are
24024d1673cSZi Xuan Wu       // allowed to be a subclass of the type specified in corresponding
24124d1673cSZi Xuan Wu       // instruction operand instead of being an exact match.
24244193a05SWang Pengcheng       if (!validateTypes(DI->getDef(), Inst.Operands[I].Rec, IsSourceInst))
24324d1673cSZi Xuan Wu         PrintFatalError(Rec->getLoc(),
24424d1673cSZi Xuan Wu                         "Error in Dag '" + Dag->getAsString() + "'. Operand '" +
24544193a05SWang Pengcheng                             Dag->getArgNameStr(I - TiedCount) + "' has type '" +
24624d1673cSZi Xuan Wu                             DI->getDef()->getName() +
24724d1673cSZi Xuan Wu                             "' which does not match the type '" +
24844193a05SWang Pengcheng                             Inst.Operands[I].Rec->getName() +
24924d1673cSZi Xuan Wu                             "' in the corresponding instruction operand!");
25024d1673cSZi Xuan Wu 
25144193a05SWang Pengcheng       OperandMap[I].Kind = OpData::Operand;
25262e2c7fbSRahul Joshi     } else if (const IntInit *II =
25362e2c7fbSRahul Joshi                    dyn_cast<IntInit>(Dag->getArg(I - TiedCount))) {
25424d1673cSZi Xuan Wu       // Validate that corresponding instruction operand expects an immediate.
25544193a05SWang Pengcheng       if (Inst.Operands[I].Rec->isSubClassOf("RegisterClass"))
25624d1673cSZi Xuan Wu         PrintFatalError(
25724d1673cSZi Xuan Wu             Rec->getLoc(),
25824d1673cSZi Xuan Wu             "Error in Dag '" + Dag->getAsString() + "' Found immediate: '" +
25924d1673cSZi Xuan Wu                 II->getAsString() +
26024d1673cSZi Xuan Wu                 "' but corresponding instruction operand expected a register!");
26124d1673cSZi Xuan Wu       // No pattern validation check possible for values of fixed immediate.
26244193a05SWang Pengcheng       OperandMap[I].Kind = OpData::Imm;
26344193a05SWang Pengcheng       OperandMap[I].Data.Imm = II->getValue();
26424d1673cSZi Xuan Wu       LLVM_DEBUG(
26524d1673cSZi Xuan Wu           dbgs() << "  Found immediate '" << II->getValue() << "' at "
26624d1673cSZi Xuan Wu                  << (IsSourceInst ? "input " : "output ")
26724d1673cSZi Xuan Wu                  << "Dag. No validation time check possible for values of "
26824d1673cSZi Xuan Wu                     "fixed immediate.\n");
26924d1673cSZi Xuan Wu     } else
27024d1673cSZi Xuan Wu       llvm_unreachable("Unhandled CompressPat argument type!");
27124d1673cSZi Xuan Wu   }
27224d1673cSZi Xuan Wu }
27324d1673cSZi Xuan Wu 
27424d1673cSZi Xuan Wu // Verify the Dag operand count is enough to build an instruction.
2752c966709SRahul Joshi static bool verifyDagOpCount(const CodeGenInstruction &Inst, const DagInit *Dag,
27624d1673cSZi Xuan Wu                              bool IsSource) {
27724d1673cSZi Xuan Wu   if (Dag->getNumArgs() == Inst.Operands.size())
27824d1673cSZi Xuan Wu     return true;
27924d1673cSZi Xuan Wu   // Source instructions are non compressed instructions and don't have tied
28024d1673cSZi Xuan Wu   // operands.
28124d1673cSZi Xuan Wu   if (IsSource)
28224d1673cSZi Xuan Wu     PrintFatalError(Inst.TheDef->getLoc(),
28324d1673cSZi Xuan Wu                     "Input operands for Inst '" + Inst.TheDef->getName() +
28424d1673cSZi Xuan Wu                         "' and input Dag operand count mismatch");
28524d1673cSZi Xuan Wu   // The Dag can't have more arguments than the Instruction.
28624d1673cSZi Xuan Wu   if (Dag->getNumArgs() > Inst.Operands.size())
28724d1673cSZi Xuan Wu     PrintFatalError(Inst.TheDef->getLoc(),
28824d1673cSZi Xuan Wu                     "Inst '" + Inst.TheDef->getName() +
28924d1673cSZi Xuan Wu                         "' and Dag operand count mismatch");
29024d1673cSZi Xuan Wu 
29124d1673cSZi Xuan Wu   // The Instruction might have tied operands so the Dag might have
29224d1673cSZi Xuan Wu   // a fewer operand count.
29324d1673cSZi Xuan Wu   unsigned RealCount = Inst.Operands.size();
29424d1673cSZi Xuan Wu   for (const auto &Operand : Inst.Operands)
29524d1673cSZi Xuan Wu     if (Operand.getTiedRegister() != -1)
29624d1673cSZi Xuan Wu       --RealCount;
29724d1673cSZi Xuan Wu 
29824d1673cSZi Xuan Wu   if (Dag->getNumArgs() != RealCount)
29924d1673cSZi Xuan Wu     PrintFatalError(Inst.TheDef->getLoc(),
30024d1673cSZi Xuan Wu                     "Inst '" + Inst.TheDef->getName() +
30124d1673cSZi Xuan Wu                         "' and Dag operand count mismatch");
30224d1673cSZi Xuan Wu   return true;
30324d1673cSZi Xuan Wu }
30424d1673cSZi Xuan Wu 
3052c966709SRahul Joshi static bool validateArgsTypes(const Init *Arg1, const Init *Arg2) {
30624d1673cSZi Xuan Wu   return cast<DefInit>(Arg1)->getDef() == cast<DefInit>(Arg2)->getDef();
30724d1673cSZi Xuan Wu }
30824d1673cSZi Xuan Wu 
30924d1673cSZi Xuan Wu // Creates a mapping between the operand name in the Dag (e.g. $rs1) and
31024d1673cSZi Xuan Wu // its index in the list of Dag operands and checks that operands with the same
31124d1673cSZi Xuan Wu // name have the same types. For example in 'C_ADD $rs1, $rs2' we generate the
31224d1673cSZi Xuan Wu // mapping $rs1 --> 0, $rs2 ---> 1. If the operand appears twice in the (tied)
31324d1673cSZi Xuan Wu // same Dag we use the last occurrence for indexing.
31424d1673cSZi Xuan Wu void CompressInstEmitter::createDagOperandMapping(
3152c966709SRahul Joshi     const Record *Rec, StringMap<unsigned> &SourceOperands,
3162c966709SRahul Joshi     StringMap<unsigned> &DestOperands, const DagInit *SourceDag,
3172c966709SRahul Joshi     const DagInit *DestDag, IndexedMap<OpData> &SourceOperandMap) {
31844193a05SWang Pengcheng   for (unsigned I = 0; I < DestDag->getNumArgs(); ++I) {
31924d1673cSZi Xuan Wu     // Skip fixed immediates and registers, they were handled in
32024d1673cSZi Xuan Wu     // addDagOperandMapping.
32144193a05SWang Pengcheng     if ("" == DestDag->getArgNameStr(I))
32224d1673cSZi Xuan Wu       continue;
32344193a05SWang Pengcheng     DestOperands[DestDag->getArgNameStr(I)] = I;
32424d1673cSZi Xuan Wu   }
32524d1673cSZi Xuan Wu 
32644193a05SWang Pengcheng   for (unsigned I = 0; I < SourceDag->getNumArgs(); ++I) {
32724d1673cSZi Xuan Wu     // Skip fixed immediates and registers, they were handled in
32824d1673cSZi Xuan Wu     // addDagOperandMapping.
32944193a05SWang Pengcheng     if ("" == SourceDag->getArgNameStr(I))
33024d1673cSZi Xuan Wu       continue;
33124d1673cSZi Xuan Wu 
33244193a05SWang Pengcheng     StringMap<unsigned>::iterator It =
33344193a05SWang Pengcheng         SourceOperands.find(SourceDag->getArgNameStr(I));
33444193a05SWang Pengcheng     if (It != SourceOperands.end()) {
33524d1673cSZi Xuan Wu       // Operand sharing the same name in the Dag should be mapped as tied.
33644193a05SWang Pengcheng       SourceOperandMap[I].TiedOpIdx = It->getValue();
33744193a05SWang Pengcheng       if (!validateArgsTypes(SourceDag->getArg(It->getValue()),
33844193a05SWang Pengcheng                              SourceDag->getArg(I)))
33924d1673cSZi Xuan Wu         PrintFatalError(Rec->getLoc(),
34044193a05SWang Pengcheng                         "Input Operand '" + SourceDag->getArgNameStr(I) +
34124d1673cSZi Xuan Wu                             "' has a mismatched tied operand!\n");
34224d1673cSZi Xuan Wu     }
34344193a05SWang Pengcheng     It = DestOperands.find(SourceDag->getArgNameStr(I));
34444193a05SWang Pengcheng     if (It == DestOperands.end())
34544193a05SWang Pengcheng       PrintFatalError(Rec->getLoc(), "Operand " + SourceDag->getArgNameStr(I) +
34624d1673cSZi Xuan Wu                                          " defined in Input Dag but not used in"
34724d1673cSZi Xuan Wu                                          " Output Dag!\n");
34824d1673cSZi Xuan Wu     // Input Dag operand types must match output Dag operand type.
34944193a05SWang Pengcheng     if (!validateArgsTypes(DestDag->getArg(It->getValue()),
35044193a05SWang Pengcheng                            SourceDag->getArg(I)))
35124d1673cSZi Xuan Wu       PrintFatalError(Rec->getLoc(), "Type mismatch between Input and "
35224d1673cSZi Xuan Wu                                      "Output Dag operand '" +
35344193a05SWang Pengcheng                                          SourceDag->getArgNameStr(I) + "'!");
35444193a05SWang Pengcheng     SourceOperands[SourceDag->getArgNameStr(I)] = I;
35524d1673cSZi Xuan Wu   }
35624d1673cSZi Xuan Wu }
35724d1673cSZi Xuan Wu 
35824d1673cSZi Xuan Wu /// Map operand names in the Dag to their index in both corresponding input and
35924d1673cSZi Xuan Wu /// output instructions. Validate that operands defined in the input are
36024d1673cSZi Xuan Wu /// used in the output pattern while populating the maps.
36124d1673cSZi Xuan Wu void CompressInstEmitter::createInstOperandMapping(
3622c966709SRahul Joshi     const Record *Rec, const DagInit *SourceDag, const DagInit *DestDag,
36324d1673cSZi Xuan Wu     IndexedMap<OpData> &SourceOperandMap, IndexedMap<OpData> &DestOperandMap,
3642c966709SRahul Joshi     StringMap<unsigned> &SourceOperands, const CodeGenInstruction &DestInst) {
36524d1673cSZi Xuan Wu   // TiedCount keeps track of the number of operands skipped in Inst
36624d1673cSZi Xuan Wu   // operands list to get to the corresponding Dag operand.
36724d1673cSZi Xuan Wu   unsigned TiedCount = 0;
36824d1673cSZi Xuan Wu   LLVM_DEBUG(dbgs() << "  Operand mapping:\n  Source   Dest\n");
36944193a05SWang Pengcheng   for (unsigned I = 0, E = DestInst.Operands.size(); I != E; ++I) {
37044193a05SWang Pengcheng     int TiedInstOpIdx = DestInst.Operands[I].getTiedRegister();
37124d1673cSZi Xuan Wu     if (TiedInstOpIdx != -1) {
37224d1673cSZi Xuan Wu       ++TiedCount;
37344193a05SWang Pengcheng       DestOperandMap[I].Data = DestOperandMap[TiedInstOpIdx].Data;
37444193a05SWang Pengcheng       DestOperandMap[I].Kind = DestOperandMap[TiedInstOpIdx].Kind;
37544193a05SWang Pengcheng       if (DestOperandMap[I].Kind == OpData::Operand)
37624d1673cSZi Xuan Wu         // No need to fill the SourceOperandMap here since it was mapped to
37724d1673cSZi Xuan Wu         // destination operand 'TiedInstOpIdx' in a previous iteration.
37844193a05SWang Pengcheng         LLVM_DEBUG(dbgs() << "    " << DestOperandMap[I].Data.Operand
37944193a05SWang Pengcheng                           << " ====> " << I
38024d1673cSZi Xuan Wu                           << "  Dest operand tied with operand '"
38124d1673cSZi Xuan Wu                           << TiedInstOpIdx << "'\n");
38224d1673cSZi Xuan Wu       continue;
38324d1673cSZi Xuan Wu     }
38424d1673cSZi Xuan Wu     // Skip fixed immediates and registers, they were handled in
38524d1673cSZi Xuan Wu     // addDagOperandMapping.
38644193a05SWang Pengcheng     if (DestOperandMap[I].Kind != OpData::Operand)
38724d1673cSZi Xuan Wu       continue;
38824d1673cSZi Xuan Wu 
38944193a05SWang Pengcheng     unsigned DagArgIdx = I - TiedCount;
39024d1673cSZi Xuan Wu     StringMap<unsigned>::iterator SourceOp =
39124d1673cSZi Xuan Wu         SourceOperands.find(DestDag->getArgNameStr(DagArgIdx));
39224d1673cSZi Xuan Wu     if (SourceOp == SourceOperands.end())
39324d1673cSZi Xuan Wu       PrintFatalError(Rec->getLoc(),
39424d1673cSZi Xuan Wu                       "Output Dag operand '" +
39524d1673cSZi Xuan Wu                           DestDag->getArgNameStr(DagArgIdx) +
39624d1673cSZi Xuan Wu                           "' has no matching input Dag operand.");
39724d1673cSZi Xuan Wu 
39824d1673cSZi Xuan Wu     assert(DestDag->getArgNameStr(DagArgIdx) ==
39924d1673cSZi Xuan Wu                SourceDag->getArgNameStr(SourceOp->getValue()) &&
40024d1673cSZi Xuan Wu            "Incorrect operand mapping detected!\n");
40144193a05SWang Pengcheng     DestOperandMap[I].Data.Operand = SourceOp->getValue();
40244193a05SWang Pengcheng     SourceOperandMap[SourceOp->getValue()].Data.Operand = I;
40344193a05SWang Pengcheng     LLVM_DEBUG(dbgs() << "    " << SourceOp->getValue() << " ====> " << I
40424d1673cSZi Xuan Wu                       << "\n");
40524d1673cSZi Xuan Wu   }
40624d1673cSZi Xuan Wu }
40724d1673cSZi Xuan Wu 
40824d1673cSZi Xuan Wu /// Validates the CompressPattern and create operand mapping.
40924d1673cSZi Xuan Wu /// These are the checks to validate a CompressPat pattern declarations.
41024d1673cSZi Xuan Wu /// Error out with message under these conditions:
41124d1673cSZi Xuan Wu /// - Dag Input opcode is an expanded instruction and Dag Output opcode is a
41224d1673cSZi Xuan Wu ///   compressed instruction.
41324d1673cSZi Xuan Wu /// - Operands in Dag Input must be all used in Dag Output.
41424d1673cSZi Xuan Wu ///   Register Operand type in Dag Input Type must be contained in the
41524d1673cSZi Xuan Wu ///   corresponding Source Instruction type.
41624d1673cSZi Xuan Wu /// - Register Operand type in Dag Input must be the same as in Dag Ouput.
41724d1673cSZi Xuan Wu /// - Register Operand type in Dag Output must be the same as the
41824d1673cSZi Xuan Wu ///   corresponding Destination Inst type.
41924d1673cSZi Xuan Wu /// - Immediate Operand type in Dag Input must be the same as in Dag Ouput.
42024d1673cSZi Xuan Wu /// - Immediate Operand type in Dag Ouput must be the same as the corresponding
42124d1673cSZi Xuan Wu ///   Destination Instruction type.
42224d1673cSZi Xuan Wu /// - Fixed register must be contained in the corresponding Source Instruction
42324d1673cSZi Xuan Wu ///   type.
42424d1673cSZi Xuan Wu /// - Fixed register must be contained in the corresponding Destination
42544193a05SWang Pengcheng ///   Instruction type.
42644193a05SWang Pengcheng /// Warning message printed under these conditions:
42724d1673cSZi Xuan Wu /// - Fixed immediate in Dag Input or Dag Ouput cannot be checked at this time
42824d1673cSZi Xuan Wu ///   and generate warning.
42924d1673cSZi Xuan Wu /// - Immediate operand type in Dag Input differs from the corresponding Source
43024d1673cSZi Xuan Wu ///   Instruction type and generate a warning.
4312c966709SRahul Joshi void CompressInstEmitter::evaluateCompressPat(const Record *Rec) {
43224d1673cSZi Xuan Wu   // Validate input Dag operands.
43362e2c7fbSRahul Joshi   const DagInit *SourceDag = Rec->getValueAsDag("Input");
43424d1673cSZi Xuan Wu   assert(SourceDag && "Missing 'Input' in compress pattern!");
43524d1673cSZi Xuan Wu   LLVM_DEBUG(dbgs() << "Input: " << *SourceDag << "\n");
43624d1673cSZi Xuan Wu 
43724d1673cSZi Xuan Wu   // Checking we are transforming from compressed to uncompressed instructions.
4382c966709SRahul Joshi   const Record *SourceOperator = SourceDag->getOperatorAsDef(Rec->getLoc());
43944193a05SWang Pengcheng   CodeGenInstruction SourceInst(SourceOperator);
44024d1673cSZi Xuan Wu   verifyDagOpCount(SourceInst, SourceDag, true);
44124d1673cSZi Xuan Wu 
44224d1673cSZi Xuan Wu   // Validate output Dag operands.
44362e2c7fbSRahul Joshi   const DagInit *DestDag = Rec->getValueAsDag("Output");
44424d1673cSZi Xuan Wu   assert(DestDag && "Missing 'Output' in compress pattern!");
44524d1673cSZi Xuan Wu   LLVM_DEBUG(dbgs() << "Output: " << *DestDag << "\n");
44624d1673cSZi Xuan Wu 
4472c966709SRahul Joshi   const Record *DestOperator = DestDag->getOperatorAsDef(Rec->getLoc());
44824d1673cSZi Xuan Wu   CodeGenInstruction DestInst(DestOperator);
44924d1673cSZi Xuan Wu   verifyDagOpCount(DestInst, DestDag, false);
45024d1673cSZi Xuan Wu 
45144193a05SWang Pengcheng   if (SourceOperator->getValueAsInt("Size") <=
45244193a05SWang Pengcheng       DestOperator->getValueAsInt("Size"))
45324d1673cSZi Xuan Wu     PrintFatalError(
45424d1673cSZi Xuan Wu         Rec->getLoc(),
45524d1673cSZi Xuan Wu         "Compressed instruction '" + DestOperator->getName() +
45624d1673cSZi Xuan Wu             "'is not strictly smaller than the uncompressed instruction '" +
45744193a05SWang Pengcheng             SourceOperator->getName() + "' !");
45824d1673cSZi Xuan Wu 
45924d1673cSZi Xuan Wu   // Fill the mapping from the source to destination instructions.
46024d1673cSZi Xuan Wu 
46124d1673cSZi Xuan Wu   IndexedMap<OpData> SourceOperandMap;
46224d1673cSZi Xuan Wu   SourceOperandMap.grow(SourceInst.Operands.size());
46324d1673cSZi Xuan Wu   // Create a mapping between source Dag operands and source Inst operands.
46424d1673cSZi Xuan Wu   addDagOperandMapping(Rec, SourceDag, SourceInst, SourceOperandMap,
46524d1673cSZi Xuan Wu                        /*IsSourceInst*/ true);
46624d1673cSZi Xuan Wu 
46724d1673cSZi Xuan Wu   IndexedMap<OpData> DestOperandMap;
46824d1673cSZi Xuan Wu   DestOperandMap.grow(DestInst.Operands.size());
46924d1673cSZi Xuan Wu   // Create a mapping between destination Dag operands and destination Inst
47024d1673cSZi Xuan Wu   // operands.
47124d1673cSZi Xuan Wu   addDagOperandMapping(Rec, DestDag, DestInst, DestOperandMap,
47224d1673cSZi Xuan Wu                        /*IsSourceInst*/ false);
47324d1673cSZi Xuan Wu 
47424d1673cSZi Xuan Wu   StringMap<unsigned> SourceOperands;
47524d1673cSZi Xuan Wu   StringMap<unsigned> DestOperands;
47624d1673cSZi Xuan Wu   createDagOperandMapping(Rec, SourceOperands, DestOperands, SourceDag, DestDag,
47724d1673cSZi Xuan Wu                           SourceOperandMap);
47824d1673cSZi Xuan Wu   // Create operand mapping between the source and destination instructions.
47924d1673cSZi Xuan Wu   createInstOperandMapping(Rec, SourceDag, DestDag, SourceOperandMap,
48024d1673cSZi Xuan Wu                            DestOperandMap, SourceOperands, DestInst);
48124d1673cSZi Xuan Wu 
48224d1673cSZi Xuan Wu   // Get the target features for the CompressPat.
4832c966709SRahul Joshi   std::vector<const Record *> PatReqFeatures;
484a140931bSRahul Joshi   std::vector<const Record *> RF = Rec->getValueAsListOfDefs("Predicates");
4852c966709SRahul Joshi   copy_if(RF, std::back_inserter(PatReqFeatures), [](const Record *R) {
48624d1673cSZi Xuan Wu     return R->getValueAsBit("AssemblerMatcherPredicate");
48724d1673cSZi Xuan Wu   });
48824d1673cSZi Xuan Wu 
48931ce47b5Sabhishek-kaushik22   CompressPatterns.push_back(CompressPat(
49031ce47b5Sabhishek-kaushik22       SourceInst, DestInst, std::move(PatReqFeatures), SourceOperandMap,
49131ce47b5Sabhishek-kaushik22       DestOperandMap, Rec->getValueAsBit("isCompressOnly")));
49224d1673cSZi Xuan Wu }
49324d1673cSZi Xuan Wu 
49424d1673cSZi Xuan Wu static void
49524d1673cSZi Xuan Wu getReqFeatures(std::set<std::pair<bool, StringRef>> &FeaturesSet,
49624d1673cSZi Xuan Wu                std::set<std::set<std::pair<bool, StringRef>>> &AnyOfFeatureSets,
4972c966709SRahul Joshi                ArrayRef<const Record *> ReqFeatures) {
4982c966709SRahul Joshi   for (const Record *R : ReqFeatures) {
49924d1673cSZi Xuan Wu     const DagInit *D = R->getValueAsDag("AssemblerCondDag");
50024d1673cSZi Xuan Wu     std::string CombineType = D->getOperator()->getAsString();
50124d1673cSZi Xuan Wu     if (CombineType != "any_of" && CombineType != "all_of")
50224d1673cSZi Xuan Wu       PrintFatalError(R->getLoc(), "Invalid AssemblerCondDag!");
50324d1673cSZi Xuan Wu     if (D->getNumArgs() == 0)
50424d1673cSZi Xuan Wu       PrintFatalError(R->getLoc(), "Invalid AssemblerCondDag!");
50524d1673cSZi Xuan Wu     bool IsOr = CombineType == "any_of";
50624d1673cSZi Xuan Wu     std::set<std::pair<bool, StringRef>> AnyOfSet;
50724d1673cSZi Xuan Wu 
50824d1673cSZi Xuan Wu     for (auto *Arg : D->getArgs()) {
50924d1673cSZi Xuan Wu       bool IsNot = false;
51024d1673cSZi Xuan Wu       if (auto *NotArg = dyn_cast<DagInit>(Arg)) {
51124d1673cSZi Xuan Wu         if (NotArg->getOperator()->getAsString() != "not" ||
51224d1673cSZi Xuan Wu             NotArg->getNumArgs() != 1)
51324d1673cSZi Xuan Wu           PrintFatalError(R->getLoc(), "Invalid AssemblerCondDag!");
51424d1673cSZi Xuan Wu         Arg = NotArg->getArg(0);
51524d1673cSZi Xuan Wu         IsNot = true;
51624d1673cSZi Xuan Wu       }
51724d1673cSZi Xuan Wu       if (!isa<DefInit>(Arg) ||
51824d1673cSZi Xuan Wu           !cast<DefInit>(Arg)->getDef()->isSubClassOf("SubtargetFeature"))
51924d1673cSZi Xuan Wu         PrintFatalError(R->getLoc(), "Invalid AssemblerCondDag!");
52024d1673cSZi Xuan Wu       if (IsOr)
52124d1673cSZi Xuan Wu         AnyOfSet.insert({IsNot, cast<DefInit>(Arg)->getDef()->getName()});
52224d1673cSZi Xuan Wu       else
52324d1673cSZi Xuan Wu         FeaturesSet.insert({IsNot, cast<DefInit>(Arg)->getDef()->getName()});
52424d1673cSZi Xuan Wu     }
52524d1673cSZi Xuan Wu 
52624d1673cSZi Xuan Wu     if (IsOr)
52731ce47b5Sabhishek-kaushik22       AnyOfFeatureSets.insert(std::move(AnyOfSet));
52824d1673cSZi Xuan Wu   }
52924d1673cSZi Xuan Wu }
53024d1673cSZi Xuan Wu 
53124d1673cSZi Xuan Wu static unsigned getPredicates(DenseMap<const Record *, unsigned> &PredicateMap,
53224d1673cSZi Xuan Wu                               std::vector<const Record *> &Predicates,
533bdf02249SRahul Joshi                               const Record *Rec, StringRef Name) {
53424d1673cSZi Xuan Wu   unsigned &Entry = PredicateMap[Rec];
53524d1673cSZi Xuan Wu   if (Entry)
53624d1673cSZi Xuan Wu     return Entry;
53724d1673cSZi Xuan Wu 
53824d1673cSZi Xuan Wu   if (!Rec->isValueUnset(Name)) {
53924d1673cSZi Xuan Wu     Predicates.push_back(Rec);
54024d1673cSZi Xuan Wu     Entry = Predicates.size();
54124d1673cSZi Xuan Wu     return Entry;
54224d1673cSZi Xuan Wu   }
54324d1673cSZi Xuan Wu 
54424d1673cSZi Xuan Wu   PrintFatalError(Rec->getLoc(), "No " + Name +
54524d1673cSZi Xuan Wu                                      " predicate on this operand at all: '" +
54624d1673cSZi Xuan Wu                                      Rec->getName() + "'");
54724d1673cSZi Xuan Wu   return 0;
54824d1673cSZi Xuan Wu }
54924d1673cSZi Xuan Wu 
5502c966709SRahul Joshi static void printPredicates(ArrayRef<const Record *> Predicates, StringRef Name,
5512c966709SRahul Joshi                             raw_ostream &OS) {
55244193a05SWang Pengcheng   for (unsigned I = 0; I < Predicates.size(); ++I) {
55344193a05SWang Pengcheng     StringRef Pred = Predicates[I]->getValueAsString(Name);
55444193a05SWang Pengcheng     OS << "  case " << I + 1 << ": {\n"
55544193a05SWang Pengcheng        << "  // " << Predicates[I]->getName() << "\n"
55624d1673cSZi Xuan Wu        << "  " << Pred << "\n"
55724d1673cSZi Xuan Wu        << "  }\n";
55824d1673cSZi Xuan Wu   }
55924d1673cSZi Xuan Wu }
56024d1673cSZi Xuan Wu 
56124d1673cSZi Xuan Wu static void mergeCondAndCode(raw_ostream &CombinedStream, StringRef CondStr,
56224d1673cSZi Xuan Wu                              StringRef CodeStr) {
56324d1673cSZi Xuan Wu   // Remove first indentation and last '&&'.
56424d1673cSZi Xuan Wu   CondStr = CondStr.drop_front(6).drop_back(4);
56524d1673cSZi Xuan Wu   CombinedStream.indent(4) << "if (" << CondStr << ") {\n";
56624d1673cSZi Xuan Wu   CombinedStream << CodeStr;
56724d1673cSZi Xuan Wu   CombinedStream.indent(4) << "  return true;\n";
56824d1673cSZi Xuan Wu   CombinedStream.indent(4) << "} // if\n";
56924d1673cSZi Xuan Wu }
57024d1673cSZi Xuan Wu 
57144193a05SWang Pengcheng void CompressInstEmitter::emitCompressInstEmitter(raw_ostream &OS,
57224d1673cSZi Xuan Wu                                                   EmitterType EType) {
5732c966709SRahul Joshi   const Record *AsmWriter = Target.getAsmWriter();
57424d1673cSZi Xuan Wu   if (!AsmWriter->getValueAsInt("PassSubtarget"))
57524d1673cSZi Xuan Wu     PrintFatalError(AsmWriter->getLoc(),
57624d1673cSZi Xuan Wu                     "'PassSubtarget' is false. SubTargetInfo object is needed "
57724d1673cSZi Xuan Wu                     "for target features.\n");
57824d1673cSZi Xuan Wu 
57924d1673cSZi Xuan Wu   StringRef TargetName = Target.getName();
58024d1673cSZi Xuan Wu 
58124d1673cSZi Xuan Wu   // Sort entries in CompressPatterns to handle instructions that can have more
58224d1673cSZi Xuan Wu   // than one candidate for compression\uncompression, e.g ADD can be
58324d1673cSZi Xuan Wu   // transformed to a C_ADD or a C_MV. When emitting 'uncompress()' function the
58424d1673cSZi Xuan Wu   // source and destination are flipped and the sort key needs to change
58524d1673cSZi Xuan Wu   // accordingly.
58624d1673cSZi Xuan Wu   llvm::stable_sort(CompressPatterns, [EType](const CompressPat &LHS,
58724d1673cSZi Xuan Wu                                               const CompressPat &RHS) {
58824d1673cSZi Xuan Wu     if (EType == EmitterType::Compress || EType == EmitterType::CheckCompress)
58924d1673cSZi Xuan Wu       return (LHS.Source.TheDef->getName() < RHS.Source.TheDef->getName());
59024d1673cSZi Xuan Wu     return (LHS.Dest.TheDef->getName() < RHS.Dest.TheDef->getName());
59124d1673cSZi Xuan Wu   });
59224d1673cSZi Xuan Wu 
59324d1673cSZi Xuan Wu   // A list of MCOperandPredicates for all operands in use, and the reverse map.
59424d1673cSZi Xuan Wu   std::vector<const Record *> MCOpPredicates;
59524d1673cSZi Xuan Wu   DenseMap<const Record *, unsigned> MCOpPredicateMap;
59624d1673cSZi Xuan Wu   // A list of ImmLeaf Predicates for all operands in use, and the reverse map.
59724d1673cSZi Xuan Wu   std::vector<const Record *> ImmLeafPredicates;
59824d1673cSZi Xuan Wu   DenseMap<const Record *, unsigned> ImmLeafPredicateMap;
59924d1673cSZi Xuan Wu 
60024d1673cSZi Xuan Wu   std::string F;
60124d1673cSZi Xuan Wu   std::string FH;
60224d1673cSZi Xuan Wu   raw_string_ostream Func(F);
60324d1673cSZi Xuan Wu   raw_string_ostream FuncH(FH);
60424d1673cSZi Xuan Wu 
60524d1673cSZi Xuan Wu   if (EType == EmitterType::Compress)
60644193a05SWang Pengcheng     OS << "\n#ifdef GEN_COMPRESS_INSTR\n"
60724d1673cSZi Xuan Wu        << "#undef GEN_COMPRESS_INSTR\n\n";
60824d1673cSZi Xuan Wu   else if (EType == EmitterType::Uncompress)
60944193a05SWang Pengcheng     OS << "\n#ifdef GEN_UNCOMPRESS_INSTR\n"
61024d1673cSZi Xuan Wu        << "#undef GEN_UNCOMPRESS_INSTR\n\n";
61124d1673cSZi Xuan Wu   else if (EType == EmitterType::CheckCompress)
61244193a05SWang Pengcheng     OS << "\n#ifdef GEN_CHECK_COMPRESS_INSTR\n"
61324d1673cSZi Xuan Wu        << "#undef GEN_CHECK_COMPRESS_INSTR\n\n";
61424d1673cSZi Xuan Wu 
61524d1673cSZi Xuan Wu   if (EType == EmitterType::Compress) {
61624d1673cSZi Xuan Wu     FuncH << "static bool compressInst(MCInst &OutInst,\n";
61724d1673cSZi Xuan Wu     FuncH.indent(25) << "const MCInst &MI,\n";
6180b38636fSCraig Topper     FuncH.indent(25) << "const MCSubtargetInfo &STI) {\n";
61924d1673cSZi Xuan Wu   } else if (EType == EmitterType::Uncompress) {
62024d1673cSZi Xuan Wu     FuncH << "static bool uncompressInst(MCInst &OutInst,\n";
62124d1673cSZi Xuan Wu     FuncH.indent(27) << "const MCInst &MI,\n";
62224d1673cSZi Xuan Wu     FuncH.indent(27) << "const MCSubtargetInfo &STI) {\n";
62324d1673cSZi Xuan Wu   } else if (EType == EmitterType::CheckCompress) {
62424d1673cSZi Xuan Wu     FuncH << "static bool isCompressibleInst(const MachineInstr &MI,\n";
625a971ce70SCraig Topper     FuncH.indent(31) << "const " << TargetName << "Subtarget &STI) {\n";
62624d1673cSZi Xuan Wu   }
62724d1673cSZi Xuan Wu 
62824d1673cSZi Xuan Wu   if (CompressPatterns.empty()) {
62934855405SYoungsuk Kim     OS << FH;
63044193a05SWang Pengcheng     OS.indent(2) << "return false;\n}\n";
63124d1673cSZi Xuan Wu     if (EType == EmitterType::Compress)
63244193a05SWang Pengcheng       OS << "\n#endif //GEN_COMPRESS_INSTR\n";
63324d1673cSZi Xuan Wu     else if (EType == EmitterType::Uncompress)
63444193a05SWang Pengcheng       OS << "\n#endif //GEN_UNCOMPRESS_INSTR\n\n";
63524d1673cSZi Xuan Wu     else if (EType == EmitterType::CheckCompress)
63644193a05SWang Pengcheng       OS << "\n#endif //GEN_CHECK_COMPRESS_INSTR\n\n";
63724d1673cSZi Xuan Wu     return;
63824d1673cSZi Xuan Wu   }
63924d1673cSZi Xuan Wu 
64024d1673cSZi Xuan Wu   std::string CaseString;
64124d1673cSZi Xuan Wu   raw_string_ostream CaseStream(CaseString);
64224d1673cSZi Xuan Wu   StringRef PrevOp;
64324d1673cSZi Xuan Wu   StringRef CurOp;
64424d1673cSZi Xuan Wu   CaseStream << "  switch (MI.getOpcode()) {\n";
64524d1673cSZi Xuan Wu   CaseStream << "    default: return false;\n";
64624d1673cSZi Xuan Wu 
64724d1673cSZi Xuan Wu   bool CompressOrCheck =
64824d1673cSZi Xuan Wu       EType == EmitterType::Compress || EType == EmitterType::CheckCompress;
64924d1673cSZi Xuan Wu   bool CompressOrUncompress =
65024d1673cSZi Xuan Wu       EType == EmitterType::Compress || EType == EmitterType::Uncompress;
651fcc2e5aaSwangpc   std::string ValidatorName =
652fcc2e5aaSwangpc       CompressOrUncompress
653fcc2e5aaSwangpc           ? (TargetName + "ValidateMCOperandFor" +
654fcc2e5aaSwangpc              (EType == EmitterType::Compress ? "Compress" : "Uncompress"))
655fcc2e5aaSwangpc                 .str()
656fcc2e5aaSwangpc           : "";
65724d1673cSZi Xuan Wu 
65824d1673cSZi Xuan Wu   for (auto &CompressPat : CompressPatterns) {
65924d1673cSZi Xuan Wu     if (EType == EmitterType::Uncompress && CompressPat.IsCompressOnly)
66024d1673cSZi Xuan Wu       continue;
66124d1673cSZi Xuan Wu 
66224d1673cSZi Xuan Wu     std::string CondString;
66324d1673cSZi Xuan Wu     std::string CodeString;
66424d1673cSZi Xuan Wu     raw_string_ostream CondStream(CondString);
66524d1673cSZi Xuan Wu     raw_string_ostream CodeStream(CodeString);
66624d1673cSZi Xuan Wu     CodeGenInstruction &Source =
66724d1673cSZi Xuan Wu         CompressOrCheck ? CompressPat.Source : CompressPat.Dest;
66824d1673cSZi Xuan Wu     CodeGenInstruction &Dest =
66924d1673cSZi Xuan Wu         CompressOrCheck ? CompressPat.Dest : CompressPat.Source;
67024d1673cSZi Xuan Wu     IndexedMap<OpData> SourceOperandMap = CompressOrCheck
67124d1673cSZi Xuan Wu                                               ? CompressPat.SourceOperandMap
67224d1673cSZi Xuan Wu                                               : CompressPat.DestOperandMap;
67324d1673cSZi Xuan Wu     IndexedMap<OpData> &DestOperandMap = CompressOrCheck
67424d1673cSZi Xuan Wu                                              ? CompressPat.DestOperandMap
67524d1673cSZi Xuan Wu                                              : CompressPat.SourceOperandMap;
67624d1673cSZi Xuan Wu 
67724d1673cSZi Xuan Wu     CurOp = Source.TheDef->getName();
67824d1673cSZi Xuan Wu     // Check current and previous opcode to decide to continue or end a case.
67924d1673cSZi Xuan Wu     if (CurOp != PrevOp) {
68024d1673cSZi Xuan Wu       if (!PrevOp.empty())
68124d1673cSZi Xuan Wu         CaseStream.indent(6) << "break;\n    } // case " + PrevOp + "\n";
68224d1673cSZi Xuan Wu       CaseStream.indent(4) << "case " + TargetName + "::" + CurOp + ": {\n";
68324d1673cSZi Xuan Wu     }
68424d1673cSZi Xuan Wu 
68524d1673cSZi Xuan Wu     std::set<std::pair<bool, StringRef>> FeaturesSet;
68624d1673cSZi Xuan Wu     std::set<std::set<std::pair<bool, StringRef>>> AnyOfFeatureSets;
68724d1673cSZi Xuan Wu     // Add CompressPat required features.
68824d1673cSZi Xuan Wu     getReqFeatures(FeaturesSet, AnyOfFeatureSets, CompressPat.PatReqFeatures);
68924d1673cSZi Xuan Wu 
69024d1673cSZi Xuan Wu     // Add Dest instruction required features.
6912c966709SRahul Joshi     std::vector<const Record *> ReqFeatures;
6922c966709SRahul Joshi     std::vector<const Record *> RF =
693a140931bSRahul Joshi         Dest.TheDef->getValueAsListOfDefs("Predicates");
6942c966709SRahul Joshi     copy_if(RF, std::back_inserter(ReqFeatures), [](const Record *R) {
69524d1673cSZi Xuan Wu       return R->getValueAsBit("AssemblerMatcherPredicate");
69624d1673cSZi Xuan Wu     });
69724d1673cSZi Xuan Wu     getReqFeatures(FeaturesSet, AnyOfFeatureSets, ReqFeatures);
69824d1673cSZi Xuan Wu 
69924d1673cSZi Xuan Wu     // Emit checks for all required features.
70024d1673cSZi Xuan Wu     for (auto &Op : FeaturesSet) {
70124d1673cSZi Xuan Wu       StringRef Not = Op.first ? "!" : "";
70224d1673cSZi Xuan Wu       CondStream.indent(6) << Not << "STI.getFeatureBits()[" << TargetName
70324d1673cSZi Xuan Wu                            << "::" << Op.second << "]"
70424d1673cSZi Xuan Wu                            << " &&\n";
70524d1673cSZi Xuan Wu     }
70624d1673cSZi Xuan Wu 
70724d1673cSZi Xuan Wu     // Emit checks for all required feature groups.
70824d1673cSZi Xuan Wu     for (auto &Set : AnyOfFeatureSets) {
70924d1673cSZi Xuan Wu       CondStream.indent(6) << "(";
71024d1673cSZi Xuan Wu       for (auto &Op : Set) {
71144193a05SWang Pengcheng         bool IsLast = &Op == &*Set.rbegin();
71224d1673cSZi Xuan Wu         StringRef Not = Op.first ? "!" : "";
71324d1673cSZi Xuan Wu         CondStream << Not << "STI.getFeatureBits()[" << TargetName
71424d1673cSZi Xuan Wu                    << "::" << Op.second << "]";
71544193a05SWang Pengcheng         if (!IsLast)
71624d1673cSZi Xuan Wu           CondStream << " || ";
71724d1673cSZi Xuan Wu       }
71824d1673cSZi Xuan Wu       CondStream << ") &&\n";
71924d1673cSZi Xuan Wu     }
72024d1673cSZi Xuan Wu 
72124d1673cSZi Xuan Wu     // Start Source Inst operands validation.
72224d1673cSZi Xuan Wu     unsigned OpNo = 0;
72324d1673cSZi Xuan Wu     for (OpNo = 0; OpNo < Source.Operands.size(); ++OpNo) {
72424d1673cSZi Xuan Wu       if (SourceOperandMap[OpNo].TiedOpIdx != -1) {
72524d1673cSZi Xuan Wu         if (Source.Operands[OpNo].Rec->isSubClassOf("RegisterClass"))
72624d1673cSZi Xuan Wu           CondStream.indent(6)
727d51581ffSZHU Zijia               << "(MI.getOperand(" << OpNo << ").isReg()) && (MI.getOperand("
728d51581ffSZHU Zijia               << SourceOperandMap[OpNo].TiedOpIdx << ").isReg()) &&\n"
729d51581ffSZHU Zijia               << "      (MI.getOperand(" << OpNo
730d51581ffSZHU Zijia               << ").getReg() ==  MI.getOperand("
73124d1673cSZi Xuan Wu               << SourceOperandMap[OpNo].TiedOpIdx << ").getReg()) &&\n";
73224d1673cSZi Xuan Wu         else
73324d1673cSZi Xuan Wu           PrintFatalError("Unexpected tied operand types!\n");
73424d1673cSZi Xuan Wu       }
73524d1673cSZi Xuan Wu       // Check for fixed immediates\registers in the source instruction.
73624d1673cSZi Xuan Wu       switch (SourceOperandMap[OpNo].Kind) {
73724d1673cSZi Xuan Wu       case OpData::Operand:
73824d1673cSZi Xuan Wu         // We don't need to do anything for source instruction operand checks.
73924d1673cSZi Xuan Wu         break;
74024d1673cSZi Xuan Wu       case OpData::Imm:
74124d1673cSZi Xuan Wu         CondStream.indent(6)
74224d1673cSZi Xuan Wu             << "(MI.getOperand(" << OpNo << ").isImm()) &&\n"
74324d1673cSZi Xuan Wu             << "      (MI.getOperand(" << OpNo
74424d1673cSZi Xuan Wu             << ").getImm() == " << SourceOperandMap[OpNo].Data.Imm << ") &&\n";
74524d1673cSZi Xuan Wu         break;
74624d1673cSZi Xuan Wu       case OpData::Reg: {
7472c966709SRahul Joshi         const Record *Reg = SourceOperandMap[OpNo].Data.Reg;
74824d1673cSZi Xuan Wu         CondStream.indent(6)
749d51581ffSZHU Zijia             << "(MI.getOperand(" << OpNo << ").isReg()) &&\n"
75024d1673cSZi Xuan Wu             << "      (MI.getOperand(" << OpNo << ").getReg() == " << TargetName
75124d1673cSZi Xuan Wu             << "::" << Reg->getName() << ") &&\n";
75224d1673cSZi Xuan Wu         break;
75324d1673cSZi Xuan Wu       }
75424d1673cSZi Xuan Wu       }
75524d1673cSZi Xuan Wu     }
75624d1673cSZi Xuan Wu     CodeStream.indent(6) << "// " << Dest.AsmString << "\n";
75724d1673cSZi Xuan Wu     if (CompressOrUncompress)
75824d1673cSZi Xuan Wu       CodeStream.indent(6) << "OutInst.setOpcode(" << TargetName
75924d1673cSZi Xuan Wu                            << "::" << Dest.TheDef->getName() << ");\n";
76024d1673cSZi Xuan Wu     OpNo = 0;
76124d1673cSZi Xuan Wu     for (const auto &DestOperand : Dest.Operands) {
76224d1673cSZi Xuan Wu       CodeStream.indent(6) << "// Operand: " << DestOperand.Name << "\n";
76324d1673cSZi Xuan Wu       switch (DestOperandMap[OpNo].Kind) {
76424d1673cSZi Xuan Wu       case OpData::Operand: {
76524d1673cSZi Xuan Wu         unsigned OpIdx = DestOperandMap[OpNo].Data.Operand;
76624d1673cSZi Xuan Wu         // Check that the operand in the Source instruction fits
76724d1673cSZi Xuan Wu         // the type for the Dest instruction.
76895ef0052SDmitry Bushev         if (DestOperand.Rec->isSubClassOf("RegisterClass") ||
76995ef0052SDmitry Bushev             DestOperand.Rec->isSubClassOf("RegisterOperand")) {
77095ef0052SDmitry Bushev           auto *ClassRec = DestOperand.Rec->isSubClassOf("RegisterClass")
77195ef0052SDmitry Bushev                                ? DestOperand.Rec
77295ef0052SDmitry Bushev                                : DestOperand.Rec->getValueAsDef("RegClass");
77324d1673cSZi Xuan Wu           // This is a register operand. Check the register class.
77424d1673cSZi Xuan Wu           // Don't check register class if this is a tied operand, it was done
77524d1673cSZi Xuan Wu           // for the operand its tied to.
776*726cfc67SCraig Topper           if (DestOperand.getTiedRegister() == -1) {
777*726cfc67SCraig Topper             CondStream.indent(6) << "MI.getOperand(" << OpIdx << ").isReg()";
778*726cfc67SCraig Topper             if (EType == EmitterType::CheckCompress)
779*726cfc67SCraig Topper               CondStream << " && MI.getOperand(" << OpIdx
780*726cfc67SCraig Topper                          << ").getReg().isPhysical()";
781*726cfc67SCraig Topper             CondStream << " &&\n"
782*726cfc67SCraig Topper                        << indent(6) << TargetName << "MCRegisterClasses["
783*726cfc67SCraig Topper                        << TargetName << "::" << ClassRec->getName()
7840b38636fSCraig Topper                        << "RegClassID].contains(MI.getOperand(" << OpIdx
785*726cfc67SCraig Topper                        << ").getReg()) &&\n";
786*726cfc67SCraig Topper           }
78724d1673cSZi Xuan Wu 
78824d1673cSZi Xuan Wu           if (CompressOrUncompress)
78924d1673cSZi Xuan Wu             CodeStream.indent(6)
79024d1673cSZi Xuan Wu                 << "OutInst.addOperand(MI.getOperand(" << OpIdx << "));\n";
79124d1673cSZi Xuan Wu         } else {
79224d1673cSZi Xuan Wu           // Handling immediate operands.
79324d1673cSZi Xuan Wu           if (CompressOrUncompress) {
79424d1673cSZi Xuan Wu             unsigned Entry =
79524d1673cSZi Xuan Wu                 getPredicates(MCOpPredicateMap, MCOpPredicates, DestOperand.Rec,
79624d1673cSZi Xuan Wu                               "MCOperandPredicate");
79724d1673cSZi Xuan Wu             CondStream.indent(6)
798fcc2e5aaSwangpc                 << ValidatorName << "("
79924d1673cSZi Xuan Wu                 << "MI.getOperand(" << OpIdx << "), STI, " << Entry << ") &&\n";
80024d1673cSZi Xuan Wu           } else {
80124d1673cSZi Xuan Wu             unsigned Entry =
80224d1673cSZi Xuan Wu                 getPredicates(ImmLeafPredicateMap, ImmLeafPredicates,
80324d1673cSZi Xuan Wu                               DestOperand.Rec, "ImmediateCode");
80424d1673cSZi Xuan Wu             CondStream.indent(6)
80524d1673cSZi Xuan Wu                 << "MI.getOperand(" << OpIdx << ").isImm() &&\n";
80624d1673cSZi Xuan Wu             CondStream.indent(6) << TargetName << "ValidateMachineOperand("
80744193a05SWang Pengcheng                                  << "MI.getOperand(" << OpIdx << "), &STI, "
80844193a05SWang Pengcheng                                  << Entry << ") &&\n";
80924d1673cSZi Xuan Wu           }
81024d1673cSZi Xuan Wu           if (CompressOrUncompress)
81124d1673cSZi Xuan Wu             CodeStream.indent(6)
81224d1673cSZi Xuan Wu                 << "OutInst.addOperand(MI.getOperand(" << OpIdx << "));\n";
81324d1673cSZi Xuan Wu         }
81424d1673cSZi Xuan Wu         break;
81524d1673cSZi Xuan Wu       }
81624d1673cSZi Xuan Wu       case OpData::Imm: {
81724d1673cSZi Xuan Wu         if (CompressOrUncompress) {
81824d1673cSZi Xuan Wu           unsigned Entry = getPredicates(MCOpPredicateMap, MCOpPredicates,
81924d1673cSZi Xuan Wu                                          DestOperand.Rec, "MCOperandPredicate");
82024d1673cSZi Xuan Wu           CondStream.indent(6)
821fcc2e5aaSwangpc               << ValidatorName << "("
82224d1673cSZi Xuan Wu               << "MCOperand::createImm(" << DestOperandMap[OpNo].Data.Imm
82324d1673cSZi Xuan Wu               << "), STI, " << Entry << ") &&\n";
82424d1673cSZi Xuan Wu         } else {
82524d1673cSZi Xuan Wu           unsigned Entry = getPredicates(ImmLeafPredicateMap, ImmLeafPredicates,
82624d1673cSZi Xuan Wu                                          DestOperand.Rec, "ImmediateCode");
82724d1673cSZi Xuan Wu           CondStream.indent(6)
82824d1673cSZi Xuan Wu               << TargetName
82924d1673cSZi Xuan Wu               << "ValidateMachineOperand(MachineOperand::CreateImm("
830a971ce70SCraig Topper               << DestOperandMap[OpNo].Data.Imm << "), &STI, " << Entry
83124d1673cSZi Xuan Wu               << ") &&\n";
83224d1673cSZi Xuan Wu         }
83324d1673cSZi Xuan Wu         if (CompressOrUncompress)
83424d1673cSZi Xuan Wu           CodeStream.indent(6) << "OutInst.addOperand(MCOperand::createImm("
83524d1673cSZi Xuan Wu                                << DestOperandMap[OpNo].Data.Imm << "));\n";
83624d1673cSZi Xuan Wu       } break;
83724d1673cSZi Xuan Wu       case OpData::Reg: {
83824d1673cSZi Xuan Wu         if (CompressOrUncompress) {
83924d1673cSZi Xuan Wu           // Fixed register has been validated at pattern validation time.
8402c966709SRahul Joshi           const Record *Reg = DestOperandMap[OpNo].Data.Reg;
84124d1673cSZi Xuan Wu           CodeStream.indent(6)
84224d1673cSZi Xuan Wu               << "OutInst.addOperand(MCOperand::createReg(" << TargetName
84324d1673cSZi Xuan Wu               << "::" << Reg->getName() << "));\n";
84424d1673cSZi Xuan Wu         }
84524d1673cSZi Xuan Wu       } break;
84624d1673cSZi Xuan Wu       }
84724d1673cSZi Xuan Wu       ++OpNo;
84824d1673cSZi Xuan Wu     }
84924d1673cSZi Xuan Wu     if (CompressOrUncompress)
85024d1673cSZi Xuan Wu       CodeStream.indent(6) << "OutInst.setLoc(MI.getLoc());\n";
85134855405SYoungsuk Kim     mergeCondAndCode(CaseStream, CondString, CodeString);
85224d1673cSZi Xuan Wu     PrevOp = CurOp;
85324d1673cSZi Xuan Wu   }
85434855405SYoungsuk Kim   Func << CaseString << "\n";
85524d1673cSZi Xuan Wu   // Close brace for the last case.
85624d1673cSZi Xuan Wu   Func.indent(4) << "} // case " << CurOp << "\n";
85724d1673cSZi Xuan Wu   Func.indent(2) << "} // switch\n";
85824d1673cSZi Xuan Wu   Func.indent(2) << "return false;\n}\n";
85924d1673cSZi Xuan Wu 
86024d1673cSZi Xuan Wu   if (!MCOpPredicates.empty()) {
86144193a05SWang Pengcheng     OS << "static bool " << ValidatorName << "(const MCOperand &MCOp,\n"
86224d1673cSZi Xuan Wu        << "                  const MCSubtargetInfo &STI,\n"
86324d1673cSZi Xuan Wu        << "                  unsigned PredicateIndex) {\n"
86424d1673cSZi Xuan Wu        << "  switch (PredicateIndex) {\n"
86524d1673cSZi Xuan Wu        << "  default:\n"
86624d1673cSZi Xuan Wu        << "    llvm_unreachable(\"Unknown MCOperandPredicate kind\");\n"
86724d1673cSZi Xuan Wu        << "    break;\n";
86824d1673cSZi Xuan Wu 
86944193a05SWang Pengcheng     printPredicates(MCOpPredicates, "MCOperandPredicate", OS);
87024d1673cSZi Xuan Wu 
87144193a05SWang Pengcheng     OS << "  }\n"
87224d1673cSZi Xuan Wu        << "}\n\n";
87324d1673cSZi Xuan Wu   }
87424d1673cSZi Xuan Wu 
87524d1673cSZi Xuan Wu   if (!ImmLeafPredicates.empty()) {
87644193a05SWang Pengcheng     OS << "static bool " << TargetName
87724d1673cSZi Xuan Wu        << "ValidateMachineOperand(const MachineOperand &MO,\n"
87824d1673cSZi Xuan Wu        << "                  const " << TargetName << "Subtarget *Subtarget,\n"
87924d1673cSZi Xuan Wu        << "                  unsigned PredicateIndex) {\n"
88024d1673cSZi Xuan Wu        << "  int64_t Imm = MO.getImm();\n"
88124d1673cSZi Xuan Wu        << "  switch (PredicateIndex) {\n"
88224d1673cSZi Xuan Wu        << "  default:\n"
88324d1673cSZi Xuan Wu        << "    llvm_unreachable(\"Unknown ImmLeaf Predicate kind\");\n"
88424d1673cSZi Xuan Wu        << "    break;\n";
88524d1673cSZi Xuan Wu 
88644193a05SWang Pengcheng     printPredicates(ImmLeafPredicates, "ImmediateCode", OS);
88724d1673cSZi Xuan Wu 
88844193a05SWang Pengcheng     OS << "  }\n"
88924d1673cSZi Xuan Wu        << "}\n\n";
89024d1673cSZi Xuan Wu   }
89124d1673cSZi Xuan Wu 
89234855405SYoungsuk Kim   OS << FH;
89334855405SYoungsuk Kim   OS << F;
89424d1673cSZi Xuan Wu 
89524d1673cSZi Xuan Wu   if (EType == EmitterType::Compress)
89644193a05SWang Pengcheng     OS << "\n#endif //GEN_COMPRESS_INSTR\n";
89724d1673cSZi Xuan Wu   else if (EType == EmitterType::Uncompress)
89844193a05SWang Pengcheng     OS << "\n#endif //GEN_UNCOMPRESS_INSTR\n\n";
89924d1673cSZi Xuan Wu   else if (EType == EmitterType::CheckCompress)
90044193a05SWang Pengcheng     OS << "\n#endif //GEN_CHECK_COMPRESS_INSTR\n\n";
90124d1673cSZi Xuan Wu }
90224d1673cSZi Xuan Wu 
90344193a05SWang Pengcheng void CompressInstEmitter::run(raw_ostream &OS) {
90424d1673cSZi Xuan Wu   // Process the CompressPat definitions, validating them as we do so.
9052c966709SRahul Joshi   for (const Record *Pat : Records.getAllDerivedDefinitions("CompressPat"))
9062c966709SRahul Joshi     evaluateCompressPat(Pat);
90724d1673cSZi Xuan Wu 
90824d1673cSZi Xuan Wu   // Emit file header.
90944193a05SWang Pengcheng   emitSourceFileHeader("Compress instruction Source Fragment", OS, Records);
91024d1673cSZi Xuan Wu   // Generate compressInst() function.
91144193a05SWang Pengcheng   emitCompressInstEmitter(OS, EmitterType::Compress);
91224d1673cSZi Xuan Wu   // Generate uncompressInst() function.
91344193a05SWang Pengcheng   emitCompressInstEmitter(OS, EmitterType::Uncompress);
91424d1673cSZi Xuan Wu   // Generate isCompressibleInst() function.
91544193a05SWang Pengcheng   emitCompressInstEmitter(OS, EmitterType::CheckCompress);
91624d1673cSZi Xuan Wu }
91724d1673cSZi Xuan Wu 
9189c93e728SNAKAMURA Takumi static TableGen::Emitter::OptClass<CompressInstEmitter>
9190f4c9c01SCraig Topper     X("gen-compress-inst-emitter", "Generate compressed instructions.");
920