Skip to content

Commit df4235c

Browse files
committed
[PseudoProbe] Add PseudoProbeDescUpdatePass
Add PseudoProbeDescUpdatePass to update pseudo_probe_desc metadata for functions generated by optimization transformation. Those functions may contain pseudo probe discriminator so that llvm-profgen will try to get its function name based on GUID and then crash.
1 parent d15ada2 commit df4235c

File tree

5 files changed

+92
-9
lines changed

5 files changed

+92
-9
lines changed

llvm/include/llvm/Transforms/IPO/SampleProfileProbe.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,5 +140,13 @@ class PseudoProbeUpdatePass : public PassInfoMixin<PseudoProbeUpdatePass> {
140140
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
141141
};
142142

143+
// Update pseudo_probe_desc metadata for functions generated by optimization
144+
// transformation.
145+
class PseudoProbeDescUpdatePass
146+
: public PassInfoMixin<PseudoProbeDescUpdatePass> {
147+
public:
148+
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
149+
};
150+
143151
} // end namespace llvm
144152
#endif // LLVM_TRANSFORMS_IPO_SAMPLEPROFILEPROBE_H

llvm/lib/Passes/PassBuilderPipelines.cpp

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1581,9 +1581,12 @@ PassBuilder::buildPerModuleDefaultPipeline(OptimizationLevel Level,
15811581
// Now add the optimization pipeline.
15821582
MPM.addPass(buildModuleOptimizationPipeline(Level, LTOPhase));
15831583

1584-
if (PGOOpt && PGOOpt->PseudoProbeForProfiling &&
1585-
PGOOpt->Action == PGOOptions::SampleUse)
1586-
MPM.addPass(PseudoProbeUpdatePass());
1584+
if (PGOOpt && PGOOpt->PseudoProbeForProfiling) {
1585+
if (PGOOpt->Action == PGOOptions::SampleUse)
1586+
MPM.addPass(PseudoProbeUpdatePass());
1587+
else
1588+
MPM.addPass(PseudoProbeDescUpdatePass());
1589+
}
15871590

15881591
// Emit annotation remarks.
15891592
addAnnotationRemarksPass(MPM);
@@ -1651,9 +1654,12 @@ PassBuilder::buildThinLTOPreLinkDefaultPipeline(OptimizationLevel Level) {
16511654
if (RunPartialInlining)
16521655
MPM.addPass(PartialInlinerPass());
16531656

1654-
if (PGOOpt && PGOOpt->PseudoProbeForProfiling &&
1655-
PGOOpt->Action == PGOOptions::SampleUse)
1656-
MPM.addPass(PseudoProbeUpdatePass());
1657+
if (PGOOpt && PGOOpt->PseudoProbeForProfiling) {
1658+
if (PGOOpt->Action == PGOOptions::SampleUse)
1659+
MPM.addPass(PseudoProbeUpdatePass());
1660+
else
1661+
MPM.addPass(PseudoProbeDescUpdatePass());
1662+
}
16571663

16581664
// Handle Optimizer{Early,Last}EPCallbacks added by clang on PreLink. Actual
16591665
// optimization is going to be done in PostLink stage, but clang can't add

llvm/lib/Passes/PassRegistry.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ MODULE_PASS("print<inline-advisor>", InlineAdvisorAnalysisPrinterPass(dbgs()))
119119
MODULE_PASS("print<module-debuginfo>", ModuleDebugInfoPrinterPass(dbgs()))
120120
MODULE_PASS("pseudo-probe", SampleProfileProbePass(TM))
121121
MODULE_PASS("pseudo-probe-update", PseudoProbeUpdatePass())
122+
MODULE_PASS("pseudo-probe-desc-update", PseudoProbeDescUpdatePass())
122123
MODULE_PASS("recompute-globalsaa", RecomputeGlobalsAAPass())
123124
MODULE_PASS("rel-lookup-table-converter", RelLookupTableConverterPass())
124125
MODULE_PASS("rewrite-statepoints-for-gc", RewriteStatepointsForGC())

llvm/lib/Transforms/IPO/SampleProfileProbe.cpp

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -341,9 +341,7 @@ uint32_t SampleProfileProber::getCallsiteId(const Instruction *Call) const {
341341
return Iter == CallProbeIds.end() ? 0 : Iter->second;
342342
}
343343

344-
void SampleProfileProber::instrumentOneFunc(Function &F, TargetMachine *TM) {
345-
Module *M = F.getParent();
346-
MDBuilder MDB(F.getContext());
344+
static StringRef getFuncName(const Function &F) {
347345
// Since the GUID from probe desc and inline stack are computed separately, we
348346
// need to make sure their names are consistent, so here also use the name
349347
// from debug info.
@@ -353,6 +351,13 @@ void SampleProfileProber::instrumentOneFunc(Function &F, TargetMachine *TM) {
353351
if (FName.empty())
354352
FName = SP->getName();
355353
}
354+
return FName;
355+
}
356+
357+
void SampleProfileProber::instrumentOneFunc(Function &F, TargetMachine *TM) {
358+
Module *M = F.getParent();
359+
MDBuilder MDB(F.getContext());
360+
StringRef FName = getFuncName(F);
356361
uint64_t Guid = Function::getGUID(FName);
357362

358363
// Assign an artificial debug line to a probe that doesn't come with a real
@@ -513,3 +518,31 @@ PreservedAnalyses PseudoProbeUpdatePass::run(Module &M,
513518
}
514519
return PreservedAnalyses::none();
515520
}
521+
522+
PreservedAnalyses PseudoProbeDescUpdatePass::run(Module &M,
523+
ModuleAnalysisManager &AM) {
524+
if (NamedMDNode *FuncInfo = M.getNamedMetadata(PseudoProbeDescMetadataName)) {
525+
DenseSet<uint64_t> GuidSet;
526+
for (const auto *Operand : FuncInfo->operands()) {
527+
const auto *MD = cast<MDNode>(Operand);
528+
auto *GUID = mdconst::dyn_extract<ConstantInt>(MD->getOperand(0));
529+
GuidSet.insert(GUID->getZExtValue());
530+
}
531+
532+
MDBuilder MDB(M.getContext());
533+
for (Function &F : M) {
534+
if (F.isDeclaration())
535+
continue;
536+
StringRef FName = getFuncName(F);
537+
uint64_t Guid = Function::getGUID(FName);
538+
if (GuidSet.insert(Guid).second) {
539+
// Set those function's hash to 0 since it may vary depending on IR
540+
// input to optimization transformation.
541+
auto *MD = MDB.createPseudoProbeDesc(Guid, 0, FName);
542+
FuncInfo->addOperand(MD);
543+
LLVM_DEBUG(dbgs() << "New fixup pseudo_probe_desc MD: " << *MD << "\n");
544+
}
545+
}
546+
}
547+
return PreservedAnalyses::all();
548+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
; RUN: opt < %s -passes='pseudo-probe-desc-update' -S | FileCheck %s
2+
3+
; CHECK: !llvm.pseudo_probe_desc = !{!0, !1, !2, !3, !4, !5}
4+
; CHECK: !0 = !{i64 -2012135647395072713, i64 4294967295, !"bar"}
5+
; CHECK-NEXT: !1 = !{i64 9204417991963109735, i64 72617220756, !"work"}
6+
; CHECK-NEXT: !2 = !{i64 6699318081062747564, i64 844700110938769, !"foo"}
7+
; CHECK-NEXT: !3 = !{i64 -2624081020897602054, i64 281563657672557, !"main"}
8+
; CHECK-NEXT: !4 = !{i64 6028998432455395745, i64 0, !"extract1"}
9+
; CHECK-NEXT: !5 = !{i64 -8314581669044049530, i64 0, !"_Zextract2v"}
10+
11+
target triple = "x86_64-unknown-linux-gnu"
12+
13+
define void @extract1() !dbg !1 {
14+
entry:
15+
ret void
16+
}
17+
18+
define void @extract2() !dbg !2 {
19+
entry:
20+
ret void
21+
}
22+
23+
!llvm.pseudo_probe_desc = !{!4, !5, !6, !7}
24+
!llvm.module.flags = !{!8, !9}
25+
26+
!0 = distinct !DICompileUnit(language: DW_LANG_C11, file: !3, emissionKind: FullDebug, splitDebugInlining: false, debugInfoForProfiling: true)
27+
!1 = distinct !DISubprogram(name: "extract1", unit: !0)
28+
!2 = distinct !DISubprogram(name: "extract2", linkageName: "_Zextract2v", unit: !0)
29+
!3 = !DIFile(filename: "foo.c", directory: "/home/test")
30+
!4 = !{i64 -2012135647395072713, i64 4294967295, !"bar"}
31+
!5 = !{i64 9204417991963109735, i64 72617220756, !"work"}
32+
!6 = !{i64 6699318081062747564, i64 844700110938769, !"foo"}
33+
!7 = !{i64 -2624081020897602054, i64 281563657672557, !"main"}
34+
!8 = !{i32 7, !"Dwarf Version", i32 5}
35+
!9 = !{i32 2, !"Debug Info Version", i32 3}

0 commit comments

Comments
 (0)