[clang] 0e56b0f - [OpenCL] Group builtin functions by prototype
Sven van Haastregt via cfe-commits
cfe-commits at lists.llvm.org
Tue Nov 5 02:45:14 PST 2019
Author: Sven van Haastregt
Date: 2019-11-05T10:26:47Z
New Revision: 0e56b0f94bfc683c5a95e96784cfc9229a730bc8
URL: https://github.com/llvm/llvm-project/commit/0e56b0f94bfc683c5a95e96784cfc9229a730bc8
DIFF: https://github.com/llvm/llvm-project/commit/0e56b0f94bfc683c5a95e96784cfc9229a730bc8.diff
LOG: [OpenCL] Group builtin functions by prototype
The TableGen-generated file containing the function definitions can be
reorganized to save some memory in the Clang binary. Functions having
the same prototype(s) will point to a shared list of prototype(s).
Patch by Pierre Gondois and Sven van Haastregt.
Differential Revision: https://reviews.llvm.org/D63557
Added:
Modified:
clang/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp
Removed:
################################################################################
diff --git a/clang/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp b/clang/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp
index 983e267ce9ac..4042c17c5296 100644
--- a/clang/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp
+++ b/clang/utils/TableGen/ClangOpenCLBuiltinEmitter.cpp
@@ -69,6 +69,13 @@
using namespace llvm;
namespace {
+
+// A list of signatures that are shared by one or more builtin functions.
+struct BuiltinTableEntries {
+ SmallVector<StringRef, 4> Names;
+ std::vector<std::pair<const Record *, unsigned>> Signatures;
+};
+
class BuiltinNameEmitter {
public:
BuiltinNameEmitter(RecordKeeper &Records, raw_ostream &OS)
@@ -79,6 +86,9 @@ class BuiltinNameEmitter {
void Emit();
private:
+ // A list of indices into the builtin function table.
+ using BuiltinIndexListTy = SmallVector<unsigned, 11>;
+
// Contains OpenCL builtin functions and related information, stored as
// Record instances. They are coming from the associated TableGen file.
RecordKeeper &Records;
@@ -106,6 +116,23 @@ class BuiltinNameEmitter {
// FctOverloadMap and TypeMap.
void GetOverloads();
+ // Compare two lists of signatures and check that e.g. the OpenCL version,
+ // function attributes, and extension are equal for each signature.
+ // \param Candidate (in) Entry in the SignatureListMap to check.
+ // \param SignatureList (in) List of signatures of the considered function.
+ // \returns true if the two lists of signatures are identical.
+ bool CanReuseSignature(
+ BuiltinIndexListTy *Candidate,
+ std::vector<std::pair<const Record *, unsigned>> &SignatureList);
+
+ // Group functions with the same list of signatures by populating the
+ // SignatureListMap.
+ // Some builtin functions have the same list of signatures, for example the
+ // "sin" and "cos" functions. To save space in the BuiltinTable, the
+ // "isOpenCLBuiltin" function will have the same output for these two
+ // function names.
+ void GroupBySignature();
+
// Emit the TypeTable containing all types used by OpenCL builtins.
void EmitTypeTable();
@@ -170,6 +197,24 @@ class BuiltinNameEmitter {
// Same as TypeList, but for generic types only.
std::vector<const Record *> GenTypeList;
+
+ // Map an ordered vector of signatures to their original Record instances,
+ // and to a list of function names that share these signatures.
+ //
+ // For example, suppose the "cos" and "sin" functions have only three
+ // signatures, and these signatures are at index Ix in the SignatureTable:
+ // cos | sin | Signature | Index
+ // float cos(float) | float sin(float) | Signature1 | I1
+ // double cos(double) | double sin(double) | Signature2 | I2
+ // half cos(half) | half sin(half) | Signature3 | I3
+ //
+ // Then we will create a mapping of the vector of signatures:
+ // SignatureListMap[<I1, I2, I3>] = <
+ // <"cos", "sin">,
+ // <Signature1, Signature2, Signature3>>
+ // The function "tan", having the same signatures, would be mapped to the
+ // same entry (<I1, I2, I3>).
+ MapVector<BuiltinIndexListTy *, BuiltinTableEntries> SignatureListMap;
};
} // namespace
@@ -183,6 +228,7 @@ void BuiltinNameEmitter::Emit() {
EmitDeclarations();
GetOverloads();
+ GroupBySignature();
// Emit tables.
EmitTypeTable();
@@ -408,11 +454,15 @@ void BuiltinNameEmitter::EmitBuiltinTable() {
unsigned Index = 0;
OS << "static const OpenCLBuiltinStruct BuiltinTable[] = {\n";
- for (const auto &FOM : FctOverloadMap) {
+ for (const auto &SLM : SignatureListMap) {
- OS << " // " << (Index + 1) << ": " << FOM.first << "\n";
+ OS << " // " << (Index + 1) << ": ";
+ for (const auto &Name : SLM.second.Names) {
+ OS << Name << ", ";
+ }
+ OS << "\n";
- for (const auto &Overload : FOM.second) {
+ for (const auto &Overload : SLM.second.Signatures) {
OS << " { " << Overload.second << ", "
<< Overload.first->getValueAsListOfDefs("Signature").size() << ", "
<< (Overload.first->getValueAsBit("IsPure")) << ", "
@@ -428,19 +478,92 @@ void BuiltinNameEmitter::EmitBuiltinTable() {
OS << "};\n\n";
}
+bool BuiltinNameEmitter::CanReuseSignature(
+ BuiltinIndexListTy *Candidate,
+ std::vector<std::pair<const Record *, unsigned>> &SignatureList) {
+ assert(Candidate->size() == SignatureList.size() &&
+ "signature lists should have the same size");
+
+ auto &CandidateSigs =
+ SignatureListMap.find(Candidate)->second.Signatures;
+ for (unsigned Index = 0; Index < Candidate->size(); Index++) {
+ const Record *Rec = SignatureList[Index].first;
+ const Record *Rec2 = CandidateSigs[Index].first;
+ if (Rec->getValueAsBit("IsPure") == Rec2->getValueAsBit("IsPure") &&
+ Rec->getValueAsBit("IsConst") == Rec2->getValueAsBit("IsConst") &&
+ Rec->getValueAsBit("IsConv") == Rec2->getValueAsBit("IsConv") &&
+ Rec->getValueAsDef("MinVersion")->getValueAsInt("ID") ==
+ Rec2->getValueAsDef("MinVersion")->getValueAsInt("ID") &&
+ Rec->getValueAsDef("MaxVersion")->getValueAsInt("ID") ==
+ Rec2->getValueAsDef("MaxVersion")->getValueAsInt("ID") &&
+ Rec->getValueAsString("Extension") ==
+ Rec2->getValueAsString("Extension")) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void BuiltinNameEmitter::GroupBySignature() {
+ // List of signatures known to be emitted.
+ std::vector<BuiltinIndexListTy *> KnownSignatures;
+
+ for (auto &Fct : FctOverloadMap) {
+ bool FoundReusableSig = false;
+
+ // Gather all signatures for the current function.
+ auto *CurSignatureList = new BuiltinIndexListTy();
+ for (const auto &Signature : Fct.second) {
+ CurSignatureList->push_back(Signature.second);
+ }
+ // Sort the list to facilitate future comparisons.
+ std::sort(CurSignatureList->begin(), CurSignatureList->end());
+
+ // Check if we have already seen another function with the same list of
+ // signatures. If so, just add the name of the function.
+ for (auto *Candidate : KnownSignatures) {
+ if (Candidate->size() == CurSignatureList->size() &&
+ *Candidate == *CurSignatureList) {
+ if (CanReuseSignature(Candidate, Fct.second)) {
+ SignatureListMap.find(Candidate)->second.Names.push_back(Fct.first);
+ FoundReusableSig = true;
+ }
+ }
+ }
+
+ if (FoundReusableSig) {
+ delete CurSignatureList;
+ } else {
+ // Add a new entry.
+ SignatureListMap[CurSignatureList] = {
+ SmallVector<StringRef, 4>(1, Fct.first), Fct.second};
+ KnownSignatures.push_back(CurSignatureList);
+ }
+ }
+
+ for (auto *I : KnownSignatures) {
+ delete I;
+ }
+}
+
void BuiltinNameEmitter::EmitStringMatcher() {
std::vector<StringMatcher::StringPair> ValidBuiltins;
unsigned CumulativeIndex = 1;
- for (auto &i : FctOverloadMap) {
- auto &Ov = i.second;
- std::string RetStmt;
- raw_string_ostream SS(RetStmt);
- SS << "return std::make_pair(" << CumulativeIndex << ", " << Ov.size()
- << ");";
- SS.flush();
- CumulativeIndex += Ov.size();
-
- ValidBuiltins.push_back(StringMatcher::StringPair(i.first, RetStmt));
+
+ for (const auto &SLM : SignatureListMap) {
+ const auto &Ovl = SLM.second.Signatures;
+
+ // A single signature list may be used by
diff erent builtins. Return the
+ // same <index, length> pair for each of those builtins.
+ for (const auto &FctName : SLM.second.Names) {
+ std::string RetStmt;
+ raw_string_ostream SS(RetStmt);
+ SS << "return std::make_pair(" << CumulativeIndex << ", " << Ovl.size()
+ << ");";
+ SS.flush();
+ ValidBuiltins.push_back(StringMatcher::StringPair(FctName, RetStmt));
+ }
+ CumulativeIndex += Ovl.size();
}
OS << R"(
More information about the cfe-commits
mailing list