1349cc55cSDimitry Andric //===-------- CompressInstEmitter.cpp - Generator for Compression ---------===// 2349cc55cSDimitry Andric // 3349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5349cc55cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6349cc55cSDimitry Andric // 7349cc55cSDimitry Andric // CompressInstEmitter implements a tablegen-driven CompressPat based 8349cc55cSDimitry Andric // Instruction Compression mechanism. 9349cc55cSDimitry Andric // 10349cc55cSDimitry Andric //===----------------------------------------------------------------------===// 11349cc55cSDimitry Andric // 12349cc55cSDimitry Andric // CompressInstEmitter implements a tablegen-driven CompressPat Instruction 13349cc55cSDimitry Andric // Compression mechanism for generating compressed instructions from the 14349cc55cSDimitry Andric // expanded instruction form. 15349cc55cSDimitry Andric 16349cc55cSDimitry Andric // This tablegen backend processes CompressPat declarations in a 17349cc55cSDimitry Andric // td file and generates all the required checks to validate the pattern 18349cc55cSDimitry Andric // declarations; validate the input and output operands to generate the correct 19349cc55cSDimitry Andric // compressed instructions. The checks include validating different types of 20349cc55cSDimitry Andric // operands; register operands, immediate operands, fixed register and fixed 21349cc55cSDimitry Andric // immediate inputs. 22349cc55cSDimitry Andric // 23349cc55cSDimitry Andric // Example: 24349cc55cSDimitry Andric // /// Defines a Pat match between compressed and uncompressed instruction. 25349cc55cSDimitry Andric // /// The relationship and helper function generation are handled by 26349cc55cSDimitry Andric // /// CompressInstEmitter backend. 27349cc55cSDimitry Andric // class CompressPat<dag input, dag output, list<Predicate> predicates = []> { 28349cc55cSDimitry Andric // /// Uncompressed instruction description. 29349cc55cSDimitry Andric // dag Input = input; 30349cc55cSDimitry Andric // /// Compressed instruction description. 31349cc55cSDimitry Andric // dag Output = output; 32349cc55cSDimitry Andric // /// Predicates that must be true for this to match. 33349cc55cSDimitry Andric // list<Predicate> Predicates = predicates; 34349cc55cSDimitry Andric // /// Duplicate match when tied operand is just different. 35349cc55cSDimitry Andric // bit isCompressOnly = false; 36349cc55cSDimitry Andric // } 37349cc55cSDimitry Andric // 38349cc55cSDimitry Andric // let Predicates = [HasStdExtC] in { 39349cc55cSDimitry Andric // def : CompressPat<(ADD GPRNoX0:$rs1, GPRNoX0:$rs1, GPRNoX0:$rs2), 40349cc55cSDimitry Andric // (C_ADD GPRNoX0:$rs1, GPRNoX0:$rs2)>; 41349cc55cSDimitry Andric // } 42349cc55cSDimitry Andric // 43349cc55cSDimitry Andric // The <TargetName>GenCompressInstEmitter.inc is an auto-generated header 44349cc55cSDimitry Andric // file which exports two functions for compressing/uncompressing MCInst 45349cc55cSDimitry Andric // instructions, plus some helper functions: 46349cc55cSDimitry Andric // 47349cc55cSDimitry Andric // bool compressInst(MCInst &OutInst, const MCInst &MI, 48bdd1243dSDimitry Andric // const MCSubtargetInfo &STI); 49349cc55cSDimitry Andric // 50349cc55cSDimitry Andric // bool uncompressInst(MCInst &OutInst, const MCInst &MI, 51349cc55cSDimitry Andric // const MCSubtargetInfo &STI); 52349cc55cSDimitry Andric // 53349cc55cSDimitry Andric // In addition, it exports a function for checking whether 54349cc55cSDimitry Andric // an instruction is compressable: 55349cc55cSDimitry Andric // 56349cc55cSDimitry Andric // bool isCompressibleInst(const MachineInstr& MI, 57bdd1243dSDimitry Andric // const <TargetName>Subtarget &STI); 58349cc55cSDimitry Andric // 59349cc55cSDimitry Andric // The clients that include this auto-generated header file and 60349cc55cSDimitry Andric // invoke these functions can compress an instruction before emitting 61349cc55cSDimitry Andric // it in the target-specific ASM or ELF streamer or can uncompress 62349cc55cSDimitry Andric // an instruction before printing it when the expanded instruction 63349cc55cSDimitry Andric // format aliases is favored. 64349cc55cSDimitry Andric 65349cc55cSDimitry Andric //===----------------------------------------------------------------------===// 66349cc55cSDimitry Andric 67*0fca6ea1SDimitry Andric #include "Common/CodeGenInstruction.h" 68*0fca6ea1SDimitry Andric #include "Common/CodeGenRegisters.h" 69*0fca6ea1SDimitry Andric #include "Common/CodeGenTarget.h" 70349cc55cSDimitry Andric #include "llvm/ADT/IndexedMap.h" 71349cc55cSDimitry Andric #include "llvm/ADT/SmallVector.h" 72349cc55cSDimitry Andric #include "llvm/ADT/StringMap.h" 73349cc55cSDimitry Andric #include "llvm/Support/Debug.h" 74349cc55cSDimitry Andric #include "llvm/Support/ErrorHandling.h" 75349cc55cSDimitry Andric #include "llvm/TableGen/Error.h" 76349cc55cSDimitry Andric #include "llvm/TableGen/Record.h" 77349cc55cSDimitry Andric #include "llvm/TableGen/TableGenBackend.h" 78349cc55cSDimitry Andric #include <set> 79349cc55cSDimitry Andric #include <vector> 80349cc55cSDimitry Andric using namespace llvm; 81349cc55cSDimitry Andric 82349cc55cSDimitry Andric #define DEBUG_TYPE "compress-inst-emitter" 83349cc55cSDimitry Andric 84349cc55cSDimitry Andric namespace { 85349cc55cSDimitry Andric class CompressInstEmitter { 86349cc55cSDimitry Andric struct OpData { 87349cc55cSDimitry Andric enum MapKind { Operand, Imm, Reg }; 88349cc55cSDimitry Andric MapKind Kind; 89349cc55cSDimitry Andric union { 90349cc55cSDimitry Andric // Operand number mapped to. 91349cc55cSDimitry Andric unsigned Operand; 92349cc55cSDimitry Andric // Integer immediate value. 93349cc55cSDimitry Andric int64_t Imm; 94349cc55cSDimitry Andric // Physical register. 95349cc55cSDimitry Andric Record *Reg; 96349cc55cSDimitry Andric } Data; 97349cc55cSDimitry Andric // Tied operand index within the instruction. 98349cc55cSDimitry Andric int TiedOpIdx = -1; 99349cc55cSDimitry Andric }; 100349cc55cSDimitry Andric struct CompressPat { 101349cc55cSDimitry Andric // The source instruction definition. 102349cc55cSDimitry Andric CodeGenInstruction Source; 103349cc55cSDimitry Andric // The destination instruction to transform to. 104349cc55cSDimitry Andric CodeGenInstruction Dest; 105349cc55cSDimitry Andric // Required target features to enable pattern. 106349cc55cSDimitry Andric std::vector<Record *> PatReqFeatures; 107349cc55cSDimitry Andric // Maps operands in the Source Instruction to 108349cc55cSDimitry Andric // the corresponding Dest instruction operand. 1095f757f3fSDimitry Andric IndexedMap<OpData> SourceOperandMap; 110349cc55cSDimitry Andric // Maps operands in the Dest Instruction 111349cc55cSDimitry Andric // to the corresponding Source instruction operand. 112349cc55cSDimitry Andric IndexedMap<OpData> DestOperandMap; 113349cc55cSDimitry Andric 114349cc55cSDimitry Andric bool IsCompressOnly; 115349cc55cSDimitry Andric CompressPat(CodeGenInstruction &S, CodeGenInstruction &D, 116349cc55cSDimitry Andric std::vector<Record *> RF, IndexedMap<OpData> &SourceMap, 117349cc55cSDimitry Andric IndexedMap<OpData> &DestMap, bool IsCompressOnly) 118349cc55cSDimitry Andric : Source(S), Dest(D), PatReqFeatures(RF), SourceOperandMap(SourceMap), 119349cc55cSDimitry Andric DestOperandMap(DestMap), IsCompressOnly(IsCompressOnly) {} 120349cc55cSDimitry Andric }; 121349cc55cSDimitry Andric enum EmitterType { Compress, Uncompress, CheckCompress }; 122349cc55cSDimitry Andric RecordKeeper &Records; 123349cc55cSDimitry Andric CodeGenTarget Target; 124349cc55cSDimitry Andric SmallVector<CompressPat, 4> CompressPatterns; 125349cc55cSDimitry Andric 126349cc55cSDimitry Andric void addDagOperandMapping(Record *Rec, DagInit *Dag, CodeGenInstruction &Inst, 127349cc55cSDimitry Andric IndexedMap<OpData> &OperandMap, bool IsSourceInst); 128349cc55cSDimitry Andric void evaluateCompressPat(Record *Compress); 1295f757f3fSDimitry Andric void emitCompressInstEmitter(raw_ostream &OS, EmitterType EType); 130349cc55cSDimitry Andric bool validateTypes(Record *SubType, Record *Type, bool IsSourceInst); 131349cc55cSDimitry Andric bool validateRegister(Record *Reg, Record *RegClass); 132349cc55cSDimitry Andric void createDagOperandMapping(Record *Rec, StringMap<unsigned> &SourceOperands, 133349cc55cSDimitry Andric StringMap<unsigned> &DestOperands, 134349cc55cSDimitry Andric DagInit *SourceDag, DagInit *DestDag, 135349cc55cSDimitry Andric IndexedMap<OpData> &SourceOperandMap); 136349cc55cSDimitry Andric 137349cc55cSDimitry Andric void createInstOperandMapping(Record *Rec, DagInit *SourceDag, 138349cc55cSDimitry Andric DagInit *DestDag, 139349cc55cSDimitry Andric IndexedMap<OpData> &SourceOperandMap, 140349cc55cSDimitry Andric IndexedMap<OpData> &DestOperandMap, 141349cc55cSDimitry Andric StringMap<unsigned> &SourceOperands, 142349cc55cSDimitry Andric CodeGenInstruction &DestInst); 143349cc55cSDimitry Andric 144349cc55cSDimitry Andric public: 145349cc55cSDimitry Andric CompressInstEmitter(RecordKeeper &R) : Records(R), Target(R) {} 146349cc55cSDimitry Andric 1475f757f3fSDimitry Andric void run(raw_ostream &OS); 148349cc55cSDimitry Andric }; 149349cc55cSDimitry Andric } // End anonymous namespace. 150349cc55cSDimitry Andric 151349cc55cSDimitry Andric bool CompressInstEmitter::validateRegister(Record *Reg, Record *RegClass) { 152349cc55cSDimitry Andric assert(Reg->isSubClassOf("Register") && "Reg record should be a Register"); 153349cc55cSDimitry Andric assert(RegClass->isSubClassOf("RegisterClass") && 154349cc55cSDimitry Andric "RegClass record should be a RegisterClass"); 155349cc55cSDimitry Andric const CodeGenRegisterClass &RC = Target.getRegisterClass(RegClass); 156349cc55cSDimitry Andric const CodeGenRegister *R = Target.getRegisterByName(Reg->getName().lower()); 157349cc55cSDimitry Andric assert((R != nullptr) && "Register not defined!!"); 158349cc55cSDimitry Andric return RC.contains(R); 159349cc55cSDimitry Andric } 160349cc55cSDimitry Andric 161349cc55cSDimitry Andric bool CompressInstEmitter::validateTypes(Record *DagOpType, Record *InstOpType, 162349cc55cSDimitry Andric bool IsSourceInst) { 163349cc55cSDimitry Andric if (DagOpType == InstOpType) 164349cc55cSDimitry Andric return true; 165349cc55cSDimitry Andric // Only source instruction operands are allowed to not match Input Dag 166349cc55cSDimitry Andric // operands. 167349cc55cSDimitry Andric if (!IsSourceInst) 168349cc55cSDimitry Andric return false; 169349cc55cSDimitry Andric 170349cc55cSDimitry Andric if (DagOpType->isSubClassOf("RegisterClass") && 171349cc55cSDimitry Andric InstOpType->isSubClassOf("RegisterClass")) { 172349cc55cSDimitry Andric const CodeGenRegisterClass &RC = Target.getRegisterClass(InstOpType); 173349cc55cSDimitry Andric const CodeGenRegisterClass &SubRC = Target.getRegisterClass(DagOpType); 174349cc55cSDimitry Andric return RC.hasSubClass(&SubRC); 175349cc55cSDimitry Andric } 176349cc55cSDimitry Andric 177349cc55cSDimitry Andric // At this point either or both types are not registers, reject the pattern. 178349cc55cSDimitry Andric if (DagOpType->isSubClassOf("RegisterClass") || 179349cc55cSDimitry Andric InstOpType->isSubClassOf("RegisterClass")) 180349cc55cSDimitry Andric return false; 181349cc55cSDimitry Andric 182349cc55cSDimitry Andric // Let further validation happen when compress()/uncompress() functions are 183349cc55cSDimitry Andric // invoked. 184349cc55cSDimitry Andric LLVM_DEBUG(dbgs() << (IsSourceInst ? "Input" : "Output") 185349cc55cSDimitry Andric << " Dag Operand Type: '" << DagOpType->getName() 186349cc55cSDimitry Andric << "' and " 187349cc55cSDimitry Andric << "Instruction Operand Type: '" << InstOpType->getName() 188349cc55cSDimitry Andric << "' can't be checked at pattern validation time!\n"); 189349cc55cSDimitry Andric return true; 190349cc55cSDimitry Andric } 191349cc55cSDimitry Andric 192349cc55cSDimitry Andric /// The patterns in the Dag contain different types of operands: 193349cc55cSDimitry Andric /// Register operands, e.g.: GPRC:$rs1; Fixed registers, e.g: X1; Immediate 194349cc55cSDimitry Andric /// operands, e.g.: simm6:$imm; Fixed immediate operands, e.g.: 0. This function 195349cc55cSDimitry Andric /// maps Dag operands to its corresponding instruction operands. For register 196349cc55cSDimitry Andric /// operands and fixed registers it expects the Dag operand type to be contained 197349cc55cSDimitry Andric /// in the instantiated instruction operand type. For immediate operands and 198349cc55cSDimitry Andric /// immediates no validation checks are enforced at pattern validation time. 199349cc55cSDimitry Andric void CompressInstEmitter::addDagOperandMapping(Record *Rec, DagInit *Dag, 200349cc55cSDimitry Andric CodeGenInstruction &Inst, 201349cc55cSDimitry Andric IndexedMap<OpData> &OperandMap, 202349cc55cSDimitry Andric bool IsSourceInst) { 203349cc55cSDimitry Andric // TiedCount keeps track of the number of operands skipped in Inst 204349cc55cSDimitry Andric // operands list to get to the corresponding Dag operand. This is 205349cc55cSDimitry Andric // necessary because the number of operands in Inst might be greater 206349cc55cSDimitry Andric // than number of operands in the Dag due to how tied operands 207349cc55cSDimitry Andric // are represented. 208349cc55cSDimitry Andric unsigned TiedCount = 0; 2095f757f3fSDimitry Andric for (unsigned I = 0, E = Inst.Operands.size(); I != E; ++I) { 2105f757f3fSDimitry Andric int TiedOpIdx = Inst.Operands[I].getTiedRegister(); 211349cc55cSDimitry Andric if (-1 != TiedOpIdx) { 212349cc55cSDimitry Andric // Set the entry in OperandMap for the tied operand we're skipping. 2135f757f3fSDimitry Andric OperandMap[I].Kind = OperandMap[TiedOpIdx].Kind; 2145f757f3fSDimitry Andric OperandMap[I].Data = OperandMap[TiedOpIdx].Data; 215349cc55cSDimitry Andric TiedCount++; 216349cc55cSDimitry Andric continue; 217349cc55cSDimitry Andric } 2185f757f3fSDimitry Andric if (DefInit *DI = dyn_cast<DefInit>(Dag->getArg(I - TiedCount))) { 219349cc55cSDimitry Andric if (DI->getDef()->isSubClassOf("Register")) { 220349cc55cSDimitry Andric // Check if the fixed register belongs to the Register class. 2215f757f3fSDimitry Andric if (!validateRegister(DI->getDef(), Inst.Operands[I].Rec)) 222349cc55cSDimitry Andric PrintFatalError(Rec->getLoc(), 223349cc55cSDimitry Andric "Error in Dag '" + Dag->getAsString() + 224349cc55cSDimitry Andric "'Register: '" + DI->getDef()->getName() + 225349cc55cSDimitry Andric "' is not in register class '" + 2265f757f3fSDimitry Andric Inst.Operands[I].Rec->getName() + "'"); 2275f757f3fSDimitry Andric OperandMap[I].Kind = OpData::Reg; 2285f757f3fSDimitry Andric OperandMap[I].Data.Reg = DI->getDef(); 229349cc55cSDimitry Andric continue; 230349cc55cSDimitry Andric } 231349cc55cSDimitry Andric // Validate that Dag operand type matches the type defined in the 232349cc55cSDimitry Andric // corresponding instruction. Operands in the input Dag pattern are 233349cc55cSDimitry Andric // allowed to be a subclass of the type specified in corresponding 234349cc55cSDimitry Andric // instruction operand instead of being an exact match. 2355f757f3fSDimitry Andric if (!validateTypes(DI->getDef(), Inst.Operands[I].Rec, IsSourceInst)) 236349cc55cSDimitry Andric PrintFatalError(Rec->getLoc(), 237349cc55cSDimitry Andric "Error in Dag '" + Dag->getAsString() + "'. Operand '" + 2385f757f3fSDimitry Andric Dag->getArgNameStr(I - TiedCount) + "' has type '" + 239349cc55cSDimitry Andric DI->getDef()->getName() + 240349cc55cSDimitry Andric "' which does not match the type '" + 2415f757f3fSDimitry Andric Inst.Operands[I].Rec->getName() + 242349cc55cSDimitry Andric "' in the corresponding instruction operand!"); 243349cc55cSDimitry Andric 2445f757f3fSDimitry Andric OperandMap[I].Kind = OpData::Operand; 2455f757f3fSDimitry Andric } else if (IntInit *II = dyn_cast<IntInit>(Dag->getArg(I - TiedCount))) { 246349cc55cSDimitry Andric // Validate that corresponding instruction operand expects an immediate. 2475f757f3fSDimitry Andric if (Inst.Operands[I].Rec->isSubClassOf("RegisterClass")) 248349cc55cSDimitry Andric PrintFatalError( 249349cc55cSDimitry Andric Rec->getLoc(), 250349cc55cSDimitry Andric "Error in Dag '" + Dag->getAsString() + "' Found immediate: '" + 251349cc55cSDimitry Andric II->getAsString() + 252349cc55cSDimitry Andric "' but corresponding instruction operand expected a register!"); 253349cc55cSDimitry Andric // No pattern validation check possible for values of fixed immediate. 2545f757f3fSDimitry Andric OperandMap[I].Kind = OpData::Imm; 2555f757f3fSDimitry Andric OperandMap[I].Data.Imm = II->getValue(); 256349cc55cSDimitry Andric LLVM_DEBUG( 257349cc55cSDimitry Andric dbgs() << " Found immediate '" << II->getValue() << "' at " 258349cc55cSDimitry Andric << (IsSourceInst ? "input " : "output ") 259349cc55cSDimitry Andric << "Dag. No validation time check possible for values of " 260349cc55cSDimitry Andric "fixed immediate.\n"); 261349cc55cSDimitry Andric } else 262349cc55cSDimitry Andric llvm_unreachable("Unhandled CompressPat argument type!"); 263349cc55cSDimitry Andric } 264349cc55cSDimitry Andric } 265349cc55cSDimitry Andric 266349cc55cSDimitry Andric // Verify the Dag operand count is enough to build an instruction. 267349cc55cSDimitry Andric static bool verifyDagOpCount(CodeGenInstruction &Inst, DagInit *Dag, 268349cc55cSDimitry Andric bool IsSource) { 269349cc55cSDimitry Andric if (Dag->getNumArgs() == Inst.Operands.size()) 270349cc55cSDimitry Andric return true; 271349cc55cSDimitry Andric // Source instructions are non compressed instructions and don't have tied 272349cc55cSDimitry Andric // operands. 273349cc55cSDimitry Andric if (IsSource) 274349cc55cSDimitry Andric PrintFatalError(Inst.TheDef->getLoc(), 275349cc55cSDimitry Andric "Input operands for Inst '" + Inst.TheDef->getName() + 276349cc55cSDimitry Andric "' and input Dag operand count mismatch"); 277349cc55cSDimitry Andric // The Dag can't have more arguments than the Instruction. 278349cc55cSDimitry Andric if (Dag->getNumArgs() > Inst.Operands.size()) 279349cc55cSDimitry Andric PrintFatalError(Inst.TheDef->getLoc(), 280349cc55cSDimitry Andric "Inst '" + Inst.TheDef->getName() + 281349cc55cSDimitry Andric "' and Dag operand count mismatch"); 282349cc55cSDimitry Andric 283349cc55cSDimitry Andric // The Instruction might have tied operands so the Dag might have 284349cc55cSDimitry Andric // a fewer operand count. 285349cc55cSDimitry Andric unsigned RealCount = Inst.Operands.size(); 286349cc55cSDimitry Andric for (const auto &Operand : Inst.Operands) 287349cc55cSDimitry Andric if (Operand.getTiedRegister() != -1) 288349cc55cSDimitry Andric --RealCount; 289349cc55cSDimitry Andric 290349cc55cSDimitry Andric if (Dag->getNumArgs() != RealCount) 291349cc55cSDimitry Andric PrintFatalError(Inst.TheDef->getLoc(), 292349cc55cSDimitry Andric "Inst '" + Inst.TheDef->getName() + 293349cc55cSDimitry Andric "' and Dag operand count mismatch"); 294349cc55cSDimitry Andric return true; 295349cc55cSDimitry Andric } 296349cc55cSDimitry Andric 297349cc55cSDimitry Andric static bool validateArgsTypes(Init *Arg1, Init *Arg2) { 298349cc55cSDimitry Andric return cast<DefInit>(Arg1)->getDef() == cast<DefInit>(Arg2)->getDef(); 299349cc55cSDimitry Andric } 300349cc55cSDimitry Andric 301349cc55cSDimitry Andric // Creates a mapping between the operand name in the Dag (e.g. $rs1) and 302349cc55cSDimitry Andric // its index in the list of Dag operands and checks that operands with the same 303349cc55cSDimitry Andric // name have the same types. For example in 'C_ADD $rs1, $rs2' we generate the 304349cc55cSDimitry Andric // mapping $rs1 --> 0, $rs2 ---> 1. If the operand appears twice in the (tied) 305349cc55cSDimitry Andric // same Dag we use the last occurrence for indexing. 306349cc55cSDimitry Andric void CompressInstEmitter::createDagOperandMapping( 307349cc55cSDimitry Andric Record *Rec, StringMap<unsigned> &SourceOperands, 308349cc55cSDimitry Andric StringMap<unsigned> &DestOperands, DagInit *SourceDag, DagInit *DestDag, 309349cc55cSDimitry Andric IndexedMap<OpData> &SourceOperandMap) { 3105f757f3fSDimitry Andric for (unsigned I = 0; I < DestDag->getNumArgs(); ++I) { 311349cc55cSDimitry Andric // Skip fixed immediates and registers, they were handled in 312349cc55cSDimitry Andric // addDagOperandMapping. 3135f757f3fSDimitry Andric if ("" == DestDag->getArgNameStr(I)) 314349cc55cSDimitry Andric continue; 3155f757f3fSDimitry Andric DestOperands[DestDag->getArgNameStr(I)] = I; 316349cc55cSDimitry Andric } 317349cc55cSDimitry Andric 3185f757f3fSDimitry Andric for (unsigned I = 0; I < SourceDag->getNumArgs(); ++I) { 319349cc55cSDimitry Andric // Skip fixed immediates and registers, they were handled in 320349cc55cSDimitry Andric // addDagOperandMapping. 3215f757f3fSDimitry Andric if ("" == SourceDag->getArgNameStr(I)) 322349cc55cSDimitry Andric continue; 323349cc55cSDimitry Andric 3245f757f3fSDimitry Andric StringMap<unsigned>::iterator It = 3255f757f3fSDimitry Andric SourceOperands.find(SourceDag->getArgNameStr(I)); 3265f757f3fSDimitry Andric if (It != SourceOperands.end()) { 327349cc55cSDimitry Andric // Operand sharing the same name in the Dag should be mapped as tied. 3285f757f3fSDimitry Andric SourceOperandMap[I].TiedOpIdx = It->getValue(); 3295f757f3fSDimitry Andric if (!validateArgsTypes(SourceDag->getArg(It->getValue()), 3305f757f3fSDimitry Andric SourceDag->getArg(I))) 331349cc55cSDimitry Andric PrintFatalError(Rec->getLoc(), 3325f757f3fSDimitry Andric "Input Operand '" + SourceDag->getArgNameStr(I) + 333349cc55cSDimitry Andric "' has a mismatched tied operand!\n"); 334349cc55cSDimitry Andric } 3355f757f3fSDimitry Andric It = DestOperands.find(SourceDag->getArgNameStr(I)); 3365f757f3fSDimitry Andric if (It == DestOperands.end()) 3375f757f3fSDimitry Andric PrintFatalError(Rec->getLoc(), "Operand " + SourceDag->getArgNameStr(I) + 338349cc55cSDimitry Andric " defined in Input Dag but not used in" 339349cc55cSDimitry Andric " Output Dag!\n"); 340349cc55cSDimitry Andric // Input Dag operand types must match output Dag operand type. 3415f757f3fSDimitry Andric if (!validateArgsTypes(DestDag->getArg(It->getValue()), 3425f757f3fSDimitry Andric SourceDag->getArg(I))) 343349cc55cSDimitry Andric PrintFatalError(Rec->getLoc(), "Type mismatch between Input and " 344349cc55cSDimitry Andric "Output Dag operand '" + 3455f757f3fSDimitry Andric SourceDag->getArgNameStr(I) + "'!"); 3465f757f3fSDimitry Andric SourceOperands[SourceDag->getArgNameStr(I)] = I; 347349cc55cSDimitry Andric } 348349cc55cSDimitry Andric } 349349cc55cSDimitry Andric 350349cc55cSDimitry Andric /// Map operand names in the Dag to their index in both corresponding input and 351349cc55cSDimitry Andric /// output instructions. Validate that operands defined in the input are 352349cc55cSDimitry Andric /// used in the output pattern while populating the maps. 353349cc55cSDimitry Andric void CompressInstEmitter::createInstOperandMapping( 354349cc55cSDimitry Andric Record *Rec, DagInit *SourceDag, DagInit *DestDag, 355349cc55cSDimitry Andric IndexedMap<OpData> &SourceOperandMap, IndexedMap<OpData> &DestOperandMap, 356349cc55cSDimitry Andric StringMap<unsigned> &SourceOperands, CodeGenInstruction &DestInst) { 357349cc55cSDimitry Andric // TiedCount keeps track of the number of operands skipped in Inst 358349cc55cSDimitry Andric // operands list to get to the corresponding Dag operand. 359349cc55cSDimitry Andric unsigned TiedCount = 0; 360349cc55cSDimitry Andric LLVM_DEBUG(dbgs() << " Operand mapping:\n Source Dest\n"); 3615f757f3fSDimitry Andric for (unsigned I = 0, E = DestInst.Operands.size(); I != E; ++I) { 3625f757f3fSDimitry Andric int TiedInstOpIdx = DestInst.Operands[I].getTiedRegister(); 363349cc55cSDimitry Andric if (TiedInstOpIdx != -1) { 364349cc55cSDimitry Andric ++TiedCount; 3655f757f3fSDimitry Andric DestOperandMap[I].Data = DestOperandMap[TiedInstOpIdx].Data; 3665f757f3fSDimitry Andric DestOperandMap[I].Kind = DestOperandMap[TiedInstOpIdx].Kind; 3675f757f3fSDimitry Andric if (DestOperandMap[I].Kind == OpData::Operand) 368349cc55cSDimitry Andric // No need to fill the SourceOperandMap here since it was mapped to 369349cc55cSDimitry Andric // destination operand 'TiedInstOpIdx' in a previous iteration. 3705f757f3fSDimitry Andric LLVM_DEBUG(dbgs() << " " << DestOperandMap[I].Data.Operand 3715f757f3fSDimitry Andric << " ====> " << I 372349cc55cSDimitry Andric << " Dest operand tied with operand '" 373349cc55cSDimitry Andric << TiedInstOpIdx << "'\n"); 374349cc55cSDimitry Andric continue; 375349cc55cSDimitry Andric } 376349cc55cSDimitry Andric // Skip fixed immediates and registers, they were handled in 377349cc55cSDimitry Andric // addDagOperandMapping. 3785f757f3fSDimitry Andric if (DestOperandMap[I].Kind != OpData::Operand) 379349cc55cSDimitry Andric continue; 380349cc55cSDimitry Andric 3815f757f3fSDimitry Andric unsigned DagArgIdx = I - TiedCount; 382349cc55cSDimitry Andric StringMap<unsigned>::iterator SourceOp = 383349cc55cSDimitry Andric SourceOperands.find(DestDag->getArgNameStr(DagArgIdx)); 384349cc55cSDimitry Andric if (SourceOp == SourceOperands.end()) 385349cc55cSDimitry Andric PrintFatalError(Rec->getLoc(), 386349cc55cSDimitry Andric "Output Dag operand '" + 387349cc55cSDimitry Andric DestDag->getArgNameStr(DagArgIdx) + 388349cc55cSDimitry Andric "' has no matching input Dag operand."); 389349cc55cSDimitry Andric 390349cc55cSDimitry Andric assert(DestDag->getArgNameStr(DagArgIdx) == 391349cc55cSDimitry Andric SourceDag->getArgNameStr(SourceOp->getValue()) && 392349cc55cSDimitry Andric "Incorrect operand mapping detected!\n"); 3935f757f3fSDimitry Andric DestOperandMap[I].Data.Operand = SourceOp->getValue(); 3945f757f3fSDimitry Andric SourceOperandMap[SourceOp->getValue()].Data.Operand = I; 3955f757f3fSDimitry Andric LLVM_DEBUG(dbgs() << " " << SourceOp->getValue() << " ====> " << I 396349cc55cSDimitry Andric << "\n"); 397349cc55cSDimitry Andric } 398349cc55cSDimitry Andric } 399349cc55cSDimitry Andric 400349cc55cSDimitry Andric /// Validates the CompressPattern and create operand mapping. 401349cc55cSDimitry Andric /// These are the checks to validate a CompressPat pattern declarations. 402349cc55cSDimitry Andric /// Error out with message under these conditions: 403349cc55cSDimitry Andric /// - Dag Input opcode is an expanded instruction and Dag Output opcode is a 404349cc55cSDimitry Andric /// compressed instruction. 405349cc55cSDimitry Andric /// - Operands in Dag Input must be all used in Dag Output. 406349cc55cSDimitry Andric /// Register Operand type in Dag Input Type must be contained in the 407349cc55cSDimitry Andric /// corresponding Source Instruction type. 408349cc55cSDimitry Andric /// - Register Operand type in Dag Input must be the same as in Dag Ouput. 409349cc55cSDimitry Andric /// - Register Operand type in Dag Output must be the same as the 410349cc55cSDimitry Andric /// corresponding Destination Inst type. 411349cc55cSDimitry Andric /// - Immediate Operand type in Dag Input must be the same as in Dag Ouput. 412349cc55cSDimitry Andric /// - Immediate Operand type in Dag Ouput must be the same as the corresponding 413349cc55cSDimitry Andric /// Destination Instruction type. 414349cc55cSDimitry Andric /// - Fixed register must be contained in the corresponding Source Instruction 415349cc55cSDimitry Andric /// type. 416349cc55cSDimitry Andric /// - Fixed register must be contained in the corresponding Destination 4175f757f3fSDimitry Andric /// Instruction type. 4185f757f3fSDimitry Andric /// Warning message printed under these conditions: 419349cc55cSDimitry Andric /// - Fixed immediate in Dag Input or Dag Ouput cannot be checked at this time 420349cc55cSDimitry Andric /// and generate warning. 421349cc55cSDimitry Andric /// - Immediate operand type in Dag Input differs from the corresponding Source 422349cc55cSDimitry Andric /// Instruction type and generate a warning. 423349cc55cSDimitry Andric void CompressInstEmitter::evaluateCompressPat(Record *Rec) { 424349cc55cSDimitry Andric // Validate input Dag operands. 425349cc55cSDimitry Andric DagInit *SourceDag = Rec->getValueAsDag("Input"); 426349cc55cSDimitry Andric assert(SourceDag && "Missing 'Input' in compress pattern!"); 427349cc55cSDimitry Andric LLVM_DEBUG(dbgs() << "Input: " << *SourceDag << "\n"); 428349cc55cSDimitry Andric 429349cc55cSDimitry Andric // Checking we are transforming from compressed to uncompressed instructions. 4305f757f3fSDimitry Andric Record *SourceOperator = SourceDag->getOperatorAsDef(Rec->getLoc()); 4315f757f3fSDimitry Andric CodeGenInstruction SourceInst(SourceOperator); 432349cc55cSDimitry Andric verifyDagOpCount(SourceInst, SourceDag, true); 433349cc55cSDimitry Andric 434349cc55cSDimitry Andric // Validate output Dag operands. 435349cc55cSDimitry Andric DagInit *DestDag = Rec->getValueAsDag("Output"); 436349cc55cSDimitry Andric assert(DestDag && "Missing 'Output' in compress pattern!"); 437349cc55cSDimitry Andric LLVM_DEBUG(dbgs() << "Output: " << *DestDag << "\n"); 438349cc55cSDimitry Andric 439349cc55cSDimitry Andric Record *DestOperator = DestDag->getOperatorAsDef(Rec->getLoc()); 440349cc55cSDimitry Andric CodeGenInstruction DestInst(DestOperator); 441349cc55cSDimitry Andric verifyDagOpCount(DestInst, DestDag, false); 442349cc55cSDimitry Andric 4435f757f3fSDimitry Andric if (SourceOperator->getValueAsInt("Size") <= 4445f757f3fSDimitry Andric DestOperator->getValueAsInt("Size")) 445349cc55cSDimitry Andric PrintFatalError( 446349cc55cSDimitry Andric Rec->getLoc(), 447349cc55cSDimitry Andric "Compressed instruction '" + DestOperator->getName() + 448349cc55cSDimitry Andric "'is not strictly smaller than the uncompressed instruction '" + 4495f757f3fSDimitry Andric SourceOperator->getName() + "' !"); 450349cc55cSDimitry Andric 451349cc55cSDimitry Andric // Fill the mapping from the source to destination instructions. 452349cc55cSDimitry Andric 453349cc55cSDimitry Andric IndexedMap<OpData> SourceOperandMap; 454349cc55cSDimitry Andric SourceOperandMap.grow(SourceInst.Operands.size()); 455349cc55cSDimitry Andric // Create a mapping between source Dag operands and source Inst operands. 456349cc55cSDimitry Andric addDagOperandMapping(Rec, SourceDag, SourceInst, SourceOperandMap, 457349cc55cSDimitry Andric /*IsSourceInst*/ true); 458349cc55cSDimitry Andric 459349cc55cSDimitry Andric IndexedMap<OpData> DestOperandMap; 460349cc55cSDimitry Andric DestOperandMap.grow(DestInst.Operands.size()); 461349cc55cSDimitry Andric // Create a mapping between destination Dag operands and destination Inst 462349cc55cSDimitry Andric // operands. 463349cc55cSDimitry Andric addDagOperandMapping(Rec, DestDag, DestInst, DestOperandMap, 464349cc55cSDimitry Andric /*IsSourceInst*/ false); 465349cc55cSDimitry Andric 466349cc55cSDimitry Andric StringMap<unsigned> SourceOperands; 467349cc55cSDimitry Andric StringMap<unsigned> DestOperands; 468349cc55cSDimitry Andric createDagOperandMapping(Rec, SourceOperands, DestOperands, SourceDag, DestDag, 469349cc55cSDimitry Andric SourceOperandMap); 470349cc55cSDimitry Andric // Create operand mapping between the source and destination instructions. 471349cc55cSDimitry Andric createInstOperandMapping(Rec, SourceDag, DestDag, SourceOperandMap, 472349cc55cSDimitry Andric DestOperandMap, SourceOperands, DestInst); 473349cc55cSDimitry Andric 474349cc55cSDimitry Andric // Get the target features for the CompressPat. 475349cc55cSDimitry Andric std::vector<Record *> PatReqFeatures; 476349cc55cSDimitry Andric std::vector<Record *> RF = Rec->getValueAsListOfDefs("Predicates"); 477349cc55cSDimitry Andric copy_if(RF, std::back_inserter(PatReqFeatures), [](Record *R) { 478349cc55cSDimitry Andric return R->getValueAsBit("AssemblerMatcherPredicate"); 479349cc55cSDimitry Andric }); 480349cc55cSDimitry Andric 481349cc55cSDimitry Andric CompressPatterns.push_back(CompressPat(SourceInst, DestInst, PatReqFeatures, 482349cc55cSDimitry Andric SourceOperandMap, DestOperandMap, 483349cc55cSDimitry Andric Rec->getValueAsBit("isCompressOnly"))); 484349cc55cSDimitry Andric } 485349cc55cSDimitry Andric 486349cc55cSDimitry Andric static void 487349cc55cSDimitry Andric getReqFeatures(std::set<std::pair<bool, StringRef>> &FeaturesSet, 488349cc55cSDimitry Andric std::set<std::set<std::pair<bool, StringRef>>> &AnyOfFeatureSets, 489349cc55cSDimitry Andric const std::vector<Record *> &ReqFeatures) { 490349cc55cSDimitry Andric for (auto &R : ReqFeatures) { 491349cc55cSDimitry Andric const DagInit *D = R->getValueAsDag("AssemblerCondDag"); 492349cc55cSDimitry Andric std::string CombineType = D->getOperator()->getAsString(); 493349cc55cSDimitry Andric if (CombineType != "any_of" && CombineType != "all_of") 494349cc55cSDimitry Andric PrintFatalError(R->getLoc(), "Invalid AssemblerCondDag!"); 495349cc55cSDimitry Andric if (D->getNumArgs() == 0) 496349cc55cSDimitry Andric PrintFatalError(R->getLoc(), "Invalid AssemblerCondDag!"); 497349cc55cSDimitry Andric bool IsOr = CombineType == "any_of"; 498349cc55cSDimitry Andric std::set<std::pair<bool, StringRef>> AnyOfSet; 499349cc55cSDimitry Andric 500349cc55cSDimitry Andric for (auto *Arg : D->getArgs()) { 501349cc55cSDimitry Andric bool IsNot = false; 502349cc55cSDimitry Andric if (auto *NotArg = dyn_cast<DagInit>(Arg)) { 503349cc55cSDimitry Andric if (NotArg->getOperator()->getAsString() != "not" || 504349cc55cSDimitry Andric NotArg->getNumArgs() != 1) 505349cc55cSDimitry Andric PrintFatalError(R->getLoc(), "Invalid AssemblerCondDag!"); 506349cc55cSDimitry Andric Arg = NotArg->getArg(0); 507349cc55cSDimitry Andric IsNot = true; 508349cc55cSDimitry Andric } 509349cc55cSDimitry Andric if (!isa<DefInit>(Arg) || 510349cc55cSDimitry Andric !cast<DefInit>(Arg)->getDef()->isSubClassOf("SubtargetFeature")) 511349cc55cSDimitry Andric PrintFatalError(R->getLoc(), "Invalid AssemblerCondDag!"); 512349cc55cSDimitry Andric if (IsOr) 513349cc55cSDimitry Andric AnyOfSet.insert({IsNot, cast<DefInit>(Arg)->getDef()->getName()}); 514349cc55cSDimitry Andric else 515349cc55cSDimitry Andric FeaturesSet.insert({IsNot, cast<DefInit>(Arg)->getDef()->getName()}); 516349cc55cSDimitry Andric } 517349cc55cSDimitry Andric 518349cc55cSDimitry Andric if (IsOr) 519349cc55cSDimitry Andric AnyOfFeatureSets.insert(AnyOfSet); 520349cc55cSDimitry Andric } 521349cc55cSDimitry Andric } 522349cc55cSDimitry Andric 523349cc55cSDimitry Andric static unsigned getPredicates(DenseMap<const Record *, unsigned> &PredicateMap, 524349cc55cSDimitry Andric std::vector<const Record *> &Predicates, 525349cc55cSDimitry Andric Record *Rec, StringRef Name) { 526349cc55cSDimitry Andric unsigned &Entry = PredicateMap[Rec]; 527349cc55cSDimitry Andric if (Entry) 528349cc55cSDimitry Andric return Entry; 529349cc55cSDimitry Andric 530349cc55cSDimitry Andric if (!Rec->isValueUnset(Name)) { 531349cc55cSDimitry Andric Predicates.push_back(Rec); 532349cc55cSDimitry Andric Entry = Predicates.size(); 533349cc55cSDimitry Andric return Entry; 534349cc55cSDimitry Andric } 535349cc55cSDimitry Andric 536349cc55cSDimitry Andric PrintFatalError(Rec->getLoc(), "No " + Name + 537349cc55cSDimitry Andric " predicate on this operand at all: '" + 538349cc55cSDimitry Andric Rec->getName() + "'"); 539349cc55cSDimitry Andric return 0; 540349cc55cSDimitry Andric } 541349cc55cSDimitry Andric 542349cc55cSDimitry Andric static void printPredicates(const std::vector<const Record *> &Predicates, 5435f757f3fSDimitry Andric StringRef Name, raw_ostream &OS) { 5445f757f3fSDimitry Andric for (unsigned I = 0; I < Predicates.size(); ++I) { 5455f757f3fSDimitry Andric StringRef Pred = Predicates[I]->getValueAsString(Name); 5465f757f3fSDimitry Andric OS << " case " << I + 1 << ": {\n" 5475f757f3fSDimitry Andric << " // " << Predicates[I]->getName() << "\n" 548349cc55cSDimitry Andric << " " << Pred << "\n" 549349cc55cSDimitry Andric << " }\n"; 550349cc55cSDimitry Andric } 551349cc55cSDimitry Andric } 552349cc55cSDimitry Andric 553349cc55cSDimitry Andric static void mergeCondAndCode(raw_ostream &CombinedStream, StringRef CondStr, 554349cc55cSDimitry Andric StringRef CodeStr) { 555349cc55cSDimitry Andric // Remove first indentation and last '&&'. 556349cc55cSDimitry Andric CondStr = CondStr.drop_front(6).drop_back(4); 557349cc55cSDimitry Andric CombinedStream.indent(4) << "if (" << CondStr << ") {\n"; 558349cc55cSDimitry Andric CombinedStream << CodeStr; 559349cc55cSDimitry Andric CombinedStream.indent(4) << " return true;\n"; 560349cc55cSDimitry Andric CombinedStream.indent(4) << "} // if\n"; 561349cc55cSDimitry Andric } 562349cc55cSDimitry Andric 5635f757f3fSDimitry Andric void CompressInstEmitter::emitCompressInstEmitter(raw_ostream &OS, 564349cc55cSDimitry Andric EmitterType EType) { 565349cc55cSDimitry Andric Record *AsmWriter = Target.getAsmWriter(); 566349cc55cSDimitry Andric if (!AsmWriter->getValueAsInt("PassSubtarget")) 567349cc55cSDimitry Andric PrintFatalError(AsmWriter->getLoc(), 568349cc55cSDimitry Andric "'PassSubtarget' is false. SubTargetInfo object is needed " 569349cc55cSDimitry Andric "for target features.\n"); 570349cc55cSDimitry Andric 571349cc55cSDimitry Andric StringRef TargetName = Target.getName(); 572349cc55cSDimitry Andric 573349cc55cSDimitry Andric // Sort entries in CompressPatterns to handle instructions that can have more 574349cc55cSDimitry Andric // than one candidate for compression\uncompression, e.g ADD can be 575349cc55cSDimitry Andric // transformed to a C_ADD or a C_MV. When emitting 'uncompress()' function the 576349cc55cSDimitry Andric // source and destination are flipped and the sort key needs to change 577349cc55cSDimitry Andric // accordingly. 578349cc55cSDimitry Andric llvm::stable_sort(CompressPatterns, [EType](const CompressPat &LHS, 579349cc55cSDimitry Andric const CompressPat &RHS) { 580349cc55cSDimitry Andric if (EType == EmitterType::Compress || EType == EmitterType::CheckCompress) 581349cc55cSDimitry Andric return (LHS.Source.TheDef->getName() < RHS.Source.TheDef->getName()); 582349cc55cSDimitry Andric return (LHS.Dest.TheDef->getName() < RHS.Dest.TheDef->getName()); 583349cc55cSDimitry Andric }); 584349cc55cSDimitry Andric 585349cc55cSDimitry Andric // A list of MCOperandPredicates for all operands in use, and the reverse map. 586349cc55cSDimitry Andric std::vector<const Record *> MCOpPredicates; 587349cc55cSDimitry Andric DenseMap<const Record *, unsigned> MCOpPredicateMap; 588349cc55cSDimitry Andric // A list of ImmLeaf Predicates for all operands in use, and the reverse map. 589349cc55cSDimitry Andric std::vector<const Record *> ImmLeafPredicates; 590349cc55cSDimitry Andric DenseMap<const Record *, unsigned> ImmLeafPredicateMap; 591349cc55cSDimitry Andric 592349cc55cSDimitry Andric std::string F; 593349cc55cSDimitry Andric std::string FH; 594349cc55cSDimitry Andric raw_string_ostream Func(F); 595349cc55cSDimitry Andric raw_string_ostream FuncH(FH); 596349cc55cSDimitry Andric 597349cc55cSDimitry Andric if (EType == EmitterType::Compress) 5985f757f3fSDimitry Andric OS << "\n#ifdef GEN_COMPRESS_INSTR\n" 599349cc55cSDimitry Andric << "#undef GEN_COMPRESS_INSTR\n\n"; 600349cc55cSDimitry Andric else if (EType == EmitterType::Uncompress) 6015f757f3fSDimitry Andric OS << "\n#ifdef GEN_UNCOMPRESS_INSTR\n" 602349cc55cSDimitry Andric << "#undef GEN_UNCOMPRESS_INSTR\n\n"; 603349cc55cSDimitry Andric else if (EType == EmitterType::CheckCompress) 6045f757f3fSDimitry Andric OS << "\n#ifdef GEN_CHECK_COMPRESS_INSTR\n" 605349cc55cSDimitry Andric << "#undef GEN_CHECK_COMPRESS_INSTR\n\n"; 606349cc55cSDimitry Andric 607349cc55cSDimitry Andric if (EType == EmitterType::Compress) { 608349cc55cSDimitry Andric FuncH << "static bool compressInst(MCInst &OutInst,\n"; 609349cc55cSDimitry Andric FuncH.indent(25) << "const MCInst &MI,\n"; 610bdd1243dSDimitry Andric FuncH.indent(25) << "const MCSubtargetInfo &STI) {\n"; 611349cc55cSDimitry Andric } else if (EType == EmitterType::Uncompress) { 612349cc55cSDimitry Andric FuncH << "static bool uncompressInst(MCInst &OutInst,\n"; 613349cc55cSDimitry Andric FuncH.indent(27) << "const MCInst &MI,\n"; 614349cc55cSDimitry Andric FuncH.indent(27) << "const MCSubtargetInfo &STI) {\n"; 615349cc55cSDimitry Andric } else if (EType == EmitterType::CheckCompress) { 616349cc55cSDimitry Andric FuncH << "static bool isCompressibleInst(const MachineInstr &MI,\n"; 617bdd1243dSDimitry Andric FuncH.indent(31) << "const " << TargetName << "Subtarget &STI) {\n"; 618349cc55cSDimitry Andric } 619349cc55cSDimitry Andric 620349cc55cSDimitry Andric if (CompressPatterns.empty()) { 621*0fca6ea1SDimitry Andric OS << FH; 6225f757f3fSDimitry Andric OS.indent(2) << "return false;\n}\n"; 623349cc55cSDimitry Andric if (EType == EmitterType::Compress) 6245f757f3fSDimitry Andric OS << "\n#endif //GEN_COMPRESS_INSTR\n"; 625349cc55cSDimitry Andric else if (EType == EmitterType::Uncompress) 6265f757f3fSDimitry Andric OS << "\n#endif //GEN_UNCOMPRESS_INSTR\n\n"; 627349cc55cSDimitry Andric else if (EType == EmitterType::CheckCompress) 6285f757f3fSDimitry Andric OS << "\n#endif //GEN_CHECK_COMPRESS_INSTR\n\n"; 629349cc55cSDimitry Andric return; 630349cc55cSDimitry Andric } 631349cc55cSDimitry Andric 632349cc55cSDimitry Andric std::string CaseString; 633349cc55cSDimitry Andric raw_string_ostream CaseStream(CaseString); 634349cc55cSDimitry Andric StringRef PrevOp; 635349cc55cSDimitry Andric StringRef CurOp; 636349cc55cSDimitry Andric CaseStream << " switch (MI.getOpcode()) {\n"; 637349cc55cSDimitry Andric CaseStream << " default: return false;\n"; 638349cc55cSDimitry Andric 639349cc55cSDimitry Andric bool CompressOrCheck = 640349cc55cSDimitry Andric EType == EmitterType::Compress || EType == EmitterType::CheckCompress; 641349cc55cSDimitry Andric bool CompressOrUncompress = 642349cc55cSDimitry Andric EType == EmitterType::Compress || EType == EmitterType::Uncompress; 643bdd1243dSDimitry Andric std::string ValidatorName = 644bdd1243dSDimitry Andric CompressOrUncompress 645bdd1243dSDimitry Andric ? (TargetName + "ValidateMCOperandFor" + 646bdd1243dSDimitry Andric (EType == EmitterType::Compress ? "Compress" : "Uncompress")) 647bdd1243dSDimitry Andric .str() 648bdd1243dSDimitry Andric : ""; 649349cc55cSDimitry Andric 650349cc55cSDimitry Andric for (auto &CompressPat : CompressPatterns) { 651349cc55cSDimitry Andric if (EType == EmitterType::Uncompress && CompressPat.IsCompressOnly) 652349cc55cSDimitry Andric continue; 653349cc55cSDimitry Andric 654349cc55cSDimitry Andric std::string CondString; 655349cc55cSDimitry Andric std::string CodeString; 656349cc55cSDimitry Andric raw_string_ostream CondStream(CondString); 657349cc55cSDimitry Andric raw_string_ostream CodeStream(CodeString); 658349cc55cSDimitry Andric CodeGenInstruction &Source = 659349cc55cSDimitry Andric CompressOrCheck ? CompressPat.Source : CompressPat.Dest; 660349cc55cSDimitry Andric CodeGenInstruction &Dest = 661349cc55cSDimitry Andric CompressOrCheck ? CompressPat.Dest : CompressPat.Source; 662349cc55cSDimitry Andric IndexedMap<OpData> SourceOperandMap = CompressOrCheck 663349cc55cSDimitry Andric ? CompressPat.SourceOperandMap 664349cc55cSDimitry Andric : CompressPat.DestOperandMap; 665349cc55cSDimitry Andric IndexedMap<OpData> &DestOperandMap = CompressOrCheck 666349cc55cSDimitry Andric ? CompressPat.DestOperandMap 667349cc55cSDimitry Andric : CompressPat.SourceOperandMap; 668349cc55cSDimitry Andric 669349cc55cSDimitry Andric CurOp = Source.TheDef->getName(); 670349cc55cSDimitry Andric // Check current and previous opcode to decide to continue or end a case. 671349cc55cSDimitry Andric if (CurOp != PrevOp) { 672349cc55cSDimitry Andric if (!PrevOp.empty()) 673349cc55cSDimitry Andric CaseStream.indent(6) << "break;\n } // case " + PrevOp + "\n"; 674349cc55cSDimitry Andric CaseStream.indent(4) << "case " + TargetName + "::" + CurOp + ": {\n"; 675349cc55cSDimitry Andric } 676349cc55cSDimitry Andric 677349cc55cSDimitry Andric std::set<std::pair<bool, StringRef>> FeaturesSet; 678349cc55cSDimitry Andric std::set<std::set<std::pair<bool, StringRef>>> AnyOfFeatureSets; 679349cc55cSDimitry Andric // Add CompressPat required features. 680349cc55cSDimitry Andric getReqFeatures(FeaturesSet, AnyOfFeatureSets, CompressPat.PatReqFeatures); 681349cc55cSDimitry Andric 682349cc55cSDimitry Andric // Add Dest instruction required features. 683349cc55cSDimitry Andric std::vector<Record *> ReqFeatures; 684349cc55cSDimitry Andric std::vector<Record *> RF = Dest.TheDef->getValueAsListOfDefs("Predicates"); 685349cc55cSDimitry Andric copy_if(RF, std::back_inserter(ReqFeatures), [](Record *R) { 686349cc55cSDimitry Andric return R->getValueAsBit("AssemblerMatcherPredicate"); 687349cc55cSDimitry Andric }); 688349cc55cSDimitry Andric getReqFeatures(FeaturesSet, AnyOfFeatureSets, ReqFeatures); 689349cc55cSDimitry Andric 690349cc55cSDimitry Andric // Emit checks for all required features. 691349cc55cSDimitry Andric for (auto &Op : FeaturesSet) { 692349cc55cSDimitry Andric StringRef Not = Op.first ? "!" : ""; 693349cc55cSDimitry Andric CondStream.indent(6) << Not << "STI.getFeatureBits()[" << TargetName 694349cc55cSDimitry Andric << "::" << Op.second << "]" 695349cc55cSDimitry Andric << " &&\n"; 696349cc55cSDimitry Andric } 697349cc55cSDimitry Andric 698349cc55cSDimitry Andric // Emit checks for all required feature groups. 699349cc55cSDimitry Andric for (auto &Set : AnyOfFeatureSets) { 700349cc55cSDimitry Andric CondStream.indent(6) << "("; 701349cc55cSDimitry Andric for (auto &Op : Set) { 7025f757f3fSDimitry Andric bool IsLast = &Op == &*Set.rbegin(); 703349cc55cSDimitry Andric StringRef Not = Op.first ? "!" : ""; 704349cc55cSDimitry Andric CondStream << Not << "STI.getFeatureBits()[" << TargetName 705349cc55cSDimitry Andric << "::" << Op.second << "]"; 7065f757f3fSDimitry Andric if (!IsLast) 707349cc55cSDimitry Andric CondStream << " || "; 708349cc55cSDimitry Andric } 709349cc55cSDimitry Andric CondStream << ") &&\n"; 710349cc55cSDimitry Andric } 711349cc55cSDimitry Andric 712349cc55cSDimitry Andric // Start Source Inst operands validation. 713349cc55cSDimitry Andric unsigned OpNo = 0; 714349cc55cSDimitry Andric for (OpNo = 0; OpNo < Source.Operands.size(); ++OpNo) { 715349cc55cSDimitry Andric if (SourceOperandMap[OpNo].TiedOpIdx != -1) { 716349cc55cSDimitry Andric if (Source.Operands[OpNo].Rec->isSubClassOf("RegisterClass")) 717349cc55cSDimitry Andric CondStream.indent(6) 718bdd1243dSDimitry Andric << "(MI.getOperand(" << OpNo << ").isReg()) && (MI.getOperand(" 719bdd1243dSDimitry Andric << SourceOperandMap[OpNo].TiedOpIdx << ").isReg()) &&\n" 720bdd1243dSDimitry Andric << " (MI.getOperand(" << OpNo 721bdd1243dSDimitry Andric << ").getReg() == MI.getOperand(" 722349cc55cSDimitry Andric << SourceOperandMap[OpNo].TiedOpIdx << ").getReg()) &&\n"; 723349cc55cSDimitry Andric else 724349cc55cSDimitry Andric PrintFatalError("Unexpected tied operand types!\n"); 725349cc55cSDimitry Andric } 726349cc55cSDimitry Andric // Check for fixed immediates\registers in the source instruction. 727349cc55cSDimitry Andric switch (SourceOperandMap[OpNo].Kind) { 728349cc55cSDimitry Andric case OpData::Operand: 729349cc55cSDimitry Andric // We don't need to do anything for source instruction operand checks. 730349cc55cSDimitry Andric break; 731349cc55cSDimitry Andric case OpData::Imm: 732349cc55cSDimitry Andric CondStream.indent(6) 733349cc55cSDimitry Andric << "(MI.getOperand(" << OpNo << ").isImm()) &&\n" 734349cc55cSDimitry Andric << " (MI.getOperand(" << OpNo 735349cc55cSDimitry Andric << ").getImm() == " << SourceOperandMap[OpNo].Data.Imm << ") &&\n"; 736349cc55cSDimitry Andric break; 737349cc55cSDimitry Andric case OpData::Reg: { 738349cc55cSDimitry Andric Record *Reg = SourceOperandMap[OpNo].Data.Reg; 739349cc55cSDimitry Andric CondStream.indent(6) 740bdd1243dSDimitry Andric << "(MI.getOperand(" << OpNo << ").isReg()) &&\n" 741349cc55cSDimitry Andric << " (MI.getOperand(" << OpNo << ").getReg() == " << TargetName 742349cc55cSDimitry Andric << "::" << Reg->getName() << ") &&\n"; 743349cc55cSDimitry Andric break; 744349cc55cSDimitry Andric } 745349cc55cSDimitry Andric } 746349cc55cSDimitry Andric } 747349cc55cSDimitry Andric CodeStream.indent(6) << "// " << Dest.AsmString << "\n"; 748349cc55cSDimitry Andric if (CompressOrUncompress) 749349cc55cSDimitry Andric CodeStream.indent(6) << "OutInst.setOpcode(" << TargetName 750349cc55cSDimitry Andric << "::" << Dest.TheDef->getName() << ");\n"; 751349cc55cSDimitry Andric OpNo = 0; 752349cc55cSDimitry Andric for (const auto &DestOperand : Dest.Operands) { 753349cc55cSDimitry Andric CodeStream.indent(6) << "// Operand: " << DestOperand.Name << "\n"; 754349cc55cSDimitry Andric switch (DestOperandMap[OpNo].Kind) { 755349cc55cSDimitry Andric case OpData::Operand: { 756349cc55cSDimitry Andric unsigned OpIdx = DestOperandMap[OpNo].Data.Operand; 757349cc55cSDimitry Andric // Check that the operand in the Source instruction fits 758349cc55cSDimitry Andric // the type for the Dest instruction. 759bdd1243dSDimitry Andric if (DestOperand.Rec->isSubClassOf("RegisterClass") || 760bdd1243dSDimitry Andric DestOperand.Rec->isSubClassOf("RegisterOperand")) { 761bdd1243dSDimitry Andric auto *ClassRec = DestOperand.Rec->isSubClassOf("RegisterClass") 762bdd1243dSDimitry Andric ? DestOperand.Rec 763bdd1243dSDimitry Andric : DestOperand.Rec->getValueAsDef("RegClass"); 764349cc55cSDimitry Andric // This is a register operand. Check the register class. 765349cc55cSDimitry Andric // Don't check register class if this is a tied operand, it was done 766349cc55cSDimitry Andric // for the operand its tied to. 767349cc55cSDimitry Andric if (DestOperand.getTiedRegister() == -1) 768bdd1243dSDimitry Andric CondStream.indent(6) 769bdd1243dSDimitry Andric << "(MI.getOperand(" << OpIdx << ").isReg()) &&\n" 7705f757f3fSDimitry Andric << " (" << TargetName << "MCRegisterClasses[" << TargetName 7715f757f3fSDimitry Andric << "::" << ClassRec->getName() 772bdd1243dSDimitry Andric << "RegClassID].contains(MI.getOperand(" << OpIdx 773bdd1243dSDimitry Andric << ").getReg())) &&\n"; 774349cc55cSDimitry Andric 775349cc55cSDimitry Andric if (CompressOrUncompress) 776349cc55cSDimitry Andric CodeStream.indent(6) 777349cc55cSDimitry Andric << "OutInst.addOperand(MI.getOperand(" << OpIdx << "));\n"; 778349cc55cSDimitry Andric } else { 779349cc55cSDimitry Andric // Handling immediate operands. 780349cc55cSDimitry Andric if (CompressOrUncompress) { 781349cc55cSDimitry Andric unsigned Entry = 782349cc55cSDimitry Andric getPredicates(MCOpPredicateMap, MCOpPredicates, DestOperand.Rec, 783349cc55cSDimitry Andric "MCOperandPredicate"); 784349cc55cSDimitry Andric CondStream.indent(6) 785bdd1243dSDimitry Andric << ValidatorName << "(" 786349cc55cSDimitry Andric << "MI.getOperand(" << OpIdx << "), STI, " << Entry << ") &&\n"; 787349cc55cSDimitry Andric } else { 788349cc55cSDimitry Andric unsigned Entry = 789349cc55cSDimitry Andric getPredicates(ImmLeafPredicateMap, ImmLeafPredicates, 790349cc55cSDimitry Andric DestOperand.Rec, "ImmediateCode"); 791349cc55cSDimitry Andric CondStream.indent(6) 792349cc55cSDimitry Andric << "MI.getOperand(" << OpIdx << ").isImm() &&\n"; 793349cc55cSDimitry Andric CondStream.indent(6) << TargetName << "ValidateMachineOperand(" 7945f757f3fSDimitry Andric << "MI.getOperand(" << OpIdx << "), &STI, " 7955f757f3fSDimitry Andric << Entry << ") &&\n"; 796349cc55cSDimitry Andric } 797349cc55cSDimitry Andric if (CompressOrUncompress) 798349cc55cSDimitry Andric CodeStream.indent(6) 799349cc55cSDimitry Andric << "OutInst.addOperand(MI.getOperand(" << OpIdx << "));\n"; 800349cc55cSDimitry Andric } 801349cc55cSDimitry Andric break; 802349cc55cSDimitry Andric } 803349cc55cSDimitry Andric case OpData::Imm: { 804349cc55cSDimitry Andric if (CompressOrUncompress) { 805349cc55cSDimitry Andric unsigned Entry = getPredicates(MCOpPredicateMap, MCOpPredicates, 806349cc55cSDimitry Andric DestOperand.Rec, "MCOperandPredicate"); 807349cc55cSDimitry Andric CondStream.indent(6) 808bdd1243dSDimitry Andric << ValidatorName << "(" 809349cc55cSDimitry Andric << "MCOperand::createImm(" << DestOperandMap[OpNo].Data.Imm 810349cc55cSDimitry Andric << "), STI, " << Entry << ") &&\n"; 811349cc55cSDimitry Andric } else { 812349cc55cSDimitry Andric unsigned Entry = getPredicates(ImmLeafPredicateMap, ImmLeafPredicates, 813349cc55cSDimitry Andric DestOperand.Rec, "ImmediateCode"); 814349cc55cSDimitry Andric CondStream.indent(6) 815349cc55cSDimitry Andric << TargetName 816349cc55cSDimitry Andric << "ValidateMachineOperand(MachineOperand::CreateImm(" 817bdd1243dSDimitry Andric << DestOperandMap[OpNo].Data.Imm << "), &STI, " << Entry 818349cc55cSDimitry Andric << ") &&\n"; 819349cc55cSDimitry Andric } 820349cc55cSDimitry Andric if (CompressOrUncompress) 821349cc55cSDimitry Andric CodeStream.indent(6) << "OutInst.addOperand(MCOperand::createImm(" 822349cc55cSDimitry Andric << DestOperandMap[OpNo].Data.Imm << "));\n"; 823349cc55cSDimitry Andric } break; 824349cc55cSDimitry Andric case OpData::Reg: { 825349cc55cSDimitry Andric if (CompressOrUncompress) { 826349cc55cSDimitry Andric // Fixed register has been validated at pattern validation time. 827349cc55cSDimitry Andric Record *Reg = DestOperandMap[OpNo].Data.Reg; 828349cc55cSDimitry Andric CodeStream.indent(6) 829349cc55cSDimitry Andric << "OutInst.addOperand(MCOperand::createReg(" << TargetName 830349cc55cSDimitry Andric << "::" << Reg->getName() << "));\n"; 831349cc55cSDimitry Andric } 832349cc55cSDimitry Andric } break; 833349cc55cSDimitry Andric } 834349cc55cSDimitry Andric ++OpNo; 835349cc55cSDimitry Andric } 836349cc55cSDimitry Andric if (CompressOrUncompress) 837349cc55cSDimitry Andric CodeStream.indent(6) << "OutInst.setLoc(MI.getLoc());\n"; 838*0fca6ea1SDimitry Andric mergeCondAndCode(CaseStream, CondString, CodeString); 839349cc55cSDimitry Andric PrevOp = CurOp; 840349cc55cSDimitry Andric } 841*0fca6ea1SDimitry Andric Func << CaseString << "\n"; 842349cc55cSDimitry Andric // Close brace for the last case. 843349cc55cSDimitry Andric Func.indent(4) << "} // case " << CurOp << "\n"; 844349cc55cSDimitry Andric Func.indent(2) << "} // switch\n"; 845349cc55cSDimitry Andric Func.indent(2) << "return false;\n}\n"; 846349cc55cSDimitry Andric 847349cc55cSDimitry Andric if (!MCOpPredicates.empty()) { 8485f757f3fSDimitry Andric OS << "static bool " << ValidatorName << "(const MCOperand &MCOp,\n" 849349cc55cSDimitry Andric << " const MCSubtargetInfo &STI,\n" 850349cc55cSDimitry Andric << " unsigned PredicateIndex) {\n" 851349cc55cSDimitry Andric << " switch (PredicateIndex) {\n" 852349cc55cSDimitry Andric << " default:\n" 853349cc55cSDimitry Andric << " llvm_unreachable(\"Unknown MCOperandPredicate kind\");\n" 854349cc55cSDimitry Andric << " break;\n"; 855349cc55cSDimitry Andric 8565f757f3fSDimitry Andric printPredicates(MCOpPredicates, "MCOperandPredicate", OS); 857349cc55cSDimitry Andric 8585f757f3fSDimitry Andric OS << " }\n" 859349cc55cSDimitry Andric << "}\n\n"; 860349cc55cSDimitry Andric } 861349cc55cSDimitry Andric 862349cc55cSDimitry Andric if (!ImmLeafPredicates.empty()) { 8635f757f3fSDimitry Andric OS << "static bool " << TargetName 864349cc55cSDimitry Andric << "ValidateMachineOperand(const MachineOperand &MO,\n" 865349cc55cSDimitry Andric << " const " << TargetName << "Subtarget *Subtarget,\n" 866349cc55cSDimitry Andric << " unsigned PredicateIndex) {\n" 867349cc55cSDimitry Andric << " int64_t Imm = MO.getImm();\n" 868349cc55cSDimitry Andric << " switch (PredicateIndex) {\n" 869349cc55cSDimitry Andric << " default:\n" 870349cc55cSDimitry Andric << " llvm_unreachable(\"Unknown ImmLeaf Predicate kind\");\n" 871349cc55cSDimitry Andric << " break;\n"; 872349cc55cSDimitry Andric 8735f757f3fSDimitry Andric printPredicates(ImmLeafPredicates, "ImmediateCode", OS); 874349cc55cSDimitry Andric 8755f757f3fSDimitry Andric OS << " }\n" 876349cc55cSDimitry Andric << "}\n\n"; 877349cc55cSDimitry Andric } 878349cc55cSDimitry Andric 879*0fca6ea1SDimitry Andric OS << FH; 880*0fca6ea1SDimitry Andric OS << F; 881349cc55cSDimitry Andric 882349cc55cSDimitry Andric if (EType == EmitterType::Compress) 8835f757f3fSDimitry Andric OS << "\n#endif //GEN_COMPRESS_INSTR\n"; 884349cc55cSDimitry Andric else if (EType == EmitterType::Uncompress) 8855f757f3fSDimitry Andric OS << "\n#endif //GEN_UNCOMPRESS_INSTR\n\n"; 886349cc55cSDimitry Andric else if (EType == EmitterType::CheckCompress) 8875f757f3fSDimitry Andric OS << "\n#endif //GEN_CHECK_COMPRESS_INSTR\n\n"; 888349cc55cSDimitry Andric } 889349cc55cSDimitry Andric 8905f757f3fSDimitry Andric void CompressInstEmitter::run(raw_ostream &OS) { 891349cc55cSDimitry Andric std::vector<Record *> Insts = Records.getAllDerivedDefinitions("CompressPat"); 892349cc55cSDimitry Andric 893349cc55cSDimitry Andric // Process the CompressPat definitions, validating them as we do so. 8945f757f3fSDimitry Andric for (unsigned I = 0, E = Insts.size(); I != E; ++I) 8955f757f3fSDimitry Andric evaluateCompressPat(Insts[I]); 896349cc55cSDimitry Andric 897349cc55cSDimitry Andric // Emit file header. 8985f757f3fSDimitry Andric emitSourceFileHeader("Compress instruction Source Fragment", OS, Records); 899349cc55cSDimitry Andric // Generate compressInst() function. 9005f757f3fSDimitry Andric emitCompressInstEmitter(OS, EmitterType::Compress); 901349cc55cSDimitry Andric // Generate uncompressInst() function. 9025f757f3fSDimitry Andric emitCompressInstEmitter(OS, EmitterType::Uncompress); 903349cc55cSDimitry Andric // Generate isCompressibleInst() function. 9045f757f3fSDimitry Andric emitCompressInstEmitter(OS, EmitterType::CheckCompress); 905349cc55cSDimitry Andric } 906349cc55cSDimitry Andric 90706c3fb27SDimitry Andric static TableGen::Emitter::OptClass<CompressInstEmitter> 90806c3fb27SDimitry Andric X("gen-compress-inst-emitter", "Generate compressed instructions."); 909