//===-------- CompressInstEmitter.cpp - Generator for Compression ---------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // // CompressInstEmitter implements a tablegen-driven CompressPat based // Instruction Compression mechanism. // //===----------------------------------------------------------------------===// // // CompressInstEmitter implements a tablegen-driven CompressPat Instruction // Compression mechanism for generating compressed instructions from the // expanded instruction form. // This tablegen backend processes CompressPat declarations in a // td file and generates all the required checks to validate the pattern // declarations; validate the input and output operands to generate the correct // compressed instructions. The checks include validating different types of // operands; register operands, immediate operands, fixed register and fixed // immediate inputs. // // Example: // /// Defines a Pat match between compressed and uncompressed instruction. // /// The relationship and helper function generation are handled by // /// CompressInstEmitter backend. // class CompressPat<dag input, dag output, list<Predicate> predicates = []> { // /// Uncompressed instruction description. // dag Input = input; // /// Compressed instruction description. // dag Output = output; // /// Predicates that must be true for this to match. // list<Predicate> Predicates = predicates; // /// Duplicate match when tied operand is just different. // bit isCompressOnly = false; // } // // let Predicates = [HasStdExtC] in { // def : CompressPat<(ADD GPRNoX0:$rs1, GPRNoX0:$rs1, GPRNoX0:$rs2), // (C_ADD GPRNoX0:$rs1, GPRNoX0:$rs2)>; // } // // The <TargetName>GenCompressInstEmitter.inc is an auto-generated header // file which exports two functions for compressing/uncompressing MCInst // instructions, plus some helper functions: // // bool compressInst(MCInst &OutInst, const MCInst &MI, // const MCSubtargetInfo &STI); // // bool uncompressInst(MCInst &OutInst, const MCInst &MI, // const MCSubtargetInfo &STI); // // In addition, it exports a function for checking whether // an instruction is compressable: // // bool isCompressibleInst(const MachineInstr& MI, // const <TargetName>Subtarget &STI); // // The clients that include this auto-generated header file and // invoke these functions can compress an instruction before emitting // it in the target-specific ASM or ELF streamer or can uncompress // an instruction before printing it when the expanded instruction // format aliases is favored. //===----------------------------------------------------------------------===// #include "Common/CodeGenInstruction.h" #include "Common/CodeGenRegisters.h" #include "Common/CodeGenTarget.h" #include "llvm/ADT/IndexedMap.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" #include "llvm/TableGen/TableGenBackend.h" #include <set> #include <vector> usingnamespacellvm; #define DEBUG_TYPE … namespace { class CompressInstEmitter { … }; } // End anonymous namespace. bool CompressInstEmitter::validateRegister(const Record *Reg, const Record *RegClass) { … } bool CompressInstEmitter::validateTypes(const Record *DagOpType, const Record *InstOpType, bool IsSourceInst) { … } /// The patterns in the Dag contain different types of operands: /// Register operands, e.g.: GPRC:$rs1; Fixed registers, e.g: X1; Immediate /// operands, e.g.: simm6:$imm; Fixed immediate operands, e.g.: 0. This function /// maps Dag operands to its corresponding instruction operands. For register /// operands and fixed registers it expects the Dag operand type to be contained /// in the instantiated instruction operand type. For immediate operands and /// immediates no validation checks are enforced at pattern validation time. void CompressInstEmitter::addDagOperandMapping(const Record *Rec, const DagInit *Dag, const CodeGenInstruction &Inst, IndexedMap<OpData> &OperandMap, bool IsSourceInst) { … } // Verify the Dag operand count is enough to build an instruction. static bool verifyDagOpCount(const CodeGenInstruction &Inst, const DagInit *Dag, bool IsSource) { … } static bool validateArgsTypes(const Init *Arg1, const Init *Arg2) { … } // Creates a mapping between the operand name in the Dag (e.g. $rs1) and // its index in the list of Dag operands and checks that operands with the same // name have the same types. For example in 'C_ADD $rs1, $rs2' we generate the // mapping $rs1 --> 0, $rs2 ---> 1. If the operand appears twice in the (tied) // same Dag we use the last occurrence for indexing. void CompressInstEmitter::createDagOperandMapping( const Record *Rec, StringMap<unsigned> &SourceOperands, StringMap<unsigned> &DestOperands, const DagInit *SourceDag, const DagInit *DestDag, IndexedMap<OpData> &SourceOperandMap) { … } /// Map operand names in the Dag to their index in both corresponding input and /// output instructions. Validate that operands defined in the input are /// used in the output pattern while populating the maps. void CompressInstEmitter::createInstOperandMapping( const Record *Rec, const DagInit *SourceDag, const DagInit *DestDag, IndexedMap<OpData> &SourceOperandMap, IndexedMap<OpData> &DestOperandMap, StringMap<unsigned> &SourceOperands, const CodeGenInstruction &DestInst) { … } /// Validates the CompressPattern and create operand mapping. /// These are the checks to validate a CompressPat pattern declarations. /// Error out with message under these conditions: /// - Dag Input opcode is an expanded instruction and Dag Output opcode is a /// compressed instruction. /// - Operands in Dag Input must be all used in Dag Output. /// Register Operand type in Dag Input Type must be contained in the /// corresponding Source Instruction type. /// - Register Operand type in Dag Input must be the same as in Dag Ouput. /// - Register Operand type in Dag Output must be the same as the /// corresponding Destination Inst type. /// - Immediate Operand type in Dag Input must be the same as in Dag Ouput. /// - Immediate Operand type in Dag Ouput must be the same as the corresponding /// Destination Instruction type. /// - Fixed register must be contained in the corresponding Source Instruction /// type. /// - Fixed register must be contained in the corresponding Destination /// Instruction type. /// Warning message printed under these conditions: /// - Fixed immediate in Dag Input or Dag Ouput cannot be checked at this time /// and generate warning. /// - Immediate operand type in Dag Input differs from the corresponding Source /// Instruction type and generate a warning. void CompressInstEmitter::evaluateCompressPat(const Record *Rec) { … } static void getReqFeatures(std::set<std::pair<bool, StringRef>> &FeaturesSet, std::set<std::set<std::pair<bool, StringRef>>> &AnyOfFeatureSets, ArrayRef<const Record *> ReqFeatures) { … } static unsigned getPredicates(DenseMap<const Record *, unsigned> &PredicateMap, std::vector<const Record *> &Predicates, const Record *Rec, StringRef Name) { … } static void printPredicates(ArrayRef<const Record *> Predicates, StringRef Name, raw_ostream &OS) { … } static void mergeCondAndCode(raw_ostream &CombinedStream, StringRef CondStr, StringRef CodeStr) { … } void CompressInstEmitter::emitCompressInstEmitter(raw_ostream &OS, EmitterType EType) { … } void CompressInstEmitter::run(raw_ostream &OS) { … } static TableGen::Emitter::OptClass<CompressInstEmitter> X("gen-compress-inst-emitter", "Generate compressed instructions.");