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