1*349cc55cSDimitry Andric //===-------- CompressInstEmitter.cpp - Generator for Compression ---------===// 2*349cc55cSDimitry Andric // 3*349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*349cc55cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*349cc55cSDimitry Andric // 7*349cc55cSDimitry Andric // CompressInstEmitter implements a tablegen-driven CompressPat based 8*349cc55cSDimitry Andric // Instruction Compression mechanism. 9*349cc55cSDimitry Andric // 10*349cc55cSDimitry Andric //===----------------------------------------------------------------------===// 11*349cc55cSDimitry Andric // 12*349cc55cSDimitry Andric // CompressInstEmitter implements a tablegen-driven CompressPat Instruction 13*349cc55cSDimitry Andric // Compression mechanism for generating compressed instructions from the 14*349cc55cSDimitry Andric // expanded instruction form. 15*349cc55cSDimitry Andric 16*349cc55cSDimitry Andric // This tablegen backend processes CompressPat declarations in a 17*349cc55cSDimitry Andric // td file and generates all the required checks to validate the pattern 18*349cc55cSDimitry Andric // declarations; validate the input and output operands to generate the correct 19*349cc55cSDimitry Andric // compressed instructions. The checks include validating different types of 20*349cc55cSDimitry Andric // operands; register operands, immediate operands, fixed register and fixed 21*349cc55cSDimitry Andric // immediate inputs. 22*349cc55cSDimitry Andric // 23*349cc55cSDimitry Andric // Example: 24*349cc55cSDimitry Andric // /// Defines a Pat match between compressed and uncompressed instruction. 25*349cc55cSDimitry Andric // /// The relationship and helper function generation are handled by 26*349cc55cSDimitry Andric // /// CompressInstEmitter backend. 27*349cc55cSDimitry Andric // class CompressPat<dag input, dag output, list<Predicate> predicates = []> { 28*349cc55cSDimitry Andric // /// Uncompressed instruction description. 29*349cc55cSDimitry Andric // dag Input = input; 30*349cc55cSDimitry Andric // /// Compressed instruction description. 31*349cc55cSDimitry Andric // dag Output = output; 32*349cc55cSDimitry Andric // /// Predicates that must be true for this to match. 33*349cc55cSDimitry Andric // list<Predicate> Predicates = predicates; 34*349cc55cSDimitry Andric // /// Duplicate match when tied operand is just different. 35*349cc55cSDimitry Andric // bit isCompressOnly = false; 36*349cc55cSDimitry Andric // } 37*349cc55cSDimitry Andric // 38*349cc55cSDimitry Andric // let Predicates = [HasStdExtC] in { 39*349cc55cSDimitry Andric // def : CompressPat<(ADD GPRNoX0:$rs1, GPRNoX0:$rs1, GPRNoX0:$rs2), 40*349cc55cSDimitry Andric // (C_ADD GPRNoX0:$rs1, GPRNoX0:$rs2)>; 41*349cc55cSDimitry Andric // } 42*349cc55cSDimitry Andric // 43*349cc55cSDimitry Andric // The <TargetName>GenCompressInstEmitter.inc is an auto-generated header 44*349cc55cSDimitry Andric // file which exports two functions for compressing/uncompressing MCInst 45*349cc55cSDimitry Andric // instructions, plus some helper functions: 46*349cc55cSDimitry Andric // 47*349cc55cSDimitry Andric // bool compressInst(MCInst &OutInst, const MCInst &MI, 48*349cc55cSDimitry Andric // const MCSubtargetInfo &STI, 49*349cc55cSDimitry Andric // MCContext &Context); 50*349cc55cSDimitry Andric // 51*349cc55cSDimitry Andric // bool uncompressInst(MCInst &OutInst, const MCInst &MI, 52*349cc55cSDimitry Andric // const MCRegisterInfo &MRI, 53*349cc55cSDimitry Andric // const MCSubtargetInfo &STI); 54*349cc55cSDimitry Andric // 55*349cc55cSDimitry Andric // In addition, it exports a function for checking whether 56*349cc55cSDimitry Andric // an instruction is compressable: 57*349cc55cSDimitry Andric // 58*349cc55cSDimitry Andric // bool isCompressibleInst(const MachineInstr& MI, 59*349cc55cSDimitry Andric // const <TargetName>Subtarget *Subtarget, 60*349cc55cSDimitry Andric // const MCRegisterInfo &MRI, 61*349cc55cSDimitry Andric // const MCSubtargetInfo &STI); 62*349cc55cSDimitry Andric // 63*349cc55cSDimitry Andric // The clients that include this auto-generated header file and 64*349cc55cSDimitry Andric // invoke these functions can compress an instruction before emitting 65*349cc55cSDimitry Andric // it in the target-specific ASM or ELF streamer or can uncompress 66*349cc55cSDimitry Andric // an instruction before printing it when the expanded instruction 67*349cc55cSDimitry Andric // format aliases is favored. 68*349cc55cSDimitry Andric 69*349cc55cSDimitry Andric //===----------------------------------------------------------------------===// 70*349cc55cSDimitry Andric 71*349cc55cSDimitry Andric #include "CodeGenInstruction.h" 72*349cc55cSDimitry Andric #include "CodeGenTarget.h" 73*349cc55cSDimitry Andric #include "llvm/ADT/IndexedMap.h" 74*349cc55cSDimitry Andric #include "llvm/ADT/SmallVector.h" 75*349cc55cSDimitry Andric #include "llvm/ADT/StringExtras.h" 76*349cc55cSDimitry Andric #include "llvm/ADT/StringMap.h" 77*349cc55cSDimitry Andric #include "llvm/Support/Debug.h" 78*349cc55cSDimitry Andric #include "llvm/Support/ErrorHandling.h" 79*349cc55cSDimitry Andric #include "llvm/TableGen/Error.h" 80*349cc55cSDimitry Andric #include "llvm/TableGen/Record.h" 81*349cc55cSDimitry Andric #include "llvm/TableGen/TableGenBackend.h" 82*349cc55cSDimitry Andric #include <set> 83*349cc55cSDimitry Andric #include <vector> 84*349cc55cSDimitry Andric using namespace llvm; 85*349cc55cSDimitry Andric 86*349cc55cSDimitry Andric #define DEBUG_TYPE "compress-inst-emitter" 87*349cc55cSDimitry Andric 88*349cc55cSDimitry Andric namespace { 89*349cc55cSDimitry Andric class CompressInstEmitter { 90*349cc55cSDimitry Andric struct OpData { 91*349cc55cSDimitry Andric enum MapKind { Operand, Imm, Reg }; 92*349cc55cSDimitry Andric MapKind Kind; 93*349cc55cSDimitry Andric union { 94*349cc55cSDimitry Andric // Operand number mapped to. 95*349cc55cSDimitry Andric unsigned Operand; 96*349cc55cSDimitry Andric // Integer immediate value. 97*349cc55cSDimitry Andric int64_t Imm; 98*349cc55cSDimitry Andric // Physical register. 99*349cc55cSDimitry Andric Record *Reg; 100*349cc55cSDimitry Andric } Data; 101*349cc55cSDimitry Andric // Tied operand index within the instruction. 102*349cc55cSDimitry Andric int TiedOpIdx = -1; 103*349cc55cSDimitry Andric }; 104*349cc55cSDimitry Andric struct CompressPat { 105*349cc55cSDimitry Andric // The source instruction definition. 106*349cc55cSDimitry Andric CodeGenInstruction Source; 107*349cc55cSDimitry Andric // The destination instruction to transform to. 108*349cc55cSDimitry Andric CodeGenInstruction Dest; 109*349cc55cSDimitry Andric // Required target features to enable pattern. 110*349cc55cSDimitry Andric std::vector<Record *> PatReqFeatures; 111*349cc55cSDimitry Andric // Maps operands in the Source Instruction to 112*349cc55cSDimitry Andric IndexedMap<OpData> SourceOperandMap; 113*349cc55cSDimitry Andric // the corresponding Dest instruction operand. 114*349cc55cSDimitry Andric // Maps operands in the Dest Instruction 115*349cc55cSDimitry Andric // to the corresponding Source instruction operand. 116*349cc55cSDimitry Andric IndexedMap<OpData> DestOperandMap; 117*349cc55cSDimitry Andric 118*349cc55cSDimitry Andric bool IsCompressOnly; 119*349cc55cSDimitry Andric CompressPat(CodeGenInstruction &S, CodeGenInstruction &D, 120*349cc55cSDimitry Andric std::vector<Record *> RF, IndexedMap<OpData> &SourceMap, 121*349cc55cSDimitry Andric IndexedMap<OpData> &DestMap, bool IsCompressOnly) 122*349cc55cSDimitry Andric : Source(S), Dest(D), PatReqFeatures(RF), SourceOperandMap(SourceMap), 123*349cc55cSDimitry Andric DestOperandMap(DestMap), IsCompressOnly(IsCompressOnly) {} 124*349cc55cSDimitry Andric }; 125*349cc55cSDimitry Andric enum EmitterType { Compress, Uncompress, CheckCompress }; 126*349cc55cSDimitry Andric RecordKeeper &Records; 127*349cc55cSDimitry Andric CodeGenTarget Target; 128*349cc55cSDimitry Andric SmallVector<CompressPat, 4> CompressPatterns; 129*349cc55cSDimitry Andric 130*349cc55cSDimitry Andric void addDagOperandMapping(Record *Rec, DagInit *Dag, CodeGenInstruction &Inst, 131*349cc55cSDimitry Andric IndexedMap<OpData> &OperandMap, bool IsSourceInst); 132*349cc55cSDimitry Andric void evaluateCompressPat(Record *Compress); 133*349cc55cSDimitry Andric void emitCompressInstEmitter(raw_ostream &o, EmitterType EType); 134*349cc55cSDimitry Andric bool validateTypes(Record *SubType, Record *Type, bool IsSourceInst); 135*349cc55cSDimitry Andric bool validateRegister(Record *Reg, Record *RegClass); 136*349cc55cSDimitry Andric void createDagOperandMapping(Record *Rec, StringMap<unsigned> &SourceOperands, 137*349cc55cSDimitry Andric StringMap<unsigned> &DestOperands, 138*349cc55cSDimitry Andric DagInit *SourceDag, DagInit *DestDag, 139*349cc55cSDimitry Andric IndexedMap<OpData> &SourceOperandMap); 140*349cc55cSDimitry Andric 141*349cc55cSDimitry Andric void createInstOperandMapping(Record *Rec, DagInit *SourceDag, 142*349cc55cSDimitry Andric DagInit *DestDag, 143*349cc55cSDimitry Andric IndexedMap<OpData> &SourceOperandMap, 144*349cc55cSDimitry Andric IndexedMap<OpData> &DestOperandMap, 145*349cc55cSDimitry Andric StringMap<unsigned> &SourceOperands, 146*349cc55cSDimitry Andric CodeGenInstruction &DestInst); 147*349cc55cSDimitry Andric 148*349cc55cSDimitry Andric public: 149*349cc55cSDimitry Andric CompressInstEmitter(RecordKeeper &R) : Records(R), Target(R) {} 150*349cc55cSDimitry Andric 151*349cc55cSDimitry Andric void run(raw_ostream &o); 152*349cc55cSDimitry Andric }; 153*349cc55cSDimitry Andric } // End anonymous namespace. 154*349cc55cSDimitry Andric 155*349cc55cSDimitry Andric bool CompressInstEmitter::validateRegister(Record *Reg, Record *RegClass) { 156*349cc55cSDimitry Andric assert(Reg->isSubClassOf("Register") && "Reg record should be a Register"); 157*349cc55cSDimitry Andric assert(RegClass->isSubClassOf("RegisterClass") && 158*349cc55cSDimitry Andric "RegClass record should be a RegisterClass"); 159*349cc55cSDimitry Andric const CodeGenRegisterClass &RC = Target.getRegisterClass(RegClass); 160*349cc55cSDimitry Andric const CodeGenRegister *R = Target.getRegisterByName(Reg->getName().lower()); 161*349cc55cSDimitry Andric assert((R != nullptr) && "Register not defined!!"); 162*349cc55cSDimitry Andric return RC.contains(R); 163*349cc55cSDimitry Andric } 164*349cc55cSDimitry Andric 165*349cc55cSDimitry Andric bool CompressInstEmitter::validateTypes(Record *DagOpType, Record *InstOpType, 166*349cc55cSDimitry Andric bool IsSourceInst) { 167*349cc55cSDimitry Andric if (DagOpType == InstOpType) 168*349cc55cSDimitry Andric return true; 169*349cc55cSDimitry Andric // Only source instruction operands are allowed to not match Input Dag 170*349cc55cSDimitry Andric // operands. 171*349cc55cSDimitry Andric if (!IsSourceInst) 172*349cc55cSDimitry Andric return false; 173*349cc55cSDimitry Andric 174*349cc55cSDimitry Andric if (DagOpType->isSubClassOf("RegisterClass") && 175*349cc55cSDimitry Andric InstOpType->isSubClassOf("RegisterClass")) { 176*349cc55cSDimitry Andric const CodeGenRegisterClass &RC = Target.getRegisterClass(InstOpType); 177*349cc55cSDimitry Andric const CodeGenRegisterClass &SubRC = Target.getRegisterClass(DagOpType); 178*349cc55cSDimitry Andric return RC.hasSubClass(&SubRC); 179*349cc55cSDimitry Andric } 180*349cc55cSDimitry Andric 181*349cc55cSDimitry Andric // At this point either or both types are not registers, reject the pattern. 182*349cc55cSDimitry Andric if (DagOpType->isSubClassOf("RegisterClass") || 183*349cc55cSDimitry Andric InstOpType->isSubClassOf("RegisterClass")) 184*349cc55cSDimitry Andric return false; 185*349cc55cSDimitry Andric 186*349cc55cSDimitry Andric // Let further validation happen when compress()/uncompress() functions are 187*349cc55cSDimitry Andric // invoked. 188*349cc55cSDimitry Andric LLVM_DEBUG(dbgs() << (IsSourceInst ? "Input" : "Output") 189*349cc55cSDimitry Andric << " Dag Operand Type: '" << DagOpType->getName() 190*349cc55cSDimitry Andric << "' and " 191*349cc55cSDimitry Andric << "Instruction Operand Type: '" << InstOpType->getName() 192*349cc55cSDimitry Andric << "' can't be checked at pattern validation time!\n"); 193*349cc55cSDimitry Andric return true; 194*349cc55cSDimitry Andric } 195*349cc55cSDimitry Andric 196*349cc55cSDimitry Andric /// The patterns in the Dag contain different types of operands: 197*349cc55cSDimitry Andric /// Register operands, e.g.: GPRC:$rs1; Fixed registers, e.g: X1; Immediate 198*349cc55cSDimitry Andric /// operands, e.g.: simm6:$imm; Fixed immediate operands, e.g.: 0. This function 199*349cc55cSDimitry Andric /// maps Dag operands to its corresponding instruction operands. For register 200*349cc55cSDimitry Andric /// operands and fixed registers it expects the Dag operand type to be contained 201*349cc55cSDimitry Andric /// in the instantiated instruction operand type. For immediate operands and 202*349cc55cSDimitry Andric /// immediates no validation checks are enforced at pattern validation time. 203*349cc55cSDimitry Andric void CompressInstEmitter::addDagOperandMapping(Record *Rec, DagInit *Dag, 204*349cc55cSDimitry Andric CodeGenInstruction &Inst, 205*349cc55cSDimitry Andric IndexedMap<OpData> &OperandMap, 206*349cc55cSDimitry Andric bool IsSourceInst) { 207*349cc55cSDimitry Andric // TiedCount keeps track of the number of operands skipped in Inst 208*349cc55cSDimitry Andric // operands list to get to the corresponding Dag operand. This is 209*349cc55cSDimitry Andric // necessary because the number of operands in Inst might be greater 210*349cc55cSDimitry Andric // than number of operands in the Dag due to how tied operands 211*349cc55cSDimitry Andric // are represented. 212*349cc55cSDimitry Andric unsigned TiedCount = 0; 213*349cc55cSDimitry Andric for (unsigned i = 0, e = Inst.Operands.size(); i != e; ++i) { 214*349cc55cSDimitry Andric int TiedOpIdx = Inst.Operands[i].getTiedRegister(); 215*349cc55cSDimitry Andric if (-1 != TiedOpIdx) { 216*349cc55cSDimitry Andric // Set the entry in OperandMap for the tied operand we're skipping. 217*349cc55cSDimitry Andric OperandMap[i].Kind = OperandMap[TiedOpIdx].Kind; 218*349cc55cSDimitry Andric OperandMap[i].Data = OperandMap[TiedOpIdx].Data; 219*349cc55cSDimitry Andric TiedCount++; 220*349cc55cSDimitry Andric continue; 221*349cc55cSDimitry Andric } 222*349cc55cSDimitry Andric if (DefInit *DI = dyn_cast<DefInit>(Dag->getArg(i - TiedCount))) { 223*349cc55cSDimitry Andric if (DI->getDef()->isSubClassOf("Register")) { 224*349cc55cSDimitry Andric // Check if the fixed register belongs to the Register class. 225*349cc55cSDimitry Andric if (!validateRegister(DI->getDef(), Inst.Operands[i].Rec)) 226*349cc55cSDimitry Andric PrintFatalError(Rec->getLoc(), 227*349cc55cSDimitry Andric "Error in Dag '" + Dag->getAsString() + 228*349cc55cSDimitry Andric "'Register: '" + DI->getDef()->getName() + 229*349cc55cSDimitry Andric "' is not in register class '" + 230*349cc55cSDimitry Andric Inst.Operands[i].Rec->getName() + "'"); 231*349cc55cSDimitry Andric OperandMap[i].Kind = OpData::Reg; 232*349cc55cSDimitry Andric OperandMap[i].Data.Reg = DI->getDef(); 233*349cc55cSDimitry Andric continue; 234*349cc55cSDimitry Andric } 235*349cc55cSDimitry Andric // Validate that Dag operand type matches the type defined in the 236*349cc55cSDimitry Andric // corresponding instruction. Operands in the input Dag pattern are 237*349cc55cSDimitry Andric // allowed to be a subclass of the type specified in corresponding 238*349cc55cSDimitry Andric // instruction operand instead of being an exact match. 239*349cc55cSDimitry Andric if (!validateTypes(DI->getDef(), Inst.Operands[i].Rec, IsSourceInst)) 240*349cc55cSDimitry Andric PrintFatalError(Rec->getLoc(), 241*349cc55cSDimitry Andric "Error in Dag '" + Dag->getAsString() + "'. Operand '" + 242*349cc55cSDimitry Andric Dag->getArgNameStr(i - TiedCount) + "' has type '" + 243*349cc55cSDimitry Andric DI->getDef()->getName() + 244*349cc55cSDimitry Andric "' which does not match the type '" + 245*349cc55cSDimitry Andric Inst.Operands[i].Rec->getName() + 246*349cc55cSDimitry Andric "' in the corresponding instruction operand!"); 247*349cc55cSDimitry Andric 248*349cc55cSDimitry Andric OperandMap[i].Kind = OpData::Operand; 249*349cc55cSDimitry Andric } else if (IntInit *II = dyn_cast<IntInit>(Dag->getArg(i - TiedCount))) { 250*349cc55cSDimitry Andric // Validate that corresponding instruction operand expects an immediate. 251*349cc55cSDimitry Andric if (Inst.Operands[i].Rec->isSubClassOf("RegisterClass")) 252*349cc55cSDimitry Andric PrintFatalError( 253*349cc55cSDimitry Andric Rec->getLoc(), 254*349cc55cSDimitry Andric "Error in Dag '" + Dag->getAsString() + "' Found immediate: '" + 255*349cc55cSDimitry Andric II->getAsString() + 256*349cc55cSDimitry Andric "' but corresponding instruction operand expected a register!"); 257*349cc55cSDimitry Andric // No pattern validation check possible for values of fixed immediate. 258*349cc55cSDimitry Andric OperandMap[i].Kind = OpData::Imm; 259*349cc55cSDimitry Andric OperandMap[i].Data.Imm = II->getValue(); 260*349cc55cSDimitry Andric LLVM_DEBUG( 261*349cc55cSDimitry Andric dbgs() << " Found immediate '" << II->getValue() << "' at " 262*349cc55cSDimitry Andric << (IsSourceInst ? "input " : "output ") 263*349cc55cSDimitry Andric << "Dag. No validation time check possible for values of " 264*349cc55cSDimitry Andric "fixed immediate.\n"); 265*349cc55cSDimitry Andric } else 266*349cc55cSDimitry Andric llvm_unreachable("Unhandled CompressPat argument type!"); 267*349cc55cSDimitry Andric } 268*349cc55cSDimitry Andric } 269*349cc55cSDimitry Andric 270*349cc55cSDimitry Andric // Verify the Dag operand count is enough to build an instruction. 271*349cc55cSDimitry Andric static bool verifyDagOpCount(CodeGenInstruction &Inst, DagInit *Dag, 272*349cc55cSDimitry Andric bool IsSource) { 273*349cc55cSDimitry Andric if (Dag->getNumArgs() == Inst.Operands.size()) 274*349cc55cSDimitry Andric return true; 275*349cc55cSDimitry Andric // Source instructions are non compressed instructions and don't have tied 276*349cc55cSDimitry Andric // operands. 277*349cc55cSDimitry Andric if (IsSource) 278*349cc55cSDimitry Andric PrintFatalError(Inst.TheDef->getLoc(), 279*349cc55cSDimitry Andric "Input operands for Inst '" + Inst.TheDef->getName() + 280*349cc55cSDimitry Andric "' and input Dag operand count mismatch"); 281*349cc55cSDimitry Andric // The Dag can't have more arguments than the Instruction. 282*349cc55cSDimitry Andric if (Dag->getNumArgs() > Inst.Operands.size()) 283*349cc55cSDimitry Andric PrintFatalError(Inst.TheDef->getLoc(), 284*349cc55cSDimitry Andric "Inst '" + Inst.TheDef->getName() + 285*349cc55cSDimitry Andric "' and Dag operand count mismatch"); 286*349cc55cSDimitry Andric 287*349cc55cSDimitry Andric // The Instruction might have tied operands so the Dag might have 288*349cc55cSDimitry Andric // a fewer operand count. 289*349cc55cSDimitry Andric unsigned RealCount = Inst.Operands.size(); 290*349cc55cSDimitry Andric for (const auto &Operand : Inst.Operands) 291*349cc55cSDimitry Andric if (Operand.getTiedRegister() != -1) 292*349cc55cSDimitry Andric --RealCount; 293*349cc55cSDimitry Andric 294*349cc55cSDimitry Andric if (Dag->getNumArgs() != RealCount) 295*349cc55cSDimitry Andric PrintFatalError(Inst.TheDef->getLoc(), 296*349cc55cSDimitry Andric "Inst '" + Inst.TheDef->getName() + 297*349cc55cSDimitry Andric "' and Dag operand count mismatch"); 298*349cc55cSDimitry Andric return true; 299*349cc55cSDimitry Andric } 300*349cc55cSDimitry Andric 301*349cc55cSDimitry Andric static bool validateArgsTypes(Init *Arg1, Init *Arg2) { 302*349cc55cSDimitry Andric return cast<DefInit>(Arg1)->getDef() == cast<DefInit>(Arg2)->getDef(); 303*349cc55cSDimitry Andric } 304*349cc55cSDimitry Andric 305*349cc55cSDimitry Andric // Creates a mapping between the operand name in the Dag (e.g. $rs1) and 306*349cc55cSDimitry Andric // its index in the list of Dag operands and checks that operands with the same 307*349cc55cSDimitry Andric // name have the same types. For example in 'C_ADD $rs1, $rs2' we generate the 308*349cc55cSDimitry Andric // mapping $rs1 --> 0, $rs2 ---> 1. If the operand appears twice in the (tied) 309*349cc55cSDimitry Andric // same Dag we use the last occurrence for indexing. 310*349cc55cSDimitry Andric void CompressInstEmitter::createDagOperandMapping( 311*349cc55cSDimitry Andric Record *Rec, StringMap<unsigned> &SourceOperands, 312*349cc55cSDimitry Andric StringMap<unsigned> &DestOperands, DagInit *SourceDag, DagInit *DestDag, 313*349cc55cSDimitry Andric IndexedMap<OpData> &SourceOperandMap) { 314*349cc55cSDimitry Andric for (unsigned i = 0; i < DestDag->getNumArgs(); ++i) { 315*349cc55cSDimitry Andric // Skip fixed immediates and registers, they were handled in 316*349cc55cSDimitry Andric // addDagOperandMapping. 317*349cc55cSDimitry Andric if ("" == DestDag->getArgNameStr(i)) 318*349cc55cSDimitry Andric continue; 319*349cc55cSDimitry Andric DestOperands[DestDag->getArgNameStr(i)] = i; 320*349cc55cSDimitry Andric } 321*349cc55cSDimitry Andric 322*349cc55cSDimitry Andric for (unsigned i = 0; i < SourceDag->getNumArgs(); ++i) { 323*349cc55cSDimitry Andric // Skip fixed immediates and registers, they were handled in 324*349cc55cSDimitry Andric // addDagOperandMapping. 325*349cc55cSDimitry Andric if ("" == SourceDag->getArgNameStr(i)) 326*349cc55cSDimitry Andric continue; 327*349cc55cSDimitry Andric 328*349cc55cSDimitry Andric StringMap<unsigned>::iterator it = 329*349cc55cSDimitry Andric SourceOperands.find(SourceDag->getArgNameStr(i)); 330*349cc55cSDimitry Andric if (it != SourceOperands.end()) { 331*349cc55cSDimitry Andric // Operand sharing the same name in the Dag should be mapped as tied. 332*349cc55cSDimitry Andric SourceOperandMap[i].TiedOpIdx = it->getValue(); 333*349cc55cSDimitry Andric if (!validateArgsTypes(SourceDag->getArg(it->getValue()), 334*349cc55cSDimitry Andric SourceDag->getArg(i))) 335*349cc55cSDimitry Andric PrintFatalError(Rec->getLoc(), 336*349cc55cSDimitry Andric "Input Operand '" + SourceDag->getArgNameStr(i) + 337*349cc55cSDimitry Andric "' has a mismatched tied operand!\n"); 338*349cc55cSDimitry Andric } 339*349cc55cSDimitry Andric it = DestOperands.find(SourceDag->getArgNameStr(i)); 340*349cc55cSDimitry Andric if (it == DestOperands.end()) 341*349cc55cSDimitry Andric PrintFatalError(Rec->getLoc(), "Operand " + SourceDag->getArgNameStr(i) + 342*349cc55cSDimitry Andric " defined in Input Dag but not used in" 343*349cc55cSDimitry Andric " Output Dag!\n"); 344*349cc55cSDimitry Andric // Input Dag operand types must match output Dag operand type. 345*349cc55cSDimitry Andric if (!validateArgsTypes(DestDag->getArg(it->getValue()), 346*349cc55cSDimitry Andric SourceDag->getArg(i))) 347*349cc55cSDimitry Andric PrintFatalError(Rec->getLoc(), "Type mismatch between Input and " 348*349cc55cSDimitry Andric "Output Dag operand '" + 349*349cc55cSDimitry Andric SourceDag->getArgNameStr(i) + "'!"); 350*349cc55cSDimitry Andric SourceOperands[SourceDag->getArgNameStr(i)] = i; 351*349cc55cSDimitry Andric } 352*349cc55cSDimitry Andric } 353*349cc55cSDimitry Andric 354*349cc55cSDimitry Andric /// Map operand names in the Dag to their index in both corresponding input and 355*349cc55cSDimitry Andric /// output instructions. Validate that operands defined in the input are 356*349cc55cSDimitry Andric /// used in the output pattern while populating the maps. 357*349cc55cSDimitry Andric void CompressInstEmitter::createInstOperandMapping( 358*349cc55cSDimitry Andric Record *Rec, DagInit *SourceDag, DagInit *DestDag, 359*349cc55cSDimitry Andric IndexedMap<OpData> &SourceOperandMap, IndexedMap<OpData> &DestOperandMap, 360*349cc55cSDimitry Andric StringMap<unsigned> &SourceOperands, CodeGenInstruction &DestInst) { 361*349cc55cSDimitry Andric // TiedCount keeps track of the number of operands skipped in Inst 362*349cc55cSDimitry Andric // operands list to get to the corresponding Dag operand. 363*349cc55cSDimitry Andric unsigned TiedCount = 0; 364*349cc55cSDimitry Andric LLVM_DEBUG(dbgs() << " Operand mapping:\n Source Dest\n"); 365*349cc55cSDimitry Andric for (unsigned i = 0, e = DestInst.Operands.size(); i != e; ++i) { 366*349cc55cSDimitry Andric int TiedInstOpIdx = DestInst.Operands[i].getTiedRegister(); 367*349cc55cSDimitry Andric if (TiedInstOpIdx != -1) { 368*349cc55cSDimitry Andric ++TiedCount; 369*349cc55cSDimitry Andric DestOperandMap[i].Data = DestOperandMap[TiedInstOpIdx].Data; 370*349cc55cSDimitry Andric DestOperandMap[i].Kind = DestOperandMap[TiedInstOpIdx].Kind; 371*349cc55cSDimitry Andric if (DestOperandMap[i].Kind == OpData::Operand) 372*349cc55cSDimitry Andric // No need to fill the SourceOperandMap here since it was mapped to 373*349cc55cSDimitry Andric // destination operand 'TiedInstOpIdx' in a previous iteration. 374*349cc55cSDimitry Andric LLVM_DEBUG(dbgs() << " " << DestOperandMap[i].Data.Operand 375*349cc55cSDimitry Andric << " ====> " << i 376*349cc55cSDimitry Andric << " Dest operand tied with operand '" 377*349cc55cSDimitry Andric << TiedInstOpIdx << "'\n"); 378*349cc55cSDimitry Andric continue; 379*349cc55cSDimitry Andric } 380*349cc55cSDimitry Andric // Skip fixed immediates and registers, they were handled in 381*349cc55cSDimitry Andric // addDagOperandMapping. 382*349cc55cSDimitry Andric if (DestOperandMap[i].Kind != OpData::Operand) 383*349cc55cSDimitry Andric continue; 384*349cc55cSDimitry Andric 385*349cc55cSDimitry Andric unsigned DagArgIdx = i - TiedCount; 386*349cc55cSDimitry Andric StringMap<unsigned>::iterator SourceOp = 387*349cc55cSDimitry Andric SourceOperands.find(DestDag->getArgNameStr(DagArgIdx)); 388*349cc55cSDimitry Andric if (SourceOp == SourceOperands.end()) 389*349cc55cSDimitry Andric PrintFatalError(Rec->getLoc(), 390*349cc55cSDimitry Andric "Output Dag operand '" + 391*349cc55cSDimitry Andric DestDag->getArgNameStr(DagArgIdx) + 392*349cc55cSDimitry Andric "' has no matching input Dag operand."); 393*349cc55cSDimitry Andric 394*349cc55cSDimitry Andric assert(DestDag->getArgNameStr(DagArgIdx) == 395*349cc55cSDimitry Andric SourceDag->getArgNameStr(SourceOp->getValue()) && 396*349cc55cSDimitry Andric "Incorrect operand mapping detected!\n"); 397*349cc55cSDimitry Andric DestOperandMap[i].Data.Operand = SourceOp->getValue(); 398*349cc55cSDimitry Andric SourceOperandMap[SourceOp->getValue()].Data.Operand = i; 399*349cc55cSDimitry Andric LLVM_DEBUG(dbgs() << " " << SourceOp->getValue() << " ====> " << i 400*349cc55cSDimitry Andric << "\n"); 401*349cc55cSDimitry Andric } 402*349cc55cSDimitry Andric } 403*349cc55cSDimitry Andric 404*349cc55cSDimitry Andric /// Validates the CompressPattern and create operand mapping. 405*349cc55cSDimitry Andric /// These are the checks to validate a CompressPat pattern declarations. 406*349cc55cSDimitry Andric /// Error out with message under these conditions: 407*349cc55cSDimitry Andric /// - Dag Input opcode is an expanded instruction and Dag Output opcode is a 408*349cc55cSDimitry Andric /// compressed instruction. 409*349cc55cSDimitry Andric /// - Operands in Dag Input must be all used in Dag Output. 410*349cc55cSDimitry Andric /// Register Operand type in Dag Input Type must be contained in the 411*349cc55cSDimitry Andric /// corresponding Source Instruction type. 412*349cc55cSDimitry Andric /// - Register Operand type in Dag Input must be the same as in Dag Ouput. 413*349cc55cSDimitry Andric /// - Register Operand type in Dag Output must be the same as the 414*349cc55cSDimitry Andric /// corresponding Destination Inst type. 415*349cc55cSDimitry Andric /// - Immediate Operand type in Dag Input must be the same as in Dag Ouput. 416*349cc55cSDimitry Andric /// - Immediate Operand type in Dag Ouput must be the same as the corresponding 417*349cc55cSDimitry Andric /// Destination Instruction type. 418*349cc55cSDimitry Andric /// - Fixed register must be contained in the corresponding Source Instruction 419*349cc55cSDimitry Andric /// type. 420*349cc55cSDimitry Andric /// - Fixed register must be contained in the corresponding Destination 421*349cc55cSDimitry Andric /// Instruction type. Warning message printed under these conditions: 422*349cc55cSDimitry Andric /// - Fixed immediate in Dag Input or Dag Ouput cannot be checked at this time 423*349cc55cSDimitry Andric /// and generate warning. 424*349cc55cSDimitry Andric /// - Immediate operand type in Dag Input differs from the corresponding Source 425*349cc55cSDimitry Andric /// Instruction type and generate a warning. 426*349cc55cSDimitry Andric void CompressInstEmitter::evaluateCompressPat(Record *Rec) { 427*349cc55cSDimitry Andric // Validate input Dag operands. 428*349cc55cSDimitry Andric DagInit *SourceDag = Rec->getValueAsDag("Input"); 429*349cc55cSDimitry Andric assert(SourceDag && "Missing 'Input' in compress pattern!"); 430*349cc55cSDimitry Andric LLVM_DEBUG(dbgs() << "Input: " << *SourceDag << "\n"); 431*349cc55cSDimitry Andric 432*349cc55cSDimitry Andric // Checking we are transforming from compressed to uncompressed instructions. 433*349cc55cSDimitry Andric Record *Operator = SourceDag->getOperatorAsDef(Rec->getLoc()); 434*349cc55cSDimitry Andric CodeGenInstruction SourceInst(Operator); 435*349cc55cSDimitry Andric verifyDagOpCount(SourceInst, SourceDag, true); 436*349cc55cSDimitry Andric 437*349cc55cSDimitry Andric // Validate output Dag operands. 438*349cc55cSDimitry Andric DagInit *DestDag = Rec->getValueAsDag("Output"); 439*349cc55cSDimitry Andric assert(DestDag && "Missing 'Output' in compress pattern!"); 440*349cc55cSDimitry Andric LLVM_DEBUG(dbgs() << "Output: " << *DestDag << "\n"); 441*349cc55cSDimitry Andric 442*349cc55cSDimitry Andric Record *DestOperator = DestDag->getOperatorAsDef(Rec->getLoc()); 443*349cc55cSDimitry Andric CodeGenInstruction DestInst(DestOperator); 444*349cc55cSDimitry Andric verifyDagOpCount(DestInst, DestDag, false); 445*349cc55cSDimitry Andric 446*349cc55cSDimitry Andric if (Operator->getValueAsInt("Size") <= DestOperator->getValueAsInt("Size")) 447*349cc55cSDimitry Andric PrintFatalError( 448*349cc55cSDimitry Andric Rec->getLoc(), 449*349cc55cSDimitry Andric "Compressed instruction '" + DestOperator->getName() + 450*349cc55cSDimitry Andric "'is not strictly smaller than the uncompressed instruction '" + 451*349cc55cSDimitry Andric Operator->getName() + "' !"); 452*349cc55cSDimitry Andric 453*349cc55cSDimitry Andric // Fill the mapping from the source to destination instructions. 454*349cc55cSDimitry Andric 455*349cc55cSDimitry Andric IndexedMap<OpData> SourceOperandMap; 456*349cc55cSDimitry Andric SourceOperandMap.grow(SourceInst.Operands.size()); 457*349cc55cSDimitry Andric // Create a mapping between source Dag operands and source Inst operands. 458*349cc55cSDimitry Andric addDagOperandMapping(Rec, SourceDag, SourceInst, SourceOperandMap, 459*349cc55cSDimitry Andric /*IsSourceInst*/ true); 460*349cc55cSDimitry Andric 461*349cc55cSDimitry Andric IndexedMap<OpData> DestOperandMap; 462*349cc55cSDimitry Andric DestOperandMap.grow(DestInst.Operands.size()); 463*349cc55cSDimitry Andric // Create a mapping between destination Dag operands and destination Inst 464*349cc55cSDimitry Andric // operands. 465*349cc55cSDimitry Andric addDagOperandMapping(Rec, DestDag, DestInst, DestOperandMap, 466*349cc55cSDimitry Andric /*IsSourceInst*/ false); 467*349cc55cSDimitry Andric 468*349cc55cSDimitry Andric StringMap<unsigned> SourceOperands; 469*349cc55cSDimitry Andric StringMap<unsigned> DestOperands; 470*349cc55cSDimitry Andric createDagOperandMapping(Rec, SourceOperands, DestOperands, SourceDag, DestDag, 471*349cc55cSDimitry Andric SourceOperandMap); 472*349cc55cSDimitry Andric // Create operand mapping between the source and destination instructions. 473*349cc55cSDimitry Andric createInstOperandMapping(Rec, SourceDag, DestDag, SourceOperandMap, 474*349cc55cSDimitry Andric DestOperandMap, SourceOperands, DestInst); 475*349cc55cSDimitry Andric 476*349cc55cSDimitry Andric // Get the target features for the CompressPat. 477*349cc55cSDimitry Andric std::vector<Record *> PatReqFeatures; 478*349cc55cSDimitry Andric std::vector<Record *> RF = Rec->getValueAsListOfDefs("Predicates"); 479*349cc55cSDimitry Andric copy_if(RF, std::back_inserter(PatReqFeatures), [](Record *R) { 480*349cc55cSDimitry Andric return R->getValueAsBit("AssemblerMatcherPredicate"); 481*349cc55cSDimitry Andric }); 482*349cc55cSDimitry Andric 483*349cc55cSDimitry Andric CompressPatterns.push_back(CompressPat(SourceInst, DestInst, PatReqFeatures, 484*349cc55cSDimitry Andric SourceOperandMap, DestOperandMap, 485*349cc55cSDimitry Andric Rec->getValueAsBit("isCompressOnly"))); 486*349cc55cSDimitry Andric } 487*349cc55cSDimitry Andric 488*349cc55cSDimitry Andric static void 489*349cc55cSDimitry Andric getReqFeatures(std::set<std::pair<bool, StringRef>> &FeaturesSet, 490*349cc55cSDimitry Andric std::set<std::set<std::pair<bool, StringRef>>> &AnyOfFeatureSets, 491*349cc55cSDimitry Andric const std::vector<Record *> &ReqFeatures) { 492*349cc55cSDimitry Andric for (auto &R : ReqFeatures) { 493*349cc55cSDimitry Andric const DagInit *D = R->getValueAsDag("AssemblerCondDag"); 494*349cc55cSDimitry Andric std::string CombineType = D->getOperator()->getAsString(); 495*349cc55cSDimitry Andric if (CombineType != "any_of" && CombineType != "all_of") 496*349cc55cSDimitry Andric PrintFatalError(R->getLoc(), "Invalid AssemblerCondDag!"); 497*349cc55cSDimitry Andric if (D->getNumArgs() == 0) 498*349cc55cSDimitry Andric PrintFatalError(R->getLoc(), "Invalid AssemblerCondDag!"); 499*349cc55cSDimitry Andric bool IsOr = CombineType == "any_of"; 500*349cc55cSDimitry Andric std::set<std::pair<bool, StringRef>> AnyOfSet; 501*349cc55cSDimitry Andric 502*349cc55cSDimitry Andric for (auto *Arg : D->getArgs()) { 503*349cc55cSDimitry Andric bool IsNot = false; 504*349cc55cSDimitry Andric if (auto *NotArg = dyn_cast<DagInit>(Arg)) { 505*349cc55cSDimitry Andric if (NotArg->getOperator()->getAsString() != "not" || 506*349cc55cSDimitry Andric NotArg->getNumArgs() != 1) 507*349cc55cSDimitry Andric PrintFatalError(R->getLoc(), "Invalid AssemblerCondDag!"); 508*349cc55cSDimitry Andric Arg = NotArg->getArg(0); 509*349cc55cSDimitry Andric IsNot = true; 510*349cc55cSDimitry Andric } 511*349cc55cSDimitry Andric if (!isa<DefInit>(Arg) || 512*349cc55cSDimitry Andric !cast<DefInit>(Arg)->getDef()->isSubClassOf("SubtargetFeature")) 513*349cc55cSDimitry Andric PrintFatalError(R->getLoc(), "Invalid AssemblerCondDag!"); 514*349cc55cSDimitry Andric if (IsOr) 515*349cc55cSDimitry Andric AnyOfSet.insert({IsNot, cast<DefInit>(Arg)->getDef()->getName()}); 516*349cc55cSDimitry Andric else 517*349cc55cSDimitry Andric FeaturesSet.insert({IsNot, cast<DefInit>(Arg)->getDef()->getName()}); 518*349cc55cSDimitry Andric } 519*349cc55cSDimitry Andric 520*349cc55cSDimitry Andric if (IsOr) 521*349cc55cSDimitry Andric AnyOfFeatureSets.insert(AnyOfSet); 522*349cc55cSDimitry Andric } 523*349cc55cSDimitry Andric } 524*349cc55cSDimitry Andric 525*349cc55cSDimitry Andric static unsigned getPredicates(DenseMap<const Record *, unsigned> &PredicateMap, 526*349cc55cSDimitry Andric std::vector<const Record *> &Predicates, 527*349cc55cSDimitry Andric Record *Rec, StringRef Name) { 528*349cc55cSDimitry Andric unsigned &Entry = PredicateMap[Rec]; 529*349cc55cSDimitry Andric if (Entry) 530*349cc55cSDimitry Andric return Entry; 531*349cc55cSDimitry Andric 532*349cc55cSDimitry Andric if (!Rec->isValueUnset(Name)) { 533*349cc55cSDimitry Andric Predicates.push_back(Rec); 534*349cc55cSDimitry Andric Entry = Predicates.size(); 535*349cc55cSDimitry Andric return Entry; 536*349cc55cSDimitry Andric } 537*349cc55cSDimitry Andric 538*349cc55cSDimitry Andric PrintFatalError(Rec->getLoc(), "No " + Name + 539*349cc55cSDimitry Andric " predicate on this operand at all: '" + 540*349cc55cSDimitry Andric Rec->getName() + "'"); 541*349cc55cSDimitry Andric return 0; 542*349cc55cSDimitry Andric } 543*349cc55cSDimitry Andric 544*349cc55cSDimitry Andric static void printPredicates(const std::vector<const Record *> &Predicates, 545*349cc55cSDimitry Andric StringRef Name, raw_ostream &o) { 546*349cc55cSDimitry Andric for (unsigned i = 0; i < Predicates.size(); ++i) { 547*349cc55cSDimitry Andric StringRef Pred = Predicates[i]->getValueAsString(Name); 548*349cc55cSDimitry Andric o << " case " << i + 1 << ": {\n" 549*349cc55cSDimitry Andric << " // " << Predicates[i]->getName() << "\n" 550*349cc55cSDimitry Andric << " " << Pred << "\n" 551*349cc55cSDimitry Andric << " }\n"; 552*349cc55cSDimitry Andric } 553*349cc55cSDimitry Andric } 554*349cc55cSDimitry Andric 555*349cc55cSDimitry Andric static void mergeCondAndCode(raw_ostream &CombinedStream, StringRef CondStr, 556*349cc55cSDimitry Andric StringRef CodeStr) { 557*349cc55cSDimitry Andric // Remove first indentation and last '&&'. 558*349cc55cSDimitry Andric CondStr = CondStr.drop_front(6).drop_back(4); 559*349cc55cSDimitry Andric CombinedStream.indent(4) << "if (" << CondStr << ") {\n"; 560*349cc55cSDimitry Andric CombinedStream << CodeStr; 561*349cc55cSDimitry Andric CombinedStream.indent(4) << " return true;\n"; 562*349cc55cSDimitry Andric CombinedStream.indent(4) << "} // if\n"; 563*349cc55cSDimitry Andric } 564*349cc55cSDimitry Andric 565*349cc55cSDimitry Andric void CompressInstEmitter::emitCompressInstEmitter(raw_ostream &o, 566*349cc55cSDimitry Andric EmitterType EType) { 567*349cc55cSDimitry Andric Record *AsmWriter = Target.getAsmWriter(); 568*349cc55cSDimitry Andric if (!AsmWriter->getValueAsInt("PassSubtarget")) 569*349cc55cSDimitry Andric PrintFatalError(AsmWriter->getLoc(), 570*349cc55cSDimitry Andric "'PassSubtarget' is false. SubTargetInfo object is needed " 571*349cc55cSDimitry Andric "for target features.\n"); 572*349cc55cSDimitry Andric 573*349cc55cSDimitry Andric StringRef TargetName = Target.getName(); 574*349cc55cSDimitry Andric 575*349cc55cSDimitry Andric // Sort entries in CompressPatterns to handle instructions that can have more 576*349cc55cSDimitry Andric // than one candidate for compression\uncompression, e.g ADD can be 577*349cc55cSDimitry Andric // transformed to a C_ADD or a C_MV. When emitting 'uncompress()' function the 578*349cc55cSDimitry Andric // source and destination are flipped and the sort key needs to change 579*349cc55cSDimitry Andric // accordingly. 580*349cc55cSDimitry Andric llvm::stable_sort(CompressPatterns, [EType](const CompressPat &LHS, 581*349cc55cSDimitry Andric const CompressPat &RHS) { 582*349cc55cSDimitry Andric if (EType == EmitterType::Compress || EType == EmitterType::CheckCompress) 583*349cc55cSDimitry Andric return (LHS.Source.TheDef->getName() < RHS.Source.TheDef->getName()); 584*349cc55cSDimitry Andric else 585*349cc55cSDimitry Andric return (LHS.Dest.TheDef->getName() < RHS.Dest.TheDef->getName()); 586*349cc55cSDimitry Andric }); 587*349cc55cSDimitry Andric 588*349cc55cSDimitry Andric // A list of MCOperandPredicates for all operands in use, and the reverse map. 589*349cc55cSDimitry Andric std::vector<const Record *> MCOpPredicates; 590*349cc55cSDimitry Andric DenseMap<const Record *, unsigned> MCOpPredicateMap; 591*349cc55cSDimitry Andric // A list of ImmLeaf Predicates for all operands in use, and the reverse map. 592*349cc55cSDimitry Andric std::vector<const Record *> ImmLeafPredicates; 593*349cc55cSDimitry Andric DenseMap<const Record *, unsigned> ImmLeafPredicateMap; 594*349cc55cSDimitry Andric 595*349cc55cSDimitry Andric std::string F; 596*349cc55cSDimitry Andric std::string FH; 597*349cc55cSDimitry Andric raw_string_ostream Func(F); 598*349cc55cSDimitry Andric raw_string_ostream FuncH(FH); 599*349cc55cSDimitry Andric bool NeedMRI = false; 600*349cc55cSDimitry Andric 601*349cc55cSDimitry Andric if (EType == EmitterType::Compress) 602*349cc55cSDimitry Andric o << "\n#ifdef GEN_COMPRESS_INSTR\n" 603*349cc55cSDimitry Andric << "#undef GEN_COMPRESS_INSTR\n\n"; 604*349cc55cSDimitry Andric else if (EType == EmitterType::Uncompress) 605*349cc55cSDimitry Andric o << "\n#ifdef GEN_UNCOMPRESS_INSTR\n" 606*349cc55cSDimitry Andric << "#undef GEN_UNCOMPRESS_INSTR\n\n"; 607*349cc55cSDimitry Andric else if (EType == EmitterType::CheckCompress) 608*349cc55cSDimitry Andric o << "\n#ifdef GEN_CHECK_COMPRESS_INSTR\n" 609*349cc55cSDimitry Andric << "#undef GEN_CHECK_COMPRESS_INSTR\n\n"; 610*349cc55cSDimitry Andric 611*349cc55cSDimitry Andric if (EType == EmitterType::Compress) { 612*349cc55cSDimitry Andric FuncH << "static bool compressInst(MCInst &OutInst,\n"; 613*349cc55cSDimitry Andric FuncH.indent(25) << "const MCInst &MI,\n"; 614*349cc55cSDimitry Andric FuncH.indent(25) << "const MCSubtargetInfo &STI,\n"; 615*349cc55cSDimitry Andric FuncH.indent(25) << "MCContext &Context) {\n"; 616*349cc55cSDimitry Andric } else if (EType == EmitterType::Uncompress) { 617*349cc55cSDimitry Andric FuncH << "static bool uncompressInst(MCInst &OutInst,\n"; 618*349cc55cSDimitry Andric FuncH.indent(27) << "const MCInst &MI,\n"; 619*349cc55cSDimitry Andric FuncH.indent(27) << "const MCRegisterInfo &MRI,\n"; 620*349cc55cSDimitry Andric FuncH.indent(27) << "const MCSubtargetInfo &STI) {\n"; 621*349cc55cSDimitry Andric } else if (EType == EmitterType::CheckCompress) { 622*349cc55cSDimitry Andric FuncH << "static bool isCompressibleInst(const MachineInstr &MI,\n"; 623*349cc55cSDimitry Andric FuncH.indent(27) << "const " << TargetName << "Subtarget *Subtarget,\n"; 624*349cc55cSDimitry Andric FuncH.indent(27) << "const MCRegisterInfo &MRI,\n"; 625*349cc55cSDimitry Andric FuncH.indent(27) << "const MCSubtargetInfo &STI) {\n"; 626*349cc55cSDimitry Andric } 627*349cc55cSDimitry Andric 628*349cc55cSDimitry Andric if (CompressPatterns.empty()) { 629*349cc55cSDimitry Andric o << FuncH.str(); 630*349cc55cSDimitry Andric o.indent(2) << "return false;\n}\n"; 631*349cc55cSDimitry Andric if (EType == EmitterType::Compress) 632*349cc55cSDimitry Andric o << "\n#endif //GEN_COMPRESS_INSTR\n"; 633*349cc55cSDimitry Andric else if (EType == EmitterType::Uncompress) 634*349cc55cSDimitry Andric o << "\n#endif //GEN_UNCOMPRESS_INSTR\n\n"; 635*349cc55cSDimitry Andric else if (EType == EmitterType::CheckCompress) 636*349cc55cSDimitry Andric o << "\n#endif //GEN_CHECK_COMPRESS_INSTR\n\n"; 637*349cc55cSDimitry Andric return; 638*349cc55cSDimitry Andric } 639*349cc55cSDimitry Andric 640*349cc55cSDimitry Andric std::string CaseString; 641*349cc55cSDimitry Andric raw_string_ostream CaseStream(CaseString); 642*349cc55cSDimitry Andric StringRef PrevOp; 643*349cc55cSDimitry Andric StringRef CurOp; 644*349cc55cSDimitry Andric CaseStream << " switch (MI.getOpcode()) {\n"; 645*349cc55cSDimitry Andric CaseStream << " default: return false;\n"; 646*349cc55cSDimitry Andric 647*349cc55cSDimitry Andric bool CompressOrCheck = 648*349cc55cSDimitry Andric EType == EmitterType::Compress || EType == EmitterType::CheckCompress; 649*349cc55cSDimitry Andric bool CompressOrUncompress = 650*349cc55cSDimitry Andric EType == EmitterType::Compress || EType == EmitterType::Uncompress; 651*349cc55cSDimitry Andric 652*349cc55cSDimitry Andric for (auto &CompressPat : CompressPatterns) { 653*349cc55cSDimitry Andric if (EType == EmitterType::Uncompress && CompressPat.IsCompressOnly) 654*349cc55cSDimitry Andric continue; 655*349cc55cSDimitry Andric 656*349cc55cSDimitry Andric std::string CondString; 657*349cc55cSDimitry Andric std::string CodeString; 658*349cc55cSDimitry Andric raw_string_ostream CondStream(CondString); 659*349cc55cSDimitry Andric raw_string_ostream CodeStream(CodeString); 660*349cc55cSDimitry Andric CodeGenInstruction &Source = 661*349cc55cSDimitry Andric CompressOrCheck ? CompressPat.Source : CompressPat.Dest; 662*349cc55cSDimitry Andric CodeGenInstruction &Dest = 663*349cc55cSDimitry Andric CompressOrCheck ? CompressPat.Dest : CompressPat.Source; 664*349cc55cSDimitry Andric IndexedMap<OpData> SourceOperandMap = CompressOrCheck 665*349cc55cSDimitry Andric ? CompressPat.SourceOperandMap 666*349cc55cSDimitry Andric : CompressPat.DestOperandMap; 667*349cc55cSDimitry Andric IndexedMap<OpData> &DestOperandMap = CompressOrCheck 668*349cc55cSDimitry Andric ? CompressPat.DestOperandMap 669*349cc55cSDimitry Andric : CompressPat.SourceOperandMap; 670*349cc55cSDimitry Andric 671*349cc55cSDimitry Andric CurOp = Source.TheDef->getName(); 672*349cc55cSDimitry Andric // Check current and previous opcode to decide to continue or end a case. 673*349cc55cSDimitry Andric if (CurOp != PrevOp) { 674*349cc55cSDimitry Andric if (!PrevOp.empty()) 675*349cc55cSDimitry Andric CaseStream.indent(6) << "break;\n } // case " + PrevOp + "\n"; 676*349cc55cSDimitry Andric CaseStream.indent(4) << "case " + TargetName + "::" + CurOp + ": {\n"; 677*349cc55cSDimitry Andric } 678*349cc55cSDimitry Andric 679*349cc55cSDimitry Andric std::set<std::pair<bool, StringRef>> FeaturesSet; 680*349cc55cSDimitry Andric std::set<std::set<std::pair<bool, StringRef>>> AnyOfFeatureSets; 681*349cc55cSDimitry Andric // Add CompressPat required features. 682*349cc55cSDimitry Andric getReqFeatures(FeaturesSet, AnyOfFeatureSets, CompressPat.PatReqFeatures); 683*349cc55cSDimitry Andric 684*349cc55cSDimitry Andric // Add Dest instruction required features. 685*349cc55cSDimitry Andric std::vector<Record *> ReqFeatures; 686*349cc55cSDimitry Andric std::vector<Record *> RF = Dest.TheDef->getValueAsListOfDefs("Predicates"); 687*349cc55cSDimitry Andric copy_if(RF, std::back_inserter(ReqFeatures), [](Record *R) { 688*349cc55cSDimitry Andric return R->getValueAsBit("AssemblerMatcherPredicate"); 689*349cc55cSDimitry Andric }); 690*349cc55cSDimitry Andric getReqFeatures(FeaturesSet, AnyOfFeatureSets, ReqFeatures); 691*349cc55cSDimitry Andric 692*349cc55cSDimitry Andric // Emit checks for all required features. 693*349cc55cSDimitry Andric for (auto &Op : FeaturesSet) { 694*349cc55cSDimitry Andric StringRef Not = Op.first ? "!" : ""; 695*349cc55cSDimitry Andric CondStream.indent(6) << Not << "STI.getFeatureBits()[" << TargetName 696*349cc55cSDimitry Andric << "::" << Op.second << "]" 697*349cc55cSDimitry Andric << " &&\n"; 698*349cc55cSDimitry Andric } 699*349cc55cSDimitry Andric 700*349cc55cSDimitry Andric // Emit checks for all required feature groups. 701*349cc55cSDimitry Andric for (auto &Set : AnyOfFeatureSets) { 702*349cc55cSDimitry Andric CondStream.indent(6) << "("; 703*349cc55cSDimitry Andric for (auto &Op : Set) { 704*349cc55cSDimitry Andric bool isLast = &Op == &*Set.rbegin(); 705*349cc55cSDimitry Andric StringRef Not = Op.first ? "!" : ""; 706*349cc55cSDimitry Andric CondStream << Not << "STI.getFeatureBits()[" << TargetName 707*349cc55cSDimitry Andric << "::" << Op.second << "]"; 708*349cc55cSDimitry Andric if (!isLast) 709*349cc55cSDimitry Andric CondStream << " || "; 710*349cc55cSDimitry Andric } 711*349cc55cSDimitry Andric CondStream << ") &&\n"; 712*349cc55cSDimitry Andric } 713*349cc55cSDimitry Andric 714*349cc55cSDimitry Andric // Start Source Inst operands validation. 715*349cc55cSDimitry Andric unsigned OpNo = 0; 716*349cc55cSDimitry Andric for (OpNo = 0; OpNo < Source.Operands.size(); ++OpNo) { 717*349cc55cSDimitry Andric if (SourceOperandMap[OpNo].TiedOpIdx != -1) { 718*349cc55cSDimitry Andric if (Source.Operands[OpNo].Rec->isSubClassOf("RegisterClass")) 719*349cc55cSDimitry Andric CondStream.indent(6) 720*349cc55cSDimitry Andric << "(MI.getOperand(" << OpNo << ").getReg() == MI.getOperand(" 721*349cc55cSDimitry Andric << SourceOperandMap[OpNo].TiedOpIdx << ").getReg()) &&\n"; 722*349cc55cSDimitry Andric else 723*349cc55cSDimitry Andric PrintFatalError("Unexpected tied operand types!\n"); 724*349cc55cSDimitry Andric } 725*349cc55cSDimitry Andric // Check for fixed immediates\registers in the source instruction. 726*349cc55cSDimitry Andric switch (SourceOperandMap[OpNo].Kind) { 727*349cc55cSDimitry Andric case OpData::Operand: 728*349cc55cSDimitry Andric // We don't need to do anything for source instruction operand checks. 729*349cc55cSDimitry Andric break; 730*349cc55cSDimitry Andric case OpData::Imm: 731*349cc55cSDimitry Andric CondStream.indent(6) 732*349cc55cSDimitry Andric << "(MI.getOperand(" << OpNo << ").isImm()) &&\n" 733*349cc55cSDimitry Andric << " (MI.getOperand(" << OpNo 734*349cc55cSDimitry Andric << ").getImm() == " << SourceOperandMap[OpNo].Data.Imm << ") &&\n"; 735*349cc55cSDimitry Andric break; 736*349cc55cSDimitry Andric case OpData::Reg: { 737*349cc55cSDimitry Andric Record *Reg = SourceOperandMap[OpNo].Data.Reg; 738*349cc55cSDimitry Andric CondStream.indent(6) 739*349cc55cSDimitry Andric << "(MI.getOperand(" << OpNo << ").getReg() == " << TargetName 740*349cc55cSDimitry Andric << "::" << Reg->getName() << ") &&\n"; 741*349cc55cSDimitry Andric break; 742*349cc55cSDimitry Andric } 743*349cc55cSDimitry Andric } 744*349cc55cSDimitry Andric } 745*349cc55cSDimitry Andric CodeStream.indent(6) << "// " << Dest.AsmString << "\n"; 746*349cc55cSDimitry Andric if (CompressOrUncompress) 747*349cc55cSDimitry Andric CodeStream.indent(6) << "OutInst.setOpcode(" << TargetName 748*349cc55cSDimitry Andric << "::" << Dest.TheDef->getName() << ");\n"; 749*349cc55cSDimitry Andric OpNo = 0; 750*349cc55cSDimitry Andric for (const auto &DestOperand : Dest.Operands) { 751*349cc55cSDimitry Andric CodeStream.indent(6) << "// Operand: " << DestOperand.Name << "\n"; 752*349cc55cSDimitry Andric switch (DestOperandMap[OpNo].Kind) { 753*349cc55cSDimitry Andric case OpData::Operand: { 754*349cc55cSDimitry Andric unsigned OpIdx = DestOperandMap[OpNo].Data.Operand; 755*349cc55cSDimitry Andric // Check that the operand in the Source instruction fits 756*349cc55cSDimitry Andric // the type for the Dest instruction. 757*349cc55cSDimitry Andric if (DestOperand.Rec->isSubClassOf("RegisterClass")) { 758*349cc55cSDimitry Andric NeedMRI = true; 759*349cc55cSDimitry Andric // This is a register operand. Check the register class. 760*349cc55cSDimitry Andric // Don't check register class if this is a tied operand, it was done 761*349cc55cSDimitry Andric // for the operand its tied to. 762*349cc55cSDimitry Andric if (DestOperand.getTiedRegister() == -1) 763*349cc55cSDimitry Andric CondStream.indent(6) << "(MRI.getRegClass(" << TargetName 764*349cc55cSDimitry Andric << "::" << DestOperand.Rec->getName() 765*349cc55cSDimitry Andric << "RegClassID).contains(MI.getOperand(" 766*349cc55cSDimitry Andric << OpIdx << ").getReg())) &&\n"; 767*349cc55cSDimitry Andric 768*349cc55cSDimitry Andric if (CompressOrUncompress) 769*349cc55cSDimitry Andric CodeStream.indent(6) 770*349cc55cSDimitry Andric << "OutInst.addOperand(MI.getOperand(" << OpIdx << "));\n"; 771*349cc55cSDimitry Andric } else { 772*349cc55cSDimitry Andric // Handling immediate operands. 773*349cc55cSDimitry Andric if (CompressOrUncompress) { 774*349cc55cSDimitry Andric unsigned Entry = 775*349cc55cSDimitry Andric getPredicates(MCOpPredicateMap, MCOpPredicates, DestOperand.Rec, 776*349cc55cSDimitry Andric "MCOperandPredicate"); 777*349cc55cSDimitry Andric CondStream.indent(6) 778*349cc55cSDimitry Andric << TargetName << "ValidateMCOperand(" 779*349cc55cSDimitry Andric << "MI.getOperand(" << OpIdx << "), STI, " << Entry << ") &&\n"; 780*349cc55cSDimitry Andric } else { 781*349cc55cSDimitry Andric unsigned Entry = 782*349cc55cSDimitry Andric getPredicates(ImmLeafPredicateMap, ImmLeafPredicates, 783*349cc55cSDimitry Andric DestOperand.Rec, "ImmediateCode"); 784*349cc55cSDimitry Andric CondStream.indent(6) 785*349cc55cSDimitry Andric << "MI.getOperand(" << OpIdx << ").isImm() &&\n"; 786*349cc55cSDimitry Andric CondStream.indent(6) << TargetName << "ValidateMachineOperand(" 787*349cc55cSDimitry Andric << "MI.getOperand(" << OpIdx 788*349cc55cSDimitry Andric << "), Subtarget, " << Entry << ") &&\n"; 789*349cc55cSDimitry Andric } 790*349cc55cSDimitry Andric if (CompressOrUncompress) 791*349cc55cSDimitry Andric CodeStream.indent(6) 792*349cc55cSDimitry Andric << "OutInst.addOperand(MI.getOperand(" << OpIdx << "));\n"; 793*349cc55cSDimitry Andric } 794*349cc55cSDimitry Andric break; 795*349cc55cSDimitry Andric } 796*349cc55cSDimitry Andric case OpData::Imm: { 797*349cc55cSDimitry Andric if (CompressOrUncompress) { 798*349cc55cSDimitry Andric unsigned Entry = getPredicates(MCOpPredicateMap, MCOpPredicates, 799*349cc55cSDimitry Andric DestOperand.Rec, "MCOperandPredicate"); 800*349cc55cSDimitry Andric CondStream.indent(6) 801*349cc55cSDimitry Andric << TargetName << "ValidateMCOperand(" 802*349cc55cSDimitry Andric << "MCOperand::createImm(" << DestOperandMap[OpNo].Data.Imm 803*349cc55cSDimitry Andric << "), STI, " << Entry << ") &&\n"; 804*349cc55cSDimitry Andric } else { 805*349cc55cSDimitry Andric unsigned Entry = getPredicates(ImmLeafPredicateMap, ImmLeafPredicates, 806*349cc55cSDimitry Andric DestOperand.Rec, "ImmediateCode"); 807*349cc55cSDimitry Andric CondStream.indent(6) 808*349cc55cSDimitry Andric << TargetName 809*349cc55cSDimitry Andric << "ValidateMachineOperand(MachineOperand::CreateImm(" 810*349cc55cSDimitry Andric << DestOperandMap[OpNo].Data.Imm << "), SubTarget, " << Entry 811*349cc55cSDimitry Andric << ") &&\n"; 812*349cc55cSDimitry Andric } 813*349cc55cSDimitry Andric if (CompressOrUncompress) 814*349cc55cSDimitry Andric CodeStream.indent(6) << "OutInst.addOperand(MCOperand::createImm(" 815*349cc55cSDimitry Andric << DestOperandMap[OpNo].Data.Imm << "));\n"; 816*349cc55cSDimitry Andric } break; 817*349cc55cSDimitry Andric case OpData::Reg: { 818*349cc55cSDimitry Andric if (CompressOrUncompress) { 819*349cc55cSDimitry Andric // Fixed register has been validated at pattern validation time. 820*349cc55cSDimitry Andric Record *Reg = DestOperandMap[OpNo].Data.Reg; 821*349cc55cSDimitry Andric CodeStream.indent(6) 822*349cc55cSDimitry Andric << "OutInst.addOperand(MCOperand::createReg(" << TargetName 823*349cc55cSDimitry Andric << "::" << Reg->getName() << "));\n"; 824*349cc55cSDimitry Andric } 825*349cc55cSDimitry Andric } break; 826*349cc55cSDimitry Andric } 827*349cc55cSDimitry Andric ++OpNo; 828*349cc55cSDimitry Andric } 829*349cc55cSDimitry Andric if (CompressOrUncompress) 830*349cc55cSDimitry Andric CodeStream.indent(6) << "OutInst.setLoc(MI.getLoc());\n"; 831*349cc55cSDimitry Andric mergeCondAndCode(CaseStream, CondStream.str(), CodeStream.str()); 832*349cc55cSDimitry Andric PrevOp = CurOp; 833*349cc55cSDimitry Andric } 834*349cc55cSDimitry Andric Func << CaseStream.str() << "\n"; 835*349cc55cSDimitry Andric // Close brace for the last case. 836*349cc55cSDimitry Andric Func.indent(4) << "} // case " << CurOp << "\n"; 837*349cc55cSDimitry Andric Func.indent(2) << "} // switch\n"; 838*349cc55cSDimitry Andric Func.indent(2) << "return false;\n}\n"; 839*349cc55cSDimitry Andric 840*349cc55cSDimitry Andric if (!MCOpPredicates.empty()) { 841*349cc55cSDimitry Andric o << "static bool " << TargetName 842*349cc55cSDimitry Andric << "ValidateMCOperand(const MCOperand &MCOp,\n" 843*349cc55cSDimitry Andric << " const MCSubtargetInfo &STI,\n" 844*349cc55cSDimitry Andric << " unsigned PredicateIndex) {\n" 845*349cc55cSDimitry Andric << " switch (PredicateIndex) {\n" 846*349cc55cSDimitry Andric << " default:\n" 847*349cc55cSDimitry Andric << " llvm_unreachable(\"Unknown MCOperandPredicate kind\");\n" 848*349cc55cSDimitry Andric << " break;\n"; 849*349cc55cSDimitry Andric 850*349cc55cSDimitry Andric printPredicates(MCOpPredicates, "MCOperandPredicate", o); 851*349cc55cSDimitry Andric 852*349cc55cSDimitry Andric o << " }\n" 853*349cc55cSDimitry Andric << "}\n\n"; 854*349cc55cSDimitry Andric } 855*349cc55cSDimitry Andric 856*349cc55cSDimitry Andric if (!ImmLeafPredicates.empty()) { 857*349cc55cSDimitry Andric o << "static bool " << TargetName 858*349cc55cSDimitry Andric << "ValidateMachineOperand(const MachineOperand &MO,\n" 859*349cc55cSDimitry Andric << " const " << TargetName << "Subtarget *Subtarget,\n" 860*349cc55cSDimitry Andric << " unsigned PredicateIndex) {\n" 861*349cc55cSDimitry Andric << " int64_t Imm = MO.getImm();\n" 862*349cc55cSDimitry Andric << " switch (PredicateIndex) {\n" 863*349cc55cSDimitry Andric << " default:\n" 864*349cc55cSDimitry Andric << " llvm_unreachable(\"Unknown ImmLeaf Predicate kind\");\n" 865*349cc55cSDimitry Andric << " break;\n"; 866*349cc55cSDimitry Andric 867*349cc55cSDimitry Andric printPredicates(ImmLeafPredicates, "ImmediateCode", o); 868*349cc55cSDimitry Andric 869*349cc55cSDimitry Andric o << " }\n" 870*349cc55cSDimitry Andric << "}\n\n"; 871*349cc55cSDimitry Andric } 872*349cc55cSDimitry Andric 873*349cc55cSDimitry Andric o << FuncH.str(); 874*349cc55cSDimitry Andric if (NeedMRI && EType == EmitterType::Compress) 875*349cc55cSDimitry Andric o.indent(2) << "const MCRegisterInfo &MRI = *Context.getRegisterInfo();\n"; 876*349cc55cSDimitry Andric o << Func.str(); 877*349cc55cSDimitry Andric 878*349cc55cSDimitry Andric if (EType == EmitterType::Compress) 879*349cc55cSDimitry Andric o << "\n#endif //GEN_COMPRESS_INSTR\n"; 880*349cc55cSDimitry Andric else if (EType == EmitterType::Uncompress) 881*349cc55cSDimitry Andric o << "\n#endif //GEN_UNCOMPRESS_INSTR\n\n"; 882*349cc55cSDimitry Andric else if (EType == EmitterType::CheckCompress) 883*349cc55cSDimitry Andric o << "\n#endif //GEN_CHECK_COMPRESS_INSTR\n\n"; 884*349cc55cSDimitry Andric } 885*349cc55cSDimitry Andric 886*349cc55cSDimitry Andric void CompressInstEmitter::run(raw_ostream &o) { 887*349cc55cSDimitry Andric std::vector<Record *> Insts = Records.getAllDerivedDefinitions("CompressPat"); 888*349cc55cSDimitry Andric 889*349cc55cSDimitry Andric // Process the CompressPat definitions, validating them as we do so. 890*349cc55cSDimitry Andric for (unsigned i = 0, e = Insts.size(); i != e; ++i) 891*349cc55cSDimitry Andric evaluateCompressPat(Insts[i]); 892*349cc55cSDimitry Andric 893*349cc55cSDimitry Andric // Emit file header. 894*349cc55cSDimitry Andric emitSourceFileHeader("Compress instruction Source Fragment", o); 895*349cc55cSDimitry Andric // Generate compressInst() function. 896*349cc55cSDimitry Andric emitCompressInstEmitter(o, EmitterType::Compress); 897*349cc55cSDimitry Andric // Generate uncompressInst() function. 898*349cc55cSDimitry Andric emitCompressInstEmitter(o, EmitterType::Uncompress); 899*349cc55cSDimitry Andric // Generate isCompressibleInst() function. 900*349cc55cSDimitry Andric emitCompressInstEmitter(o, EmitterType::CheckCompress); 901*349cc55cSDimitry Andric } 902*349cc55cSDimitry Andric 903*349cc55cSDimitry Andric namespace llvm { 904*349cc55cSDimitry Andric 905*349cc55cSDimitry Andric void EmitCompressInst(RecordKeeper &RK, raw_ostream &OS) { 906*349cc55cSDimitry Andric CompressInstEmitter(RK).run(OS); 907*349cc55cSDimitry Andric } 908*349cc55cSDimitry Andric 909*349cc55cSDimitry Andric } // namespace llvm 910