| 1 | //===- NewPMDriver.cpp - Driver for opt with new PM -----------------------===// |
| 2 | // |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | // See https://llvm.org/LICENSE.txt for license information. |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | /// \file |
| 9 | /// |
| 10 | /// This file is just a split of the code that logically belongs in opt.cpp but |
| 11 | /// that includes the new pass manager headers. |
| 12 | /// |
| 13 | //===----------------------------------------------------------------------===// |
| 14 | |
| 15 | #include "NewPMDriver.h" |
| 16 | #include "llvm/ADT/SmallVector.h" |
| 17 | #include "llvm/ADT/Statistic.h" |
| 18 | #include "llvm/ADT/StringRef.h" |
| 19 | #include "llvm/Analysis/AliasAnalysis.h" |
| 20 | #include "llvm/Analysis/CGSCCPassManager.h" |
| 21 | #include "llvm/Analysis/RuntimeLibcallInfo.h" |
| 22 | #include "llvm/Analysis/TargetLibraryInfo.h" |
| 23 | #include "llvm/Bitcode/BitcodeWriterPass.h" |
| 24 | #include "llvm/CodeGen/LibcallLoweringInfo.h" |
| 25 | #include "llvm/Config/llvm-config.h" |
| 26 | #include "llvm/IR/Dominators.h" |
| 27 | #include "llvm/IR/LLVMContext.h" |
| 28 | #include "llvm/IR/Module.h" |
| 29 | #include "llvm/IR/PassManager.h" |
| 30 | #include "llvm/IR/Verifier.h" |
| 31 | #include "llvm/IRPrinter/IRPrintingPasses.h" |
| 32 | #include "llvm/Passes/PassBuilder.h" |
| 33 | #include "llvm/Passes/StandardInstrumentations.h" |
| 34 | #include "llvm/Plugins/PassPlugin.h" |
| 35 | #include "llvm/Support/ErrorHandling.h" |
| 36 | #include "llvm/Support/Timer.h" |
| 37 | #include "llvm/Support/ToolOutputFile.h" |
| 38 | #include "llvm/Support/VirtualFileSystem.h" |
| 39 | #include "llvm/Support/raw_ostream.h" |
| 40 | #include "llvm/Target/TargetMachine.h" |
| 41 | #include "llvm/Transforms/IPO/ThinLTOBitcodeWriter.h" |
| 42 | #include "llvm/Transforms/Instrumentation/AddressSanitizer.h" |
| 43 | #include "llvm/Transforms/Scalar/LoopPassManager.h" |
| 44 | #include "llvm/Transforms/Utils/Debugify.h" |
| 45 | #include "llvm/Transforms/Utils/ProfileVerify.h" |
| 46 | |
| 47 | using namespace llvm; |
| 48 | using namespace opt_tool; |
| 49 | |
| 50 | cl::opt<bool> llvm::DebugifyEach( |
| 51 | "debugify-each" , |
| 52 | cl::desc("Start each pass with debugify and end it with check-debugify" )); |
| 53 | |
| 54 | cl::opt<std::string> llvm::DebugifyExport( |
| 55 | "debugify-export" , |
| 56 | cl::desc("Export per-pass debugify statistics to this file" ), |
| 57 | cl::value_desc("filename" )); |
| 58 | |
| 59 | cl::opt<bool> llvm::VerifyEachDebugInfoPreserve( |
| 60 | "verify-each-debuginfo-preserve" , |
| 61 | cl::desc("Start each pass with collecting and end it with checking of " |
| 62 | "debug info preservation." )); |
| 63 | |
| 64 | cl::opt<std::string> llvm::VerifyDIPreserveExport( |
| 65 | "verify-di-preserve-export" , |
| 66 | cl::desc("Export debug info preservation failures into " |
| 67 | "specified (JSON) file (should be abs path as we use" |
| 68 | " append mode to insert new JSON objects)" ), |
| 69 | cl::value_desc("filename" ), cl::init(Val: "" )); |
| 70 | |
| 71 | static cl::opt<bool> EnableLoopFusion("enable-loopfusion" , cl::init(Val: false), |
| 72 | cl::Hidden, |
| 73 | cl::desc("Enable the LoopFuse Pass" )); |
| 74 | |
| 75 | enum class DebugLogging { None, Normal, Verbose, Quiet }; |
| 76 | |
| 77 | static cl::opt<DebugLogging> DebugPM( |
| 78 | "debug-pass-manager" , cl::Hidden, cl::ValueOptional, |
| 79 | cl::desc("Print pass management debugging information" ), |
| 80 | cl::init(Val: DebugLogging::None), |
| 81 | cl::values( |
| 82 | clEnumValN(DebugLogging::Normal, "" , "" ), |
| 83 | clEnumValN(DebugLogging::Quiet, "quiet" , |
| 84 | "Skip printing info about analyses" ), |
| 85 | clEnumValN( |
| 86 | DebugLogging::Verbose, "verbose" , |
| 87 | "Print extra information about adaptors and pass managers" ))); |
| 88 | |
| 89 | // This flag specifies a textual description of the alias analysis pipeline to |
| 90 | // use when querying for aliasing information. It only works in concert with |
| 91 | // the "passes" flag above. |
| 92 | static cl::opt<std::string> |
| 93 | AAPipeline("aa-pipeline" , |
| 94 | cl::desc("A textual description of the alias analysis " |
| 95 | "pipeline for handling managed aliasing queries" ), |
| 96 | cl::Hidden, cl::init(Val: "default" )); |
| 97 | |
| 98 | /// {{@ These options accept textual pipeline descriptions which will be |
| 99 | /// inserted into default pipelines at the respective extension points |
| 100 | static cl::opt<std::string> PeepholeEPPipeline( |
| 101 | "passes-ep-peephole" , |
| 102 | cl::desc("A textual description of the function pass pipeline inserted at " |
| 103 | "the Peephole extension points into default pipelines" ), |
| 104 | cl::Hidden); |
| 105 | static cl::opt<std::string> LateLoopOptimizationsEPPipeline( |
| 106 | "passes-ep-late-loop-optimizations" , |
| 107 | cl::desc( |
| 108 | "A textual description of the loop pass pipeline inserted at " |
| 109 | "the LateLoopOptimizations extension point into default pipelines" ), |
| 110 | cl::Hidden); |
| 111 | static cl::opt<std::string> LoopOptimizerEndEPPipeline( |
| 112 | "passes-ep-loop-optimizer-end" , |
| 113 | cl::desc("A textual description of the loop pass pipeline inserted at " |
| 114 | "the LoopOptimizerEnd extension point into default pipelines" ), |
| 115 | cl::Hidden); |
| 116 | static cl::opt<std::string> ScalarOptimizerLateEPPipeline( |
| 117 | "passes-ep-scalar-optimizer-late" , |
| 118 | cl::desc("A textual description of the function pass pipeline inserted at " |
| 119 | "the ScalarOptimizerLate extension point into default pipelines" ), |
| 120 | cl::Hidden); |
| 121 | static cl::opt<std::string> CGSCCOptimizerLateEPPipeline( |
| 122 | "passes-ep-cgscc-optimizer-late" , |
| 123 | cl::desc("A textual description of the cgscc pass pipeline inserted at " |
| 124 | "the CGSCCOptimizerLate extension point into default pipelines" ), |
| 125 | cl::Hidden); |
| 126 | static cl::opt<std::string> VectorizerStartEPPipeline( |
| 127 | "passes-ep-vectorizer-start" , |
| 128 | cl::desc("A textual description of the function pass pipeline inserted at " |
| 129 | "the VectorizerStart extension point into default pipelines" ), |
| 130 | cl::Hidden); |
| 131 | static cl::opt<std::string> VectorizerEndEPPipeline( |
| 132 | "passes-ep-vectorizer-end" , |
| 133 | cl::desc("A textual description of the function pass pipeline inserted at " |
| 134 | "the VectorizerEnd extension point into default pipelines" ), |
| 135 | cl::Hidden); |
| 136 | static cl::opt<std::string> PipelineStartEPPipeline( |
| 137 | "passes-ep-pipeline-start" , |
| 138 | cl::desc("A textual description of the module pass pipeline inserted at " |
| 139 | "the PipelineStart extension point into default pipelines" ), |
| 140 | cl::Hidden); |
| 141 | static cl::opt<std::string> PipelineEarlySimplificationEPPipeline( |
| 142 | "passes-ep-pipeline-early-simplification" , |
| 143 | cl::desc("A textual description of the module pass pipeline inserted at " |
| 144 | "the EarlySimplification extension point into default pipelines" ), |
| 145 | cl::Hidden); |
| 146 | static cl::opt<std::string> OptimizerEarlyEPPipeline( |
| 147 | "passes-ep-optimizer-early" , |
| 148 | cl::desc("A textual description of the module pass pipeline inserted at " |
| 149 | "the OptimizerEarly extension point into default pipelines" ), |
| 150 | cl::Hidden); |
| 151 | static cl::opt<std::string> OptimizerLastEPPipeline( |
| 152 | "passes-ep-optimizer-last" , |
| 153 | cl::desc("A textual description of the module pass pipeline inserted at " |
| 154 | "the OptimizerLast extension point into default pipelines" ), |
| 155 | cl::Hidden); |
| 156 | static cl::opt<std::string> FullLinkTimeOptimizationEarlyEPPipeline( |
| 157 | "passes-ep-full-link-time-optimization-early" , |
| 158 | cl::desc("A textual description of the module pass pipeline inserted at " |
| 159 | "the FullLinkTimeOptimizationEarly extension point into default " |
| 160 | "pipelines" ), |
| 161 | cl::Hidden); |
| 162 | static cl::opt<std::string> FullLinkTimeOptimizationLastEPPipeline( |
| 163 | "passes-ep-full-link-time-optimization-last" , |
| 164 | cl::desc("A textual description of the module pass pipeline inserted at " |
| 165 | "the FullLinkTimeOptimizationLast extension point into default " |
| 166 | "pipelines" ), |
| 167 | cl::Hidden); |
| 168 | /// @}} |
| 169 | |
| 170 | static cl::opt<bool> DisablePipelineVerification( |
| 171 | "disable-pipeline-verification" , |
| 172 | cl::desc("Only has an effect when specified with -print-pipeline-passes. " |
| 173 | "Disables verifying that the textual pipeline generated by " |
| 174 | "-print-pipeline-passes can be used to create a pipeline." ), |
| 175 | cl::Hidden); |
| 176 | |
| 177 | |
| 178 | static cl::opt<PGOKind> |
| 179 | PGOKindFlag("pgo-kind" , cl::init(Val: NoPGO), cl::Hidden, |
| 180 | cl::desc("The kind of profile guided optimization" ), |
| 181 | cl::values(clEnumValN(NoPGO, "nopgo" , "Do not use PGO." ), |
| 182 | clEnumValN(InstrGen, "pgo-instr-gen-pipeline" , |
| 183 | "Instrument the IR to generate profile." ), |
| 184 | clEnumValN(InstrUse, "pgo-instr-use-pipeline" , |
| 185 | "Use instrumented profile to guide PGO." ), |
| 186 | clEnumValN(SampleUse, "pgo-sample-use-pipeline" , |
| 187 | "Use sampled profile to guide PGO." ))); |
| 188 | static cl::opt<std::string> ProfileFile("profile-file" , |
| 189 | cl::desc("Path to the profile." ), cl::Hidden); |
| 190 | static cl::opt<std::string> |
| 191 | MemoryProfileFile("memory-profile-file" , |
| 192 | cl::desc("Path to the memory profile." ), cl::Hidden); |
| 193 | |
| 194 | static cl::opt<CSPGOKind> CSPGOKindFlag( |
| 195 | "cspgo-kind" , cl::init(Val: NoCSPGO), cl::Hidden, |
| 196 | cl::desc("The kind of context sensitive profile guided optimization" ), |
| 197 | cl::values( |
| 198 | clEnumValN(NoCSPGO, "nocspgo" , "Do not use CSPGO." ), |
| 199 | clEnumValN( |
| 200 | CSInstrGen, "cspgo-instr-gen-pipeline" , |
| 201 | "Instrument (context sensitive) the IR to generate profile." ), |
| 202 | clEnumValN( |
| 203 | CSInstrUse, "cspgo-instr-use-pipeline" , |
| 204 | "Use instrumented (context sensitive) profile to guide PGO." ))); |
| 205 | |
| 206 | static cl::opt<std::string> CSProfileGenFile( |
| 207 | "cs-profilegen-file" , |
| 208 | cl::desc("Path to the instrumented context sensitive profile." ), |
| 209 | cl::Hidden); |
| 210 | |
| 211 | static cl::opt<std::string> |
| 212 | ProfileRemappingFile("profile-remapping-file" , |
| 213 | cl::desc("Path to the profile remapping file." ), |
| 214 | cl::Hidden); |
| 215 | |
| 216 | static cl::opt<PGOOptions::ColdFuncOpt> PGOColdFuncAttr( |
| 217 | "pgo-cold-func-opt" , cl::init(Val: PGOOptions::ColdFuncOpt::Default), cl::Hidden, |
| 218 | cl::desc( |
| 219 | "Function attribute to apply to cold functions as determined by PGO" ), |
| 220 | cl::values(clEnumValN(PGOOptions::ColdFuncOpt::Default, "default" , |
| 221 | "Default (no attribute)" ), |
| 222 | clEnumValN(PGOOptions::ColdFuncOpt::OptSize, "optsize" , |
| 223 | "Mark cold functions with optsize." ), |
| 224 | clEnumValN(PGOOptions::ColdFuncOpt::MinSize, "minsize" , |
| 225 | "Mark cold functions with minsize." ), |
| 226 | clEnumValN(PGOOptions::ColdFuncOpt::OptNone, "optnone" , |
| 227 | "Mark cold functions with optnone." ))); |
| 228 | |
| 229 | static cl::opt<bool> DebugInfoForProfiling( |
| 230 | "debug-info-for-profiling" , cl::init(Val: false), cl::Hidden, |
| 231 | cl::desc("Emit special debug info to enable PGO profile generation." )); |
| 232 | |
| 233 | static cl::opt<bool> PseudoProbeForProfiling( |
| 234 | "pseudo-probe-for-profiling" , cl::init(Val: false), cl::Hidden, |
| 235 | cl::desc("Emit pseudo probes to enable PGO profile generation." )); |
| 236 | |
| 237 | static cl::opt<bool> DisableLoopUnrolling( |
| 238 | "disable-loop-unrolling" , |
| 239 | cl::desc("Disable loop unrolling in all relevant passes" ), cl::init(Val: false)); |
| 240 | |
| 241 | template <typename PassManagerT> |
| 242 | bool tryParsePipelineText(PassBuilder &PB, |
| 243 | const cl::opt<std::string> &PipelineOpt) { |
| 244 | if (PipelineOpt.empty()) |
| 245 | return false; |
| 246 | |
| 247 | // Verify the pipeline is parseable: |
| 248 | PassManagerT PM; |
| 249 | if (auto Err = PB.parsePassPipeline(PM, PipelineOpt)) { |
| 250 | errs() << "Could not parse -" << PipelineOpt.ArgStr |
| 251 | << " pipeline: " << toString(std::move(Err)) |
| 252 | << "... I'm going to ignore it.\n" ; |
| 253 | return false; |
| 254 | } |
| 255 | return true; |
| 256 | } |
| 257 | |
| 258 | /// If one of the EPPipeline command line options was given, register callbacks |
| 259 | /// for parsing and inserting the given pipeline |
| 260 | static void registerEPCallbacks(PassBuilder &PB) { |
| 261 | if (tryParsePipelineText<FunctionPassManager>(PB, PipelineOpt: PeepholeEPPipeline)) |
| 262 | PB.registerPeepholeEPCallback( |
| 263 | C: [&PB](FunctionPassManager &PM, OptimizationLevel Level) { |
| 264 | ExitOnError Err("Unable to parse PeepholeEP pipeline: " ); |
| 265 | Err(PB.parsePassPipeline(FPM&: PM, PipelineText: PeepholeEPPipeline)); |
| 266 | }); |
| 267 | if (tryParsePipelineText<LoopPassManager>(PB, |
| 268 | PipelineOpt: LateLoopOptimizationsEPPipeline)) |
| 269 | PB.registerLateLoopOptimizationsEPCallback( |
| 270 | C: [&PB](LoopPassManager &PM, OptimizationLevel Level) { |
| 271 | ExitOnError Err("Unable to parse LateLoopOptimizationsEP pipeline: " ); |
| 272 | Err(PB.parsePassPipeline(LPM&: PM, PipelineText: LateLoopOptimizationsEPPipeline)); |
| 273 | }); |
| 274 | if (tryParsePipelineText<LoopPassManager>(PB, PipelineOpt: LoopOptimizerEndEPPipeline)) |
| 275 | PB.registerLoopOptimizerEndEPCallback( |
| 276 | C: [&PB](LoopPassManager &PM, OptimizationLevel Level) { |
| 277 | ExitOnError Err("Unable to parse LoopOptimizerEndEP pipeline: " ); |
| 278 | Err(PB.parsePassPipeline(LPM&: PM, PipelineText: LoopOptimizerEndEPPipeline)); |
| 279 | }); |
| 280 | if (tryParsePipelineText<FunctionPassManager>(PB, |
| 281 | PipelineOpt: ScalarOptimizerLateEPPipeline)) |
| 282 | PB.registerScalarOptimizerLateEPCallback( |
| 283 | C: [&PB](FunctionPassManager &PM, OptimizationLevel Level) { |
| 284 | ExitOnError Err("Unable to parse ScalarOptimizerLateEP pipeline: " ); |
| 285 | Err(PB.parsePassPipeline(FPM&: PM, PipelineText: ScalarOptimizerLateEPPipeline)); |
| 286 | }); |
| 287 | if (tryParsePipelineText<CGSCCPassManager>(PB, PipelineOpt: CGSCCOptimizerLateEPPipeline)) |
| 288 | PB.registerCGSCCOptimizerLateEPCallback( |
| 289 | C: [&PB](CGSCCPassManager &PM, OptimizationLevel Level) { |
| 290 | ExitOnError Err("Unable to parse CGSCCOptimizerLateEP pipeline: " ); |
| 291 | Err(PB.parsePassPipeline(CGPM&: PM, PipelineText: CGSCCOptimizerLateEPPipeline)); |
| 292 | }); |
| 293 | if (tryParsePipelineText<FunctionPassManager>(PB, PipelineOpt: VectorizerStartEPPipeline)) |
| 294 | PB.registerVectorizerStartEPCallback( |
| 295 | C: [&PB](FunctionPassManager &PM, OptimizationLevel Level) { |
| 296 | ExitOnError Err("Unable to parse VectorizerStartEP pipeline: " ); |
| 297 | Err(PB.parsePassPipeline(FPM&: PM, PipelineText: VectorizerStartEPPipeline)); |
| 298 | }); |
| 299 | if (tryParsePipelineText<FunctionPassManager>(PB, PipelineOpt: VectorizerEndEPPipeline)) |
| 300 | PB.registerVectorizerEndEPCallback( |
| 301 | C: [&PB](FunctionPassManager &PM, OptimizationLevel Level) { |
| 302 | ExitOnError Err("Unable to parse VectorizerEndEP pipeline: " ); |
| 303 | Err(PB.parsePassPipeline(FPM&: PM, PipelineText: VectorizerEndEPPipeline)); |
| 304 | }); |
| 305 | if (tryParsePipelineText<ModulePassManager>(PB, PipelineOpt: PipelineStartEPPipeline)) |
| 306 | PB.registerPipelineStartEPCallback( |
| 307 | C: [&PB](ModulePassManager &PM, OptimizationLevel) { |
| 308 | ExitOnError Err("Unable to parse PipelineStartEP pipeline: " ); |
| 309 | Err(PB.parsePassPipeline(MPM&: PM, PipelineText: PipelineStartEPPipeline)); |
| 310 | }); |
| 311 | if (tryParsePipelineText<ModulePassManager>( |
| 312 | PB, PipelineOpt: PipelineEarlySimplificationEPPipeline)) |
| 313 | PB.registerPipelineEarlySimplificationEPCallback( |
| 314 | C: [&PB](ModulePassManager &PM, OptimizationLevel, ThinOrFullLTOPhase) { |
| 315 | ExitOnError Err("Unable to parse EarlySimplification pipeline: " ); |
| 316 | Err(PB.parsePassPipeline(MPM&: PM, PipelineText: PipelineEarlySimplificationEPPipeline)); |
| 317 | }); |
| 318 | if (tryParsePipelineText<ModulePassManager>(PB, PipelineOpt: OptimizerEarlyEPPipeline)) |
| 319 | PB.registerOptimizerEarlyEPCallback( |
| 320 | C: [&PB](ModulePassManager &PM, OptimizationLevel, ThinOrFullLTOPhase) { |
| 321 | ExitOnError Err("Unable to parse OptimizerEarlyEP pipeline: " ); |
| 322 | Err(PB.parsePassPipeline(MPM&: PM, PipelineText: OptimizerEarlyEPPipeline)); |
| 323 | }); |
| 324 | if (tryParsePipelineText<ModulePassManager>(PB, PipelineOpt: OptimizerLastEPPipeline)) |
| 325 | PB.registerOptimizerLastEPCallback( |
| 326 | C: [&PB](ModulePassManager &PM, OptimizationLevel, ThinOrFullLTOPhase) { |
| 327 | ExitOnError Err("Unable to parse OptimizerLastEP pipeline: " ); |
| 328 | Err(PB.parsePassPipeline(MPM&: PM, PipelineText: OptimizerLastEPPipeline)); |
| 329 | }); |
| 330 | if (tryParsePipelineText<ModulePassManager>( |
| 331 | PB, PipelineOpt: FullLinkTimeOptimizationEarlyEPPipeline)) |
| 332 | PB.registerFullLinkTimeOptimizationEarlyEPCallback( |
| 333 | C: [&PB](ModulePassManager &PM, OptimizationLevel) { |
| 334 | ExitOnError Err( |
| 335 | "Unable to parse FullLinkTimeOptimizationEarlyEP pipeline: " ); |
| 336 | Err(PB.parsePassPipeline(MPM&: PM, |
| 337 | PipelineText: FullLinkTimeOptimizationEarlyEPPipeline)); |
| 338 | }); |
| 339 | if (tryParsePipelineText<ModulePassManager>( |
| 340 | PB, PipelineOpt: FullLinkTimeOptimizationLastEPPipeline)) |
| 341 | PB.registerFullLinkTimeOptimizationLastEPCallback( |
| 342 | C: [&PB](ModulePassManager &PM, OptimizationLevel) { |
| 343 | ExitOnError Err( |
| 344 | "Unable to parse FullLinkTimeOptimizationLastEP pipeline: " ); |
| 345 | Err(PB.parsePassPipeline(MPM&: PM, PipelineText: FullLinkTimeOptimizationLastEPPipeline)); |
| 346 | }); |
| 347 | } |
| 348 | |
| 349 | #define HANDLE_EXTENSION(Ext) \ |
| 350 | llvm::PassPluginLibraryInfo get##Ext##PluginInfo(); |
| 351 | #include "llvm/Support/Extension.def" |
| 352 | #undef HANDLE_EXTENSION |
| 353 | |
| 354 | bool llvm::runPassPipeline( |
| 355 | StringRef Arg0, Module &M, TargetMachine *TM, TargetLibraryInfoImpl *TLII, |
| 356 | ToolOutputFile *Out, ToolOutputFile *ThinLTOLinkOut, |
| 357 | ToolOutputFile *, StringRef PassPipeline, |
| 358 | ArrayRef<PassPlugin> PassPlugins, |
| 359 | ArrayRef<std::function<void(PassBuilder &)>> PassBuilderCallbacks, |
| 360 | OutputKind OK, VerifierKind VK, bool ShouldPreserveAssemblyUseListOrder, |
| 361 | bool ShouldPreserveBitcodeUseListOrder, bool EmitSummaryIndex, |
| 362 | bool EmitModuleHash, bool EnableDebugify, bool VerifyDIPreserve, |
| 363 | bool EnableProfcheck, bool UnifiedLTO) { |
| 364 | std::optional<PGOOptions> P; |
| 365 | switch (PGOKindFlag) { |
| 366 | case InstrGen: |
| 367 | P = PGOOptions(ProfileFile, "" , "" , MemoryProfileFile, PGOOptions::IRInstr, |
| 368 | PGOOptions::NoCSAction, PGOColdFuncAttr); |
| 369 | break; |
| 370 | case InstrUse: |
| 371 | P = PGOOptions(ProfileFile, "" , ProfileRemappingFile, MemoryProfileFile, |
| 372 | PGOOptions::IRUse, PGOOptions::NoCSAction, PGOColdFuncAttr); |
| 373 | break; |
| 374 | case SampleUse: |
| 375 | P = PGOOptions(ProfileFile, "" , ProfileRemappingFile, MemoryProfileFile, |
| 376 | PGOOptions::SampleUse, PGOOptions::NoCSAction, |
| 377 | PGOColdFuncAttr); |
| 378 | break; |
| 379 | case NoPGO: |
| 380 | if (DebugInfoForProfiling || PseudoProbeForProfiling || |
| 381 | !MemoryProfileFile.empty()) |
| 382 | P = PGOOptions("" , "" , "" , MemoryProfileFile, PGOOptions::NoAction, |
| 383 | PGOOptions::NoCSAction, PGOColdFuncAttr, |
| 384 | DebugInfoForProfiling, PseudoProbeForProfiling); |
| 385 | else |
| 386 | P = std::nullopt; |
| 387 | } |
| 388 | if (CSPGOKindFlag != NoCSPGO) { |
| 389 | if (P && (P->Action == PGOOptions::IRInstr || |
| 390 | P->Action == PGOOptions::SampleUse)) { |
| 391 | errs() << "CSPGOKind cannot be used with IRInstr or SampleUse" ; |
| 392 | return false; |
| 393 | } |
| 394 | if (CSPGOKindFlag == CSInstrGen) { |
| 395 | if (CSProfileGenFile.empty()) { |
| 396 | errs() << "CSInstrGen needs to specify CSProfileGenFile" ; |
| 397 | return false; |
| 398 | } |
| 399 | if (P) { |
| 400 | P->CSAction = PGOOptions::CSIRInstr; |
| 401 | P->CSProfileGenFile = CSProfileGenFile; |
| 402 | } else |
| 403 | P = PGOOptions("" , CSProfileGenFile, ProfileRemappingFile, |
| 404 | /*MemoryProfile=*/"" , PGOOptions::NoAction, |
| 405 | PGOOptions::CSIRInstr); |
| 406 | } else /* CSPGOKindFlag == CSInstrUse */ { |
| 407 | if (!P) { |
| 408 | errs() << "CSInstrUse needs to be together with InstrUse" ; |
| 409 | return false; |
| 410 | } |
| 411 | P->CSAction = PGOOptions::CSIRUse; |
| 412 | } |
| 413 | } |
| 414 | |
| 415 | LoopAnalysisManager LAM; |
| 416 | FunctionAnalysisManager FAM; |
| 417 | CGSCCAnalysisManager CGAM; |
| 418 | ModuleAnalysisManager MAM; |
| 419 | |
| 420 | if (TM) { |
| 421 | TM->setPGOOption(P); |
| 422 | |
| 423 | MAM.registerPass(PassBuilder: [&] { |
| 424 | const TargetOptions &Options = TM->Options; |
| 425 | return RuntimeLibraryAnalysis(M.getTargetTriple(), Options.ExceptionModel, |
| 426 | Options.FloatABIType, Options.EABIVersion, |
| 427 | Options.MCOptions.ABIName, Options.VecLib); |
| 428 | }); |
| 429 | |
| 430 | MAM.registerPass(PassBuilder: [&] { return LibcallLoweringModuleAnalysis(); }); |
| 431 | } |
| 432 | |
| 433 | PassInstrumentationCallbacks PIC; |
| 434 | PrintPassOptions PrintPassOpts; |
| 435 | PrintPassOpts.Verbose = DebugPM == DebugLogging::Verbose; |
| 436 | PrintPassOpts.SkipAnalyses = DebugPM == DebugLogging::Quiet; |
| 437 | StandardInstrumentations SI(M.getContext(), DebugPM != DebugLogging::None, |
| 438 | VK == VerifierKind::EachPass, PrintPassOpts); |
| 439 | SI.registerCallbacks(PIC, MAM: &MAM); |
| 440 | DebugifyEachInstrumentation Debugify; |
| 441 | DebugifyStatsMap DIStatsMap; |
| 442 | DebugInfoPerPass DebugInfoBeforePass; |
| 443 | if (DebugifyEach) { |
| 444 | Debugify.setDIStatsMap(DIStatsMap); |
| 445 | Debugify.setDebugifyMode(DebugifyMode::SyntheticDebugInfo); |
| 446 | Debugify.registerCallbacks(PIC, MAM); |
| 447 | } else if (VerifyEachDebugInfoPreserve) { |
| 448 | Debugify.setDebugInfoBeforePass(DebugInfoBeforePass); |
| 449 | Debugify.setDebugifyMode(DebugifyMode::OriginalDebugInfo); |
| 450 | Debugify.setOrigDIVerifyBugsReportFilePath( |
| 451 | VerifyDIPreserveExport); |
| 452 | Debugify.registerCallbacks(PIC, MAM); |
| 453 | } |
| 454 | |
| 455 | PipelineTuningOptions PTO; |
| 456 | // LoopUnrolling defaults on to true and DisableLoopUnrolling is initialized |
| 457 | // to false above so we shouldn't necessarily need to check whether or not the |
| 458 | // option has been enabled. |
| 459 | PTO.LoopUnrolling = !DisableLoopUnrolling; |
| 460 | PTO.UnifiedLTO = UnifiedLTO; |
| 461 | PTO.LoopFusion = EnableLoopFusion; |
| 462 | PassBuilder PB(TM, PTO, P, &PIC); |
| 463 | registerEPCallbacks(PB); |
| 464 | |
| 465 | // For any loaded plugins, let them register pass builder callbacks. |
| 466 | for (auto &PassPlugin : PassPlugins) |
| 467 | PassPlugin.registerPassBuilderCallbacks(PB); |
| 468 | |
| 469 | // Load any explicitly specified plugins. |
| 470 | for (auto &PassCallback : PassBuilderCallbacks) |
| 471 | PassCallback(PB); |
| 472 | |
| 473 | #define HANDLE_EXTENSION(Ext) \ |
| 474 | get##Ext##PluginInfo().RegisterPassBuilderCallbacks(PB); |
| 475 | #include "llvm/Support/Extension.def" |
| 476 | #undef HANDLE_EXTENSION |
| 477 | |
| 478 | // Specially handle the alias analysis manager so that we can register |
| 479 | // a custom pipeline of AA passes with it. |
| 480 | AAManager AA; |
| 481 | if (auto Err = PB.parseAAPipeline(AA, PipelineText: AAPipeline)) { |
| 482 | errs() << Arg0 << ": " << toString(E: std::move(Err)) << "\n" ; |
| 483 | return false; |
| 484 | } |
| 485 | |
| 486 | // Register the AA manager first so that our version is the one used. |
| 487 | FAM.registerPass(PassBuilder: [&] { return std::move(AA); }); |
| 488 | // Register our TargetLibraryInfoImpl. |
| 489 | FAM.registerPass(PassBuilder: [&] { return TargetLibraryAnalysis(*TLII); }); |
| 490 | |
| 491 | // Register all the basic analyses with the managers. |
| 492 | PB.registerModuleAnalyses(MAM); |
| 493 | PB.registerCGSCCAnalyses(CGAM); |
| 494 | PB.registerFunctionAnalyses(FAM); |
| 495 | PB.registerLoopAnalyses(LAM); |
| 496 | PB.crossRegisterProxies(LAM, FAM, CGAM, MAM); |
| 497 | |
| 498 | ModulePassManager MPM; |
| 499 | if (EnableDebugify) |
| 500 | MPM.addPass(Pass: NewPMDebugifyPass()); |
| 501 | if (VerifyDIPreserve) |
| 502 | MPM.addPass(Pass: NewPMDebugifyPass(DebugifyMode::OriginalDebugInfo, "" , |
| 503 | &DebugInfoBeforePass)); |
| 504 | if (EnableProfcheck) |
| 505 | MPM.addPass(Pass: createModuleToFunctionPassAdaptor(Pass: ProfileInjectorPass())); |
| 506 | // Add passes according to the -passes options. |
| 507 | if (!PassPipeline.empty()) { |
| 508 | if (auto Err = PB.parsePassPipeline(MPM, PipelineText: PassPipeline)) { |
| 509 | errs() << Arg0 << ": " << toString(E: std::move(Err)) << "\n" ; |
| 510 | return false; |
| 511 | } |
| 512 | } |
| 513 | |
| 514 | if (VK != VerifierKind::None) |
| 515 | MPM.addPass(Pass: VerifierPass()); |
| 516 | if (EnableDebugify) |
| 517 | MPM.addPass(Pass: NewPMCheckDebugifyPass(false, "" , &DIStatsMap)); |
| 518 | if (VerifyDIPreserve) |
| 519 | MPM.addPass(Pass: NewPMCheckDebugifyPass( |
| 520 | false, "" , nullptr, DebugifyMode::OriginalDebugInfo, |
| 521 | &DebugInfoBeforePass, VerifyDIPreserveExport)); |
| 522 | if (EnableProfcheck) |
| 523 | MPM.addPass(Pass: ProfileVerifierPass()); |
| 524 | |
| 525 | // Add any relevant output pass at the end of the pipeline. |
| 526 | switch (OK) { |
| 527 | case OK_NoOutput: |
| 528 | break; // No output pass needed. |
| 529 | case OK_OutputAssembly: |
| 530 | MPM.addPass(Pass: PrintModulePass( |
| 531 | Out->os(), "" , ShouldPreserveAssemblyUseListOrder, EmitSummaryIndex)); |
| 532 | break; |
| 533 | case OK_OutputBitcode: |
| 534 | MPM.addPass(Pass: BitcodeWriterPass(Out->os(), ShouldPreserveBitcodeUseListOrder, |
| 535 | EmitSummaryIndex, EmitModuleHash)); |
| 536 | break; |
| 537 | case OK_OutputThinLTOBitcode: |
| 538 | MPM.addPass(Pass: ThinLTOBitcodeWriterPass( |
| 539 | Out->os(), ThinLTOLinkOut ? &ThinLTOLinkOut->os() : nullptr, |
| 540 | ShouldPreserveBitcodeUseListOrder)); |
| 541 | break; |
| 542 | } |
| 543 | |
| 544 | // Before executing passes, print the final values of the LLVM options. |
| 545 | cl::PrintOptionValues(); |
| 546 | |
| 547 | // Print a textual, '-passes=' compatible, representation of pipeline if |
| 548 | // requested. |
| 549 | if (PrintPipelinePasses) { |
| 550 | std::string Pipeline; |
| 551 | raw_string_ostream SOS(Pipeline); |
| 552 | MPM.printPipeline(OS&: SOS, MapClassName2PassName: [&PIC](StringRef ClassName) { |
| 553 | auto PassName = PIC.getPassNameForClassName(ClassName); |
| 554 | return PassName.empty() ? ClassName : PassName; |
| 555 | }); |
| 556 | outs() << Pipeline; |
| 557 | outs() << "\n" ; |
| 558 | |
| 559 | if (!DisablePipelineVerification) { |
| 560 | // Check that we can parse the returned pipeline string as an actual |
| 561 | // pipeline. |
| 562 | ModulePassManager TempPM; |
| 563 | if (auto Err = PB.parsePassPipeline(MPM&: TempPM, PipelineText: Pipeline)) { |
| 564 | errs() << "Could not parse dumped pass pipeline: " |
| 565 | << toString(E: std::move(Err)) << "\n" ; |
| 566 | return false; |
| 567 | } |
| 568 | } |
| 569 | |
| 570 | return true; |
| 571 | } |
| 572 | |
| 573 | // Now that we have all of the passes ready, run them. |
| 574 | MPM.run(IR&: M, AM&: MAM); |
| 575 | |
| 576 | // Declare success. |
| 577 | if (OK != OK_NoOutput) { |
| 578 | Out->keep(); |
| 579 | if (OK == OK_OutputThinLTOBitcode && ThinLTOLinkOut) |
| 580 | ThinLTOLinkOut->keep(); |
| 581 | } |
| 582 | |
| 583 | if (OptRemarkFile) |
| 584 | OptRemarkFile->keep(); |
| 585 | |
| 586 | if (DebugifyEach && !DebugifyExport.empty()) |
| 587 | exportDebugifyStats(Path: DebugifyExport, Map: Debugify.getDebugifyStatsMap()); |
| 588 | |
| 589 | TimerGroup::printAll(OS&: *CreateInfoOutputFile()); |
| 590 | TimerGroup::clearAll(); |
| 591 | |
| 592 | return true; |
| 593 | } |
| 594 | |
| 595 | void llvm::printPasses(raw_ostream &OS) { |
| 596 | PassBuilder PB; |
| 597 | PB.printPassNames(OS); |
| 598 | } |
| 599 | |