Skip to content

Commit 86601fc

Browse files
authored
Merge pull request #76532 from kavon/samplepgo
Add support for SamplePGO
2 parents f4df1a8 + 19e593b commit 86601fc

File tree

8 files changed

+123
-2
lines changed

8 files changed

+123
-2
lines changed

include/swift/AST/IRGenOptions.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,13 @@ class IRGenOptions {
500500
/// Path to the profdata file to be used for PGO, or the empty string.
501501
std::string UseProfile = "";
502502

503+
/// Path to the data file to be used for sampling-based PGO,
504+
/// or the empty string.
505+
std::string UseSampleProfile = "";
506+
507+
/// Controls whether DWARF discriminators are added to the IR.
508+
unsigned DebugInfoForProfiling : 1;
509+
503510
/// List of backend command-line options for -embed-bitcode.
504511
std::vector<uint8_t> CmdArgs;
505512

@@ -584,7 +591,8 @@ class IRGenOptions {
584591
ColocateTypeDescriptors(true), UseRelativeProtocolWitnessTables(false),
585592
UseFragileResilientProtocolWitnesses(false), EnableHotColdSplit(false),
586593
EmitAsyncFramePushPopMetadata(false), EmitYieldOnce2AsYieldOnce(true),
587-
AsyncFramePointerAll(false), UseProfilingMarkerThunks(false), CmdArgs(),
594+
AsyncFramePointerAll(false), UseProfilingMarkerThunks(false),
595+
DebugInfoForProfiling(false), CmdArgs(),
588596
SanitizeCoverage(llvm::SanitizerCoverageOptions()),
589597
TypeInfoFilter(TypeInfoDumpFilter::All),
590598
PlatformCCallingConvention(llvm::CallingConv::C), UseCASBackend(false),

include/swift/Option/Options.td

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1479,6 +1479,10 @@ def profile_generate : Flag<["-"], "profile-generate">,
14791479
Flags<[FrontendOption, NoInteractiveOption]>,
14801480
HelpText<"Generate instrumented code to collect execution counts">;
14811481

1482+
def debug_info_for_profiling : Flag<["-"], "debug-info-for-profiling">,
1483+
Flags<[FrontendOption, NoInteractiveOption]>,
1484+
HelpText<"Emit extra debug info (DWARF discriminators) to make sampling-based profiling more accurate">;
1485+
14821486
def profile_use : CommaJoined<["-"], "profile-use=">,
14831487
Flags<[FrontendOption, NoInteractiveOption, ArgumentIsPath]>,
14841488
MetaVarName<"<profdata>">,
@@ -1488,6 +1492,11 @@ def profile_coverage_mapping : Flag<["-"], "profile-coverage-mapping">,
14881492
Flags<[FrontendOption, NoInteractiveOption]>,
14891493
HelpText<"Generate coverage data for use with profiled execution counts">;
14901494

1495+
def profile_sample_use : CommaJoined<["-"], "profile-sample-use=">,
1496+
Flags<[FrontendOption, NoInteractiveOption, ArgumentIsPath]>,
1497+
MetaVarName<"<profile data>">,
1498+
HelpText<"Supply sampling-based profiling data from llvm-profdata to enable profile-guided optimization">;
1499+
14911500
def embed_bitcode : Flag<["-"], "embed-bitcode">,
14921501
Flags<[FrontendOption, NoInteractiveOption]>,
14931502
HelpText<"Embed LLVM IR bitcode as data">;

lib/Frontend/CompilerInvocation.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3177,6 +3177,11 @@ static bool ParseIRGenArgs(IRGenOptions &Opts, ArgList &Args,
31773177
const Arg *ProfileUse = Args.getLastArg(OPT_profile_use);
31783178
Opts.UseProfile = ProfileUse ? ProfileUse->getValue() : "";
31793179

3180+
const Arg *ProfileSampleUse = Args.getLastArg(OPT_profile_sample_use);
3181+
Opts.UseSampleProfile = ProfileSampleUse ? ProfileSampleUse->getValue() : "";
3182+
3183+
Opts.DebugInfoForProfiling |= Args.hasArg(OPT_debug_info_for_profiling);
3184+
31803185
Opts.PrintInlineTree |= Args.hasArg(OPT_print_llvm_inline_tree);
31813186
// Always producing all outputs when caching is enabled.
31823187
Opts.AlwaysCompile |= Args.hasArg(OPT_always_compile_output_files) ||

lib/IRGen/IRGen.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,11 +200,45 @@ static void align(llvm::Module *Module) {
200200
}
201201
}
202202

203+
static void populatePGOOptions(std::optional<PGOOptions> &Out,
204+
const IRGenOptions &Opts) {
205+
if (!Opts.UseSampleProfile.empty()) {
206+
Out = PGOOptions(
207+
/*ProfileFile=*/ Opts.UseSampleProfile,
208+
/*CSProfileGenFile=*/ "",
209+
/*ProfileRemappingFile=*/ "",
210+
/*MemoryProfile=*/ "",
211+
/*FS=*/ llvm::vfs::getRealFileSystem(), // TODO: is this fine?
212+
/*Action=*/ PGOOptions::SampleUse,
213+
/*CSPGOAction=*/ PGOOptions::NoCSAction,
214+
/*ColdType=*/ PGOOptions::ColdFuncOpt::Default,
215+
/*DebugInfoForProfiling=*/ Opts.DebugInfoForProfiling
216+
);
217+
return;
218+
}
219+
220+
if (Opts.DebugInfoForProfiling) {
221+
Out = PGOOptions(
222+
/*ProfileFile=*/ "",
223+
/*CSProfileGenFile=*/ "",
224+
/*ProfileRemappingFile=*/ "",
225+
/*MemoryProfile=*/ "",
226+
/*FS=*/ nullptr,
227+
/*Action=*/ PGOOptions::NoAction,
228+
/*CSPGOAction=*/ PGOOptions::NoCSAction,
229+
/*ColdType=*/ PGOOptions::ColdFuncOpt::Default,
230+
/*DebugInfoForProfiling=*/ true
231+
);
232+
return;
233+
}
234+
}
235+
203236
void swift::performLLVMOptimizations(const IRGenOptions &Opts,
204237
llvm::Module *Module,
205238
llvm::TargetMachine *TargetMachine,
206239
llvm::raw_pwrite_stream *out) {
207240
std::optional<PGOOptions> PGOOpt;
241+
populatePGOOptions(PGOOpt, Opts);
208242

209243
PipelineTuningOptions PTO;
210244

lib/IRGen/IRGenDebugInfo.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -839,6 +839,7 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
839839
TheCU->getProducer(), true, StringRef(), 0,
840840
RemappedASTFile, llvm::DICompileUnit::FullDebug,
841841
Signature);
842+
// NOTE: not setting DebugInfoForProfiling here
842843
DIB.finalize();
843844
}
844845
}
@@ -2519,7 +2520,7 @@ IRGenDebugInfoImpl::IRGenDebugInfoImpl(const IRGenOptions &Opts,
25192520
? llvm::DICompileUnit::FullDebug
25202521
: llvm::DICompileUnit::LineTablesOnly,
25212522
/* DWOId */ 0, /* SplitDebugInlining */ true,
2522-
/* DebugInfoForProfiling */ false,
2523+
/* DebugInfoForProfiling */ Opts.DebugInfoForProfiling,
25232524
llvm::DICompileUnit::DebugNameTableKind::Default,
25242525
/* RangesBaseAddress */ false, DebugPrefixMap.remapPath(Sysroot), SDK);
25252526

