7272#include " llvm/Passes/PassBuilder.h"
7373#include " llvm/Passes/PassPlugin.h"
7474#include " llvm/Passes/StandardInstrumentations.h"
75+ #include " llvm/ProfileData/InstrProfReader.h"
7576#include " llvm/Remarks/Remark.h"
7677#include " llvm/Remarks/RemarkStreamer.h"
7778#include " llvm/Support/CommandLine.h"
@@ -214,8 +215,57 @@ static void align(llvm::Module *Module) {
214215 }
215216}
216217
218+ static std::unique_ptr<llvm::IndexedInstrProfReader>
219+ getProfileReader (const Twine &ProfileName, llvm::vfs::FileSystem &FS,
220+ DiagnosticEngine &Diags) {
221+ auto ReaderOrErr = llvm::IndexedInstrProfReader::create (ProfileName, FS);
222+ if (auto E = ReaderOrErr.takeError ()) {
223+ llvm::handleAllErrors (std::move (E), [&](const llvm::ErrorInfoBase &EI) {
224+ Diags.diagnose (SourceLoc (), diag::ir_profile_read_failed,
225+ ProfileName.str (), EI.message ());
226+ });
227+ return nullptr ;
228+ }
229+ return std::move (*ReaderOrErr);
230+ }
231+
232+ static std::optional<PGOOptions> buildIRUseOptions (const IRGenOptions &Opts,
233+ DiagnosticEngine &Diags) {
234+ if (Opts.UseIRProfile .empty ())
235+ return std::nullopt ;
236+
237+ auto FS = llvm::vfs::getRealFileSystem ();
238+ std::unique_ptr<llvm::IndexedInstrProfReader> Reader =
239+ getProfileReader (Opts.UseIRProfile .c_str (), *FS, Diags);
240+ if (!Reader)
241+ return std::nullopt ;
242+
243+ // Currently memprof profiles are only added at the IR level. Mark the
244+ // profile type as IR in that case as well and the subsequent matching
245+ // needs to detect which is available (might be one or both).
246+ const bool IsIR = Reader->isIRLevelProfile () || Reader->hasMemoryProfile ();
247+ if (!IsIR) {
248+ Diags.diagnose (SourceLoc (), diag::ir_profile_invalid,
249+ Opts.UseIRProfile .c_str ());
250+ return std::nullopt ;
251+ }
252+
253+ const bool IsCS = Reader->hasCSIRLevelProfile ();
254+ return PGOOptions (
255+ /* ProfileFile=*/ Opts.UseIRProfile ,
256+ /* CSProfileGenFile=*/ " " ,
257+ /* ProfileRemappingFile=*/ " " ,
258+ /* MemoryProfile=*/ " " ,
259+ /* FS=*/ FS,
260+ /* Action=*/ PGOOptions::IRUse,
261+ /* CSPGOAction=*/ IsCS ? PGOOptions::CSIRUse : PGOOptions::NoCSAction,
262+ /* ColdType=*/ PGOOptions::ColdFuncOpt::Default,
263+ /* DebugInfoForProfiling=*/ Opts.DebugInfoForProfiling );
264+ }
265+
217266static void populatePGOOptions (std::optional<PGOOptions> &Out,
218- const IRGenOptions &Opts) {
267+ const IRGenOptions &Opts,
268+ DiagnosticEngine &Diags) {
219269 if (!Opts.UseSampleProfile .empty ()) {
220270 Out = PGOOptions (
221271 /* ProfileFile=*/ Opts.UseSampleProfile ,
@@ -234,31 +284,34 @@ static void populatePGOOptions(std::optional<PGOOptions> &Out,
234284 if (Opts.EnableCSIRProfileGen ) {
235285 const bool hasUse = !Opts.UseIRProfile .empty ();
236286 Out = PGOOptions (
237- /* ProfileFile=*/ Opts.UseIRProfile ,
238- /* CSProfileGenFile=*/ Opts.InstrProfileOutput ,
239- /* ProfileRemappingFile=*/ " " ,
240- /* MemoryProfile=*/ " " ,
241- /* FS=*/ llvm::vfs::getRealFileSystem (),
242- /* Action=*/ hasUse ? PGOOptions::IRUse : PGOOptions::NoAction,
243- /* CSPGOAction=*/ PGOOptions::CSIRInstr,
244- /* ColdType=*/ PGOOptions::ColdFuncOpt::Default,
245- /* DebugInfoForProfiling=*/ Opts.DebugInfoForProfiling
246- );
287+ /* ProfileFile=*/ Opts.UseIRProfile ,
288+ /* CSProfileGenFile=*/ Opts.InstrProfileOutput ,
289+ /* ProfileRemappingFile=*/ " " ,
290+ /* MemoryProfile=*/ " " ,
291+ /* FS=*/ llvm::vfs::getRealFileSystem (),
292+ /* Action=*/ hasUse ? PGOOptions::IRUse : PGOOptions::NoAction,
293+ /* CSPGOAction=*/ PGOOptions::CSIRInstr,
294+ /* ColdType=*/ PGOOptions::ColdFuncOpt::Default,
295+ /* DebugInfoForProfiling=*/ Opts.DebugInfoForProfiling );
247296 return ;
248297 }
249298
250299 if (Opts.EnableIRProfileGen ) {
251300 Out = PGOOptions (
252- /* ProfileFile=*/ Opts.InstrProfileOutput ,
253- /* CSProfileGenFile=*/ " " ,
254- /* ProfileRemappingFile=*/ " " ,
255- /* MemoryProfile=*/ " " ,
256- /* FS=*/ llvm::vfs::getRealFileSystem (),
257- /* Action=*/ PGOOptions::IRInstr,
258- /* CSPGOAction=*/ PGOOptions::NoCSAction,
259- /* ColdType=*/ PGOOptions::ColdFuncOpt::Default,
260- /* DebugInfoForProfiling=*/ Opts.DebugInfoForProfiling
261- );
301+ /* ProfileFile=*/ Opts.InstrProfileOutput ,
302+ /* CSProfileGenFile=*/ " " ,
303+ /* ProfileRemappingFile=*/ " " ,
304+ /* MemoryProfile=*/ " " ,
305+ /* FS=*/ llvm::vfs::getRealFileSystem (),
306+ /* Action=*/ PGOOptions::IRInstr,
307+ /* CSPGOAction=*/ PGOOptions::NoCSAction,
308+ /* ColdType=*/ PGOOptions::ColdFuncOpt::Default,
309+ /* DebugInfoForProfiling=*/ Opts.DebugInfoForProfiling );
310+ return ;
311+ }
312+
313+ if (auto IRUseOptions = buildIRUseOptions (Opts, Diags)) {
314+ Out = *IRUseOptions;
262315 return ;
263316 }
264317
@@ -297,7 +350,7 @@ void swift::performLLVMOptimizations(const IRGenOptions &Opts,
297350 llvm::TargetMachine *TargetMachine,
298351 llvm::raw_pwrite_stream *out) {
299352 std::optional<PGOOptions> PGOOpt;
300- populatePGOOptions (PGOOpt, Opts);
353+ populatePGOOptions (PGOOpt, Opts, Diags );
301354
302355 PipelineTuningOptions PTO;
303356
0 commit comments