summaryrefslogtreecommitdiffstats
path: root/llvm/utils/TableGen/IntrinsicEmitter.cpp
diff options
context:
space:
mode:
authorReid Kleckner <rnk@google.com>2016-01-27 01:43:12 +0000
committerReid Kleckner <rnk@google.com>2016-01-27 01:43:12 +0000
commit5b4637141eb4f1e1d01e58699f90541a480b5a96 (patch)
treeb0625bbd2ce32dcc287a89f2e2746207a2f7785b /llvm/utils/TableGen/IntrinsicEmitter.cpp
parent3075134739edc9cd16d5ca7b9a78d8b4d5fbff3e (diff)
downloadbcm5719-llvm-5b4637141eb4f1e1d01e58699f90541a480b5a96.tar.gz
bcm5719-llvm-5b4637141eb4f1e1d01e58699f90541a480b5a96.zip
[llvm-tblgen] Avoid StringMatcher for GCC and MS builtin names
This brings the compile time of Function.cpp from ~40s down to ~4s for me locally. It also shaves off about 400KB of object file size in a release+asserts build. I also realized that the AMDGPU backend does not have any GCC builtin names to match, so the extra lookup was a no-op. I removed it to silence a zero-length string table array warning. There should be no functional change here. This change really ends the story of PR11951. llvm-svn: 258897
Diffstat (limited to 'llvm/utils/TableGen/IntrinsicEmitter.cpp')
-rw-r--r--llvm/utils/TableGen/IntrinsicEmitter.cpp147
1 files changed, 56 insertions, 91 deletions
diff --git a/llvm/utils/TableGen/IntrinsicEmitter.cpp b/llvm/utils/TableGen/IntrinsicEmitter.cpp
index c4e461453b7..dcb70e19ba8 100644
--- a/llvm/utils/TableGen/IntrinsicEmitter.cpp
+++ b/llvm/utils/TableGen/IntrinsicEmitter.cpp
@@ -20,6 +20,7 @@
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/StringMatcher.h"
#include "llvm/TableGen/TableGenBackend.h"
+#include "llvm/TableGen/StringToOffsetTable.h"
#include <algorithm>
using namespace llvm;
@@ -48,10 +49,8 @@ public:
raw_ostream &OS);
void EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints,
raw_ostream &OS);
- void EmitIntrinsicToGCCBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints,
- raw_ostream &OS);
- void EmitIntrinsicToMSBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints,
- raw_ostream &OS);
+ void EmitIntrinsicToBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints,
+ bool IsGCC, raw_ostream &OS);
void EmitSuffix(raw_ostream &OS);
};
} // End anonymous namespace
@@ -85,11 +84,14 @@ void IntrinsicEmitter::run(raw_ostream &OS) {
// Emit the intrinsic parameter attributes.
EmitAttributes(Ints, OS);
- // Emit code to translate GCC builtins into LLVM intrinsics.
- EmitIntrinsicToGCCBuiltinMap(Ints, OS);
+ // Individual targets don't need GCC builtin name mappings.
+ if (!TargetOnly) {
+ // Emit code to translate GCC builtins into LLVM intrinsics.
+ EmitIntrinsicToBuiltinMap(Ints, true, OS);
- // Emit code to translate MS builtins into LLVM intrinsics.
- EmitIntrinsicToMSBuiltinMap(Ints, OS);
+ // Emit code to translate MS builtins into LLVM intrinsics.
+ EmitIntrinsicToBuiltinMap(Ints, false, OS);
+ }
EmitSuffix(OS);
}
@@ -644,56 +646,57 @@ EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) {
OS << "#endif // GET_INTRINSIC_ATTRIBUTES\n\n";
}
-/// EmitTargetBuiltins - All of the builtins in the specified map are for the
-/// same target, and we already checked it.
-static void EmitTargetBuiltins(const std::map<std::string, std::string> &BIM,
- const std::string &TargetPrefix,
- raw_ostream &OS) {
-
- std::vector<StringMatcher::StringPair> Results;
-
- for (std::map<std::string, std::string>::const_iterator I = BIM.begin(),
- E = BIM.end(); I != E; ++I) {
- std::string ResultCode =
- "return " + TargetPrefix + "Intrinsic::" + I->second + ";";
- Results.emplace_back(I->first, ResultCode);
- }
-
- StringMatcher("BuiltinName", Results, OS).Emit();
-}
-
-
-void IntrinsicEmitter::
-EmitIntrinsicToGCCBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints,
- raw_ostream &OS) {
- typedef std::map<std::string, std::map<std::string, std::string> > BIMTy;
+void IntrinsicEmitter::EmitIntrinsicToBuiltinMap(
+ const std::vector<CodeGenIntrinsic> &Ints, bool IsGCC, raw_ostream &OS) {
+ StringRef CompilerName = (IsGCC ? "GCC" : "MS");
+ typedef std::map<std::string, std::map<std::string, std::string>> BIMTy;
BIMTy BuiltinMap;
+ StringToOffsetTable Table;
for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
- if (!Ints[i].GCCBuiltinName.empty()) {
+ const std::string &BuiltinName =
+ IsGCC ? Ints[i].GCCBuiltinName : Ints[i].MSBuiltinName;
+ if (!BuiltinName.empty()) {
// Get the map for this target prefix.
- std::map<std::string, std::string> &BIM =BuiltinMap[Ints[i].TargetPrefix];
+ std::map<std::string, std::string> &BIM =
+ BuiltinMap[Ints[i].TargetPrefix];
- if (!BIM.insert(std::make_pair(Ints[i].GCCBuiltinName,
- Ints[i].EnumName)).second)
+ if (!BIM.insert(std::make_pair(BuiltinName, Ints[i].EnumName)).second)
PrintFatalError("Intrinsic '" + Ints[i].TheDef->getName() +
- "': duplicate GCC builtin name!");
+ "': duplicate " + CompilerName + " builtin name!");
+ Table.GetOrAddStringOffset(BuiltinName);
}
}
- OS << "// Get the LLVM intrinsic that corresponds to a GCC builtin.\n";
- OS << "// This is used by the C front-end. The GCC builtin name is passed\n";
+ OS << "// Get the LLVM intrinsic that corresponds to a builtin.\n";
+ OS << "// This is used by the C front-end. The builtin name is passed\n";
OS << "// in as BuiltinName, and a target prefix (e.g. 'ppc') is passed\n";
OS << "// in as TargetPrefix. The result is assigned to 'IntrinsicID'.\n";
- OS << "#ifdef GET_LLVM_INTRINSIC_FOR_GCC_BUILTIN\n";
+ OS << "#ifdef GET_LLVM_INTRINSIC_FOR_" << CompilerName << "_BUILTIN\n";
if (TargetOnly) {
OS << "static " << TargetPrefix << "Intrinsic::ID "
- << "getIntrinsicForGCCBuiltin(const char "
+ << "getIntrinsicFor" << CompilerName << "Builtin(const char "
<< "*TargetPrefixStr, const char *BuiltinNameStr) {\n";
} else {
- OS << "Intrinsic::ID Intrinsic::getIntrinsicForGCCBuiltin(const char "
+ OS << "Intrinsic::ID Intrinsic::getIntrinsicFor" << CompilerName
+ << "Builtin(const char "
<< "*TargetPrefixStr, const char *BuiltinNameStr) {\n";
}
+ OS << " static const char BuiltinNames[] = {\n";
+ Table.EmitCharArray(OS);
+ OS << " };\n\n";
+
+ OS << " struct BuiltinEntry {\n";
+ OS << " Intrinsic::ID IntrinID;\n";
+ OS << " unsigned StrTabOffset;\n";
+ OS << " const char *getName() const {\n";
+ OS << " return &BuiltinNames[StrTabOffset];\n";
+ OS << " }\n";
+ OS << " bool operator<(const char *RHS) const {\n";
+ OS << " return strcmp(getName(), RHS) < 0;\n";
+ OS << " }\n";
+ OS << " };\n";
+
OS << " StringRef BuiltinName(BuiltinNameStr);\n";
OS << " StringRef TargetPrefix(TargetPrefixStr);\n\n";
@@ -708,7 +711,18 @@ EmitIntrinsicToGCCBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints,
OS << "{\n";
// Emit the comparisons for this target prefix.
- EmitTargetBuiltins(I->second, TargetPrefix, OS);
+ OS << " static const BuiltinEntry " << I->first << "Names[] = {\n";
+ for (const auto &P : I->second) {
+ OS << " {Intrinsic::" << P.second << ", "
+ << Table.GetOrAddStringOffset(P.first) << "}, // " << P.first << "\n";
+ }
+ OS << " };\n";
+ OS << " auto I = std::lower_bound(std::begin(" << I->first << "Names),\n";
+ OS << " std::end(" << I->first << "Names),\n";
+ OS << " BuiltinNameStr);\n";
+ OS << " if (I != std::end(" << I->first << "Names) &&\n";
+ OS << " strcmp(I->getName(), BuiltinNameStr) == 0)\n";
+ OS << " return I->IntrinID;\n";
OS << " }\n";
}
OS << " return ";
@@ -719,55 +733,6 @@ EmitIntrinsicToGCCBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints,
OS << "#endif\n\n";
}
-void IntrinsicEmitter::
-EmitIntrinsicToMSBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints,
- raw_ostream &OS) {
- std::map<std::string, std::map<std::string, std::string>> TargetBuiltins;
-
- for (const auto &Intrinsic : Ints) {
- if (Intrinsic.MSBuiltinName.empty())
- continue;
-
- auto &Builtins = TargetBuiltins[Intrinsic.TargetPrefix];
- if (!Builtins.insert(std::make_pair(Intrinsic.MSBuiltinName,
- Intrinsic.EnumName)).second)
- PrintFatalError("Intrinsic '" + Intrinsic.TheDef->getName() + "': "
- "duplicate MS builtin name!");
- }
-
- OS << "// Get the LLVM intrinsic that corresponds to a MS builtin.\n"
- "// This is used by the C front-end. The MS builtin name is passed\n"
- "// in as a BuiltinName, and a target prefix (e.g. 'arm') is passed\n"
- "// in as a TargetPrefix. The result is assigned to 'IntrinsicID'.\n"
- "#ifdef GET_LLVM_INTRINSIC_FOR_MS_BUILTIN\n";
-
- OS << (TargetOnly ? "static " + TargetPrefix : "") << "Intrinsic::ID "
- << (TargetOnly ? "" : "Intrinsic::")
- << "getIntrinsicForMSBuiltin(const char *TP, const char *BN) {\n";
- OS << " StringRef BuiltinName(BN);\n"
- " StringRef TargetPrefix(TP);\n"
- "\n";
-
- for (const auto &Builtins : TargetBuiltins) {
- OS << " ";
- if (Builtins.first.empty())
- OS << "/* Target Independent Builtins */ ";
- else
- OS << "if (TargetPrefix == \"" << Builtins.first << "\") ";
- OS << "{\n";
- EmitTargetBuiltins(Builtins.second, TargetPrefix, OS);
- OS << "}";
- }
-
- OS << " return ";
- if (!TargetPrefix.empty())
- OS << "(" << TargetPrefix << "Intrinsic::ID)";
- OS << "Intrinsic::not_intrinsic;\n";
- OS << "}\n";
-
- OS << "#endif\n\n";
-}
-
void llvm::EmitIntrinsics(RecordKeeper &RK, raw_ostream &OS, bool TargetOnly) {
IntrinsicEmitter(RK, TargetOnly).run(OS);
}
OpenPOWER on IntegriCloud