Path: blob/main/contrib/llvm-project/llvm/utils/TableGen/Common/CodeGenTarget.cpp
35290 views
//===- CodeGenTarget.cpp - CodeGen Target Class Wrapper -------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This class wraps target description classes used by the various code9// generation TableGen backends. This makes it easier to access the data and10// provides a single place that needs to check it for validity. All of these11// classes abort on error conditions.12//13//===----------------------------------------------------------------------===//1415#include "CodeGenTarget.h"16#include "CodeGenInstruction.h"17#include "CodeGenRegisters.h"18#include "CodeGenSchedule.h"19#include "llvm/ADT/STLExtras.h"20#include "llvm/ADT/Twine.h"21#include "llvm/Support/CommandLine.h"22#include "llvm/Support/ErrorHandling.h"23#include "llvm/TableGen/Error.h"24#include "llvm/TableGen/Record.h"25#include <algorithm>26#include <iterator>27#include <tuple>28using namespace llvm;2930cl::OptionCategory AsmParserCat("Options for -gen-asm-parser");31cl::OptionCategory AsmWriterCat("Options for -gen-asm-writer");3233static cl::opt<unsigned>34AsmParserNum("asmparsernum", cl::init(0),35cl::desc("Make -gen-asm-parser emit assembly parser #N"),36cl::cat(AsmParserCat));3738static cl::opt<unsigned>39AsmWriterNum("asmwriternum", cl::init(0),40cl::desc("Make -gen-asm-writer emit assembly writer #N"),41cl::cat(AsmWriterCat));4243/// getValueType - Return the MVT::SimpleValueType that the specified TableGen44/// record corresponds to.45MVT::SimpleValueType llvm::getValueType(const Record *Rec) {46return (MVT::SimpleValueType)Rec->getValueAsInt("Value");47}4849StringRef llvm::getName(MVT::SimpleValueType T) {50switch (T) {51case MVT::Other:52return "UNKNOWN";53case MVT::iPTR:54return "TLI.getPointerTy()";55case MVT::iPTRAny:56return "TLI.getPointerTy()";57default:58return getEnumName(T);59}60}6162StringRef llvm::getEnumName(MVT::SimpleValueType T) {63// clang-format off64switch (T) {65#define GET_VT_ATTR(Ty, N, Sz, Any, Int, FP, Vec, Sc, NElem, EltTy) \66case MVT::Ty: return "MVT::" # Ty;67#include "llvm/CodeGen/GenVT.inc"68default: llvm_unreachable("ILLEGAL VALUE TYPE!");69}70// clang-format on71}7273/// getQualifiedName - Return the name of the specified record, with a74/// namespace qualifier if the record contains one.75///76std::string llvm::getQualifiedName(const Record *R) {77std::string Namespace;78if (R->getValue("Namespace"))79Namespace = std::string(R->getValueAsString("Namespace"));80if (Namespace.empty())81return std::string(R->getName());82return Namespace + "::" + R->getName().str();83}8485/// getTarget - Return the current instance of the Target class.86///87CodeGenTarget::CodeGenTarget(RecordKeeper &records)88: Records(records), CGH(records) {89std::vector<Record *> Targets = Records.getAllDerivedDefinitions("Target");90if (Targets.size() == 0)91PrintFatalError("No 'Target' subclasses defined!");92if (Targets.size() != 1)93PrintFatalError("Multiple subclasses of Target defined!");94TargetRec = Targets[0];95MacroFusions = Records.getAllDerivedDefinitions("Fusion");96}9798CodeGenTarget::~CodeGenTarget() {}99100StringRef CodeGenTarget::getName() const { return TargetRec->getName(); }101102/// getInstNamespace - Find and return the target machine's instruction103/// namespace. The namespace is cached because it is requested multiple times.104StringRef CodeGenTarget::getInstNamespace() const {105if (InstNamespace.empty()) {106for (const CodeGenInstruction *Inst : getInstructionsByEnumValue()) {107// We are not interested in the "TargetOpcode" namespace.108if (Inst->Namespace != "TargetOpcode") {109InstNamespace = Inst->Namespace;110break;111}112}113}114115return InstNamespace;116}117118StringRef CodeGenTarget::getRegNamespace() const {119auto &RegClasses = RegBank->getRegClasses();120return RegClasses.size() > 0 ? RegClasses.front().Namespace : "";121}122123Record *CodeGenTarget::getInstructionSet() const {124return TargetRec->getValueAsDef("InstructionSet");125}126127bool CodeGenTarget::getAllowRegisterRenaming() const {128return TargetRec->getValueAsInt("AllowRegisterRenaming");129}130131/// getAsmParser - Return the AssemblyParser definition for this target.132///133Record *CodeGenTarget::getAsmParser() const {134std::vector<Record *> LI = TargetRec->getValueAsListOfDefs("AssemblyParsers");135if (AsmParserNum >= LI.size())136PrintFatalError("Target does not have an AsmParser #" +137Twine(AsmParserNum) + "!");138return LI[AsmParserNum];139}140141/// getAsmParserVariant - Return the AssemblyParserVariant definition for142/// this target.143///144Record *CodeGenTarget::getAsmParserVariant(unsigned i) const {145std::vector<Record *> LI =146TargetRec->getValueAsListOfDefs("AssemblyParserVariants");147if (i >= LI.size())148PrintFatalError("Target does not have an AsmParserVariant #" + Twine(i) +149"!");150return LI[i];151}152153/// getAsmParserVariantCount - Return the AssemblyParserVariant definition154/// available for this target.155///156unsigned CodeGenTarget::getAsmParserVariantCount() const {157std::vector<Record *> LI =158TargetRec->getValueAsListOfDefs("AssemblyParserVariants");159return LI.size();160}161162/// getAsmWriter - Return the AssemblyWriter definition for this target.163///164Record *CodeGenTarget::getAsmWriter() const {165std::vector<Record *> LI = TargetRec->getValueAsListOfDefs("AssemblyWriters");166if (AsmWriterNum >= LI.size())167PrintFatalError("Target does not have an AsmWriter #" +168Twine(AsmWriterNum) + "!");169return LI[AsmWriterNum];170}171172CodeGenRegBank &CodeGenTarget::getRegBank() const {173if (!RegBank)174RegBank = std::make_unique<CodeGenRegBank>(Records, getHwModes());175return *RegBank;176}177178std::optional<CodeGenRegisterClass *> CodeGenTarget::getSuperRegForSubReg(179const ValueTypeByHwMode &ValueTy, CodeGenRegBank &RegBank,180const CodeGenSubRegIndex *SubIdx, bool MustBeAllocatable) const {181std::vector<CodeGenRegisterClass *> Candidates;182auto &RegClasses = RegBank.getRegClasses();183184// Try to find a register class which supports ValueTy, and also contains185// SubIdx.186for (CodeGenRegisterClass &RC : RegClasses) {187// Is there a subclass of this class which contains this subregister index?188CodeGenRegisterClass *SubClassWithSubReg = RC.getSubClassWithSubReg(SubIdx);189if (!SubClassWithSubReg)190continue;191192// We have a class. Check if it supports this value type.193if (!llvm::is_contained(SubClassWithSubReg->VTs, ValueTy))194continue;195196// If necessary, check that it is allocatable.197if (MustBeAllocatable && !SubClassWithSubReg->Allocatable)198continue;199200// We have a register class which supports both the value type and201// subregister index. Remember it.202Candidates.push_back(SubClassWithSubReg);203}204205// If we didn't find anything, we're done.206if (Candidates.empty())207return std::nullopt;208209// Find and return the largest of our candidate classes.210llvm::stable_sort(Candidates, [&](const CodeGenRegisterClass *A,211const CodeGenRegisterClass *B) {212if (A->getMembers().size() > B->getMembers().size())213return true;214215if (A->getMembers().size() < B->getMembers().size())216return false;217218// Order by name as a tie-breaker.219return StringRef(A->getName()) < B->getName();220});221222return Candidates[0];223}224225void CodeGenTarget::ReadRegAltNameIndices() const {226RegAltNameIndices = Records.getAllDerivedDefinitions("RegAltNameIndex");227llvm::sort(RegAltNameIndices, LessRecord());228}229230/// getRegisterByName - If there is a register with the specific AsmName,231/// return it.232const CodeGenRegister *CodeGenTarget::getRegisterByName(StringRef Name) const {233return getRegBank().getRegistersByName().lookup(Name);234}235236const CodeGenRegisterClass &CodeGenTarget::getRegisterClass(Record *R) const {237return *getRegBank().getRegClass(R);238}239240std::vector<ValueTypeByHwMode> CodeGenTarget::getRegisterVTs(Record *R) const {241const CodeGenRegister *Reg = getRegBank().getReg(R);242std::vector<ValueTypeByHwMode> Result;243for (const auto &RC : getRegBank().getRegClasses()) {244if (RC.contains(Reg)) {245ArrayRef<ValueTypeByHwMode> InVTs = RC.getValueTypes();246llvm::append_range(Result, InVTs);247}248}249250// Remove duplicates.251llvm::sort(Result);252Result.erase(llvm::unique(Result), Result.end());253return Result;254}255256void CodeGenTarget::ReadLegalValueTypes() const {257for (const auto &RC : getRegBank().getRegClasses())258llvm::append_range(LegalValueTypes, RC.VTs);259260// Remove duplicates.261llvm::sort(LegalValueTypes);262LegalValueTypes.erase(llvm::unique(LegalValueTypes), LegalValueTypes.end());263}264265CodeGenSchedModels &CodeGenTarget::getSchedModels() const {266if (!SchedModels)267SchedModels = std::make_unique<CodeGenSchedModels>(Records, *this);268return *SchedModels;269}270271void CodeGenTarget::ReadInstructions() const {272std::vector<Record *> Insts = Records.getAllDerivedDefinitions("Instruction");273if (Insts.size() <= 2)274PrintFatalError("No 'Instruction' subclasses defined!");275276// Parse the instructions defined in the .td file.277for (Record *R : Insts) {278Instructions[R] = std::make_unique<CodeGenInstruction>(R);279if (Instructions[R]->isVariableLengthEncoding())280HasVariableLengthEncodings = true;281}282}283284static const CodeGenInstruction *GetInstByName(285const char *Name,286const DenseMap<const Record *, std::unique_ptr<CodeGenInstruction>> &Insts,287RecordKeeper &Records) {288const Record *Rec = Records.getDef(Name);289290const auto I = Insts.find(Rec);291if (!Rec || I == Insts.end())292PrintFatalError(Twine("Could not find '") + Name + "' instruction!");293return I->second.get();294}295296static const char *FixedInstrs[] = {297#define HANDLE_TARGET_OPCODE(OPC) #OPC,298#include "llvm/Support/TargetOpcodes.def"299nullptr};300301unsigned CodeGenTarget::getNumFixedInstructions() {302return std::size(FixedInstrs) - 1;303}304305/// Return all of the instructions defined by the target, ordered by306/// their enum value.307void CodeGenTarget::ComputeInstrsByEnum() const {308const auto &Insts = getInstructions();309for (const char *const *p = FixedInstrs; *p; ++p) {310const CodeGenInstruction *Instr = GetInstByName(*p, Insts, Records);311assert(Instr && "Missing target independent instruction");312assert(Instr->Namespace == "TargetOpcode" && "Bad namespace");313InstrsByEnum.push_back(Instr);314}315unsigned EndOfPredefines = InstrsByEnum.size();316assert(EndOfPredefines == getNumFixedInstructions() &&317"Missing generic opcode");318319for (const auto &I : Insts) {320const CodeGenInstruction *CGI = I.second.get();321if (CGI->Namespace != "TargetOpcode") {322InstrsByEnum.push_back(CGI);323if (CGI->TheDef->getValueAsBit("isPseudo"))324++NumPseudoInstructions;325}326}327328assert(InstrsByEnum.size() == Insts.size() && "Missing predefined instr");329330// All of the instructions are now in random order based on the map iteration.331llvm::sort(332InstrsByEnum.begin() + EndOfPredefines, InstrsByEnum.end(),333[](const CodeGenInstruction *Rec1, const CodeGenInstruction *Rec2) {334const auto &D1 = *Rec1->TheDef;335const auto &D2 = *Rec2->TheDef;336return std::tuple(!D1.getValueAsBit("isPseudo"), D1.getName()) <337std::tuple(!D2.getValueAsBit("isPseudo"), D2.getName());338});339340// Assign an enum value to each instruction according to the sorted order.341unsigned Num = 0;342for (const CodeGenInstruction *Inst : InstrsByEnum)343Inst->EnumVal = Num++;344}345346/// isLittleEndianEncoding - Return whether this target encodes its instruction347/// in little-endian format, i.e. bits laid out in the order [0..n]348///349bool CodeGenTarget::isLittleEndianEncoding() const {350return getInstructionSet()->getValueAsBit("isLittleEndianEncoding");351}352353/// reverseBitsForLittleEndianEncoding - For little-endian instruction bit354/// encodings, reverse the bit order of all instructions.355void CodeGenTarget::reverseBitsForLittleEndianEncoding() {356if (!isLittleEndianEncoding())357return;358359std::vector<Record *> Insts =360Records.getAllDerivedDefinitions("InstructionEncoding");361for (Record *R : Insts) {362if (R->getValueAsString("Namespace") == "TargetOpcode" ||363R->getValueAsBit("isPseudo"))364continue;365366BitsInit *BI = R->getValueAsBitsInit("Inst");367368unsigned numBits = BI->getNumBits();369370SmallVector<Init *, 16> NewBits(numBits);371372for (unsigned bit = 0, end = numBits / 2; bit != end; ++bit) {373unsigned bitSwapIdx = numBits - bit - 1;374Init *OrigBit = BI->getBit(bit);375Init *BitSwap = BI->getBit(bitSwapIdx);376NewBits[bit] = BitSwap;377NewBits[bitSwapIdx] = OrigBit;378}379if (numBits % 2) {380unsigned middle = (numBits + 1) / 2;381NewBits[middle] = BI->getBit(middle);382}383384BitsInit *NewBI = BitsInit::get(Records, NewBits);385386// Update the bits in reversed order so that emitInstrOpBits will get the387// correct endianness.388R->getValue("Inst")->setValue(NewBI);389}390}391392/// guessInstructionProperties - Return true if it's OK to guess instruction393/// properties instead of raising an error.394///395/// This is configurable as a temporary migration aid. It will eventually be396/// permanently false.397bool CodeGenTarget::guessInstructionProperties() const {398return getInstructionSet()->getValueAsBit("guessInstructionProperties");399}400401//===----------------------------------------------------------------------===//402// ComplexPattern implementation403//404ComplexPattern::ComplexPattern(Record *R) {405Ty = R->getValueAsDef("Ty");406NumOperands = R->getValueAsInt("NumOperands");407SelectFunc = std::string(R->getValueAsString("SelectFunc"));408RootNodes = R->getValueAsListOfDefs("RootNodes");409410// FIXME: This is a hack to statically increase the priority of patterns which411// maps a sub-dag to a complex pattern. e.g. favors LEA over ADD. To get best412// possible pattern match we'll need to dynamically calculate the complexity413// of all patterns a dag can potentially map to.414int64_t RawComplexity = R->getValueAsInt("Complexity");415if (RawComplexity == -1)416Complexity = NumOperands * 3;417else418Complexity = RawComplexity;419420// FIXME: Why is this different from parseSDPatternOperatorProperties?421// Parse the properties.422Properties = 0;423std::vector<Record *> PropList = R->getValueAsListOfDefs("Properties");424for (unsigned i = 0, e = PropList.size(); i != e; ++i)425if (PropList[i]->getName() == "SDNPHasChain") {426Properties |= 1 << SDNPHasChain;427} else if (PropList[i]->getName() == "SDNPOptInGlue") {428Properties |= 1 << SDNPOptInGlue;429} else if (PropList[i]->getName() == "SDNPMayStore") {430Properties |= 1 << SDNPMayStore;431} else if (PropList[i]->getName() == "SDNPMayLoad") {432Properties |= 1 << SDNPMayLoad;433} else if (PropList[i]->getName() == "SDNPSideEffect") {434Properties |= 1 << SDNPSideEffect;435} else if (PropList[i]->getName() == "SDNPMemOperand") {436Properties |= 1 << SDNPMemOperand;437} else if (PropList[i]->getName() == "SDNPVariadic") {438Properties |= 1 << SDNPVariadic;439} else if (PropList[i]->getName() == "SDNPWantRoot") {440Properties |= 1 << SDNPWantRoot;441} else if (PropList[i]->getName() == "SDNPWantParent") {442Properties |= 1 << SDNPWantParent;443} else {444PrintFatalError(R->getLoc(), "Unsupported SD Node property '" +445PropList[i]->getName() +446"' on ComplexPattern '" + R->getName() +447"'!");448}449}450451452