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