Skip to content

Commit 2b01714

Browse files
committed
PGO: new -profile-sample-use= frontend flag
This is meant to match clang's `-fprofile-sample-use=` and accepts a file with the same format. rdar://135443278
1 parent a7336e8 commit 2b01714

File tree

6 files changed

+79
-0
lines changed

6 files changed

+79
-0
lines changed

include/swift/AST/IRGenOptions.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,10 @@ 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+
503507
/// List of backend command-line options for -embed-bitcode.
504508
std::vector<uint8_t> CmdArgs;
505509

include/swift/Option/Options.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1486,6 +1486,11 @@ def profile_coverage_mapping : Flag<["-"], "profile-coverage-mapping">,
14861486
Flags<[FrontendOption, NoInteractiveOption]>,
14871487
HelpText<"Generate coverage data for use with profiled execution counts">;
14881488

1489+
def profile_sample_use : CommaJoined<["-"], "profile-sample-use=">,
1490+
Flags<[FrontendOption, NoInteractiveOption, ArgumentIsPath]>,
1491+
MetaVarName<"<profile data>">,
1492+
HelpText<"Supply sampling-based profiling data from llvm-profdata to enable profile-guided optimization">;
1493+
14891494
def embed_bitcode : Flag<["-"], "embed-bitcode">,
14901495
Flags<[FrontendOption, NoInteractiveOption]>,
14911496
HelpText<"Embed LLVM IR bitcode as data">;

lib/Frontend/CompilerInvocation.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3177,6 +3177,9 @@ 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+
31803183
Opts.PrintInlineTree |= Args.hasArg(OPT_print_llvm_inline_tree);
31813184
// Always producing all outputs when caching is enabled.
31823185
Opts.AlwaysCompile |= Args.hasArg(OPT_always_compile_output_files) ||

lib/IRGen/IRGen.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,11 +200,30 @@ 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=*/ false
216+
);
217+
return;
218+
}
219+
}
220+
203221
void swift::performLLVMOptimizations(const IRGenOptions &Opts,
204222
llvm::Module *Module,
205223
llvm::TargetMachine *TargetMachine,
206224
llvm::raw_pwrite_stream *out) {
207225
std::optional<PGOOptions> PGOOpt;
226+
populatePGOOptions(PGOOpt, Opts);
208227

209228
PipelineTuningOptions PTO;
210229

lib/IRGen/IRGenSIL.cpp

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

1942+
if (!IGM.IRGen.Opts.UseSampleProfile.empty()) {
1943+
// This attribute helps in LTO situations: https://reviews.llvm.org/D79959
1944+
CurFn->addFnAttr("use-sample-profile");
1945+
}
1946+
19421947
// Emit the thunk that calls the previous implementation if this is a dynamic
19431948
// replacement.
19441949
if (f->getDynamicallyReplacedFunction()) {

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)