]> granicus.if.org Git - llvm/commitdiff
IR: Sort generic intrinsics before target specific ones
authorJustin Bogner <mail@justinbogner.com>
Fri, 15 Jul 2016 16:31:37 +0000 (16:31 +0000)
committerJustin Bogner <mail@justinbogner.com>
Fri, 15 Jul 2016 16:31:37 +0000 (16:31 +0000)
This splits out the intrinsic table such that generic intrinsics come
first and target specific intrinsics are grouped by target. From here
we can find out which target an intrinsic is for or differentiate
between generic and target intrinsics.

The motivation here is to make it easier to move target specific
intrinsic handling out of generic code.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@275575 91177308-0d34-0410-b5e6-96231b3b80d8

lib/IR/Function.cpp
utils/TableGen/CodeGenDAGPatterns.cpp
utils/TableGen/CodeGenDAGPatterns.h
utils/TableGen/CodeGenIntrinsics.h
utils/TableGen/CodeGenTarget.cpp
utils/TableGen/IntrinsicEmitter.cpp

index 42fb7649aa6bca9b2a88d6e704ba72c4f8653edc..e1223d0d03379d4d2f31eeef7a611c720d78eeee 100644 (file)
@@ -461,17 +461,45 @@ static const char * const IntrinsicNameTable[] = {
 #undef GET_INTRINSIC_NAME_TABLE
 };
 
