Skip to content

Commit

Permalink
[StrTable] Mechanically convert NVPTX builtins to use TableGen (llvm#…
Browse files Browse the repository at this point in the history
…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.
  • Loading branch information
chandlerc authored Jan 28, 2025
1 parent ea9993a commit b968fd9
Show file tree
Hide file tree
Showing 8 changed files with 1,126 additions and 1,131 deletions.
1,119 changes: 0 additions & 1,119 deletions clang/include/clang/Basic/BuiltinsNVPTX.def

This file was deleted.

1,078 changes: 1,078 additions & 0 deletions clang/include/clang/Basic/BuiltinsNVPTX.td

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions clang/include/clang/Basic/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ clang_tablegen(BuiltinsBPF.inc -gen-clang-builtins
SOURCE BuiltinsBPF.td
TARGET ClangBuiltinsBPF)

clang_tablegen(BuiltinsNVPTX.inc -gen-clang-builtins
SOURCE BuiltinsNVPTX.td
TARGET ClangBuiltinsNVPTX)

clang_tablegen(BuiltinsRISCV.inc -gen-clang-builtins
SOURCE BuiltinsRISCV.td
TARGET ClangBuiltinsRISCV)
Expand Down
10 changes: 5 additions & 5 deletions clang/include/clang/Basic/TargetBuiltins.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,12 +101,12 @@ namespace clang {

/// NVPTX builtins
namespace NVPTX {
enum {
LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1,
enum {
LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1,
#define BUILTIN(ID, TYPE, ATTRS) BI##ID,
#include "clang/Basic/BuiltinsNVPTX.def"
LastTSBuiltin
};
#include "clang/Basic/BuiltinsNVPTX.inc"
LastTSBuiltin
};
}

/// AMDGPU builtins
Expand Down
1 change: 0 additions & 1 deletion clang/include/module.modulemap
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ module Clang_Basic {
textual header "clang/Basic/BuiltinsLoongArchLSX.def"
textual header "clang/Basic/BuiltinsMips.def"
textual header "clang/Basic/BuiltinsNEON.def"
textual header "clang/Basic/BuiltinsNVPTX.def"
textual header "clang/Basic/BuiltinsPPC.def"
textual header "clang/Basic/BuiltinsRISCVVector.def"
textual header "clang/Basic/BuiltinsSME.def"
Expand Down
6 changes: 1 addition & 5 deletions clang/lib/Basic/Targets/NVPTX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,9 @@ using namespace clang;
using namespace clang::targets;

static constexpr Builtin::Info BuiltinInfo[] = {
#define BUILTIN(ID, TYPE, ATTRS) \
{#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \
{#ID, TYPE, ATTRS, nullptr, HeaderDesc::HEADER, ALL_LANGUAGES},
#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \
{#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
#include "clang/Basic/BuiltinsNVPTX.def"
#include "clang/Basic/BuiltinsNVPTX.inc"
};

const char *const NVPTXTargetInfo::GCCRegNames[] = {"r0"};
Expand Down
2 changes: 1 addition & 1 deletion clang/test/CodeGen/builtins-nvptx.c
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ __device__ void exit() {
// NVVM intrinsics

// The idea is not to test all intrinsics, just that Clang is recognizing the
// builtins defined in BuiltinsNVPTX.def
// builtins defined in BuiltinsNVPTX.td
__device__ void nvvm_math(float f1, float f2, double d1, double d2) {
// CHECK: call float @llvm.nvvm.fmax.f
float t1 = __nvvm_fmax_f(f1, f2);
Expand Down
37 changes: 37 additions & 0 deletions clang/utils/TableGen/ClangBuiltinsEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,39 @@ class PrototypeParser {

void ParseType(StringRef T) {
T = T.trim();

auto ConsumeAddrSpace = [&]() -> std::optional<unsigned> {
T = T.trim();
if (!T.consume_back(">"))
return std::nullopt;

auto Open = T.find_last_of('<');
if (Open == StringRef::npos)
PrintFatalError(Loc, "Mismatched angle-brackets in type");

StringRef ArgStr = T.substr(Open + 1);
T = T.slice(0, Open);
if (!T.consume_back("address_space"))
PrintFatalError(Loc,
"Only `address_space<N>` supported as a parameterized "
"pointer or reference type qualifier");

unsigned Number = 0;
if (ArgStr.getAsInteger(10, Number))
PrintFatalError(
Loc, "Expected an integer argument to the address_space qualifier");
if (Number == 0)
PrintFatalError(Loc, "No need for a qualifier for address space `0`");
return Number;
};

if (T.consume_back("*")) {
// Pointers may have an address space qualifier immediately before them.
std::optional<unsigned> AS = ConsumeAddrSpace();
ParseType(T);
Type += "*";
if (AS)
Type += std::to_string(*AS);
} else if (T.consume_back("const")) {
ParseType(T);
Type += "C";
Expand All @@ -117,6 +147,13 @@ class PrototypeParser {
ParseType(T);
Type += "R";
} else if (T.consume_back("&")) {
// References may have an address space qualifier immediately before them.
std::optional<unsigned> AS = ConsumeAddrSpace();
ParseType(T);
Type += "&";
if (AS)
Type += std::to_string(*AS);
} else if (T.consume_back(")")) {
ParseType(T);
Type += "&";
} else if (EnableOpenCLLong && T.consume_front("long long")) {
Expand Down

0 comments on commit b968fd9

Please sign in to comment.