Skip to content

Commit 3976fa6

Browse files
mtrofinronlieb
authored andcommitted
[ctx_prof] Extend WorkloadImportsManager to use the contextual profile (llvm#98682)
Keeping the json-based input as it's useful for diagnostics or for driving the import by other means than contextual composition. The support for the contextual profile is just another modality for constructing the import list (`WorkloadImportsManager::Workloads`). Everything else - i.e. the actual importing logic - is already independent from how that list was obtained. Change-Id: I267f13222a7007aeffb690feac00af90e779301a
1 parent e6fa1a2 commit 3976fa6

File tree

3 files changed

+149
-13
lines changed

3 files changed

+149
-13
lines changed

llvm/lib/Transforms/IPO/FunctionImport.cpp

Lines changed: 76 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
#include "llvm/ADT/StringRef.h"
2020
#include "llvm/Bitcode/BitcodeReader.h"
2121
#include "llvm/IR/AutoUpgrade.h"
22-
#include "llvm/IR/Constants.h"
2322
#include "llvm/IR/Function.h"
2423
#include "llvm/IR/GlobalAlias.h"
2524
#include "llvm/IR/GlobalObject.h"
@@ -30,6 +29,7 @@
3029
#include "llvm/IR/ModuleSummaryIndex.h"
3130
#include "llvm/IRReader/IRReader.h"
3231
#include "llvm/Linker/IRMover.h"
32+
#include "llvm/ProfileData/PGOCtxProfReader.h"
3333
#include "llvm/Support/Casting.h"
3434
#include "llvm/Support/CommandLine.h"
3535
#include "llvm/Support/Debug.h"
@@ -176,6 +176,10 @@ static cl::opt<std::string> WorkloadDefinitions(
176176

177177
extern cl::opt<std::string> UseCtxProfile;
178178

179+
static cl::opt<std::string>
180+
ContextualProfile("thinlto-pgo-ctx-prof",
181+
cl::desc("Path to a contextual profile."), cl::Hidden);
182+
179183
namespace llvm {
180184
extern cl::opt<bool> EnableMemProfContextDisambiguation;
181185
}
@@ -634,13 +638,7 @@ class WorkloadImportsManager : public ModuleImportsManager {
634638
LLVM_DEBUG(dbgs() << "[Workload] Done\n");
635639
}
636640

637-
public:
638-
WorkloadImportsManager(
639-
function_ref<bool(GlobalValue::GUID, const GlobalValueSummary *)>
640-
IsPrevailing,
641-
const ModuleSummaryIndex &Index,
642-
DenseMap<StringRef, FunctionImporter::ExportSetTy> *ExportLists)
643-
: ModuleImportsManager(IsPrevailing, Index, ExportLists) {
641+
void loadFromJson() {
644642
// Since the workload def uses names, we need a quick lookup
645643
// name->ValueInfo.
646644
StringMap<ValueInfo> NameToValueInfo;
@@ -710,15 +708,81 @@ class WorkloadImportsManager : public ModuleImportsManager {
710708
}
711709
Set.insert(ElemIt->second);
712710
}
713-
LLVM_DEBUG({
711+
}
712+
}
713+
714+
void loadFromCtxProf() {
715+
std::error_code EC;
716+
auto BufferOrErr = MemoryBuffer::getFileOrSTDIN(ContextualProfile);
717+
if (std::error_code EC = BufferOrErr.getError()) {
718+
report_fatal_error("Failed to open contextual profile file");
719+
return;
720+
}
721+
auto Buffer = std::move(BufferOrErr.get());
722+
723+
PGOCtxProfileReader Reader(Buffer->getBuffer());
724+
auto Ctx = Reader.loadContexts();
725+
if (!Ctx) {
726+
report_fatal_error("Failed to parse contextual profiles");
727+
return;
728+
}
729+
const auto &CtxMap = *Ctx;
730+
DenseSet<GlobalValue::GUID> ContainedGUIDs;
731+
for (const auto &[RootGuid, Root] : CtxMap) {
732+
// Avoid ContainedGUIDs to get in/out of scope. Reuse its memory for
733+
// subsequent roots, but clear its contents.
734+
ContainedGUIDs.clear();
735+
736+
auto RootVI = Index.getValueInfo(RootGuid);
737+
if (!RootVI) {
738+
LLVM_DEBUG(dbgs() << "[Workload] Root " << RootGuid
739+
<< " not found in this linkage unit.\n");
740+
continue;
741+
}
742+
if (RootVI.getSummaryList().size() != 1) {
743+
LLVM_DEBUG(dbgs() << "[Workload] Root " << RootGuid
744+
<< " should have exactly one summary, but has "
745+
<< RootVI.getSummaryList().size() << ". Skipping.\n");
746+
continue;
747+
}
748+
StringRef RootDefiningModule =
749+
RootVI.getSummaryList().front()->modulePath();
750+
LLVM_DEBUG(dbgs() << "[Workload] Root defining module for " << RootGuid
751+
<< " is : " << RootDefiningModule << "\n");
752+
auto &Set = Workloads[RootDefiningModule];
753+
Root.getContainedGuids(ContainedGUIDs);
754+
for (auto Guid : ContainedGUIDs)
755+
if (auto VI = Index.getValueInfo(Guid))
756+
Set.insert(VI);
757+
}
758+
}
759+
760+
public:
761+
WorkloadImportsManager(
762+
function_ref<bool(GlobalValue::GUID, const GlobalValueSummary *)>
763+
IsPrevailing,
764+
const ModuleSummaryIndex &Index,
765+
DenseMap<StringRef, FunctionImporter::ExportSetTy> *ExportLists)
766+
: ModuleImportsManager(IsPrevailing, Index, ExportLists) {
767+
if (ContextualProfile.empty() == WorkloadDefinitions.empty()) {
768+
report_fatal_error(
769+
"Pass only one of: -thinlto-pgo-ctx-prof or -thinlto-workload-def");
770+
return;
771+
}
772+
if (!ContextualProfile.empty())
773+
loadFromCtxProf();
774+
else
775+
loadFromJson();
776+
LLVM_DEBUG({
777+
for (const auto &[Root, Set] : Workloads) {
714778
dbgs() << "[Workload] Root: " << Root << " we have " << Set.size()
715779
<< " distinct callees.\n";
716780
for (const auto &VI : Set) {
717781
dbgs() << "[Workload] Root: " << Root
718782
<< " Would include: " << VI.getGUID() << "\n";
719783
}
720-
});
721-
}
784+
}
785+
});
722786
}
723787
};
724788

