Skip to content

Commit 59631d4

Browse files
committed
Store GUIDs in metadata
This takes the existing AssignGUID pass from CtxProfAnalysis, and runs it by default, at the appropriate stages of the LTO pipeline. It also changes GlobalValue::getGUID() to retrieve the GUID from the metadata instead of computing it. We don't yet have the supporting downstream changes to make a dedicated GUID table in bitcode, nor do we use the metadata as part of ThinLTO -- it retains its existing mechanisms of recomputing GUIDs from separately saved data. That will be changed later.
1 parent 49e4618 commit 59631d4

14 files changed

+130
-84
lines changed

llvm/include/llvm/Analysis/CtxProfAnalysis.h

Lines changed: 5 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,6 @@ class PGOContextualProfile {
3737
// we'll need when we maintain the profiles during IPO transformations.
3838
std::map<GlobalValue::GUID, FunctionInfo> FuncInfo;
3939

40-
/// Get the GUID of this Function if it's defined in this module.
41-
GlobalValue::GUID getDefinedFunctionGUID(const Function &F) const;
42-
4340
// This is meant to be constructed from CtxProfAnalysis, which will also set
4441
// its state piecemeal.
4542
PGOContextualProfile() = default;
@@ -56,9 +53,7 @@ class PGOContextualProfile {
5653

5754
const PGOCtxProfile &profiles() const { return Profiles; }
5855

59-
bool isFunctionKnown(const Function &F) const {
60-
return getDefinedFunctionGUID(F) != 0;
61-
}
56+
bool isFunctionKnown(const Function &F) const { return F.getGUID() != 0; }
6257

6358
StringRef getFunctionName(GlobalValue::GUID GUID) const {
6459
auto It = FuncInfo.find(GUID);
@@ -69,22 +64,22 @@ class PGOContextualProfile {
6964

7065
uint32_t getNumCounters(const Function &F) const {
7166
assert(isFunctionKnown(F));
72-
return FuncInfo.find(getDefinedFunctionGUID(F))->second.NextCounterIndex;
67+
return FuncInfo.find(F.getGUID())->second.NextCounterIndex;
7368
}
7469

7570
uint32_t getNumCallsites(const Function &F) const {
7671
assert(isFunctionKnown(F));
77-
return FuncInfo.find(getDefinedFunctionGUID(F))->second.NextCallsiteIndex;
72+
return FuncInfo.find(F.getGUID())->second.NextCallsiteIndex;
7873
}
7974

8075
uint32_t allocateNextCounterIndex(const Function &F) {
8176
assert(isFunctionKnown(F));
82-
return FuncInfo.find(getDefinedFunctionGUID(F))->second.NextCounterIndex++;
77+
return FuncInfo.find(F.getGUID())->second.NextCounterIndex++;
8378
}
8479

8580
uint32_t allocateNextCallsiteIndex(const Function &F) {
8681
assert(isFunctionKnown(F));
87-
return FuncInfo.find(getDefinedFunctionGUID(F))->second.NextCallsiteIndex++;
82+
return FuncInfo.find(F.getGUID())->second.NextCallsiteIndex++;
8883
}
8984

9085
using ConstVisitor = function_ref<void(const PGOCtxProfContext &)>;
@@ -145,26 +140,5 @@ class CtxProfAnalysisPrinterPass
145140
const PrintMode Mode;
146141
};
147142

148-
/// Assign a GUID to functions as metadata. GUID calculation takes linkage into
149-
/// account, which may change especially through and after thinlto. By
150-
/// pre-computing and assigning as metadata, this mechanism is resilient to such
151-
/// changes (as well as name changes e.g. suffix ".llvm." additions).
152-
153-
// FIXME(mtrofin): we can generalize this mechanism to calculate a GUID early in
154-
// the pass pipeline, associate it with any Global Value, and then use it for
155-
// PGO and ThinLTO.
156-
// At that point, this should be moved elsewhere.
157-
class AssignGUIDPass : public PassInfoMixin<AssignGUIDPass> {
158-
public:
159-
explicit AssignGUIDPass() = default;
160-
161-
/// Assign a GUID *if* one is not already assign, as a function metadata named
162-
/// `GUIDMetadataName`.
163-
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM);
164-
static const char *GUIDMetadataName;
165-
// This should become GlobalValue::getGUID
166-
static uint64_t getGUID(const Function &F);
167-
};
168-
169143
} // namespace llvm
170144
#endif // LLVM_ANALYSIS_CTXPROFANALYSIS_H

llvm/include/llvm/IR/FixedMetadataKinds.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,4 @@ LLVM_FIXED_MD_KIND(MD_DIAssignID, "DIAssignID", 38)
5353
LLVM_FIXED_MD_KIND(MD_coro_outside_frame, "coro.outside.frame", 39)
5454
LLVM_FIXED_MD_KIND(MD_mmra, "mmra", 40)
5555
LLVM_FIXED_MD_KIND(MD_noalias_addrspace, "noalias.addrspace", 41)
56+
LLVM_FIXED_MD_KIND(MD_unique_id, "unique_id", 42)

llvm/include/llvm/IR/GlobalValue.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -594,11 +594,11 @@ class GlobalValue : public Constant {
594594
/// the GUID computation will assume that the global has external linkage.
595595
static GUID getGUIDAssumingExternalLinkage(StringRef GlobalName);
596596

597+
bool assignGUID();
598+
597599
/// Return a 64-bit global unique ID constructed from global value name
598600
/// (i.e. returned by getGlobalIdentifier()).
599-
GUID getGUID() const {
600-
return getGUIDAssumingExternalLinkage(getGlobalIdentifier());
601-
}
601+
GUID getGUID() const;
602602

603603
/// @name Materialization
604604
/// Materialization is used to construct functions only as they're needed.
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
//===-- AssignGUID.h - Unique identifier assignment pass --------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This file provides a pass which assigns a a GUID (globally unique identifier)
10+
// to every GlobalValue in the module, according to its current name, linkage,
11+
// and originating file.
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
#ifndef LLVM_TRANSFORMS_UTILS_ASSIGNGUID_H
16+
#define LLVM_TRANSFORMS_UTILS_ASSIGNGUID_H
17+
18+
#include "llvm/IR/Module.h"
19+
#include "llvm/IR/PassManager.h"
20+
21+
namespace llvm {
22+
23+
class AssignGUIDPass : public PassInfoMixin<AssignGUIDPass> {
24+
public:
25+
AssignGUIDPass() = default;
26+
27+
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
28+
29+
static bool isRequired() { return true; }
30+
};
31+
32+
} // end namespace llvm
33+
34+
#endif // LLVM_TRANSFORMS_UTILS_ASSIGNGUID_H

llvm/lib/Analysis/CtxProfAnalysis.cpp

Lines changed: 4 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -37,35 +37,6 @@ static cl::opt<CtxProfAnalysisPrinterPass::PrintMode> PrintLevel(
3737
"just the yaml representation of the profile")),
3838
cl::desc("Verbosity level of the contextual profile printer pass."));
3939

