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