Skip to content

Commit

Permalink
Reland "[MC][NFC] Make ELFUniquingMap a StringMap (#95006)" (#95030)
Browse files Browse the repository at this point in the history
This avoids std::map, which is slow, and uses a StringMap. Section name,
group name, linked-to name and unique id are encoded into the key for
fast lookup.

This gives a measurable performance boost for applications that compile
many small object files (e.g., functions in JIT compilers).

---

Now also the second case works properly. That's what happens when you do
that last refactoring without re-running all tests... sorry.
  • Loading branch information
aengelke authored Jun 11, 2024
1 parent 2825342 commit 05e87a5
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 36 deletions.
27 changes: 1 addition & 26 deletions llvm/include/llvm/MC/MCContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -252,31 +252,6 @@ class MCContext {
/// A collection of MCPseudoProbe in the current module
MCPseudoProbeTable PseudoProbeTable;

// Sections are differentiated by the quadruple (section_name, group_name,
// unique_id, link_to_symbol_name). Sections sharing the same quadruple are
// combined into one section.
struct ELFSectionKey {
std::string SectionName;
StringRef GroupName;
StringRef LinkedToName;
unsigned UniqueID;

ELFSectionKey(StringRef SectionName, StringRef GroupName,
StringRef LinkedToName, unsigned UniqueID)
: SectionName(SectionName), GroupName(GroupName),
LinkedToName(LinkedToName), UniqueID(UniqueID) {}

bool operator<(const ELFSectionKey &Other) const {
if (SectionName != Other.SectionName)
return SectionName < Other.SectionName;
if (GroupName != Other.GroupName)
return GroupName < Other.GroupName;
if (int O = LinkedToName.compare(Other.LinkedToName))
return O < 0;
return UniqueID < Other.UniqueID;
}
};

struct COFFSectionKey {
std::string SectionName;
StringRef GroupName;
Expand Down Expand Up @@ -350,8 +325,8 @@ class MCContext {
};

StringMap<MCSectionMachO *> MachOUniquingMap;
std::map<ELFSectionKey, MCSectionELF *> ELFUniquingMap;
std::map<COFFSectionKey, MCSectionCOFF *> COFFUniquingMap;
StringMap<MCSectionELF *> ELFUniquingMap;
std::map<std::string, MCSectionGOFF *> GOFFUniquingMap;
std::map<WasmSectionKey, MCSectionWasm *> WasmUniquingMap;
std::map<XCOFFSectionKey, MCSectionXCOFF *> XCOFFUniquingMap;
Expand Down
47 changes: 37 additions & 10 deletions llvm/lib/MC/MCContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
#include "llvm/MC/SectionKind.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/EndianStream.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
Expand Down Expand Up @@ -547,16 +548,42 @@ MCSectionELF *MCContext::getELFSection(const Twine &Section, unsigned Type,
if (GroupSym)
Group = GroupSym->getName();
assert(!(LinkedToSym && LinkedToSym->getName().empty()));
// Do the lookup, if we have a hit, return it.
auto IterBool = ELFUniquingMap.insert(std::make_pair(
ELFSectionKey{Section.str(), Group,
LinkedToSym ? LinkedToSym->getName() : "", UniqueID},
nullptr));
auto &Entry = *IterBool.first;
if (!IterBool.second)
return Entry.second;

StringRef CachedName = Entry.first.SectionName;
// Sections are differentiated by the quadruple (section_name, group_name,
// unique_id, link_to_symbol_name). Sections sharing the same quadruple are
// combined into one section. As an optimization, non-unique sections without
// group or linked-to symbol have a shorter unique-ing key.
std::pair<StringMap<MCSectionELF *>::iterator, bool> EntryNewPair;
// Length of the section name, which are the first SectionLen bytes of the key
unsigned SectionLen;
if (GroupSym || LinkedToSym || UniqueID != MCSection::NonUniqueID) {
SmallString<128> Buffer;
Section.toVector(Buffer);
SectionLen = Buffer.size();
Buffer.push_back(0); // separator which cannot occur in the name
if (GroupSym)
Buffer.append(GroupSym->getName());
Buffer.push_back(0); // separator which cannot occur in the name
if (LinkedToSym)
Buffer.append(LinkedToSym->getName());
support::endian::write(Buffer, UniqueID, endianness::native);
StringRef UniqueMapKey = StringRef(Buffer);
EntryNewPair = ELFUniquingMap.insert(std::make_pair(UniqueMapKey, nullptr));
} else if (!Section.isSingleStringRef()) {
SmallString<128> Buffer;
StringRef UniqueMapKey = Section.toStringRef(Buffer);
SectionLen = UniqueMapKey.size();
EntryNewPair = ELFUniquingMap.insert(std::make_pair(UniqueMapKey, nullptr));
} else {
StringRef UniqueMapKey = Section.getSingleStringRef();
SectionLen = UniqueMapKey.size();
EntryNewPair = ELFUniquingMap.insert(std::make_pair(UniqueMapKey, nullptr));
}

if (!EntryNewPair.second)
return EntryNewPair.first->second;

StringRef CachedName = EntryNewPair.first->getKey().take_front(SectionLen);

SectionKind Kind;
if (Flags & ELF::SHF_ARM_PURECODE)
Expand Down Expand Up @@ -600,7 +627,7 @@ MCSectionELF *MCContext::getELFSection(const Twine &Section, unsigned Type,
MCSectionELF *Result =
createELFSectionImpl(CachedName, Type, Flags, Kind, EntrySize, GroupSym,
IsComdat, UniqueID, LinkedToSym);
Entry.second = Result;
EntryNewPair.first->second = Result;

recordELFMergeableSectionInfo(Result->getName(), Result->getFlags(),
Result->getUniqueID(), Result->getEntrySize());
Expand Down

0 comments on commit 05e87a5

Please sign in to comment.