+/// Table of per-target intrinsic name tables.
+#define GET_INTRINSIC_TARGET_DATA
+#include "llvm/IR/Intrinsics.gen"
+#undef GET_INTRINSIC_TARGET_DATA
+
+/// Find the segment of \c IntrinsicNameTable for intrinsics with the same
+/// target as \c Name, or the generic table if \c Name is not target specific.
+///
+/// Returns the relevant slice of \c IntrinsicNameTable
+static ArrayRef<const char *> findTargetSubtable(StringRef Name) {
+  assert(Name.startswith("llvm."));
+
+  ArrayRef<IntrinsicTargetInfo> Targets(TargetInfos);
+  // Drop "llvm." and take the first dotted component. That will be the target
+  // if this is target specific.
+  StringRef Target = Name.drop_front(5).split('.').first;
+  auto It = std::lower_bound(Targets.begin(), Targets.end(), Target,
+                             [](const IntrinsicTargetInfo &TI,
+                                StringRef Target) { return TI.Name < Target; });
+  // We've either found the target or just fall back to the generic set, which
+  // is always first.
+  const auto &TI = It != Targets.end() && It->Name == Target ? *It : Targets[0];
+  return makeArrayRef(&IntrinsicNameTable[1] + TI.Offset, TI.Count);
+}
+
 /// \brief This does the actual lookup of an intrinsic ID which
 /// matches the given function name.
 static Intrinsic::ID lookupIntrinsicID(const ValueName *ValName) {
   StringRef Name = ValName->getKey();
 
-  ArrayRef<const char *> NameTable(&IntrinsicNameTable[1],
-                                   std::end(IntrinsicNameTable));
+  ArrayRef<const char *> NameTable = findTargetSubtable(Name);
   int Idx = Intrinsic::lookupLLVMIntrinsicByName(NameTable, Name);
-  Intrinsic::ID ID = static_cast<Intrinsic::ID>(Idx + 1);
-  if (ID == Intrinsic::not_intrinsic)
-    return ID;
+  if (Idx == -1)
+    return Intrinsic::not_intrinsic;
+
+  // Intrinsic IDs correspond to the location in IntrinsicNameTable, but we have
+  // an index into a sub-table.
+  int Adjust = NameTable.data() - IntrinsicNameTable;
+  Intrinsic::ID ID = static_cast<Intrinsic::ID>(Idx + Adjust);
 
   // If the intrinsic is not overloaded, require an exact match. If it is
   // overloaded, require a prefix match.
index c2bb55f3dd42808838b04f692cad598c2123876c..307a95373c9d0802b6f0ec0033ca2d6b7345f46a 100644 (file)
@@ -2392,8 +2392,8 @@ void TreePattern::dump() const { print(errs()); }
 CodeGenDAGPatterns::CodeGenDAGPatterns(RecordKeeper &R) :
   Records(R), Target(R) {
 
-  Intrinsics = LoadIntrinsics(Records, false);
-  TgtIntrinsics = LoadIntrinsics(Records, true);
+  Intrinsics = CodeGenIntrinsicTable(Records, false);
+  TgtIntrinsics = CodeGenIntrinsicTable(Records, true);
   ParseNodeInfo();
   ParseNodeTransforms();
   ParseComplexPatterns();
index 76c9cefea50fd8f86238580094a10c8df8906130..819c4b8492cb25c686e63f89e1aaa9487707732a 100644 (file)
@@ -716,8 +716,8 @@ public:
 class CodeGenDAGPatterns {
   RecordKeeper &Records;
   CodeGenTarget Target;
-  std::vector<CodeGenIntrinsic> Intrinsics;
-  std::vector<CodeGenIntrinsic> TgtIntrinsics;
+  CodeGenIntrinsicTable Intrinsics;
+  CodeGenIntrinsicTable TgtIntrinsics;
 
   std::map<Record*, SDNodeInfo, LessRecordByID> SDNodes;
   std::map<Record*, std::pair<Record*, std::string>, LessRecordByID> SDNodeXForms;
index 76554a52a15c14899fb0be479a8d81b2898872f5..ea3ec67d62eddcbe2b21ec617ec50a3324167eca 100644 (file)
@@ -114,9 +114,27 @@ struct CodeGenIntrinsic {
   CodeGenIntrinsic(Record *R);
 };
 
-/// Read all of the intrinsics defined in the specified .td file.
-std::vector<CodeGenIntrinsic> LoadIntrinsics(const RecordKeeper &RC,
-                                             bool TargetOnly);
+class CodeGenIntrinsicTable {
+  std::vector<CodeGenIntrinsic> Intrinsics;
+
+public:
+  struct TargetSet {
+    std::string Name;
+    size_t Offset;
+    size_t Count;
+  };
+  std::vector<TargetSet> Targets;
+
+  explicit CodeGenIntrinsicTable(const RecordKeeper &RC, bool TargetOnly);
+  CodeGenIntrinsicTable() = default;
+
+  bool empty() const { return Intrinsics.empty(); }
+  size_t size() const { return Intrinsics.size(); }
+  CodeGenIntrinsic &operator[](size_t Pos) { return Intrinsics[Pos]; }
+  const CodeGenIntrinsic &operator[](size_t Pos) const {
+    return Intrinsics[Pos];
+  }
+};
 }
 
 #endif
index 08bb332b1359dcc15949f3d162413f9b790b1b4c..245b9eeeed858cc786efec8b8d08fb86c17ab870 100644 (file)
@@ -426,23 +426,29 @@ ComplexPattern::ComplexPattern(Record *R) {
 // CodeGenIntrinsic Implementation
 //===----------------------------------------------------------------------===//
 
-std::vector<CodeGenIntrinsic> llvm::LoadIntrinsics(const RecordKeeper &RC,
-                                                   bool TargetOnly) {
+CodeGenIntrinsicTable::CodeGenIntrinsicTable(const RecordKeeper &RC,
+                                             bool TargetOnly) {
   std::vector<Record*> Defs = RC.getAllDerivedDefinitions("Intrinsic");
 
-  std::vector<CodeGenIntrinsic> Result;
-  Result.reserve(Defs.size());
+  Intrinsics.reserve(Defs.size());
 
   for (unsigned I = 0, e = Defs.size(); I != e; ++I) {
     bool isTarget = Defs[I]->getValueAsBit("isTarget");
     if (isTarget == TargetOnly)
-      Result.push_back(CodeGenIntrinsic(Defs[I]));
+      Intrinsics.push_back(CodeGenIntrinsic(Defs[I]));
   }
-  std::sort(Result.begin(), Result.end(),
-            [](const CodeGenIntrinsic& LHS, const CodeGenIntrinsic& RHS) {
-              return LHS.Name < RHS.Name;
+  std::sort(Intrinsics.begin(), Intrinsics.end(),
+            [](const CodeGenIntrinsic &LHS, const CodeGenIntrinsic &RHS) {
+              return std::tie(LHS.TargetPrefix, LHS.Name) <
+                     std::tie(RHS.TargetPrefix, RHS.Name);
             });
-  return Result;
+  Targets.push_back({"", 0, 0});
+  for (size_t I = 0, E = Intrinsics.size(); I < E; ++I)
+    if (Intrinsics[I].TargetPrefix != Targets.back().Name) {
+      Targets.back().Count = I - Targets.back().Offset;
+      Targets.push_back({Intrinsics[I].TargetPrefix, I, 0});
+    }
+  Targets.back().Count = Intrinsics.size() - Targets.back().Offset;
 }
 
 CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
index 062d25c6a4e929c64a183e67bb0947bd338eb6cb..a676159e494b9add1d38b35519a21550a3deaf4f 100644 (file)
@@ -38,19 +38,16 @@ public:
 
   void EmitPrefix(raw_ostream &OS);
 
-  void EmitEnumInfo(const std::vector<CodeGenIntrinsic> &Ints,
-                    raw_ostream &OS);
-
-  void EmitIntrinsicToNameTable(const std::vector<CodeGenIntrinsic> &Ints,
+  void EmitEnumInfo(const CodeGenIntrinsicTable &Ints, raw_ostream &OS);
+  void EmitTargetInfo(const CodeGenIntrinsicTable &Ints, raw_ostream &OS);
+  void EmitIntrinsicToNameTable(const CodeGenIntrinsicTable &Ints,
                                 raw_ostream &OS);
-  void EmitIntrinsicToOverloadTable(const std::vector<CodeGenIntrinsic> &Ints,
+  void EmitIntrinsicToOverloadTable(const CodeGenIntrinsicTable &Ints,
                                     raw_ostream &OS);
-  void EmitGenerator(const std::vector<CodeGenIntrinsic> &Ints,
-                     raw_ostream &OS);
-  void EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints,
-                      raw_ostream &OS);
-  void EmitIntrinsicToBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints,
-                                 bool IsGCC, raw_ostream &OS);
+  void EmitGenerator(const CodeGenIntrinsicTable &Ints, raw_ostream &OS);
+  void EmitAttributes(const CodeGenIntrinsicTable &Ints, raw_ostream &OS);
+  void EmitIntrinsicToBuiltinMap(const CodeGenIntrinsicTable &Ints, bool IsGCC,
+                                 raw_ostream &OS);
   void EmitSuffix(raw_ostream &OS);
 };
 } // End anonymous namespace
@@ -62,7 +59,7 @@ public:
 void IntrinsicEmitter::run(raw_ostream &OS) {
   emitSourceFileHeader("Intrinsic Function Source Fragment", OS);
 
-  std::vector<CodeGenIntrinsic> Ints = LoadIntrinsics(Records, TargetOnly);
+  CodeGenIntrinsicTable Ints(Records, TargetOnly);
 
   if (TargetOnly && !Ints.empty())
     TargetPrefix = Ints[0].TargetPrefix;
@@ -72,6 +69,9 @@ void IntrinsicEmitter::run(raw_ostream &OS) {
   // Emit the enum information.
   EmitEnumInfo(Ints, OS);
 
+  // Emit the target metadata.
+  EmitTargetInfo(Ints, OS);
+
   // Emit the intrinsic ID -> name table.
   EmitIntrinsicToNameTable(Ints, OS);
 
@@ -114,7 +114,7 @@ void IntrinsicEmitter::EmitSuffix(raw_ostream &OS) {
         "#endif\n\n";
 }
 
-void IntrinsicEmitter::EmitEnumInfo(const std::vector<CodeGenIntrinsic> &Ints,
+void IntrinsicEmitter::EmitEnumInfo(const CodeGenIntrinsicTable &Ints,
                                     raw_ostream &OS) {
   OS << "// Enum values for Intrinsics.h\n";
   OS << "#ifdef GET_INTRINSIC_ENUM_VALUES\n";
@@ -128,9 +128,25 @@ void IntrinsicEmitter::EmitEnumInfo(const std::vector<CodeGenIntrinsic> &Ints,
   OS << "#endif\n\n";
 }
 
-void IntrinsicEmitter::
-EmitIntrinsicToNameTable(const std::vector<CodeGenIntrinsic> &Ints,
-                         raw_ostream &OS) {
+void IntrinsicEmitter::EmitTargetInfo(const CodeGenIntrinsicTable &Ints,
+                                    raw_ostream &OS) {
+  OS << "// Target mapping\n";
+  OS << "#ifdef GET_INTRINSIC_TARGET_DATA\n";
+  OS << "struct IntrinsicTargetInfo {\n"
+     << "  StringRef Name;\n"
+     << "  size_t Offset;\n"
+     << "  size_t Count;\n"
+     << "};\n";
+  OS << "static const IntrinsicTargetInfo TargetInfos[] = {\n";
+  for (auto Target : Ints.Targets)
+    OS << "  {\"" << Target.Name << "\", " << Target.Offset << ", "
+       << Target.Count << "},\n";
+  OS << "};\n";
+  OS << "#endif\n\n";
+}
+
+void IntrinsicEmitter::EmitIntrinsicToNameTable(
+    const CodeGenIntrinsicTable &Ints, raw_ostream &OS) {
   OS << "// Intrinsic ID to name table\n";
   OS << "#ifdef GET_INTRINSIC_NAME_TABLE\n";
   OS << "  // Note that entry #0 is the invalid intrinsic!\n";
@@ -139,9 +155,8 @@ EmitIntrinsicToNameTable(const std::vector<CodeGenIntrinsic> &Ints,
   OS << "#endif\n\n";
 }
 
-void IntrinsicEmitter::
-EmitIntrinsicToOverloadTable(const std::vector<CodeGenIntrinsic> &Ints,
-                         raw_ostream &OS) {
+void IntrinsicEmitter::EmitIntrinsicToOverloadTable(
+    const CodeGenIntrinsicTable &Ints, raw_ostream &OS) {
   OS << "// Intrinsic ID to overload bitset\n";
   OS << "#ifdef GET_INTRINSIC_OVERLOAD_TABLE\n";
   OS << "static const uint8_t OTable[] = {\n";
@@ -363,7 +378,7 @@ static void printIITEntry(raw_ostream &OS, unsigned char X) {
   OS << (unsigned)X;
 }
 
-void IntrinsicEmitter::EmitGenerator(const std::vector<CodeGenIntrinsic> &Ints,
+void IntrinsicEmitter::EmitGenerator(const CodeGenIntrinsicTable &Ints,
                                      raw_ostream &OS) {
   // If we can compute a 32-bit fixed encoding for this intrinsic, do so and
   // capture it in this vector, otherwise store a ~0U.
@@ -474,8 +489,8 @@ struct AttributeComparator {
 } // End anonymous namespace
 
 /// EmitAttributes - This emits the Intrinsic::getAttributes method.
-void IntrinsicEmitter::
-EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) {
+void IntrinsicEmitter::EmitAttributes(const CodeGenIntrinsicTable &Ints,
+                                      raw_ostream &OS) {
   OS << "// Add parameter attributes that are not common to all intrinsics.\n";
   OS << "#ifdef GET_INTRINSIC_ATTRIBUTES\n";
   if (TargetOnly)
@@ -670,7 +685,7 @@ EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) {
 }
 
 void IntrinsicEmitter::EmitIntrinsicToBuiltinMap(
-    const std::vector<CodeGenIntrinsic> &Ints, bool IsGCC, raw_ostream &OS) {
+    const CodeGenIntrinsicTable &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;