[llvm] [llvm] Replace unordered_{map,set} with Dense{Map,Set}/SmallPtrSet (PR #202222)
Fangrui Song via llvm-commits
llvm-commits at lists.llvm.org
Fri Jun 12 10:59:30 PDT 2026
https://github.com/MaskRay updated https://github.com/llvm/llvm-project/pull/202222
>From 182374eaca55fa641e9d1f54e4d598f24dc67ac4 Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Sat, 6 Jun 2026 22:17:20 -0700
Subject: [PATCH 1/4] [llvm] Replace unordered_{map,set} with Dense{Map,Set}
std::unordered_map is slow. The remaining uses are pointer stability,
key spanning the full value range, or huge pair<key,value>. After
PR #201281 DenseMap no longer reserves sentinel keys, so more of these maps
can switch.
---
.../LogicalView/Readers/LVDWARFReader.h | 7 +-
llvm/include/llvm/IR/ModuleSummaryIndex.h | 3 +-
.../llvm/Support/ELFAttrParserCompact.h | 8 +--
llvm/include/llvm/XRay/InstrumentationMap.h | 6 +-
llvm/lib/CodeGen/MLRegAllocEvictAdvisor.cpp | 3 +-
llvm/lib/CodeGen/RDFLiveness.cpp | 3 +-
llvm/lib/ObjCopy/ELF/ELFObject.cpp | 4 +-
llvm/lib/Passes/StandardInstrumentations.cpp | 14 ++--
llvm/lib/Target/BPF/BTFDebug.cpp | 12 ++--
llvm/lib/Target/BPF/BTFDebug.h | 15 ++---
.../Target/Hexagon/HexagonISelDAGToDAGHVX.cpp | 3 +-
llvm/lib/Target/PowerPC/PPCInstrInfo.cpp | 2 +-
.../SPIRVConvergenceRegionAnalysis.cpp | 6 +-
llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp | 66 +++++++++----------
llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h | 2 +-
.../SPIRV/SPIRVMergeRegionExitTargets.cpp | 3 +-
llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp | 2 +-
llvm/lib/Target/SPIRV/SPIRVStructurizer.cpp | 12 ++--
llvm/lib/Target/SPIRV/SPIRVUtils.cpp | 8 +--
llvm/lib/Target/SPIRV/SPIRVUtils.h | 9 +--
.../IPO/MemProfContextDisambiguation.cpp | 5 +-
.../Instrumentation/IndirectCallPromotion.cpp | 3 +-
.../Utils/SampleProfileInference.cpp | 4 +-
llvm/tools/llvm-xray/func-id-helper.h | 3 +-
24 files changed, 98 insertions(+), 105 deletions(-)
diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVDWARFReader.h b/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVDWARFReader.h
index 1cf29147fe2a1..b6d514edab6e4 100644
--- a/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVDWARFReader.h
+++ b/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVDWARFReader.h
@@ -14,10 +14,11 @@
#ifndef LLVM_DEBUGINFO_LOGICALVIEW_READERS_LVDWARFREADER_H
#define LLVM_DEBUGINFO_LOGICALVIEW_READERS_LVDWARFREADER_H
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
#include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
#include "llvm/DebugInfo/LogicalView/Readers/LVBinaryReader.h"
-#include <unordered_set>
namespace llvm {
namespace logicalview {
@@ -62,14 +63,14 @@ class LVDWARFReader final : public LVBinaryReader {
std::optional<LVAddress> TombstoneAddress;
// Cross references (Elements).
- using LVElementSet = std::unordered_set<LVElement *>;
+ using LVElementSet = DenseSet<LVElement *>;
struct LVElementEntry {
LVElement *Element;
LVElementSet References;
LVElementSet Types;
LVElementEntry(LVElement *Element = nullptr) : Element(Element) {}
};
- using LVElementReference = std::unordered_map<LVOffset, LVElementEntry>;
+ using LVElementReference = DenseMap<LVOffset, LVElementEntry>;
LVElementReference ElementTable;
Error loadTargetInfo(const object::ObjectFile &Obj);
diff --git a/llvm/include/llvm/IR/ModuleSummaryIndex.h b/llvm/include/llvm/IR/ModuleSummaryIndex.h
index 359026cfc85a0..de487d0429e7e 100644
--- a/llvm/include/llvm/IR/ModuleSummaryIndex.h
+++ b/llvm/include/llvm/IR/ModuleSummaryIndex.h
@@ -45,7 +45,6 @@
#include <optional>
#include <set>
#include <string>
-#include <unordered_set>
#include <utility>
#include <vector>
@@ -1401,7 +1400,7 @@ using ModuleToSummariesForIndexTy =
std::map<std::string, GVSummaryMapTy, std::less<>>;
/// A set of global value summary pointers.
-using GVSummaryPtrSet = std::unordered_set<GlobalValueSummary *>;
+using GVSummaryPtrSet = DenseSet<GlobalValueSummary *>;
/// Map of a type GUID to type id string and summary (multimap used
/// in case of GUID conflicts).
diff --git a/llvm/include/llvm/Support/ELFAttrParserCompact.h b/llvm/include/llvm/Support/ELFAttrParserCompact.h
index d7e415331d1c3..f55c21d42de3d 100644
--- a/llvm/include/llvm/Support/ELFAttrParserCompact.h
+++ b/llvm/include/llvm/Support/ELFAttrParserCompact.h
@@ -10,6 +10,7 @@
#define LLVM_SUPPORT_ELFCOMPACTATTRPARSER_H
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/DataExtractor.h"
#include "llvm/Support/ELFAttributeParser.h"
@@ -17,7 +18,6 @@
#include "llvm/Support/Error.h"
#include <optional>
-#include <unordered_map>
namespace llvm {
class StringRef;
@@ -25,8 +25,8 @@ class ScopedPrinter;
class LLVM_ABI ELFCompactAttrParser : public ELFAttributeParser {
StringRef vendor;
- std::unordered_map<unsigned, unsigned> attributes;
- std::unordered_map<unsigned, StringRef> attributesStr;
+ DenseMap<unsigned, unsigned> attributes;
+ DenseMap<unsigned, StringRef> attributesStr;
virtual Error handler(uint64_t tag, bool &handled) = 0;
@@ -45,7 +45,7 @@ class LLVM_ABI ELFCompactAttrParser : public ELFAttributeParser {
Error parseSubsection(uint32_t length);
void setAttributeString(unsigned tag, StringRef value) {
- attributesStr.emplace(tag, value);
+ attributesStr.try_emplace(tag, value);
}
public:
diff --git a/llvm/include/llvm/XRay/InstrumentationMap.h b/llvm/include/llvm/XRay/InstrumentationMap.h
index c5e7ebff0e2c1..9305b2e3ad36c 100644
--- a/llvm/include/llvm/XRay/InstrumentationMap.h
+++ b/llvm/include/llvm/XRay/InstrumentationMap.h
@@ -14,13 +14,13 @@
#ifndef LLVM_XRAY_INSTRUMENTATIONMAP_H
#define LLVM_XRAY_INSTRUMENTATIONMAP_H
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/YAMLTraits.h"
#include <cstdint>
#include <optional>
-#include <unordered_map>
#include <vector>
namespace llvm::xray {
@@ -74,8 +74,8 @@ struct YAMLXRaySledEntry {
///
class InstrumentationMap {
public:
- using FunctionAddressMap = std::unordered_map<int32_t, uint64_t>;
- using FunctionAddressReverseMap = std::unordered_map<uint64_t, int32_t>;
+ using FunctionAddressMap = DenseMap<int32_t, uint64_t>;
+ using FunctionAddressReverseMap = DenseMap<uint64_t, int32_t>;
using SledContainer = std::vector<SledEntry>;
private:
diff --git a/llvm/lib/CodeGen/MLRegAllocEvictAdvisor.cpp b/llvm/lib/CodeGen/MLRegAllocEvictAdvisor.cpp
index 2f2ee6f535f40..23dc6fbd6e500 100644
--- a/llvm/lib/CodeGen/MLRegAllocEvictAdvisor.cpp
+++ b/llvm/lib/CodeGen/MLRegAllocEvictAdvisor.cpp
@@ -42,7 +42,6 @@
#include <array>
#include <bitset>
#include <memory>
-#include <unordered_map>
using namespace llvm;
@@ -329,7 +328,7 @@ class MLEvictAdvisor : public RegAllocEvictionAdvisor {
using RegID = unsigned;
mutable DenseMap<RegID, LIFeatureComponents> CachedFeatures;
- mutable std::unordered_map<unsigned, unsigned> VirtRegEvictionCounts;
+ mutable DenseMap<unsigned, unsigned> VirtRegEvictionCounts;
void onEviction(Register RegBeingEvicted) const {
// If we cannot find the virtual register in the map, we just assume it has
diff --git a/llvm/lib/CodeGen/RDFLiveness.cpp b/llvm/lib/CodeGen/RDFLiveness.cpp
index 195446e61076e..10ab9b88a05e1 100644
--- a/llvm/lib/CodeGen/RDFLiveness.cpp
+++ b/llvm/lib/CodeGen/RDFLiveness.cpp
@@ -471,8 +471,7 @@ void Liveness::computePhiInfo() {
// phi use -> (map: reaching phi -> set of registers defined in between)
std::map<NodeId, std::map<NodeId, RegisterAggr>> PhiUp;
std::vector<NodeId> PhiUQ; // Work list of phis for upward propagation.
- std::unordered_map<NodeId, RegisterAggr>
- PhiDRs; // Phi -> registers defined by it.
+ DenseMap<NodeId, RegisterAggr> PhiDRs; // Phi -> registers defined by it.
// Go over all phis.
for (NodeAddr<PhiNode *> PhiA : Phis) {
diff --git a/llvm/lib/ObjCopy/ELF/ELFObject.cpp b/llvm/lib/ObjCopy/ELF/ELFObject.cpp
index 3c6f9a966694a..0982e3c02de08 100644
--- a/llvm/lib/ObjCopy/ELF/ELFObject.cpp
+++ b/llvm/lib/ObjCopy/ELF/ELFObject.cpp
@@ -8,6 +8,7 @@
#include "ELFObject.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
@@ -23,7 +24,6 @@
#include <cstddef>
#include <cstdint>
#include <iterator>
-#include <unordered_set>
#include <utility>
#include <vector>
@@ -2235,7 +2235,7 @@ Error Object::removeSections(
// Now make sure there are no remaining references to the sections that will
// be removed. Sometimes it is impossible to remove a reference so we emit
// an error here instead.
- std::unordered_set<const SectionBase *> RemoveSections;
+ DenseSet<const SectionBase *> RemoveSections;
RemoveSections.reserve(std::distance(Iter, std::end(Sections)));
for (auto &RemoveSec : make_range(Iter, std::end(Sections))) {
for (auto &Segment : Segments)
diff --git a/llvm/lib/Passes/StandardInstrumentations.cpp b/llvm/lib/Passes/StandardInstrumentations.cpp
index 19e72a8612c4a..3f00a15dbc617 100644
--- a/llvm/lib/Passes/StandardInstrumentations.cpp
+++ b/llvm/lib/Passes/StandardInstrumentations.cpp
@@ -14,6 +14,8 @@
#include "llvm/Passes/StandardInstrumentations.h"
#include "llvm/ADT/Any.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Analysis/LazyCallGraph.h"
#include "llvm/Analysis/LoopInfo.h"
@@ -40,8 +42,6 @@
#include "llvm/Support/Signals.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/xxhash.h"
-#include <unordered_map>
-#include <unordered_set>
#include <utility>
#include <vector>
@@ -1635,9 +1635,9 @@ class DisplayNode : public DisplayElement {
: DisplayElement(Colour), Content(Content) {}
// Iterator to the child nodes. Required by GraphWriter.
- using ChildIterator = std::unordered_set<DisplayNode *>::const_iterator;
- ChildIterator children_begin() const { return Children.cbegin(); }
- ChildIterator children_end() const { return Children.cend(); }
+ using ChildIterator = DenseSet<DisplayNode *>::const_iterator;
+ ChildIterator children_begin() const { return Children.begin(); }
+ ChildIterator children_end() const { return Children.end(); }
// Iterator for the edges. Required by GraphWriter.
using EdgeIterator = std::vector<DisplayEdge *>::const_iterator;
@@ -1673,8 +1673,8 @@ class DisplayNode : public DisplayElement {
std::vector<DisplayEdge> Edges;
std::vector<DisplayEdge *> EdgePtrs;
- std::unordered_set<DisplayNode *> Children;
- std::unordered_map<const DisplayNode *, const DisplayEdge *> EdgeMap;
+ DenseSet<DisplayNode *> Children;
+ DenseMap<const DisplayNode *, const DisplayEdge *> EdgeMap;
// Safeguard adding of edges.
bool AllEdgesCreated = false;
diff --git a/llvm/lib/Target/BPF/BTFDebug.cpp b/llvm/lib/Target/BPF/BTFDebug.cpp
index c847c1cb4b65c..227a9db86b62d 100644
--- a/llvm/lib/Target/BPF/BTFDebug.cpp
+++ b/llvm/lib/Target/BPF/BTFDebug.cpp
@@ -398,7 +398,7 @@ std::string BTFTypeStruct::getName() { return std::string(STy->getName()); }
/// for subprogram.
BTFTypeFuncProto::BTFTypeFuncProto(
const DISubroutineType *STy, uint32_t VLen,
- const std::unordered_map<uint32_t, StringRef> &FuncArgNames)
+ const DenseMap<uint32_t, StringRef> &FuncArgNames)
: STy(STy), FuncArgNames(FuncArgNames) {
Kind = BTF::BTF_KIND_FUNC_PROTO;
BTFType.Info = (Kind << 24) | VLen;
@@ -626,8 +626,7 @@ void BTFDebug::visitBasicType(const DIBasicType *BTy, uint32_t &TypeId) {
/// Handle subprogram or subroutine types.
void BTFDebug::visitSubroutineType(
const DISubroutineType *STy, bool ForSubprog,
- const std::unordered_map<uint32_t, StringRef> &FuncArgNames,
- uint32_t &TypeId) {
+ const DenseMap<uint32_t, StringRef> &FuncArgNames, uint32_t &TypeId) {
DITypeArray Elements = STy->getTypeArray();
uint32_t VLen = Elements.size() - 1;
if (VLen > BTF::MAX_VLEN)
@@ -1036,8 +1035,7 @@ void BTFDebug::visitTypeEntry(const DIType *Ty, uint32_t &TypeId,
if (const auto *BTy = dyn_cast<DIBasicType>(Ty))
visitBasicType(BTy, TypeId);
else if (const auto *STy = dyn_cast<DISubroutineType>(Ty))
- visitSubroutineType(STy, false, std::unordered_map<uint32_t, StringRef>(),
- TypeId);
+ visitSubroutineType(STy, false, DenseMap<uint32_t, StringRef>(), TypeId);
else if (const auto *CTy = dyn_cast<DICompositeType>(Ty))
visitCompositeType(CTy, TypeId);
else if (const auto *DTy = dyn_cast<DIDerivedType>(Ty))
@@ -1331,7 +1329,7 @@ void BTFDebug::beginFunctionImpl(const MachineFunction *MF) {
// Collect all types locally referenced in this function.
// Use RetainedNodes so we can collect all argument names
// even if the argument is not used.
- std::unordered_map<uint32_t, StringRef> FuncArgNames;
+ DenseMap<uint32_t, StringRef> FuncArgNames;
for (const DINode *DN : SP->getRetainedNodes()) {
if (const auto *DV = dyn_cast<DILocalVariable>(DN)) {
// Collect function arguments for subprogram func type.
@@ -1713,7 +1711,7 @@ void BTFDebug::processFuncPrototypes(const Function *F) {
return;
uint32_t ProtoTypeId;
- const std::unordered_map<uint32_t, StringRef> FuncArgNames;
+ const DenseMap<uint32_t, StringRef> FuncArgNames;
visitSubroutineType(SP->getType(), false, FuncArgNames, ProtoTypeId);
uint32_t FuncId = processDISubprogram(SP, ProtoTypeId, BTF::FUNC_EXTERN);
diff --git a/llvm/lib/Target/BPF/BTFDebug.h b/llvm/lib/Target/BPF/BTFDebug.h
index 75858fcc8bfde..7d2b7032f1faf 100644
--- a/llvm/lib/Target/BPF/BTFDebug.h
+++ b/llvm/lib/Target/BPF/BTFDebug.h
@@ -14,13 +14,13 @@
#ifndef LLVM_LIB_TARGET_BPF_BTFDEBUG_H
#define LLVM_LIB_TARGET_BPF_BTFDEBUG_H
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/CodeGen/DebugHandlerBase.h"
#include "llvm/DebugInfo/BTF/BTF.h"
#include <cstdint>
#include <map>
#include <set>
-#include <unordered_map>
namespace llvm {
@@ -142,12 +142,12 @@ class BTFTypeStruct : public BTFTypeBase {
/// Handle function pointer.
class BTFTypeFuncProto : public BTFTypeBase {
const DISubroutineType *STy;
- std::unordered_map<uint32_t, StringRef> FuncArgNames;
+ DenseMap<uint32_t, StringRef> FuncArgNames;
std::vector<struct BTF::BTFParam> Parameters;
public:
BTFTypeFuncProto(const DISubroutineType *STy, uint32_t NumParams,
- const std::unordered_map<uint32_t, StringRef> &FuncArgNames);
+ const DenseMap<uint32_t, StringRef> &FuncArgNames);
uint32_t getSize() override {
return BTFTypeBase::getSize() + Parameters.size() * BTF::BTFParamSize;
}
@@ -295,7 +295,7 @@ class BTFDebug : public DebugHandlerBase {
bool MapDefNotCollected;
BTFStringTable StringTable;
std::vector<std::unique_ptr<BTFTypeBase>> TypeEntries;
- std::unordered_map<const DIType *, uint32_t> DIToIdMap;
+ DenseMap<const DIType *, uint32_t> DIToIdMap;
std::map<uint32_t, std::vector<BTFFuncInfo>> FuncInfoTable;
std::map<uint32_t, std::vector<BTFLineInfo>> LineInfoTable;
std::map<uint32_t, std::vector<BTFFieldReloc>> FieldRelocTable;
@@ -323,10 +323,9 @@ class BTFDebug : public DebugHandlerBase {
void visitTypeEntry(const DIType *Ty, uint32_t &TypeId, bool CheckPointer,
bool SeenPointer);
void visitBasicType(const DIBasicType *BTy, uint32_t &TypeId);
- void visitSubroutineType(
- const DISubroutineType *STy, bool ForSubprog,
- const std::unordered_map<uint32_t, StringRef> &FuncArgNames,
- uint32_t &TypeId);
+ void visitSubroutineType(const DISubroutineType *STy, bool ForSubprog,
+ const DenseMap<uint32_t, StringRef> &FuncArgNames,
+ uint32_t &TypeId);
void visitFwdDeclType(const DICompositeType *CTy, bool IsUnion,
uint32_t &TypeId);
void visitCompositeType(const DICompositeType *CTy, uint32_t &TypeId);
diff --git a/llvm/lib/Target/Hexagon/HexagonISelDAGToDAGHVX.cpp b/llvm/lib/Target/Hexagon/HexagonISelDAGToDAGHVX.cpp
index ae369fe7ce901..a59ec1820a092 100644
--- a/llvm/lib/Target/Hexagon/HexagonISelDAGToDAGHVX.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonISelDAGToDAGHVX.cpp
@@ -23,7 +23,6 @@
#include <map>
#include <optional>
#include <set>
-#include <unordered_map>
#include <utility>
#include <vector>
@@ -2747,7 +2746,7 @@ void HexagonDAGToDAGISel::ppHvxShuffleOfShuffle(std::vector<SDNode *> &&Nodes) {
unsigned HalfIdx;
};
- using MapType = std::unordered_map<SDValue, unsigned>;
+ using MapType = DenseMap<SDValue, unsigned>;
auto getMaskElt = [&](unsigned Idx, ShuffleVectorSDNode *Shuff0,
ShuffleVectorSDNode *Shuff1,
diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp b/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp
index 59d18de06b2e0..925c679450ded 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp
+++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp
@@ -5448,7 +5448,7 @@ void PPCInstrInfo::promoteInstr32To64ForElimEXTSW(const Register &Reg,
// Map the 32bit to 64bit opcodes for instructions that are not signed or zero
// extended themselves, but may have operands who's destination registers of
// signed or zero extended instructions.
- std::unordered_map<unsigned, unsigned> OpcodeMap = {
+ DenseMap<unsigned, unsigned> OpcodeMap = {
{PPC::OR, PPC::OR8}, {PPC::ISEL, PPC::ISEL8},
{PPC::ORI, PPC::ORI8}, {PPC::XORI, PPC::XORI8},
{PPC::ORIS, PPC::ORIS8}, {PPC::XORIS, PPC::XORIS8},
diff --git a/llvm/lib/Target/SPIRV/Analysis/SPIRVConvergenceRegionAnalysis.cpp b/llvm/lib/Target/SPIRV/Analysis/SPIRVConvergenceRegionAnalysis.cpp
index 0798483462e18..1cb32cce32cbd 100644
--- a/llvm/lib/Target/SPIRV/Analysis/SPIRVConvergenceRegionAnalysis.cpp
+++ b/llvm/lib/Target/SPIRV/Analysis/SPIRVConvergenceRegionAnalysis.cpp
@@ -14,6 +14,7 @@
#include "SPIRVConvergenceRegionAnalysis.h"
#include "SPIRV.h"
+#include "llvm/ADT/DenseSet.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/IntrinsicInst.h"
@@ -21,7 +22,6 @@
#include "llvm/Transforms/Utils/LoopSimplify.h"
#include <optional>
#include <queue>
-#include <unordered_set>
#define DEBUG_TYPE "spirv-convergence-region-analysis"
@@ -210,10 +210,10 @@ class ConvergenceRegionAnalyzer {
return false;
}
- std::unordered_set<BasicBlock *>
+ DenseSet<BasicBlock *>
findPathsToMatch(LoopInfo &LI, BasicBlock *From,
std::function<bool(const BasicBlock *)> isMatch) const {
- std::unordered_set<BasicBlock *> Output;
+ DenseSet<BasicBlock *> Output;
if (isMatch(From))
Output.insert(From);
diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
index 97fa49d8836fb..1e1b0080be5ac 100644
--- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
@@ -17,6 +17,7 @@
#include "SPIRVSubtarget.h"
#include "SPIRVTargetMachine.h"
#include "SPIRVUtils.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Analysis/LoopInfo.h"
@@ -35,7 +36,6 @@
#include <cassert>
#include <optional>
#include <queue>
-#include <unordered_set>
// This pass performs the following transformation on LLVM IR level required
// for the following translation to SPIR-V:
@@ -192,7 +192,7 @@ class SPIRVEmitIntrinsics
DenseSet<Instruction *> AggrStores;
SmallPtrSet<Instruction *, 8> DeletedInstrs;
GlobalVariableUsers GVUsers;
- std::unordered_set<Value *> Named;
+ DenseSet<Value *> Named;
// map of function declarations to <pointer arg index => element type>
DenseMap<Function *, SmallVector<std::pair<unsigned, Type *>>> FDeclPtrTys;
@@ -224,7 +224,7 @@ class SPIRVEmitIntrinsics
}
// a register of Instructions that were visited by deduceOperandElementType()
// to validate operand types with an instruction
- std::unordered_set<Instruction *> TypeValidated;
+ DenseSet<Instruction *> TypeValidated;
// well known result types of builtins
enum WellKnownTypes { Event };
@@ -232,24 +232,22 @@ class SPIRVEmitIntrinsics
// deduce element type of untyped pointers
Type *deduceElementType(Value *I, bool UnknownElemTypeI8);
Type *deduceElementTypeHelper(Value *I, bool UnknownElemTypeI8);
- Type *deduceElementTypeHelper(Value *I, std::unordered_set<Value *> &Visited,
+ Type *deduceElementTypeHelper(Value *I, DenseSet<Value *> &Visited,
bool UnknownElemTypeI8,
bool IgnoreKnownType = false);
Type *deduceElementTypeByValueDeep(Type *ValueTy, Value *Operand,
bool UnknownElemTypeI8);
Type *deduceElementTypeByValueDeep(Type *ValueTy, Value *Operand,
- std::unordered_set<Value *> &Visited,
+ DenseSet<Value *> &Visited,
bool UnknownElemTypeI8);
- Type *deduceElementTypeByUsersDeep(Value *Op,
- std::unordered_set<Value *> &Visited,
+ Type *deduceElementTypeByUsersDeep(Value *Op, DenseSet<Value *> &Visited,
bool UnknownElemTypeI8);
void maybeAssignPtrType(Type *&Ty, Value *I, Type *RefTy,
bool UnknownElemTypeI8);
// deduce nested types of composites
Type *deduceNestedTypeHelper(User *U, bool UnknownElemTypeI8);
- Type *deduceNestedTypeHelper(User *U, Type *Ty,
- std::unordered_set<Value *> &Visited,
+ Type *deduceNestedTypeHelper(User *U, Type *Ty, DenseSet<Value *> &Visited,
bool UnknownElemTypeI8);
// deduce Types of operands of the Instruction if possible
@@ -287,7 +285,7 @@ class SPIRVEmitIntrinsics
void processParamTypesByFunHeader(Function *F, IRBuilder<> &B);
Type *deduceFunParamElementType(Function *F, unsigned OpIdx);
Type *deduceFunParamElementType(Function *F, unsigned OpIdx,
- std::unordered_set<Function *> &FVisited);
+ DenseSet<Function *> &FVisited);
bool deduceOperandElementTypeCalledFunction(
CallInst *CI, SmallVector<std::pair<Value *, unsigned>> &Ops,
@@ -310,7 +308,7 @@ class SPIRVEmitIntrinsics
DenseSet<std::pair<Value *, Value *>> &VisitedSubst);
void propagateElemTypeRec(Value *Op, Type *PtrElemTy, Type *CastElemTy,
DenseSet<std::pair<Value *, Value *>> &VisitedSubst,
- std::unordered_set<Value *> &Visited,
+ DenseSet<Value *> &Visited,
DenseMap<Function *, CallInst *> Ptrcasts);
void replaceAllUsesWith(Value *Src, Value *Dest, bool DeleteOld = true);
@@ -647,7 +645,7 @@ void SPIRVEmitIntrinsics::propagateElemType(
void SPIRVEmitIntrinsics::propagateElemTypeRec(
Value *Op, Type *PtrElemTy, Type *CastElemTy,
DenseSet<std::pair<Value *, Value *>> &VisitedSubst) {
- std::unordered_set<Value *> Visited;
+ DenseSet<Value *> Visited;
DenseMap<Function *, CallInst *> Ptrcasts;
propagateElemTypeRec(Op, PtrElemTy, CastElemTy, VisitedSubst, Visited,
std::move(Ptrcasts));
@@ -656,8 +654,7 @@ void SPIRVEmitIntrinsics::propagateElemTypeRec(
void SPIRVEmitIntrinsics::propagateElemTypeRec(
Value *Op, Type *PtrElemTy, Type *CastElemTy,
DenseSet<std::pair<Value *, Value *>> &VisitedSubst,
- std::unordered_set<Value *> &Visited,
- DenseMap<Function *, CallInst *> Ptrcasts) {
+ DenseSet<Value *> &Visited, DenseMap<Function *, CallInst *> Ptrcasts) {
if (!Visited.insert(Op).second)
return;
SmallVector<User *> Users(Op->users());
@@ -680,14 +677,15 @@ void SPIRVEmitIntrinsics::propagateElemTypeRec(
Type *
SPIRVEmitIntrinsics::deduceElementTypeByValueDeep(Type *ValueTy, Value *Operand,
bool UnknownElemTypeI8) {
- std::unordered_set<Value *> Visited;
+ DenseSet<Value *> Visited;
return deduceElementTypeByValueDeep(ValueTy, Operand, Visited,
UnknownElemTypeI8);
}
-Type *SPIRVEmitIntrinsics::deduceElementTypeByValueDeep(
- Type *ValueTy, Value *Operand, std::unordered_set<Value *> &Visited,
- bool UnknownElemTypeI8) {
+Type *
+SPIRVEmitIntrinsics::deduceElementTypeByValueDeep(Type *ValueTy, Value *Operand,
+ DenseSet<Value *> &Visited,
+ bool UnknownElemTypeI8) {
Type *Ty = ValueTy;
if (Operand) {
if (auto *PtrTy = dyn_cast<PointerType>(Ty)) {
@@ -704,7 +702,7 @@ Type *SPIRVEmitIntrinsics::deduceElementTypeByValueDeep(
// Traverse User instructions to deduce an element pointer type of the operand.
Type *SPIRVEmitIntrinsics::deduceElementTypeByUsersDeep(
- Value *Op, std::unordered_set<Value *> &Visited, bool UnknownElemTypeI8) {
+ Value *Op, DenseSet<Value *> &Visited, bool UnknownElemTypeI8) {
if (!Op || !isPointerTy(Op->getType()) || isa<ConstantPointerNull>(Op) ||
isa<UndefValue>(Op))
return nullptr;
@@ -742,7 +740,7 @@ static Type *getPointeeTypeByCallInst(StringRef DemangledName,
// or nullptr otherwise.
Type *SPIRVEmitIntrinsics::deduceElementTypeHelper(Value *I,
bool UnknownElemTypeI8) {
- std::unordered_set<Value *> Visited;
+ DenseSet<Value *> Visited;
return deduceElementTypeHelper(I, Visited, UnknownElemTypeI8);
}
@@ -929,9 +927,10 @@ Type *SPIRVEmitIntrinsics::getGEPType(GetElementPtrInst *Ref) {
return Ty;
}
-Type *SPIRVEmitIntrinsics::deduceElementTypeHelper(
- Value *I, std::unordered_set<Value *> &Visited, bool UnknownElemTypeI8,
- bool IgnoreKnownType) {
+Type *SPIRVEmitIntrinsics::deduceElementTypeHelper(Value *I,
+ DenseSet<Value *> &Visited,
+ bool UnknownElemTypeI8,
+ bool IgnoreKnownType) {
// allow to pass nullptr as an argument
if (!I)
return nullptr;
@@ -1089,13 +1088,13 @@ Type *SPIRVEmitIntrinsics::deduceElementTypeHelper(
// information is found or needed.
Type *SPIRVEmitIntrinsics::deduceNestedTypeHelper(User *U,
bool UnknownElemTypeI8) {
- std::unordered_set<Value *> Visited;
+ DenseSet<Value *> Visited;
return deduceNestedTypeHelper(U, U->getType(), Visited, UnknownElemTypeI8);
}
-Type *SPIRVEmitIntrinsics::deduceNestedTypeHelper(
- User *U, Type *OrigTy, std::unordered_set<Value *> &Visited,
- bool UnknownElemTypeI8) {
+Type *SPIRVEmitIntrinsics::deduceNestedTypeHelper(User *U, Type *OrigTy,
+ DenseSet<Value *> &Visited,
+ bool UnknownElemTypeI8) {
if (!U)
return OrigTy;
@@ -2931,7 +2930,7 @@ void SPIRVEmitIntrinsics::insertConstantsForFPFastMathDefault(Module &M) {
}
}
- std::unordered_map<unsigned, GlobalVariable *> GlobalVars;
+ DenseMap<unsigned, GlobalVariable *> GlobalVars;
for (auto &[Func, FPFastMathDefaultInfoVec] : FPFastMathDefaultInfoMap) {
if (FPFastMathDefaultInfoVec.empty())
continue;
@@ -3051,17 +3050,18 @@ void SPIRVEmitIntrinsics::processInstrAfterVisit(Instruction *I,
Type *SPIRVEmitIntrinsics::deduceFunParamElementType(Function *F,
unsigned OpIdx) {
- std::unordered_set<Function *> FVisited;
+ DenseSet<Function *> FVisited;
return deduceFunParamElementType(F, OpIdx, FVisited);
}
-Type *SPIRVEmitIntrinsics::deduceFunParamElementType(
- Function *F, unsigned OpIdx, std::unordered_set<Function *> &FVisited) {
+Type *
+SPIRVEmitIntrinsics::deduceFunParamElementType(Function *F, unsigned OpIdx,
+ DenseSet<Function *> &FVisited) {
// maybe a cycle
if (!FVisited.insert(F).second)
return nullptr;
- std::unordered_set<Value *> Visited;
+ DenseSet<Value *> Visited;
SmallVector<std::pair<Function *, unsigned>> Lookup;
// search in function's call sites
for (User *U : F->users()) {
@@ -3546,7 +3546,7 @@ bool SPIRVEmitIntrinsics::postprocessTypes(Module &M) {
// Try to improve the type deduced after all Functions are processed.
if (auto *CI = dyn_cast<Instruction>(Op)) {
CurrF = CI->getParent()->getParent();
- std::unordered_set<Value *> Visited;
+ DenseSet<Value *> Visited;
if (Type *ElemTy = deduceElementTypeHelper(Op, Visited, false, true)) {
if (ElemTy != KnownTy) {
DenseSet<std::pair<Value *, Value *>> VisitedSubst;
diff --git a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h
index f05bdc2cc9861..fcb8b3fd66f91 100644
--- a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h
+++ b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h
@@ -87,7 +87,7 @@ class SPIRVGlobalRegistry : public SPIRVIRMapping {
DenseMap<std::pair<const MachineFunction *, Register>, const Value *> Reg2GO;
// map of aliasing decorations to aliasing metadata
- std::unordered_map<const MDNode *, MachineInstr *> AliasInstMDMap;
+ DenseMap<const MDNode *, MachineInstr *> AliasInstMDMap;
// Add a new OpTypeXXX instruction without checking for duplicates.
SPIRVTypeInst createSPIRVType(const Type *Type, MachineIRBuilder &MIRBuilder,
diff --git a/llvm/lib/Target/SPIRV/SPIRVMergeRegionExitTargets.cpp b/llvm/lib/Target/SPIRV/SPIRVMergeRegionExitTargets.cpp
index 959e7eb1e9e04..899026fd95ef4 100644
--- a/llvm/lib/Target/SPIRV/SPIRVMergeRegionExitTargets.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVMergeRegionExitTargets.cpp
@@ -18,6 +18,7 @@
#include "SPIRVSubtarget.h"
#include "SPIRVUtils.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/IR/Dominators.h"
@@ -166,7 +167,7 @@ static void validateRegionExits(const SPIRV::ConvergenceRegion *CR) {
for (auto *Child : CR->Children)
validateRegionExits(Child);
- std::unordered_set<BasicBlock *> ExitTargets;
+ DenseSet<BasicBlock *> ExitTargets;
for (auto *Exit : CR->Exits) {
for (auto *BB : successors(Exit)) {
if (CR->Blocks.count(BB) == 0)
diff --git a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
index 49d9dc95603ca..ea0635dfdf89d 100644
--- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
@@ -2152,7 +2152,7 @@ void addInstrRequirements(const MachineInstr &MI,
// Check Layout operand in case if it's not a standard one and add the
// appropriate capability.
- std::unordered_map<unsigned, unsigned> LayoutToInstMap = {
+ DenseMap<unsigned, unsigned> LayoutToInstMap = {
{SPIRV::OpCooperativeMatrixLoadKHR, 3},
{SPIRV::OpCooperativeMatrixStoreKHR, 2},
{SPIRV::OpCooperativeMatrixLoadCheckedINTEL, 5},
diff --git a/llvm/lib/Target/SPIRV/SPIRVStructurizer.cpp b/llvm/lib/Target/SPIRV/SPIRVStructurizer.cpp
index d2befa50789fa..b9d3095c36a8e 100644
--- a/llvm/lib/Target/SPIRV/SPIRVStructurizer.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVStructurizer.cpp
@@ -14,6 +14,7 @@
#include "SPIRVSubtarget.h"
#include "SPIRVUtils.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/IR/CFG.h"
@@ -29,12 +30,11 @@
#include "llvm/Transforms/Utils/LoopSimplify.h"
#include "llvm/Transforms/Utils/LowerMemIntrinsics.h"
#include <stack>
-#include <unordered_set>
using namespace llvm;
using namespace SPIRV;
-using BlockSet = std::unordered_set<BasicBlock *>;
+using BlockSet = DenseSet<BasicBlock *>;
using Edge = std::pair<BasicBlock *, BasicBlock *>;
// Helper function to do a partial order visit from the block |Start|, calling
@@ -63,7 +63,7 @@ getRegionForHeader(const ConvergenceRegion *Node, BasicBlock *BB) {
// Returns the single BasicBlock exiting the convergence region `CR`,
// nullptr if no such exit exists.
static BasicBlock *getExitFor(const ConvergenceRegion *CR) {
- std::unordered_set<BasicBlock *> ExitTargets;
+ DenseSet<BasicBlock *> ExitTargets;
for (BasicBlock *Exit : CR->Exits) {
for (BasicBlock *Successor : successors(Exit)) {
if (CR->Blocks.count(Successor) == 0)
@@ -427,7 +427,7 @@ class SPIRVStructurizer : public FunctionPass {
// clang-format on
std::vector<Edge>
createAliasBlocksForComplexEdges(std::vector<Edge> Edges) {
- std::unordered_set<BasicBlock *> Seen;
+ DenseSet<BasicBlock *> Seen;
std::vector<Edge> Output;
Output.reserve(Edges.size());
@@ -465,14 +465,14 @@ class SPIRVStructurizer : public FunctionPass {
std::vector<Edge> FixedEdges = createAliasBlocksForComplexEdges(Edges);
std::vector<BasicBlock *> Dsts;
- std::unordered_map<BasicBlock *, ConstantInt *> DstToIndex;
+ DenseMap<BasicBlock *, ConstantInt *> DstToIndex;
auto NewExit = BasicBlock::Create(F.getContext(),
Header->getName() + ".new.exit", &F);
IRBuilder<> ExitBuilder(NewExit);
for (auto &[Src, Dst] : FixedEdges) {
if (DstToIndex.count(Dst) != 0)
continue;
- DstToIndex.emplace(Dst, ExitBuilder.getInt32(DstToIndex.size()));
+ DstToIndex.try_emplace(Dst, ExitBuilder.getInt32(DstToIndex.size()));
Dsts.push_back(Dst);
}
diff --git a/llvm/lib/Target/SPIRV/SPIRVUtils.cpp b/llvm/lib/Target/SPIRV/SPIRVUtils.cpp
index 6c5619c4585ef..6abdffe743f74 100644
--- a/llvm/lib/Target/SPIRV/SPIRVUtils.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVUtils.cpp
@@ -678,12 +678,12 @@ Type *parseBasicTypeName(StringRef &TypeName, LLVMContext &Ctx) {
return nullptr;
}
-std::unordered_set<BasicBlock *>
+DenseSet<BasicBlock *>
PartialOrderingVisitor::getReachableFrom(BasicBlock *Start) {
std::queue<BasicBlock *> ToVisit;
ToVisit.push(Start);
- std::unordered_set<BasicBlock *> Output;
+ DenseSet<BasicBlock *> Output;
while (ToVisit.size() != 0) {
BasicBlock *BB = ToVisit.front();
ToVisit.pop();
@@ -792,7 +792,7 @@ size_t PartialOrderingVisitor::visit(BasicBlock *BB, size_t Unused) {
QueueIndex = 0;
size_t Rank = GetNodeRank(BB);
OrderInfo Info = {Rank, BlockToOrder.size()};
- BlockToOrder.emplace(BB, Info);
+ BlockToOrder.try_emplace(BB, Info);
for (BasicBlock *S : successors(BB)) {
if (Queued.count(S) != 0)
@@ -831,7 +831,7 @@ bool PartialOrderingVisitor::compare(const BasicBlock *LHS,
void PartialOrderingVisitor::partialOrderVisit(
BasicBlock &Start, std::function<bool(BasicBlock *)> Op) {
- std::unordered_set<BasicBlock *> Reachable = getReachableFrom(&Start);
+ DenseSet<BasicBlock *> Reachable = getReachableFrom(&Start);
assert(BlockToOrder.count(&Start) != 0);
// Skipping blocks with a rank inferior to |Start|'s rank.
diff --git a/llvm/lib/Target/SPIRV/SPIRVUtils.h b/llvm/lib/Target/SPIRV/SPIRVUtils.h
index 27b196cb8dad3..78346abeeafd8 100644
--- a/llvm/lib/Target/SPIRV/SPIRVUtils.h
+++ b/llvm/lib/Target/SPIRV/SPIRVUtils.h
@@ -14,6 +14,8 @@
#define LLVM_LIB_TARGET_SPIRV_SPIRVUTILS_H
#include "MCTargetDesc/SPIRVBaseInfo.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/IR/Dominators.h"
@@ -24,7 +26,6 @@
#include <set>
#include <string>
#include <unordered_map>
-#include <unordered_set>
#include "SPIRVTypeInst.h"
@@ -72,7 +73,7 @@ class PartialOrderingVisitor {
DomTreeBuilder::BBDomTree DT;
LoopInfo LI;
- std::unordered_set<BasicBlock *> Queued = {};
+ DenseSet<BasicBlock *> Queued = {};
std::queue<BasicBlock *> ToVisit = {};
struct OrderInfo {
@@ -80,12 +81,12 @@ class PartialOrderingVisitor {
size_t TraversalIndex;
};
- using BlockToOrderInfoMap = std::unordered_map<BasicBlock *, OrderInfo>;
+ using BlockToOrderInfoMap = DenseMap<BasicBlock *, OrderInfo>;
BlockToOrderInfoMap BlockToOrder;
std::vector<BasicBlock *> Order = {};
// Get all basic-blocks reachable from Start.
- std::unordered_set<BasicBlock *> getReachableFrom(BasicBlock *Start);
+ DenseSet<BasicBlock *> getReachableFrom(BasicBlock *Start);
// Internal function used to determine the partial ordering.
// Visits |BB| with the current rank being |Rank|.
diff --git a/llvm/lib/Transforms/IPO/MemProfContextDisambiguation.cpp b/llvm/lib/Transforms/IPO/MemProfContextDisambiguation.cpp
index ac93576391aff..73583981df31b 100644
--- a/llvm/lib/Transforms/IPO/MemProfContextDisambiguation.cpp
+++ b/llvm/lib/Transforms/IPO/MemProfContextDisambiguation.cpp
@@ -49,7 +49,6 @@
#include "llvm/Transforms/Utils/Instrumentation.h"
#include <deque>
#include <sstream>
-#include <unordered_map>
#include <vector>
using namespace llvm;
using namespace llvm::memprof;
@@ -1103,8 +1102,8 @@ class IndexCallsiteContextGraph
// frames that we discover while building the graph.
// It maps from the summary of the function making the tail call, to a map
// of callee ValueInfo to corresponding synthesized callsite info.
- std::unordered_map<FunctionSummary *,
- std::map<ValueInfo, std::unique_ptr<CallsiteInfo>>>
+ DenseMap<FunctionSummary *,
+ std::map<ValueInfo, std::unique_ptr<CallsiteInfo>>>
FunctionCalleesToSynthesizedCallsiteInfos;
};
} // namespace
diff --git a/llvm/lib/Transforms/Instrumentation/IndirectCallPromotion.cpp b/llvm/lib/Transforms/Instrumentation/IndirectCallPromotion.cpp
index 9fe751a56df64..cc6361f03d89b 100644
--- a/llvm/lib/Transforms/Instrumentation/IndirectCallPromotion.cpp
+++ b/llvm/lib/Transforms/Instrumentation/IndirectCallPromotion.cpp
@@ -44,7 +44,6 @@
#include <cstdint>
#include <set>
#include <string>
-#include <unordered_map>
#include <utility>
#include <vector>
@@ -167,7 +166,7 @@ namespace {
// In the inner map, the key represents address point offsets and the value is a
// constant for this address point.
using VTableAddressPointOffsetValMap =
- SmallDenseMap<const GlobalVariable *, std::unordered_map<int, Constant *>>;
+ SmallDenseMap<const GlobalVariable *, DenseMap<int, Constant *>>;
// A struct to collect type information for a virtual call site.
struct VirtualCallSiteInfo {
diff --git a/llvm/lib/Transforms/Utils/SampleProfileInference.cpp b/llvm/lib/Transforms/Utils/SampleProfileInference.cpp
index 3e40cced8771c..69a6f18baef10 100644
--- a/llvm/lib/Transforms/Utils/SampleProfileInference.cpp
+++ b/llvm/lib/Transforms/Utils/SampleProfileInference.cpp
@@ -15,12 +15,12 @@
#include "llvm/Transforms/Utils/SampleProfileInference.h"
#include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/DenseSet.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include <queue>
#include <set>
#include <stack>
-#include <unordered_set>
using namespace llvm;
#define DEBUG_TYPE "sample-profile-inference"
@@ -1229,7 +1229,7 @@ void verifyInput(const FlowFunction &Func) {
// Verify that there are no parallel edges
for (auto &Block : Func.Blocks) {
- std::unordered_set<uint64_t> UniqueSuccs;
+ DenseSet<uint64_t> UniqueSuccs;
for (auto &Jump : Block.SuccJumps) {
auto It = UniqueSuccs.insert(Jump->Target);
assert(It.second && "input CFG contains parallel edges");
diff --git a/llvm/tools/llvm-xray/func-id-helper.h b/llvm/tools/llvm-xray/func-id-helper.h
index d1a66282bab0b..389415fa038fb 100644
--- a/llvm/tools/llvm-xray/func-id-helper.h
+++ b/llvm/tools/llvm-xray/func-id-helper.h
@@ -15,14 +15,13 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/DebugInfo/Symbolize/SymbolizableModule.h"
#include "llvm/DebugInfo/Symbolize/Symbolize.h"
-#include <unordered_map>
namespace llvm::xray {
// This class consolidates common operations related to Function IDs.
class FuncIdConversionHelper {
public:
- using FunctionAddressMap = std::unordered_map<int32_t, uint64_t>;
+ using FunctionAddressMap = DenseMap<int32_t, uint64_t>;
private:
std::string BinaryInstrMap;
>From 2837ed2ae7f4d4928012803427ed38c0b0bd6760 Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Sun, 7 Jun 2026 14:11:08 -0700
Subject: [PATCH 2/4] use SmallPtrSet<T *, 0>
---
.../LogicalView/Readers/LVDWARFReader.h | 4 +-
llvm/include/llvm/IR/ModuleSummaryIndex.h | 3 +-
llvm/lib/ObjCopy/ELF/ELFObject.cpp | 4 +-
llvm/lib/Passes/StandardInstrumentations.cpp | 6 +-
.../SPIRVConvergenceRegionAnalysis.cpp | 6 +-
llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp | 66 ++++++++++---------
.../SPIRV/SPIRVMergeRegionExitTargets.cpp | 3 +-
llvm/lib/Target/SPIRV/SPIRVStructurizer.cpp | 7 +-
llvm/lib/Target/SPIRV/SPIRVUtils.cpp | 6 +-
llvm/lib/Target/SPIRV/SPIRVUtils.h | 6 +-
10 files changed, 56 insertions(+), 55 deletions(-)
diff --git a/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVDWARFReader.h b/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVDWARFReader.h
index b6d514edab6e4..930eeac5f400e 100644
--- a/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVDWARFReader.h
+++ b/llvm/include/llvm/DebugInfo/LogicalView/Readers/LVDWARFReader.h
@@ -15,7 +15,7 @@
#define LLVM_DEBUGINFO_LOGICALVIEW_READERS_LVDWARFREADER_H
#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
#include "llvm/DebugInfo/LogicalView/Readers/LVBinaryReader.h"
@@ -63,7 +63,7 @@ class LVDWARFReader final : public LVBinaryReader {
std::optional<LVAddress> TombstoneAddress;
// Cross references (Elements).
- using LVElementSet = DenseSet<LVElement *>;
+ using LVElementSet = SmallPtrSet<LVElement *, 0>;
struct LVElementEntry {
LVElement *Element;
LVElementSet References;
diff --git a/llvm/include/llvm/IR/ModuleSummaryIndex.h b/llvm/include/llvm/IR/ModuleSummaryIndex.h
index de487d0429e7e..7858bd1f015d9 100644
--- a/llvm/include/llvm/IR/ModuleSummaryIndex.h
+++ b/llvm/include/llvm/IR/ModuleSummaryIndex.h
@@ -19,6 +19,7 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
@@ -1400,7 +1401,7 @@ using ModuleToSummariesForIndexTy =
std::map<std::string, GVSummaryMapTy, std::less<>>;
/// A set of global value summary pointers.
-using GVSummaryPtrSet = DenseSet<GlobalValueSummary *>;
+using GVSummaryPtrSet = SmallPtrSet<GlobalValueSummary *, 0>;
/// Map of a type GUID to type id string and summary (multimap used
/// in case of GUID conflicts).
diff --git a/llvm/lib/ObjCopy/ELF/ELFObject.cpp b/llvm/lib/ObjCopy/ELF/ELFObject.cpp
index 0982e3c02de08..ac818343f3f8f 100644
--- a/llvm/lib/ObjCopy/ELF/ELFObject.cpp
+++ b/llvm/lib/ObjCopy/ELF/ELFObject.cpp
@@ -8,8 +8,8 @@
#include "ELFObject.h"
#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/ADT/iterator_range.h"
@@ -2235,7 +2235,7 @@ Error Object::removeSections(
// Now make sure there are no remaining references to the sections that will
// be removed. Sometimes it is impossible to remove a reference so we emit
// an error here instead.
- DenseSet<const SectionBase *> RemoveSections;
+ SmallPtrSet<const SectionBase *, 0> RemoveSections;
RemoveSections.reserve(std::distance(Iter, std::end(Sections)));
for (auto &RemoveSec : make_range(Iter, std::end(Sections))) {
for (auto &Segment : Segments)
diff --git a/llvm/lib/Passes/StandardInstrumentations.cpp b/llvm/lib/Passes/StandardInstrumentations.cpp
index 3f00a15dbc617..ef02299445391 100644
--- a/llvm/lib/Passes/StandardInstrumentations.cpp
+++ b/llvm/lib/Passes/StandardInstrumentations.cpp
@@ -15,7 +15,7 @@
#include "llvm/Passes/StandardInstrumentations.h"
#include "llvm/ADT/Any.h"
#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Analysis/LazyCallGraph.h"
#include "llvm/Analysis/LoopInfo.h"
@@ -1635,7 +1635,7 @@ class DisplayNode : public DisplayElement {
: DisplayElement(Colour), Content(Content) {}
// Iterator to the child nodes. Required by GraphWriter.
- using ChildIterator = DenseSet<DisplayNode *>::const_iterator;
+ using ChildIterator = SmallPtrSet<DisplayNode *, 0>::const_iterator;
ChildIterator children_begin() const { return Children.begin(); }
ChildIterator children_end() const { return Children.end(); }
@@ -1673,7 +1673,7 @@ class DisplayNode : public DisplayElement {
std::vector<DisplayEdge> Edges;
std::vector<DisplayEdge *> EdgePtrs;
- DenseSet<DisplayNode *> Children;
+ SmallPtrSet<DisplayNode *, 0> Children;
DenseMap<const DisplayNode *, const DisplayEdge *> EdgeMap;
// Safeguard adding of edges.
diff --git a/llvm/lib/Target/SPIRV/Analysis/SPIRVConvergenceRegionAnalysis.cpp b/llvm/lib/Target/SPIRV/Analysis/SPIRVConvergenceRegionAnalysis.cpp
index 1cb32cce32cbd..f24877611f077 100644
--- a/llvm/lib/Target/SPIRV/Analysis/SPIRVConvergenceRegionAnalysis.cpp
+++ b/llvm/lib/Target/SPIRV/Analysis/SPIRVConvergenceRegionAnalysis.cpp
@@ -14,7 +14,7 @@
#include "SPIRVConvergenceRegionAnalysis.h"
#include "SPIRV.h"
-#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/IntrinsicInst.h"
@@ -210,10 +210,10 @@ class ConvergenceRegionAnalyzer {
return false;
}
- DenseSet<BasicBlock *>
+ SmallPtrSet<BasicBlock *, 0>
findPathsToMatch(LoopInfo &LI, BasicBlock *From,
std::function<bool(const BasicBlock *)> isMatch) const {
- DenseSet<BasicBlock *> Output;
+ SmallPtrSet<BasicBlock *, 0> Output;
if (isMatch(From))
Output.insert(From);
diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
index 1e1b0080be5ac..e94b17d420b32 100644
--- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
@@ -19,6 +19,7 @@
#include "SPIRVUtils.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/IR/Dominators.h"
@@ -189,10 +190,10 @@ class SPIRVEmitIntrinsics
bool HaveFunPtrs = false;
DenseMap<Instruction *, Constant *> AggrConsts;
DenseMap<Instruction *, Type *> AggrConstTypes;
- DenseSet<Instruction *> AggrStores;
+ SmallPtrSet<Instruction *, 0> AggrStores;
SmallPtrSet<Instruction *, 8> DeletedInstrs;
GlobalVariableUsers GVUsers;
- DenseSet<Value *> Named;
+ SmallPtrSet<Value *, 0> Named;
// map of function declarations to <pointer arg index => element type>
DenseMap<Function *, SmallVector<std::pair<unsigned, Type *>>> FDeclPtrTys;
@@ -224,7 +225,7 @@ class SPIRVEmitIntrinsics
}
// a register of Instructions that were visited by deduceOperandElementType()
// to validate operand types with an instruction
- DenseSet<Instruction *> TypeValidated;
+ SmallPtrSet<Instruction *, 0> TypeValidated;
// well known result types of builtins
enum WellKnownTypes { Event };
@@ -232,22 +233,24 @@ class SPIRVEmitIntrinsics
// deduce element type of untyped pointers
Type *deduceElementType(Value *I, bool UnknownElemTypeI8);
Type *deduceElementTypeHelper(Value *I, bool UnknownElemTypeI8);
- Type *deduceElementTypeHelper(Value *I, DenseSet<Value *> &Visited,
+ Type *deduceElementTypeHelper(Value *I, SmallPtrSet<Value *, 0> &Visited,
bool UnknownElemTypeI8,
bool IgnoreKnownType = false);
Type *deduceElementTypeByValueDeep(Type *ValueTy, Value *Operand,
bool UnknownElemTypeI8);
Type *deduceElementTypeByValueDeep(Type *ValueTy, Value *Operand,
- DenseSet<Value *> &Visited,
+ SmallPtrSet<Value *, 0> &Visited,
bool UnknownElemTypeI8);
- Type *deduceElementTypeByUsersDeep(Value *Op, DenseSet<Value *> &Visited,
+ Type *deduceElementTypeByUsersDeep(Value *Op,
+ SmallPtrSet<Value *, 0> &Visited,
bool UnknownElemTypeI8);
void maybeAssignPtrType(Type *&Ty, Value *I, Type *RefTy,
bool UnknownElemTypeI8);
// deduce nested types of composites
Type *deduceNestedTypeHelper(User *U, bool UnknownElemTypeI8);
- Type *deduceNestedTypeHelper(User *U, Type *Ty, DenseSet<Value *> &Visited,
+ Type *deduceNestedTypeHelper(User *U, Type *Ty,
+ SmallPtrSet<Value *, 0> &Visited,
bool UnknownElemTypeI8);
// deduce Types of operands of the Instruction if possible
@@ -285,7 +288,7 @@ class SPIRVEmitIntrinsics
void processParamTypesByFunHeader(Function *F, IRBuilder<> &B);
Type *deduceFunParamElementType(Function *F, unsigned OpIdx);
Type *deduceFunParamElementType(Function *F, unsigned OpIdx,
- DenseSet<Function *> &FVisited);
+ SmallPtrSet<Function *, 0> &FVisited);
bool deduceOperandElementTypeCalledFunction(
CallInst *CI, SmallVector<std::pair<Value *, unsigned>> &Ops,
@@ -308,7 +311,7 @@ class SPIRVEmitIntrinsics
DenseSet<std::pair<Value *, Value *>> &VisitedSubst);
void propagateElemTypeRec(Value *Op, Type *PtrElemTy, Type *CastElemTy,
DenseSet<std::pair<Value *, Value *>> &VisitedSubst,
- DenseSet<Value *> &Visited,
+ SmallPtrSet<Value *, 0> &Visited,
DenseMap<Function *, CallInst *> Ptrcasts);
void replaceAllUsesWith(Value *Src, Value *Dest, bool DeleteOld = true);
@@ -645,7 +648,7 @@ void SPIRVEmitIntrinsics::propagateElemType(
void SPIRVEmitIntrinsics::propagateElemTypeRec(
Value *Op, Type *PtrElemTy, Type *CastElemTy,
DenseSet<std::pair<Value *, Value *>> &VisitedSubst) {
- DenseSet<Value *> Visited;
+ SmallPtrSet<Value *, 0> Visited;
DenseMap<Function *, CallInst *> Ptrcasts;
propagateElemTypeRec(Op, PtrElemTy, CastElemTy, VisitedSubst, Visited,
std::move(Ptrcasts));
@@ -654,7 +657,8 @@ void SPIRVEmitIntrinsics::propagateElemTypeRec(
void SPIRVEmitIntrinsics::propagateElemTypeRec(
Value *Op, Type *PtrElemTy, Type *CastElemTy,
DenseSet<std::pair<Value *, Value *>> &VisitedSubst,
- DenseSet<Value *> &Visited, DenseMap<Function *, CallInst *> Ptrcasts) {
+ SmallPtrSet<Value *, 0> &Visited,
+ DenseMap<Function *, CallInst *> Ptrcasts) {
if (!Visited.insert(Op).second)
return;
SmallVector<User *> Users(Op->users());
@@ -677,15 +681,14 @@ void SPIRVEmitIntrinsics::propagateElemTypeRec(
Type *
SPIRVEmitIntrinsics::deduceElementTypeByValueDeep(Type *ValueTy, Value *Operand,
bool UnknownElemTypeI8) {
- DenseSet<Value *> Visited;
+ SmallPtrSet<Value *, 0> Visited;
return deduceElementTypeByValueDeep(ValueTy, Operand, Visited,
UnknownElemTypeI8);
}
-Type *
-SPIRVEmitIntrinsics::deduceElementTypeByValueDeep(Type *ValueTy, Value *Operand,
- DenseSet<Value *> &Visited,
- bool UnknownElemTypeI8) {
+Type *SPIRVEmitIntrinsics::deduceElementTypeByValueDeep(
+ Type *ValueTy, Value *Operand, SmallPtrSet<Value *, 0> &Visited,
+ bool UnknownElemTypeI8) {
Type *Ty = ValueTy;
if (Operand) {
if (auto *PtrTy = dyn_cast<PointerType>(Ty)) {
@@ -702,7 +705,7 @@ SPIRVEmitIntrinsics::deduceElementTypeByValueDeep(Type *ValueTy, Value *Operand,
// Traverse User instructions to deduce an element pointer type of the operand.
Type *SPIRVEmitIntrinsics::deduceElementTypeByUsersDeep(
- Value *Op, DenseSet<Value *> &Visited, bool UnknownElemTypeI8) {
+ Value *Op, SmallPtrSet<Value *, 0> &Visited, bool UnknownElemTypeI8) {
if (!Op || !isPointerTy(Op->getType()) || isa<ConstantPointerNull>(Op) ||
isa<UndefValue>(Op))
return nullptr;
@@ -740,7 +743,7 @@ static Type *getPointeeTypeByCallInst(StringRef DemangledName,
// or nullptr otherwise.
Type *SPIRVEmitIntrinsics::deduceElementTypeHelper(Value *I,
bool UnknownElemTypeI8) {
- DenseSet<Value *> Visited;
+ SmallPtrSet<Value *, 0> Visited;
return deduceElementTypeHelper(I, Visited, UnknownElemTypeI8);
}
@@ -927,10 +930,9 @@ Type *SPIRVEmitIntrinsics::getGEPType(GetElementPtrInst *Ref) {
return Ty;
}
-Type *SPIRVEmitIntrinsics::deduceElementTypeHelper(Value *I,
- DenseSet<Value *> &Visited,
- bool UnknownElemTypeI8,
- bool IgnoreKnownType) {
+Type *SPIRVEmitIntrinsics::deduceElementTypeHelper(
+ Value *I, SmallPtrSet<Value *, 0> &Visited, bool UnknownElemTypeI8,
+ bool IgnoreKnownType) {
// allow to pass nullptr as an argument
if (!I)
return nullptr;
@@ -1088,13 +1090,14 @@ Type *SPIRVEmitIntrinsics::deduceElementTypeHelper(Value *I,
// information is found or needed.
Type *SPIRVEmitIntrinsics::deduceNestedTypeHelper(User *U,
bool UnknownElemTypeI8) {
- DenseSet<Value *> Visited;
+ SmallPtrSet<Value *, 0> Visited;
return deduceNestedTypeHelper(U, U->getType(), Visited, UnknownElemTypeI8);
}
-Type *SPIRVEmitIntrinsics::deduceNestedTypeHelper(User *U, Type *OrigTy,
- DenseSet<Value *> &Visited,
- bool UnknownElemTypeI8) {
+Type *
+SPIRVEmitIntrinsics::deduceNestedTypeHelper(User *U, Type *OrigTy,
+ SmallPtrSet<Value *, 0> &Visited,
+ bool UnknownElemTypeI8) {
if (!U)
return OrigTy;
@@ -3050,18 +3053,17 @@ void SPIRVEmitIntrinsics::processInstrAfterVisit(Instruction *I,
Type *SPIRVEmitIntrinsics::deduceFunParamElementType(Function *F,
unsigned OpIdx) {
- DenseSet<Function *> FVisited;
+ SmallPtrSet<Function *, 0> FVisited;
return deduceFunParamElementType(F, OpIdx, FVisited);
}
-Type *
-SPIRVEmitIntrinsics::deduceFunParamElementType(Function *F, unsigned OpIdx,
- DenseSet<Function *> &FVisited) {
+Type *SPIRVEmitIntrinsics::deduceFunParamElementType(
+ Function *F, unsigned OpIdx, SmallPtrSet<Function *, 0> &FVisited) {
// maybe a cycle
if (!FVisited.insert(F).second)
return nullptr;
- DenseSet<Value *> Visited;
+ SmallPtrSet<Value *, 0> Visited;
SmallVector<std::pair<Function *, unsigned>> Lookup;
// search in function's call sites
for (User *U : F->users()) {
@@ -3546,7 +3548,7 @@ bool SPIRVEmitIntrinsics::postprocessTypes(Module &M) {
// Try to improve the type deduced after all Functions are processed.
if (auto *CI = dyn_cast<Instruction>(Op)) {
CurrF = CI->getParent()->getParent();
- DenseSet<Value *> Visited;
+ SmallPtrSet<Value *, 0> Visited;
if (Type *ElemTy = deduceElementTypeHelper(Op, Visited, false, true)) {
if (ElemTy != KnownTy) {
DenseSet<std::pair<Value *, Value *>> VisitedSubst;
diff --git a/llvm/lib/Target/SPIRV/SPIRVMergeRegionExitTargets.cpp b/llvm/lib/Target/SPIRV/SPIRVMergeRegionExitTargets.cpp
index 899026fd95ef4..d1d40d0d899a5 100644
--- a/llvm/lib/Target/SPIRV/SPIRVMergeRegionExitTargets.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVMergeRegionExitTargets.cpp
@@ -18,7 +18,6 @@
#include "SPIRVSubtarget.h"
#include "SPIRVUtils.h"
#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/IR/Dominators.h"
@@ -167,7 +166,7 @@ static void validateRegionExits(const SPIRV::ConvergenceRegion *CR) {
for (auto *Child : CR->Children)
validateRegionExits(Child);
- DenseSet<BasicBlock *> ExitTargets;
+ SmallPtrSet<BasicBlock *, 0> ExitTargets;
for (auto *Exit : CR->Exits) {
for (auto *BB : successors(Exit)) {
if (CR->Blocks.count(BB) == 0)
diff --git a/llvm/lib/Target/SPIRV/SPIRVStructurizer.cpp b/llvm/lib/Target/SPIRV/SPIRVStructurizer.cpp
index b9d3095c36a8e..2b13a8da1f5e1 100644
--- a/llvm/lib/Target/SPIRV/SPIRVStructurizer.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVStructurizer.cpp
@@ -14,7 +14,6 @@
#include "SPIRVSubtarget.h"
#include "SPIRVUtils.h"
#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/IR/CFG.h"
@@ -34,7 +33,7 @@
using namespace llvm;
using namespace SPIRV;
-using BlockSet = DenseSet<BasicBlock *>;
+using BlockSet = SmallPtrSet<BasicBlock *, 0>;
using Edge = std::pair<BasicBlock *, BasicBlock *>;
// Helper function to do a partial order visit from the block |Start|, calling
@@ -63,7 +62,7 @@ getRegionForHeader(const ConvergenceRegion *Node, BasicBlock *BB) {
// Returns the single BasicBlock exiting the convergence region `CR`,
// nullptr if no such exit exists.
static BasicBlock *getExitFor(const ConvergenceRegion *CR) {
- DenseSet<BasicBlock *> ExitTargets;
+ SmallPtrSet<BasicBlock *, 0> ExitTargets;
for (BasicBlock *Exit : CR->Exits) {
for (BasicBlock *Successor : successors(Exit)) {
if (CR->Blocks.count(Successor) == 0)
@@ -427,7 +426,7 @@ class SPIRVStructurizer : public FunctionPass {
// clang-format on
std::vector<Edge>
createAliasBlocksForComplexEdges(std::vector<Edge> Edges) {
- DenseSet<BasicBlock *> Seen;
+ SmallPtrSet<BasicBlock *, 0> Seen;
std::vector<Edge> Output;
Output.reserve(Edges.size());
diff --git a/llvm/lib/Target/SPIRV/SPIRVUtils.cpp b/llvm/lib/Target/SPIRV/SPIRVUtils.cpp
index 6abdffe743f74..7246a968aabac 100644
--- a/llvm/lib/Target/SPIRV/SPIRVUtils.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVUtils.cpp
@@ -678,12 +678,12 @@ Type *parseBasicTypeName(StringRef &TypeName, LLVMContext &Ctx) {
return nullptr;
}
-DenseSet<BasicBlock *>
+SmallPtrSet<BasicBlock *, 0>
PartialOrderingVisitor::getReachableFrom(BasicBlock *Start) {
std::queue<BasicBlock *> ToVisit;
ToVisit.push(Start);
- DenseSet<BasicBlock *> Output;
+ SmallPtrSet<BasicBlock *, 0> Output;
while (ToVisit.size() != 0) {
BasicBlock *BB = ToVisit.front();
ToVisit.pop();
@@ -831,7 +831,7 @@ bool PartialOrderingVisitor::compare(const BasicBlock *LHS,
void PartialOrderingVisitor::partialOrderVisit(
BasicBlock &Start, std::function<bool(BasicBlock *)> Op) {
- DenseSet<BasicBlock *> Reachable = getReachableFrom(&Start);
+ SmallPtrSet<BasicBlock *, 0> Reachable = getReachableFrom(&Start);
assert(BlockToOrder.count(&Start) != 0);
// Skipping blocks with a rank inferior to |Start|'s rank.
diff --git a/llvm/lib/Target/SPIRV/SPIRVUtils.h b/llvm/lib/Target/SPIRV/SPIRVUtils.h
index 78346abeeafd8..a52012deff403 100644
--- a/llvm/lib/Target/SPIRV/SPIRVUtils.h
+++ b/llvm/lib/Target/SPIRV/SPIRVUtils.h
@@ -15,7 +15,7 @@
#include "MCTargetDesc/SPIRVBaseInfo.h"
#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/IR/Dominators.h"
@@ -73,7 +73,7 @@ class PartialOrderingVisitor {
DomTreeBuilder::BBDomTree DT;
LoopInfo LI;
- DenseSet<BasicBlock *> Queued = {};
+ SmallPtrSet<BasicBlock *, 0> Queued = {};
std::queue<BasicBlock *> ToVisit = {};
struct OrderInfo {
@@ -86,7 +86,7 @@ class PartialOrderingVisitor {
std::vector<BasicBlock *> Order = {};
// Get all basic-blocks reachable from Start.
- DenseSet<BasicBlock *> getReachableFrom(BasicBlock *Start);
+ SmallPtrSet<BasicBlock *, 0> getReachableFrom(BasicBlock *Start);
// Internal function used to determine the partial ordering.
// Visits |BB| with the current rank being |Rank|.
>From b05f92f1bc1377e4ce50a44bfed902b36a666fe1 Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Fri, 12 Jun 2026 10:27:09 -0700
Subject: [PATCH 3/4] migrate more
---
llvm/include/llvm/ADT/SCCIterator.h | 18 +++++--
.../llvm/Analysis/DOTGraphTraitsPass.h | 4 +-
llvm/include/llvm/CGData/OutlinedHashTree.h | 5 +-
llvm/include/llvm/CGData/StableFunctionMap.h | 6 +--
.../CodeGen/GlobalISel/LegacyLegalizerInfo.h | 5 +-
llvm/include/llvm/CodeGen/LexicalScopes.h | 22 ++++----
llvm/include/llvm/CodeGen/LiveStacks.h | 13 +++--
llvm/include/llvm/CodeGen/RDFGraph.h | 5 +-
llvm/include/llvm/CodeGen/RDFLiveness.h | 3 +-
llvm/include/llvm/DebugInfo/PDB/PDBExtras.h | 4 +-
.../llvm/ExecutionEngine/Orc/ELFNixPlatform.h | 23 ++-------
llvm/include/llvm/MC/MCPseudoProbe.h | 36 +++++++------
llvm/include/llvm/ObjectYAML/DWARFYAML.h | 3 +-
llvm/include/llvm/ProfileData/MemProf.h | 12 +++++
llvm/include/llvm/ProfileData/SampleProf.h | 51 +++++++++++--------
.../llvm/ProfileData/SampleProfReader.h | 8 +--
llvm/include/llvm/Transforms/IPO/GlobalDCE.h | 3 +-
.../Transforms/IPO/SampleContextTracker.h | 3 +-
.../Transforms/IPO/SampleProfileMatcher.h | 37 +++++---------
.../llvm/Transforms/IPO/SampleProfileProbe.h | 8 ++-
.../Transforms/Instrumentation/MemProfUse.h | 11 +---
llvm/lib/CGData/OutlinedHashTree.cpp | 4 +-
llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp | 18 +++++--
llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h | 7 +--
llvm/lib/CodeGen/LexicalScopes.cpp | 38 +++++++-------
llvm/lib/CodeGen/LiveStacks.cpp | 23 +++++----
llvm/lib/CodeGen/RDFGraph.cpp | 15 +++---
llvm/lib/CodeGen/RDFLiveness.cpp | 21 +++++---
llvm/lib/CodeGen/StackSlotColoring.cpp | 2 +-
llvm/lib/DebugInfo/PDB/PDBSymbolFunc.cpp | 4 +-
.../RuntimeDyld/RuntimeDyldImpl.h | 4 +-
llvm/lib/IR/PrintPasses.cpp | 13 ++---
llvm/lib/MC/MCPseudoProbe.cpp | 2 +-
llvm/lib/ProfileData/SampleProf.cpp | 8 +--
llvm/lib/Support/Z3Solver.cpp | 14 ++---
llvm/lib/Target/AArch64/AArch64.h | 4 +-
.../Target/AArch64/AArch64SIMDInstrOpt.cpp | 4 +-
.../AMDGPU/AMDGPUMarkLastScratchLoad.cpp | 4 +-
.../AMDGPU/AMDGPURewriteAGPRCopyMFMA.cpp | 2 +-
.../MCTargetDesc/HexagonMCTargetDesc.cpp | 9 ++--
llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp | 2 +-
llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp | 21 ++++----
llvm/lib/Target/SPIRV/SPIRVUtils.h | 4 +-
llvm/lib/Transforms/IPO/GlobalDCE.cpp | 12 +++--
llvm/lib/Transforms/IPO/SampleProfile.cpp | 4 +-
.../Transforms/IPO/SampleProfileMatcher.cpp | 9 ++--
.../lib/Transforms/IPO/SampleProfileProbe.cpp | 8 +--
.../tools/llvm-exegesis/lib/BenchmarkResult.h | 4 +-
llvm/tools/llvm-exegesis/lib/SnippetFile.cpp | 4 +-
.../llvm-exegesis/lib/SubprocessMemory.cpp | 20 ++++----
.../llvm-exegesis/lib/SubprocessMemory.h | 14 ++---
llvm/tools/llvm-objdump/SourcePrinter.h | 5 +-
llvm/tools/llvm-profgen/ProfiledBinary.cpp | 12 ++---
llvm/tools/llvm-profgen/ProfiledBinary.h | 7 ++-
.../llvm-exegesis/X86/SnippetFileTest.cpp | 4 +-
.../X86/SubprocessMemoryTest.cpp | 6 +--
llvm/utils/TableGen/DFAPacketizerEmitter.cpp | 9 ++--
57 files changed, 309 insertions(+), 312 deletions(-)
diff --git a/llvm/include/llvm/ADT/SCCIterator.h b/llvm/include/llvm/ADT/SCCIterator.h
index 5e0ca2eb949a0..742a1ff5aabeb 100644
--- a/llvm/include/llvm/ADT/SCCIterator.h
+++ b/llvm/include/llvm/ADT/SCCIterator.h
@@ -25,14 +25,13 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/GraphTraits.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/iterator.h"
#include <cassert>
#include <cstddef>
#include <iterator>
#include <queue>
#include <set>
-#include <unordered_map>
-#include <unordered_set>
#include <vector>
namespace llvm {
@@ -292,7 +291,10 @@ class scc_member_iterator {
return true;
}
- std::unordered_map<NodeType *, NodeInfo> NodeInfoMap;
+ // NodeInfo::Group is self-referential and unionGroups follows pointers into
+ // the map values, so the map must never relocate elements after the initial
+ // population: reserve() upfront and do not insert afterwards.
+ DenseMap<NodeType *, NodeInfo> NodeInfoMap;
NodesType Nodes;
public:
@@ -311,6 +313,7 @@ scc_member_iterator<GraphT, GT>::scc_member_iterator(
// Initialize auxilary node information.
NodeInfoMap.clear();
+ NodeInfoMap.reserve(InputNodes.size());
for (auto *Node : InputNodes) {
// Construct a `NodeInfo` object in place. `insert()` would involve a copy
// construction, invalidating the initial value of the `Group` field, which
@@ -335,7 +338,7 @@ scc_member_iterator<GraphT, GT>::scc_member_iterator(
// Traverse all the edges and compute the Maximum Weight Spanning Tree
// using Kruskal's algorithm.
- std::unordered_set<const EdgeType *> MSTEdges;
+ SmallPtrSet<const EdgeType *, 0> MSTEdges;
for (auto *Edge : SortedEdges) {
if (unionGroups(Edge))
MSTEdges.insert(Edge);
@@ -365,7 +368,12 @@ scc_member_iterator<GraphT, GT>::scc_member_iterator(
Queue.pop();
Nodes.push_back(Node);
for (auto &Edge : Node->Edges) {
- NodeInfo &Info = NodeInfoMap[Edge.Target];
+ // Edges to nodes outside the SCC carry no MST state; skip them instead
+ // of inserting a fresh entry (the map must not grow at this point).
+ auto It = NodeInfoMap.find(Edge.Target);
+ if (It == NodeInfoMap.end())
+ continue;
+ NodeInfo &Info = It->second;
Info.IncomingMSTEdges.erase(&Edge);
if (MSTEdges.count(&Edge) && Info.IncomingMSTEdges.empty()) {
Queue.push(Edge.Target);
diff --git a/llvm/include/llvm/Analysis/DOTGraphTraitsPass.h b/llvm/include/llvm/Analysis/DOTGraphTraitsPass.h
index fe48f9910acae..4c9538d8a2cda 100644
--- a/llvm/include/llvm/Analysis/DOTGraphTraitsPass.h
+++ b/llvm/include/llvm/Analysis/DOTGraphTraitsPass.h
@@ -13,12 +13,12 @@
#ifndef LLVM_ANALYSIS_DOTGRAPHTRAITSPASS_H
#define LLVM_ANALYSIS_DOTGRAPHTRAITSPASS_H
+#include "llvm/ADT/StringSet.h"
#include "llvm/Analysis/CFGPrinter.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/GraphWriter.h"
-#include <unordered_set>
-static std::unordered_set<std::string> nameObj;
+static llvm::StringSet<> nameObj;
namespace llvm {
diff --git a/llvm/include/llvm/CGData/OutlinedHashTree.h b/llvm/include/llvm/CGData/OutlinedHashTree.h
index 8cbc50bc1b9ee..af0a392e38a84 100644
--- a/llvm/include/llvm/CGData/OutlinedHashTree.h
+++ b/llvm/include/llvm/CGData/OutlinedHashTree.h
@@ -21,8 +21,6 @@
#include "llvm/Support/Compiler.h"
#include "llvm/Support/raw_ostream.h"
-#include <unordered_map>
-
namespace llvm {
/// A HashNode is an entry in an OutlinedHashTree, holding a hash value
@@ -35,8 +33,7 @@ struct HashNode {
/// The number of terminals in the sequence ending at this node.
std::optional<unsigned> Terminals;
/// The successors of this node.
- /// We don't use DenseMap as a stable_hash value can be tombstone.
- std::unordered_map<stable_hash, std::unique_ptr<HashNode>> Successors;
+ DenseMap<stable_hash, std::unique_ptr<HashNode>> Successors;
};
class OutlinedHashTree {
diff --git a/llvm/include/llvm/CGData/StableFunctionMap.h b/llvm/include/llvm/CGData/StableFunctionMap.h
index 50db26d31df37..94585e958485e 100644
--- a/llvm/include/llvm/CGData/StableFunctionMap.h
+++ b/llvm/include/llvm/CGData/StableFunctionMap.h
@@ -99,9 +99,9 @@ struct StableFunctionMap {
friend struct StableFunctionMapRecord;
};
- // Note: DenseMap requires value type to be copyable even if only using
- // in-place insertion. Use STL instead. This also affects the
- // deletion-while-iteration in finalize().
+ // Note: EntryStorage contains a std::once_flag, which is neither copyable
+ // nor movable, and the lazy-loading design relies on value addresses being
+ // stable. DenseMap relocates values on rehash, so use std::unordered_map.
using HashFuncsMapType = std::unordered_map<stable_hash, EntryStorage>;
/// Get the HashToFuncs map for serialization.
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/LegacyLegalizerInfo.h b/llvm/include/llvm/CodeGen/GlobalISel/LegacyLegalizerInfo.h
index e6d593e4f6d49..c4ceb99588906 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/LegacyLegalizerInfo.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/LegacyLegalizerInfo.h
@@ -19,7 +19,6 @@
#include "llvm/CodeGen/TargetOpcodes.h"
#include "llvm/CodeGenTypes/LowLevelType.h"
#include "llvm/Support/Compiler.h"
-#include <unordered_map>
#include <vector>
namespace llvm {
@@ -456,9 +455,9 @@ class LegacyLegalizerInfo {
// Data structures used by getAction:
SmallVector<SizeAndActionsVec, 1> ScalarActions[LastOp - FirstOp + 1];
SmallVector<SizeAndActionsVec, 1> ScalarInVectorActions[LastOp - FirstOp + 1];
- std::unordered_map<uint16_t, SmallVector<SizeAndActionsVec, 1>>
+ DenseMap<uint16_t, SmallVector<SizeAndActionsVec, 1>>
AddrSpace2PointerActions[LastOp - FirstOp + 1];
- std::unordered_map<uint16_t, SmallVector<SizeAndActionsVec, 1>>
+ DenseMap<uint16_t, SmallVector<SizeAndActionsVec, 1>>
NumElements2Actions[LastOp - FirstOp + 1];
};
diff --git a/llvm/include/llvm/CodeGen/LexicalScopes.h b/llvm/include/llvm/CodeGen/LexicalScopes.h
index 6a52bdfb2f48c..1faa37cb3dc68 100644
--- a/llvm/include/llvm/CodeGen/LexicalScopes.h
+++ b/llvm/include/llvm/CodeGen/LexicalScopes.h
@@ -23,7 +23,7 @@
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/Support/Compiler.h"
#include <cassert>
-#include <unordered_map>
+#include <memory>
#include <utility>
namespace llvm {
@@ -190,19 +190,19 @@ class LexicalScopes {
/// Find an abstract scope or return null.
LexicalScope *findAbstractScope(const DILocalScope *N) {
auto I = AbstractScopeMap.find(N);
- return I != AbstractScopeMap.end() ? &I->second : nullptr;
+ return I != AbstractScopeMap.end() ? I->second.get() : nullptr;
}
/// Find an inlined scope for the given scope/inlined-at.
LexicalScope *findInlinedScope(const DILocalScope *N, const DILocation *IA) {
auto I = InlinedLexicalScopeMap.find(std::make_pair(N, IA));
- return I != InlinedLexicalScopeMap.end() ? &I->second : nullptr;
+ return I != InlinedLexicalScopeMap.end() ? I->second.get() : nullptr;
}
/// Find regular lexical scope or return null.
LexicalScope *findLexicalScope(const DILocalScope *N) {
auto I = LexicalScopeMap.find(N);
- return I != LexicalScopeMap.end() ? &I->second : nullptr;
+ return I != LexicalScopeMap.end() ? I->second.get() : nullptr;
}
/// Find or create an abstract lexical scope.
@@ -246,18 +246,18 @@ class LexicalScopes {
DenseMap<const DISubprogram *, const Function *> FunctionMap;
/// Tracks the scopes in the current function.
- // Use an unordered_map to ensure value pointer validity over insertion.
- std::unordered_map<const DILocalScope *, LexicalScope> LexicalScopeMap;
+ // The scopes are heap-allocated to ensure LexicalScope pointer validity
+ // over insertion.
+ DenseMap<const DILocalScope *, std::unique_ptr<LexicalScope>> LexicalScopeMap;
/// Tracks inlined function scopes in current function.
- std::unordered_map<std::pair<const DILocalScope *, const DILocation *>,
- LexicalScope,
- pair_hash<const DILocalScope *, const DILocation *>>
+ DenseMap<std::pair<const DILocalScope *, const DILocation *>,
+ std::unique_ptr<LexicalScope>>
InlinedLexicalScopeMap;
/// These scopes are not included LexicalScopeMap.
- // Use an unordered_map to ensure value pointer validity over insertion.
- std::unordered_map<const DILocalScope *, LexicalScope> AbstractScopeMap;
+ DenseMap<const DILocalScope *, std::unique_ptr<LexicalScope>>
+ AbstractScopeMap;
/// Tracks abstract scopes constructed while processing a function.
SmallVector<LexicalScope *, 4> AbstractScopesList;
diff --git a/llvm/include/llvm/CodeGen/LiveStacks.h b/llvm/include/llvm/CodeGen/LiveStacks.h
index f2ecdca257bb1..c31ef0b05c36b 100644
--- a/llvm/include/llvm/CodeGen/LiveStacks.h
+++ b/llvm/include/llvm/CodeGen/LiveStacks.h
@@ -15,6 +15,7 @@
#ifndef LLVM_CODEGEN_LIVESTACKS_H
#define LLVM_CODEGEN_LIVESTACKS_H
+#include "llvm/ADT/DenseMap.h"
#include "llvm/CodeGen/LiveInterval.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/IR/PassManager.h"
@@ -22,7 +23,7 @@
#include "llvm/PassRegistry.h"
#include <cassert>
#include <map>
-#include <unordered_map>
+#include <memory>
namespace llvm {
@@ -40,8 +41,10 @@ class LiveStacks {
///
VNInfo::Allocator VNInfoAllocator;
- /// S2IMap - Stack slot indices to live interval mapping.
- using SS2IntervalMap = std::unordered_map<int, LiveInterval>;
+ /// S2IMap - Stack slot indices to live interval mapping. The intervals are
+ /// heap-allocated so that references remain valid while new slots are
+ /// created.
+ using SS2IntervalMap = DenseMap<int, std::unique_ptr<LiveInterval>>;
SS2IntervalMap S2IMap;
/// S2RCMap - Stack slot indices to register class mapping.
@@ -65,14 +68,14 @@ class LiveStacks {
assert(Slot >= 0 && "Spill slot indice must be >= 0");
SS2IntervalMap::iterator I = S2IMap.find(Slot);
assert(I != S2IMap.end() && "Interval does not exist for stack slot");
- return I->second;
+ return *I->second;
}
const LiveInterval &getInterval(int Slot) const {
assert(Slot >= 0 && "Spill slot indice must be >= 0");
SS2IntervalMap::const_iterator I = S2IMap.find(Slot);
assert(I != S2IMap.end() && "Interval does not exist for stack slot");
- return I->second;
+ return *I->second;
}
bool hasInterval(int Slot) const { return S2IMap.count(Slot); }
diff --git a/llvm/include/llvm/CodeGen/RDFGraph.h b/llvm/include/llvm/CodeGen/RDFGraph.h
index c1ec2ddff14a3..27b5795b8ed2d 100644
--- a/llvm/include/llvm/CodeGen/RDFGraph.h
+++ b/llvm/include/llvm/CodeGen/RDFGraph.h
@@ -226,6 +226,7 @@
#include "RDFRegisters.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/MC/LaneBitmask.h"
#include "llvm/Support/Allocator.h"
@@ -236,7 +237,6 @@
#include <map>
#include <memory>
#include <set>
-#include <unordered_map>
#include <utility>
#include <vector>
@@ -770,9 +770,8 @@ struct DataFlowGraph {
StorageType Stack;
};
- // Make this std::unordered_map for speed of accessing elements.
// Map: Register (physical or virtual) -> DefStack
- using DefStackMap = std::unordered_map<RegisterId, DefStack>;
+ using DefStackMap = DenseMap<RegisterId, DefStack>;
LLVM_ABI void build(const Config &config);
void build() { build(Config()); }
diff --git a/llvm/include/llvm/CodeGen/RDFLiveness.h b/llvm/include/llvm/CodeGen/RDFLiveness.h
index da88fb2bbeb3e..0ff4bb1e3b5a0 100644
--- a/llvm/include/llvm/CodeGen/RDFLiveness.h
+++ b/llvm/include/llvm/CodeGen/RDFLiveness.h
@@ -18,7 +18,6 @@
#include "llvm/MC/LaneBitmask.h"
#include <map>
#include <set>
-#include <unordered_map>
#include <unordered_set>
#include <utility>
@@ -57,7 +56,7 @@ struct Liveness {
using LiveMapType = RegisterAggrMap<MachineBasicBlock *>;
using NodeRef = detail::NodeRef;
using NodeRefSet = std::unordered_set<NodeRef>;
- using RefMap = std::unordered_map<RegisterId, NodeRefSet>;
+ using RefMap = DenseMap<RegisterId, NodeRefSet>;
Liveness(MachineRegisterInfo &mri, const DataFlowGraph &g)
: DFG(g), TRI(g.getTRI()), PRI(g.getPRI()), MDT(g.getDT()),
diff --git a/llvm/include/llvm/DebugInfo/PDB/PDBExtras.h b/llvm/include/llvm/DebugInfo/PDB/PDBExtras.h
index d35b162d56a6b..0a5eca5cf66ef 100644
--- a/llvm/include/llvm/DebugInfo/PDB/PDBExtras.h
+++ b/llvm/include/llvm/DebugInfo/PDB/PDBExtras.h
@@ -9,19 +9,19 @@
#ifndef LLVM_DEBUGINFO_PDB_PDBEXTRAS_H
#define LLVM_DEBUGINFO_PDB_PDBEXTRAS_H
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/PDB/PDBTypes.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/raw_ostream.h"
#include <cstdint>
-#include <unordered_map>
namespace llvm {
namespace pdb {
-using TagStats = std::unordered_map<PDB_SymType, int>;
+using TagStats = DenseMap<PDB_SymType, int>;
LLVM_ABI raw_ostream &operator<<(raw_ostream &OS, const PDB_VariantType &Value);
LLVM_ABI raw_ostream &operator<<(raw_ostream &OS, const PDB_CallingConv &Conv);
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/ELFNixPlatform.h b/llvm/include/llvm/ExecutionEngine/Orc/ELFNixPlatform.h
index 1d1c51d40be69..e601bca181483 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/ELFNixPlatform.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/ELFNixPlatform.h
@@ -13,6 +13,7 @@
#ifndef LLVM_EXECUTIONENGINE_ORC_ELFNIXPLATFORM_H
#define LLVM_EXECUTIONENGINE_ORC_ELFNIXPLATFORM_H
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ExecutionEngine/Orc/Core.h"
#include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h"
@@ -22,7 +23,6 @@
#include <future>
#include <thread>
-#include <unordered_map>
#include <vector>
namespace llvm {
@@ -43,27 +43,10 @@ struct RuntimeFunction {
ExecutorAddr Addr;
};
-struct FunctionPairKeyHash {
- std::size_t
- operator()(const std::pair<RuntimeFunction *, RuntimeFunction *> &key) const {
- return std::hash<void *>()(key.first->Addr.toPtr<void *>()) ^
- std::hash<void *>()(key.second->Addr.toPtr<void *>());
- }
-};
-
-struct FunctionPairKeyEqual {
- std::size_t
- operator()(const std::pair<RuntimeFunction *, RuntimeFunction *> &lhs,
- const std::pair<RuntimeFunction *, RuntimeFunction *> &rhs) const {
- return lhs.first == rhs.first && lhs.second == rhs.second;
- }
-};
-
-using DeferredRuntimeFnMap = std::unordered_map<
+using DeferredRuntimeFnMap = DenseMap<
std::pair<RuntimeFunction *, RuntimeFunction *>,
SmallVector<std::pair<shared::WrapperFunctionCall::ArgDataBufferType,
- shared::WrapperFunctionCall::ArgDataBufferType>>,
- FunctionPairKeyHash, FunctionPairKeyEqual>;
+ shared::WrapperFunctionCall::ArgDataBufferType>>>;
/// Mediates between ELFNix initialization and ExecutionSession state.
class LLVM_ABI ELFNixPlatform : public Platform {
diff --git a/llvm/include/llvm/MC/MCPseudoProbe.h b/llvm/include/llvm/MC/MCPseudoProbe.h
index 2079e41e319f0..e5f581a1758a2 100644
--- a/llvm/include/llvm/MC/MCPseudoProbe.h
+++ b/llvm/include/llvm/MC/MCPseudoProbe.h
@@ -69,7 +69,6 @@
#include <string>
#include <tuple>
#include <type_traits>
-#include <unordered_map>
#include <vector>
namespace llvm {
@@ -273,10 +272,12 @@ class MCPseudoProbeInlineTreeBase {
MCPseudoProbeInlineTreeBase<ProbesType, DerivedProbeInlineTreeType,
InlinedProbeTreeMap> *Parent = nullptr;
DerivedProbeInlineTreeType *getOrAddNode(const InlineSite &Site) {
- auto Ret = Children.emplace(
- Site, std::make_unique<DerivedProbeInlineTreeType>(Site));
- Ret.first->second->Parent = this;
- return Ret.first->second.get();
+ auto [It, Inserted] = Children.try_emplace(Site);
+ if (Inserted) {
+ It->second = std::make_unique<DerivedProbeInlineTreeType>(Site);
+ It->second->Parent = this;
+ }
+ return It->second.get();
};
};
@@ -285,17 +286,10 @@ class MCPseudoProbeInlineTreeBase {
// instance is created as the root of a tree.
// A real instance of this class is created for each function, either a
// not inlined function that has code in .text section or an inlined function.
-struct InlineSiteHash {
- uint64_t operator()(const InlineSite &Site) const {
- return std::get<0>(Site) ^ std::get<1>(Site);
- }
-};
class MCPseudoProbeInlineTree
: public MCPseudoProbeInlineTreeBase<
std::vector<MCPseudoProbe>, MCPseudoProbeInlineTree,
- std::unordered_map<InlineSite,
- std::unique_ptr<MCPseudoProbeInlineTree>,
- InlineSiteHash>> {
+ DenseMap<InlineSite, std::unique_ptr<MCPseudoProbeInlineTree>>> {
public:
MCPseudoProbeInlineTree() = default;
MCPseudoProbeInlineTree(uint64_t Guid) { this->Guid = Guid; }
@@ -345,12 +339,16 @@ class MCPseudoProbeSections {
public:
void addPseudoProbe(MCSymbol *FuncSym, const MCPseudoProbe &Probe,
const MCPseudoProbeInlineStack &InlineStack) {
- MCProbeDivisions[FuncSym].addPseudoProbe(Probe, InlineStack);
+ auto &Tree = MCProbeDivisions[FuncSym];
+ if (!Tree)
+ Tree = std::make_unique<MCPseudoProbeInlineTree>();
+ Tree->addPseudoProbe(Probe, InlineStack);
}
- // The addresses of MCPseudoProbeInlineTree are used by the tree structure and
- // need to be stable.
- using MCProbeDivisionMap = std::unordered_map<MCSymbol *, MCPseudoProbeInlineTree>;
+ // The addresses of MCPseudoProbeInlineTree are used by the tree structure
+ // and need to be stable, so the trees are heap-allocated.
+ using MCProbeDivisionMap =
+ DenseMap<MCSymbol *, std::unique_ptr<MCPseudoProbeInlineTree>>;
private:
// A collection of MCPseudoProbe for each function. The MCPseudoProbes are
@@ -394,8 +392,8 @@ class MCPseudoProbeDecoder {
// reallocation so that pointers to its elements will become invalid.
// 2) Probes belonging to function record must be contiguous in PseudoProbeVec
// as owning InlineTree references them with an ArrayRef to save space.
- std::unordered_map<const MCDecodedPseudoProbeInlineTree *,
- std::vector<MCDecodedPseudoProbe>>
+ DenseMap<const MCDecodedPseudoProbeInlineTree *,
+ std::vector<MCDecodedPseudoProbe>>
InjectedProbeMap;
// Decoded inline records vector.
std::vector<MCDecodedPseudoProbeInlineTree> InlineTreeVec;
diff --git a/llvm/include/llvm/ObjectYAML/DWARFYAML.h b/llvm/include/llvm/ObjectYAML/DWARFYAML.h
index 46ec59feef40f..363f2631c172e 100644
--- a/llvm/include/llvm/ObjectYAML/DWARFYAML.h
+++ b/llvm/include/llvm/ObjectYAML/DWARFYAML.h
@@ -15,6 +15,7 @@
#ifndef LLVM_OBJECTYAML_DWARFYAML_H
#define LLVM_OBJECTYAML_DWARFYAML_H
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/BinaryFormat/Dwarf.h"
@@ -288,7 +289,7 @@ struct Data {
LLVM_ABI StringRef getAbbrevTableContentByIndex(uint64_t Index) const;
private:
- mutable std::unordered_map<uint64_t, AbbrevTableInfo> AbbrevTableInfoMap;
+ mutable DenseMap<uint64_t, AbbrevTableInfo> AbbrevTableInfoMap;
mutable std::unordered_map<uint64_t, std::string> AbbrevTableContents;
};
diff --git a/llvm/include/llvm/ProfileData/MemProf.h b/llvm/include/llvm/ProfileData/MemProf.h
index e4bc9ee6f6ad1..391ac0f339f67 100644
--- a/llvm/include/llvm/ProfileData/MemProf.h
+++ b/llvm/include/llvm/ProfileData/MemProf.h
@@ -853,5 +853,17 @@ struct LineLocation {
// A pair of a call site location and its corresponding callee GUID.
using CallEdgeTy = std::pair<LineLocation, uint64_t>;
} // namespace memprof
+
+template <> struct DenseMapInfo<memprof::LineLocation> {
+ static unsigned getHashValue(const memprof::LineLocation &Val) {
+ return DenseMapInfo<uint64_t>::getHashValue(Val.getHashCode());
+ }
+
+ static bool isEqual(const memprof::LineLocation &LHS,
+ const memprof::LineLocation &RHS) {
+ return LHS == RHS;
+ }
+};
+
} // namespace llvm
#endif // LLVM_PROFILEDATA_MEMPROF_H
diff --git a/llvm/include/llvm/ProfileData/SampleProf.h b/llvm/include/llvm/ProfileData/SampleProf.h
index a3f25e5402ff9..cb0344e848c34 100644
--- a/llvm/include/llvm/ProfileData/SampleProf.h
+++ b/llvm/include/llvm/ProfileData/SampleProf.h
@@ -14,6 +14,7 @@
#ifndef LLVM_PROFILEDATA_SAMPLEPROF_H
#define LLVM_PROFILEDATA_SAMPLEPROF_H
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/SmallVector.h"
@@ -315,13 +316,22 @@ struct LineLocation {
uint32_t Discriminator;
};
-struct LineLocationHash {
- uint64_t operator()(const LineLocation &Loc) const {
- return Loc.getHashCode();
+LLVM_ABI raw_ostream &operator<<(raw_ostream &OS, const LineLocation &Loc);
+
+} // end namespace sampleprof
+
+template <> struct DenseMapInfo<sampleprof::LineLocation> {
+ static unsigned getHashValue(const sampleprof::LineLocation &Val) {
+ return DenseMapInfo<uint64_t>::getHashValue(Val.getHashCode());
+ }
+
+ static bool isEqual(const sampleprof::LineLocation &LHS,
+ const sampleprof::LineLocation &RHS) {
+ return LHS == RHS;
}
};
-LLVM_ABI raw_ostream &operator<<(raw_ostream &OS, const LineLocation &Loc);
+namespace sampleprof {
/// Key represents type of a C++ polymorphic class type by its vtable and value
/// represents its counter.
@@ -360,7 +370,7 @@ class SampleRecord {
};
using SortedCallTargetSet = std::set<CallTarget, CallTargetComparator>;
- using CallTargetMap = std::unordered_map<FunctionId, uint64_t>;
+ using CallTargetMap = DenseMap<FunctionId, uint64_t>;
SampleRecord() = default;
/// Increment the number of samples for this record by \p S.
@@ -772,8 +782,7 @@ using BodySampleMap = std::map<LineLocation, SampleRecord>;
using FunctionSamplesMap = std::map<FunctionId, FunctionSamples>;
using CallsiteSampleMap = std::map<LineLocation, FunctionSamplesMap>;
using CallsiteTypeMap = std::map<LineLocation, TypeCountMap>;
-using LocToLocMap =
- std::unordered_map<LineLocation, LineLocation, LineLocationHash>;
+using LocToLocMap = DenseMap<LineLocation, LineLocation>;
/// Representation of the samples collected for a function.
///
@@ -979,11 +988,11 @@ class FunctionSamples {
/// \p Loc with the maximum total sample count. If \p Remapper or \p
/// FuncNameToProfNameMap is not nullptr, use them to find FunctionSamples
/// with equivalent name as \p CalleeName.
- LLVM_ABI const FunctionSamples *findFunctionSamplesAt(
- const LineLocation &Loc, StringRef CalleeName,
- SampleProfileReaderItaniumRemapper *Remapper,
- const HashKeyMap<std::unordered_map, FunctionId, FunctionId>
- *FuncNameToProfNameMap = nullptr) const;
+ LLVM_ABI const FunctionSamples *
+ findFunctionSamplesAt(const LineLocation &Loc, StringRef CalleeName,
+ SampleProfileReaderItaniumRemapper *Remapper,
+ const HashKeyMap<DenseMap, FunctionId, FunctionId>
+ *FuncNameToProfNameMap = nullptr) const;
bool empty() const { return TotalSamples == 0; }
@@ -1154,10 +1163,10 @@ class FunctionSamples {
/// corresponding function is no less than \p Threshold, add its corresponding
/// GUID to \p S. Also traverse the BodySamples to add hot CallTarget's GUID
/// to \p S.
- void findInlinedFunctions(DenseSet<GlobalValue::GUID> &S,
- const HashKeyMap<std::unordered_map, FunctionId,
- Function *> &SymbolMap,
- uint64_t Threshold) const {
+ void findInlinedFunctions(
+ DenseSet<GlobalValue::GUID> &S,
+ const HashKeyMap<DenseMap, FunctionId, Function *> &SymbolMap,
+ uint64_t Threshold) const {
if (TotalSamples <= Threshold)
return;
auto IsDeclaration = [](const Function *F) {
@@ -1310,11 +1319,11 @@ class FunctionSamples {
/// If \p Remapper or \p FuncNameToProfNameMap is not nullptr, it will be used
/// to find matching FunctionSamples with not exactly the same but equivalent
/// name.
- LLVM_ABI const FunctionSamples *findFunctionSamples(
- const DILocation *DIL,
- SampleProfileReaderItaniumRemapper *Remapper = nullptr,
- const HashKeyMap<std::unordered_map, FunctionId, FunctionId>
- *FuncNameToProfNameMap = nullptr) const;
+ LLVM_ABI const FunctionSamples *
+ findFunctionSamples(const DILocation *DIL,
+ SampleProfileReaderItaniumRemapper *Remapper = nullptr,
+ const HashKeyMap<DenseMap, FunctionId, FunctionId>
+ *FuncNameToProfNameMap = nullptr) const;
LLVM_ABI static bool ProfileIsProbeBased;
diff --git a/llvm/include/llvm/ProfileData/SampleProfReader.h b/llvm/include/llvm/ProfileData/SampleProfReader.h
index 71140af3b25e3..9854e90e6ffe7 100644
--- a/llvm/include/llvm/ProfileData/SampleProfReader.h
+++ b/llvm/include/llvm/ProfileData/SampleProfReader.h
@@ -543,7 +543,7 @@ class SampleProfileReader {
void setModule(const Module *Mod) { M = Mod; }
void setFuncNameToProfNameMap(
- const HashKeyMap<std::unordered_map, FunctionId, FunctionId> &FPMap) {
+ const HashKeyMap<DenseMap, FunctionId, FunctionId> &FPMap) {
FuncNameToProfNameMap = &FPMap;
}
@@ -586,12 +586,12 @@ class SampleProfileReader {
// A map pointer to the FuncNameToProfNameMap in SampleProfileLoader,
// which maps the function name to the matched profile name. This is used
// for sample loader to look up profile using the new name.
- const HashKeyMap<std::unordered_map, FunctionId, FunctionId>
- *FuncNameToProfNameMap = nullptr;
+ const HashKeyMap<DenseMap, FunctionId, FunctionId> *FuncNameToProfNameMap =
+ nullptr;
// A map from a function's context hash to its meta data section range, used
// for on-demand read function profile metadata.
- std::unordered_map<uint64_t, std::pair<const uint8_t *, const uint8_t *>>
+ DenseMap<uint64_t, std::pair<const uint8_t *, const uint8_t *>>
FuncMetadataIndex;
std::pair<const uint8_t *, const uint8_t *> ProfileSecRange;
diff --git a/llvm/include/llvm/Transforms/IPO/GlobalDCE.h b/llvm/include/llvm/Transforms/IPO/GlobalDCE.h
index 9a0c8c20c13d1..ca38650075530 100644
--- a/llvm/include/llvm/Transforms/IPO/GlobalDCE.h
+++ b/llvm/include/llvm/Transforms/IPO/GlobalDCE.h
@@ -54,8 +54,7 @@ class GlobalDCEPass : public OptionalPassInfoMixin<GlobalDCEPass> {
DenseMap<GlobalValue *, SmallPtrSet<GlobalValue *, 4>> GVDependencies;
/// Constant -> Globals that use this global cache.
- std::unordered_map<Constant *, SmallPtrSet<GlobalValue *, 8>>
- ConstantDependenciesCache;
+ DenseMap<Constant *, SmallPtrSet<GlobalValue *, 8>> ConstantDependenciesCache;
/// Comdat -> Globals in that Comdat section.
std::unordered_multimap<Comdat *, GlobalValue *> ComdatMembers;
diff --git a/llvm/include/llvm/Transforms/IPO/SampleContextTracker.h b/llvm/include/llvm/Transforms/IPO/SampleContextTracker.h
index 1efe3ea127fd0..f8890899fedfb 100644
--- a/llvm/include/llvm/Transforms/IPO/SampleContextTracker.h
+++ b/llvm/include/llvm/Transforms/IPO/SampleContextTracker.h
@@ -215,8 +215,7 @@ class SampleContextTracker {
FuncToCtxtProfiles;
// Map from current FunctionSample to the belonged context trie.
- std::unordered_map<const FunctionSamples *, ContextTrieNode *>
- ProfileToNodeMap;
+ DenseMap<const FunctionSamples *, ContextTrieNode *> ProfileToNodeMap;
// Map from function guid to real function names. Only used in md5 mode.
const DenseMap<uint64_t, StringRef> *GUIDToFuncNameMap;
diff --git a/llvm/include/llvm/Transforms/IPO/SampleProfileMatcher.h b/llvm/include/llvm/Transforms/IPO/SampleProfileMatcher.h
index fa69177a822f4..22767cd058e21 100644
--- a/llvm/include/llvm/Transforms/IPO/SampleProfileMatcher.h
+++ b/llvm/include/llvm/Transforms/IPO/SampleProfileMatcher.h
@@ -14,12 +14,12 @@
#ifndef LLVM_TRANSFORMS_IPO_SAMPLEPROFILEMATCHER_H
#define LLVM_TRANSFORMS_IPO_SAMPLEPROFILEMATCHER_H
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Transforms/Utils/SampleProfileLoaderBaseImpl.h"
-#include <unordered_set>
-
namespace llvm {
using AnchorList = std::vector<std::pair<LineLocation, FunctionId>>;
@@ -59,21 +59,12 @@ class SampleProfileMatcher {
// For each function, store every callsite and its matching state into this
// map, of which each entry is a pair of callsite location and MatchState.
// This is used for profile staleness computation and report.
- StringMap<std::unordered_map<LineLocation, MatchState, LineLocationHash>>
- FuncCallsiteMatchStates;
-
- struct FuncToProfileNameMapHash {
- uint64_t
- operator()(const std::pair<const Function *, FunctionId> &P) const {
- return hash_combine(P.first, P.second);
- }
- };
+ StringMap<DenseMap<LineLocation, MatchState>> FuncCallsiteMatchStates;
+
// A map from a pair of function and profile name to a boolean value
// indicating whether they are matched. This is used as a cache for the
// matching result.
- std::unordered_map<std::pair<const Function *, FunctionId>, bool,
- FuncToProfileNameMapHash>
- FuncProfileMatchCache;
+ DenseMap<std::pair<const Function *, FunctionId>, bool> FuncProfileMatchCache;
// The new functions found by the call graph matching. The map's key is the
// the new(renamed) function pointer and the value is old(unused) profile
// name.
@@ -82,16 +73,15 @@ class SampleProfileMatcher {
// A map pointer to the FuncNameToProfNameMap in SampleProfileLoader,
// which maps the function name to the matched profile name. This is used
// for sample loader to look up profile using the new name.
- HashKeyMap<std::unordered_map, FunctionId, FunctionId> *FuncNameToProfNameMap;
+ HashKeyMap<DenseMap, FunctionId, FunctionId> *FuncNameToProfNameMap;
// A map pointer to the SymbolMap in SampleProfileLoader, which stores all
// the original matched symbols before the matching. this is to determine if
// the profile is unused(to be matched) or not.
- HashKeyMap<std::unordered_map, FunctionId, Function *> *SymbolMap;
+ HashKeyMap<DenseMap, FunctionId, Function *> *SymbolMap;
// The new functions from IR.
- HashKeyMap<std::unordered_map, FunctionId, Function *>
- FunctionsWithoutProfile;
+ HashKeyMap<DenseMap, FunctionId, Function *> FunctionsWithoutProfile;
// Pointer to the Profile Symbol List in the reader.
std::shared_ptr<ProfileSymbolList> PSL;
@@ -123,10 +113,9 @@ class SampleProfileMatcher {
SampleProfileMatcher(
Module &M, SampleProfileReader &Reader, LazyCallGraph &CG,
const PseudoProbeManager *ProbeManager, ThinOrFullLTOPhase LTOPhase,
- HashKeyMap<std::unordered_map, FunctionId, Function *> &SymMap,
+ HashKeyMap<DenseMap, FunctionId, Function *> &SymMap,
std::shared_ptr<ProfileSymbolList> PSL,
- HashKeyMap<std::unordered_map, FunctionId, FunctionId>
- &FuncNameToProfNameMap)
+ HashKeyMap<DenseMap, FunctionId, FunctionId> &FuncNameToProfNameMap)
: M(M), Reader(Reader), CG(CG), ProbeManager(ProbeManager),
LTOPhase(LTOPhase), FuncNameToProfNameMap(&FuncNameToProfNameMap),
SymbolMap(&SymMap), PSL(PSL) {};
@@ -189,9 +178,9 @@ class SampleProfileMatcher {
State == MatchState::RemovedMatch;
};
- void countCallGraphRecoveredSamples(
- const FunctionSamples &FS,
- std::unordered_set<FunctionId> &MatchedUnusedProfile);
+ void
+ countCallGraphRecoveredSamples(const FunctionSamples &FS,
+ DenseSet<FunctionId> &MatchedUnusedProfile);
// Count the samples of checksum mismatched function for the top-level
// function and all inlinees.
void countMismatchedFuncSamples(const FunctionSamples &FS, bool IsTopLevel);
diff --git a/llvm/include/llvm/Transforms/IPO/SampleProfileProbe.h b/llvm/include/llvm/Transforms/IPO/SampleProfileProbe.h
index bdb01ab353a84..1f6234f6778b0 100644
--- a/llvm/include/llvm/Transforms/IPO/SampleProfileProbe.h
+++ b/llvm/include/llvm/Transforms/IPO/SampleProfileProbe.h
@@ -20,7 +20,6 @@
#include "llvm/IR/PassManager.h"
#include "llvm/ProfileData/SampleProf.h"
#include "llvm/Support/Compiler.h"
-#include <unordered_map>
namespace llvm {
class BasicBlock;
@@ -33,12 +32,11 @@ class TargetMachine;
class Module;
using namespace sampleprof;
-using BlockIdMap = std::unordered_map<BasicBlock *, uint32_t>;
-using InstructionIdMap = std::unordered_map<Instruction *, uint32_t>;
+using BlockIdMap = DenseMap<BasicBlock *, uint32_t>;
+using InstructionIdMap = DenseMap<Instruction *, uint32_t>;
// Map from tuples of Probe id and inline stack hash code to distribution
// factors.
-using ProbeFactorMap = std::unordered_map<std::pair<uint64_t, uint64_t>, float,
- pair_hash<uint64_t, uint64_t>>;
+using ProbeFactorMap = DenseMap<std::pair<uint64_t, uint64_t>, float>;
using FuncProbeFactorMap = StringMap<ProbeFactorMap>;
diff --git a/llvm/include/llvm/Transforms/Instrumentation/MemProfUse.h b/llvm/include/llvm/Transforms/Instrumentation/MemProfUse.h
index 5402ee25fc35c..01104097180e4 100644
--- a/llvm/include/llvm/Transforms/Instrumentation/MemProfUse.h
+++ b/llvm/include/llvm/Transforms/Instrumentation/MemProfUse.h
@@ -18,8 +18,6 @@
#include "llvm/ProfileData/MemProf.h"
#include "llvm/Support/Compiler.h"
-#include <unordered_map>
-
namespace llvm {
class IndexedInstrProfReader;
class Module;
@@ -56,14 +54,7 @@ LLVM_ABI DenseMap<uint64_t, SmallVector<CallEdgeTy, 0>> extractCallsFromIR(
return true;
});
-struct LineLocationHash {
- uint64_t operator()(const LineLocation &Loc) const {
- return Loc.getHashCode();
- }
-};
-
-using LocToLocMap =
- std::unordered_map<LineLocation, LineLocation, LineLocationHash>;
+using LocToLocMap = DenseMap<LineLocation, LineLocation>;
// Compute an undrifting map. The result is a map from caller GUIDs to an inner
// map that maps source locations in the profile to those in the current IR.
diff --git a/llvm/lib/CGData/OutlinedHashTree.cpp b/llvm/lib/CGData/OutlinedHashTree.cpp
index 7ddab66ae41f3..cc30feb30f67f 100644
--- a/llvm/lib/CGData/OutlinedHashTree.cpp
+++ b/llvm/lib/CGData/OutlinedHashTree.cpp
@@ -78,7 +78,7 @@ void OutlinedHashTree::insert(const HashSequencePair &SequencePair) {
std::unique_ptr<HashNode> Next = std::make_unique<HashNode>();
HashNode *NextPtr = Next.get();
NextPtr->Hash = StableHash;
- Current->Successors.emplace(StableHash, std::move(Next));
+ Current->Successors.try_emplace(StableHash, std::move(Next));
Current = NextPtr;
} else
Current = I->second.get();
@@ -106,7 +106,7 @@ void OutlinedHashTree::merge(const OutlinedHashTree *Tree) {
auto NextDst = std::make_unique<HashNode>();
NextDstNode = NextDst.get();
NextDstNode->Hash = Hash;
- DstNode->Successors.emplace(Hash, std::move(NextDst));
+ DstNode->Successors.try_emplace(Hash, std::move(NextDst));
} else
NextDstNode = I->second.get();
diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
index ccec0b5910658..205bb193d32b6 100644
--- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
@@ -237,8 +237,13 @@ CodeViewDebug::InlineSite &
CodeViewDebug::getInlineSite(const DILocation *InlinedAt,
const DISubprogram *Inlinee) {
auto SiteInsertion = CurFn->InlineSites.try_emplace(InlinedAt);
- InlineSite *Site = &SiteInsertion.first->second;
- if (SiteInsertion.second) {
+ bool Inserted = SiteInsertion.second;
+ if (Inserted)
+ SiteInsertion.first->second = std::make_unique<InlineSite>();
+ // The InlineSite is heap-allocated, so Site stays valid while the recursive
+ // getInlineSite call below grows InlineSites.
+ InlineSite *Site = SiteInsertion.first->second.get();
+ if (Inserted) {
unsigned ParentFuncId = CurFn->FuncId;
if (const DILocation *OuterIA = InlinedAt->getInlinedAt())
ParentFuncId =
@@ -1046,7 +1051,7 @@ void CodeViewDebug::emitInlinedCallSite(const FunctionInfo &FI,
auto I = FI.InlineSites.find(ChildSite);
assert(I != FI.InlineSites.end() &&
"child site not in function inline site map");
- emitInlinedCallSite(FI, ChildSite, I->second);
+ emitInlinedCallSite(FI, ChildSite, *I->second);
}
// Close the scope.
@@ -1222,7 +1227,7 @@ void CodeViewDebug::emitDebugInfoForFunction(const Function *GV,
auto I = FI.InlineSites.find(InlinedAt);
assert(I != FI.InlineSites.end() &&
"child site not in function inline site map");
- emitInlinedCallSite(FI, InlinedAt, I->second);
+ emitInlinedCallSite(FI, InlinedAt, *I->second);
}
for (auto Annot : FI.Annotations) {
@@ -3052,12 +3057,15 @@ void CodeViewDebug::collectLexicalBlockInfo(
auto BlockInsertion = CurFn->LexicalBlocks.try_emplace(DILB);
if (!BlockInsertion.second)
return;
+ BlockInsertion.first->second = std::make_unique<LexicalBlock>();
// Create a lexical block containing the variables and collect the
// lexical block information for the children.
const InsnRange &Range = Ranges.front();
assert(Range.first && Range.second);
- LexicalBlock &Block = BlockInsertion.first->second;
+ // The LexicalBlock is heap-allocated, so Block stays valid while the
+ // recursive collectLexicalBlockInfo call below grows LexicalBlocks.
+ LexicalBlock &Block = *BlockInsertion.first->second;
Block.Begin = getLabelBeforeInsn(Range.first);
Block.End = getLabelAfterInsn(Range.second);
assert(Block.Begin && "missing label for scope begin");
diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h
index 04a75a21d7679..148e980c737e8 100644
--- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h
+++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h
@@ -33,9 +33,9 @@
#include "llvm/Support/Compiler.h"
#include <cstdint>
#include <map>
+#include <memory>
#include <string>
#include <tuple>
-#include <unordered_map>
#include <utility>
#include <vector>
@@ -176,7 +176,7 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
/// Map from inlined call site to inlined instructions and child inlined
/// call sites. Listed in program order.
- std::unordered_map<const DILocation *, InlineSite> InlineSites;
+ DenseMap<const DILocation *, std::unique_ptr<InlineSite>> InlineSites;
/// Ordered list of top-level inlined call sites.
SmallVector<const DILocation *, 1> ChildSites;
@@ -187,7 +187,8 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
SmallVector<LocalVariable, 1> Locals;
SmallVector<CVGlobalVariable, 1> Globals;
- std::unordered_map<const DILexicalBlockBase*, LexicalBlock> LexicalBlocks;
+ DenseMap<const DILexicalBlockBase *, std::unique_ptr<LexicalBlock>>
+ LexicalBlocks;
// Lexical blocks containing local variables.
SmallVector<LexicalBlock *, 1> ChildBlocks;
diff --git a/llvm/lib/CodeGen/LexicalScopes.cpp b/llvm/lib/CodeGen/LexicalScopes.cpp
index 9fc9ac9a66d41..3966ca8f23be8 100644
--- a/llvm/lib/CodeGen/LexicalScopes.cpp
+++ b/llvm/lib/CodeGen/LexicalScopes.cpp
@@ -148,7 +148,7 @@ LexicalScope *LexicalScopes::findLexicalScope(const DILocation *DL) {
if (auto *IA = DL->getInlinedAt()) {
auto I = InlinedLexicalScopeMap.find(std::make_pair(Scope, IA));
- return I != InlinedLexicalScopeMap.end() ? &I->second : nullptr;
+ return I != InlinedLexicalScopeMap.end() ? I->second.get() : nullptr;
}
return findLexicalScope(Scope);
}
@@ -178,24 +178,24 @@ LexicalScopes::getOrCreateRegularScope(const DILocalScope *Scope) {
auto I = LexicalScopeMap.find(Scope);
if (I != LexicalScopeMap.end())
- return &I->second;
+ return I->second.get();
// FIXME: Should the following dyn_cast be DILexicalBlock?
LexicalScope *Parent = nullptr;
if (auto *Block = dyn_cast<DILexicalBlockBase>(Scope))
Parent = getOrCreateLexicalScope(Block->getScope());
- I = LexicalScopeMap.emplace(std::piecewise_construct,
- std::forward_as_tuple(Scope),
- std::forward_as_tuple(Parent, Scope, nullptr,
- false)).first;
+ I = LexicalScopeMap
+ .try_emplace(Scope, std::make_unique<LexicalScope>(Parent, Scope,
+ nullptr, false))
+ .first;
if (!Parent) {
assert(cast<DISubprogram>(Scope)->describes(&MF->getFunction()));
assert(!CurrentFnLexicalScope);
- CurrentFnLexicalScope = &I->second;
+ CurrentFnLexicalScope = I->second.get();
}
- return &I->second;
+ return I->second.get();
}
/// getOrCreateInlinedScope - Find or create an inlined lexical scope.
@@ -207,7 +207,7 @@ LexicalScopes::getOrCreateInlinedScope(const DILocalScope *Scope,
std::pair<const DILocalScope *, const DILocation *> P(Scope, InlinedAt);
auto I = InlinedLexicalScopeMap.find(P);
if (I != InlinedLexicalScopeMap.end())
- return &I->second;
+ return I->second.get();
LexicalScope *Parent;
if (auto *Block = dyn_cast<DILexicalBlockBase>(Scope))
@@ -216,10 +216,10 @@ LexicalScopes::getOrCreateInlinedScope(const DILocalScope *Scope,
Parent = getOrCreateLexicalScope(InlinedAt);
I = InlinedLexicalScopeMap
- .emplace(std::piecewise_construct, std::forward_as_tuple(P),
- std::forward_as_tuple(Parent, Scope, InlinedAt, false))
+ .try_emplace(P, std::make_unique<LexicalScope>(Parent, Scope,
+ InlinedAt, false))
.first;
- return &I->second;
+ return I->second.get();
}
/// getOrCreateAbstractScope - Find or create an abstract lexical scope.
@@ -229,20 +229,20 @@ LexicalScopes::getOrCreateAbstractScope(const DILocalScope *Scope) {
Scope = Scope->getNonLexicalBlockFileScope();
auto I = AbstractScopeMap.find(Scope);
if (I != AbstractScopeMap.end())
- return &I->second;
+ return I->second.get();
// FIXME: Should the following isa be DILexicalBlock?
LexicalScope *Parent = nullptr;
if (auto *Block = dyn_cast<DILexicalBlockBase>(Scope))
Parent = getOrCreateAbstractScope(Block->getScope());
- I = AbstractScopeMap.emplace(std::piecewise_construct,
- std::forward_as_tuple(Scope),
- std::forward_as_tuple(Parent, Scope,
- nullptr, true)).first;
+ I = AbstractScopeMap
+ .try_emplace(Scope, std::make_unique<LexicalScope>(Parent, Scope,
+ nullptr, true))
+ .first;
if (isa<DISubprogram>(Scope))
- AbstractScopesList.push_back(&I->second);
- return &I->second;
+ AbstractScopesList.push_back(I->second.get());
+ return I->second.get();
}
/// constructScopeNest - Traverse the Scope tree depth-first, storing
diff --git a/llvm/lib/CodeGen/LiveStacks.cpp b/llvm/lib/CodeGen/LiveStacks.cpp
index c07d985a09d1f..b76ec1195dc73 100644
--- a/llvm/lib/CodeGen/LiveStacks.cpp
+++ b/llvm/lib/CodeGen/LiveStacks.cpp
@@ -52,20 +52,17 @@ void LiveStacks::init(MachineFunction &MF) {
LiveInterval &
LiveStacks::getOrCreateInterval(int Slot, const TargetRegisterClass *RC) {
assert(Slot >= 0 && "Spill slot indice must be >= 0");
- SS2IntervalMap::iterator I = S2IMap.find(Slot);
- if (I == S2IMap.end()) {
- I = S2IMap
- .emplace(
- std::piecewise_construct, std::forward_as_tuple(Slot),
- std::forward_as_tuple(Register::index2StackSlot(Slot), 0.0F))
- .first;
+ auto [I, Inserted] = S2IMap.try_emplace(Slot);
+ if (Inserted) {
+ I->second =
+ std::make_unique<LiveInterval>(Register::index2StackSlot(Slot), 0.0F);
S2RCMap.insert(std::make_pair(Slot, RC));
} else {
// Use the largest common subclass register class.
const TargetRegisterClass *&OldRC = S2RCMap[Slot];
OldRC = TRI->getCommonSubClass(OldRC, RC);
}
- return I->second;
+ return *I->second;
}
AnalysisKey LiveStacksAnalysis::Key;
@@ -99,9 +96,13 @@ void LiveStacksWrapperLegacy::print(raw_ostream &OS, const Module *) const {
void LiveStacks::print(raw_ostream &OS, const Module*) const {
OS << "********** INTERVALS **********\n";
- for (const_iterator I = begin(), E = end(); I != E; ++I) {
- I->second.print(OS);
- int Slot = I->first;
+ // Print in slot order for deterministic output.
+ SmallVector<int, 8> Slots;
+ for (const_iterator I = begin(), E = end(); I != E; ++I)
+ Slots.push_back(I->first);
+ llvm::sort(Slots);
+ for (int Slot : Slots) {
+ getInterval(Slot).print(OS);
const TargetRegisterClass *RC = getIntervalRegClass(Slot);
if (RC)
OS << " [" << TRI->getRegClassName(RC) << "]\n";
diff --git a/llvm/lib/CodeGen/RDFGraph.cpp b/llvm/lib/CodeGen/RDFGraph.cpp
index 7e7407e117dee..b172e70288986 100644
--- a/llvm/lib/CodeGen/RDFGraph.cpp
+++ b/llvm/lib/CodeGen/RDFGraph.cpp
@@ -1015,13 +1015,14 @@ void DataFlowGraph::releaseBlock(NodeId B, DefStackMap &DefM) {
for (auto &P : DefM)
P.second.clear_block(B);
- // Finally, remove empty stacks from the map.
- for (auto I = DefM.begin(), E = DefM.end(), NextI = I; I != E; I = NextI) {
- NextI = std::next(I);
- // This preserves the validity of iterators other than I.
- if (I->second.empty())
- DefM.erase(I);
- }
+ // Finally, remove empty stacks from the map. DenseMap's erase relocates
+ // other elements, so collect the keys first.
+ SmallVector<RegisterId, 8> EmptyRegs;
+ for (auto &P : DefM)
+ if (P.second.empty())
+ EmptyRegs.push_back(P.first);
+ for (RegisterId R : EmptyRegs)
+ DefM.erase(R);
}
// Push all definitions from the instruction node IA to an appropriate
diff --git a/llvm/lib/CodeGen/RDFLiveness.cpp b/llvm/lib/CodeGen/RDFLiveness.cpp
index 10ab9b88a05e1..f0aa434bc3a53 100644
--- a/llvm/lib/CodeGen/RDFLiveness.cpp
+++ b/llvm/lib/CodeGen/RDFLiveness.cpp
@@ -573,8 +573,10 @@ void Liveness::computePhiInfo() {
UI->second.insert({I.first, S.Mask});
}
}
- UI = UI->second.empty() ? RealUses.erase(UI) : std::next(UI);
+ ++UI;
}
+ // Drop the entries whose use sets ended up empty.
+ emptify(RealUses);
// If this phi reaches some "real" uses, add it to the queue for upward
// propagation.
@@ -696,7 +698,7 @@ void Liveness::computePhiInfo() {
// if MidDefs does not cover (R,U)
// then add (R-MidDefs,U) to RealUseMap[P]
//
- for (const std::pair<const RegisterId, NodeRefSet> &T : RUM) {
+ for (const auto &T : RUM) {
RegisterRef R(T.first);
// The current phi (PA) could be a phi for a regmask. It could
// reach a whole variety of uses that are not related to the
@@ -829,7 +831,7 @@ void Liveness::computeLiveIns() {
auto PrA = DFG.addr<BlockNode *>(PUA.Addr->getPredecessor());
RefMap &LOX = PhiLOX[PrA.Addr->getCode()];
- for (const std::pair<const RegisterId, NodeRefSet> &RS : RUs) {
+ for (const auto &RS : RUs) {
// We need to visit each individual use.
for (std::pair<NodeId, LaneBitmask> P : RS.second) {
// Create a register ref corresponding to the use, and find
@@ -1047,7 +1049,7 @@ void Liveness::traverse(MachineBasicBlock *B, RefMap &LiveIn) {
RefMap LiveInCopy = LiveIn;
LiveIn.clear();
- for (const std::pair<const RegisterId, NodeRefSet> &LE : LiveInCopy) {
+ for (const auto &LE : LiveInCopy) {
RegisterRef LRef(LE.first);
NodeRefSet &NewDefs = LiveIn[LRef.Id]; // To be filled.
const NodeRefSet &OldDefs = LE.second;
@@ -1161,7 +1163,7 @@ void Liveness::traverse(MachineBasicBlock *B, RefMap &LiveIn) {
for (auto *C : IIDF[B]) {
RegisterAggr &LiveC = LiveMap[C];
- for (const std::pair<const RegisterId, NodeRefSet> &S : LiveIn)
+ for (const auto &S : LiveIn)
for (auto R : S.second)
if (MDT.properlyDominates(getBlockWithRef(R.first), C))
LiveC.insert(RegisterRef(S.first, R.second));
@@ -1169,8 +1171,13 @@ void Liveness::traverse(MachineBasicBlock *B, RefMap &LiveIn) {
}
void Liveness::emptify(RefMap &M) {
- for (auto I = M.begin(), E = M.end(); I != E;)
- I = I->second.empty() ? M.erase(I) : std::next(I);
+ // DenseMap's erase relocates other elements, so collect the keys first.
+ SmallVector<RegisterId, 8> Empty;
+ for (auto &P : M)
+ if (P.second.empty())
+ Empty.push_back(P.first);
+ for (RegisterId R : Empty)
+ M.erase(R);
}
} // namespace llvm::rdf
diff --git a/llvm/lib/CodeGen/StackSlotColoring.cpp b/llvm/lib/CodeGen/StackSlotColoring.cpp
index 105f9e93c7fbb..fad2e03baa6f5 100644
--- a/llvm/lib/CodeGen/StackSlotColoring.cpp
+++ b/llvm/lib/CodeGen/StackSlotColoring.cpp
@@ -273,7 +273,7 @@ void StackSlotColoring::InitializeSlots() {
// Gather all spill slots into a list.
LLVM_DEBUG(dbgs() << "Spill slot intervals:\n");
for (auto *I : Intervals) {
- LiveInterval &li = I->second;
+ LiveInterval &li = *I->second;
LLVM_DEBUG(li.dump());
int FI = li.reg().stackSlotIndex();
if (MFI->isDeadObjectIndex(FI))
diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolFunc.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolFunc.cpp
index beb9197fe055d..25ce8c5e3d63f 100644
--- a/llvm/lib/DebugInfo/PDB/PDBSymbolFunc.cpp
+++ b/llvm/lib/DebugInfo/PDB/PDBSymbolFunc.cpp
@@ -8,6 +8,7 @@
#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
+#include "llvm/ADT/StringSet.h"
#include "llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h"
#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
#include "llvm/DebugInfo/PDB/IPDBLineNumber.h"
@@ -17,7 +18,6 @@
#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h"
#include "llvm/DebugInfo/PDB/PDBTypes.h"
-#include <unordered_set>
#include <utility>
#include <vector>
@@ -34,7 +34,7 @@ class FunctionArgEnumerator : public IPDBEnumChildren<PDBSymbolData> {
: Session(PDBSession), Func(PDBFunc) {
// Arguments can appear multiple times if they have live range
// information, so we only take the first occurrence.
- std::unordered_set<std::string> SeenNames;
+ StringSet<> SeenNames;
auto DataChildren = Func.findAllChildren<PDBSymbolData>();
while (auto Child = DataChildren->getNext()) {
if (Child->getDataKind() == PDB_DataKind::Param) {
diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h
index 89b20978c40e6..ee2163558f61f 100644
--- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h
+++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h
@@ -13,6 +13,7 @@
#ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_RUNTIMEDYLDIMPL_H
#define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_RUNTIMEDYLDIMPL_H
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ExecutionEngine/Orc/SymbolStringPool.h"
@@ -30,7 +31,6 @@
#include <deque>
#include <map>
#include <system_error>
-#include <unordered_map>
using namespace llvm;
using namespace llvm::object;
@@ -270,7 +270,7 @@ class RuntimeDyldImpl {
// Relocations to sections already loaded. Indexed by SectionID which is the
// source of the address. The target where the address will be written is
// SectionID/Offset in the relocation itself.
- std::unordered_map<unsigned, RelocationList> Relocations;
+ DenseMap<unsigned, RelocationList> Relocations;
// Relocations to external symbols that are not yet resolved. Symbols are
// external when they aren't found in the global symbol table of all loaded
diff --git a/llvm/lib/IR/PrintPasses.cpp b/llvm/lib/IR/PrintPasses.cpp
index 5c14e3bc2a1e6..643aa69741d13 100644
--- a/llvm/lib/IR/PrintPasses.cpp
+++ b/llvm/lib/IR/PrintPasses.cpp
@@ -8,6 +8,7 @@
#include "llvm/IR/PrintPasses.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringSet.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Errc.h"
@@ -17,7 +18,6 @@
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/raw_ostream.h"
-#include <unordered_set>
using namespace llvm;
@@ -155,18 +155,15 @@ bool llvm::forcePrintModuleIR() { return PrintModuleScope; }
bool llvm::forcePrintFuncIR() { return LoopPrintFuncScope; }
bool llvm::isPassInPrintList(StringRef PassName) {
- static std::unordered_set<std::string> Set(FilterPasses.begin(),
- FilterPasses.end());
- return Set.empty() || Set.count(std::string(PassName));
+ static const StringSet<> Set(llvm::from_range, FilterPasses);
+ return Set.empty() || Set.contains(PassName);
}
bool llvm::isFilterPassesEmpty() { return FilterPasses.empty(); }
bool llvm::isFunctionInPrintList(StringRef FunctionName) {
- static std::unordered_set<std::string> PrintFuncNames(PrintFuncsList.begin(),
- PrintFuncsList.end());
- return PrintFuncNames.empty() ||
- PrintFuncNames.count(std::string(FunctionName));
+ static const StringSet<> PrintFuncNames(llvm::from_range, PrintFuncsList);
+ return PrintFuncNames.empty() || PrintFuncNames.contains(FunctionName);
}
std::error_code cleanUpTempFilesImpl(ArrayRef<std::string> FileName,
diff --git a/llvm/lib/MC/MCPseudoProbe.cpp b/llvm/lib/MC/MCPseudoProbe.cpp
index 99cba8e3d8375..8dea1908154ec 100644
--- a/llvm/lib/MC/MCPseudoProbe.cpp
+++ b/llvm/lib/MC/MCPseudoProbe.cpp
@@ -213,7 +213,7 @@ void MCPseudoProbeSections::emit(MCObjectStreamer *MCOS) {
SmallVector<std::pair<MCSymbol *, MCPseudoProbeInlineTree *>> Vec;
Vec.reserve(MCProbeDivisions.size());
for (auto &ProbeSec : MCProbeDivisions)
- Vec.emplace_back(ProbeSec.first, &ProbeSec.second);
+ Vec.emplace_back(ProbeSec.first, ProbeSec.second.get());
for (auto I : llvm::enumerate(MCOS->getAssembler()))
I.value().setOrdinal(I.index());
llvm::sort(Vec, [](auto A, auto B) {
diff --git a/llvm/lib/ProfileData/SampleProf.cpp b/llvm/lib/ProfileData/SampleProf.cpp
index a7d784a72e380..8b81cfeecc9fe 100644
--- a/llvm/lib/ProfileData/SampleProf.cpp
+++ b/llvm/lib/ProfileData/SampleProf.cpp
@@ -308,8 +308,8 @@ LineLocation FunctionSamples::getCallSiteIdentifier(const DILocation *DIL,
const FunctionSamples *FunctionSamples::findFunctionSamples(
const DILocation *DIL, SampleProfileReaderItaniumRemapper *Remapper,
- const HashKeyMap<std::unordered_map, FunctionId, FunctionId>
- *FuncNameToProfNameMap) const {
+ const HashKeyMap<DenseMap, FunctionId, FunctionId> *FuncNameToProfNameMap)
+ const {
assert(DIL);
SmallVector<std::pair<LineLocation, StringRef>, 10> S;
@@ -351,8 +351,8 @@ void FunctionSamples::findAllNames(DenseSet<FunctionId> &NameSet) const {
const FunctionSamples *FunctionSamples::findFunctionSamplesAt(
const LineLocation &Loc, StringRef CalleeName,
SampleProfileReaderItaniumRemapper *Remapper,
- const HashKeyMap<std::unordered_map, FunctionId, FunctionId>
- *FuncNameToProfNameMap) const {
+ const HashKeyMap<DenseMap, FunctionId, FunctionId> *FuncNameToProfNameMap)
+ const {
CalleeName = getCanonicalFnName(CalleeName);
auto I = CallsiteSamples.find(mapIRLocToProfileLoc(Loc));
diff --git a/llvm/lib/Support/Z3Solver.cpp b/llvm/lib/Support/Z3Solver.cpp
index 88851d2a24ce7..6715e43cf9c49 100644
--- a/llvm/lib/Support/Z3Solver.cpp
+++ b/llvm/lib/Support/Z3Solver.cpp
@@ -16,10 +16,10 @@ using namespace llvm;
#if LLVM_WITH_Z3
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/Twine.h"
#include <set>
-#include <unordered_map>
#include <z3.h>
@@ -938,19 +938,19 @@ class Z3Statistics final : public SMTSolverStatistics {
};
void print(raw_ostream &OS) const override {
- for (auto const &[K, V] : UnsignedValues) {
- OS << K << ": " << V << '\n';
+ for (const auto &E : UnsignedValues) {
+ OS << E.first() << ": " << E.second << '\n';
}
- for (auto const &[K, V] : DoubleValues) {
- write_double(OS << K << ": ", V, FloatStyle::Fixed);
+ for (const auto &E : DoubleValues) {
+ write_double(OS << E.first() << ": ", E.second, FloatStyle::Fixed);
OS << '\n';
}
}
private:
friend class Z3Solver;
- std::unordered_map<std::string, unsigned> UnsignedValues;
- std::unordered_map<std::string, double> DoubleValues;
+ StringMap<unsigned> UnsignedValues;
+ StringMap<double> DoubleValues;
};
std::unique_ptr<SMTSolverStatistics> Z3Solver::getStatistics() const {
diff --git a/llvm/lib/Target/AArch64/AArch64.h b/llvm/lib/Target/AArch64/AArch64.h
index a3660256ff4f9..e84c2bab20207 100644
--- a/llvm/lib/Target/AArch64/AArch64.h
+++ b/llvm/lib/Target/AArch64/AArch64.h
@@ -16,6 +16,7 @@
#include "MCTargetDesc/AArch64MCTargetDesc.h"
#include "Utils/AArch64BaseInfo.h"
+#include "llvm/ADT/StringMap.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionAnalysisManager.h"
#include "llvm/CodeGen/SelectionDAGISel.h"
@@ -25,7 +26,6 @@
#include "llvm/Target/TargetMachine.h"
#include <map>
#include <memory>
-#include <unordered_map>
struct AArch64O0PreLegalizerCombinerImplRuleConfig;
struct AArch64PreLegalizerCombinerImplRuleConfig;
@@ -302,7 +302,7 @@ class AArch64ConditionOptimizerPass
class AArch64SIMDInstrOptPass
: public OptionalPassInfoMixin<AArch64SIMDInstrOptPass> {
std::map<std::pair<unsigned, std::string>, bool> SIMDInstrTable;
- std::unordered_map<std::string, bool> InterlEarlyExit;
+ StringMap<bool> InterlEarlyExit;
public:
PreservedAnalyses run(MachineFunction &MF,
diff --git a/llvm/lib/Target/AArch64/AArch64SIMDInstrOpt.cpp b/llvm/lib/Target/AArch64/AArch64SIMDInstrOpt.cpp
index 4b27b77735284..1336b9f7af3c7 100644
--- a/llvm/lib/Target/AArch64/AArch64SIMDInstrOpt.cpp
+++ b/llvm/lib/Target/AArch64/AArch64SIMDInstrOpt.cpp
@@ -36,6 +36,7 @@
#include "AArch64Subtarget.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
+#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineFunction.h"
@@ -52,7 +53,6 @@
#include "llvm/MC/MCSchedule.h"
#include "llvm/Pass.h"
#include <map>
-#include <unordered_map>
using namespace llvm;
@@ -78,7 +78,7 @@ class AArch64SIMDInstrOptImpl {
using SIMDInstrTableMap = std::map<std::pair<unsigned, std::string>, bool>;
- using InterlEarlyExitMap = std::unordered_map<std::string, bool>;
+ using InterlEarlyExitMap = StringMap<bool>;
// The two maps below are used to cache decisions instead of recomputing. Note
// that we're only storing references, the data is scoped at the Pass level to
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUMarkLastScratchLoad.cpp b/llvm/lib/Target/AMDGPU/AMDGPUMarkLastScratchLoad.cpp
index 9b6bb56c85d24..639a875909851 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUMarkLastScratchLoad.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUMarkLastScratchLoad.cpp
@@ -103,14 +103,14 @@ bool AMDGPUMarkLastScratchLoad::run(MachineFunction &MF) {
bool Changed = false;
for (auto &[SS, LI] : *LS) {
- for (const LiveRange::Segment &Segment : LI.segments) {
+ for (const LiveRange::Segment &Segment : LI->segments) {
// Ignore segments that run to the end of basic block because in this case
// slot is still live at the end of it.
if (Segment.end.isBlock())
continue;
- const int FrameIndex = LI.reg().stackSlotIndex();
+ const int FrameIndex = LI->reg().stackSlotIndex();
MachineInstr *LastLoad = nullptr;
MachineInstr *MISegmentEnd = SI->getInstructionFromIndex(Segment.end);
diff --git a/llvm/lib/Target/AMDGPU/AMDGPURewriteAGPRCopyMFMA.cpp b/llvm/lib/Target/AMDGPU/AMDGPURewriteAGPRCopyMFMA.cpp
index 1d39b4f1bc52d..aebc9865d39e8 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPURewriteAGPRCopyMFMA.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPURewriteAGPRCopyMFMA.cpp
@@ -492,7 +492,7 @@ void AMDGPURewriteAGPRCopyMFMAImpl::eliminateSpillsOfReassignedVGPRs() const {
const TargetRegisterClass *RC = LSS.getIntervalRegClass(Slot);
if (TRI.hasVGPRs(RC))
- StackIntervals.push_back(&LI);
+ StackIntervals.push_back(LI.get());
}
sort(StackIntervals, [](const LiveInterval *A, const LiveInterval *B) {
diff --git a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp
index f4a7b4e78245f..fafb4e737ac4c 100644
--- a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp
+++ b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp
@@ -19,6 +19,7 @@
#include "MCTargetDesc/HexagonMCInstrInfo.h"
#include "TargetInfo/HexagonTargetInfo.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/MC/MCAsmBackend.h"
@@ -43,7 +44,6 @@
#include <mutex>
#include <new>
#include <string>
-#include <unordered_map>
using namespace llvm;
@@ -527,14 +527,13 @@ std::pair<std::string, std::string> selectCPUAndFS(StringRef CPU,
return Result;
}
std::mutex ArchSubtargetMutex;
-std::unordered_map<std::string, std::unique_ptr<MCSubtargetInfo const>>
- ArchSubtarget;
+StringMap<std::unique_ptr<MCSubtargetInfo const>> ArchSubtarget;
} // namespace
MCSubtargetInfo const *
Hexagon_MC::getArchSubtarget(MCSubtargetInfo const *STI) {
std::lock_guard<std::mutex> Lock(ArchSubtargetMutex);
- auto Existing = ArchSubtarget.find(std::string(STI->getCPU()));
+ auto Existing = ArchSubtarget.find(STI->getCPU());
if (Existing == ArchSubtarget.end())
return nullptr;
return Existing->second.get();
@@ -673,7 +672,7 @@ void Hexagon_MC::addArchSubtarget(MCSubtargetInfo const *STI, StringRef FS) {
auto ArchSTI = createHexagonMCSubtargetInfo(STI->getTargetTriple(),
STI->getCPU().drop_back(), FS);
std::lock_guard<std::mutex> Lock(ArchSubtargetMutex);
- ArchSubtarget[std::string(STI->getCPU())] =
+ ArchSubtarget[STI->getCPU()] =
std::unique_ptr<MCSubtargetInfo const>(ArchSTI);
}
}
diff --git a/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp b/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp
index befe8e3fda4f2..f0296184dde49 100644
--- a/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp
@@ -775,7 +775,7 @@ void SPIRVAsmPrinter::outputFPFastMathDefaultInfo() {
// int32, that might be used as FP Fast Math Mode.
std::vector<const MachineInstr *> SPIRVFloatTypes;
// Hashtable to associate immediate values with the constant holding them.
- std::unordered_map<int, const MachineInstr *> ConstMap;
+ DenseMap<int, const MachineInstr *> ConstMap;
for (const MachineInstr *MI : MAI->getMSInstrs(SPIRV::MB_TypeConstVars)) {
// Skip if the instruction is not OpTypeFloat or OpConstant.
unsigned OpCode = MI->getOpcode();
diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
index 7192664f2c75c..e25aa005da527 100644
--- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
@@ -253,10 +253,11 @@ class SPIRVEmitIntrinsics
bool UnknownElemTypeI8);
// deduce Types of operands of the Instruction if possible
- void deduceOperandElementType(Instruction *I,
- SmallPtrSet<Instruction *, 4> *IncompleteRets,
- const SmallPtrSet<Value *, 4> *AskOps = nullptr,
- bool IsPostprocessing = false);
+ void
+ deduceOperandElementType(Instruction *I,
+ SmallPtrSetImpl<Instruction *> *IncompleteRets,
+ const SmallPtrSetImpl<Value *> *AskOps = nullptr,
+ bool IsPostprocessing = false);
void preprocessCompositeConstants(IRBuilder<> &B);
void preprocessUndefs(IRBuilder<> &B);
@@ -296,8 +297,8 @@ class SPIRVEmitIntrinsics
CallInst *CI, SmallVector<std::pair<Value *, unsigned>> &Ops,
Type *&KnownElemTy, bool IsPostprocessing);
bool deduceOperandElementTypeFunctionRet(
- Instruction *I, SmallPtrSet<Instruction *, 4> *IncompleteRets,
- const SmallPtrSet<Value *, 4> *AskOps, bool IsPostprocessing,
+ Instruction *I, SmallPtrSetImpl<Instruction *> *IncompleteRets,
+ const SmallPtrSetImpl<Value *> *AskOps, bool IsPostprocessing,
Type *&KnownElemTy, Value *Op, Function *F);
CallInst *buildSpvPtrcast(Function *F, Value *Op, Type *ElemTy);
@@ -1313,8 +1314,8 @@ void SPIRVEmitIntrinsics::deduceOperandElementTypeFunctionPointer(
}
bool SPIRVEmitIntrinsics::deduceOperandElementTypeFunctionRet(
- Instruction *I, SmallPtrSet<Instruction *, 4> *IncompleteRets,
- const SmallPtrSet<Value *, 4> *AskOps, bool IsPostprocessing,
+ Instruction *I, SmallPtrSetImpl<Instruction *> *IncompleteRets,
+ const SmallPtrSetImpl<Value *> *AskOps, bool IsPostprocessing,
Type *&KnownElemTy, Value *Op, Function *F) {
KnownElemTy = GR->findDeducedElementType(F);
if (KnownElemTy)
@@ -1360,8 +1361,8 @@ bool SPIRVEmitIntrinsics::deduceOperandElementTypeFunctionRet(
// types which differ from expected, this function tries to insert a bitcast to
// resolve the issue.
void SPIRVEmitIntrinsics::deduceOperandElementType(
- Instruction *I, SmallPtrSet<Instruction *, 4> *IncompleteRets,
- const SmallPtrSet<Value *, 4> *AskOps, bool IsPostprocessing) {
+ Instruction *I, SmallPtrSetImpl<Instruction *> *IncompleteRets,
+ const SmallPtrSetImpl<Value *> *AskOps, bool IsPostprocessing) {
SmallVector<std::pair<Value *, unsigned>> Ops;
Type *KnownElemTy = nullptr;
bool Incomplete = false;
diff --git a/llvm/lib/Target/SPIRV/SPIRVUtils.h b/llvm/lib/Target/SPIRV/SPIRVUtils.h
index 277360270db4f..ae897d35a6277 100644
--- a/llvm/lib/Target/SPIRV/SPIRVUtils.h
+++ b/llvm/lib/Target/SPIRV/SPIRVUtils.h
@@ -16,6 +16,7 @@
#include "MCTargetDesc/SPIRVBaseInfo.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/StringMap.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/IR/Dominators.h"
@@ -25,7 +26,6 @@
#include <queue>
#include <set>
#include <string>
-#include <unordered_map>
#include "SPIRVTypeInst.h"
@@ -568,7 +568,7 @@ bool isNestedPointer(const Type *Ty);
enum FPDecorationId { NONE, RTE, RTZ, RTP, RTN, SAT };
inline FPDecorationId demangledPostfixToDecorationId(const std::string &S) {
- static std::unordered_map<std::string, FPDecorationId> Mapping = {
+ static const StringMap<FPDecorationId> Mapping = {
{"rte", FPDecorationId::RTE},
{"rtz", FPDecorationId::RTZ},
{"rtp", FPDecorationId::RTP},
diff --git a/llvm/lib/Transforms/IPO/GlobalDCE.cpp b/llvm/lib/Transforms/IPO/GlobalDCE.cpp
index ad794a9f04111..0db05c9bfcdff 100644
--- a/llvm/lib/Transforms/IPO/GlobalDCE.cpp
+++ b/llvm/lib/Transforms/IPO/GlobalDCE.cpp
@@ -96,13 +96,17 @@ void GlobalDCEPass::ComputeDependencies(Value *V,
Deps.insert(GV);
} else if (auto *CE = dyn_cast<Constant>(V)) {
// Avoid walking the whole tree of a big ConstantExprs multiple times.
- auto [Where, Inserted] = ConstantDependenciesCache.try_emplace(CE);
- SmallPtrSetImpl<GlobalValue *> &LocalDeps = Where->second;
- if (Inserted) {
+ auto Where = ConstantDependenciesCache.find(CE);
+ if (Where == ConstantDependenciesCache.end()) {
+ // Compute into a local set first: the recursion can insert into the
+ // cache, which would invalidate references into it.
+ SmallPtrSet<GlobalValue *, 8> LocalDeps;
for (User *CEUser : CE->users())
ComputeDependencies(CEUser, LocalDeps);
+ Where =
+ ConstantDependenciesCache.try_emplace(CE, std::move(LocalDeps)).first;
}
- Deps.insert_range(LocalDeps);
+ Deps.insert_range(Where->second);
}
}
diff --git a/llvm/lib/Transforms/IPO/SampleProfile.cpp b/llvm/lib/Transforms/IPO/SampleProfile.cpp
index 964c79c1e68d1..ab324ec76baa5 100644
--- a/llvm/lib/Transforms/IPO/SampleProfile.cpp
+++ b/llvm/lib/Transforms/IPO/SampleProfile.cpp
@@ -536,11 +536,11 @@ class SampleProfileLoader final : public SampleProfileLoaderBaseImpl<Function> {
/// the function name. If the function name contains suffix, additional
/// entry is added to map from the stripped name to the function if there
/// is one-to-one mapping.
- HashKeyMap<std::unordered_map, FunctionId, Function *> SymbolMap;
+ HashKeyMap<DenseMap, FunctionId, Function *> SymbolMap;
/// Map from function name to profile name generated by call-graph based
/// profile fuzzy matching(--salvage-unused-profile).
- HashKeyMap<std::unordered_map, FunctionId, FunctionId> FuncNameToProfNameMap;
+ HashKeyMap<DenseMap, FunctionId, FunctionId> FuncNameToProfNameMap;
std::function<AssumptionCache &(Function &)> GetAC;
std::function<TargetTransformInfo &(Function &)> GetTTI;
diff --git a/llvm/lib/Transforms/IPO/SampleProfileMatcher.cpp b/llvm/lib/Transforms/IPO/SampleProfileMatcher.cpp
index 73eda1b9cd48a..de89a8a1676a1 100644
--- a/llvm/lib/Transforms/IPO/SampleProfileMatcher.cpp
+++ b/llvm/lib/Transforms/IPO/SampleProfileMatcher.cpp
@@ -19,7 +19,6 @@
#include "llvm/Support/CommandLine.h"
#include "llvm/Transforms/Utils/LongestCommonSequence.h"
-#include <unordered_set>
using namespace llvm;
using namespace sampleprof;
@@ -467,7 +466,7 @@ void SampleProfileMatcher::recordCallsiteMatchStates(
if (IRCalleeId == ProfCalleeId) {
auto It = CallsiteMatchStates.find(ProfileLoc);
if (It == CallsiteMatchStates.end())
- CallsiteMatchStates.emplace(ProfileLoc, MatchState::InitialMatch);
+ CallsiteMatchStates.try_emplace(ProfileLoc, MatchState::InitialMatch);
else if (IsPostMatch) {
if (It->second == MatchState::InitialMatch)
It->second = MatchState::UnchangedMatch;
@@ -484,7 +483,7 @@ void SampleProfileMatcher::recordCallsiteMatchStates(
assert(!I.second.stringRef().empty() && "Callees should not be empty");
auto It = CallsiteMatchStates.find(Loc);
if (It == CallsiteMatchStates.end())
- CallsiteMatchStates.emplace(Loc, MatchState::InitialMismatch);
+ CallsiteMatchStates.try_emplace(Loc, MatchState::InitialMismatch);
else if (IsPostMatch) {
// Update the state if it's not matched(UnchangedMatch or
// RecoveredMismatch).
@@ -594,7 +593,7 @@ void SampleProfileMatcher::countMismatchCallsites(const FunctionSamples &FS) {
void SampleProfileMatcher::countCallGraphRecoveredSamples(
const FunctionSamples &FS,
- std::unordered_set<FunctionId> &CallGraphRecoveredProfiles) {
+ DenseSet<FunctionId> &CallGraphRecoveredProfiles) {
if (CallGraphRecoveredProfiles.count(FS.getFunction())) {
NumCallGraphRecoveredFuncSamples += FS.getTotalSamples();
return;
@@ -611,7 +610,7 @@ void SampleProfileMatcher::computeAndReportProfileStaleness() {
if (!ReportProfileStaleness && !PersistProfileStaleness)
return;
- std::unordered_set<FunctionId> CallGraphRecoveredProfiles;
+ DenseSet<FunctionId> CallGraphRecoveredProfiles;
if (SalvageUnusedProfile) {
for (const auto &I : FuncToProfileNameMap) {
CallGraphRecoveredProfiles.insert(I.second);
diff --git a/llvm/lib/Transforms/IPO/SampleProfileProbe.cpp b/llvm/lib/Transforms/IPO/SampleProfileProbe.cpp
index 7fd7d4d4f750b..b6de00de07756 100644
--- a/llvm/lib/Transforms/IPO/SampleProfileProbe.cpp
+++ b/llvm/lib/Transforms/IPO/SampleProfileProbe.cpp
@@ -12,6 +12,7 @@
#include "llvm/Transforms/IPO/SampleProfileProbe.h"
#include "llvm/ADT/Statistic.h"
+#include "llvm/ADT/StringSet.h"
#include "llvm/Analysis/BlockFrequencyInfo.h"
#include "llvm/Analysis/EHUtils.h"
#include "llvm/Analysis/LoopInfo.h"
@@ -30,7 +31,6 @@
#include "llvm/Target/TargetMachine.h"
#include "llvm/Transforms/Utils/Instrumentation.h"
#include "llvm/Transforms/Utils/ModuleUtils.h"
-#include <unordered_set>
#include <vector>
using namespace llvm;
@@ -77,9 +77,9 @@ bool PseudoProbeVerifier::shouldVerifyFunction(const Function *F) {
if (F->hasAvailableExternallyLinkage())
return false;
// Do a name matching.
- static std::unordered_set<std::string> VerifyFuncNames(
- VerifyPseudoProbeFuncList.begin(), VerifyPseudoProbeFuncList.end());
- return VerifyFuncNames.empty() || VerifyFuncNames.count(F->getName().str());
+ static const StringSet<> VerifyFuncNames(llvm::from_range,
+ VerifyPseudoProbeFuncList);
+ return VerifyFuncNames.empty() || VerifyFuncNames.contains(F->getName());
}
void PseudoProbeVerifier::registerCallbacks(PassInstrumentationCallbacks &PIC) {
diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkResult.h b/llvm/tools/llvm-exegesis/lib/BenchmarkResult.h
index 6f3bbdfc7e17f..885f4cd2f9df5 100644
--- a/llvm/tools/llvm-exegesis/lib/BenchmarkResult.h
+++ b/llvm/tools/llvm-exegesis/lib/BenchmarkResult.h
@@ -18,6 +18,7 @@
#include "LlvmState.h"
#include "RegisterValue.h"
#include "ValidationEvent.h"
+#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstBuilder.h"
@@ -25,7 +26,6 @@
#include <limits>
#include <set>
#include <string>
-#include <unordered_map>
#include <vector>
namespace llvm {
@@ -65,7 +65,7 @@ struct BenchmarkKey {
std::vector<RegisterValue> RegisterInitialValues;
// The memory values that can be mapped into the execution context of the
// snippet.
- std::unordered_map<std::string, MemoryValue> MemoryValues;
+ StringMap<MemoryValue> MemoryValues;
// The memory mappings that the snippet can access.
std::vector<MemoryMapping> MemoryMappings;
// An opaque configuration, that can be used to separate several benchmarks of
diff --git a/llvm/tools/llvm-exegesis/lib/SnippetFile.cpp b/llvm/tools/llvm-exegesis/lib/SnippetFile.cpp
index 7919d75ed0c56..250b6c7429266 100644
--- a/llvm/tools/llvm-exegesis/lib/SnippetFile.cpp
+++ b/llvm/tools/llvm-exegesis/lib/SnippetFile.cpp
@@ -108,7 +108,7 @@ class BenchmarkCodeStreamer : public MCStreamer, public AsmCommentConsumer {
}
MemVal.Value = APInt(HexValue.size() * 4, HexValue, 16);
MemVal.Index = Result->Key.MemoryValues.size();
- Result->Key.MemoryValues[Parts[0].trim().str()] = MemVal;
+ Result->Key.MemoryValues[Parts[0].trim()] = MemVal;
return;
}
if (CommentText.consume_front("MEM-MAP")) {
@@ -139,7 +139,7 @@ class BenchmarkCodeStreamer : public MCStreamer, public AsmCommentConsumer {
// validate that the annotation refers to an already existing memory
// definition
- auto MemValIT = Result->Key.MemoryValues.find(Parts[0].trim().str());
+ auto MemValIT = Result->Key.MemoryValues.find(Parts[0].trim());
if (MemValIT == Result->Key.MemoryValues.end()) {
errs() << "invalid comment 'LLVM-EXEGESIS-MEM-MAP " << CommentText
<< "', expected <VALUE NAME> to contain the name of an already "
diff --git a/llvm/tools/llvm-exegesis/lib/SubprocessMemory.cpp b/llvm/tools/llvm-exegesis/lib/SubprocessMemory.cpp
index 849e055cf7a8a..4411ecc8a296c 100644
--- a/llvm/tools/llvm-exegesis/lib/SubprocessMemory.cpp
+++ b/llvm/tools/llvm-exegesis/lib/SubprocessMemory.cpp
@@ -68,10 +68,10 @@ Error SubprocessMemory::initializeSubprocessMemory(pid_t ProcessID) {
}
Error SubprocessMemory::addMemoryDefinition(
- std::unordered_map<std::string, MemoryValue> MemoryDefinitions,
- pid_t ProcessPID) {
+ StringMap<MemoryValue> MemoryDefinitions, pid_t ProcessPID) {
SharedMemoryNames.reserve(MemoryDefinitions.size());
- for (auto &[Name, MemVal] : MemoryDefinitions) {
+ for (const auto &E : MemoryDefinitions) {
+ const MemoryValue &MemVal = E.second;
std::string SharedMemoryName =
formatv("/{0}t{1}memdef{2}", ProcessPID, getCurrentTID(), MemVal.Index);
SharedMemoryNames.push_back(SharedMemoryName);
@@ -112,8 +112,8 @@ Error SubprocessMemory::addMemoryDefinition(
}
Expected<int> SubprocessMemory::setupAuxiliaryMemoryInSubprocess(
- std::unordered_map<std::string, MemoryValue> MemoryDefinitions,
- pid_t ParentPID, long ParentTID, int CounterFileDescriptor) {
+ StringMap<MemoryValue> MemoryDefinitions, pid_t ParentPID, long ParentTID,
+ int CounterFileDescriptor) {
std::string AuxiliaryMemoryName =
formatv("/{0}auxmem{1}", ParentTID, ParentPID);
int AuxiliaryMemoryFileDescriptor =
@@ -129,7 +129,8 @@ Expected<int> SubprocessMemory::setupAuxiliaryMemoryInSubprocess(
if (reinterpret_cast<intptr_t>(AuxiliaryMemoryMapping) == -1)
return make_error<Failure>("Mapping auxiliary memory failed");
AuxiliaryMemoryMapping[0] = CounterFileDescriptor;
- for (auto &[Name, MemVal] : MemoryDefinitions) {
+ for (const auto &E : MemoryDefinitions) {
+ const MemoryValue &MemVal = E.second;
std::string MemoryValueName =
formatv("/{0}t{1}memdef{2}", ParentPID, ParentTID, MemVal.Index);
AuxiliaryMemoryMapping[AuxiliaryMemoryOffset + MemVal.Index] =
@@ -159,14 +160,13 @@ Error SubprocessMemory::initializeSubprocessMemory(pid_t ProcessPID) {
}
Error SubprocessMemory::addMemoryDefinition(
- std::unordered_map<std::string, MemoryValue> MemoryDefinitions,
- pid_t ProcessPID) {
+ StringMap<MemoryValue> MemoryDefinitions, pid_t ProcessPID) {
return make_error<Failure>("addMemoryDefinitions is only supported on Linux");
}
Expected<int> SubprocessMemory::setupAuxiliaryMemoryInSubprocess(
- std::unordered_map<std::string, MemoryValue> MemoryDefinitions,
- pid_t ParentPID, long ParentTID, int CounterFileDescriptor) {
+ StringMap<MemoryValue> MemoryDefinitions, pid_t ParentPID, long ParentTID,
+ int CounterFileDescriptor) {
return make_error<Failure>(
"setupAuxiliaryMemoryInSubprocess is only supported on Linux");
}
diff --git a/llvm/tools/llvm-exegesis/lib/SubprocessMemory.h b/llvm/tools/llvm-exegesis/lib/SubprocessMemory.h
index 52ee980b6defd..5f2a522c21c2e 100644
--- a/llvm/tools/llvm-exegesis/lib/SubprocessMemory.h
+++ b/llvm/tools/llvm-exegesis/lib/SubprocessMemory.h
@@ -16,8 +16,8 @@
#define LLVM_TOOLS_LLVM_EXEGESIS_SUBPROCESSMEMORY_H
#include "BenchmarkResult.h"
+#include "llvm/ADT/StringMap.h"
#include <string>
-#include <unordered_map>
#include <vector>
#ifdef _MSC_VER
@@ -44,9 +44,8 @@ class SubprocessMemory {
// memory objects for the definitions and fills them with the specified
// values. Arguments: MemoryDefinitions - A map from memory value names to
// MemoryValues, ProcessID - The ID of the current process.
- Error addMemoryDefinition(
- std::unordered_map<std::string, MemoryValue> MemoryDefinitions,
- pid_t ProcessID);
+ Error addMemoryDefinition(StringMap<MemoryValue> MemoryDefinitions,
+ pid_t ProcessID);
// The following function sets up the auxiliary memory by opening shared
// memory objects backing memory definitions and putting file descriptors
@@ -55,9 +54,10 @@ class SubprocessMemory {
// setup the memory definitions, CounterFileDescriptor - The file descriptor
// for the performance counter that will be placed in the auxiliary memory
// section.
- static Expected<int> setupAuxiliaryMemoryInSubprocess(
- std::unordered_map<std::string, MemoryValue> MemoryDefinitions,
- pid_t ParentPID, long ParentTID, int CounterFileDescriptor);
+ static Expected<int>
+ setupAuxiliaryMemoryInSubprocess(StringMap<MemoryValue> MemoryDefinitions,
+ pid_t ParentPID, long ParentTID,
+ int CounterFileDescriptor);
~SubprocessMemory();
diff --git a/llvm/tools/llvm-objdump/SourcePrinter.h b/llvm/tools/llvm-objdump/SourcePrinter.h
index ad3ea122b4346..aac81fdc1bfab 100644
--- a/llvm/tools/llvm-objdump/SourcePrinter.h
+++ b/llvm/tools/llvm-objdump/SourcePrinter.h
@@ -19,7 +19,6 @@
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/Support/FormattedStream.h"
#include <set>
-#include <unordered_map>
#include <vector>
namespace llvm {
@@ -215,9 +214,9 @@ class SourcePrinter {
const object::ObjectFile *Obj = nullptr;
std::unique_ptr<symbolize::LLVMSymbolizer> Symbolizer;
// File name to file contents of source.
- std::unordered_map<std::string, std::unique_ptr<MemoryBuffer>> SourceCache;
+ StringMap<std::unique_ptr<MemoryBuffer>> SourceCache;
// Mark the line endings of the cached source.
- std::unordered_map<std::string, std::vector<StringRef>> LineCache;
+ StringMap<std::vector<StringRef>> LineCache;
// Keep track of missing sources.
StringSet<> MissingSources;
// Only emit 'invalid debug info' warning once.
diff --git a/llvm/tools/llvm-profgen/ProfiledBinary.cpp b/llvm/tools/llvm-profgen/ProfiledBinary.cpp
index 3b9f1f46140cb..3b1e00093fb9e 100644
--- a/llvm/tools/llvm-profgen/ProfiledBinary.cpp
+++ b/llvm/tools/llvm-profgen/ProfiledBinary.cpp
@@ -218,7 +218,7 @@ void ProfiledBinary::warnNoFuncEntry() {
NoFuncEntryNum++;
if (ShowDetailedWarning)
WithColor::warning()
- << "Failed to determine function entry for " << F.first
+ << "Failed to determine function entry for " << F.first()
<< " due to inconsistent name from symbol table and dwarf info.\n";
}
}
@@ -953,10 +953,10 @@ void ProfiledBinary::loadSymbolsFromSymtab(const ObjectFile *Obj) {
assert(findFuncRange(EndAddr - 1) == nullptr &&
"Function range overlaps with existing functions.");
// Function from symbol table not found previously in DWARF, store ranges.
- auto Ret = BinaryFunctions.emplace(SymName, BinaryFunction());
+ auto Ret = BinaryFunctions.try_emplace(SymName);
auto &Func = Ret.first->second;
if (Ret.second) {
- Func.FuncName = Ret.first->first;
+ Func.FuncName = Ret.first->first();
HashBinaryFunctions[Function::getGUIDAssumingExternalLinkage(SymName)] =
&Func;
}
@@ -1030,10 +1030,10 @@ void ProfiledBinary::loadSymbolsFromDWARFUnit(DWARFUnit &CompilationUnit) {
// Different DWARF symbols can have same function name, search or create
// BinaryFunction indexed by the name.
- auto Ret = BinaryFunctions.emplace(Name, BinaryFunction());
+ auto Ret = BinaryFunctions.try_emplace(Name);
auto &Func = Ret.first->second;
if (Ret.second)
- Func.FuncName = Ret.first->first;
+ Func.FuncName = Ret.first->first();
for (const auto &Range : Ranges) {
uint64_t StartAddress = Range.LowPC;
@@ -1106,7 +1106,7 @@ void ProfiledBinary::loadSymbolsFromDWARF(ObjectFile &Obj) {
// Populate the hash binary function map for MD5 function name lookup. This
// is done after BinaryFunctions are finalized.
for (auto &BinaryFunction : BinaryFunctions) {
- HashBinaryFunctions[MD5Hash(StringRef(BinaryFunction.first))] =
+ HashBinaryFunctions[MD5Hash(BinaryFunction.first())] =
&BinaryFunction.second;
}
diff --git a/llvm/tools/llvm-profgen/ProfiledBinary.h b/llvm/tools/llvm-profgen/ProfiledBinary.h
index 4a2c4cec8b49f..a407adb978091 100644
--- a/llvm/tools/llvm-profgen/ProfiledBinary.h
+++ b/llvm/tools/llvm-profgen/ProfiledBinary.h
@@ -236,7 +236,7 @@ class ProfiledBinary {
std::set<std::pair<uint64_t, uint64_t>> TextSections;
// A map of mapping function name to BinaryFunction info.
- std::unordered_map<std::string, BinaryFunction> BinaryFunctions;
+ StringMap<BinaryFunction> BinaryFunctions;
// Lookup BinaryFunctions using the function name's MD5 hash. Needed if the
// profile is using MD5.
@@ -571,8 +571,7 @@ class ProfiledBinary {
return FRange->Func->Ranges;
}
- const std::unordered_map<std::string, BinaryFunction> &
- getAllBinaryFunctions() {
+ const StringMap<BinaryFunction> &getAllBinaryFunctions() {
return BinaryFunctions;
}
@@ -586,7 +585,7 @@ class ProfiledBinary {
BinaryFunction *getBinaryFunction(FunctionId FName) {
if (FName.isStringRef()) {
- auto I = BinaryFunctions.find(FName.str());
+ auto I = BinaryFunctions.find(FName.stringRef());
if (I == BinaryFunctions.end())
return nullptr;
return &I->second;
diff --git a/llvm/unittests/tools/llvm-exegesis/X86/SnippetFileTest.cpp b/llvm/unittests/tools/llvm-exegesis/X86/SnippetFileTest.cpp
index 755a74811eb69..a5493d327ac7d 100644
--- a/llvm/unittests/tools/llvm-exegesis/X86/SnippetFileTest.cpp
+++ b/llvm/unittests/tools/llvm-exegesis/X86/SnippetFileTest.cpp
@@ -67,11 +67,11 @@ MATCHER_P2(RegisterInitialValueIs, Reg, Val, "") {
MATCHER_P3(MemoryDefinitionIs, Name, Value, Size, "") {
if (arg.second.Value.getLimitedValue() == static_cast<uint64_t>(Value) &&
- arg.second.SizeBytes == static_cast<size_t>(Size) && arg.first == Name)
+ arg.second.SizeBytes == static_cast<size_t>(Size) && arg.first() == Name)
return true;
*result_listener << "expected: {" << Name << ", " << Value << ", " << Size
<< "} ";
- *result_listener << "actual: {" << arg.first << ", "
+ *result_listener << "actual: {" << arg.first().str() << ", "
<< arg.second.Value.getLimitedValue() << ", "
<< arg.second.SizeBytes << "}";
return false;
diff --git a/llvm/unittests/tools/llvm-exegesis/X86/SubprocessMemoryTest.cpp b/llvm/unittests/tools/llvm-exegesis/X86/SubprocessMemoryTest.cpp
index 08c18e4ed11e2..3a35e2e02e6be 100644
--- a/llvm/unittests/tools/llvm-exegesis/X86/SubprocessMemoryTest.cpp
+++ b/llvm/unittests/tools/llvm-exegesis/X86/SubprocessMemoryTest.cpp
@@ -11,7 +11,6 @@
#include "X86/TestBase.h"
#include "gtest/gtest.h"
#include <string>
-#include <unordered_map>
#ifdef __linux__
#include <endian.h>
@@ -40,9 +39,8 @@ class SubprocessMemoryTest : public X86TestBase {
return getpid() * TestCount + TestNumber;
}
- void
- testCommon(std::unordered_map<std::string, MemoryValue> MemoryDefinitions,
- const unsigned TestNumber) {
+ void testCommon(StringMap<MemoryValue> MemoryDefinitions,
+ const unsigned TestNumber) {
EXPECT_FALSE(
SM.initializeSubprocessMemory(getSharedMemoryNumber(TestNumber)));
EXPECT_FALSE(SM.addMemoryDefinition(MemoryDefinitions,
diff --git a/llvm/utils/TableGen/DFAPacketizerEmitter.cpp b/llvm/utils/TableGen/DFAPacketizerEmitter.cpp
index dfc92711d9e85..334aeef70ff51 100644
--- a/llvm/utils/TableGen/DFAPacketizerEmitter.cpp
+++ b/llvm/utils/TableGen/DFAPacketizerEmitter.cpp
@@ -18,6 +18,7 @@
#include "Common/CodeGenTarget.h"
#include "DFAEmitter.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringMap.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TableGen/Record.h"
@@ -28,7 +29,6 @@
#include <map>
#include <set>
#include <string>
-#include <unordered_map>
#include <vector>
#define DEBUG_TYPE "dfa-emitter"
@@ -217,17 +217,16 @@ void DFAPacketizerEmitter::run(raw_ostream &OS) {
CodeGenTarget CGT(Records);
CodeGenSchedModels CGS(Records, CGT);
- std::unordered_map<std::string, std::vector<const CodeGenProcModel *>>
- ItinsByNamespace;
+ StringMap<std::vector<const CodeGenProcModel *>> ItinsByNamespace;
for (const CodeGenProcModel &ProcModel : CGS.procModels()) {
if (ProcModel.hasItineraries()) {
auto NS = ProcModel.ItinsDef->getValueAsString("PacketizerNamespace");
- ItinsByNamespace[NS.str()].push_back(&ProcModel);
+ ItinsByNamespace[NS].push_back(&ProcModel);
}
}
for (auto &KV : ItinsByNamespace)
- emitForItineraries(OS, KV.second, KV.first);
+ emitForItineraries(OS, KV.second, KV.first().str());
OS << "} // end namespace llvm\n";
}
>From e85c985c470cf58c66866e0b3d6da0a59959fc3a Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Fri, 12 Jun 2026 10:59:17 -0700
Subject: [PATCH 4/4] rebase
---
llvm/tools/llvm-config/llvm-config.cpp | 4 +-
llvm/tools/llvm-exegesis/lib/Analysis.cpp | 4 +-
.../tools/llvm-exegesis/lib/MCInstrDescView.h | 5 +-
.../llvm-exegesis/lib/RegisterAliasing.h | 6 +-
llvm/tools/llvm-objdump/llvm-objdump.cpp | 27 ++++-----
llvm/tools/llvm-profdata/llvm-profdata.cpp | 16 +++--
.../llvm-profgen/MissingFrameInferrer.cpp | 11 ++--
.../tools/llvm-profgen/MissingFrameInferrer.h | 28 +++------
llvm/tools/llvm-profgen/PerfReader.cpp | 21 +++----
llvm/tools/llvm-profgen/PerfReader.h | 58 ++++++++++---------
llvm/tools/llvm-profgen/ProfileGenerator.cpp | 11 ++--
llvm/tools/llvm-profgen/ProfileGenerator.h | 17 +++---
llvm/tools/llvm-profgen/ProfiledBinary.cpp | 10 ++--
llvm/tools/llvm-profgen/ProfiledBinary.h | 38 +++++++-----
llvm/tools/llvm-readobj/ObjDumper.h | 5 +-
.../llvm-remarkutil/RemarkUtilRegistry.cpp | 6 +-
llvm/tools/llvm-xray/xray-registry.cpp | 6 +-
17 files changed, 131 insertions(+), 142 deletions(-)
diff --git a/llvm/tools/llvm-config/llvm-config.cpp b/llvm/tools/llvm-config/llvm-config.cpp
index 24ea264419af4..76aa9f82eb0a7 100644
--- a/llvm/tools/llvm-config/llvm-config.cpp
+++ b/llvm/tools/llvm-config/llvm-config.cpp
@@ -21,6 +21,7 @@
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSet.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Config/config.h"
#include "llvm/Support/FileSystem.h"
@@ -31,7 +32,6 @@
#include "llvm/TargetParser/Triple.h"
#include <cstdlib>
#include <set>
-#include <unordered_set>
#include <vector>
using namespace llvm;
@@ -695,7 +695,7 @@ int main(int argc, char **argv) {
}
if (PrintSharedMode) {
- std::unordered_set<std::string> FullDyLibComponents;
+ StringSet<> FullDyLibComponents;
std::vector<std::string> DyLibComponents =
getAllDyLibComponents(IsInDevelopmentTree, false, DirSep);
diff --git a/llvm/tools/llvm-exegesis/lib/Analysis.cpp b/llvm/tools/llvm-exegesis/lib/Analysis.cpp
index 559add2916896..c35ae0399c91b 100644
--- a/llvm/tools/llvm-exegesis/lib/Analysis.cpp
+++ b/llvm/tools/llvm-exegesis/lib/Analysis.cpp
@@ -196,7 +196,7 @@ std::vector<Analysis::ResolvedSchedClassAndPoints>
Analysis::makePointsPerSchedClass() const {
std::vector<ResolvedSchedClassAndPoints> Entries;
// Maps SchedClassIds to index in result.
- std::unordered_map<unsigned, size_t> SchedClassIdToIndex;
+ DenseMap<unsigned, size_t> SchedClassIdToIndex;
const auto &Points = Clustering_.getPoints();
for (size_t PointId = 0, E = Points.size(); PointId < E; ++PointId) {
const Benchmark &Point = Points[PointId];
@@ -214,7 +214,7 @@ Analysis::makePointsPerSchedClass() const {
const auto IndexIt = SchedClassIdToIndex.find(SchedClassId);
if (IndexIt == SchedClassIdToIndex.end()) {
// Create a new entry.
- SchedClassIdToIndex.emplace(SchedClassId, Entries.size());
+ SchedClassIdToIndex.try_emplace(SchedClassId, Entries.size());
ResolvedSchedClassAndPoints Entry(ResolvedSchedClass(
State_.getSubtargetInfo(), SchedClassId, WasVariant));
Entry.PointIds.push_back(PointId);
diff --git a/llvm/tools/llvm-exegesis/lib/MCInstrDescView.h b/llvm/tools/llvm-exegesis/lib/MCInstrDescView.h
index 5c97fdac6916a..c0f28d7d168da 100644
--- a/llvm/tools/llvm-exegesis/lib/MCInstrDescView.h
+++ b/llvm/tools/llvm-exegesis/lib/MCInstrDescView.h
@@ -20,10 +20,10 @@
#include <memory>
#include <random>
-#include <unordered_map>
#include "RegisterAliasing.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstrDesc.h"
#include "llvm/MC/MCInstrInfo.h"
@@ -197,8 +197,7 @@ struct InstructionsCache {
const MCInstrInfo &InstrInfo;
const RegisterAliasingTrackerCache &RATC;
const MCSubtargetInfo *STI;
- mutable std::unordered_map<unsigned, std::unique_ptr<Instruction>>
- Instructions;
+ mutable DenseMap<unsigned, std::unique_ptr<Instruction>> Instructions;
const BitVectorCache BVC;
};
diff --git a/llvm/tools/llvm-exegesis/lib/RegisterAliasing.h b/llvm/tools/llvm-exegesis/lib/RegisterAliasing.h
index 00e699d4c69b9..ebb7e1ba6d608 100644
--- a/llvm/tools/llvm-exegesis/lib/RegisterAliasing.h
+++ b/llvm/tools/llvm-exegesis/lib/RegisterAliasing.h
@@ -15,9 +15,9 @@
#define LLVM_TOOLS_LLVM_EXEGESIS_ALIASINGTRACKER_H
#include <memory>
-#include <unordered_map>
#include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/PackedVector.h"
#include "llvm/MC/MCRegisterInfo.h"
@@ -97,9 +97,9 @@ struct RegisterAliasingTrackerCache {
const MCRegisterInfo &RegInfo;
const BitVector ReservedReg;
const BitVector EmptyRegisters;
- mutable std::unordered_map<unsigned, std::unique_ptr<RegisterAliasingTracker>>
+ mutable DenseMap<unsigned, std::unique_ptr<RegisterAliasingTracker>>
Registers;
- mutable std::unordered_map<unsigned, std::unique_ptr<RegisterAliasingTracker>>
+ mutable DenseMap<unsigned, std::unique_ptr<RegisterAliasingTracker>>
RegisterClasses;
};
diff --git a/llvm/tools/llvm-objdump/llvm-objdump.cpp b/llvm/tools/llvm-objdump/llvm-objdump.cpp
index 1da9b5771fd3f..13232d232c669 100644
--- a/llvm/tools/llvm-objdump/llvm-objdump.cpp
+++ b/llvm/tools/llvm-objdump/llvm-objdump.cpp
@@ -24,6 +24,7 @@
#include "SourcePrinter.h"
#include "WasmDump.h"
#include "XCOFFDump.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SetOperations.h"
#include "llvm/ADT/StringExtras.h"
@@ -83,7 +84,6 @@
#include <optional>
#include <set>
#include <system_error>
-#include <unordered_map>
#include <utility>
using namespace llvm;
@@ -262,8 +262,8 @@ class BBAddrMapInfo {
void AddFunctionEntry(BBAddrMap AddrMap, PGOAnalysisMap PGOMap) {
uint64_t FunctionAddr = AddrMap.getFunctionAddress();
for (size_t I = 1; I < AddrMap.BBRanges.size(); ++I)
- RangeBaseAddrToFunctionAddr.emplace(AddrMap.BBRanges[I].BaseAddress,
- FunctionAddr);
+ RangeBaseAddrToFunctionAddr.try_emplace(AddrMap.BBRanges[I].BaseAddress,
+ FunctionAddr);
[[maybe_unused]] auto R = FunctionAddrToMap.try_emplace(
FunctionAddr, std::move(AddrMap), std::move(PGOMap));
assert(R.second && "duplicate function address");
@@ -285,8 +285,8 @@ class BBAddrMapInfo {
}
private:
- std::unordered_map<uint64_t, BBAddrMapFunctionEntry> FunctionAddrToMap;
- std::unordered_map<uint64_t, uint64_t> RangeBaseAddrToFunctionAddr;
+ DenseMap<uint64_t, BBAddrMapFunctionEntry> FunctionAddrToMap;
+ DenseMap<uint64_t, uint64_t> RangeBaseAddrToFunctionAddr;
};
} // namespace
@@ -1659,8 +1659,7 @@ static SymbolInfoTy createDummySymbolInfo(const ObjectFile &Obj,
static void collectBBAddrMapLabels(
const BBAddrMapInfo &FullAddrMap, uint64_t SectionAddr, uint64_t Start,
- uint64_t End,
- std::unordered_map<uint64_t, std::vector<BBAddrMapLabel>> &Labels) {
+ uint64_t End, DenseMap<uint64_t, std::vector<BBAddrMapLabel>> &Labels) {
if (FullAddrMap.empty())
return;
Labels.clear();
@@ -1692,12 +1691,10 @@ static void collectBBAddrMapLabels(
}
}
-static void
-collectLocalBranchTargets(ArrayRef<uint8_t> Bytes, MCInstrAnalysis *MIA,
- MCDisassembler *DisAsm, MCInstPrinter *IP,
- const MCSubtargetInfo *STI, uint64_t SectionAddr,
- uint64_t Start, uint64_t End,
- std::unordered_map<uint64_t, std::string> &Labels) {
+static void collectLocalBranchTargets(
+ ArrayRef<uint8_t> Bytes, MCInstrAnalysis *MIA, MCDisassembler *DisAsm,
+ MCInstPrinter *IP, const MCSubtargetInfo *STI, uint64_t SectionAddr,
+ uint64_t Start, uint64_t End, DenseMap<uint64_t, std::string> &Labels) {
// Supported by certain targets.
const bool isPPC = STI->getTargetTriple().isPPC();
const bool isX86 = STI->getTargetTriple().isX86();
@@ -2422,8 +2419,8 @@ disassembleObject(ObjectFile &Obj, const ObjectFile &DbgObj,
Symbols[SI - 1].XCOFFSymInfo.StorageMappingClass &&
(*Symbols[SI - 1].XCOFFSymInfo.StorageMappingClass == XCOFF::XMC_PR);
- std::unordered_map<uint64_t, std::string> AllLabels;
- std::unordered_map<uint64_t, std::vector<BBAddrMapLabel>> BBAddrMapLabels;
+ DenseMap<uint64_t, std::string> AllLabels;
+ DenseMap<uint64_t, std::vector<BBAddrMapLabel>> BBAddrMapLabels;
if (SymbolizeOperands) {
collectLocalBranchTargets(Bytes, DT->InstrAnalysis.get(),
DT->DisAsm.get(), DT->InstPrinter.get(),
diff --git a/llvm/tools/llvm-profdata/llvm-profdata.cpp b/llvm/tools/llvm-profdata/llvm-profdata.cpp
index 08a1ea51af8e5..5a3be5f21c7ff 100644
--- a/llvm/tools/llvm-profdata/llvm-profdata.cpp
+++ b/llvm/tools/llvm-profdata/llvm-profdata.cpp
@@ -10,6 +10,7 @@
//
//===----------------------------------------------------------------------===//
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
@@ -2045,8 +2046,7 @@ class SampleOverlapAggregator {
/// Load profiles specified by BaseFilename and TestFilename.
std::error_code loadProfiles();
- using FuncSampleStatsMap =
- std::unordered_map<SampleContext, FuncSampleStats, SampleContext::Hash>;
+ using FuncSampleStatsMap = DenseMap<SampleContext, FuncSampleStats>;
private:
SampleOverlapStats ProfOverlap;
@@ -2207,7 +2207,7 @@ void SampleOverlapAggregator::getHotFunctions(
uint64_t HotThreshold) const {
for (const auto &F : ProfStats) {
if (isFunctionHot(F.second, HotThreshold))
- HotFunc.emplace(F.first, F.second);
+ HotFunc.try_emplace(F.first, F.second);
}
}
@@ -2434,12 +2434,10 @@ double SampleOverlapAggregator::computeSampleFunctionOverlap(
void SampleOverlapAggregator::computeSampleProfileOverlap(raw_fd_ostream &OS) {
using namespace sampleprof;
- std::unordered_map<SampleContext, const FunctionSamples *,
- SampleContext::Hash>
- BaseFuncProf;
+ DenseMap<SampleContext, const FunctionSamples *> BaseFuncProf;
const auto &BaseProfiles = BaseReader->getProfiles();
for (const auto &BaseFunc : BaseProfiles) {
- BaseFuncProf.emplace(BaseFunc.second.getContext(), &(BaseFunc.second));
+ BaseFuncProf.try_emplace(BaseFunc.second.getContext(), &(BaseFunc.second));
}
ProfOverlap.UnionCount = BaseFuncProf.size();
@@ -2557,7 +2555,7 @@ void SampleOverlapAggregator::initializeSampleProfileOverlap() {
FuncSampleStats FuncStats;
getFuncSampleStats(I.second, FuncStats, BaseHotThreshold);
ProfOverlap.BaseSample += FuncStats.SampleSum;
- BaseStats.emplace(I.second.getContext(), FuncStats);
+ BaseStats.try_emplace(I.second.getContext(), FuncStats);
}
const auto &TestProf = TestReader->getProfiles();
@@ -2566,7 +2564,7 @@ void SampleOverlapAggregator::initializeSampleProfileOverlap() {
FuncSampleStats FuncStats;
getFuncSampleStats(I.second, FuncStats, TestHotThreshold);
ProfOverlap.TestSample += FuncStats.SampleSum;
- TestStats.emplace(I.second.getContext(), FuncStats);
+ TestStats.try_emplace(I.second.getContext(), FuncStats);
}
ProfOverlap.BaseName = StringRef(BaseFilename);
diff --git a/llvm/tools/llvm-profgen/MissingFrameInferrer.cpp b/llvm/tools/llvm-profgen/MissingFrameInferrer.cpp
index 1141c41978428..de0eb3681cd3f 100644
--- a/llvm/tools/llvm-profgen/MissingFrameInferrer.cpp
+++ b/llvm/tools/llvm-profgen/MissingFrameInferrer.cpp
@@ -44,8 +44,8 @@ void MissingFrameInferrer::initialize(
const ContextSampleCounterMap *SampleCounters) {
// Refine call edges based on LBR samples.
if (SampleCounters) {
- std::unordered_map<uint64_t, std::unordered_set<uint64_t>> SampledCalls;
- std::unordered_map<uint64_t, std::unordered_set<uint64_t>> SampledTailCalls;
+ DenseMap<uint64_t, DenseSet<uint64_t>> SampledCalls;
+ DenseMap<uint64_t, DenseSet<uint64_t>> SampledTailCalls;
// Populate SampledCalls based on static call sites. Similarly to
// SampledTailCalls.
@@ -72,8 +72,8 @@ void MissingFrameInferrer::initialize(
}
// Replace static edges with dynamic edges.
- CallEdges = SampledCalls;
- TailCallEdges = SampledTailCalls;
+ CallEdges = std::move(SampledCalls);
+ TailCallEdges = std::move(SampledTailCalls);
}
// Populate function-based edges. This is to speed up address to function
@@ -106,8 +106,7 @@ void MissingFrameInferrer::initialize(
#ifndef NDEBUG
auto PrintCallTargets =
- [&](const std::unordered_map<uint64_t, std::unordered_set<uint64_t>>
- &CallTargets,
+ [&](const DenseMap<uint64_t, DenseSet<uint64_t>> &CallTargets,
bool IsTailCall) {
for (const auto &Targets : CallTargets) {
for (const auto &Target : Targets.second) {
diff --git a/llvm/tools/llvm-profgen/MissingFrameInferrer.h b/llvm/tools/llvm-profgen/MissingFrameInferrer.h
index 4680a9a979ffa..4ed9d3a9d5905 100644
--- a/llvm/tools/llvm-profgen/MissingFrameInferrer.h
+++ b/llvm/tools/llvm-profgen/MissingFrameInferrer.h
@@ -10,11 +10,11 @@
#define LLVM_TOOLS_LLVM_PROFGEN_MISSINGFRAMEINFERRER_H
#include "PerfReader.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
-#include <unordered_map>
-#include <unordered_set>
namespace llvm {
namespace sampleprof {
@@ -66,39 +66,29 @@ class MissingFrameInferrer {
// A map of call instructions to their target addresses. This is first
// populated with static call edges but then trimmed down to dynamic call
// edges based on LBR samples.
- std::unordered_map<uint64_t, std::unordered_set<uint64_t>> CallEdges;
+ DenseMap<uint64_t, DenseSet<uint64_t>> CallEdges;
// A map of tail call instructions to their target addresses. This is first
// populated with static call edges but then trimmed down to dynamic call
// edges based on LBR samples.
- std::unordered_map<uint64_t, std::unordered_set<uint64_t>> TailCallEdges;
+ DenseMap<uint64_t, DenseSet<uint64_t>> TailCallEdges;
// Dynamic call targets in terms of BinaryFunction for any calls.
- std::unordered_map<uint64_t, std::unordered_set<BinaryFunction *>> CallEdgesF;
+ DenseMap<uint64_t, SmallPtrSet<BinaryFunction *, 0>> CallEdgesF;
// Dynamic call targets in terms of BinaryFunction for tail calls.
- std::unordered_map<uint64_t, std::unordered_set<BinaryFunction *>>
- TailCallEdgesF;
+ DenseMap<uint64_t, SmallPtrSet<BinaryFunction *, 0>> TailCallEdgesF;
// Dynamic tail call targets of caller functions.
- std::unordered_map<BinaryFunction *, std::vector<uint64_t>> FuncToTailCallMap;
+ DenseMap<BinaryFunction *, std::vector<uint64_t>> FuncToTailCallMap;
// Functions that are reachable via tail calls.
DenseSet<const BinaryFunction *> TailCallTargetFuncs;
- struct PairHash {
- std::size_t operator()(
- const std::pair<BinaryFunction *, BinaryFunction *> &Pair) const {
- return std::hash<BinaryFunction *>()(Pair.first) ^
- std::hash<BinaryFunction *>()(Pair.second);
- }
- };
-
// Cached results from a CallerCalleePair to a unique call path between them.
- std::unordered_map<CallerCalleePair, std::vector<uint64_t>, PairHash>
- UniquePaths;
+ DenseMap<CallerCalleePair, std::vector<uint64_t>> UniquePaths;
// Cached results from CallerCalleePair to the number of available call paths.
- std::unordered_map<CallerCalleePair, uint64_t, PairHash> NonUniquePaths;
+ DenseMap<CallerCalleePair, uint64_t> NonUniquePaths;
DenseSet<BinaryFunction *> Visiting;
diff --git a/llvm/tools/llvm-profgen/PerfReader.cpp b/llvm/tools/llvm-profgen/PerfReader.cpp
index 733bfc5c250ac..62b24a288dfc4 100644
--- a/llvm/tools/llvm-profgen/PerfReader.cpp
+++ b/llvm/tools/llvm-profgen/PerfReader.cpp
@@ -218,7 +218,7 @@ void VirtualUnwinder::collectSamplesFromFrame(UnwindState::ProfiledFrame *Cur,
std::shared_ptr<ContextKey> Key = Stack.getContextKey();
if (Key == nullptr)
return;
- auto Ret = CtxCounterMap->emplace(Hashable<ContextKey>(Key), SampleCounter());
+ auto Ret = CtxCounterMap->try_emplace(Hashable<ContextKey>(Key));
SampleCounter &SCounter = Ret.first->second;
for (auto &I : Cur->RangeSamples)
SCounter.recordRangeCount(std::get<0>(I), std::get<1>(I), std::get<2>(I));
@@ -486,12 +486,12 @@ PerfScriptReader::convertPerfDataToTrace(ProfiledBinary *Binary, bool SkipPID,
// Collect the PIDs
TraceStream TraceIt(PerfTraceFile);
- std::unordered_set<int32_t> PIDSet;
+ DenseSet<int32_t> PIDSet;
while (!TraceIt.isAtEoF()) {
MMapEvent MMap;
if (isMMapEvent(TraceIt.getCurrentLine()) &&
extractMMapEventForBinary(Binary, TraceIt.getCurrentLine(), MMap)) {
- auto It = PIDSet.emplace(MMap.PID);
+ auto It = PIDSet.insert(MMap.PID);
if (It.second && (!PIDFilter || MMap.PID == *PIDFilter)) {
if (!PIDs.empty()) {
PIDs.append(",");
@@ -996,12 +996,11 @@ void UnsymbolizedProfileReader::readUnsymbolizedProfile(StringRef FileName) {
// Read context stack for CS profile.
if (Line.starts_with("[")) {
ProfileIsCS = true;
- auto I = ContextStrSet.insert(Line.str());
- SampleContext::createCtxVectorFromStr(*I.first, Key->Context);
+ auto I = ContextStrSet.insert(Line);
+ SampleContext::createCtxVectorFromStr(I.first->getKey(), Key->Context);
TraceIt.advance();
}
- auto Ret =
- SampleCounters.emplace(Hashable<ContextKey>(Key), SampleCounter());
+ auto Ret = SampleCounters.try_emplace(Hashable<ContextKey>(Key));
readSampleCounters(TraceIt, Ret.first->second);
}
}
@@ -1053,7 +1052,7 @@ void PerfScriptReader::generateUnsymbolizedProfile() {
"Sample counter map should be empty before raw profile generation");
std::shared_ptr<StringBasedCtxKey> Key =
std::make_shared<StringBasedCtxKey>();
- SampleCounters.emplace(Hashable<ContextKey>(Key), SampleCounter());
+ SampleCounters.try_emplace(Hashable<ContextKey>(Key));
for (const auto &Item : AggregatedSamples) {
const PerfSample *Sample = Item.first.getPtr();
computeCounterFromLBR(Sample, Item.second);
@@ -1265,9 +1264,7 @@ void PerfScriptReader::warnTruncatedStack() {
}
void PerfScriptReader::warnInvalidRange() {
- std::unordered_map<std::pair<uint64_t, uint64_t>, uint64_t,
- pair_hash<uint64_t, uint64_t>>
- Ranges;
+ DenseMap<std::pair<uint64_t, uint64_t>, uint64_t> Ranges;
for (const auto &Item : AggregatedSamples) {
const PerfSample *Sample = Item.first.getPtr();
@@ -1466,7 +1463,7 @@ void ETMReader::parseETMTraces() {
// Initialize the SampleCounters map with a single empty context key
// to aggregate all instruction hits into a global bucket.
auto Key = std::make_shared<StringBasedCtxKey>();
- Counters.emplace(Hashable<ContextKey>(Key), SampleCounter());
+ Counters.try_emplace(Hashable<ContextKey>(Key));
// The protocol utilizes a 0x80 byte as an initial synchronization header.
// Perform a manual search for this sync point to discard any leading
diff --git a/llvm/tools/llvm-profgen/PerfReader.h b/llvm/tools/llvm-profgen/PerfReader.h
index 4d912fa87d511..3e39ec3d0cdc8 100644
--- a/llvm/tools/llvm-profgen/PerfReader.h
+++ b/llvm/tools/llvm-profgen/PerfReader.h
@@ -10,6 +10,8 @@
#define LLVM_TOOLS_LLVM_PROFGEN_PERFREADER_H
#include "ErrorHandling.h"
#include "ProfiledBinary.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringSet.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Error.h"
@@ -124,27 +126,28 @@ template <class T> class Hashable {
std::shared_ptr<T> Data;
Hashable(const std::shared_ptr<T> &D) : Data(D) {}
- // Hash code generation
- struct Hash {
- uint64_t operator()(const Hashable<T> &Key) const {
- // Don't make it virtual for getHashCode
- uint64_t Hash = Key.Data->getHashCode();
- assert(Hash && "Should generate HashCode for it!");
- return Hash;
- }
- };
+ T *getPtr() const { return Data.get(); }
+};
- // Hash equal
- struct Equal {
- bool operator()(const Hashable<T> &LHS, const Hashable<T> &RHS) const {
- // Precisely compare the data, vtable will have overhead.
- return LHS.Data->isEqual(RHS.Data.get());
- }
- };
+} // end namespace sampleprof
- T *getPtr() const { return Data.get(); }
+template <typename T> struct DenseMapInfo<sampleprof::Hashable<T>> {
+ static unsigned getHashValue(const sampleprof::Hashable<T> &Key) {
+ // Don't make it virtual for getHashCode
+ uint64_t Hash = Key.Data->getHashCode();
+ assert(Hash && "Should generate HashCode for it!");
+ return DenseMapInfo<uint64_t>::getHashValue(Hash);
+ }
+
+ static bool isEqual(const sampleprof::Hashable<T> &LHS,
+ const sampleprof::Hashable<T> &RHS) {
+ // Precisely compare the data, vtable will have overhead.
+ return LHS.Data->isEqual(RHS.Data.get());
+ }
};
+namespace sampleprof {
+
struct PerfSample {
// LBR stack recorded in FIFO order.
SmallVector<LBREntry, 16> LBRStack;
@@ -203,9 +206,7 @@ struct PerfSample {
// After parsing the sample, we record the samples by aggregating them
// into this counter. The key stores the sample data and the value is
// the sample repeat times.
-using AggregatedCounter =
- std::unordered_map<Hashable<PerfSample>, uint64_t,
- Hashable<PerfSample>::Hash, Hashable<PerfSample>::Equal>;
+using AggregatedCounter = DenseMap<Hashable<PerfSample>, uint64_t>;
using SampleVector = SmallVector<std::tuple<uint64_t, uint64_t, uint64_t>, 16>;
@@ -232,15 +233,16 @@ struct UnwindState {
ProfiledFrame *Parent;
SampleVector RangeSamples;
SampleVector BranchSamples;
- std::unordered_map<uint64_t, std::unique_ptr<ProfiledFrame>> Children;
+ DenseMap<uint64_t, std::unique_ptr<ProfiledFrame>> Children;
ProfiledFrame(uint64_t Addr = 0, ProfiledFrame *P = nullptr)
: Address(Addr), Parent(P) {}
ProfiledFrame *getOrCreateChildFrame(uint64_t Address) {
assert(Address && "Address can't be zero!");
- auto Ret = Children.emplace(
- Address, std::make_unique<ProfiledFrame>(Address, this));
- return Ret.first->second.get();
+ auto [It, Inserted] = Children.try_emplace(Address);
+ if (Inserted)
+ It->second = std::make_unique<ProfiledFrame>(Address, this);
+ return It->second.get();
}
void recordRangeCount(uint64_t Start, uint64_t End, uint64_t Count) {
RangeSamples.emplace_back(std::make_tuple(Start, End, Count));
@@ -416,9 +418,7 @@ struct SampleCounter {
};
// Sample counter with context to support context-sensitive profile
-using ContextSampleCounterMap =
- std::unordered_map<Hashable<ContextKey>, SampleCounter,
- Hashable<ContextKey>::Hash, Hashable<ContextKey>::Equal>;
+using ContextSampleCounterMap = DenseMap<Hashable<ContextKey>, SampleCounter>;
struct FrameStack {
SmallVector<uint64_t, 16> Stack;
@@ -747,7 +747,9 @@ class UnsymbolizedProfileReader : public PerfReaderBase {
void readSampleCounters(TraceStream &TraceIt, SampleCounter &SCounters);
void readUnsymbolizedProfile(StringRef Filename);
- std::unordered_set<std::string> ContextStrSet;
+ // Owns the context strings; context frames hold StringRefs into them, which
+ // is fine: StringSet entry storage is stable.
+ StringSet<> ContextStrSet;
};
class ETMReader {
diff --git a/llvm/tools/llvm-profgen/ProfileGenerator.cpp b/llvm/tools/llvm-profgen/ProfileGenerator.cpp
index 10b5e9ad3def5..97643c1aa1708 100644
--- a/llvm/tools/llvm-profgen/ProfileGenerator.cpp
+++ b/llvm/tools/llvm-profgen/ProfileGenerator.cpp
@@ -434,7 +434,7 @@ void ProfileGeneratorBase::updateFunctionSamples() {
}
void ProfileGeneratorBase::collectProfiledFunctions() {
- std::unordered_set<const BinaryFunction *> ProfiledFunctions;
+ SmallPtrSet<const BinaryFunction *, 0> ProfiledFunctions;
if (collectFunctionsFromRawProfile(ProfiledFunctions))
Binary->setProfiledFunctions(ProfiledFunctions);
else if (collectFunctionsFromLLVMProfile(ProfiledFunctions))
@@ -444,7 +444,7 @@ void ProfileGeneratorBase::collectProfiledFunctions() {
}
bool ProfileGeneratorBase::collectFunctionsFromRawProfile(
- std::unordered_set<const BinaryFunction *> &ProfiledFunctions) {
+ SmallPtrSetImpl<const BinaryFunction *> &ProfiledFunctions) {
if (!SampleCounters)
return false;
// Go through all the stacks, ranges and branches in sample counters, use
@@ -477,7 +477,7 @@ bool ProfileGeneratorBase::collectFunctionsFromRawProfile(
}
bool ProfileGenerator::collectFunctionsFromLLVMProfile(
- std::unordered_set<const BinaryFunction *> &ProfiledFunctions) {
+ SmallPtrSetImpl<const BinaryFunction *> &ProfiledFunctions) {
for (const auto &FS : ProfileMap) {
if (auto *Func = Binary->getBinaryFunction(FS.second.getFunction()))
ProfiledFunctions.insert(Func);
@@ -486,7 +486,7 @@ bool ProfileGenerator::collectFunctionsFromLLVMProfile(
}
bool CSProfileGenerator::collectFunctionsFromLLVMProfile(
- std::unordered_set<const BinaryFunction *> &ProfiledFunctions) {
+ SmallPtrSetImpl<const BinaryFunction *> &ProfiledFunctions) {
for (auto *Node : ContextTracker) {
if (!Node->getFuncName().empty())
if (auto *Func = Binary->getBinaryFunction(Node->getFuncName()))
@@ -1296,8 +1296,7 @@ void CSProfileGenerator::populateBodySamplesWithProbes(
// Extract the top frame probes by looking up each address among the range in
// the Address2ProbeMap
extractProbesFromRange(RangeCounter, ProbeCounter);
- std::unordered_map<MCDecodedPseudoProbeInlineTree *,
- std::unordered_set<FunctionSamples *>>
+ DenseMap<MCDecodedPseudoProbeInlineTree *, SmallPtrSet<FunctionSamples *, 0>>
FrameSamples;
for (const auto &PI : ProbeCounter) {
const MCDecodedPseudoProbe *Probe = PI.first;
diff --git a/llvm/tools/llvm-profgen/ProfileGenerator.h b/llvm/tools/llvm-profgen/ProfileGenerator.h
index 2c512779319d4..274dec5d4cf24 100644
--- a/llvm/tools/llvm-profgen/ProfileGenerator.h
+++ b/llvm/tools/llvm-profgen/ProfileGenerator.h
@@ -12,6 +12,8 @@
#include "ErrorHandling.h"
#include "PerfReader.h"
#include "ProfiledBinary.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/ProfileData/SampleProfWriter.h"
#include <memory>
@@ -20,8 +22,7 @@
namespace llvm {
namespace sampleprof {
-using ProbeCounterMap =
- std::unordered_map<const MCDecodedPseudoProbe *, uint64_t>;
+using ProbeCounterMap = DenseMap<const MCDecodedPseudoProbe *, uint64_t>;
// This base class for profile generation of sample-based PGO. We reuse all
// structures relating to function profiles and profile writers as seen in
@@ -128,11 +129,11 @@ class ProfileGeneratorBase {
void collectProfiledFunctions();
bool collectFunctionsFromRawProfile(
- std::unordered_set<const BinaryFunction *> &ProfiledFunctions);
+ SmallPtrSetImpl<const BinaryFunction *> &ProfiledFunctions);
// Collect profiled Functions for llvm sample profile input.
virtual bool collectFunctionsFromLLVMProfile(
- std::unordered_set<const BinaryFunction *> &ProfiledFunctions) = 0;
+ SmallPtrSetImpl<const BinaryFunction *> &ProfiledFunctions) = 0;
// List of function prefix to filter out.
static constexpr const char *FuncPrefixsToFilter[] = {"__cxx_global_var_init",
@@ -186,7 +187,7 @@ class ProfileGenerator : public ProfileGeneratorBase {
void postProcessProfiles();
void trimColdProfiles(uint64_t ColdCntThreshold);
bool collectFunctionsFromLLVMProfile(
- std::unordered_set<const BinaryFunction *> &ProfiledFunctions) override;
+ SmallPtrSetImpl<const BinaryFunction *> &ProfiledFunctions) override;
};
class CSProfileGenerator : public ProfileGeneratorBase {
@@ -367,7 +368,7 @@ class CSProfileGenerator : public ProfileGeneratorBase {
void computeSummaryAndThreshold();
bool collectFunctionsFromLLVMProfile(
- std::unordered_set<const BinaryFunction *> &ProfiledFunctions) override;
+ SmallPtrSetImpl<const BinaryFunction *> &ProfiledFunctions) override;
void initializeMissingFrameInferrer();
@@ -381,7 +382,9 @@ class CSProfileGenerator : public ProfileGeneratorBase {
// The container for holding the FunctionSamples used by context trie.
std::list<FunctionSamples> FSamplesList;
- // Underlying context table serves for sample profile writer.
+ // Underlying context table serves for sample profile writer. SampleContexts
+ // in the output profile hold ArrayRefs into the stored vectors, so the
+ // elements' addresses must be stable: keep std::unordered_set.
std::unordered_set<SampleContextFrameVector, SampleContextFrameHash> Contexts;
SampleContextTracker ContextTracker;
diff --git a/llvm/tools/llvm-profgen/ProfiledBinary.cpp b/llvm/tools/llvm-profgen/ProfiledBinary.cpp
index 3b1e00093fb9e..ab452d78062e6 100644
--- a/llvm/tools/llvm-profgen/ProfiledBinary.cpp
+++ b/llvm/tools/llvm-profgen/ProfiledBinary.cpp
@@ -1165,8 +1165,8 @@ SampleContextFrameVector ProfiledBinary::symbolize(const InstructionPointer &IP,
}
LineLocation Line(LineOffset, Discriminator);
- auto It = NameStrings.insert(FunctionName.str());
- CallStack.emplace_back(FunctionId(StringRef(*It.first)), Line);
+ auto It = NameStrings.insert(FunctionName);
+ CallStack.emplace_back(FunctionId(It.first->getKey()), Line);
}
return CallStack;
@@ -1177,9 +1177,7 @@ StringRef ProfiledBinary::symbolizeDataAddress(uint64_t Address) {
unwrapOrError(Symbolizer->symbolizeData(SymbolizerPath.str(),
getSectionedAddress(Address)),
SymbolizerPath);
- decltype(NameStrings)::iterator Iter;
- std::tie(Iter, std::ignore) = NameStrings.insert(DataDIGlobal.Name);
- return StringRef(*Iter);
+ return NameStrings.insert(DataDIGlobal.Name).first->getKey();
}
void ProfiledBinary::computeInlinedContextSizeForRange(uint64_t RangeBegin,
@@ -1250,7 +1248,7 @@ void ProfiledBinary::loadSymbolsFromPseudoProbe() {
"Top level pseudo probe does not match function range");
const auto *ProbeDesc = getFuncDescForGUID(InlineTreeNode->Guid);
- auto Ret = PseudoProbeNames.emplace(Func, ProbeDesc->FuncName);
+ auto Ret = PseudoProbeNames.try_emplace(Func, ProbeDesc->FuncName);
if (!Ret.second && Ret.first->second != ProbeDesc->FuncName &&
ShowDetailedWarning)
WithColor::warning()
diff --git a/llvm/tools/llvm-profgen/ProfiledBinary.h b/llvm/tools/llvm-profgen/ProfiledBinary.h
index a407adb978091..cb15fb14a4680 100644
--- a/llvm/tools/llvm-profgen/ProfiledBinary.h
+++ b/llvm/tools/llvm-profgen/ProfiledBinary.h
@@ -12,6 +12,8 @@
#include "CallContext.h"
#include "ErrorHandling.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
@@ -119,7 +121,7 @@ struct FuncRange {
// we will switch to Dwarf CFI based tracker
struct PrologEpilogTracker {
// A set of prolog and epilog addresses. Used by virtual unwinding.
- std::unordered_set<uint64_t> PrologEpilogSet;
+ DenseSet<uint64_t> PrologEpilogSet;
ProfiledBinary *Binary;
PrologEpilogTracker(ProfiledBinary *Bin) : Binary(Bin){};
@@ -136,7 +138,7 @@ struct PrologEpilogTracker {
}
// Take the last two addresses before the return address as epilog
- void inferEpilogAddresses(std::unordered_set<uint64_t> &RetAddrs) {
+ void inferEpilogAddresses(DenseSet<uint64_t> &RetAddrs) {
for (auto Addr : RetAddrs) {
PrologEpilogSet.insert(Addr);
InstructionPointer IP(Binary, Addr);
@@ -240,10 +242,10 @@ class ProfiledBinary {
// Lookup BinaryFunctions using the function name's MD5 hash. Needed if the
// profile is using MD5.
- std::unordered_map<uint64_t, BinaryFunction *> HashBinaryFunctions;
+ DenseMap<uint64_t, BinaryFunction *> HashBinaryFunctions;
// A list of binary functions that have samples.
- std::unordered_set<const BinaryFunction *> ProfiledFunctions;
+ SmallPtrSet<const BinaryFunction *, 0> ProfiledFunctions;
// GUID to symbol start address map
DenseMap<uint64_t, uint64_t> SymbolStartAddrs;
@@ -254,7 +256,7 @@ class ProfiledBinary {
AlternativeFunctionGUIDs;
// Mapping of profiled binary function to its pseudo probe name
- std::unordered_map<const BinaryFunction *, StringRef> PseudoProbeNames;
+ DenseMap<const BinaryFunction *, StringRef> PseudoProbeNames;
// These maps are for temporary use of warning diagnosis.
DenseSet<int64_t> AddrsWithMultipleSymbols;
@@ -269,26 +271,29 @@ class ProfiledBinary {
std::map<uint64_t, FuncRange> StartAddrToFuncRangeMap;
// Address to context location map. Used to expand the context.
+ // getCachedFrameLocationStack returns references to the mapped values while
+ // later queries insert, so the values' addresses must be stable: keep
+ // std::unordered_map.
std::unordered_map<uint64_t, SampleContextFrameVector> AddressToLocStackMap;
// Address to instruction size map. Also used for quick Address lookup.
- std::unordered_map<uint64_t, uint64_t> AddressToInstSizeMap;
+ DenseMap<uint64_t, uint64_t> AddressToInstSizeMap;
// An array of Addresses of all instructions sorted in increasing order. The
// sorting is needed to fast advance to the next forward/backward instruction.
std::vector<uint64_t> CodeAddressVec;
// A set of call instruction addresses. Used by virtual unwinding.
- std::unordered_set<uint64_t> CallAddressSet;
+ DenseSet<uint64_t> CallAddressSet;
// A set of return instruction addresses. Used by virtual unwinding.
- std::unordered_set<uint64_t> RetAddressSet;
+ DenseSet<uint64_t> RetAddressSet;
// An ordered set of unconditional branch instruction addresses.
std::set<uint64_t> UncondBranchAddrSet;
// A set of branch instruction addresses.
- std::unordered_set<uint64_t> BranchAddressSet;
+ DenseSet<uint64_t> BranchAddressSet;
// A set of indirect branch instruction addresses.
- std::unordered_set<uint64_t> IndirectBranchAddressSet;
+ DenseSet<uint64_t> IndirectBranchAddressSet;
// A set of branch target addresses (destinations of branches/calls).
- std::unordered_set<uint64_t> BranchTargetAddressSet;
+ DenseSet<uint64_t> BranchTargetAddressSet;
// Estimate and track function prolog and epilog ranges.
PrologEpilogTracker ProEpilogTracker;
@@ -304,7 +309,9 @@ class ProfiledBinary {
std::unique_ptr<symbolize::LLVMSymbolizer> Symbolizer;
// String table owning function name strings created from the symbolizer.
- std::unordered_set<std::string> NameStrings;
+ // StringRefs into the stored names are retained by symbolization results,
+ // which is fine: StringSet entry storage is stable.
+ StringSet<> NameStrings;
// MMap events for PT_LOAD segments without 'x' memory protection flag.
std::map<uint64_t, MMapEvent, std::greater<uint64_t>> NonTextMMapEvents;
@@ -575,12 +582,13 @@ class ProfiledBinary {
return BinaryFunctions;
}
- std::unordered_set<const BinaryFunction *> &getProfiledFunctions() {
+ SmallPtrSetImpl<const BinaryFunction *> &getProfiledFunctions() {
return ProfiledFunctions;
}
- void setProfiledFunctions(std::unordered_set<const BinaryFunction *> &Funcs) {
- ProfiledFunctions = Funcs;
+ void setProfiledFunctions(SmallPtrSetImpl<const BinaryFunction *> &Funcs) {
+ ProfiledFunctions.clear();
+ ProfiledFunctions.insert_range(Funcs);
}
BinaryFunction *getBinaryFunction(FunctionId FName) {
diff --git a/llvm/tools/llvm-readobj/ObjDumper.h b/llvm/tools/llvm-readobj/ObjDumper.h
index 0dba8252fd466..f019ceee112d9 100644
--- a/llvm/tools/llvm-readobj/ObjDumper.h
+++ b/llvm/tools/llvm-readobj/ObjDumper.h
@@ -15,12 +15,11 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSet.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Object/OffloadBinary.h"
#include "llvm/Support/CommandLine.h"
-#include <unordered_set>
-
namespace llvm {
namespace object {
class Archive;
@@ -207,7 +206,7 @@ class ObjDumper {
virtual void printProgramHeaders() {}
virtual void printSectionMapping() {}
- std::unordered_set<std::string> Warnings;
+ StringSet<> Warnings;
};
std::unique_ptr<ObjDumper> createCOFFDumper(const object::COFFObjectFile &Obj,
diff --git a/llvm/tools/llvm-remarkutil/RemarkUtilRegistry.cpp b/llvm/tools/llvm-remarkutil/RemarkUtilRegistry.cpp
index 244a16d51805b..8ff8ac3d79ce0 100644
--- a/llvm/tools/llvm-remarkutil/RemarkUtilRegistry.cpp
+++ b/llvm/tools/llvm-remarkutil/RemarkUtilRegistry.cpp
@@ -10,15 +10,15 @@
//
//===----------------------------------------------------------------------===//
#include "RemarkUtilRegistry.h"
-#include <unordered_map>
+#include "llvm/ADT/DenseMap.h"
namespace llvm {
namespace remarkutil {
using HandlerType = std::function<Error()>;
-static std::unordered_map<cl::SubCommand *, HandlerType> &getCommands() {
- static std::unordered_map<cl::SubCommand *, HandlerType> Commands;
+static DenseMap<cl::SubCommand *, HandlerType> &getCommands() {
+ static DenseMap<cl::SubCommand *, HandlerType> Commands;
return Commands;
}
diff --git a/llvm/tools/llvm-xray/xray-registry.cpp b/llvm/tools/llvm-xray/xray-registry.cpp
index ae18f8d6f57c1..d5149a20c58ea 100644
--- a/llvm/tools/llvm-xray/xray-registry.cpp
+++ b/llvm/tools/llvm-xray/xray-registry.cpp
@@ -11,15 +11,15 @@
//===----------------------------------------------------------------------===//
#include "xray-registry.h"
-#include <unordered_map>
+#include "llvm/ADT/DenseMap.h"
using namespace llvm;
using namespace xray;
using HandlerType = std::function<Error()>;
-static std::unordered_map<cl::SubCommand *, HandlerType> &getCommands() {
- static std::unordered_map<cl::SubCommand *, HandlerType> Commands;
+static DenseMap<cl::SubCommand *, HandlerType> &getCommands() {
+ static DenseMap<cl::SubCommand *, HandlerType> Commands;
return Commands;
}
More information about the llvm-commits
mailing list