40-
const char *AssignGUIDPass::GUIDMetadataName = "guid";
41-
42-
PreservedAnalyses AssignGUIDPass::run(Module &M, ModuleAnalysisManager &MAM) {
43-
for (auto &F : M.functions()) {
44-
if (F.isDeclaration())
45-
continue;
46-
if (F.getMetadata(GUIDMetadataName))
47-
continue;
48-
const GlobalValue::GUID GUID = F.getGUID();
49-
F.setMetadata(GUIDMetadataName,
50-
MDNode::get(M.getContext(),
51-
{ConstantAsMetadata::get(ConstantInt::get(
52-
Type::getInt64Ty(M.getContext()), GUID))}));
53-
}
54-
return PreservedAnalyses::none();
55-
}
56-
57-
GlobalValue::GUID AssignGUIDPass::getGUID(const Function &F) {
58-
if (F.isDeclaration()) {
59-
assert(GlobalValue::isExternalLinkage(F.getLinkage()));
60-
return F.getGUID();
61-
}
62-
auto *MD = F.getMetadata(GUIDMetadataName);
63-
assert(MD && "guid not found for defined function");
64-
return cast<ConstantInt>(cast<ConstantAsMetadata>(MD->getOperand(0))
65-
->getValue()
66-
->stripPointerCasts())
67-
->getZExtValue();
68-
}
6940
AnalysisKey CtxProfAnalysis::Key;
7041

