diff options
Diffstat (limited to 'llvm/utils/TableGen')
-rw-r--r-- | llvm/utils/TableGen/CodeEmitterGen.cpp | 130 | ||||
-rw-r--r-- | llvm/utils/TableGen/CodeGenTarget.cpp | 3 | ||||
-rw-r--r-- | llvm/utils/TableGen/FixedLenDecoderEmitter.cpp | 65 | ||||
-rw-r--r-- | llvm/utils/TableGen/InfoByHwMode.cpp | 11 | ||||
-rw-r--r-- | llvm/utils/TableGen/InfoByHwMode.h | 5 | ||||
-rw-r--r-- | llvm/utils/TableGen/SubtargetEmitter.cpp | 3 |
6 files changed, 179 insertions, 38 deletions
diff --git a/llvm/utils/TableGen/CodeEmitterGen.cpp b/llvm/utils/TableGen/CodeEmitterGen.cpp index 10c42bbc6ff..b021d08881f 100644 --- a/llvm/utils/TableGen/CodeEmitterGen.cpp +++ b/llvm/utils/TableGen/CodeEmitterGen.cpp @@ -46,12 +46,17 @@ public: private: int getVariableBit(const std::string &VarName, BitsInit *BI, int bit); std::string getInstructionCase(Record *R, CodeGenTarget &Target); + std::string getInstructionCaseForEncoding(Record *R, Record *EncodingDef, + CodeGenTarget &Target); void AddCodeToMergeInOperand(Record *R, BitsInit *BI, const std::string &VarName, unsigned &NumberedOp, std::set<unsigned> &NamedOpIndices, std::string &Case, CodeGenTarget &Target); + void emitInstructionBaseValues( + raw_ostream &o, ArrayRef<const CodeGenInstruction *> NumberedInstructions, + CodeGenTarget &Target, int HwMode = -1); unsigned BitWidth; bool UseAPInt; }; @@ -261,7 +266,29 @@ AddCodeToMergeInOperand(Record *R, BitsInit *BI, const std::string &VarName, std::string CodeEmitterGen::getInstructionCase(Record *R, CodeGenTarget &Target) { std::string Case; - BitsInit *BI = R->getValueAsBitsInit("Inst"); + if (const RecordVal *RV = R->getValue("EncodingInfos")) { + if (auto *DI = dyn_cast_or_null<DefInit>(RV->getValue())) { + const CodeGenHwModes &HWM = Target.getHwModes(); + EncodingInfoByHwMode EBM(DI->getDef(), HWM); + Case += " switch (HwMode) {\n"; + Case += " default: llvm_unreachable(\"Unhandled HwMode\");\n"; + for (auto &KV : EBM.Map) { + Case += " case " + itostr(KV.first) + ": {\n"; + Case += getInstructionCaseForEncoding(R, KV.second, Target); + Case += " break;\n"; + Case += " }\n"; + } + Case += " }\n"; + return Case; + } + } + return getInstructionCaseForEncoding(R, R, Target); +} + +std::string CodeEmitterGen::getInstructionCaseForEncoding(Record *R, Record *EncodingDef, + CodeGenTarget &Target) { + std::string Case; + BitsInit *BI = EncodingDef->getValueAsBitsInit("Inst"); unsigned NumberedOp = 0; std::set<unsigned> NamedOpIndices; @@ -281,7 +308,7 @@ std::string CodeEmitterGen::getInstructionCase(Record *R, // Loop over all of the fields in the instruction, determining which are the // operands to the instruction. - for (const RecordVal &RV : R->getValues()) { + for (const RecordVal &RV : EncodingDef->getValues()) { // Ignore fixed fields in the record, we're looking for values like: // bits<5> RST = { ?, ?, ?, ?, ? }; if (RV.getPrefix() || RV.getValue()->isComplete()) @@ -317,6 +344,47 @@ static void emitInstBits(raw_ostream &OS, const APInt &Bits) { << ")"; } +void CodeEmitterGen::emitInstructionBaseValues( + raw_ostream &o, ArrayRef<const CodeGenInstruction *> NumberedInstructions, + CodeGenTarget &Target, int HwMode) { + const CodeGenHwModes &HWM = Target.getHwModes(); + if (HwMode == -1) + o << " static const uint64_t InstBits[] = {\n"; + else + o << " static const uint64_t InstBits_" << HWM.getMode(HwMode).Name + << "[] = {\n"; + + for (const CodeGenInstruction *CGI : NumberedInstructions) { + Record *R = CGI->TheDef; + + if (R->getValueAsString("Namespace") == "TargetOpcode" || + R->getValueAsBit("isPseudo")) { + o << " "; emitInstBits(o, APInt(BitWidth, 0)); o << ",\n"; + continue; + } + + Record *EncodingDef = R; + if (const RecordVal *RV = R->getValue("EncodingInfos")) { + if (auto *DI = dyn_cast_or_null<DefInit>(RV->getValue())) { + EncodingInfoByHwMode EBM(DI->getDef(), HWM); + EncodingDef = EBM.get(HwMode); + } + } + BitsInit *BI = EncodingDef->getValueAsBitsInit("Inst"); + + // Start by filling in fixed values. + APInt Value(BitWidth, 0); + for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i) { + if (BitInit *B = dyn_cast<BitInit>(BI->getBit(e - i - 1))) + Value |= APInt(BitWidth, (uint64_t)B->getValue()) << (e - i - 1); + } + o << " "; + emitInstBits(o, Value); + o << "," << '\t' << "// " << R->getName() << "\n"; + } + o << " UINT64_C(0)\n };\n"; +} + void CodeEmitterGen::run(raw_ostream &o) { CodeGenTarget Target(Records); std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction"); @@ -327,17 +395,29 @@ void CodeEmitterGen::run(raw_ostream &o) { ArrayRef<const CodeGenInstruction*> NumberedInstructions = Target.getInstructionsByEnumValue(); - // Default to something sensible in case the target doesn't define Inst. - BitWidth = 32; + const CodeGenHwModes &HWM = Target.getHwModes(); + // The set of HwModes used by instruction encodings. + std::set<unsigned> HwModes; + BitWidth = 0; for (const CodeGenInstruction *CGI : NumberedInstructions) { Record *R = CGI->TheDef; if (R->getValueAsString("Namespace") == "TargetOpcode" || R->getValueAsBit("isPseudo")) continue; + if (const RecordVal *RV = R->getValue("EncodingInfos")) { + if (DefInit *DI = dyn_cast_or_null<DefInit>(RV->getValue())) { + EncodingInfoByHwMode EBM(DI->getDef(), HWM); + for (auto &KV : EBM.Map) { + BitsInit *BI = KV.second->getValueAsBitsInit("Inst"); + BitWidth = std::max(BitWidth, BI->getNumBits()); + HwModes.insert(KV.first); + } + continue; + } + } BitsInit *BI = R->getValueAsBitsInit("Inst"); - BitWidth = BI->getNumBits(); - break; + BitWidth = std::max(BitWidth, BI->getNumBits()); } UseAPInt = BitWidth > 64; @@ -357,31 +437,25 @@ void CodeEmitterGen::run(raw_ostream &o) { } // Emit instruction base values - o << " static const uint64_t InstBits[] = {\n"; - for (const CodeGenInstruction *CGI : NumberedInstructions) { - Record *R = CGI->TheDef; - - if (R->getValueAsString("Namespace") == "TargetOpcode" || - R->getValueAsBit("isPseudo")) { - o << " "; emitInstBits(o, APInt(BitWidth, 0)); o << ",\n"; - continue; - } - - BitsInit *BI = R->getValueAsBitsInit("Inst"); - BitWidth = BI->getNumBits(); + if (HwModes.empty()) { + emitInstructionBaseValues(o, NumberedInstructions, Target, -1); + } else { + for (unsigned HwMode : HwModes) + emitInstructionBaseValues(o, NumberedInstructions, Target, (int)HwMode); + } - // Start by filling in fixed values. - APInt Value(BitWidth, 0); - for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i) { - if (BitInit *B = dyn_cast<BitInit>(BI->getBit(e - i - 1))) - Value |= APInt(BitWidth, (uint64_t)B->getValue()) << (e - i - 1); + if (!HwModes.empty()) { + o << " const uint64_t *InstBits;\n"; + o << " unsigned HwMode = STI.getHwMode();\n"; + o << " switch (HwMode) {\n"; + o << " default: llvm_unreachable(\"Unknown hardware mode!\"); break;\n"; + for (unsigned I : HwModes) { + o << " case " << I << ": InstBits = InstBits_" << HWM.getMode(I).Name + << "; break;\n"; } - o << " "; - emitInstBits(o, Value); - o << "," << '\t' << "// " << R->getName() << "\n"; + o << " };\n"; } - o << " UINT64_C(0)\n };\n"; - + // Map to accumulate all the cases. std::map<std::string, std::vector<std::string>> CaseMap; diff --git a/llvm/utils/TableGen/CodeGenTarget.cpp b/llvm/utils/TableGen/CodeGenTarget.cpp index 478bbb7e480..fa8b842c97f 100644 --- a/llvm/utils/TableGen/CodeGenTarget.cpp +++ b/llvm/utils/TableGen/CodeGenTarget.cpp @@ -478,7 +478,8 @@ void CodeGenTarget::reverseBitsForLittleEndianEncoding() { if (!isLittleEndianEncoding()) return; - std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction"); + std::vector<Record *> Insts = + Records.getAllDerivedDefinitions("InstructionEncoding"); for (Record *R : Insts) { if (R->getValueAsString("Namespace") == "TargetOpcode" || R->getValueAsBit("isPseudo")) diff --git a/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp b/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp index 01f4115aa1d..ac69b431607 100644 --- a/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp +++ b/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp @@ -13,6 +13,7 @@ #include "CodeGenInstruction.h" #include "CodeGenTarget.h" +#include "InfoByHwMode.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/CachedHashString.h" @@ -97,9 +98,11 @@ struct DecoderTableInfo { struct EncodingAndInst { const Record *EncodingDef; const CodeGenInstruction *Inst; + StringRef HwModeName; - EncodingAndInst(const Record *EncodingDef, const CodeGenInstruction *Inst) - : EncodingDef(EncodingDef), Inst(Inst) {} + EncodingAndInst(const Record *EncodingDef, const CodeGenInstruction *Inst, + StringRef HwModeName = "") + : EncodingDef(EncodingDef), Inst(Inst), HwModeName(HwModeName) {} }; struct EncodingIDAndOpcode { @@ -2382,12 +2385,50 @@ void FixedLenDecoderEmitter::run(raw_ostream &o) { Target.reverseBitsForLittleEndianEncoding(); // Parameterize the decoders based on namespace and instruction width. + std::set<StringRef> HwModeNames; const auto &NumberedInstructions = Target.getInstructionsByEnumValue(); NumberedEncodings.reserve(NumberedInstructions.size()); DenseMap<Record *, unsigned> IndexOfInstruction; + // First, collect all HwModes referenced by the target. for (const auto &NumberedInstruction : NumberedInstructions) { IndexOfInstruction[NumberedInstruction->TheDef] = NumberedEncodings.size(); - NumberedEncodings.emplace_back(NumberedInstruction->TheDef, NumberedInstruction); + + if (const RecordVal *RV = + NumberedInstruction->TheDef->getValue("EncodingInfos")) { + if (auto *DI = dyn_cast_or_null<DefInit>(RV->getValue())) { + const CodeGenHwModes &HWM = Target.getHwModes(); + EncodingInfoByHwMode EBM(DI->getDef(), HWM); + for (auto &KV : EBM.Map) + HwModeNames.insert(HWM.getMode(KV.first).Name); + } + } + } + + // If HwModeNames is empty, add the empty string so we always have one HwMode. + if (HwModeNames.empty()) + HwModeNames.insert(""); + + for (const auto &NumberedInstruction : NumberedInstructions) { + IndexOfInstruction[NumberedInstruction->TheDef] = NumberedEncodings.size(); + + if (const RecordVal *RV = + NumberedInstruction->TheDef->getValue("EncodingInfos")) { + if (DefInit *DI = dyn_cast_or_null<DefInit>(RV->getValue())) { + const CodeGenHwModes &HWM = Target.getHwModes(); + EncodingInfoByHwMode EBM(DI->getDef(), HWM); + for (auto &KV : EBM.Map) { + NumberedEncodings.emplace_back(KV.second, NumberedInstruction, + HWM.getMode(KV.first).Name); + HwModeNames.insert(HWM.getMode(KV.first).Name); + } + continue; + } + } + // This instruction is encoded the same on all HwModes. Emit it for all + // HwModes. + for (StringRef HwModeName : HwModeNames) + NumberedEncodings.emplace_back(NumberedInstruction->TheDef, + NumberedInstruction, HwModeName); } for (const auto &NumberedAlias : RK.getAllDerivedDefinitions("AdditionalEncoding")) NumberedEncodings.emplace_back( @@ -2415,13 +2456,19 @@ void FixedLenDecoderEmitter::run(raw_ostream &o) { NumInstructions++; NumEncodings++; - StringRef DecoderNamespace = EncodingDef->getValueAsString("DecoderNamespace"); + if (!Size) + continue; - if (Size) { - if (populateInstruction(Target, *EncodingDef, *Inst, i, Operands)) { - OpcMap[std::make_pair(DecoderNamespace, Size)].emplace_back(i, IndexOfInstruction.find(Def)->second); - } else - NumEncodingsOmitted++; + if (populateInstruction(Target, *EncodingDef, *Inst, i, Operands)) { + std::string DecoderNamespace = + EncodingDef->getValueAsString("DecoderNamespace"); + if (!NumberedEncodings[i].HwModeName.empty()) + DecoderNamespace += + std::string("_") + NumberedEncodings[i].HwModeName.str(); + OpcMap[std::make_pair(DecoderNamespace, Size)].emplace_back( + i, IndexOfInstruction.find(Def)->second); + } else { + NumEncodingsOmitted++; } } diff --git a/llvm/utils/TableGen/InfoByHwMode.cpp b/llvm/utils/TableGen/InfoByHwMode.cpp index d9662889a5d..7cd1b0f0813 100644 --- a/llvm/utils/TableGen/InfoByHwMode.cpp +++ b/llvm/utils/TableGen/InfoByHwMode.cpp @@ -192,6 +192,17 @@ void RegSizeInfoByHwMode::writeToStream(raw_ostream &OS) const { OS << '}'; } +EncodingInfoByHwMode::EncodingInfoByHwMode(Record *R, const CodeGenHwModes &CGH) { + const HwModeSelect &MS = CGH.getHwModeSelect(R); + for (const HwModeSelect::PairType &P : MS.Items) { + assert(P.second && P.second->isSubClassOf("InstructionEncoding") && + "Encoding must subclass InstructionEncoding"); + auto I = Map.insert({P.first, P.second}); + assert(I.second && "Duplicate entry?"); + (void)I; + } +} + namespace llvm { raw_ostream &operator<<(raw_ostream &OS, const ValueTypeByHwMode &T) { T.writeToStream(OS); diff --git a/llvm/utils/TableGen/InfoByHwMode.h b/llvm/utils/TableGen/InfoByHwMode.h index 9e5cc3d5f2a..d92e5901a7f 100644 --- a/llvm/utils/TableGen/InfoByHwMode.h +++ b/llvm/utils/TableGen/InfoByHwMode.h @@ -184,6 +184,11 @@ raw_ostream &operator<<(raw_ostream &OS, const ValueTypeByHwMode &T); raw_ostream &operator<<(raw_ostream &OS, const RegSizeInfo &T); raw_ostream &operator<<(raw_ostream &OS, const RegSizeInfoByHwMode &T); +struct EncodingInfoByHwMode : public InfoByHwMode<Record*> { + EncodingInfoByHwMode(Record *R, const CodeGenHwModes &CGH); + EncodingInfoByHwMode() = default; +}; + } // namespace llvm #endif // LLVM_UTILS_TABLEGEN_INFOBYHWMODE_H diff --git a/llvm/utils/TableGen/SubtargetEmitter.cpp b/llvm/utils/TableGen/SubtargetEmitter.cpp index 41589b6b10d..f9705723650 100644 --- a/llvm/utils/TableGen/SubtargetEmitter.cpp +++ b/llvm/utils/TableGen/SubtargetEmitter.cpp @@ -1746,7 +1746,10 @@ void SubtargetEmitter::emitGenMCSubtargetInfo(raw_ostream &OS) { << " return " << Target << "_MC" << "::resolveVariantSchedClassImpl(SchedClass, MI, CPUID); \n"; OS << " }\n"; + if (TGT.getHwModes().getNumModeIds() > 1) + OS << " unsigned getHwMode() const override;\n"; OS << "};\n"; + EmitHwModeCheck(Target + "GenMCSubtargetInfo", OS); } void SubtargetEmitter::EmitMCInstrAnalysisPredicateFunctions(raw_ostream &OS) { |