mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-26 04:32:44 +01:00
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. llvm-svn: 275575
This commit is contained in:
parent
af2caac28b
commit
5a8c8a3672
@ -461,17 +461,45 @@ static const char * const IntrinsicNameTable[] = {
|
|||||||
#undef GET_INTRINSIC_NAME_TABLE
|
#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
|
/// \brief This does the actual lookup of an intrinsic ID which
|
||||||
/// matches the given function name.
|
/// matches the given function name.
|
||||||
static Intrinsic::ID lookupIntrinsicID(const ValueName *ValName) {
|
static Intrinsic::ID lookupIntrinsicID(const ValueName *ValName) {
|
||||||
StringRef Name = ValName->getKey();
|
StringRef Name = ValName->getKey();
|
||||||
|
|
||||||
ArrayRef<const char *> NameTable(&IntrinsicNameTable[1],
|
ArrayRef<const char *> NameTable = findTargetSubtable(Name);
|
||||||
std::end(IntrinsicNameTable));
|
|
||||||
int Idx = Intrinsic::lookupLLVMIntrinsicByName(NameTable, Name);
|
int Idx = Intrinsic::lookupLLVMIntrinsicByName(NameTable, Name);
|
||||||
Intrinsic::ID ID = static_cast<Intrinsic::ID>(Idx + 1);
|
if (Idx == -1)
|
||||||
if (ID == Intrinsic::not_intrinsic)
|
return Intrinsic::not_intrinsic;
|
||||||
return ID;
|
|
||||||
|
// 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
|
// If the intrinsic is not overloaded, require an exact match. If it is
|
||||||
// overloaded, require a prefix match.
|
// overloaded, require a prefix match.
|
||||||
|
@ -2392,8 +2392,8 @@ void TreePattern::dump() const { print(errs()); }
|
|||||||
CodeGenDAGPatterns::CodeGenDAGPatterns(RecordKeeper &R) :
|
CodeGenDAGPatterns::CodeGenDAGPatterns(RecordKeeper &R) :
|
||||||
Records(R), Target(R) {
|
Records(R), Target(R) {
|
||||||
|
|
||||||
Intrinsics = LoadIntrinsics(Records, false);
|
Intrinsics = CodeGenIntrinsicTable(Records, false);
|
||||||
TgtIntrinsics = LoadIntrinsics(Records, true);
|
TgtIntrinsics = CodeGenIntrinsicTable(Records, true);
|
||||||
ParseNodeInfo();
|
ParseNodeInfo();
|
||||||
ParseNodeTransforms();
|
ParseNodeTransforms();
|
||||||
ParseComplexPatterns();
|
ParseComplexPatterns();
|
||||||
|
@ -716,8 +716,8 @@ public:
|
|||||||
class CodeGenDAGPatterns {
|
class CodeGenDAGPatterns {
|
||||||
RecordKeeper &Records;
|
RecordKeeper &Records;
|
||||||
CodeGenTarget Target;
|
CodeGenTarget Target;
|
||||||
std::vector<CodeGenIntrinsic> Intrinsics;
|
CodeGenIntrinsicTable Intrinsics;
|
||||||
std::vector<CodeGenIntrinsic> TgtIntrinsics;
|
CodeGenIntrinsicTable TgtIntrinsics;
|
||||||
|
|
||||||
std::map<Record*, SDNodeInfo, LessRecordByID> SDNodes;
|
std::map<Record*, SDNodeInfo, LessRecordByID> SDNodes;
|
||||||
std::map<Record*, std::pair<Record*, std::string>, LessRecordByID> SDNodeXForms;
|
std::map<Record*, std::pair<Record*, std::string>, LessRecordByID> SDNodeXForms;
|
||||||
|
@ -114,9 +114,27 @@ struct CodeGenIntrinsic {
|
|||||||
CodeGenIntrinsic(Record *R);
|
CodeGenIntrinsic(Record *R);
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Read all of the intrinsics defined in the specified .td file.
|
class CodeGenIntrinsicTable {
|
||||||
std::vector<CodeGenIntrinsic> LoadIntrinsics(const RecordKeeper &RC,
|
std::vector<CodeGenIntrinsic> Intrinsics;
|
||||||
bool TargetOnly);
|
|
||||||
|
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
|
#endif
|
||||||
|
@ -426,23 +426,29 @@ ComplexPattern::ComplexPattern(Record *R) {
|
|||||||
// CodeGenIntrinsic Implementation
|
// CodeGenIntrinsic Implementation
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
std::vector<CodeGenIntrinsic> llvm::LoadIntrinsics(const RecordKeeper &RC,
|
CodeGenIntrinsicTable::CodeGenIntrinsicTable(const RecordKeeper &RC,
|
||||||
bool TargetOnly) {
|
bool TargetOnly) {
|
||||||
std::vector<Record*> Defs = RC.getAllDerivedDefinitions("Intrinsic");
|
std::vector<Record*> Defs = RC.getAllDerivedDefinitions("Intrinsic");
|
||||||
|
|
||||||
std::vector<CodeGenIntrinsic> Result;
|
Intrinsics.reserve(Defs.size());
|
||||||
Result.reserve(Defs.size());
|
|
||||||
|
|
||||||
for (unsigned I = 0, e = Defs.size(); I != e; ++I) {
|
for (unsigned I = 0, e = Defs.size(); I != e; ++I) {
|
||||||
bool isTarget = Defs[I]->getValueAsBit("isTarget");
|
bool isTarget = Defs[I]->getValueAsBit("isTarget");
|
||||||
if (isTarget == TargetOnly)
|
if (isTarget == TargetOnly)
|
||||||
Result.push_back(CodeGenIntrinsic(Defs[I]));
|
Intrinsics.push_back(CodeGenIntrinsic(Defs[I]));
|
||||||
}
|
}
|
||||||
std::sort(Result.begin(), Result.end(),
|
std::sort(Intrinsics.begin(), Intrinsics.end(),
|
||||||
[](const CodeGenIntrinsic& LHS, const CodeGenIntrinsic& RHS) {
|
[](const CodeGenIntrinsic &LHS, const CodeGenIntrinsic &RHS) {
|
||||||
return LHS.Name < RHS.Name;
|
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) {
|
CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
|
||||||
|
@ -38,19 +38,16 @@ public:
|
|||||||
|
|
||||||
void EmitPrefix(raw_ostream &OS);
|
void EmitPrefix(raw_ostream &OS);
|
||||||
|
|
||||||
void EmitEnumInfo(const std::vector<CodeGenIntrinsic> &Ints,
|
void EmitEnumInfo(const CodeGenIntrinsicTable &Ints, raw_ostream &OS);
|
||||||
raw_ostream &OS);
|
void EmitTargetInfo(const CodeGenIntrinsicTable &Ints, raw_ostream &OS);
|
||||||
|
void EmitIntrinsicToNameTable(const CodeGenIntrinsicTable &Ints,
|
||||||
void EmitIntrinsicToNameTable(const std::vector<CodeGenIntrinsic> &Ints,
|
|
||||||
raw_ostream &OS);
|
raw_ostream &OS);
|
||||||
void EmitIntrinsicToOverloadTable(const std::vector<CodeGenIntrinsic> &Ints,
|
void EmitIntrinsicToOverloadTable(const CodeGenIntrinsicTable &Ints,
|
||||||
raw_ostream &OS);
|
raw_ostream &OS);
|
||||||
void EmitGenerator(const std::vector<CodeGenIntrinsic> &Ints,
|
void EmitGenerator(const CodeGenIntrinsicTable &Ints, raw_ostream &OS);
|
||||||
raw_ostream &OS);
|
void EmitAttributes(const CodeGenIntrinsicTable &Ints, raw_ostream &OS);
|
||||||
void EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints,
|
void EmitIntrinsicToBuiltinMap(const CodeGenIntrinsicTable &Ints, bool IsGCC,
|
||||||
raw_ostream &OS);
|
raw_ostream &OS);
|
||||||
void EmitIntrinsicToBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints,
|
|
||||||
bool IsGCC, raw_ostream &OS);
|
|
||||||
void EmitSuffix(raw_ostream &OS);
|
void EmitSuffix(raw_ostream &OS);
|
||||||
};
|
};
|
||||||
} // End anonymous namespace
|
} // End anonymous namespace
|
||||||
@ -62,7 +59,7 @@ public:
|
|||||||
void IntrinsicEmitter::run(raw_ostream &OS) {
|
void IntrinsicEmitter::run(raw_ostream &OS) {
|
||||||
emitSourceFileHeader("Intrinsic Function Source Fragment", OS);
|
emitSourceFileHeader("Intrinsic Function Source Fragment", OS);
|
||||||
|
|
||||||
std::vector<CodeGenIntrinsic> Ints = LoadIntrinsics(Records, TargetOnly);
|
CodeGenIntrinsicTable Ints(Records, TargetOnly);
|
||||||
|
|
||||||
if (TargetOnly && !Ints.empty())
|
if (TargetOnly && !Ints.empty())
|
||||||
TargetPrefix = Ints[0].TargetPrefix;
|
TargetPrefix = Ints[0].TargetPrefix;
|
||||||
@ -72,6 +69,9 @@ void IntrinsicEmitter::run(raw_ostream &OS) {
|
|||||||
// Emit the enum information.
|
// Emit the enum information.
|
||||||
EmitEnumInfo(Ints, OS);
|
EmitEnumInfo(Ints, OS);
|
||||||
|
|
||||||
|
// Emit the target metadata.
|
||||||
|
EmitTargetInfo(Ints, OS);
|
||||||
|
|
||||||
// Emit the intrinsic ID -> name table.
|
// Emit the intrinsic ID -> name table.
|
||||||
EmitIntrinsicToNameTable(Ints, OS);
|
EmitIntrinsicToNameTable(Ints, OS);
|
||||||
|
|
||||||
@ -114,7 +114,7 @@ void IntrinsicEmitter::EmitSuffix(raw_ostream &OS) {
|
|||||||
"#endif\n\n";
|
"#endif\n\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void IntrinsicEmitter::EmitEnumInfo(const std::vector<CodeGenIntrinsic> &Ints,
|
void IntrinsicEmitter::EmitEnumInfo(const CodeGenIntrinsicTable &Ints,
|
||||||
raw_ostream &OS) {
|
raw_ostream &OS) {
|
||||||
OS << "// Enum values for Intrinsics.h\n";
|
OS << "// Enum values for Intrinsics.h\n";
|
||||||
OS << "#ifdef GET_INTRINSIC_ENUM_VALUES\n";
|
OS << "#ifdef GET_INTRINSIC_ENUM_VALUES\n";
|
||||||
@ -128,9 +128,25 @@ void IntrinsicEmitter::EmitEnumInfo(const std::vector<CodeGenIntrinsic> &Ints,
|
|||||||
OS << "#endif\n\n";
|
OS << "#endif\n\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void IntrinsicEmitter::
|
void IntrinsicEmitter::EmitTargetInfo(const CodeGenIntrinsicTable &Ints,
|
||||||
EmitIntrinsicToNameTable(const std::vector<CodeGenIntrinsic> &Ints,
|
raw_ostream &OS) {
|
||||||
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 << "// Intrinsic ID to name table\n";
|
||||||
OS << "#ifdef GET_INTRINSIC_NAME_TABLE\n";
|
OS << "#ifdef GET_INTRINSIC_NAME_TABLE\n";
|
||||||
OS << " // Note that entry #0 is the invalid intrinsic!\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";
|
OS << "#endif\n\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void IntrinsicEmitter::
|
void IntrinsicEmitter::EmitIntrinsicToOverloadTable(
|
||||||
EmitIntrinsicToOverloadTable(const std::vector<CodeGenIntrinsic> &Ints,
|
const CodeGenIntrinsicTable &Ints, raw_ostream &OS) {
|
||||||
raw_ostream &OS) {
|
|
||||||
OS << "// Intrinsic ID to overload bitset\n";
|
OS << "// Intrinsic ID to overload bitset\n";
|
||||||
OS << "#ifdef GET_INTRINSIC_OVERLOAD_TABLE\n";
|
OS << "#ifdef GET_INTRINSIC_OVERLOAD_TABLE\n";
|
||||||
OS << "static const uint8_t OTable[] = {\n";
|
OS << "static const uint8_t OTable[] = {\n";
|
||||||
@ -363,7 +378,7 @@ static void printIITEntry(raw_ostream &OS, unsigned char X) {
|
|||||||
OS << (unsigned)X;
|
OS << (unsigned)X;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IntrinsicEmitter::EmitGenerator(const std::vector<CodeGenIntrinsic> &Ints,
|
void IntrinsicEmitter::EmitGenerator(const CodeGenIntrinsicTable &Ints,
|
||||||
raw_ostream &OS) {
|
raw_ostream &OS) {
|
||||||
// If we can compute a 32-bit fixed encoding for this intrinsic, do so and
|
// If we can compute a 32-bit fixed encoding for this intrinsic, do so and
|
||||||
// capture it in this vector, otherwise store a ~0U.
|
// capture it in this vector, otherwise store a ~0U.
|
||||||
@ -474,8 +489,8 @@ struct AttributeComparator {
|
|||||||
} // End anonymous namespace
|
} // End anonymous namespace
|
||||||
|
|
||||||
/// EmitAttributes - This emits the Intrinsic::getAttributes method.
|
/// EmitAttributes - This emits the Intrinsic::getAttributes method.
|
||||||
void IntrinsicEmitter::
|
void IntrinsicEmitter::EmitAttributes(const CodeGenIntrinsicTable &Ints,
|
||||||
EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) {
|
raw_ostream &OS) {
|
||||||
OS << "// Add parameter attributes that are not common to all intrinsics.\n";
|
OS << "// Add parameter attributes that are not common to all intrinsics.\n";
|
||||||
OS << "#ifdef GET_INTRINSIC_ATTRIBUTES\n";
|
OS << "#ifdef GET_INTRINSIC_ATTRIBUTES\n";
|
||||||
if (TargetOnly)
|
if (TargetOnly)
|
||||||
@ -670,7 +685,7 @@ EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void IntrinsicEmitter::EmitIntrinsicToBuiltinMap(
|
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");
|
StringRef CompilerName = (IsGCC ? "GCC" : "MS");
|
||||||
typedef std::map<std::string, std::map<std::string, std::string>> BIMTy;
|
typedef std::map<std::string, std::map<std::string, std::string>> BIMTy;
|
||||||
BIMTy BuiltinMap;
|
BIMTy BuiltinMap;
|
||||||
|
Loading…
Reference in New Issue
Block a user