[llvm] [TableGen] Rework `EmitIntrinsicToBuiltinMap` (PR #104681)
Artem Belevich via llvm-commits
llvm-commits at lists.llvm.org
Mon Aug 19 17:02:09 PDT 2024
================
@@ -596,89 +598,178 @@ void IntrinsicEmitter::EmitIntrinsicToBuiltinMap(
const CodeGenIntrinsicTable &Ints, bool IsClang, raw_ostream &OS) {
StringRef CompilerName = IsClang ? "Clang" : "MS";
StringRef UpperCompilerName = IsClang ? "CLANG" : "MS";
- // map<TargetPrefix, map<BuiltinName, EnumName>>. Note that we iterate over
- // both maps in the code below. For the inner map, entries need to be emitted
- // in the sorted order of `BuiltinName` because we use std::lower_bound to
- // search these entries. For the outer map, it doesn't need be be sorted, but
- // we use a map to eliminate non-determinism in the emitted code.
- typedef std::map<StringRef, std::map<StringRef, StringRef>> BIMTy;
- BIMTy BuiltinMap;
- StringToOffsetTable Table;
+
+ // map<TargetPrefix, pair<map<BuiltinName, EnumName>, CommonPrefix>.
+ // Note that we iterate over both the maps in the code below and both
+ // iterations need to iterate in sorted key order. For the inner map, entries
+ // need to be emitted in the sorted order of `BuiltinName - CommonPrefix`
+ // because we use std::lower_bound to search these entries. For the outer map
+ // as well, entries need to be emitted in sorter order of `TargetPrefix` as we
+ // use std::lower_bound to search these entries.
+ using BIMEntryTy = std::pair<std::map<StringRef, StringRef>, StringRef>;
+ std::map<StringRef, BIMEntryTy> BuiltinMap;
+
for (const CodeGenIntrinsic &Int : Ints) {
StringRef BuiltinName = IsClang ? Int.ClangBuiltinName : Int.MSBuiltinName;
if (BuiltinName.empty())
continue;
// Get the map for this target prefix.
- std::map<StringRef, StringRef> &BIM = BuiltinMap[Int.TargetPrefix];
+ auto &[Map, CommonPrefix] = BuiltinMap[Int.TargetPrefix];
- if (!BIM.insert(std::pair(BuiltinName, Int.EnumName)).second)
+ if (!Map.insert({BuiltinName, Int.EnumName}).second)
PrintFatalError(Int.TheDef->getLoc(),
"Intrinsic '" + Int.TheDef->getName() + "': duplicate " +
CompilerName + " builtin name!");
- Table.GetOrAddStringOffset(BuiltinName);
- }
- 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_" << UpperCompilerName << "_BUILTIN\n";
+ // Update common prefix.
+ if (!CommonPrefix.data()) {
+ // For the first builtin for this target, initialize the common prefix.
+ CommonPrefix = BuiltinName;
+ continue;
+ }
- OS << "Intrinsic::ID Intrinsic::getIntrinsicFor" << CompilerName
- << "Builtin(const char "
- << "*TargetPrefixStr, StringRef BuiltinNameStr) {\n";
+ // Update the common prefix. Note that this assumes that `take_front` will
+ // never set the `Data` pointer in CommonPrefix to nullptr.
----------------
Artem-B wrote:
That relies on an implementation detail, IMO. If we have "no prefix" that's distinct from `.empty()` as a special case, can we make it explicit? E.g. by making it `std::optional<StringRef>`.
https://github.com/llvm/llvm-project/pull/104681
More information about the llvm-commits
mailing list