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