123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911 |
- //===-------- 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 "CodeGenInstruction.h"
- #include "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>
- using namespace llvm;
- #define DEBUG_TYPE "compress-inst-emitter"
- namespace {
- class CompressInstEmitter {
- struct OpData {
- enum MapKind { Operand, Imm, Reg };
- MapKind Kind;
- union {
- // Operand number mapped to.
- unsigned Operand;
- // Integer immediate value.
- int64_t Imm;
- // Physical register.
- Record *Reg;
- } Data;
- // Tied operand index within the instruction.
- int TiedOpIdx = -1;
- };
- struct CompressPat {
- // The source instruction definition.
- CodeGenInstruction Source;
- // The destination instruction to transform to.
- CodeGenInstruction Dest;
- // Required target features to enable pattern.
- std::vector<Record *> PatReqFeatures;
- // Maps operands in the Source Instruction to
- IndexedMap<OpData> SourceOperandMap;
- // the corresponding Dest instruction operand.
- // Maps operands in the Dest Instruction
- // to the corresponding Source instruction operand.
- IndexedMap<OpData> DestOperandMap;
- bool IsCompressOnly;
- CompressPat(CodeGenInstruction &S, CodeGenInstruction &D,
- std::vector<Record *> RF, IndexedMap<OpData> &SourceMap,
- IndexedMap<OpData> &DestMap, bool IsCompressOnly)
- : Source(S), Dest(D), PatReqFeatures(RF), SourceOperandMap(SourceMap),
- DestOperandMap(DestMap), IsCompressOnly(IsCompressOnly) {}
- };
- enum EmitterType { Compress, Uncompress, CheckCompress };
- RecordKeeper &Records;
- CodeGenTarget Target;
- SmallVector<CompressPat, 4> CompressPatterns;
- void addDagOperandMapping(Record *Rec, DagInit *Dag, CodeGenInstruction &Inst,
- IndexedMap<OpData> &OperandMap, bool IsSourceInst);
- void evaluateCompressPat(Record *Compress);
- void emitCompressInstEmitter(raw_ostream &o, EmitterType EType);
- bool validateTypes(Record *SubType, Record *Type, bool IsSourceInst);
- bool validateRegister(Record *Reg, Record *RegClass);
- void createDagOperandMapping(Record *Rec, StringMap<unsigned> &SourceOperands,
- StringMap<unsigned> &DestOperands,
- DagInit *SourceDag, DagInit *DestDag,
- IndexedMap<OpData> &SourceOperandMap);
- void createInstOperandMapping(Record *Rec, DagInit *SourceDag,
- DagInit *DestDag,
- IndexedMap<OpData> &SourceOperandMap,
- IndexedMap<OpData> &DestOperandMap,
- StringMap<unsigned> &SourceOperands,
- CodeGenInstruction &DestInst);
- public:
- CompressInstEmitter(RecordKeeper &R) : Records(R), Target(R) {}
- void run(raw_ostream &o);
- };
- } // End anonymous namespace.
- bool CompressInstEmitter::validateRegister(Record *Reg, Record *RegClass) {
- assert(Reg->isSubClassOf("Register") && "Reg record should be a Register");
- assert(RegClass->isSubClassOf("RegisterClass") &&
- "RegClass record should be a RegisterClass");
- const CodeGenRegisterClass &RC = Target.getRegisterClass(RegClass);
- const CodeGenRegister *R = Target.getRegisterByName(Reg->getName().lower());
- assert((R != nullptr) && "Register not defined!!");
- return RC.contains(R);
- }
- bool CompressInstEmitter::validateTypes(Record *DagOpType, Record *InstOpType,
- bool IsSourceInst) {
- if (DagOpType == InstOpType)
- return true;
- // Only source instruction operands are allowed to not match Input Dag
- // operands.
- if (!IsSourceInst)
- return false;
- if (DagOpType->isSubClassOf("RegisterClass") &&
- InstOpType->isSubClassOf("RegisterClass")) {
- const CodeGenRegisterClass &RC = Target.getRegisterClass(InstOpType);
- const CodeGenRegisterClass &SubRC = Target.getRegisterClass(DagOpType);
- return RC.hasSubClass(&SubRC);
- }
- // At this point either or both types are not registers, reject the pattern.
- if (DagOpType->isSubClassOf("RegisterClass") ||
- InstOpType->isSubClassOf("RegisterClass"))
- return false;
- // Let further validation happen when compress()/uncompress() functions are
- // invoked.
- LLVM_DEBUG(dbgs() << (IsSourceInst ? "Input" : "Output")
- << " Dag Operand Type: '" << DagOpType->getName()
- << "' and "
- << "Instruction Operand Type: '" << InstOpType->getName()
- << "' can't be checked at pattern validation time!\n");
- return true;
- }
- /// 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(Record *Rec, DagInit *Dag,
- CodeGenInstruction &Inst,
- IndexedMap<OpData> &OperandMap,
- bool IsSourceInst) {
- // TiedCount keeps track of the number of operands skipped in Inst
- // operands list to get to the corresponding Dag operand. This is
- // necessary because the number of operands in Inst might be greater
- // than number of operands in the Dag due to how tied operands
- // are represented.
- unsigned TiedCount = 0;
- for (unsigned i = 0, e = Inst.Operands.size(); i != e; ++i) {
- int TiedOpIdx = Inst.Operands[i].getTiedRegister();
- if (-1 != TiedOpIdx) {
- // Set the entry in OperandMap for the tied operand we're skipping.
- OperandMap[i].Kind = OperandMap[TiedOpIdx].Kind;
- OperandMap[i].Data = OperandMap[TiedOpIdx].Data;
- TiedCount++;
- continue;
- }
- if (DefInit *DI = dyn_cast<DefInit>(Dag->getArg(i - TiedCount))) {
- if (DI->getDef()->isSubClassOf("Register")) {
- // Check if the fixed register belongs to the Register class.
- if (!validateRegister(DI->getDef(), Inst.Operands[i].Rec))
- PrintFatalError(Rec->getLoc(),
- "Error in Dag '" + Dag->getAsString() +
- "'Register: '" + DI->getDef()->getName() +
- "' is not in register class '" +
- Inst.Operands[i].Rec->getName() + "'");
- OperandMap[i].Kind = OpData::Reg;
- OperandMap[i].Data.Reg = DI->getDef();
- continue;
- }
- // Validate that Dag operand type matches the type defined in the
- // corresponding instruction. Operands in the input Dag pattern are
- // allowed to be a subclass of the type specified in corresponding
- // instruction operand instead of being an exact match.
- if (!validateTypes(DI->getDef(), Inst.Operands[i].Rec, IsSourceInst))
- PrintFatalError(Rec->getLoc(),
- "Error in Dag '" + Dag->getAsString() + "'. Operand '" +
- Dag->getArgNameStr(i - TiedCount) + "' has type '" +
- DI->getDef()->getName() +
- "' which does not match the type '" +
- Inst.Operands[i].Rec->getName() +
- "' in the corresponding instruction operand!");
- OperandMap[i].Kind = OpData::Operand;
- } else if (IntInit *II = dyn_cast<IntInit>(Dag->getArg(i - TiedCount))) {
- // Validate that corresponding instruction operand expects an immediate.
- if (Inst.Operands[i].Rec->isSubClassOf("RegisterClass"))
- PrintFatalError(
- Rec->getLoc(),
- "Error in Dag '" + Dag->getAsString() + "' Found immediate: '" +
- II->getAsString() +
- "' but corresponding instruction operand expected a register!");
- // No pattern validation check possible for values of fixed immediate.
- OperandMap[i].Kind = OpData::Imm;
- OperandMap[i].Data.Imm = II->getValue();
- LLVM_DEBUG(
- dbgs() << " Found immediate '" << II->getValue() << "' at "
- << (IsSourceInst ? "input " : "output ")
- << "Dag. No validation time check possible for values of "
- "fixed immediate.\n");
- } else
- llvm_unreachable("Unhandled CompressPat argument type!");
- }
- }
- // Verify the Dag operand count is enough to build an instruction.
- static bool verifyDagOpCount(CodeGenInstruction &Inst, DagInit *Dag,
- bool IsSource) {
- if (Dag->getNumArgs() == Inst.Operands.size())
- return true;
- // Source instructions are non compressed instructions and don't have tied
- // operands.
- if (IsSource)
- PrintFatalError(Inst.TheDef->getLoc(),
- "Input operands for Inst '" + Inst.TheDef->getName() +
- "' and input Dag operand count mismatch");
- // The Dag can't have more arguments than the Instruction.
- if (Dag->getNumArgs() > Inst.Operands.size())
- PrintFatalError(Inst.TheDef->getLoc(),
- "Inst '" + Inst.TheDef->getName() +
- "' and Dag operand count mismatch");
- // The Instruction might have tied operands so the Dag might have
- // a fewer operand count.
- unsigned RealCount = Inst.Operands.size();
- for (const auto &Operand : Inst.Operands)
- if (Operand.getTiedRegister() != -1)
- --RealCount;
- if (Dag->getNumArgs() != RealCount)
- PrintFatalError(Inst.TheDef->getLoc(),
- "Inst '" + Inst.TheDef->getName() +
- "' and Dag operand count mismatch");
- return true;
- }
- static bool validateArgsTypes(Init *Arg1, Init *Arg2) {
- return cast<DefInit>(Arg1)->getDef() == cast<DefInit>(Arg2)->getDef();
- }
- // 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(
- Record *Rec, StringMap<unsigned> &SourceOperands,
- StringMap<unsigned> &DestOperands, DagInit *SourceDag, DagInit *DestDag,
- IndexedMap<OpData> &SourceOperandMap) {
- for (unsigned i = 0; i < DestDag->getNumArgs(); ++i) {
- // Skip fixed immediates and registers, they were handled in
- // addDagOperandMapping.
- if ("" == DestDag->getArgNameStr(i))
- continue;
- DestOperands[DestDag->getArgNameStr(i)] = i;
- }
- for (unsigned i = 0; i < SourceDag->getNumArgs(); ++i) {
- // Skip fixed immediates and registers, they were handled in
- // addDagOperandMapping.
- if ("" == SourceDag->getArgNameStr(i))
- continue;
- StringMap<unsigned>::iterator it =
- SourceOperands.find(SourceDag->getArgNameStr(i));
- if (it != SourceOperands.end()) {
- // Operand sharing the same name in the Dag should be mapped as tied.
- SourceOperandMap[i].TiedOpIdx = it->getValue();
- if (!validateArgsTypes(SourceDag->getArg(it->getValue()),
- SourceDag->getArg(i)))
- PrintFatalError(Rec->getLoc(),
- "Input Operand '" + SourceDag->getArgNameStr(i) +
- "' has a mismatched tied operand!\n");
- }
- it = DestOperands.find(SourceDag->getArgNameStr(i));
- if (it == DestOperands.end())
- PrintFatalError(Rec->getLoc(), "Operand " + SourceDag->getArgNameStr(i) +
- " defined in Input Dag but not used in"
- " Output Dag!\n");
- // Input Dag operand types must match output Dag operand type.
- if (!validateArgsTypes(DestDag->getArg(it->getValue()),
- SourceDag->getArg(i)))
- PrintFatalError(Rec->getLoc(), "Type mismatch between Input and "
- "Output Dag operand '" +
- SourceDag->getArgNameStr(i) + "'!");
- SourceOperands[SourceDag->getArgNameStr(i)] = i;
- }
- }
- /// 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(
- Record *Rec, DagInit *SourceDag, DagInit *DestDag,
- IndexedMap<OpData> &SourceOperandMap, IndexedMap<OpData> &DestOperandMap,
- StringMap<unsigned> &SourceOperands, CodeGenInstruction &DestInst) {
- // TiedCount keeps track of the number of operands skipped in Inst
- // operands list to get to the corresponding Dag operand.
- unsigned TiedCount = 0;
- LLVM_DEBUG(dbgs() << " Operand mapping:\n Source Dest\n");
- for (unsigned i = 0, e = DestInst.Operands.size(); i != e; ++i) {
- int TiedInstOpIdx = DestInst.Operands[i].getTiedRegister();
- if (TiedInstOpIdx != -1) {
- ++TiedCount;
- DestOperandMap[i].Data = DestOperandMap[TiedInstOpIdx].Data;
- DestOperandMap[i].Kind = DestOperandMap[TiedInstOpIdx].Kind;
- if (DestOperandMap[i].Kind == OpData::Operand)
- // No need to fill the SourceOperandMap here since it was mapped to
- // destination operand 'TiedInstOpIdx' in a previous iteration.
- LLVM_DEBUG(dbgs() << " " << DestOperandMap[i].Data.Operand
- << " ====> " << i
- << " Dest operand tied with operand '"
- << TiedInstOpIdx << "'\n");
- continue;
- }
- // Skip fixed immediates and registers, they were handled in
- // addDagOperandMapping.
- if (DestOperandMap[i].Kind != OpData::Operand)
- continue;
- unsigned DagArgIdx = i - TiedCount;
- StringMap<unsigned>::iterator SourceOp =
- SourceOperands.find(DestDag->getArgNameStr(DagArgIdx));
- if (SourceOp == SourceOperands.end())
- PrintFatalError(Rec->getLoc(),
- "Output Dag operand '" +
- DestDag->getArgNameStr(DagArgIdx) +
- "' has no matching input Dag operand.");
- assert(DestDag->getArgNameStr(DagArgIdx) ==
- SourceDag->getArgNameStr(SourceOp->getValue()) &&
- "Incorrect operand mapping detected!\n");
- DestOperandMap[i].Data.Operand = SourceOp->getValue();
- SourceOperandMap[SourceOp->getValue()].Data.Operand = i;
- LLVM_DEBUG(dbgs() << " " << SourceOp->getValue() << " ====> " << i
- << "\n");
- }
- }
- /// 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(Record *Rec) {
- // Validate input Dag operands.
- DagInit *SourceDag = Rec->getValueAsDag("Input");
- assert(SourceDag && "Missing 'Input' in compress pattern!");
- LLVM_DEBUG(dbgs() << "Input: " << *SourceDag << "\n");
- // Checking we are transforming from compressed to uncompressed instructions.
- Record *Operator = SourceDag->getOperatorAsDef(Rec->getLoc());
- CodeGenInstruction SourceInst(Operator);
- verifyDagOpCount(SourceInst, SourceDag, true);
- // Validate output Dag operands.
- DagInit *DestDag = Rec->getValueAsDag("Output");
- assert(DestDag && "Missing 'Output' in compress pattern!");
- LLVM_DEBUG(dbgs() << "Output: " << *DestDag << "\n");
- Record *DestOperator = DestDag->getOperatorAsDef(Rec->getLoc());
- CodeGenInstruction DestInst(DestOperator);
- verifyDagOpCount(DestInst, DestDag, false);
- if (Operator->getValueAsInt("Size") <= DestOperator->getValueAsInt("Size"))
- PrintFatalError(
- Rec->getLoc(),
- "Compressed instruction '" + DestOperator->getName() +
- "'is not strictly smaller than the uncompressed instruction '" +
- Operator->getName() + "' !");
- // Fill the mapping from the source to destination instructions.
- IndexedMap<OpData> SourceOperandMap;
- SourceOperandMap.grow(SourceInst.Operands.size());
- // Create a mapping between source Dag operands and source Inst operands.
- addDagOperandMapping(Rec, SourceDag, SourceInst, SourceOperandMap,
- /*IsSourceInst*/ true);
- IndexedMap<OpData> DestOperandMap;
- DestOperandMap.grow(DestInst.Operands.size());
- // Create a mapping between destination Dag operands and destination Inst
- // operands.
- addDagOperandMapping(Rec, DestDag, DestInst, DestOperandMap,
- /*IsSourceInst*/ false);
- StringMap<unsigned> SourceOperands;
- StringMap<unsigned> DestOperands;
- createDagOperandMapping(Rec, SourceOperands, DestOperands, SourceDag, DestDag,
- SourceOperandMap);
- // Create operand mapping between the source and destination instructions.
- createInstOperandMapping(Rec, SourceDag, DestDag, SourceOperandMap,
- DestOperandMap, SourceOperands, DestInst);
- // Get the target features for the CompressPat.
- std::vector<Record *> PatReqFeatures;
- std::vector<Record *> RF = Rec->getValueAsListOfDefs("Predicates");
- copy_if(RF, std::back_inserter(PatReqFeatures), [](Record *R) {
- return R->getValueAsBit("AssemblerMatcherPredicate");
- });
- CompressPatterns.push_back(CompressPat(SourceInst, DestInst, PatReqFeatures,
- SourceOperandMap, DestOperandMap,
- Rec->getValueAsBit("isCompressOnly")));
- }
- static void
- getReqFeatures(std::set<std::pair<bool, StringRef>> &FeaturesSet,
- std::set<std::set<std::pair<bool, StringRef>>> &AnyOfFeatureSets,
- const std::vector<Record *> &ReqFeatures) {
- for (auto &R : ReqFeatures) {
- const DagInit *D = R->getValueAsDag("AssemblerCondDag");
- std::string CombineType = D->getOperator()->getAsString();
- if (CombineType != "any_of" && CombineType != "all_of")
- PrintFatalError(R->getLoc(), "Invalid AssemblerCondDag!");
- if (D->getNumArgs() == 0)
- PrintFatalError(R->getLoc(), "Invalid AssemblerCondDag!");
- bool IsOr = CombineType == "any_of";
- std::set<std::pair<bool, StringRef>> AnyOfSet;
- for (auto *Arg : D->getArgs()) {
- bool IsNot = false;
- if (auto *NotArg = dyn_cast<DagInit>(Arg)) {
- if (NotArg->getOperator()->getAsString() != "not" ||
- NotArg->getNumArgs() != 1)
- PrintFatalError(R->getLoc(), "Invalid AssemblerCondDag!");
- Arg = NotArg->getArg(0);
- IsNot = true;
- }
- if (!isa<DefInit>(Arg) ||
- !cast<DefInit>(Arg)->getDef()->isSubClassOf("SubtargetFeature"))
- PrintFatalError(R->getLoc(), "Invalid AssemblerCondDag!");
- if (IsOr)
- AnyOfSet.insert({IsNot, cast<DefInit>(Arg)->getDef()->getName()});
- else
- FeaturesSet.insert({IsNot, cast<DefInit>(Arg)->getDef()->getName()});
- }
- if (IsOr)
- AnyOfFeatureSets.insert(AnyOfSet);
- }
- }
- static unsigned getPredicates(DenseMap<const Record *, unsigned> &PredicateMap,
- std::vector<const Record *> &Predicates,
- Record *Rec, StringRef Name) {
- unsigned &Entry = PredicateMap[Rec];
- if (Entry)
- return Entry;
- if (!Rec->isValueUnset(Name)) {
- Predicates.push_back(Rec);
- Entry = Predicates.size();
- return Entry;
- }
- PrintFatalError(Rec->getLoc(), "No " + Name +
- " predicate on this operand at all: '" +
- Rec->getName() + "'");
- return 0;
- }
- static void printPredicates(const std::vector<const Record *> &Predicates,
- StringRef Name, raw_ostream &o) {
- for (unsigned i = 0; i < Predicates.size(); ++i) {
- StringRef Pred = Predicates[i]->getValueAsString(Name);
- o << " case " << i + 1 << ": {\n"
- << " // " << Predicates[i]->getName() << "\n"
- << " " << Pred << "\n"
- << " }\n";
- }
- }
- static void mergeCondAndCode(raw_ostream &CombinedStream, StringRef CondStr,
- StringRef CodeStr) {
- // Remove first indentation and last '&&'.
- CondStr = CondStr.drop_front(6).drop_back(4);
- CombinedStream.indent(4) << "if (" << CondStr << ") {\n";
- CombinedStream << CodeStr;
- CombinedStream.indent(4) << " return true;\n";
- CombinedStream.indent(4) << "} // if\n";
- }
- void CompressInstEmitter::emitCompressInstEmitter(raw_ostream &o,
- EmitterType EType) {
- Record *AsmWriter = Target.getAsmWriter();
- if (!AsmWriter->getValueAsInt("PassSubtarget"))
- PrintFatalError(AsmWriter->getLoc(),
- "'PassSubtarget' is false. SubTargetInfo object is needed "
- "for target features.\n");
- StringRef TargetName = Target.getName();
- // Sort entries in CompressPatterns to handle instructions that can have more
- // than one candidate for compression\uncompression, e.g ADD can be
- // transformed to a C_ADD or a C_MV. When emitting 'uncompress()' function the
- // source and destination are flipped and the sort key needs to change
- // accordingly.
- llvm::stable_sort(CompressPatterns, [EType](const CompressPat &LHS,
- const CompressPat &RHS) {
- if (EType == EmitterType::Compress || EType == EmitterType::CheckCompress)
- return (LHS.Source.TheDef->getName() < RHS.Source.TheDef->getName());
- else
- return (LHS.Dest.TheDef->getName() < RHS.Dest.TheDef->getName());
- });
- // A list of MCOperandPredicates for all operands in use, and the reverse map.
- std::vector<const Record *> MCOpPredicates;
- DenseMap<const Record *, unsigned> MCOpPredicateMap;
- // A list of ImmLeaf Predicates for all operands in use, and the reverse map.
- std::vector<const Record *> ImmLeafPredicates;
- DenseMap<const Record *, unsigned> ImmLeafPredicateMap;
- std::string F;
- std::string FH;
- raw_string_ostream Func(F);
- raw_string_ostream FuncH(FH);
- if (EType == EmitterType::Compress)
- o << "\n#ifdef GEN_COMPRESS_INSTR\n"
- << "#undef GEN_COMPRESS_INSTR\n\n";
- else if (EType == EmitterType::Uncompress)
- o << "\n#ifdef GEN_UNCOMPRESS_INSTR\n"
- << "#undef GEN_UNCOMPRESS_INSTR\n\n";
- else if (EType == EmitterType::CheckCompress)
- o << "\n#ifdef GEN_CHECK_COMPRESS_INSTR\n"
- << "#undef GEN_CHECK_COMPRESS_INSTR\n\n";
- if (EType == EmitterType::Compress) {
- FuncH << "static bool compressInst(MCInst &OutInst,\n";
- FuncH.indent(25) << "const MCInst &MI,\n";
- FuncH.indent(25) << "const MCSubtargetInfo &STI) {\n";
- } else if (EType == EmitterType::Uncompress) {
- FuncH << "static bool uncompressInst(MCInst &OutInst,\n";
- FuncH.indent(27) << "const MCInst &MI,\n";
- FuncH.indent(27) << "const MCSubtargetInfo &STI) {\n";
- } else if (EType == EmitterType::CheckCompress) {
- FuncH << "static bool isCompressibleInst(const MachineInstr &MI,\n";
- FuncH.indent(31) << "const " << TargetName << "Subtarget &STI) {\n";
- }
- if (CompressPatterns.empty()) {
- o << FuncH.str();
- o.indent(2) << "return false;\n}\n";
- if (EType == EmitterType::Compress)
- o << "\n#endif //GEN_COMPRESS_INSTR\n";
- else if (EType == EmitterType::Uncompress)
- o << "\n#endif //GEN_UNCOMPRESS_INSTR\n\n";
- else if (EType == EmitterType::CheckCompress)
- o << "\n#endif //GEN_CHECK_COMPRESS_INSTR\n\n";
- return;
- }
- std::string CaseString;
- raw_string_ostream CaseStream(CaseString);
- StringRef PrevOp;
- StringRef CurOp;
- CaseStream << " switch (MI.getOpcode()) {\n";
- CaseStream << " default: return false;\n";
- bool CompressOrCheck =
- EType == EmitterType::Compress || EType == EmitterType::CheckCompress;
- bool CompressOrUncompress =
- EType == EmitterType::Compress || EType == EmitterType::Uncompress;
- std::string ValidatorName =
- CompressOrUncompress
- ? (TargetName + "ValidateMCOperandFor" +
- (EType == EmitterType::Compress ? "Compress" : "Uncompress"))
- .str()
- : "";
- for (auto &CompressPat : CompressPatterns) {
- if (EType == EmitterType::Uncompress && CompressPat.IsCompressOnly)
- continue;
- std::string CondString;
- std::string CodeString;
- raw_string_ostream CondStream(CondString);
- raw_string_ostream CodeStream(CodeString);
- CodeGenInstruction &Source =
- CompressOrCheck ? CompressPat.Source : CompressPat.Dest;
- CodeGenInstruction &Dest =
- CompressOrCheck ? CompressPat.Dest : CompressPat.Source;
- IndexedMap<OpData> SourceOperandMap = CompressOrCheck
- ? CompressPat.SourceOperandMap
- : CompressPat.DestOperandMap;
- IndexedMap<OpData> &DestOperandMap = CompressOrCheck
- ? CompressPat.DestOperandMap
- : CompressPat.SourceOperandMap;
- CurOp = Source.TheDef->getName();
- // Check current and previous opcode to decide to continue or end a case.
- if (CurOp != PrevOp) {
- if (!PrevOp.empty())
- CaseStream.indent(6) << "break;\n } // case " + PrevOp + "\n";
- CaseStream.indent(4) << "case " + TargetName + "::" + CurOp + ": {\n";
- }
- std::set<std::pair<bool, StringRef>> FeaturesSet;
- std::set<std::set<std::pair<bool, StringRef>>> AnyOfFeatureSets;
- // Add CompressPat required features.
- getReqFeatures(FeaturesSet, AnyOfFeatureSets, CompressPat.PatReqFeatures);
- // Add Dest instruction required features.
- std::vector<Record *> ReqFeatures;
- std::vector<Record *> RF = Dest.TheDef->getValueAsListOfDefs("Predicates");
- copy_if(RF, std::back_inserter(ReqFeatures), [](Record *R) {
- return R->getValueAsBit("AssemblerMatcherPredicate");
- });
- getReqFeatures(FeaturesSet, AnyOfFeatureSets, ReqFeatures);
- // Emit checks for all required features.
- for (auto &Op : FeaturesSet) {
- StringRef Not = Op.first ? "!" : "";
- CondStream.indent(6) << Not << "STI.getFeatureBits()[" << TargetName
- << "::" << Op.second << "]"
- << " &&\n";
- }
- // Emit checks for all required feature groups.
- for (auto &Set : AnyOfFeatureSets) {
- CondStream.indent(6) << "(";
- for (auto &Op : Set) {
- bool isLast = &Op == &*Set.rbegin();
- StringRef Not = Op.first ? "!" : "";
- CondStream << Not << "STI.getFeatureBits()[" << TargetName
- << "::" << Op.second << "]";
- if (!isLast)
- CondStream << " || ";
- }
- CondStream << ") &&\n";
- }
- // Start Source Inst operands validation.
- unsigned OpNo = 0;
- for (OpNo = 0; OpNo < Source.Operands.size(); ++OpNo) {
- if (SourceOperandMap[OpNo].TiedOpIdx != -1) {
- if (Source.Operands[OpNo].Rec->isSubClassOf("RegisterClass"))
- CondStream.indent(6)
- << "(MI.getOperand(" << OpNo << ").isReg()) && (MI.getOperand("
- << SourceOperandMap[OpNo].TiedOpIdx << ").isReg()) &&\n"
- << " (MI.getOperand(" << OpNo
- << ").getReg() == MI.getOperand("
- << SourceOperandMap[OpNo].TiedOpIdx << ").getReg()) &&\n";
- else
- PrintFatalError("Unexpected tied operand types!\n");
- }
- // Check for fixed immediates\registers in the source instruction.
- switch (SourceOperandMap[OpNo].Kind) {
- case OpData::Operand:
- // We don't need to do anything for source instruction operand checks.
- break;
- case OpData::Imm:
- CondStream.indent(6)
- << "(MI.getOperand(" << OpNo << ").isImm()) &&\n"
- << " (MI.getOperand(" << OpNo
- << ").getImm() == " << SourceOperandMap[OpNo].Data.Imm << ") &&\n";
- break;
- case OpData::Reg: {
- Record *Reg = SourceOperandMap[OpNo].Data.Reg;
- CondStream.indent(6)
- << "(MI.getOperand(" << OpNo << ").isReg()) &&\n"
- << " (MI.getOperand(" << OpNo << ").getReg() == " << TargetName
- << "::" << Reg->getName() << ") &&\n";
- break;
- }
- }
- }
- CodeStream.indent(6) << "// " << Dest.AsmString << "\n";
- if (CompressOrUncompress)
- CodeStream.indent(6) << "OutInst.setOpcode(" << TargetName
- << "::" << Dest.TheDef->getName() << ");\n";
- OpNo = 0;
- for (const auto &DestOperand : Dest.Operands) {
- CodeStream.indent(6) << "// Operand: " << DestOperand.Name << "\n";
- switch (DestOperandMap[OpNo].Kind) {
- case OpData::Operand: {
- unsigned OpIdx = DestOperandMap[OpNo].Data.Operand;
- // Check that the operand in the Source instruction fits
- // the type for the Dest instruction.
- if (DestOperand.Rec->isSubClassOf("RegisterClass") ||
- DestOperand.Rec->isSubClassOf("RegisterOperand")) {
- auto *ClassRec = DestOperand.Rec->isSubClassOf("RegisterClass")
- ? DestOperand.Rec
- : DestOperand.Rec->getValueAsDef("RegClass");
- // This is a register operand. Check the register class.
- // Don't check register class if this is a tied operand, it was done
- // for the operand its tied to.
- if (DestOperand.getTiedRegister() == -1)
- CondStream.indent(6)
- << "(MI.getOperand(" << OpIdx << ").isReg()) &&\n"
- << " (" << TargetName << "MCRegisterClasses["
- << TargetName << "::" << ClassRec->getName()
- << "RegClassID].contains(MI.getOperand(" << OpIdx
- << ").getReg())) &&\n";
- if (CompressOrUncompress)
- CodeStream.indent(6)
- << "OutInst.addOperand(MI.getOperand(" << OpIdx << "));\n";
- } else {
- // Handling immediate operands.
- if (CompressOrUncompress) {
- unsigned Entry =
- getPredicates(MCOpPredicateMap, MCOpPredicates, DestOperand.Rec,
- "MCOperandPredicate");
- CondStream.indent(6)
- << ValidatorName << "("
- << "MI.getOperand(" << OpIdx << "), STI, " << Entry << ") &&\n";
- } else {
- unsigned Entry =
- getPredicates(ImmLeafPredicateMap, ImmLeafPredicates,
- DestOperand.Rec, "ImmediateCode");
- CondStream.indent(6)
- << "MI.getOperand(" << OpIdx << ").isImm() &&\n";
- CondStream.indent(6) << TargetName << "ValidateMachineOperand("
- << "MI.getOperand(" << OpIdx
- << "), &STI, " << Entry << ") &&\n";
- }
- if (CompressOrUncompress)
- CodeStream.indent(6)
- << "OutInst.addOperand(MI.getOperand(" << OpIdx << "));\n";
- }
- break;
- }
- case OpData::Imm: {
- if (CompressOrUncompress) {
- unsigned Entry = getPredicates(MCOpPredicateMap, MCOpPredicates,
- DestOperand.Rec, "MCOperandPredicate");
- CondStream.indent(6)
- << ValidatorName << "("
- << "MCOperand::createImm(" << DestOperandMap[OpNo].Data.Imm
- << "), STI, " << Entry << ") &&\n";
- } else {
- unsigned Entry = getPredicates(ImmLeafPredicateMap, ImmLeafPredicates,
- DestOperand.Rec, "ImmediateCode");
- CondStream.indent(6)
- << TargetName
- << "ValidateMachineOperand(MachineOperand::CreateImm("
- << DestOperandMap[OpNo].Data.Imm << "), &STI, " << Entry
- << ") &&\n";
- }
- if (CompressOrUncompress)
- CodeStream.indent(6) << "OutInst.addOperand(MCOperand::createImm("
- << DestOperandMap[OpNo].Data.Imm << "));\n";
- } break;
- case OpData::Reg: {
- if (CompressOrUncompress) {
- // Fixed register has been validated at pattern validation time.
- Record *Reg = DestOperandMap[OpNo].Data.Reg;
- CodeStream.indent(6)
- << "OutInst.addOperand(MCOperand::createReg(" << TargetName
- << "::" << Reg->getName() << "));\n";
- }
- } break;
- }
- ++OpNo;
- }
- if (CompressOrUncompress)
- CodeStream.indent(6) << "OutInst.setLoc(MI.getLoc());\n";
- mergeCondAndCode(CaseStream, CondStream.str(), CodeStream.str());
- PrevOp = CurOp;
- }
- Func << CaseStream.str() << "\n";
- // Close brace for the last case.
- Func.indent(4) << "} // case " << CurOp << "\n";
- Func.indent(2) << "} // switch\n";
- Func.indent(2) << "return false;\n}\n";
- if (!MCOpPredicates.empty()) {
- o << "static bool " << ValidatorName << "(const MCOperand &MCOp,\n"
- << " const MCSubtargetInfo &STI,\n"
- << " unsigned PredicateIndex) {\n"
- << " switch (PredicateIndex) {\n"
- << " default:\n"
- << " llvm_unreachable(\"Unknown MCOperandPredicate kind\");\n"
- << " break;\n";
- printPredicates(MCOpPredicates, "MCOperandPredicate", o);
- o << " }\n"
- << "}\n\n";
- }
- if (!ImmLeafPredicates.empty()) {
- o << "static bool " << TargetName
- << "ValidateMachineOperand(const MachineOperand &MO,\n"
- << " const " << TargetName << "Subtarget *Subtarget,\n"
- << " unsigned PredicateIndex) {\n"
- << " int64_t Imm = MO.getImm();\n"
- << " switch (PredicateIndex) {\n"
- << " default:\n"
- << " llvm_unreachable(\"Unknown ImmLeaf Predicate kind\");\n"
- << " break;\n";
- printPredicates(ImmLeafPredicates, "ImmediateCode", o);
- o << " }\n"
- << "}\n\n";
- }
- o << FuncH.str();
- o << Func.str();
- if (EType == EmitterType::Compress)
- o << "\n#endif //GEN_COMPRESS_INSTR\n";
- else if (EType == EmitterType::Uncompress)
- o << "\n#endif //GEN_UNCOMPRESS_INSTR\n\n";
- else if (EType == EmitterType::CheckCompress)
- o << "\n#endif //GEN_CHECK_COMPRESS_INSTR\n\n";
- }
- void CompressInstEmitter::run(raw_ostream &o) {
- std::vector<Record *> Insts = Records.getAllDerivedDefinitions("CompressPat");
- // Process the CompressPat definitions, validating them as we do so.
- for (unsigned i = 0, e = Insts.size(); i != e; ++i)
- evaluateCompressPat(Insts[i]);
- // Emit file header.
- emitSourceFileHeader("Compress instruction Source Fragment", o);
- // Generate compressInst() function.
- emitCompressInstEmitter(o, EmitterType::Compress);
- // Generate uncompressInst() function.
- emitCompressInstEmitter(o, EmitterType::Uncompress);
- // Generate isCompressibleInst() function.
- emitCompressInstEmitter(o, EmitterType::CheckCompress);
- }
- namespace llvm {
- void EmitCompressInst(RecordKeeper &RK, raw_ostream &OS) {
- CompressInstEmitter(RK).run(OS);
- }
- } // namespace llvm
|