7142
CtxProfAnalysis::CtxProfAnalysis(std::optional<StringRef> Profile)
@@ -98,7 +69,7 @@ PGOContextualProfile CtxProfAnalysis::run(Module &M,
9869
DenseSet<GlobalValue::GUID> ProfileRootsInModule;
9970
for (const auto &F : M)
10071
if (!F.isDeclaration())
101-
if (auto GUID = AssignGUIDPass::getGUID(F);
72+
if (auto GUID = F.getGUID();
10273
MaybeProfiles->Contexts.find(GUID) != MaybeProfiles->Contexts.end())
10374
ProfileRootsInModule.insert(GUID);
10475

@@ -118,7 +89,7 @@ PGOContextualProfile CtxProfAnalysis::run(Module &M,
11889
for (const auto &F : M) {
11990
if (F.isDeclaration())
12091
continue;
121-
auto GUID = AssignGUIDPass::getGUID(F);
92+
auto GUID = F.getGUID();
12293
assert(GUID && "guid not found for defined function");
12394
const auto &Entry = F.begin();
12495
uint32_t MaxCounters = 0; // we expect at least a counter.
@@ -152,13 +123,6 @@ PGOContextualProfile CtxProfAnalysis::run(Module &M,
152123
return Result;
153124
}
154125

155-
GlobalValue::GUID
156-
PGOContextualProfile::getDefinedFunctionGUID(const Function &F) const {
157-
if (auto It = FuncInfo.find(AssignGUIDPass::getGUID(F)); It != FuncInfo.end())
158-
return It->first;
159-
return 0;
160-
}
161-
162126
CtxProfAnalysisPrinterPass::CtxProfAnalysisPrinterPass(raw_ostream &OS)
163127
: OS(OS), Mode(PrintLevel) {}
164128

@@ -262,7 +226,7 @@ void PGOContextualProfile::initIndex() {
262226

263227
void PGOContextualProfile::update(Visitor V, const Function &F) {
264228
assert(isFunctionKnown(F));
265-
GlobalValue::GUID G = getDefinedFunctionGUID(F);
229+
GlobalValue::GUID G = F.getGUID();
266230
for (auto *Node = FuncInfo.find(G)->second.Index.Next; Node;
267231
Node = Node->Next)
268232
V(*reinterpret_cast<PGOCtxProfContext *>(Node));
@@ -273,7 +237,7 @@ void PGOContextualProfile::visit(ConstVisitor V, const Function *F) const {
273237
return preorderVisit<const PGOCtxProfContext::CallTargetMapTy,
274238
const PGOCtxProfContext>(Profiles.Contexts, V);
275239
assert(isFunctionKnown(*F));
276-
GlobalValue::GUID G = getDefinedFunctionGUID(*F);
240+
GlobalValue::GUID G = F->getGUID();
277241
for (const auto *Node = FuncInfo.find(G)->second.Index.Next; Node;
278242
Node = Node->Next)
279243
V(*reinterpret_cast<const PGOCtxProfContext *>(Node));

llvm/lib/IR/Globals.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,40 @@ GlobalValue::getGUIDAssumingExternalLinkage(StringRef GlobalIdentifier) {
7878
return MD5Hash(GlobalIdentifier);
7979
}
8080

81+
bool GlobalValue::assignGUID() {
82+
if (isDeclaration())
83+
return false;
84+
if (getMetadata(LLVMContext::MD_unique_id) != nullptr)
85+
return false;
86+
87+
const GUID G =
88+
GlobalValue::getGUIDAssumingExternalLinkage(getGlobalIdentifier());
89+
setMetadata(
90+
LLVMContext::MD_unique_id,
91+
MDNode::get(getContext(), {ConstantAsMetadata::get(ConstantInt::get(
92+
Type::getInt64Ty(getContext()), G))}));
93+
return true;
94+
}
95+
96+
GlobalValue::GUID GlobalValue::getGUID() const {
97+
// TODO: do we need a special case for GlobalAlias?
98+
99+
if (isDeclaration()) {
100+
// Declarations don't get an assigned GUID. Their definition is in another
101+
// module, and it may have been promoted from local to external linkage
102+
// during LTO. Because of this, we can only determine their GUID once the
103+
// definition is available.
104+
return 0;
105+
}
106+
107+
auto *MD = getMetadata(LLVMContext::MD_unique_id);
108+
assert(MD != nullptr && "GUID was not assigned before calling GetGUID()");
109+
return cast<ConstantInt>(cast<ConstantAsMetadata>(MD->getOperand(0))
110+
->getValue()
111+
->stripPointerCasts())
112+
->getZExtValue();
113+
}
114+
81115
void GlobalValue::removeFromParent() {
82116
switch (getValueID()) {
83117
#define HANDLE_GLOBAL_VALUE(NAME) \

llvm/lib/Passes/PassBuilder.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,7 @@
324324
#include "llvm/Transforms/Scalar/TailRecursionElimination.h"
325325
#include "llvm/Transforms/Scalar/WarnMissedTransforms.h"
326326
#include "llvm/Transforms/Utils/AddDiscriminators.h"
327+
#include "llvm/Transforms/Utils/AssignGUID.h"
327328
#include "llvm/Transforms/Utils/AssumeBundleBuilder.h"
328329
#include "llvm/Transforms/Utils/BreakCriticalEdges.h"
329330
#include "llvm/Transforms/Utils/CanonicalizeAliases.h"

llvm/lib/Passes/PassBuilderPipelines.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@
130130
#include "llvm/Transforms/Scalar/TailRecursionElimination.h"
131131
#include "llvm/Transforms/Scalar/WarnMissedTransforms.h"
132132
#include "llvm/Transforms/Utils/AddDiscriminators.h"
133+
#include "llvm/Transforms/Utils/AssignGUID.h"
133134
#include "llvm/Transforms/Utils/AssumeBundleBuilder.h"
134135
#include "llvm/Transforms/Utils/CanonicalizeAliases.h"
135136
#include "llvm/Transforms/Utils/CountVisits.h"
@@ -791,6 +792,7 @@ PassBuilder::buildFunctionSimplificationPipeline(OptimizationLevel Level,
791792
void PassBuilder::addRequiredLTOPreLinkPasses(ModulePassManager &MPM) {
792793
MPM.addPass(CanonicalizeAliasesPass());
793794
MPM.addPass(NameAnonGlobalPass());
795+
MPM.addPass(AssignGUIDPass());
794796
}
795797

796798
void PassBuilder::addPreInlinerPasses(ModulePassManager &MPM,
@@ -1076,6 +1078,11 @@ PassBuilder::buildModuleSimplificationPipeline(OptimizationLevel Level,
10761078

10771079
ModulePassManager MPM;
10781080

1081+
if (Phase != ThinOrFullLTOPhase::ThinLTOPostLink) {
1082+
MPM.addPass(NameAnonGlobalPass());
1083+
MPM.addPass(AssignGUIDPass());
1084+
}
1085+
10791086
// Place pseudo probe instrumentation as the first pass of the pipeline to
10801087
// minimize the impact of optimization changes.
10811088
if (PGOOpt && PGOOpt->PseudoProbeForProfiling &&
@@ -1239,8 +1246,6 @@ PassBuilder::buildModuleSimplificationPipeline(OptimizationLevel Level,
12391246
// In pre-link, we just want the instrumented IR. We use the contextual
12401247
// profile in the post-thinlink phase.
12411248
// The instrumentation will be removed in post-thinlink after IPO.
1242-
// FIXME(mtrofin): move AssignGUIDPass if there is agreement to use this
1243-
// mechanism for GUIDs.
12441249
MPM.addPass(AssignGUIDPass());
12451250
if (IsCtxProfUse)
12461251
return MPM;

llvm/lib/Transforms/Instrumentation/PGOCtxProfFlattening.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -451,7 +451,7 @@ PreservedAnalyses PGOCtxProfFlatteningPass::run(Module &M,
451451
"Function has unreacheable basic blocks. The expectation was that "
452452
"DCE was run before.");
453453

454-
auto It = FlattenedProfile.find(AssignGUIDPass::getGUID(F));
454+
auto It = FlattenedProfile.find(F.getGUID());
455455
// If this function didn't appear in the contextual profile, it's cold.
456456
if (It == FlattenedProfile.end())
457457
clearColdFunctionProfile(F);

llvm/lib/Transforms/Instrumentation/PGOCtxProfLowering.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -235,8 +235,7 @@ bool CtxInstrumentationLowerer::lowerFunction(Function &F) {
235235
assert(Mark->getIndex()->isZero());
236236

237237
IRBuilder<> Builder(Mark);
238-
Guid = Builder.getInt64(
239-
AssignGUIDPass::getGUID(cast<Function>(*Mark->getNameValue())));
238+
Guid = Builder.getInt64(cast<Function>(*Mark->getNameValue()).getGUID());
240239
// The type of the context of this function is now knowable since we have
241240
// NumCallsites and NumCounters. We delcare it here because it's more
242241
// convenient - we have the Builder.
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
//===-- AssignGUID.cpp - Unique identifier assignment pass ------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This file provides a pass which assigns a a GUID (globally unique identifier)
10+
// to every GlobalValue in the module, according to its current name, linkage,
11+
// and originating file.
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
#include "llvm/Transforms/Utils/AssignGUID.h"
16+
#include "llvm/Support/Debug.h"
17+
18+
using namespace llvm;
19+
20+
PreservedAnalyses AssignGUIDPass::run(Module &M, ModuleAnalysisManager &AM) {
21+
for (auto &GV : M.globals()) {
22+
if (GV.isDeclaration())
23+
continue;
24+
GV.assignGUID();
25+
dbgs() << "[Added GUID to GV:] " << GV.getName() << "\n";
26+
}
27+
for (auto &F : M.functions()) {
28+
if (F.isDeclaration())
29+
continue;
30+
F.assignGUID();
31+
dbgs() << "[Added GUID to F:] " << F.getName() << "\n";
32+
}
33+
return PreservedAnalyses::none();
34+
}

llvm/lib/Transforms/Utils/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ add_llvm_component_library(LLVMTransformUtils
22
AddDiscriminators.cpp
33
AMDGPUEmitPrintf.cpp
44
ASanStackFrameLayout.cpp
5+
AssignGUID.cpp
56
AssumeBundleBuilder.cpp
67
BasicBlockUtils.cpp
78
BreakCriticalEdges.cpp

llvm/lib/Transforms/Utils/CallPromotionUtils.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -616,11 +616,11 @@ CallBase *llvm::promoteCallWithIfThenElse(CallBase &CB, Function &Callee,
616616
IndirectBBIns->setIndex(IndirectID);
617617
IndirectBBIns->insertInto(&IndirectBB, IndirectBB.getFirstInsertionPt());
618618

619-
const GlobalValue::GUID CalleeGUID = AssignGUIDPass::getGUID(Callee);
619+
const GlobalValue::GUID CalleeGUID = Callee.getGUID();
620620
const uint32_t NewCountersSize = IndirectID + 1;
621621

622622
auto ProfileUpdater = [&](PGOCtxProfContext &Ctx) {
623-
assert(Ctx.guid() == AssignGUIDPass::getGUID(Caller));
623+
assert(Ctx.guid() == Caller.getGUID());
624624
assert(NewCountersSize - 2 == Ctx.counters().size());
625625
// All the ctx-es belonging to a function must have the same size counters.
626626
Ctx.resizeCounters(NewCountersSize);
@@ -655,7 +655,6 @@ CallBase *llvm::promoteCallWithIfThenElse(CallBase &CB, Function &Callee,
655655
// times, and the indirect BB, IndirectCount times
656656
Ctx.counters()[DirectID] = DirectCount;
657657
Ctx.counters()[IndirectID] = IndirectCount;
658-
659658
};
660659
CtxProf.update(ProfileUpdater, Caller);
661660
return &DirectCall;

0 commit comments

Comments
 (0)