Skip to content

Commit b968fd9

Browse files
authored
[StrTable] Mechanically convert NVPTX builtins to use TableGen (#122873)
This switches them to use tho common TableGen layer, extending it to support the missing features needed by the NVPTX backend. The biggest thing was to build a TableGen system that computes the cumulative SM and PTX feature sets the same way the macros did. That's done with some string concatenation tricks in TableGen, but they worked out pretty neatly and are very comparable in complexity to the macro version. Then the actual defines were mapped over using a very hacky Python script. It was never productionized or intended to work in the future, but for posterity: https://gist.github.com/chandlerc/10bdf8fb1312e252b4a501bace184b66 Last but not least, there was a very odd "bug" in one of the converted builtins' prototype in the TableGen model: it didn't handle uses of `Z` and `U` both as *qualifiers* of a single type, treating `Z` as its own `int32_t` type. So my hacky Python script converted `ZUi` into two types, an `int32_t` and an `unsigned int`. This produced a very wrong prototype. But the tests caught this nicely and I fixed it manually rather than trying to improve the Python script as it occurred in exactly one place I could find. This should provide direct benefits of allowing future refactorings to more directly leverage TableGen to express builtins more structurally rather than textually. It will also make my efforts to move builtins to string tables significantly more effective for the NVPTX backend where the X-macro approach resulted in *significantly* less efficient string tables than other targets due to the long repeated feature strings.
1 parent ea9993a commit b968fd9

File tree

8 files changed

+1126
-1131
lines changed

8 files changed

+1126
-1131
lines changed

clang/include/clang/Basic/BuiltinsNVPTX.def

Lines changed: 0 additions & 1119 deletions
This file was deleted.

clang/include/clang/Basic/BuiltinsNVPTX.td

Lines changed: 1078 additions & 0 deletions
Large diffs are not rendered by default.

clang/include/clang/Basic/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ clang_tablegen(BuiltinsBPF.inc -gen-clang-builtins
7272
SOURCE BuiltinsBPF.td
7373
TARGET ClangBuiltinsBPF)
7474

75+
clang_tablegen(BuiltinsNVPTX.inc -gen-clang-builtins
76+
SOURCE BuiltinsNVPTX.td
77+
TARGET ClangBuiltinsNVPTX)
78+
7579
clang_tablegen(BuiltinsRISCV.inc -gen-clang-builtins
7680
SOURCE BuiltinsRISCV.td
7781
TARGET ClangBuiltinsRISCV)

clang/include/clang/Basic/TargetBuiltins.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -101,12 +101,12 @@ namespace clang {
101101

102102
/// NVPTX builtins
103103
namespace NVPTX {
104-
enum {
105-
LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1,
104+
enum {
105+
LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1,
106106
#define BUILTIN(ID, TYPE, ATTRS) BI##ID,
107-
#include "clang/Basic/BuiltinsNVPTX.def"
108-
LastTSBuiltin
109-
};
107+
#include "clang/Basic/BuiltinsNVPTX.inc"
108+
LastTSBuiltin
109+
};
110110
}
111111

112112
/// AMDGPU builtins

clang/include/module.modulemap

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@ module Clang_Basic {
5353
textual header "clang/Basic/BuiltinsLoongArchLSX.def"
5454
textual header "clang/Basic/BuiltinsMips.def"
5555
textual header "clang/Basic/BuiltinsNEON.def"
56-
textual header "clang/Basic/BuiltinsNVPTX.def"
5756
textual header "clang/Basic/BuiltinsPPC.def"
5857
textual header "clang/Basic/BuiltinsRISCVVector.def"
5958
textual header "clang/Basic/BuiltinsSME.def"

clang/lib/Basic/Targets/NVPTX.cpp

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,9 @@ using namespace clang;
2121
using namespace clang::targets;
2222

2323
static constexpr Builtin::Info BuiltinInfo[] = {
24-
#define BUILTIN(ID, TYPE, ATTRS) \
25-
{#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
26-
#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \
27-
{#ID, TYPE, ATTRS, nullptr, HeaderDesc::HEADER, ALL_LANGUAGES},
2824
#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
2925
{#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
30-
#include "clang/Basic/BuiltinsNVPTX.def"
26+
#include "clang/Basic/BuiltinsNVPTX.inc"
3127
};
3228

3329
const char *const NVPTXTargetInfo::GCCRegNames[] = {"r0"};

clang/test/CodeGen/builtins-nvptx.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ __device__ void exit() {
202202
// NVVM intrinsics
203203

204204
// The idea is not to test all intrinsics, just that Clang is recognizing the
205-
// builtins defined in BuiltinsNVPTX.def
205+
// builtins defined in BuiltinsNVPTX.td
206206
__device__ void nvvm_math(float f1, float f2, double d1, double d2) {
207207
// CHECK: call float @llvm.nvvm.fmax.f
208208
float t1 = __nvvm_fmax_f(f1, f2);

clang/utils/TableGen/ClangBuiltinsEmitter.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,39 @@ class PrototypeParser {
104104

105105
void ParseType(StringRef T) {
106106
T = T.trim();
107+
108+
auto ConsumeAddrSpace = [&]() -> std::optional<unsigned> {
109+
T = T.trim();
110+
if (!T.consume_back(">"))
111+
return std::nullopt;
112+
113+
auto Open = T.find_last_of('<');
114+
if (Open == StringRef::npos)
115+
PrintFatalError(Loc, "Mismatched angle-brackets in type");
116+
117+
StringRef ArgStr = T.substr(Open + 1);
118+
T = T.slice(0, Open);
119+
if (!T.consume_back("address_space"))
120+
PrintFatalError(Loc,
121+
"Only `address_space<N>` supported as a parameterized "
122+
"pointer or reference type qualifier");
123+
124+
unsigned Number = 0;
125+
if (ArgStr.getAsInteger(10, Number))
126+
PrintFatalError(
127+
Loc, "Expected an integer argument to the address_space qualifier");
128+
if (Number == 0)
129+
PrintFatalError(Loc, "No need for a qualifier for address space `0`");
130+
return Number;
131+
};
132+
107133
if (T.consume_back("*")) {
134+
// Pointers may have an address space qualifier immediately before them.
135+
std::optional<unsigned> AS = ConsumeAddrSpace();
108136
ParseType(T);
109137
Type += "*";
138+
if (AS)
139+
Type += std::to_string(*AS);
110140
} else if (T.consume_back("const")) {
111141
ParseType(T);
112142
Type += "C";
@@ -117,6 +147,13 @@ class PrototypeParser {
117147
ParseType(T);
118148
Type += "R";
119149
} else if (T.consume_back("&")) {
150+
// References may have an address space qualifier immediately before them.
151+
std::optional<unsigned> AS = ConsumeAddrSpace();
152+
ParseType(T);
153+
Type += "&";
154+
if (AS)
155+
Type += std::to_string(*AS);
156+
} else if (T.consume_back(")")) {
120157
ParseType(T);
121158
Type += "&";
122159
} else if (EnableOpenCLLong && T.consume_front("long long")) {

0 commit comments

Comments
 (0)