1*0fca6ea1SDimitry Andric //===- CodeGenTarget.cpp - CodeGen Target Class Wrapper -------------------===// 2*0fca6ea1SDimitry Andric // 3*0fca6ea1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0fca6ea1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0fca6ea1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0fca6ea1SDimitry Andric // 7*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 8*0fca6ea1SDimitry Andric // 9*0fca6ea1SDimitry Andric // This class wraps target description classes used by the various code 10*0fca6ea1SDimitry Andric // generation TableGen backends. This makes it easier to access the data and 11*0fca6ea1SDimitry Andric // provides a single place that needs to check it for validity. All of these 12*0fca6ea1SDimitry Andric // classes abort on error conditions. 13*0fca6ea1SDimitry Andric // 14*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 15*0fca6ea1SDimitry Andric 16*0fca6ea1SDimitry Andric #include "CodeGenTarget.h" 17*0fca6ea1SDimitry Andric #include "CodeGenInstruction.h" 18*0fca6ea1SDimitry Andric #include "CodeGenRegisters.h" 19*0fca6ea1SDimitry Andric #include "CodeGenSchedule.h" 20*0fca6ea1SDimitry Andric #include "llvm/ADT/STLExtras.h" 21*0fca6ea1SDimitry Andric #include "llvm/ADT/Twine.h" 22*0fca6ea1SDimitry Andric #include "llvm/Support/CommandLine.h" 23*0fca6ea1SDimitry Andric #include "llvm/Support/ErrorHandling.h" 24*0fca6ea1SDimitry Andric #include "llvm/TableGen/Error.h" 25*0fca6ea1SDimitry Andric #include "llvm/TableGen/Record.h" 26*0fca6ea1SDimitry Andric #include <algorithm> 27*0fca6ea1SDimitry Andric #include <iterator> 28*0fca6ea1SDimitry Andric #include <tuple> 29*0fca6ea1SDimitry Andric using namespace llvm; 30*0fca6ea1SDimitry Andric 31*0fca6ea1SDimitry Andric cl::OptionCategory AsmParserCat("Options for -gen-asm-parser"); 32*0fca6ea1SDimitry Andric cl::OptionCategory AsmWriterCat("Options for -gen-asm-writer"); 33*0fca6ea1SDimitry Andric 34*0fca6ea1SDimitry Andric static cl::opt<unsigned> 35*0fca6ea1SDimitry Andric AsmParserNum("asmparsernum", cl::init(0), 36*0fca6ea1SDimitry Andric cl::desc("Make -gen-asm-parser emit assembly parser #N"), 37*0fca6ea1SDimitry Andric cl::cat(AsmParserCat)); 38*0fca6ea1SDimitry Andric 39*0fca6ea1SDimitry Andric static cl::opt<unsigned> 40*0fca6ea1SDimitry Andric AsmWriterNum("asmwriternum", cl::init(0), 41*0fca6ea1SDimitry Andric cl::desc("Make -gen-asm-writer emit assembly writer #N"), 42*0fca6ea1SDimitry Andric cl::cat(AsmWriterCat)); 43*0fca6ea1SDimitry Andric 44*0fca6ea1SDimitry Andric /// getValueType - Return the MVT::SimpleValueType that the specified TableGen 45*0fca6ea1SDimitry Andric /// record corresponds to. 46*0fca6ea1SDimitry Andric MVT::SimpleValueType llvm::getValueType(const Record *Rec) { 47*0fca6ea1SDimitry Andric return (MVT::SimpleValueType)Rec->getValueAsInt("Value"); 48*0fca6ea1SDimitry Andric } 49*0fca6ea1SDimitry Andric 50*0fca6ea1SDimitry Andric StringRef llvm::getName(MVT::SimpleValueType T) { 51*0fca6ea1SDimitry Andric switch (T) { 52*0fca6ea1SDimitry Andric case MVT::Other: 53*0fca6ea1SDimitry Andric return "UNKNOWN"; 54*0fca6ea1SDimitry Andric case MVT::iPTR: 55*0fca6ea1SDimitry Andric return "TLI.getPointerTy()"; 56*0fca6ea1SDimitry Andric case MVT::iPTRAny: 57*0fca6ea1SDimitry Andric return "TLI.getPointerTy()"; 58*0fca6ea1SDimitry Andric default: 59*0fca6ea1SDimitry Andric return getEnumName(T); 60*0fca6ea1SDimitry Andric } 61*0fca6ea1SDimitry Andric } 62*0fca6ea1SDimitry Andric 63*0fca6ea1SDimitry Andric StringRef llvm::getEnumName(MVT::SimpleValueType T) { 64*0fca6ea1SDimitry Andric // clang-format off 65*0fca6ea1SDimitry Andric switch (T) { 66*0fca6ea1SDimitry Andric #define GET_VT_ATTR(Ty, N, Sz, Any, Int, FP, Vec, Sc, NElem, EltTy) \ 67*0fca6ea1SDimitry Andric case MVT::Ty: return "MVT::" # Ty; 68*0fca6ea1SDimitry Andric #include "llvm/CodeGen/GenVT.inc" 69*0fca6ea1SDimitry Andric default: llvm_unreachable("ILLEGAL VALUE TYPE!"); 70*0fca6ea1SDimitry Andric } 71*0fca6ea1SDimitry Andric // clang-format on 72*0fca6ea1SDimitry Andric } 73*0fca6ea1SDimitry Andric 74*0fca6ea1SDimitry Andric /// getQualifiedName - Return the name of the specified record, with a 75*0fca6ea1SDimitry Andric /// namespace qualifier if the record contains one. 76*0fca6ea1SDimitry Andric /// 77*0fca6ea1SDimitry Andric std::string llvm::getQualifiedName(const Record *R) { 78*0fca6ea1SDimitry Andric std::string Namespace; 79*0fca6ea1SDimitry Andric if (R->getValue("Namespace")) 80*0fca6ea1SDimitry Andric Namespace = std::string(R->getValueAsString("Namespace")); 81*0fca6ea1SDimitry Andric if (Namespace.empty()) 82*0fca6ea1SDimitry Andric return std::string(R->getName()); 83*0fca6ea1SDimitry Andric return Namespace + "::" + R->getName().str(); 84*0fca6ea1SDimitry Andric } 85*0fca6ea1SDimitry Andric 86*0fca6ea1SDimitry Andric /// getTarget - Return the current instance of the Target class. 87*0fca6ea1SDimitry Andric /// 88*0fca6ea1SDimitry Andric CodeGenTarget::CodeGenTarget(RecordKeeper &records) 89*0fca6ea1SDimitry Andric : Records(records), CGH(records) { 90*0fca6ea1SDimitry Andric std::vector<Record *> Targets = Records.getAllDerivedDefinitions("Target"); 91*0fca6ea1SDimitry Andric if (Targets.size() == 0) 92*0fca6ea1SDimitry Andric PrintFatalError("No 'Target' subclasses defined!"); 93*0fca6ea1SDimitry Andric if (Targets.size() != 1) 94*0fca6ea1SDimitry Andric PrintFatalError("Multiple subclasses of Target defined!"); 95*0fca6ea1SDimitry Andric TargetRec = Targets[0]; 96*0fca6ea1SDimitry Andric MacroFusions = Records.getAllDerivedDefinitions("Fusion"); 97*0fca6ea1SDimitry Andric } 98*0fca6ea1SDimitry Andric 99*0fca6ea1SDimitry Andric CodeGenTarget::~CodeGenTarget() {} 100*0fca6ea1SDimitry Andric 101*0fca6ea1SDimitry Andric StringRef CodeGenTarget::getName() const { return TargetRec->getName(); } 102*0fca6ea1SDimitry Andric 103*0fca6ea1SDimitry Andric /// getInstNamespace - Find and return the target machine's instruction 104*0fca6ea1SDimitry Andric /// namespace. The namespace is cached because it is requested multiple times. 105*0fca6ea1SDimitry Andric StringRef CodeGenTarget::getInstNamespace() const { 106*0fca6ea1SDimitry Andric if (InstNamespace.empty()) { 107*0fca6ea1SDimitry Andric for (const CodeGenInstruction *Inst : getInstructionsByEnumValue()) { 108*0fca6ea1SDimitry Andric // We are not interested in the "TargetOpcode" namespace. 109*0fca6ea1SDimitry Andric if (Inst->Namespace != "TargetOpcode") { 110*0fca6ea1SDimitry Andric InstNamespace = Inst->Namespace; 111*0fca6ea1SDimitry Andric break; 112*0fca6ea1SDimitry Andric } 113*0fca6ea1SDimitry Andric } 114*0fca6ea1SDimitry Andric } 115*0fca6ea1SDimitry Andric 116*0fca6ea1SDimitry Andric return InstNamespace; 117*0fca6ea1SDimitry Andric } 118*0fca6ea1SDimitry Andric 119*0fca6ea1SDimitry Andric StringRef CodeGenTarget::getRegNamespace() const { 120*0fca6ea1SDimitry Andric auto &RegClasses = RegBank->getRegClasses(); 121*0fca6ea1SDimitry Andric return RegClasses.size() > 0 ? RegClasses.front().Namespace : ""; 122*0fca6ea1SDimitry Andric } 123*0fca6ea1SDimitry Andric 124*0fca6ea1SDimitry Andric Record *CodeGenTarget::getInstructionSet() const { 125*0fca6ea1SDimitry Andric return TargetRec->getValueAsDef("InstructionSet"); 126*0fca6ea1SDimitry Andric } 127*0fca6ea1SDimitry Andric 128*0fca6ea1SDimitry Andric bool CodeGenTarget::getAllowRegisterRenaming() const { 129*0fca6ea1SDimitry Andric return TargetRec->getValueAsInt("AllowRegisterRenaming"); 130*0fca6ea1SDimitry Andric } 131*0fca6ea1SDimitry Andric 132*0fca6ea1SDimitry Andric /// getAsmParser - Return the AssemblyParser definition for this target. 133*0fca6ea1SDimitry Andric /// 134*0fca6ea1SDimitry Andric Record *CodeGenTarget::getAsmParser() const { 135*0fca6ea1SDimitry Andric std::vector<Record *> LI = TargetRec->getValueAsListOfDefs("AssemblyParsers"); 136*0fca6ea1SDimitry Andric if (AsmParserNum >= LI.size()) 137*0fca6ea1SDimitry Andric PrintFatalError("Target does not have an AsmParser #" + 138*0fca6ea1SDimitry Andric Twine(AsmParserNum) + "!"); 139*0fca6ea1SDimitry Andric return LI[AsmParserNum]; 140*0fca6ea1SDimitry Andric } 141*0fca6ea1SDimitry Andric 142*0fca6ea1SDimitry Andric /// getAsmParserVariant - Return the AssemblyParserVariant definition for 143*0fca6ea1SDimitry Andric /// this target. 144*0fca6ea1SDimitry Andric /// 145*0fca6ea1SDimitry Andric Record *CodeGenTarget::getAsmParserVariant(unsigned i) const { 146*0fca6ea1SDimitry Andric std::vector<Record *> LI = 147*0fca6ea1SDimitry Andric TargetRec->getValueAsListOfDefs("AssemblyParserVariants"); 148*0fca6ea1SDimitry Andric if (i >= LI.size()) 149*0fca6ea1SDimitry Andric PrintFatalError("Target does not have an AsmParserVariant #" + Twine(i) + 150*0fca6ea1SDimitry Andric "!"); 151*0fca6ea1SDimitry Andric return LI[i]; 152*0fca6ea1SDimitry Andric } 153*0fca6ea1SDimitry Andric 154*0fca6ea1SDimitry Andric /// getAsmParserVariantCount - Return the AssemblyParserVariant definition 155*0fca6ea1SDimitry Andric /// available for this target. 156*0fca6ea1SDimitry Andric /// 157*0fca6ea1SDimitry Andric unsigned CodeGenTarget::getAsmParserVariantCount() const { 158*0fca6ea1SDimitry Andric std::vector<Record *> LI = 159*0fca6ea1SDimitry Andric TargetRec->getValueAsListOfDefs("AssemblyParserVariants"); 160*0fca6ea1SDimitry Andric return LI.size(); 161*0fca6ea1SDimitry Andric } 162*0fca6ea1SDimitry Andric 163*0fca6ea1SDimitry Andric /// getAsmWriter - Return the AssemblyWriter definition for this target. 164*0fca6ea1SDimitry Andric /// 165*0fca6ea1SDimitry Andric Record *CodeGenTarget::getAsmWriter() const { 166*0fca6ea1SDimitry Andric std::vector<Record *> LI = TargetRec->getValueAsListOfDefs("AssemblyWriters"); 167*0fca6ea1SDimitry Andric if (AsmWriterNum >= LI.size()) 168*0fca6ea1SDimitry Andric PrintFatalError("Target does not have an AsmWriter #" + 169*0fca6ea1SDimitry Andric Twine(AsmWriterNum) + "!"); 170*0fca6ea1SDimitry Andric return LI[AsmWriterNum]; 171*0fca6ea1SDimitry Andric } 172*0fca6ea1SDimitry Andric 173*0fca6ea1SDimitry Andric CodeGenRegBank &CodeGenTarget::getRegBank() const { 174*0fca6ea1SDimitry Andric if (!RegBank) 175*0fca6ea1SDimitry Andric RegBank = std::make_unique<CodeGenRegBank>(Records, getHwModes()); 176*0fca6ea1SDimitry Andric return *RegBank; 177*0fca6ea1SDimitry Andric } 178*0fca6ea1SDimitry Andric 179*0fca6ea1SDimitry Andric std::optional<CodeGenRegisterClass *> CodeGenTarget::getSuperRegForSubReg( 180*0fca6ea1SDimitry Andric const ValueTypeByHwMode &ValueTy, CodeGenRegBank &RegBank, 181*0fca6ea1SDimitry Andric const CodeGenSubRegIndex *SubIdx, bool MustBeAllocatable) const { 182*0fca6ea1SDimitry Andric std::vector<CodeGenRegisterClass *> Candidates; 183*0fca6ea1SDimitry Andric auto &RegClasses = RegBank.getRegClasses(); 184*0fca6ea1SDimitry Andric 185*0fca6ea1SDimitry Andric // Try to find a register class which supports ValueTy, and also contains 186*0fca6ea1SDimitry Andric // SubIdx. 187*0fca6ea1SDimitry Andric for (CodeGenRegisterClass &RC : RegClasses) { 188*0fca6ea1SDimitry Andric // Is there a subclass of this class which contains this subregister index? 189*0fca6ea1SDimitry Andric CodeGenRegisterClass *SubClassWithSubReg = RC.getSubClassWithSubReg(SubIdx); 190*0fca6ea1SDimitry Andric if (!SubClassWithSubReg) 191*0fca6ea1SDimitry Andric continue; 192*0fca6ea1SDimitry Andric 193*0fca6ea1SDimitry Andric // We have a class. Check if it supports this value type. 194*0fca6ea1SDimitry Andric if (!llvm::is_contained(SubClassWithSubReg->VTs, ValueTy)) 195*0fca6ea1SDimitry Andric continue; 196*0fca6ea1SDimitry Andric 197*0fca6ea1SDimitry Andric // If necessary, check that it is allocatable. 198*0fca6ea1SDimitry Andric if (MustBeAllocatable && !SubClassWithSubReg->Allocatable) 199*0fca6ea1SDimitry Andric continue; 200*0fca6ea1SDimitry Andric 201*0fca6ea1SDimitry Andric // We have a register class which supports both the value type and 202*0fca6ea1SDimitry Andric // subregister index. Remember it. 203*0fca6ea1SDimitry Andric Candidates.push_back(SubClassWithSubReg); 204*0fca6ea1SDimitry Andric } 205*0fca6ea1SDimitry Andric 206*0fca6ea1SDimitry Andric // If we didn't find anything, we're done. 207*0fca6ea1SDimitry Andric if (Candidates.empty()) 208*0fca6ea1SDimitry Andric return std::nullopt; 209*0fca6ea1SDimitry Andric 210*0fca6ea1SDimitry Andric // Find and return the largest of our candidate classes. 211*0fca6ea1SDimitry Andric llvm::stable_sort(Candidates, [&](const CodeGenRegisterClass *A, 212*0fca6ea1SDimitry Andric const CodeGenRegisterClass *B) { 213*0fca6ea1SDimitry Andric if (A->getMembers().size() > B->getMembers().size()) 214*0fca6ea1SDimitry Andric return true; 215*0fca6ea1SDimitry Andric 216*0fca6ea1SDimitry Andric if (A->getMembers().size() < B->getMembers().size()) 217*0fca6ea1SDimitry Andric return false; 218*0fca6ea1SDimitry Andric 219*0fca6ea1SDimitry Andric // Order by name as a tie-breaker. 220*0fca6ea1SDimitry Andric return StringRef(A->getName()) < B->getName(); 221*0fca6ea1SDimitry Andric }); 222*0fca6ea1SDimitry Andric 223*0fca6ea1SDimitry Andric return Candidates[0]; 224*0fca6ea1SDimitry Andric } 225*0fca6ea1SDimitry Andric 226*0fca6ea1SDimitry Andric void CodeGenTarget::ReadRegAltNameIndices() const { 227*0fca6ea1SDimitry Andric RegAltNameIndices = Records.getAllDerivedDefinitions("RegAltNameIndex"); 228*0fca6ea1SDimitry Andric llvm::sort(RegAltNameIndices, LessRecord()); 229*0fca6ea1SDimitry Andric } 230*0fca6ea1SDimitry Andric 231*0fca6ea1SDimitry Andric /// getRegisterByName - If there is a register with the specific AsmName, 232*0fca6ea1SDimitry Andric /// return it. 233*0fca6ea1SDimitry Andric const CodeGenRegister *CodeGenTarget::getRegisterByName(StringRef Name) const { 234*0fca6ea1SDimitry Andric return getRegBank().getRegistersByName().lookup(Name); 235*0fca6ea1SDimitry Andric } 236*0fca6ea1SDimitry Andric 237*0fca6ea1SDimitry Andric const CodeGenRegisterClass &CodeGenTarget::getRegisterClass(Record *R) const { 238*0fca6ea1SDimitry Andric return *getRegBank().getRegClass(R); 239*0fca6ea1SDimitry Andric } 240*0fca6ea1SDimitry Andric 241*0fca6ea1SDimitry Andric std::vector<ValueTypeByHwMode> CodeGenTarget::getRegisterVTs(Record *R) const { 242*0fca6ea1SDimitry Andric const CodeGenRegister *Reg = getRegBank().getReg(R); 243*0fca6ea1SDimitry Andric std::vector<ValueTypeByHwMode> Result; 244*0fca6ea1SDimitry Andric for (const auto &RC : getRegBank().getRegClasses()) { 245*0fca6ea1SDimitry Andric if (RC.contains(Reg)) { 246*0fca6ea1SDimitry Andric ArrayRef<ValueTypeByHwMode> InVTs = RC.getValueTypes(); 247*0fca6ea1SDimitry Andric llvm::append_range(Result, InVTs); 248*0fca6ea1SDimitry Andric } 249*0fca6ea1SDimitry Andric } 250*0fca6ea1SDimitry Andric 251*0fca6ea1SDimitry Andric // Remove duplicates. 252*0fca6ea1SDimitry Andric llvm::sort(Result); 253*0fca6ea1SDimitry Andric Result.erase(llvm::unique(Result), Result.end()); 254*0fca6ea1SDimitry Andric return Result; 255*0fca6ea1SDimitry Andric } 256*0fca6ea1SDimitry Andric 257*0fca6ea1SDimitry Andric void CodeGenTarget::ReadLegalValueTypes() const { 258*0fca6ea1SDimitry Andric for (const auto &RC : getRegBank().getRegClasses()) 259*0fca6ea1SDimitry Andric llvm::append_range(LegalValueTypes, RC.VTs); 260*0fca6ea1SDimitry Andric 261*0fca6ea1SDimitry Andric // Remove duplicates. 262*0fca6ea1SDimitry Andric llvm::sort(LegalValueTypes); 263*0fca6ea1SDimitry Andric LegalValueTypes.erase(llvm::unique(LegalValueTypes), LegalValueTypes.end()); 264*0fca6ea1SDimitry Andric } 265*0fca6ea1SDimitry Andric 266*0fca6ea1SDimitry Andric CodeGenSchedModels &CodeGenTarget::getSchedModels() const { 267*0fca6ea1SDimitry Andric if (!SchedModels) 268*0fca6ea1SDimitry Andric SchedModels = std::make_unique<CodeGenSchedModels>(Records, *this); 269*0fca6ea1SDimitry Andric return *SchedModels; 270*0fca6ea1SDimitry Andric } 271*0fca6ea1SDimitry Andric 272*0fca6ea1SDimitry Andric void CodeGenTarget::ReadInstructions() const { 273*0fca6ea1SDimitry Andric std::vector<Record *> Insts = Records.getAllDerivedDefinitions("Instruction"); 274*0fca6ea1SDimitry Andric if (Insts.size() <= 2) 275*0fca6ea1SDimitry Andric PrintFatalError("No 'Instruction' subclasses defined!"); 276*0fca6ea1SDimitry Andric 277*0fca6ea1SDimitry Andric // Parse the instructions defined in the .td file. 278*0fca6ea1SDimitry Andric for (Record *R : Insts) { 279*0fca6ea1SDimitry Andric Instructions[R] = std::make_unique<CodeGenInstruction>(R); 280*0fca6ea1SDimitry Andric if (Instructions[R]->isVariableLengthEncoding()) 281*0fca6ea1SDimitry Andric HasVariableLengthEncodings = true; 282*0fca6ea1SDimitry Andric } 283*0fca6ea1SDimitry Andric } 284*0fca6ea1SDimitry Andric 285*0fca6ea1SDimitry Andric static const CodeGenInstruction *GetInstByName( 286*0fca6ea1SDimitry Andric const char *Name, 287*0fca6ea1SDimitry Andric const DenseMap<const Record *, std::unique_ptr<CodeGenInstruction>> &Insts, 288*0fca6ea1SDimitry Andric RecordKeeper &Records) { 289*0fca6ea1SDimitry Andric const Record *Rec = Records.getDef(Name); 290*0fca6ea1SDimitry Andric 291*0fca6ea1SDimitry Andric const auto I = Insts.find(Rec); 292*0fca6ea1SDimitry Andric if (!Rec || I == Insts.end()) 293*0fca6ea1SDimitry Andric PrintFatalError(Twine("Could not find '") + Name + "' instruction!"); 294*0fca6ea1SDimitry Andric return I->second.get(); 295*0fca6ea1SDimitry Andric } 296*0fca6ea1SDimitry Andric 297*0fca6ea1SDimitry Andric static const char *FixedInstrs[] = { 298*0fca6ea1SDimitry Andric #define HANDLE_TARGET_OPCODE(OPC) #OPC, 299*0fca6ea1SDimitry Andric #include "llvm/Support/TargetOpcodes.def" 300*0fca6ea1SDimitry Andric nullptr}; 301*0fca6ea1SDimitry Andric 302*0fca6ea1SDimitry Andric unsigned CodeGenTarget::getNumFixedInstructions() { 303*0fca6ea1SDimitry Andric return std::size(FixedInstrs) - 1; 304*0fca6ea1SDimitry Andric } 305*0fca6ea1SDimitry Andric 306*0fca6ea1SDimitry Andric /// Return all of the instructions defined by the target, ordered by 307*0fca6ea1SDimitry Andric /// their enum value. 308*0fca6ea1SDimitry Andric void CodeGenTarget::ComputeInstrsByEnum() const { 309*0fca6ea1SDimitry Andric const auto &Insts = getInstructions(); 310*0fca6ea1SDimitry Andric for (const char *const *p = FixedInstrs; *p; ++p) { 311*0fca6ea1SDimitry Andric const CodeGenInstruction *Instr = GetInstByName(*p, Insts, Records); 312*0fca6ea1SDimitry Andric assert(Instr && "Missing target independent instruction"); 313*0fca6ea1SDimitry Andric assert(Instr->Namespace == "TargetOpcode" && "Bad namespace"); 314*0fca6ea1SDimitry Andric InstrsByEnum.push_back(Instr); 315*0fca6ea1SDimitry Andric } 316*0fca6ea1SDimitry Andric unsigned EndOfPredefines = InstrsByEnum.size(); 317*0fca6ea1SDimitry Andric assert(EndOfPredefines == getNumFixedInstructions() && 318*0fca6ea1SDimitry Andric "Missing generic opcode"); 319*0fca6ea1SDimitry Andric 320*0fca6ea1SDimitry Andric for (const auto &I : Insts) { 321*0fca6ea1SDimitry Andric const CodeGenInstruction *CGI = I.second.get(); 322*0fca6ea1SDimitry Andric if (CGI->Namespace != "TargetOpcode") { 323*0fca6ea1SDimitry Andric InstrsByEnum.push_back(CGI); 324*0fca6ea1SDimitry Andric if (CGI->TheDef->getValueAsBit("isPseudo")) 325*0fca6ea1SDimitry Andric ++NumPseudoInstructions; 326*0fca6ea1SDimitry Andric } 327*0fca6ea1SDimitry Andric } 328*0fca6ea1SDimitry Andric 329*0fca6ea1SDimitry Andric assert(InstrsByEnum.size() == Insts.size() && "Missing predefined instr"); 330*0fca6ea1SDimitry Andric 331*0fca6ea1SDimitry Andric // All of the instructions are now in random order based on the map iteration. 332*0fca6ea1SDimitry Andric llvm::sort( 333*0fca6ea1SDimitry Andric InstrsByEnum.begin() + EndOfPredefines, InstrsByEnum.end(), 334*0fca6ea1SDimitry Andric [](const CodeGenInstruction *Rec1, const CodeGenInstruction *Rec2) { 335*0fca6ea1SDimitry Andric const auto &D1 = *Rec1->TheDef; 336*0fca6ea1SDimitry Andric const auto &D2 = *Rec2->TheDef; 337*0fca6ea1SDimitry Andric return std::tuple(!D1.getValueAsBit("isPseudo"), D1.getName()) < 338*0fca6ea1SDimitry Andric std::tuple(!D2.getValueAsBit("isPseudo"), D2.getName()); 339*0fca6ea1SDimitry Andric }); 340*0fca6ea1SDimitry Andric 341*0fca6ea1SDimitry Andric // Assign an enum value to each instruction according to the sorted order. 342*0fca6ea1SDimitry Andric unsigned Num = 0; 343*0fca6ea1SDimitry Andric for (const CodeGenInstruction *Inst : InstrsByEnum) 344*0fca6ea1SDimitry Andric Inst->EnumVal = Num++; 345*0fca6ea1SDimitry Andric } 346*0fca6ea1SDimitry Andric 347*0fca6ea1SDimitry Andric /// isLittleEndianEncoding - Return whether this target encodes its instruction 348*0fca6ea1SDimitry Andric /// in little-endian format, i.e. bits laid out in the order [0..n] 349*0fca6ea1SDimitry Andric /// 350*0fca6ea1SDimitry Andric bool CodeGenTarget::isLittleEndianEncoding() const { 351*0fca6ea1SDimitry Andric return getInstructionSet()->getValueAsBit("isLittleEndianEncoding"); 352*0fca6ea1SDimitry Andric } 353*0fca6ea1SDimitry Andric 354*0fca6ea1SDimitry Andric /// reverseBitsForLittleEndianEncoding - For little-endian instruction bit 355*0fca6ea1SDimitry Andric /// encodings, reverse the bit order of all instructions. 356*0fca6ea1SDimitry Andric void CodeGenTarget::reverseBitsForLittleEndianEncoding() { 357*0fca6ea1SDimitry Andric if (!isLittleEndianEncoding()) 358*0fca6ea1SDimitry Andric return; 359*0fca6ea1SDimitry Andric 360*0fca6ea1SDimitry Andric std::vector<Record *> Insts = 361*0fca6ea1SDimitry Andric Records.getAllDerivedDefinitions("InstructionEncoding"); 362*0fca6ea1SDimitry Andric for (Record *R : Insts) { 363*0fca6ea1SDimitry Andric if (R->getValueAsString("Namespace") == "TargetOpcode" || 364*0fca6ea1SDimitry Andric R->getValueAsBit("isPseudo")) 365*0fca6ea1SDimitry Andric continue; 366*0fca6ea1SDimitry Andric 367*0fca6ea1SDimitry Andric BitsInit *BI = R->getValueAsBitsInit("Inst"); 368*0fca6ea1SDimitry Andric 369*0fca6ea1SDimitry Andric unsigned numBits = BI->getNumBits(); 370*0fca6ea1SDimitry Andric 371*0fca6ea1SDimitry Andric SmallVector<Init *, 16> NewBits(numBits); 372*0fca6ea1SDimitry Andric 373*0fca6ea1SDimitry Andric for (unsigned bit = 0, end = numBits / 2; bit != end; ++bit) { 374*0fca6ea1SDimitry Andric unsigned bitSwapIdx = numBits - bit - 1; 375*0fca6ea1SDimitry Andric Init *OrigBit = BI->getBit(bit); 376*0fca6ea1SDimitry Andric Init *BitSwap = BI->getBit(bitSwapIdx); 377*0fca6ea1SDimitry Andric NewBits[bit] = BitSwap; 378*0fca6ea1SDimitry Andric NewBits[bitSwapIdx] = OrigBit; 379*0fca6ea1SDimitry Andric } 380*0fca6ea1SDimitry Andric if (numBits % 2) { 381*0fca6ea1SDimitry Andric unsigned middle = (numBits + 1) / 2; 382*0fca6ea1SDimitry Andric NewBits[middle] = BI->getBit(middle); 383*0fca6ea1SDimitry Andric } 384*0fca6ea1SDimitry Andric 385*0fca6ea1SDimitry Andric BitsInit *NewBI = BitsInit::get(Records, NewBits); 386*0fca6ea1SDimitry Andric 387*0fca6ea1SDimitry Andric // Update the bits in reversed order so that emitInstrOpBits will get the 388*0fca6ea1SDimitry Andric // correct endianness. 389*0fca6ea1SDimitry Andric R->getValue("Inst")->setValue(NewBI); 390*0fca6ea1SDimitry Andric } 391*0fca6ea1SDimitry Andric } 392*0fca6ea1SDimitry Andric 393*0fca6ea1SDimitry Andric /// guessInstructionProperties - Return true if it's OK to guess instruction 394*0fca6ea1SDimitry Andric /// properties instead of raising an error. 395*0fca6ea1SDimitry Andric /// 396*0fca6ea1SDimitry Andric /// This is configurable as a temporary migration aid. It will eventually be 397*0fca6ea1SDimitry Andric /// permanently false. 398*0fca6ea1SDimitry Andric bool CodeGenTarget::guessInstructionProperties() const { 399*0fca6ea1SDimitry Andric return getInstructionSet()->getValueAsBit("guessInstructionProperties"); 400*0fca6ea1SDimitry Andric } 401*0fca6ea1SDimitry Andric 402*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 403*0fca6ea1SDimitry Andric // ComplexPattern implementation 404*0fca6ea1SDimitry Andric // 405*0fca6ea1SDimitry Andric ComplexPattern::ComplexPattern(Record *R) { 406*0fca6ea1SDimitry Andric Ty = R->getValueAsDef("Ty"); 407*0fca6ea1SDimitry Andric NumOperands = R->getValueAsInt("NumOperands"); 408*0fca6ea1SDimitry Andric SelectFunc = std::string(R->getValueAsString("SelectFunc")); 409*0fca6ea1SDimitry Andric RootNodes = R->getValueAsListOfDefs("RootNodes"); 410*0fca6ea1SDimitry Andric 411*0fca6ea1SDimitry Andric // FIXME: This is a hack to statically increase the priority of patterns which 412*0fca6ea1SDimitry Andric // maps a sub-dag to a complex pattern. e.g. favors LEA over ADD. To get best 413*0fca6ea1SDimitry Andric // possible pattern match we'll need to dynamically calculate the complexity 414*0fca6ea1SDimitry Andric // of all patterns a dag can potentially map to. 415*0fca6ea1SDimitry Andric int64_t RawComplexity = R->getValueAsInt("Complexity"); 416*0fca6ea1SDimitry Andric if (RawComplexity == -1) 417*0fca6ea1SDimitry Andric Complexity = NumOperands * 3; 418*0fca6ea1SDimitry Andric else 419*0fca6ea1SDimitry Andric Complexity = RawComplexity; 420*0fca6ea1SDimitry Andric 421*0fca6ea1SDimitry Andric // FIXME: Why is this different from parseSDPatternOperatorProperties? 422*0fca6ea1SDimitry Andric // Parse the properties. 423*0fca6ea1SDimitry Andric Properties = 0; 424*0fca6ea1SDimitry Andric std::vector<Record *> PropList = R->getValueAsListOfDefs("Properties"); 425*0fca6ea1SDimitry Andric for (unsigned i = 0, e = PropList.size(); i != e; ++i) 426*0fca6ea1SDimitry Andric if (PropList[i]->getName() == "SDNPHasChain") { 427*0fca6ea1SDimitry Andric Properties |= 1 << SDNPHasChain; 428*0fca6ea1SDimitry Andric } else if (PropList[i]->getName() == "SDNPOptInGlue") { 429*0fca6ea1SDimitry Andric Properties |= 1 << SDNPOptInGlue; 430*0fca6ea1SDimitry Andric } else if (PropList[i]->getName() == "SDNPMayStore") { 431*0fca6ea1SDimitry Andric Properties |= 1 << SDNPMayStore; 432*0fca6ea1SDimitry Andric } else if (PropList[i]->getName() == "SDNPMayLoad") { 433*0fca6ea1SDimitry Andric Properties |= 1 << SDNPMayLoad; 434*0fca6ea1SDimitry Andric } else if (PropList[i]->getName() == "SDNPSideEffect") { 435*0fca6ea1SDimitry Andric Properties |= 1 << SDNPSideEffect; 436*0fca6ea1SDimitry Andric } else if (PropList[i]->getName() == "SDNPMemOperand") { 437*0fca6ea1SDimitry Andric Properties |= 1 << SDNPMemOperand; 438*0fca6ea1SDimitry Andric } else if (PropList[i]->getName() == "SDNPVariadic") { 439*0fca6ea1SDimitry Andric Properties |= 1 << SDNPVariadic; 440*0fca6ea1SDimitry Andric } else if (PropList[i]->getName() == "SDNPWantRoot") { 441*0fca6ea1SDimitry Andric Properties |= 1 << SDNPWantRoot; 442*0fca6ea1SDimitry Andric } else if (PropList[i]->getName() == "SDNPWantParent") { 443*0fca6ea1SDimitry Andric Properties |= 1 << SDNPWantParent; 444*0fca6ea1SDimitry Andric } else { 445*0fca6ea1SDimitry Andric PrintFatalError(R->getLoc(), "Unsupported SD Node property '" + 446*0fca6ea1SDimitry Andric PropList[i]->getName() + 447*0fca6ea1SDimitry Andric "' on ComplexPattern '" + R->getName() + 448*0fca6ea1SDimitry Andric "'!"); 449*0fca6ea1SDimitry Andric } 450*0fca6ea1SDimitry Andric } 451