llvm.org GIT mirror llvm / a3d02c7
IR: Sort generic intrinsics before target specific ones 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 Justin Bogner 4 years ago
6 changed file(s) with 112 addition(s) and 45 deletion(s). Raw diff Collapse all Expand all
460460 #undef GET_INTRINSIC_NAME_TABLE
461461 };
462462
463 /// Table of per-target intrinsic name tables.
464 #define GET_INTRINSIC_TARGET_DATA
465 #include "llvm/IR/Intrinsics.gen"
466 #undef GET_INTRINSIC_TARGET_DATA
467
468 /// Find the segment of \c IntrinsicNameTable for intrinsics with the same
469 /// target as \c Name, or the generic table if \c Name is not target specific.
470 ///
471 /// Returns the relevant slice of \c IntrinsicNameTable
472 static ArrayRef findTargetSubtable(StringRef Name) {
473 assert(Name.startswith("llvm."));
474
475 ArrayRef Targets(TargetInfos);
476 // Drop "llvm." and take the first dotted component. That will be the target
477 // if this is target specific.
478 StringRef Target = Name.drop_front(5).split('.').first;
479 auto It = std::lower_bound(Targets.begin(), Targets.end(), Target,
480 [](const IntrinsicTargetInfo &TI,
481 StringRef Target) { return TI.Name < Target; });
482 // We've either found the target or just fall back to the generic set, which
483 // is always first.
484 const auto &TI = It != Targets.end() && It->Name == Target ? *It : Targets[0];
485 return makeArrayRef(&IntrinsicNameTable[1] + TI.Offset, TI.Count);
486 }
487
463488 /// \brief This does the actual lookup of an intrinsic ID which
464489 /// matches the given function name.
465490 static Intrinsic::ID lookupIntrinsicID(const ValueName *ValName) {
466491 StringRef Name = ValName->getKey();
467492
468 ArrayRef NameTable(&IntrinsicNameTable[1],
469 std::end(IntrinsicNameTable));
493 ArrayRef NameTable = findTargetSubtable(Name);
470494 int Idx = Intrinsic::lookupLLVMIntrinsicByName(NameTable, Name);
471 Intrinsic::ID ID = static_cast(Idx + 1);
472 if (ID == Intrinsic::not_intrinsic)
473 return ID;
495 if (Idx == -1)
496 return Intrinsic::not_intrinsic;
497
498 // Intrinsic IDs correspond to the location in IntrinsicNameTable, but we have
499 // an index into a sub-table.
500 int Adjust = NameTable.data() - IntrinsicNameTable;
501 Intrinsic::ID ID = static_cast(Idx + Adjust);
474502
475503 // If the intrinsic is not overloaded, require an exact match. If it is
476504 // overloaded, require a prefix match.
23912391 CodeGenDAGPatterns::CodeGenDAGPatterns(RecordKeeper &R) :
23922392 Records(R), Target(R) {
23932393
2394 Intrinsics = LoadIntrinsics(Records, false);
2395 TgtIntrinsics = LoadIntrinsics(Records, true);
2394 Intrinsics = CodeGenIntrinsicTable(Records, false);
2395 TgtIntrinsics = CodeGenIntrinsicTable(Records, true);
23962396 ParseNodeInfo();
23972397 ParseNodeTransforms();
23982398 ParseComplexPatterns();
715715 class CodeGenDAGPatterns {
716716 RecordKeeper &Records;
717717 CodeGenTarget Target;
718 std::vector Intrinsics;
719 std::vector TgtIntrinsics;
718 CodeGenIntrinsicTable Intrinsics;
719 CodeGenIntrinsicTable TgtIntrinsics;
720720
721721 std::map SDNodes;
722722 std::map, LessRecordByID> SDNodeXForms;
113113 CodeGenIntrinsic(Record *R);
114114 };
115115
116 /// Read all of the intrinsics defined in the specified .td file.
117 std::vector LoadIntrinsics(const RecordKeeper &RC,
118 bool TargetOnly);
116 class CodeGenIntrinsicTable {
117 std::vector Intrinsics;
118
119 public:
120 struct TargetSet {
121 std::string Name;
122 size_t Offset;
123 size_t Count;
124 };
125 std::vector Targets;
126
127 explicit CodeGenIntrinsicTable(const RecordKeeper &RC, bool TargetOnly);
128 CodeGenIntrinsicTable() = default;
129
130 bool empty() const { return Intrinsics.empty(); }
131 size_t size() const { return Intrinsics.size(); }
132 CodeGenIntrinsic &operator[](size_t Pos) { return Intrinsics[Pos]; }
133 const CodeGenIntrinsic &operator[](size_t Pos) const {
134 return Intrinsics[Pos];
135 }
136 };
119137 }
120138
121139 #endif
425425 // CodeGenIntrinsic Implementation
426426 //===----------------------------------------------------------------------===//
427427
428 std::vector llvm::LoadIntrinsics(const RecordKeeper &RC,
429 bool TargetOnly) {
428 CodeGenIntrinsicTable::CodeGenIntrinsicTable(const RecordKeeper &RC,
429 bool TargetOnly) {
430430 std::vector Defs = RC.getAllDerivedDefinitions("Intrinsic");
431431
432 std::vector Result;
433 Result.reserve(Defs.size());
432 Intrinsics.reserve(Defs.size());
434433
435434 for (unsigned I = 0, e = Defs.size(); I != e; ++I) {
436435 bool isTarget = Defs[I]->getValueAsBit("isTarget");
437436 if (isTarget == TargetOnly)
438 Result.push_back(CodeGenIntrinsic(Defs[I]));
439 }
440 std::sort(Result.begin(), Result.end(),
441 [](const CodeGenIntrinsic& LHS, const CodeGenIntrinsic& RHS) {
442 return LHS.Name < RHS.Name;
437 Intrinsics.push_back(CodeGenIntrinsic(Defs[I]));
438 }
439 std::sort(Intrinsics.begin(), Intrinsics.end(),
440 [](const CodeGenIntrinsic &LHS, const CodeGenIntrinsic &RHS) {
441 return std::tie(LHS.TargetPrefix, LHS.Name) <
442 std::tie(RHS.TargetPrefix, RHS.Name);
443443 });
444 return Result;
444 Targets.push_back({"", 0, 0});
445 for (size_t I = 0, E = Intrinsics.size(); I < E; ++I)
446 if (Intrinsics[I].TargetPrefix != Targets.back().Name) {
447 Targets.back().Count = I - Targets.back().Offset;
448 Targets.push_back({Intrinsics[I].TargetPrefix, I, 0});
449 }
450 Targets.back().Count = Intrinsics.size() - Targets.back().Offset;
445451 }
446452
447453 CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
3737
3838 void EmitPrefix(raw_ostream &OS);
3939
40 void EmitEnumInfo(const std::vector &Ints,
41 raw_ostream &OS);
42
43 void EmitIntrinsicToNameTable(const std::vector &Ints,
40 void EmitEnumInfo(const CodeGenIntrinsicTable &Ints, raw_ostream &OS);
41 void EmitTargetInfo(const CodeGenIntrinsicTable &Ints, raw_ostream &OS);
42 void EmitIntrinsicToNameTable(const CodeGenIntrinsicTable &Ints,
4443 raw_ostream &OS);
45 void EmitIntrinsicToOverloadTable(const std::vector &Ints,
44 void EmitIntrinsicToOverloadTable(const CodeGenIntrinsicTable &Ints,
4645 raw_ostream &OS);
47 void EmitGenerator(const std::vector &Ints,
48 raw_ostream &OS);
49 void EmitAttributes(const std::vector &Ints,
50 raw_ostream &OS);
51 void EmitIntrinsicToBuiltinMap(const std::vector &Ints,
52 bool IsGCC, raw_ostream &OS);
46 void EmitGenerator(const CodeGenIntrinsicTable &Ints, raw_ostream &OS);
47 void EmitAttributes(const CodeGenIntrinsicTable &Ints, raw_ostream &OS);
48 void EmitIntrinsicToBuiltinMap(const CodeGenIntrinsicTable &Ints, bool IsGCC,
49 raw_ostream &OS);
5350 void EmitSuffix(raw_ostream &OS);
5451 };
5552 } // End anonymous namespace
6158 void IntrinsicEmitter::run(raw_ostream &OS) {
6259 emitSourceFileHeader("Intrinsic Function Source Fragment", OS);
6360
64 std::vector Ints = LoadIntrinsics(Records, TargetOnly);
61 CodeGenIntrinsicTable Ints(Records, TargetOnly);
6562
6663 if (TargetOnly && !Ints.empty())
6764 TargetPrefix = Ints[0].TargetPrefix;
7067
7168 // Emit the enum information.
7269 EmitEnumInfo(Ints, OS);
70
71 // Emit the target metadata.
72 EmitTargetInfo(Ints, OS);
7373
7474 // Emit the intrinsic ID -> name table.
7575 EmitIntrinsicToNameTable(Ints, OS);
113113 "#endif\n\n";
114114 }
115115
116 void IntrinsicEmitter::EmitEnumInfo(const std::vector &Ints,
116 void IntrinsicEmitter::EmitEnumInfo(const CodeGenIntrinsicTable &Ints,
117117 raw_ostream &OS) {
118118 OS << "// Enum values for Intrinsics.h\n";
119119 OS << "#ifdef GET_INTRINSIC_ENUM_VALUES\n";
127127 OS << "#endif\n\n";
128128 }
129129
130 void IntrinsicEmitter::
131 EmitIntrinsicToNameTable(const std::vector &Ints,
132 raw_ostream &OS) {
130 void IntrinsicEmitter::EmitTargetInfo(const CodeGenIntrinsicTable &Ints,
131 raw_ostream &OS) {
132 OS << "// Target mapping\n";
133 OS << "#ifdef GET_INTRINSIC_TARGET_DATA\n";
134 OS << "struct IntrinsicTargetInfo {\n"
135 << " StringRef Name;\n"
136 << " size_t Offset;\n"
137 << " size_t Count;\n"
138 << "};\n";
139 OS << "static const IntrinsicTargetInfo TargetInfos[] = {\n";
140 for (auto Target : Ints.Targets)
141 OS << " {\"" << Target.Name << "\", " << Target.Offset << ", "
142 << Target.Count << "},\n";
143 OS << "};\n";
144 OS << "#endif\n\n";
145 }
146
147 void IntrinsicEmitter::EmitIntrinsicToNameTable(
148 const CodeGenIntrinsicTable &Ints, raw_ostream &OS) {
133149 OS << "// Intrinsic ID to name table\n";
134150 OS << "#ifdef GET_INTRINSIC_NAME_TABLE\n";
135151 OS << " // Note that entry #0 is the invalid intrinsic!\n";
138154 OS << "#endif\n\n";
139155 }
140156
141 void IntrinsicEmitter::
142 EmitIntrinsicToOverloadTable(const std::vector &Ints,
143 raw_ostream &OS) {
157 void IntrinsicEmitter::EmitIntrinsicToOverloadTable(
158 const CodeGenIntrinsicTable &Ints, raw_ostream &OS) {
144159 OS << "// Intrinsic ID to overload bitset\n";
145160 OS << "#ifdef GET_INTRINSIC_OVERLOAD_TABLE\n";
146161 OS << "static const uint8_t OTable[] = {\n";
362377 OS << (unsigned)X;
363378 }
364379
365 void IntrinsicEmitter::EmitGenerator(const std::vector &Ints,
380 void IntrinsicEmitter::EmitGenerator(const CodeGenIntrinsicTable &Ints,
366381 raw_ostream &OS) {
367382 // If we can compute a 32-bit fixed encoding for this intrinsic, do so and
368383 // capture it in this vector, otherwise store a ~0U.
473488 } // End anonymous namespace
474489
475490 /// EmitAttributes - This emits the Intrinsic::getAttributes method.
476 void IntrinsicEmitter::
477 EmitAttributes(const std::vector &Ints, raw_ostream &OS) {
491 void IntrinsicEmitter::EmitAttributes(const CodeGenIntrinsicTable &Ints,
492 raw_ostream &OS) {
478493 OS << "// Add parameter attributes that are not common to all intrinsics.\n";
479494 OS << "#ifdef GET_INTRINSIC_ATTRIBUTES\n";
480495 if (TargetOnly)
669684 }
670685
671686 void IntrinsicEmitter::EmitIntrinsicToBuiltinMap(
672 const std::vector &Ints, bool IsGCC, raw_ostream &OS) {
687 const CodeGenIntrinsicTable &Ints, bool IsGCC, raw_ostream &OS) {
673688 StringRef CompilerName = (IsGCC ? "GCC" : "MS");
674689 typedef std::map> BIMTy;
675690 BIMTy BuiltinMap;