summaryrefslogtreecommitdiffstats
path: root/llvm/utils/TableGen
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/utils/TableGen')
-rw-r--r--llvm/utils/TableGen/CodeEmitterGen.cpp130
-rw-r--r--llvm/utils/TableGen/CodeGenTarget.cpp3
-rw-r--r--llvm/utils/TableGen/FixedLenDecoderEmitter.cpp65
-rw-r--r--llvm/utils/TableGen/InfoByHwMode.cpp11
-rw-r--r--llvm/utils/TableGen/InfoByHwMode.h5
-rw-r--r--llvm/utils/TableGen/SubtargetEmitter.cpp3
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) {
OpenPOWER on IntegriCloud