[llvm] r258897 - [llvm-tblgen] Avoid StringMatcher for GCC and MS builtin names

Reid Kleckner via llvm-commits llvm-commits at lists.llvm.org
Tue Jan 26 17:43:12 PST 2016


Author: rnk
Date: Tue Jan 26 19:43:12 2016
New Revision: 258897

URL: http://llvm.org/viewvc/llvm-project?rev=258897&view=rev
Log:
[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.

Modified:
    llvm/trunk/include/llvm/TableGen/StringToOffsetTable.h
    llvm/trunk/lib/Target/AMDGPU/AMDGPUIntrinsicInfo.cpp
    llvm/trunk/utils/TableGen/IntrinsicEmitter.cpp

Modified: llvm/trunk/include/llvm/TableGen/StringToOffsetTable.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/TableGen/StringToOffsetTable.h?rev=258897&r1=258896&r2=258897&view=diff
==============================================================================
--- llvm/trunk/include/llvm/TableGen/StringToOffsetTable.h (original)
+++ llvm/trunk/include/llvm/TableGen/StringToOffsetTable.h Tue Jan 26 19:43:12 2016
@@ -76,6 +76,26 @@ public:
     }
     O << "\"";
   }
+
+  /// Emit the string using character literals. MSVC has a limitation that
+  /// string literals cannot be longer than 64K.
+  void EmitCharArray(raw_ostream &O) {
+    assert(AggregateString.find(')') == std::string::npos &&
+           "can't emit raw string with closing parens");
+    int Count = 0;
+    O << ' ';
+    for (char C : AggregateString) {
+      O << " \'";
+      O.write_escaped(StringRef(&C, 1));
+      O << "\',";
+      Count++;
+      if (Count > 14) {
+        O << "\n ";
+        Count = 0;
+      }
+    }
+    O << '\n';
+  }
 };
 
 } // end namespace llvm

Modified: llvm/trunk/lib/Target/AMDGPU/AMDGPUIntrinsicInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AMDGPU/AMDGPUIntrinsicInfo.cpp?rev=258897&r1=258896&r2=258897&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AMDGPU/AMDGPUIntrinsicInfo.cpp (original)
+++ llvm/trunk/lib/Target/AMDGPU/AMDGPUIntrinsicInfo.cpp Tue Jan 26 19:43:12 2016
@@ -20,10 +20,6 @@
 
 using namespace llvm;
 
-#define GET_LLVM_INTRINSIC_FOR_GCC_BUILTIN
-#include "AMDGPUGenIntrinsics.inc"
-#undef GET_LLVM_INTRINSIC_FOR_GCC_BUILTIN
-
 AMDGPUIntrinsicInfo::AMDGPUIntrinsicInfo()
     : TargetIntrinsicInfo() {}
 
@@ -62,8 +58,7 @@ unsigned AMDGPUIntrinsicInfo::lookupName
                : 0;
   }
 
-  // Fall back on GCC builtin names.
-  return getIntrinsicForGCCBuiltin("AMDGPU", NameData);
+  return 0;
 }
 
 bool AMDGPUIntrinsicInfo::isOverloaded(unsigned id) const {

Modified: llvm/trunk/utils/TableGen/IntrinsicEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/IntrinsicEmitter.cpp?rev=258897&r1=258896&r2=258897&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/IntrinsicEmitter.cpp (original)
+++ llvm/trunk/utils/TableGen/IntrinsicEmitter.cpp Tue Jan 26 19:43:12 2016
@@ -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 &
   // 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<CodeGen
   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::
     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::
   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);
 }




More information about the llvm-commits mailing list