#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.
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();
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;
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
// 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) {
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
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;
// Emit the enum information.
EmitEnumInfo(Ints, OS);
+ // Emit the target metadata.
+ EmitTargetInfo(Ints, OS);
+
// Emit the intrinsic ID -> name table.
EmitIntrinsicToNameTable(Ints, 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";
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";
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";
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.
} // 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)
}
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;