Skip to content

Commit b64e483

Browse files
authored
[RISCV][TableGen] Generate RISCVTargetParserDef.inc from the new RISCVExtension tblgen information. (#89335)
Instead of using RISCVISAInfo's extension information, use the extension found in tblgen after #89326. We still need to use RISCVISAInfo code to get the sorting rules for the ISA string. The ISA string we generate now is not quite the same extension we had before. No implied extensions are included in the generate string unless they are explicitly listed in RISCVProcessors.td. This primarily affects Zicsr being implied by F, V implying Zve*, and Zvl*b implying a smaller Zvl*b. All of these implication should be picked up when the string is used by the frontend. The benefit is that we get a more manageable ISA string for humans to deal with. This is a step towards generating RISCVISAInfo's extension list from tblgen.
1 parent 4ec9a66 commit b64e483

File tree

2 files changed

+128
-23
lines changed

2 files changed

+128
-23
lines changed
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
// RUN: llvm-tblgen -gen-riscv-target-def -I %p/../../include %s | FileCheck %s
2+
3+
include "llvm/Target/Target.td"
4+
5+
class RISCVExtension<string name, int major, int minor, string fieldname,
6+
string desc, list<SubtargetFeature> implies = [],
7+
string value = "true">
8+
: SubtargetFeature<name, fieldname, value, desc, implies> {
9+
int MajorVersion = major;
10+
int MinorVersion = minor;
11+
bit Experimental = false;
12+
}
13+
14+
def FeatureStdExtI
15+
: RISCVExtension<"i", 2, 1, "HasStdExtI",
16+
"'I' (Base Integer Instruction Set)">;
17+
18+
def FeatureStdExtZicsr
19+
: RISCVExtension<"zicsr", 2, 0, "HasStdExtZicsr",
20+
"'zicsr' (CSRs)">;
21+
22+
def FeatureStdExtZifencei
23+
: RISCVExtension<"zifencei", 2, 0, "HasStdExtZifencei",
24+
"'Zifencei' (fence.i)">;
25+
26+
def Feature32Bit
27+
: SubtargetFeature<"32bit", "IsRV32", "true", "Implements RV32">;
28+
def Feature64Bit
29+
: SubtargetFeature<"64bit", "IsRV64", "true", "Implements RV64">;
30+
31+
// Dummy feature that isn't an extension.
32+
def FeatureDummy
33+
: SubtargetFeature<"dummy", "Dummy", "true", "Dummy">;
34+
35+
class RISCVProcessorModel<string n,
36+
SchedMachineModel m,
37+
list<SubtargetFeature> f,
38+
list<SubtargetFeature> tunef = [],
39+
string default_march = "">
40+
: ProcessorModel<n, m, f, tunef> {
41+
string DefaultMarch = default_march;
42+
}
43+
44+
class RISCVTuneProcessorModel<string n,
45+
SchedMachineModel m,
46+
list<SubtargetFeature> tunef = [],
47+
list<SubtargetFeature> f = []>
48+
: ProcessorModel<n, m, f,tunef>;
49+
50+
def GENERIC_RV32 : RISCVProcessorModel<"generic-rv32",
51+
NoSchedModel,
52+
[Feature32Bit,
53+
FeatureStdExtI]>;
54+
def GENERIC_RV64 : RISCVProcessorModel<"generic-rv64",
55+
NoSchedModel,
56+
[Feature64Bit,
57+
FeatureStdExtI]>;
58+
def GENERIC : RISCVTuneProcessorModel<"generic", NoSchedModel>;
59+
60+
61+
def ROCKET_RV32 : RISCVProcessorModel<"rocket-rv32",
62+
NoSchedModel,
63+
[Feature32Bit,
64+
FeatureStdExtI,
65+
FeatureStdExtZifencei,
66+
FeatureStdExtZicsr,
67+
FeatureDummy]>;
68+
def ROCKET_RV64 : RISCVProcessorModel<"rocket-rv64",
69+
NoSchedModel,
70+
[Feature64Bit,
71+
FeatureStdExtI,
72+
FeatureStdExtZifencei,
73+
FeatureStdExtZicsr,
74+
FeatureDummy]>;
75+
def ROCKET : RISCVTuneProcessorModel<"rocket",
76+
NoSchedModel>;
77+
78+
// CHECK: #ifndef PROC
79+
// CHECK: #define PROC(ENUM, NAME, DEFAULT_MARCH, FAST_UNALIGNED_ACCESS)
80+
// CHECK: #endif
81+
82+
// CHECK: PROC(GENERIC_RV32, {"generic-rv32"}, {"rv32i2p1"}, 0)
83+
// CHECK: PROC(GENERIC_RV64, {"generic-rv64"}, {"rv64i2p1"}, 0)
84+
// CHECK: PROC(ROCKET_RV32, {"rocket-rv32"}, {"rv32i2p1_zicsr2p0_zifencei2p0"}, 0)
85+
// CHECK: PROC(ROCKET_RV64, {"rocket-rv64"}, {"rv64i2p1_zicsr2p0_zifencei2p0"}, 0)
86+
87+
// CHECK: #undef PROC
88+
89+
// CHECK: #ifndef TUNE_PROC
90+
// CHECK: #define TUNE_PROC(ENUM, NAME)
91+
// CHECK: #endif
92+
93+
// CHECK: TUNE_PROC(GENERIC, "generic")
94+
// CHECK: TUNE_PROC(ROCKET, "rocket")
95+
96+
// CHECK: #undef TUNE_PROC

llvm/utils/TableGen/RISCVTargetDefEmitter.cpp

Lines changed: 32 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -17,34 +17,41 @@
1717

1818
using namespace llvm;
1919

20-
using ISAInfoTy = llvm::Expected<std::unique_ptr<RISCVISAInfo>>;
21-
2220
// We can generate march string from target features as what has been described
2321
// in RISC-V ISA specification (version 20191213) 'Chapter 27. ISA Extension
2422
// Naming Conventions'.
2523
//
2624
// This is almost the same as RISCVFeatures::parseFeatureBits, except that we
2725
// get feature name from feature records instead of feature bits.
28-
static std::string getMArch(const Record &Rec) {
29-
std::vector<std::string> FeatureVector;
30-
unsigned XLen = 32;
26+
static void printMArch(raw_ostream &OS, const Record &Rec) {
27+
std::map<std::string, RISCVISAInfo::ExtensionVersion,
28+
RISCVISAInfo::ExtensionComparator>
29+
Extensions;
30+
unsigned XLen = 0;
3131

3232
// Convert features to FeatureVector.
3333
for (auto *Feature : Rec.getValueAsListOfDefs("Features")) {
3434
StringRef FeatureName = Feature->getValueAsString("Name");
35-
if (llvm::RISCVISAInfo::isSupportedExtensionFeature(FeatureName))
36-
FeatureVector.push_back((Twine("+") + FeatureName).str());
37-
else if (FeatureName == "64bit")
35+
if (Feature->isSubClassOf("RISCVExtension")) {
36+
unsigned Major = Feature->getValueAsInt("MajorVersion");
37+
unsigned Minor = Feature->getValueAsInt("MinorVersion");
38+
Extensions[FeatureName.str()] = {Major, Minor};
39+
} else if (FeatureName == "64bit") {
40+
assert(XLen == 0 && "Already determined XLen");
3841
XLen = 64;
42+
} else if (FeatureName == "32bit") {
43+
assert(XLen == 0 && "Already determined XLen");
44+
XLen = 32;
45+
}
3946
}
4047

41-
ISAInfoTy ISAInfo = llvm::RISCVISAInfo::parseFeatures(XLen, FeatureVector);
42-
if (!ISAInfo)
43-
report_fatal_error("Invalid features");
48+
assert(XLen != 0 && "Unable to determine XLen");
49+
50+
OS << "rv" << XLen;
4451

45-
// RISCVISAInfo::toString will generate a march string with all the extensions
46-
// we have added to it.
47-
return (*ISAInfo)->toString();
52+
ListSeparator LS("_");
53+
for (auto const &Ext : Extensions)
54+
OS << LS << Ext.first << Ext.second.Major << 'p' << Ext.second.Minor;
4855
}
4956

5057
static void EmitRISCVTargetDef(RecordKeeper &RK, raw_ostream &OS) {
@@ -54,12 +61,6 @@ static void EmitRISCVTargetDef(RecordKeeper &RK, raw_ostream &OS) {
5461

5562
// Iterate on all definition records.
5663
for (const Record *Rec : RK.getAllDerivedDefinitions("RISCVProcessorModel")) {
57-
std::string MArch = Rec->getValueAsString("DefaultMarch").str();
58-
59-
// Compute MArch from features if we don't specify it.
60-
if (MArch.empty())
61-
MArch = getMArch(*Rec);
62-
6364
bool FastScalarUnalignedAccess =
6465
any_of(Rec->getValueAsListOfDefs("Features"), [&](auto &Feature) {
6566
return Feature->getValueAsString("Name") == "unaligned-scalar-mem";
@@ -73,9 +74,17 @@ static void EmitRISCVTargetDef(RecordKeeper &RK, raw_ostream &OS) {
7374
bool FastUnalignedAccess =
7475
FastScalarUnalignedAccess && FastVectorUnalignedAccess;
7576

76-
OS << "PROC(" << Rec->getName() << ", "
77-
<< "{\"" << Rec->getValueAsString("Name") << "\"}, "
78-
<< "{\"" << MArch << "\"}, " << FastUnalignedAccess << ")\n";
77+
OS << "PROC(" << Rec->getName() << ", {\"" << Rec->getValueAsString("Name")
78+
<< "\"}, {\"";
79+
80+
StringRef MArch = Rec->getValueAsString("DefaultMarch");
81+
82+
// Compute MArch from features if we don't specify it.
83+
if (MArch.empty())
84+
printMArch(OS, *Rec);
85+
else
86+
OS << MArch;
87+
OS << "\"}, " << FastUnalignedAccess << ")\n";
7988
}
8089
OS << "\n#undef PROC\n";
8190
OS << "\n";

0 commit comments

Comments
 (0)