lib/IRGen/IRGenSIL.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1944,6 +1944,11 @@ IRGenSILFunction::IRGenSILFunction(IRGenModule &IGM, SILFunction *f)
19441944
// LLVM doesn't have an attribute for -O
19451945
}
19461946

1947+
if (!IGM.IRGen.Opts.UseSampleProfile.empty()) {
1948+
// This attribute helps in LTO situations: https://reviews.llvm.org/D79959
1949+
CurFn->addFnAttr("use-sample-profile");
1950+
}
1951+
19471952
// Emit the thunk that calls the previous implementation if this is a dynamic
19481953
// replacement.
19491954
if (f->getDynamicallyReplacedFunction()) {
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// RUN: %target-swift-frontend %s -emit-ir -g -debug-info-for-profiling -o - | %FileCheck %s
2+
3+
// CHECK: distinct !DICompileUnit(language: DW_LANG_Swift
4+
// CHECK-SAME: debugInfoForProfiling: true
5+
6+
// CHECK: !DILexicalBlockFile({{.*}} discriminator: 2)
7+
8+
public func lobster(_ n: Int) -> Bool {
9+
guard n > 0 else { fatalError("too cold!") }
10+
11+
if n > 100 {
12+
print("warm but ok")
13+
}
14+
15+
return n < 120
16+
}

test/Profiler/samplepgo.swift

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: split-file %s %t
3+
4+
// ----------------------------------------
5+
// Test the -profile-sample-use= flag using bogus data, to ensure it's actually
6+
// reaching LLVM in the expected way.
7+
8+
// RUN: %target-swift-frontend %t/program.swift -module-name test -emit-ir \
9+
// RUN: -O -profile-sample-use=%t/profile.txt -o %t/has-data.ll
10+
11+
// RUN: %FileCheck %s < %t/has-data.ll
12+
13+
// CHECK: define{{.*}} @"$s4test8anythingyyF"() #[[ATTRID:[0-9]+]]
14+
// CHECK: attributes #[[ATTRID]] = {{.*}} "use-sample-profile"
15+
16+
// CHECK-LABEL: !llvm.module.flags
17+
// CHECK: !{!"ProfileFormat", !"SampleProfile"}
18+
// CHECK: !{!"TotalCount", i64 2001}
19+
20+
// ----------------------------------------
21+
// Now, test cases where there there should not be any profile metadata,
22+
// such as when no data is provided
23+
24+
// RUN: %target-swift-frontend %t/program.swift -module-name test -emit-ir \
25+
// RUN: -O -o %t/no-data.ll
26+
27+
// RUN: %FileCheck --check-prefix CHECK-NODATA %s < %t/no-data.ll
28+
29+
30+
// CHECK-NODATA: define{{.*}} @"$s4test8anythingyyF"() #[[ATTRID:[0-9]+]]
31+
// CHECK-NODATA-NOT: attributes #[[ATTRID]] = {{.*}} "use-sample-profile"
32+
33+
// CHECK-NODATA-LABEL: !llvm.module.flags
34+
// CHECK-NODATA-NOT: Profile
35+
36+
37+
//--- program.swift
38+
public func anything() {}
39+
40+
41+
//--- profile.txt
42+
bar:100:100
43+
1: 2001

0 commit comments

Comments
 (0)