@@ -727,7 +791,7 @@ std::unique_ptr<ModuleImportsManager> ModuleImportsManager::create(
727791
IsPrevailing,
728792
const ModuleSummaryIndex &Index,
729793
DenseMap<StringRef, FunctionImporter::ExportSetTy> *ExportLists) {
730-
if (WorkloadDefinitions.empty()) {
794+
if (WorkloadDefinitions.empty() && ContextualProfile.empty()) {
731795
LLVM_DEBUG(dbgs() << "[Workload] Using the regular imports manager.\n");
732796
return std::unique_ptr<ModuleImportsManager>(
733797
new ModuleImportsManager(IsPrevailing, Index, ExportLists));

llvm/test/ThinLTO/X86/ctxprof.ll

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
; Test workload based importing via -thinlto-pgo-ctx-prof
2+
; Use external linkage symbols so we don't depend on module paths which are
3+
; used when computing the GUIDs of internal linkage symbols.
4+
; The functionality is shared with what workload.ll tests, so here we only care
5+
; about testing the ctx profile is loaded and handled correctly.
6+
;
7+
; Set up
8+
; RUN: rm -rf %t
9+
; RUN: mkdir -p %t
10+
; RUN: split-file %s %t
11+
;
12+
; RUN: opt -module-summary %t/m1.ll -o %t/m1.bc
13+
; RUN: opt -module-summary %t/m2.ll -o %t/m2.bc
14+
; RUN: llvm-dis %t/m1.bc -o - | FileCheck %s --check-prefix=GUIDS-1
15+
; RUN: llvm-dis %t/m2.bc -o - | FileCheck %s --check-prefix=GUIDS-2
16+
;
17+
; GUIDS-1: name: "m1_f1"
18+
; GUIDS-1-SAME: guid = 6019442868614718803
19+
; GUIDS-2: name: "m2_f1"
20+
; GUIDS-2-SAME: guid = 15593096274670919754
21+
;
22+
; RUN: rm -rf %t_baseline
23+
; RUN: rm -rf %t_exp
24+
; RUN: mkdir -p %t_baseline
25+
; RUN: mkdir -p %t_exp
26+
;
27+
; Normal run. m1 shouldn't get m2_f1 because it's not referenced from there, and
28+
; m1_f1 shouldn't go to m2.
29+
;
30+
; RUN: llvm-lto2 run %t/m1.bc %t/m2.bc \
31+
; RUN: -o %t_baseline/result.o -save-temps \
32+
; RUN: -r %t/m1.bc,m1_f1,plx \
33+
; RUN: -r %t/m2.bc,m2_f1,plx
34+
; RUN: llvm-dis %t_baseline/result.o.1.3.import.bc -o - | FileCheck %s --check-prefix=NOPROF-1
35+
; RUN: llvm-dis %t_baseline/result.o.2.3.import.bc -o - | FileCheck %s --check-prefix=NOPROF-2
36+
;
37+
; NOPROF-1-NOT: m2_f1()
38+
; NOPROF-2-NOT: m1_f1()
39+
;
40+
; The run with workload definitions - same other options.
41+
;
42+
; RUN: echo '[ \
43+
; RUN: {"Guid": 6019442868614718803, "Counters": [1], "Callsites": [[{"Guid": 15593096274670919754, "Counters": [1]}]]}, \
44+
; RUN: {"Guid": 15593096274670919754, "Counters": [1], "Callsites": [[{"Guid": 6019442868614718803, "Counters": [1]}]]} \
45+
; RUN: ]' > %t_exp/ctxprof.json
46+
; RUN: llvm-ctxprof-util fromJSON --input %t_exp/ctxprof.json --output %t_exp/ctxprof.bitstream
47+
; RUN: llvm-lto2 run %t/m1.bc %t/m2.bc \
48+
; RUN: -o %t_exp/result.o -save-temps \
49+
; RUN: -thinlto-pgo-ctx-prof=%t_exp/ctxprof.bitstream \
50+
; RUN: -r %t/m1.bc,m1_f1,plx \
51+
; RUN: -r %t/m2.bc,m2_f1,plx
52+
; RUN: llvm-dis %t_exp/result.o.1.3.import.bc -o - | FileCheck %s --check-prefix=FIRST
53+
; RUN: llvm-dis %t_exp/result.o.2.3.import.bc -o - | FileCheck %s --check-prefix=SECOND
54+
;
55+
;
56+
; FIRST: m2_f1()
57+
; SECOND: m1_f1()
58+
;
59+
;--- m1.ll
60+
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
61+
target triple = "x86_64-pc-linux-gnu"
62+
63+
define dso_local void @m1_f1() {
64+
ret void
65+
}
66+
67+
;--- m2.ll
68+
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
69+
target triple = "x86_64-pc-linux-gnu"
70+
71+
define dso_local void @m2_f1() {
72+
ret void
73+
}

revert_patches.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,6 @@ contact: RonL
8686
---
8787
Reverts:
8888
1488fb415336 [PAC][AArch64] Lower ptrauth constants in code (#96879)
89-
c99bd3ce [ctx_prof] Extend `WorkloadImportsManager` to use the contextual profile (#98682)
9089
[ctx_prof] CtxProfAnalysis (#102084)
9190
aca01bff0 [ctx_prof] CtxProfAnalysis: populate module data (#102930)
9291
0c876a486eb [nfc][ctx_prof] Remove the need for `PassBuilder` to know about `UseCtxProfile` (#104492)

0 commit comments

Comments
 (0)