1349cc55cSDimitry Andric //===- Construction of pass pipelines -------------------------------------===// 2349cc55cSDimitry Andric // 3349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5349cc55cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6349cc55cSDimitry Andric // 7349cc55cSDimitry Andric //===----------------------------------------------------------------------===// 8349cc55cSDimitry Andric /// \file 9349cc55cSDimitry Andric /// 10349cc55cSDimitry Andric /// This file provides the implementation of the PassBuilder based on our 11349cc55cSDimitry Andric /// static pass registry as well as related functionality. It also provides 12349cc55cSDimitry Andric /// helpers to aid in analyzing, debugging, and testing passes and pass 13349cc55cSDimitry Andric /// pipelines. 14349cc55cSDimitry Andric /// 15349cc55cSDimitry Andric //===----------------------------------------------------------------------===// 16349cc55cSDimitry Andric 17349cc55cSDimitry Andric #include "llvm/Analysis/AliasAnalysis.h" 18349cc55cSDimitry Andric #include "llvm/Analysis/BasicAliasAnalysis.h" 19349cc55cSDimitry Andric #include "llvm/Analysis/CGSCCPassManager.h" 20349cc55cSDimitry Andric #include "llvm/Analysis/GlobalsModRef.h" 21349cc55cSDimitry Andric #include "llvm/Analysis/InlineAdvisor.h" 22349cc55cSDimitry Andric #include "llvm/Analysis/OptimizationRemarkEmitter.h" 23349cc55cSDimitry Andric #include "llvm/Analysis/ProfileSummaryInfo.h" 24349cc55cSDimitry Andric #include "llvm/Analysis/ScopedNoAliasAA.h" 25349cc55cSDimitry Andric #include "llvm/Analysis/TypeBasedAliasAnalysis.h" 26349cc55cSDimitry Andric #include "llvm/IR/PassManager.h" 27349cc55cSDimitry Andric #include "llvm/Passes/OptimizationLevel.h" 28349cc55cSDimitry Andric #include "llvm/Passes/PassBuilder.h" 29349cc55cSDimitry Andric #include "llvm/Support/CommandLine.h" 30349cc55cSDimitry Andric #include "llvm/Support/ErrorHandling.h" 31349cc55cSDimitry Andric #include "llvm/Support/PGOOptions.h" 32349cc55cSDimitry Andric #include "llvm/Target/TargetMachine.h" 33349cc55cSDimitry Andric #include "llvm/Transforms/AggressiveInstCombine/AggressiveInstCombine.h" 34349cc55cSDimitry Andric #include "llvm/Transforms/Coroutines/CoroCleanup.h" 3581ad6265SDimitry Andric #include "llvm/Transforms/Coroutines/CoroConditionalWrapper.h" 36349cc55cSDimitry Andric #include "llvm/Transforms/Coroutines/CoroEarly.h" 37349cc55cSDimitry Andric #include "llvm/Transforms/Coroutines/CoroElide.h" 38349cc55cSDimitry Andric #include "llvm/Transforms/Coroutines/CoroSplit.h" 39349cc55cSDimitry Andric #include "llvm/Transforms/IPO/AlwaysInliner.h" 40349cc55cSDimitry Andric #include "llvm/Transforms/IPO/Annotation2Metadata.h" 41349cc55cSDimitry Andric #include "llvm/Transforms/IPO/ArgumentPromotion.h" 42349cc55cSDimitry Andric #include "llvm/Transforms/IPO/Attributor.h" 43349cc55cSDimitry Andric #include "llvm/Transforms/IPO/CalledValuePropagation.h" 44349cc55cSDimitry Andric #include "llvm/Transforms/IPO/ConstantMerge.h" 45349cc55cSDimitry Andric #include "llvm/Transforms/IPO/CrossDSOCFI.h" 46349cc55cSDimitry Andric #include "llvm/Transforms/IPO/DeadArgumentElimination.h" 47349cc55cSDimitry Andric #include "llvm/Transforms/IPO/ElimAvailExtern.h" 48349cc55cSDimitry Andric #include "llvm/Transforms/IPO/ForceFunctionAttrs.h" 49349cc55cSDimitry Andric #include "llvm/Transforms/IPO/FunctionAttrs.h" 50349cc55cSDimitry Andric #include "llvm/Transforms/IPO/GlobalDCE.h" 51349cc55cSDimitry Andric #include "llvm/Transforms/IPO/GlobalOpt.h" 52349cc55cSDimitry Andric #include "llvm/Transforms/IPO/GlobalSplit.h" 53349cc55cSDimitry Andric #include "llvm/Transforms/IPO/HotColdSplitting.h" 54349cc55cSDimitry Andric #include "llvm/Transforms/IPO/IROutliner.h" 55349cc55cSDimitry Andric #include "llvm/Transforms/IPO/InferFunctionAttrs.h" 56349cc55cSDimitry Andric #include "llvm/Transforms/IPO/Inliner.h" 57349cc55cSDimitry Andric #include "llvm/Transforms/IPO/LowerTypeTests.h" 58349cc55cSDimitry Andric #include "llvm/Transforms/IPO/MergeFunctions.h" 59349cc55cSDimitry Andric #include "llvm/Transforms/IPO/ModuleInliner.h" 60349cc55cSDimitry Andric #include "llvm/Transforms/IPO/OpenMPOpt.h" 61349cc55cSDimitry Andric #include "llvm/Transforms/IPO/PartialInlining.h" 62349cc55cSDimitry Andric #include "llvm/Transforms/IPO/SCCP.h" 63349cc55cSDimitry Andric #include "llvm/Transforms/IPO/SampleProfile.h" 64349cc55cSDimitry Andric #include "llvm/Transforms/IPO/SampleProfileProbe.h" 65349cc55cSDimitry Andric #include "llvm/Transforms/IPO/SyntheticCountsPropagation.h" 66349cc55cSDimitry Andric #include "llvm/Transforms/IPO/WholeProgramDevirt.h" 67349cc55cSDimitry Andric #include "llvm/Transforms/InstCombine/InstCombine.h" 68349cc55cSDimitry Andric #include "llvm/Transforms/Instrumentation/CGProfile.h" 69349cc55cSDimitry Andric #include "llvm/Transforms/Instrumentation/ControlHeightReduction.h" 70349cc55cSDimitry Andric #include "llvm/Transforms/Instrumentation/InstrOrderFile.h" 71349cc55cSDimitry Andric #include "llvm/Transforms/Instrumentation/InstrProfiling.h" 72349cc55cSDimitry Andric #include "llvm/Transforms/Instrumentation/MemProfiler.h" 73349cc55cSDimitry Andric #include "llvm/Transforms/Instrumentation/PGOInstrumentation.h" 74349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/ADCE.h" 75349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/AlignmentFromAssumptions.h" 76349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/AnnotationRemarks.h" 77349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/BDCE.h" 78349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/CallSiteSplitting.h" 79349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/ConstraintElimination.h" 80349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/CorrelatedValuePropagation.h" 81349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/DFAJumpThreading.h" 82349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/DeadStoreElimination.h" 83349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/DivRemPairs.h" 84349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/EarlyCSE.h" 85349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/Float2Int.h" 86349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/GVN.h" 87349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/IndVarSimplify.h" 88349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/InstSimplifyPass.h" 89349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/JumpThreading.h" 90349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/LICM.h" 91349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/LoopDeletion.h" 92349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/LoopDistribute.h" 93349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/LoopFlatten.h" 94349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/LoopIdiomRecognize.h" 95349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/LoopInstSimplify.h" 96349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/LoopInterchange.h" 97349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/LoopLoadElimination.h" 98349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/LoopPassManager.h" 99349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/LoopRotation.h" 100349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/LoopSimplifyCFG.h" 101349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/LoopSink.h" 102349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/LoopUnrollAndJamPass.h" 103349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/LoopUnrollPass.h" 104349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/LowerConstantIntrinsics.h" 105349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/LowerExpectIntrinsic.h" 106349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/LowerMatrixIntrinsics.h" 107349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/MemCpyOptimizer.h" 108349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/MergedLoadStoreMotion.h" 109349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/NewGVN.h" 110349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/Reassociate.h" 111349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/SCCP.h" 112349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/SROA.h" 113349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/SimpleLoopUnswitch.h" 114349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/SimplifyCFG.h" 115349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/SpeculativeExecution.h" 116349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/TailRecursionElimination.h" 117349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/WarnMissedTransforms.h" 118349cc55cSDimitry Andric #include "llvm/Transforms/Utils/AddDiscriminators.h" 119349cc55cSDimitry Andric #include "llvm/Transforms/Utils/AssumeBundleBuilder.h" 120349cc55cSDimitry Andric #include "llvm/Transforms/Utils/CanonicalizeAliases.h" 121349cc55cSDimitry Andric #include "llvm/Transforms/Utils/InjectTLIMappings.h" 122349cc55cSDimitry Andric #include "llvm/Transforms/Utils/LibCallsShrinkWrap.h" 123349cc55cSDimitry Andric #include "llvm/Transforms/Utils/Mem2Reg.h" 124349cc55cSDimitry Andric #include "llvm/Transforms/Utils/NameAnonGlobals.h" 125349cc55cSDimitry Andric #include "llvm/Transforms/Utils/RelLookupTableConverter.h" 126349cc55cSDimitry Andric #include "llvm/Transforms/Utils/SimplifyCFGOptions.h" 127349cc55cSDimitry Andric #include "llvm/Transforms/Vectorize/LoopVectorize.h" 128349cc55cSDimitry Andric #include "llvm/Transforms/Vectorize/SLPVectorizer.h" 129349cc55cSDimitry Andric #include "llvm/Transforms/Vectorize/VectorCombine.h" 130349cc55cSDimitry Andric 131349cc55cSDimitry Andric using namespace llvm; 132349cc55cSDimitry Andric 133349cc55cSDimitry Andric static cl::opt<InliningAdvisorMode> UseInlineAdvisor( 134349cc55cSDimitry Andric "enable-ml-inliner", cl::init(InliningAdvisorMode::Default), cl::Hidden, 135349cc55cSDimitry Andric cl::desc("Enable ML policy for inliner. Currently trained for -Oz only"), 136349cc55cSDimitry Andric cl::values(clEnumValN(InliningAdvisorMode::Default, "default", 137349cc55cSDimitry Andric "Heuristics-based inliner version."), 138349cc55cSDimitry Andric clEnumValN(InliningAdvisorMode::Development, "development", 139349cc55cSDimitry Andric "Use development mode (runtime-loadable model)."), 140349cc55cSDimitry Andric clEnumValN(InliningAdvisorMode::Release, "release", 141349cc55cSDimitry Andric "Use release mode (AOT-compiled model)."))); 142349cc55cSDimitry Andric 143349cc55cSDimitry Andric static cl::opt<bool> EnableSyntheticCounts( 14481ad6265SDimitry Andric "enable-npm-synthetic-counts", cl::Hidden, 145349cc55cSDimitry Andric cl::desc("Run synthetic function entry count generation " 146349cc55cSDimitry Andric "pass")); 147349cc55cSDimitry Andric 148349cc55cSDimitry Andric /// Flag to enable inline deferral during PGO. 149349cc55cSDimitry Andric static cl::opt<bool> 150349cc55cSDimitry Andric EnablePGOInlineDeferral("enable-npm-pgo-inline-deferral", cl::init(true), 151349cc55cSDimitry Andric cl::Hidden, 152349cc55cSDimitry Andric cl::desc("Enable inline deferral during PGO")); 153349cc55cSDimitry Andric 15481ad6265SDimitry Andric static cl::opt<bool> EnableMemProfiler("enable-mem-prof", cl::Hidden, 155349cc55cSDimitry Andric cl::desc("Enable memory profiler")); 156349cc55cSDimitry Andric 157349cc55cSDimitry Andric static cl::opt<bool> EnableModuleInliner("enable-module-inliner", 158349cc55cSDimitry Andric cl::init(false), cl::Hidden, 159349cc55cSDimitry Andric cl::desc("Enable module inliner")); 160349cc55cSDimitry Andric 161349cc55cSDimitry Andric static cl::opt<bool> PerformMandatoryInliningsFirst( 16281ad6265SDimitry Andric "mandatory-inlining-first", cl::init(true), cl::Hidden, 163349cc55cSDimitry Andric cl::desc("Perform mandatory inlinings module-wide, before performing " 164349cc55cSDimitry Andric "inlining.")); 165349cc55cSDimitry Andric 166349cc55cSDimitry Andric static cl::opt<bool> EnableO3NonTrivialUnswitching( 167349cc55cSDimitry Andric "enable-npm-O3-nontrivial-unswitch", cl::init(true), cl::Hidden, 16881ad6265SDimitry Andric cl::desc("Enable non-trivial loop unswitching for -O3")); 169349cc55cSDimitry Andric 170349cc55cSDimitry Andric static cl::opt<bool> EnableEagerlyInvalidateAnalyses( 171349cc55cSDimitry Andric "eagerly-invalidate-analyses", cl::init(true), cl::Hidden, 172349cc55cSDimitry Andric cl::desc("Eagerly invalidate more analyses in default pipelines")); 173349cc55cSDimitry Andric 174349cc55cSDimitry Andric static cl::opt<bool> EnableNoRerunSimplificationPipeline( 175fcaf7f86SDimitry Andric "enable-no-rerun-simplification-pipeline", cl::init(true), cl::Hidden, 176349cc55cSDimitry Andric cl::desc( 177349cc55cSDimitry Andric "Prevent running the simplification pipeline on a function more " 178349cc55cSDimitry Andric "than once in the case that SCC mutations cause a function to be " 179349cc55cSDimitry Andric "visited multiple times as long as the function has not been changed")); 180349cc55cSDimitry Andric 1810eae32dcSDimitry Andric static cl::opt<bool> EnableMergeFunctions( 1820eae32dcSDimitry Andric "enable-merge-functions", cl::init(false), cl::Hidden, 1830eae32dcSDimitry Andric cl::desc("Enable function merging as part of the optimization pipeline")); 1840eae32dcSDimitry Andric 185349cc55cSDimitry Andric PipelineTuningOptions::PipelineTuningOptions() { 186349cc55cSDimitry Andric LoopInterleaving = true; 187349cc55cSDimitry Andric LoopVectorization = true; 188349cc55cSDimitry Andric SLPVectorization = false; 189349cc55cSDimitry Andric LoopUnrolling = true; 190349cc55cSDimitry Andric ForgetAllSCEVInLoopUnroll = ForgetSCEVInLoopUnroll; 191349cc55cSDimitry Andric LicmMssaOptCap = SetLicmMssaOptCap; 192349cc55cSDimitry Andric LicmMssaNoAccForPromotionCap = SetLicmMssaNoAccForPromotionCap; 193349cc55cSDimitry Andric CallGraphProfile = true; 1940eae32dcSDimitry Andric MergeFunctions = EnableMergeFunctions; 195349cc55cSDimitry Andric EagerlyInvalidateAnalyses = EnableEagerlyInvalidateAnalyses; 196349cc55cSDimitry Andric } 197349cc55cSDimitry Andric 198349cc55cSDimitry Andric namespace llvm { 199349cc55cSDimitry Andric 200349cc55cSDimitry Andric extern cl::opt<unsigned> MaxDevirtIterations; 201349cc55cSDimitry Andric extern cl::opt<bool> EnableConstraintElimination; 202349cc55cSDimitry Andric extern cl::opt<bool> EnableFunctionSpecialization; 203349cc55cSDimitry Andric extern cl::opt<bool> EnableGVNHoist; 204349cc55cSDimitry Andric extern cl::opt<bool> EnableGVNSink; 205349cc55cSDimitry Andric extern cl::opt<bool> EnableHotColdSplit; 206349cc55cSDimitry Andric extern cl::opt<bool> EnableIROutliner; 207349cc55cSDimitry Andric extern cl::opt<bool> EnableOrderFileInstrumentation; 208349cc55cSDimitry Andric extern cl::opt<bool> EnableCHR; 209349cc55cSDimitry Andric extern cl::opt<bool> EnableLoopInterchange; 210349cc55cSDimitry Andric extern cl::opt<bool> EnableUnrollAndJam; 211349cc55cSDimitry Andric extern cl::opt<bool> EnableLoopFlatten; 212349cc55cSDimitry Andric extern cl::opt<bool> EnableDFAJumpThreading; 213349cc55cSDimitry Andric extern cl::opt<bool> RunNewGVN; 214349cc55cSDimitry Andric extern cl::opt<bool> RunPartialInlining; 215349cc55cSDimitry Andric extern cl::opt<bool> ExtraVectorizerPasses; 216349cc55cSDimitry Andric 217349cc55cSDimitry Andric extern cl::opt<bool> FlattenedProfileUsed; 218349cc55cSDimitry Andric 219349cc55cSDimitry Andric extern cl::opt<AttributorRunOption> AttributorRun; 220349cc55cSDimitry Andric extern cl::opt<bool> EnableKnowledgeRetention; 221349cc55cSDimitry Andric 222349cc55cSDimitry Andric extern cl::opt<bool> EnableMatrix; 223349cc55cSDimitry Andric 224349cc55cSDimitry Andric extern cl::opt<bool> DisablePreInliner; 225349cc55cSDimitry Andric extern cl::opt<int> PreInlineThreshold; 226349cc55cSDimitry Andric } // namespace llvm 227349cc55cSDimitry Andric 228349cc55cSDimitry Andric void PassBuilder::invokePeepholeEPCallbacks(FunctionPassManager &FPM, 229349cc55cSDimitry Andric OptimizationLevel Level) { 230349cc55cSDimitry Andric for (auto &C : PeepholeEPCallbacks) 231349cc55cSDimitry Andric C(FPM, Level); 232349cc55cSDimitry Andric } 233349cc55cSDimitry Andric 234349cc55cSDimitry Andric // Helper to add AnnotationRemarksPass. 235349cc55cSDimitry Andric static void addAnnotationRemarksPass(ModulePassManager &MPM) { 23681ad6265SDimitry Andric MPM.addPass(createModuleToFunctionPassAdaptor(AnnotationRemarksPass())); 237349cc55cSDimitry Andric } 238349cc55cSDimitry Andric 239349cc55cSDimitry Andric // Helper to check if the current compilation phase is preparing for LTO 240349cc55cSDimitry Andric static bool isLTOPreLink(ThinOrFullLTOPhase Phase) { 241349cc55cSDimitry Andric return Phase == ThinOrFullLTOPhase::ThinLTOPreLink || 242349cc55cSDimitry Andric Phase == ThinOrFullLTOPhase::FullLTOPreLink; 243349cc55cSDimitry Andric } 244349cc55cSDimitry Andric 245349cc55cSDimitry Andric // TODO: Investigate the cost/benefit of tail call elimination on debugging. 246349cc55cSDimitry Andric FunctionPassManager 247349cc55cSDimitry Andric PassBuilder::buildO1FunctionSimplificationPipeline(OptimizationLevel Level, 248349cc55cSDimitry Andric ThinOrFullLTOPhase Phase) { 249349cc55cSDimitry Andric 250349cc55cSDimitry Andric FunctionPassManager FPM; 251349cc55cSDimitry Andric 252349cc55cSDimitry Andric // Form SSA out of local memory accesses after breaking apart aggregates into 253349cc55cSDimitry Andric // scalars. 254349cc55cSDimitry Andric FPM.addPass(SROAPass()); 255349cc55cSDimitry Andric 256349cc55cSDimitry Andric // Catch trivial redundancies 257349cc55cSDimitry Andric FPM.addPass(EarlyCSEPass(true /* Enable mem-ssa. */)); 258349cc55cSDimitry Andric 259349cc55cSDimitry Andric // Hoisting of scalars and load expressions. 260fb03ea46SDimitry Andric FPM.addPass( 261fb03ea46SDimitry Andric SimplifyCFGPass(SimplifyCFGOptions().convertSwitchRangeToICmp(true))); 262349cc55cSDimitry Andric FPM.addPass(InstCombinePass()); 263349cc55cSDimitry Andric 264349cc55cSDimitry Andric FPM.addPass(LibCallsShrinkWrapPass()); 265349cc55cSDimitry Andric 266349cc55cSDimitry Andric invokePeepholeEPCallbacks(FPM, Level); 267349cc55cSDimitry Andric 268fb03ea46SDimitry Andric FPM.addPass( 269fb03ea46SDimitry Andric SimplifyCFGPass(SimplifyCFGOptions().convertSwitchRangeToICmp(true))); 270349cc55cSDimitry Andric 271349cc55cSDimitry Andric // Form canonically associated expression trees, and simplify the trees using 272349cc55cSDimitry Andric // basic mathematical properties. For example, this will form (nearly) 273349cc55cSDimitry Andric // minimal multiplication trees. 274349cc55cSDimitry Andric FPM.addPass(ReassociatePass()); 275349cc55cSDimitry Andric 276349cc55cSDimitry Andric // Add the primary loop simplification pipeline. 277349cc55cSDimitry Andric // FIXME: Currently this is split into two loop pass pipelines because we run 278349cc55cSDimitry Andric // some function passes in between them. These can and should be removed 279349cc55cSDimitry Andric // and/or replaced by scheduling the loop pass equivalents in the correct 280349cc55cSDimitry Andric // positions. But those equivalent passes aren't powerful enough yet. 281349cc55cSDimitry Andric // Specifically, `SimplifyCFGPass` and `InstCombinePass` are currently still 282349cc55cSDimitry Andric // used. We have `LoopSimplifyCFGPass` which isn't yet powerful enough yet to 283349cc55cSDimitry Andric // fully replace `SimplifyCFGPass`, and the closest to the other we have is 284349cc55cSDimitry Andric // `LoopInstSimplify`. 285349cc55cSDimitry Andric LoopPassManager LPM1, LPM2; 286349cc55cSDimitry Andric 287349cc55cSDimitry Andric // Simplify the loop body. We do this initially to clean up after other loop 288349cc55cSDimitry Andric // passes run, either when iterating on a loop or on inner loops with 289349cc55cSDimitry Andric // implications on the outer loop. 290349cc55cSDimitry Andric LPM1.addPass(LoopInstSimplifyPass()); 291349cc55cSDimitry Andric LPM1.addPass(LoopSimplifyCFGPass()); 292349cc55cSDimitry Andric 293349cc55cSDimitry Andric // Try to remove as much code from the loop header as possible, 294fb03ea46SDimitry Andric // to reduce amount of IR that will have to be duplicated. However, 295fb03ea46SDimitry Andric // do not perform speculative hoisting the first time as LICM 296fb03ea46SDimitry Andric // will destroy metadata that may not need to be destroyed if run 297fb03ea46SDimitry Andric // after loop rotation. 298349cc55cSDimitry Andric // TODO: Investigate promotion cap for O1. 299fb03ea46SDimitry Andric LPM1.addPass(LICMPass(PTO.LicmMssaOptCap, PTO.LicmMssaNoAccForPromotionCap, 300fb03ea46SDimitry Andric /*AllowSpeculation=*/false)); 301349cc55cSDimitry Andric 302349cc55cSDimitry Andric LPM1.addPass(LoopRotatePass(/* Disable header duplication */ true, 303349cc55cSDimitry Andric isLTOPreLink(Phase))); 304349cc55cSDimitry Andric // TODO: Investigate promotion cap for O1. 305fb03ea46SDimitry Andric LPM1.addPass(LICMPass(PTO.LicmMssaOptCap, PTO.LicmMssaNoAccForPromotionCap, 306fb03ea46SDimitry Andric /*AllowSpeculation=*/true)); 307349cc55cSDimitry Andric LPM1.addPass(SimpleLoopUnswitchPass()); 30804eeddc0SDimitry Andric if (EnableLoopFlatten) 30904eeddc0SDimitry Andric LPM1.addPass(LoopFlattenPass()); 310349cc55cSDimitry Andric 311349cc55cSDimitry Andric LPM2.addPass(LoopIdiomRecognizePass()); 312349cc55cSDimitry Andric LPM2.addPass(IndVarSimplifyPass()); 313349cc55cSDimitry Andric 314349cc55cSDimitry Andric for (auto &C : LateLoopOptimizationsEPCallbacks) 315349cc55cSDimitry Andric C(LPM2, Level); 316349cc55cSDimitry Andric 317349cc55cSDimitry Andric LPM2.addPass(LoopDeletionPass()); 318349cc55cSDimitry Andric 319349cc55cSDimitry Andric if (EnableLoopInterchange) 320349cc55cSDimitry Andric LPM2.addPass(LoopInterchangePass()); 321349cc55cSDimitry Andric 322349cc55cSDimitry Andric // Do not enable unrolling in PreLinkThinLTO phase during sample PGO 323349cc55cSDimitry Andric // because it changes IR to makes profile annotation in back compile 324349cc55cSDimitry Andric // inaccurate. The normal unroller doesn't pay attention to forced full unroll 325349cc55cSDimitry Andric // attributes so we need to make sure and allow the full unroll pass to pay 326349cc55cSDimitry Andric // attention to it. 327349cc55cSDimitry Andric if (Phase != ThinOrFullLTOPhase::ThinLTOPreLink || !PGOOpt || 328349cc55cSDimitry Andric PGOOpt->Action != PGOOptions::SampleUse) 329349cc55cSDimitry Andric LPM2.addPass(LoopFullUnrollPass(Level.getSpeedupLevel(), 330349cc55cSDimitry Andric /* OnlyWhenForced= */ !PTO.LoopUnrolling, 331349cc55cSDimitry Andric PTO.ForgetAllSCEVInLoopUnroll)); 332349cc55cSDimitry Andric 333349cc55cSDimitry Andric for (auto &C : LoopOptimizerEndEPCallbacks) 334349cc55cSDimitry Andric C(LPM2, Level); 335349cc55cSDimitry Andric 336349cc55cSDimitry Andric // We provide the opt remark emitter pass for LICM to use. We only need to do 337349cc55cSDimitry Andric // this once as it is immutable. 338349cc55cSDimitry Andric FPM.addPass( 339349cc55cSDimitry Andric RequireAnalysisPass<OptimizationRemarkEmitterAnalysis, Function>()); 340349cc55cSDimitry Andric FPM.addPass(createFunctionToLoopPassAdaptor(std::move(LPM1), 341349cc55cSDimitry Andric /*UseMemorySSA=*/true, 342349cc55cSDimitry Andric /*UseBlockFrequencyInfo=*/true)); 343fb03ea46SDimitry Andric FPM.addPass( 344fb03ea46SDimitry Andric SimplifyCFGPass(SimplifyCFGOptions().convertSwitchRangeToICmp(true))); 345349cc55cSDimitry Andric FPM.addPass(InstCombinePass()); 346349cc55cSDimitry Andric // The loop passes in LPM2 (LoopFullUnrollPass) do not preserve MemorySSA. 347349cc55cSDimitry Andric // *All* loop passes must preserve it, in order to be able to use it. 348349cc55cSDimitry Andric FPM.addPass(createFunctionToLoopPassAdaptor(std::move(LPM2), 349349cc55cSDimitry Andric /*UseMemorySSA=*/false, 350349cc55cSDimitry Andric /*UseBlockFrequencyInfo=*/false)); 351349cc55cSDimitry Andric 352349cc55cSDimitry Andric // Delete small array after loop unroll. 353349cc55cSDimitry Andric FPM.addPass(SROAPass()); 354349cc55cSDimitry Andric 355349cc55cSDimitry Andric // Specially optimize memory movement as it doesn't look like dataflow in SSA. 356349cc55cSDimitry Andric FPM.addPass(MemCpyOptPass()); 357349cc55cSDimitry Andric 358349cc55cSDimitry Andric // Sparse conditional constant propagation. 359349cc55cSDimitry Andric // FIXME: It isn't clear why we do this *after* loop passes rather than 360349cc55cSDimitry Andric // before... 361349cc55cSDimitry Andric FPM.addPass(SCCPPass()); 362349cc55cSDimitry Andric 363349cc55cSDimitry Andric // Delete dead bit computations (instcombine runs after to fold away the dead 364349cc55cSDimitry Andric // computations, and then ADCE will run later to exploit any new DCE 365349cc55cSDimitry Andric // opportunities that creates). 366349cc55cSDimitry Andric FPM.addPass(BDCEPass()); 367349cc55cSDimitry Andric 368349cc55cSDimitry Andric // Run instcombine after redundancy and dead bit elimination to exploit 369349cc55cSDimitry Andric // opportunities opened up by them. 370349cc55cSDimitry Andric FPM.addPass(InstCombinePass()); 371349cc55cSDimitry Andric invokePeepholeEPCallbacks(FPM, Level); 372349cc55cSDimitry Andric 373349cc55cSDimitry Andric FPM.addPass(CoroElidePass()); 374349cc55cSDimitry Andric 375349cc55cSDimitry Andric for (auto &C : ScalarOptimizerLateEPCallbacks) 376349cc55cSDimitry Andric C(FPM, Level); 377349cc55cSDimitry Andric 378349cc55cSDimitry Andric // Finally, do an expensive DCE pass to catch all the dead code exposed by 379349cc55cSDimitry Andric // the simplifications and basic cleanup after all the simplifications. 380349cc55cSDimitry Andric // TODO: Investigate if this is too expensive. 381349cc55cSDimitry Andric FPM.addPass(ADCEPass()); 382fb03ea46SDimitry Andric FPM.addPass( 383fb03ea46SDimitry Andric SimplifyCFGPass(SimplifyCFGOptions().convertSwitchRangeToICmp(true))); 384349cc55cSDimitry Andric FPM.addPass(InstCombinePass()); 385349cc55cSDimitry Andric invokePeepholeEPCallbacks(FPM, Level); 386349cc55cSDimitry Andric 387349cc55cSDimitry Andric return FPM; 388349cc55cSDimitry Andric } 389349cc55cSDimitry Andric 390349cc55cSDimitry Andric FunctionPassManager 391349cc55cSDimitry Andric PassBuilder::buildFunctionSimplificationPipeline(OptimizationLevel Level, 392349cc55cSDimitry Andric ThinOrFullLTOPhase Phase) { 393349cc55cSDimitry Andric assert(Level != OptimizationLevel::O0 && "Must request optimizations!"); 394349cc55cSDimitry Andric 395349cc55cSDimitry Andric // The O1 pipeline has a separate pipeline creation function to simplify 396349cc55cSDimitry Andric // construction readability. 397349cc55cSDimitry Andric if (Level.getSpeedupLevel() == 1) 398349cc55cSDimitry Andric return buildO1FunctionSimplificationPipeline(Level, Phase); 399349cc55cSDimitry Andric 400349cc55cSDimitry Andric FunctionPassManager FPM; 401349cc55cSDimitry Andric 402349cc55cSDimitry Andric // Form SSA out of local memory accesses after breaking apart aggregates into 403349cc55cSDimitry Andric // scalars. 404349cc55cSDimitry Andric FPM.addPass(SROAPass()); 405349cc55cSDimitry Andric 406349cc55cSDimitry Andric // Catch trivial redundancies 407349cc55cSDimitry Andric FPM.addPass(EarlyCSEPass(true /* Enable mem-ssa. */)); 408349cc55cSDimitry Andric if (EnableKnowledgeRetention) 409349cc55cSDimitry Andric FPM.addPass(AssumeSimplifyPass()); 410349cc55cSDimitry Andric 411349cc55cSDimitry Andric // Hoisting of scalars and load expressions. 412349cc55cSDimitry Andric if (EnableGVNHoist) 413349cc55cSDimitry Andric FPM.addPass(GVNHoistPass()); 414349cc55cSDimitry Andric 415349cc55cSDimitry Andric // Global value numbering based sinking. 416349cc55cSDimitry Andric if (EnableGVNSink) { 417349cc55cSDimitry Andric FPM.addPass(GVNSinkPass()); 418fb03ea46SDimitry Andric FPM.addPass( 419fb03ea46SDimitry Andric SimplifyCFGPass(SimplifyCFGOptions().convertSwitchRangeToICmp(true))); 420349cc55cSDimitry Andric } 421349cc55cSDimitry Andric 422349cc55cSDimitry Andric if (EnableConstraintElimination) 423349cc55cSDimitry Andric FPM.addPass(ConstraintEliminationPass()); 424349cc55cSDimitry Andric 425349cc55cSDimitry Andric // Speculative execution if the target has divergent branches; otherwise nop. 426349cc55cSDimitry Andric FPM.addPass(SpeculativeExecutionPass(/* OnlyIfDivergentTarget =*/true)); 427349cc55cSDimitry Andric 428349cc55cSDimitry Andric // Optimize based on known information about branches, and cleanup afterward. 429349cc55cSDimitry Andric FPM.addPass(JumpThreadingPass()); 430349cc55cSDimitry Andric FPM.addPass(CorrelatedValuePropagationPass()); 431349cc55cSDimitry Andric 432fb03ea46SDimitry Andric FPM.addPass( 433fb03ea46SDimitry Andric SimplifyCFGPass(SimplifyCFGOptions().convertSwitchRangeToICmp(true))); 4340eae32dcSDimitry Andric FPM.addPass(InstCombinePass()); 435349cc55cSDimitry Andric if (Level == OptimizationLevel::O3) 436349cc55cSDimitry Andric FPM.addPass(AggressiveInstCombinePass()); 437349cc55cSDimitry Andric 438349cc55cSDimitry Andric if (!Level.isOptimizingForSize()) 439349cc55cSDimitry Andric FPM.addPass(LibCallsShrinkWrapPass()); 440349cc55cSDimitry Andric 441349cc55cSDimitry Andric invokePeepholeEPCallbacks(FPM, Level); 442349cc55cSDimitry Andric 443349cc55cSDimitry Andric // For PGO use pipeline, try to optimize memory intrinsics such as memcpy 444349cc55cSDimitry Andric // using the size value profile. Don't perform this when optimizing for size. 445349cc55cSDimitry Andric if (PGOOpt && PGOOpt->Action == PGOOptions::IRUse && 446349cc55cSDimitry Andric !Level.isOptimizingForSize()) 447349cc55cSDimitry Andric FPM.addPass(PGOMemOPSizeOpt()); 448349cc55cSDimitry Andric 449349cc55cSDimitry Andric FPM.addPass(TailCallElimPass()); 450fb03ea46SDimitry Andric FPM.addPass( 451fb03ea46SDimitry Andric SimplifyCFGPass(SimplifyCFGOptions().convertSwitchRangeToICmp(true))); 452349cc55cSDimitry Andric 453349cc55cSDimitry Andric // Form canonically associated expression trees, and simplify the trees using 454349cc55cSDimitry Andric // basic mathematical properties. For example, this will form (nearly) 455349cc55cSDimitry Andric // minimal multiplication trees. 456349cc55cSDimitry Andric FPM.addPass(ReassociatePass()); 457349cc55cSDimitry Andric 458349cc55cSDimitry Andric // Add the primary loop simplification pipeline. 459349cc55cSDimitry Andric // FIXME: Currently this is split into two loop pass pipelines because we run 460349cc55cSDimitry Andric // some function passes in between them. These can and should be removed 461349cc55cSDimitry Andric // and/or replaced by scheduling the loop pass equivalents in the correct 462349cc55cSDimitry Andric // positions. But those equivalent passes aren't powerful enough yet. 463349cc55cSDimitry Andric // Specifically, `SimplifyCFGPass` and `InstCombinePass` are currently still 464349cc55cSDimitry Andric // used. We have `LoopSimplifyCFGPass` which isn't yet powerful enough yet to 465349cc55cSDimitry Andric // fully replace `SimplifyCFGPass`, and the closest to the other we have is 466349cc55cSDimitry Andric // `LoopInstSimplify`. 467349cc55cSDimitry Andric LoopPassManager LPM1, LPM2; 468349cc55cSDimitry Andric 469349cc55cSDimitry Andric // Simplify the loop body. We do this initially to clean up after other loop 470349cc55cSDimitry Andric // passes run, either when iterating on a loop or on inner loops with 471349cc55cSDimitry Andric // implications on the outer loop. 472349cc55cSDimitry Andric LPM1.addPass(LoopInstSimplifyPass()); 473349cc55cSDimitry Andric LPM1.addPass(LoopSimplifyCFGPass()); 474349cc55cSDimitry Andric 475349cc55cSDimitry Andric // Try to remove as much code from the loop header as possible, 476fb03ea46SDimitry Andric // to reduce amount of IR that will have to be duplicated. However, 477fb03ea46SDimitry Andric // do not perform speculative hoisting the first time as LICM 478fb03ea46SDimitry Andric // will destroy metadata that may not need to be destroyed if run 479fb03ea46SDimitry Andric // after loop rotation. 480349cc55cSDimitry Andric // TODO: Investigate promotion cap for O1. 481fb03ea46SDimitry Andric LPM1.addPass(LICMPass(PTO.LicmMssaOptCap, PTO.LicmMssaNoAccForPromotionCap, 482fb03ea46SDimitry Andric /*AllowSpeculation=*/false)); 483349cc55cSDimitry Andric 484349cc55cSDimitry Andric // Disable header duplication in loop rotation at -Oz. 485349cc55cSDimitry Andric LPM1.addPass( 486349cc55cSDimitry Andric LoopRotatePass(Level != OptimizationLevel::Oz, isLTOPreLink(Phase))); 487349cc55cSDimitry Andric // TODO: Investigate promotion cap for O1. 488fb03ea46SDimitry Andric LPM1.addPass(LICMPass(PTO.LicmMssaOptCap, PTO.LicmMssaNoAccForPromotionCap, 489fb03ea46SDimitry Andric /*AllowSpeculation=*/true)); 490349cc55cSDimitry Andric LPM1.addPass( 491349cc55cSDimitry Andric SimpleLoopUnswitchPass(/* NonTrivial */ Level == OptimizationLevel::O3 && 492349cc55cSDimitry Andric EnableO3NonTrivialUnswitching)); 49304eeddc0SDimitry Andric if (EnableLoopFlatten) 49404eeddc0SDimitry Andric LPM1.addPass(LoopFlattenPass()); 49504eeddc0SDimitry Andric 496349cc55cSDimitry Andric LPM2.addPass(LoopIdiomRecognizePass()); 497349cc55cSDimitry Andric LPM2.addPass(IndVarSimplifyPass()); 498349cc55cSDimitry Andric 499349cc55cSDimitry Andric for (auto &C : LateLoopOptimizationsEPCallbacks) 500349cc55cSDimitry Andric C(LPM2, Level); 501349cc55cSDimitry Andric 502349cc55cSDimitry Andric LPM2.addPass(LoopDeletionPass()); 503349cc55cSDimitry Andric 504349cc55cSDimitry Andric if (EnableLoopInterchange) 505349cc55cSDimitry Andric LPM2.addPass(LoopInterchangePass()); 506349cc55cSDimitry Andric 507349cc55cSDimitry Andric // Do not enable unrolling in PreLinkThinLTO phase during sample PGO 508349cc55cSDimitry Andric // because it changes IR to makes profile annotation in back compile 509349cc55cSDimitry Andric // inaccurate. The normal unroller doesn't pay attention to forced full unroll 510349cc55cSDimitry Andric // attributes so we need to make sure and allow the full unroll pass to pay 511349cc55cSDimitry Andric // attention to it. 512349cc55cSDimitry Andric if (Phase != ThinOrFullLTOPhase::ThinLTOPreLink || !PGOOpt || 513349cc55cSDimitry Andric PGOOpt->Action != PGOOptions::SampleUse) 514349cc55cSDimitry Andric LPM2.addPass(LoopFullUnrollPass(Level.getSpeedupLevel(), 515349cc55cSDimitry Andric /* OnlyWhenForced= */ !PTO.LoopUnrolling, 516349cc55cSDimitry Andric PTO.ForgetAllSCEVInLoopUnroll)); 517349cc55cSDimitry Andric 518349cc55cSDimitry Andric for (auto &C : LoopOptimizerEndEPCallbacks) 519349cc55cSDimitry Andric C(LPM2, Level); 520349cc55cSDimitry Andric 521349cc55cSDimitry Andric // We provide the opt remark emitter pass for LICM to use. We only need to do 522349cc55cSDimitry Andric // this once as it is immutable. 523349cc55cSDimitry Andric FPM.addPass( 524349cc55cSDimitry Andric RequireAnalysisPass<OptimizationRemarkEmitterAnalysis, Function>()); 525349cc55cSDimitry Andric FPM.addPass(createFunctionToLoopPassAdaptor(std::move(LPM1), 526349cc55cSDimitry Andric /*UseMemorySSA=*/true, 527349cc55cSDimitry Andric /*UseBlockFrequencyInfo=*/true)); 528fb03ea46SDimitry Andric FPM.addPass( 529fb03ea46SDimitry Andric SimplifyCFGPass(SimplifyCFGOptions().convertSwitchRangeToICmp(true))); 530349cc55cSDimitry Andric FPM.addPass(InstCombinePass()); 531349cc55cSDimitry Andric // The loop passes in LPM2 (LoopIdiomRecognizePass, IndVarSimplifyPass, 532349cc55cSDimitry Andric // LoopDeletionPass and LoopFullUnrollPass) do not preserve MemorySSA. 533349cc55cSDimitry Andric // *All* loop passes must preserve it, in order to be able to use it. 534349cc55cSDimitry Andric FPM.addPass(createFunctionToLoopPassAdaptor(std::move(LPM2), 535349cc55cSDimitry Andric /*UseMemorySSA=*/false, 536349cc55cSDimitry Andric /*UseBlockFrequencyInfo=*/false)); 537349cc55cSDimitry Andric 538349cc55cSDimitry Andric // Delete small array after loop unroll. 539349cc55cSDimitry Andric FPM.addPass(SROAPass()); 540349cc55cSDimitry Andric 541349cc55cSDimitry Andric // The matrix extension can introduce large vector operations early, which can 542349cc55cSDimitry Andric // benefit from running vector-combine early on. 543349cc55cSDimitry Andric if (EnableMatrix) 544349cc55cSDimitry Andric FPM.addPass(VectorCombinePass(/*ScalarizationOnly=*/true)); 545349cc55cSDimitry Andric 546349cc55cSDimitry Andric // Eliminate redundancies. 547349cc55cSDimitry Andric FPM.addPass(MergedLoadStoreMotionPass()); 548349cc55cSDimitry Andric if (RunNewGVN) 549349cc55cSDimitry Andric FPM.addPass(NewGVNPass()); 550349cc55cSDimitry Andric else 551349cc55cSDimitry Andric FPM.addPass(GVNPass()); 552349cc55cSDimitry Andric 553349cc55cSDimitry Andric // Sparse conditional constant propagation. 554349cc55cSDimitry Andric // FIXME: It isn't clear why we do this *after* loop passes rather than 555349cc55cSDimitry Andric // before... 556349cc55cSDimitry Andric FPM.addPass(SCCPPass()); 557349cc55cSDimitry Andric 558349cc55cSDimitry Andric // Delete dead bit computations (instcombine runs after to fold away the dead 559349cc55cSDimitry Andric // computations, and then ADCE will run later to exploit any new DCE 560349cc55cSDimitry Andric // opportunities that creates). 561349cc55cSDimitry Andric FPM.addPass(BDCEPass()); 562349cc55cSDimitry Andric 563349cc55cSDimitry Andric // Run instcombine after redundancy and dead bit elimination to exploit 564349cc55cSDimitry Andric // opportunities opened up by them. 565349cc55cSDimitry Andric FPM.addPass(InstCombinePass()); 566349cc55cSDimitry Andric invokePeepholeEPCallbacks(FPM, Level); 567349cc55cSDimitry Andric 568349cc55cSDimitry Andric // Re-consider control flow based optimizations after redundancy elimination, 569349cc55cSDimitry Andric // redo DCE, etc. 570349cc55cSDimitry Andric if (EnableDFAJumpThreading && Level.getSizeLevel() == 0) 571349cc55cSDimitry Andric FPM.addPass(DFAJumpThreadingPass()); 572349cc55cSDimitry Andric 573349cc55cSDimitry Andric FPM.addPass(JumpThreadingPass()); 574349cc55cSDimitry Andric FPM.addPass(CorrelatedValuePropagationPass()); 575349cc55cSDimitry Andric 576349cc55cSDimitry Andric // Finally, do an expensive DCE pass to catch all the dead code exposed by 577349cc55cSDimitry Andric // the simplifications and basic cleanup after all the simplifications. 578349cc55cSDimitry Andric // TODO: Investigate if this is too expensive. 579349cc55cSDimitry Andric FPM.addPass(ADCEPass()); 580349cc55cSDimitry Andric 581349cc55cSDimitry Andric // Specially optimize memory movement as it doesn't look like dataflow in SSA. 582349cc55cSDimitry Andric FPM.addPass(MemCpyOptPass()); 583349cc55cSDimitry Andric 584349cc55cSDimitry Andric FPM.addPass(DSEPass()); 585349cc55cSDimitry Andric FPM.addPass(createFunctionToLoopPassAdaptor( 586fb03ea46SDimitry Andric LICMPass(PTO.LicmMssaOptCap, PTO.LicmMssaNoAccForPromotionCap, 587fb03ea46SDimitry Andric /*AllowSpeculation=*/true), 588349cc55cSDimitry Andric /*UseMemorySSA=*/true, /*UseBlockFrequencyInfo=*/true)); 589349cc55cSDimitry Andric 590349cc55cSDimitry Andric FPM.addPass(CoroElidePass()); 591349cc55cSDimitry Andric 592349cc55cSDimitry Andric for (auto &C : ScalarOptimizerLateEPCallbacks) 593349cc55cSDimitry Andric C(FPM, Level); 594349cc55cSDimitry Andric 595fb03ea46SDimitry Andric FPM.addPass(SimplifyCFGPass(SimplifyCFGOptions() 596fb03ea46SDimitry Andric .convertSwitchRangeToICmp(true) 597fb03ea46SDimitry Andric .hoistCommonInsts(true) 598fb03ea46SDimitry Andric .sinkCommonInsts(true))); 599349cc55cSDimitry Andric FPM.addPass(InstCombinePass()); 600349cc55cSDimitry Andric invokePeepholeEPCallbacks(FPM, Level); 601349cc55cSDimitry Andric 602349cc55cSDimitry Andric if (EnableCHR && Level == OptimizationLevel::O3 && PGOOpt && 603349cc55cSDimitry Andric (PGOOpt->Action == PGOOptions::IRUse || 604349cc55cSDimitry Andric PGOOpt->Action == PGOOptions::SampleUse)) 605349cc55cSDimitry Andric FPM.addPass(ControlHeightReductionPass()); 606349cc55cSDimitry Andric 607349cc55cSDimitry Andric return FPM; 608349cc55cSDimitry Andric } 609349cc55cSDimitry Andric 610349cc55cSDimitry Andric void PassBuilder::addRequiredLTOPreLinkPasses(ModulePassManager &MPM) { 611349cc55cSDimitry Andric MPM.addPass(CanonicalizeAliasesPass()); 612349cc55cSDimitry Andric MPM.addPass(NameAnonGlobalPass()); 613349cc55cSDimitry Andric } 614349cc55cSDimitry Andric 615349cc55cSDimitry Andric void PassBuilder::addPGOInstrPasses(ModulePassManager &MPM, 616349cc55cSDimitry Andric OptimizationLevel Level, bool RunProfileGen, 617349cc55cSDimitry Andric bool IsCS, std::string ProfileFile, 61881ad6265SDimitry Andric std::string ProfileRemappingFile, 61981ad6265SDimitry Andric ThinOrFullLTOPhase LTOPhase) { 620349cc55cSDimitry Andric assert(Level != OptimizationLevel::O0 && "Not expecting O0 here!"); 621349cc55cSDimitry Andric if (!IsCS && !DisablePreInliner) { 622349cc55cSDimitry Andric InlineParams IP; 623349cc55cSDimitry Andric 624349cc55cSDimitry Andric IP.DefaultThreshold = PreInlineThreshold; 625349cc55cSDimitry Andric 626349cc55cSDimitry Andric // FIXME: The hint threshold has the same value used by the regular inliner 627349cc55cSDimitry Andric // when not optimzing for size. This should probably be lowered after 628349cc55cSDimitry Andric // performance testing. 629349cc55cSDimitry Andric // FIXME: this comment is cargo culted from the old pass manager, revisit). 630349cc55cSDimitry Andric IP.HintThreshold = Level.isOptimizingForSize() ? PreInlineThreshold : 325; 63181ad6265SDimitry Andric ModuleInlinerWrapperPass MIWP( 63281ad6265SDimitry Andric IP, /* MandatoryFirst */ true, 63381ad6265SDimitry Andric InlineContext{LTOPhase, InlinePass::EarlyInliner}); 634349cc55cSDimitry Andric CGSCCPassManager &CGPipeline = MIWP.getPM(); 635349cc55cSDimitry Andric 636349cc55cSDimitry Andric FunctionPassManager FPM; 637349cc55cSDimitry Andric FPM.addPass(SROAPass()); 638349cc55cSDimitry Andric FPM.addPass(EarlyCSEPass()); // Catch trivial redundancies. 639fb03ea46SDimitry Andric FPM.addPass(SimplifyCFGPass(SimplifyCFGOptions().convertSwitchRangeToICmp( 640fb03ea46SDimitry Andric true))); // Merge & remove basic blocks. 641349cc55cSDimitry Andric FPM.addPass(InstCombinePass()); // Combine silly sequences. 642349cc55cSDimitry Andric invokePeepholeEPCallbacks(FPM, Level); 643349cc55cSDimitry Andric 644349cc55cSDimitry Andric CGPipeline.addPass(createCGSCCToFunctionPassAdaptor( 645349cc55cSDimitry Andric std::move(FPM), PTO.EagerlyInvalidateAnalyses)); 646349cc55cSDimitry Andric 647349cc55cSDimitry Andric MPM.addPass(std::move(MIWP)); 648349cc55cSDimitry Andric 649349cc55cSDimitry Andric // Delete anything that is now dead to make sure that we don't instrument 650349cc55cSDimitry Andric // dead code. Instrumentation can end up keeping dead code around and 651349cc55cSDimitry Andric // dramatically increase code size. 652349cc55cSDimitry Andric MPM.addPass(GlobalDCEPass()); 653349cc55cSDimitry Andric } 654349cc55cSDimitry Andric 655349cc55cSDimitry Andric if (!RunProfileGen) { 656349cc55cSDimitry Andric assert(!ProfileFile.empty() && "Profile use expecting a profile file!"); 657349cc55cSDimitry Andric MPM.addPass(PGOInstrumentationUse(ProfileFile, ProfileRemappingFile, IsCS)); 658349cc55cSDimitry Andric // Cache ProfileSummaryAnalysis once to avoid the potential need to insert 659349cc55cSDimitry Andric // RequireAnalysisPass for PSI before subsequent non-module passes. 660349cc55cSDimitry Andric MPM.addPass(RequireAnalysisPass<ProfileSummaryAnalysis, Module>()); 661349cc55cSDimitry Andric return; 662349cc55cSDimitry Andric } 663349cc55cSDimitry Andric 664349cc55cSDimitry Andric // Perform PGO instrumentation. 665349cc55cSDimitry Andric MPM.addPass(PGOInstrumentationGen(IsCS)); 666349cc55cSDimitry Andric 667349cc55cSDimitry Andric // Disable header duplication in loop rotation at -Oz. 66881ad6265SDimitry Andric MPM.addPass(createModuleToFunctionPassAdaptor( 66981ad6265SDimitry Andric createFunctionToLoopPassAdaptor( 67081ad6265SDimitry Andric LoopRotatePass(Level != OptimizationLevel::Oz), 67181ad6265SDimitry Andric /*UseMemorySSA=*/false, 67281ad6265SDimitry Andric /*UseBlockFrequencyInfo=*/false), 673349cc55cSDimitry Andric PTO.EagerlyInvalidateAnalyses)); 674349cc55cSDimitry Andric 675349cc55cSDimitry Andric // Add the profile lowering pass. 676349cc55cSDimitry Andric InstrProfOptions Options; 677349cc55cSDimitry Andric if (!ProfileFile.empty()) 678349cc55cSDimitry Andric Options.InstrProfileOutput = ProfileFile; 679349cc55cSDimitry Andric // Do counter promotion at Level greater than O0. 680349cc55cSDimitry Andric Options.DoCounterPromotion = true; 681349cc55cSDimitry Andric Options.UseBFIInPromotion = IsCS; 682349cc55cSDimitry Andric MPM.addPass(InstrProfiling(Options, IsCS)); 683349cc55cSDimitry Andric } 684349cc55cSDimitry Andric 685349cc55cSDimitry Andric void PassBuilder::addPGOInstrPassesForO0(ModulePassManager &MPM, 686349cc55cSDimitry Andric bool RunProfileGen, bool IsCS, 687349cc55cSDimitry Andric std::string ProfileFile, 688349cc55cSDimitry Andric std::string ProfileRemappingFile) { 689349cc55cSDimitry Andric if (!RunProfileGen) { 690349cc55cSDimitry Andric assert(!ProfileFile.empty() && "Profile use expecting a profile file!"); 691349cc55cSDimitry Andric MPM.addPass(PGOInstrumentationUse(ProfileFile, ProfileRemappingFile, IsCS)); 692349cc55cSDimitry Andric // Cache ProfileSummaryAnalysis once to avoid the potential need to insert 693349cc55cSDimitry Andric // RequireAnalysisPass for PSI before subsequent non-module passes. 694349cc55cSDimitry Andric MPM.addPass(RequireAnalysisPass<ProfileSummaryAnalysis, Module>()); 695349cc55cSDimitry Andric return; 696349cc55cSDimitry Andric } 697349cc55cSDimitry Andric 698349cc55cSDimitry Andric // Perform PGO instrumentation. 699349cc55cSDimitry Andric MPM.addPass(PGOInstrumentationGen(IsCS)); 700349cc55cSDimitry Andric // Add the profile lowering pass. 701349cc55cSDimitry Andric InstrProfOptions Options; 702349cc55cSDimitry Andric if (!ProfileFile.empty()) 703349cc55cSDimitry Andric Options.InstrProfileOutput = ProfileFile; 704349cc55cSDimitry Andric // Do not do counter promotion at O0. 705349cc55cSDimitry Andric Options.DoCounterPromotion = false; 706349cc55cSDimitry Andric Options.UseBFIInPromotion = IsCS; 707349cc55cSDimitry Andric MPM.addPass(InstrProfiling(Options, IsCS)); 708349cc55cSDimitry Andric } 709349cc55cSDimitry Andric 710349cc55cSDimitry Andric static InlineParams getInlineParamsFromOptLevel(OptimizationLevel Level) { 711349cc55cSDimitry Andric return getInlineParams(Level.getSpeedupLevel(), Level.getSizeLevel()); 712349cc55cSDimitry Andric } 713349cc55cSDimitry Andric 714349cc55cSDimitry Andric ModuleInlinerWrapperPass 715349cc55cSDimitry Andric PassBuilder::buildInlinerPipeline(OptimizationLevel Level, 716349cc55cSDimitry Andric ThinOrFullLTOPhase Phase) { 717349cc55cSDimitry Andric InlineParams IP = getInlineParamsFromOptLevel(Level); 71881ad6265SDimitry Andric // For PreLinkThinLTO + SamplePGO, set hot-caller threshold to 0 to 71981ad6265SDimitry Andric // disable hot callsite inline (as much as possible [1]) because it makes 72081ad6265SDimitry Andric // profile annotation in the backend inaccurate. 72181ad6265SDimitry Andric // 72281ad6265SDimitry Andric // [1] Note the cost of a function could be below zero due to erased 72381ad6265SDimitry Andric // prologue / epilogue. 724349cc55cSDimitry Andric if (Phase == ThinOrFullLTOPhase::ThinLTOPreLink && PGOOpt && 725349cc55cSDimitry Andric PGOOpt->Action == PGOOptions::SampleUse) 726349cc55cSDimitry Andric IP.HotCallSiteThreshold = 0; 727349cc55cSDimitry Andric 728349cc55cSDimitry Andric if (PGOOpt) 729349cc55cSDimitry Andric IP.EnableDeferral = EnablePGOInlineDeferral; 730349cc55cSDimitry Andric 73181ad6265SDimitry Andric ModuleInlinerWrapperPass MIWP( 73281ad6265SDimitry Andric IP, PerformMandatoryInliningsFirst, 73381ad6265SDimitry Andric InlineContext{Phase, InlinePass::CGSCCInliner}, 734349cc55cSDimitry Andric UseInlineAdvisor, MaxDevirtIterations); 735349cc55cSDimitry Andric 736349cc55cSDimitry Andric // Require the GlobalsAA analysis for the module so we can query it within 737349cc55cSDimitry Andric // the CGSCC pipeline. 738349cc55cSDimitry Andric MIWP.addModulePass(RequireAnalysisPass<GlobalsAA, Module>()); 739349cc55cSDimitry Andric // Invalidate AAManager so it can be recreated and pick up the newly available 740349cc55cSDimitry Andric // GlobalsAA. 741349cc55cSDimitry Andric MIWP.addModulePass( 742349cc55cSDimitry Andric createModuleToFunctionPassAdaptor(InvalidateAnalysisPass<AAManager>())); 743349cc55cSDimitry Andric 744349cc55cSDimitry Andric // Require the ProfileSummaryAnalysis for the module so we can query it within 745349cc55cSDimitry Andric // the inliner pass. 746349cc55cSDimitry Andric MIWP.addModulePass(RequireAnalysisPass<ProfileSummaryAnalysis, Module>()); 747349cc55cSDimitry Andric 748349cc55cSDimitry Andric // Now begin the main postorder CGSCC pipeline. 749349cc55cSDimitry Andric // FIXME: The current CGSCC pipeline has its origins in the legacy pass 750349cc55cSDimitry Andric // manager and trying to emulate its precise behavior. Much of this doesn't 751349cc55cSDimitry Andric // make a lot of sense and we should revisit the core CGSCC structure. 752349cc55cSDimitry Andric CGSCCPassManager &MainCGPipeline = MIWP.getPM(); 753349cc55cSDimitry Andric 754349cc55cSDimitry Andric // Note: historically, the PruneEH pass was run first to deduce nounwind and 755349cc55cSDimitry Andric // generally clean up exception handling overhead. It isn't clear this is 756349cc55cSDimitry Andric // valuable as the inliner doesn't currently care whether it is inlining an 757349cc55cSDimitry Andric // invoke or a call. 758349cc55cSDimitry Andric 759349cc55cSDimitry Andric if (AttributorRun & AttributorRunOption::CGSCC) 760349cc55cSDimitry Andric MainCGPipeline.addPass(AttributorCGSCCPass()); 761349cc55cSDimitry Andric 762349cc55cSDimitry Andric // Now deduce any function attributes based in the current code. 763349cc55cSDimitry Andric MainCGPipeline.addPass(PostOrderFunctionAttrsPass()); 764349cc55cSDimitry Andric 765349cc55cSDimitry Andric // When at O3 add argument promotion to the pass pipeline. 766349cc55cSDimitry Andric // FIXME: It isn't at all clear why this should be limited to O3. 767349cc55cSDimitry Andric if (Level == OptimizationLevel::O3) 768349cc55cSDimitry Andric MainCGPipeline.addPass(ArgumentPromotionPass()); 769349cc55cSDimitry Andric 770349cc55cSDimitry Andric // Try to perform OpenMP specific optimizations. This is a (quick!) no-op if 771349cc55cSDimitry Andric // there are no OpenMP runtime calls present in the module. 772349cc55cSDimitry Andric if (Level == OptimizationLevel::O2 || Level == OptimizationLevel::O3) 773349cc55cSDimitry Andric MainCGPipeline.addPass(OpenMPOptCGSCCPass()); 774349cc55cSDimitry Andric 775349cc55cSDimitry Andric for (auto &C : CGSCCOptimizerLateEPCallbacks) 776349cc55cSDimitry Andric C(MainCGPipeline, Level); 777349cc55cSDimitry Andric 778349cc55cSDimitry Andric // Lastly, add the core function simplification pipeline nested inside the 779349cc55cSDimitry Andric // CGSCC walk. 780349cc55cSDimitry Andric MainCGPipeline.addPass(createCGSCCToFunctionPassAdaptor( 781349cc55cSDimitry Andric buildFunctionSimplificationPipeline(Level, Phase), 782349cc55cSDimitry Andric PTO.EagerlyInvalidateAnalyses, EnableNoRerunSimplificationPipeline)); 783349cc55cSDimitry Andric 784349cc55cSDimitry Andric MainCGPipeline.addPass(CoroSplitPass(Level != OptimizationLevel::O0)); 785349cc55cSDimitry Andric 786349cc55cSDimitry Andric if (EnableNoRerunSimplificationPipeline) 787349cc55cSDimitry Andric MIWP.addLateModulePass(createModuleToFunctionPassAdaptor( 788349cc55cSDimitry Andric InvalidateAnalysisPass<ShouldNotRunFunctionPassesAnalysis>())); 789349cc55cSDimitry Andric 790349cc55cSDimitry Andric return MIWP; 791349cc55cSDimitry Andric } 792349cc55cSDimitry Andric 7930eae32dcSDimitry Andric ModulePassManager 794349cc55cSDimitry Andric PassBuilder::buildModuleInlinerPipeline(OptimizationLevel Level, 795349cc55cSDimitry Andric ThinOrFullLTOPhase Phase) { 7960eae32dcSDimitry Andric ModulePassManager MPM; 7970eae32dcSDimitry Andric 798349cc55cSDimitry Andric InlineParams IP = getInlineParamsFromOptLevel(Level); 79981ad6265SDimitry Andric // For PreLinkThinLTO + SamplePGO, set hot-caller threshold to 0 to 80081ad6265SDimitry Andric // disable hot callsite inline (as much as possible [1]) because it makes 80181ad6265SDimitry Andric // profile annotation in the backend inaccurate. 80281ad6265SDimitry Andric // 80381ad6265SDimitry Andric // [1] Note the cost of a function could be below zero due to erased 80481ad6265SDimitry Andric // prologue / epilogue. 805349cc55cSDimitry Andric if (Phase == ThinOrFullLTOPhase::ThinLTOPreLink && PGOOpt && 806349cc55cSDimitry Andric PGOOpt->Action == PGOOptions::SampleUse) 807349cc55cSDimitry Andric IP.HotCallSiteThreshold = 0; 808349cc55cSDimitry Andric 809349cc55cSDimitry Andric if (PGOOpt) 810349cc55cSDimitry Andric IP.EnableDeferral = EnablePGOInlineDeferral; 811349cc55cSDimitry Andric 812349cc55cSDimitry Andric // The inline deferral logic is used to avoid losing some 813349cc55cSDimitry Andric // inlining chance in future. It is helpful in SCC inliner, in which 814349cc55cSDimitry Andric // inlining is processed in bottom-up order. 815349cc55cSDimitry Andric // While in module inliner, the inlining order is a priority-based order 816349cc55cSDimitry Andric // by default. The inline deferral is unnecessary there. So we disable the 817349cc55cSDimitry Andric // inline deferral logic in module inliner. 818349cc55cSDimitry Andric IP.EnableDeferral = false; 819349cc55cSDimitry Andric 82081ad6265SDimitry Andric MPM.addPass(ModuleInlinerPass(IP, UseInlineAdvisor, Phase)); 8210eae32dcSDimitry Andric 8220eae32dcSDimitry Andric MPM.addPass(createModuleToFunctionPassAdaptor( 8230eae32dcSDimitry Andric buildFunctionSimplificationPipeline(Level, Phase), 8240eae32dcSDimitry Andric PTO.EagerlyInvalidateAnalyses)); 8250eae32dcSDimitry Andric 8260eae32dcSDimitry Andric MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor( 8270eae32dcSDimitry Andric CoroSplitPass(Level != OptimizationLevel::O0))); 8280eae32dcSDimitry Andric 8290eae32dcSDimitry Andric return MPM; 830349cc55cSDimitry Andric } 831349cc55cSDimitry Andric 832349cc55cSDimitry Andric ModulePassManager 833349cc55cSDimitry Andric PassBuilder::buildModuleSimplificationPipeline(OptimizationLevel Level, 834349cc55cSDimitry Andric ThinOrFullLTOPhase Phase) { 835349cc55cSDimitry Andric ModulePassManager MPM; 836349cc55cSDimitry Andric 837349cc55cSDimitry Andric // Place pseudo probe instrumentation as the first pass of the pipeline to 838349cc55cSDimitry Andric // minimize the impact of optimization changes. 839349cc55cSDimitry Andric if (PGOOpt && PGOOpt->PseudoProbeForProfiling && 840349cc55cSDimitry Andric Phase != ThinOrFullLTOPhase::ThinLTOPostLink) 841349cc55cSDimitry Andric MPM.addPass(SampleProfileProbePass(TM)); 842349cc55cSDimitry Andric 843349cc55cSDimitry Andric bool HasSampleProfile = PGOOpt && (PGOOpt->Action == PGOOptions::SampleUse); 844349cc55cSDimitry Andric 845349cc55cSDimitry Andric // In ThinLTO mode, when flattened profile is used, all the available 846349cc55cSDimitry Andric // profile information will be annotated in PreLink phase so there is 847349cc55cSDimitry Andric // no need to load the profile again in PostLink. 848349cc55cSDimitry Andric bool LoadSampleProfile = 849349cc55cSDimitry Andric HasSampleProfile && 850349cc55cSDimitry Andric !(FlattenedProfileUsed && Phase == ThinOrFullLTOPhase::ThinLTOPostLink); 851349cc55cSDimitry Andric 852349cc55cSDimitry Andric // During the ThinLTO backend phase we perform early indirect call promotion 853349cc55cSDimitry Andric // here, before globalopt. Otherwise imported available_externally functions 854349cc55cSDimitry Andric // look unreferenced and are removed. If we are going to load the sample 855349cc55cSDimitry Andric // profile then defer until later. 856349cc55cSDimitry Andric // TODO: See if we can move later and consolidate with the location where 857349cc55cSDimitry Andric // we perform ICP when we are loading a sample profile. 858349cc55cSDimitry Andric // TODO: We pass HasSampleProfile (whether there was a sample profile file 859349cc55cSDimitry Andric // passed to the compile) to the SamplePGO flag of ICP. This is used to 860349cc55cSDimitry Andric // determine whether the new direct calls are annotated with prof metadata. 861349cc55cSDimitry Andric // Ideally this should be determined from whether the IR is annotated with 862349cc55cSDimitry Andric // sample profile, and not whether the a sample profile was provided on the 863349cc55cSDimitry Andric // command line. E.g. for flattened profiles where we will not be reloading 864349cc55cSDimitry Andric // the sample profile in the ThinLTO backend, we ideally shouldn't have to 865349cc55cSDimitry Andric // provide the sample profile file. 866349cc55cSDimitry Andric if (Phase == ThinOrFullLTOPhase::ThinLTOPostLink && !LoadSampleProfile) 867349cc55cSDimitry Andric MPM.addPass(PGOIndirectCallPromotion(true /* InLTO */, HasSampleProfile)); 868349cc55cSDimitry Andric 869349cc55cSDimitry Andric // Do basic inference of function attributes from known properties of system 870349cc55cSDimitry Andric // libraries and other oracles. 871349cc55cSDimitry Andric MPM.addPass(InferFunctionAttrsPass()); 87281ad6265SDimitry Andric MPM.addPass(CoroEarlyPass()); 873349cc55cSDimitry Andric 874349cc55cSDimitry Andric // Create an early function pass manager to cleanup the output of the 875349cc55cSDimitry Andric // frontend. 876349cc55cSDimitry Andric FunctionPassManager EarlyFPM; 877349cc55cSDimitry Andric // Lower llvm.expect to metadata before attempting transforms. 878349cc55cSDimitry Andric // Compare/branch metadata may alter the behavior of passes like SimplifyCFG. 879349cc55cSDimitry Andric EarlyFPM.addPass(LowerExpectIntrinsicPass()); 880349cc55cSDimitry Andric EarlyFPM.addPass(SimplifyCFGPass()); 881349cc55cSDimitry Andric EarlyFPM.addPass(SROAPass()); 882349cc55cSDimitry Andric EarlyFPM.addPass(EarlyCSEPass()); 883349cc55cSDimitry Andric if (Level == OptimizationLevel::O3) 884349cc55cSDimitry Andric EarlyFPM.addPass(CallSiteSplittingPass()); 885349cc55cSDimitry Andric 886349cc55cSDimitry Andric // In SamplePGO ThinLTO backend, we need instcombine before profile annotation 887349cc55cSDimitry Andric // to convert bitcast to direct calls so that they can be inlined during the 888349cc55cSDimitry Andric // profile annotation prepration step. 889349cc55cSDimitry Andric // More details about SamplePGO design can be found in: 890349cc55cSDimitry Andric // https://research.google.com/pubs/pub45290.html 891349cc55cSDimitry Andric // FIXME: revisit how SampleProfileLoad/Inliner/ICP is structured. 892349cc55cSDimitry Andric if (LoadSampleProfile) 893349cc55cSDimitry Andric EarlyFPM.addPass(InstCombinePass()); 894349cc55cSDimitry Andric MPM.addPass(createModuleToFunctionPassAdaptor(std::move(EarlyFPM), 895349cc55cSDimitry Andric PTO.EagerlyInvalidateAnalyses)); 896349cc55cSDimitry Andric 897349cc55cSDimitry Andric if (LoadSampleProfile) { 898349cc55cSDimitry Andric // Annotate sample profile right after early FPM to ensure freshness of 899349cc55cSDimitry Andric // the debug info. 900349cc55cSDimitry Andric MPM.addPass(SampleProfileLoaderPass(PGOOpt->ProfileFile, 901349cc55cSDimitry Andric PGOOpt->ProfileRemappingFile, Phase)); 902349cc55cSDimitry Andric // Cache ProfileSummaryAnalysis once to avoid the potential need to insert 903349cc55cSDimitry Andric // RequireAnalysisPass for PSI before subsequent non-module passes. 904349cc55cSDimitry Andric MPM.addPass(RequireAnalysisPass<ProfileSummaryAnalysis, Module>()); 905349cc55cSDimitry Andric // Do not invoke ICP in the LTOPrelink phase as it makes it hard 906349cc55cSDimitry Andric // for the profile annotation to be accurate in the LTO backend. 907349cc55cSDimitry Andric if (Phase != ThinOrFullLTOPhase::ThinLTOPreLink && 908349cc55cSDimitry Andric Phase != ThinOrFullLTOPhase::FullLTOPreLink) 909349cc55cSDimitry Andric // We perform early indirect call promotion here, before globalopt. 910349cc55cSDimitry Andric // This is important for the ThinLTO backend phase because otherwise 911349cc55cSDimitry Andric // imported available_externally functions look unreferenced and are 912349cc55cSDimitry Andric // removed. 913349cc55cSDimitry Andric MPM.addPass( 914349cc55cSDimitry Andric PGOIndirectCallPromotion(true /* IsInLTO */, true /* SamplePGO */)); 915349cc55cSDimitry Andric } 916349cc55cSDimitry Andric 917349cc55cSDimitry Andric // Try to perform OpenMP specific optimizations on the module. This is a 918349cc55cSDimitry Andric // (quick!) no-op if there are no OpenMP runtime calls present in the module. 919349cc55cSDimitry Andric if (Level != OptimizationLevel::O0) 920349cc55cSDimitry Andric MPM.addPass(OpenMPOptPass()); 921349cc55cSDimitry Andric 922349cc55cSDimitry Andric if (AttributorRun & AttributorRunOption::MODULE) 923349cc55cSDimitry Andric MPM.addPass(AttributorPass()); 924349cc55cSDimitry Andric 925349cc55cSDimitry Andric // Lower type metadata and the type.test intrinsic in the ThinLTO 926349cc55cSDimitry Andric // post link pipeline after ICP. This is to enable usage of the type 927349cc55cSDimitry Andric // tests in ICP sequences. 928349cc55cSDimitry Andric if (Phase == ThinOrFullLTOPhase::ThinLTOPostLink) 929349cc55cSDimitry Andric MPM.addPass(LowerTypeTestsPass(nullptr, nullptr, true)); 930349cc55cSDimitry Andric 931349cc55cSDimitry Andric for (auto &C : PipelineEarlySimplificationEPCallbacks) 932349cc55cSDimitry Andric C(MPM, Level); 933349cc55cSDimitry Andric 934349cc55cSDimitry Andric // Specialize functions with IPSCCP. 935349cc55cSDimitry Andric if (EnableFunctionSpecialization && Level == OptimizationLevel::O3) 936349cc55cSDimitry Andric MPM.addPass(FunctionSpecializationPass()); 937349cc55cSDimitry Andric 938349cc55cSDimitry Andric // Interprocedural constant propagation now that basic cleanup has occurred 939349cc55cSDimitry Andric // and prior to optimizing globals. 940349cc55cSDimitry Andric // FIXME: This position in the pipeline hasn't been carefully considered in 941349cc55cSDimitry Andric // years, it should be re-analyzed. 942349cc55cSDimitry Andric MPM.addPass(IPSCCPPass()); 943349cc55cSDimitry Andric 944349cc55cSDimitry Andric // Attach metadata to indirect call sites indicating the set of functions 945349cc55cSDimitry Andric // they may target at run-time. This should follow IPSCCP. 946349cc55cSDimitry Andric MPM.addPass(CalledValuePropagationPass()); 947349cc55cSDimitry Andric 948349cc55cSDimitry Andric // Optimize globals to try and fold them into constants. 949349cc55cSDimitry Andric MPM.addPass(GlobalOptPass()); 950349cc55cSDimitry Andric 951349cc55cSDimitry Andric // Promote any localized globals to SSA registers. 952349cc55cSDimitry Andric // FIXME: Should this instead by a run of SROA? 953349cc55cSDimitry Andric // FIXME: We should probably run instcombine and simplifycfg afterward to 954349cc55cSDimitry Andric // delete control flows that are dead once globals have been folded to 955349cc55cSDimitry Andric // constants. 956349cc55cSDimitry Andric MPM.addPass(createModuleToFunctionPassAdaptor(PromotePass())); 957349cc55cSDimitry Andric 958349cc55cSDimitry Andric // Remove any dead arguments exposed by cleanups and constant folding 959349cc55cSDimitry Andric // globals. 960349cc55cSDimitry Andric MPM.addPass(DeadArgumentEliminationPass()); 961349cc55cSDimitry Andric 962349cc55cSDimitry Andric // Create a small function pass pipeline to cleanup after all the global 963349cc55cSDimitry Andric // optimizations. 964349cc55cSDimitry Andric FunctionPassManager GlobalCleanupPM; 965349cc55cSDimitry Andric GlobalCleanupPM.addPass(InstCombinePass()); 966349cc55cSDimitry Andric invokePeepholeEPCallbacks(GlobalCleanupPM, Level); 967349cc55cSDimitry Andric 968fb03ea46SDimitry Andric GlobalCleanupPM.addPass( 969fb03ea46SDimitry Andric SimplifyCFGPass(SimplifyCFGOptions().convertSwitchRangeToICmp(true))); 970349cc55cSDimitry Andric MPM.addPass(createModuleToFunctionPassAdaptor(std::move(GlobalCleanupPM), 971349cc55cSDimitry Andric PTO.EagerlyInvalidateAnalyses)); 972349cc55cSDimitry Andric 973349cc55cSDimitry Andric // Add all the requested passes for instrumentation PGO, if requested. 974349cc55cSDimitry Andric if (PGOOpt && Phase != ThinOrFullLTOPhase::ThinLTOPostLink && 975349cc55cSDimitry Andric (PGOOpt->Action == PGOOptions::IRInstr || 976349cc55cSDimitry Andric PGOOpt->Action == PGOOptions::IRUse)) { 977349cc55cSDimitry Andric addPGOInstrPasses(MPM, Level, 978349cc55cSDimitry Andric /* RunProfileGen */ PGOOpt->Action == PGOOptions::IRInstr, 979349cc55cSDimitry Andric /* IsCS */ false, PGOOpt->ProfileFile, 98081ad6265SDimitry Andric PGOOpt->ProfileRemappingFile, Phase); 981349cc55cSDimitry Andric MPM.addPass(PGOIndirectCallPromotion(false, false)); 982349cc55cSDimitry Andric } 983349cc55cSDimitry Andric if (PGOOpt && Phase != ThinOrFullLTOPhase::ThinLTOPostLink && 984349cc55cSDimitry Andric PGOOpt->CSAction == PGOOptions::CSIRInstr) 985349cc55cSDimitry Andric MPM.addPass(PGOInstrumentationGenCreateVar(PGOOpt->CSProfileGenFile)); 986349cc55cSDimitry Andric 987349cc55cSDimitry Andric // Synthesize function entry counts for non-PGO compilation. 988349cc55cSDimitry Andric if (EnableSyntheticCounts && !PGOOpt) 989349cc55cSDimitry Andric MPM.addPass(SyntheticCountsPropagation()); 990349cc55cSDimitry Andric 991349cc55cSDimitry Andric if (EnableModuleInliner) 992349cc55cSDimitry Andric MPM.addPass(buildModuleInlinerPipeline(Level, Phase)); 993349cc55cSDimitry Andric else 994349cc55cSDimitry Andric MPM.addPass(buildInlinerPipeline(Level, Phase)); 995349cc55cSDimitry Andric 99681ad6265SDimitry Andric MPM.addPass(CoroCleanupPass()); 99781ad6265SDimitry Andric 998349cc55cSDimitry Andric if (EnableMemProfiler && Phase != ThinOrFullLTOPhase::ThinLTOPreLink) { 999349cc55cSDimitry Andric MPM.addPass(createModuleToFunctionPassAdaptor(MemProfilerPass())); 1000349cc55cSDimitry Andric MPM.addPass(ModuleMemProfilerPass()); 1001349cc55cSDimitry Andric } 1002349cc55cSDimitry Andric 1003349cc55cSDimitry Andric return MPM; 1004349cc55cSDimitry Andric } 1005349cc55cSDimitry Andric 1006349cc55cSDimitry Andric /// TODO: Should LTO cause any differences to this set of passes? 1007349cc55cSDimitry Andric void PassBuilder::addVectorPasses(OptimizationLevel Level, 1008349cc55cSDimitry Andric FunctionPassManager &FPM, bool IsFullLTO) { 1009349cc55cSDimitry Andric FPM.addPass(LoopVectorizePass( 1010349cc55cSDimitry Andric LoopVectorizeOptions(!PTO.LoopInterleaving, !PTO.LoopVectorization))); 1011349cc55cSDimitry Andric 1012349cc55cSDimitry Andric if (IsFullLTO) { 1013349cc55cSDimitry Andric // The vectorizer may have significantly shortened a loop body; unroll 1014349cc55cSDimitry Andric // again. Unroll small loops to hide loop backedge latency and saturate any 1015349cc55cSDimitry Andric // parallel execution resources of an out-of-order processor. We also then 1016349cc55cSDimitry Andric // need to clean up redundancies and loop invariant code. 1017349cc55cSDimitry Andric // FIXME: It would be really good to use a loop-integrated instruction 1018349cc55cSDimitry Andric // combiner for cleanup here so that the unrolling and LICM can be pipelined 1019349cc55cSDimitry Andric // across the loop nests. 1020349cc55cSDimitry Andric // We do UnrollAndJam in a separate LPM to ensure it happens before unroll 1021349cc55cSDimitry Andric if (EnableUnrollAndJam && PTO.LoopUnrolling) 1022349cc55cSDimitry Andric FPM.addPass(createFunctionToLoopPassAdaptor( 1023349cc55cSDimitry Andric LoopUnrollAndJamPass(Level.getSpeedupLevel()))); 1024349cc55cSDimitry Andric FPM.addPass(LoopUnrollPass(LoopUnrollOptions( 1025349cc55cSDimitry Andric Level.getSpeedupLevel(), /*OnlyWhenForced=*/!PTO.LoopUnrolling, 1026349cc55cSDimitry Andric PTO.ForgetAllSCEVInLoopUnroll))); 1027349cc55cSDimitry Andric FPM.addPass(WarnMissedTransformationsPass()); 1028349cc55cSDimitry Andric } 1029349cc55cSDimitry Andric 1030349cc55cSDimitry Andric if (!IsFullLTO) { 1031349cc55cSDimitry Andric // Eliminate loads by forwarding stores from the previous iteration to loads 1032349cc55cSDimitry Andric // of the current iteration. 1033349cc55cSDimitry Andric FPM.addPass(LoopLoadEliminationPass()); 1034349cc55cSDimitry Andric } 1035349cc55cSDimitry Andric // Cleanup after the loop optimization passes. 1036349cc55cSDimitry Andric FPM.addPass(InstCombinePass()); 1037349cc55cSDimitry Andric 1038349cc55cSDimitry Andric if (Level.getSpeedupLevel() > 1 && ExtraVectorizerPasses) { 10390eae32dcSDimitry Andric ExtraVectorPassManager ExtraPasses; 1040349cc55cSDimitry Andric // At higher optimization levels, try to clean up any runtime overlap and 1041349cc55cSDimitry Andric // alignment checks inserted by the vectorizer. We want to track correlated 1042349cc55cSDimitry Andric // runtime checks for two inner loops in the same outer loop, fold any 1043349cc55cSDimitry Andric // common computations, hoist loop-invariant aspects out of any outer loop, 1044349cc55cSDimitry Andric // and unswitch the runtime checks if possible. Once hoisted, we may have 1045349cc55cSDimitry Andric // dead (or speculatable) control flows or more combining opportunities. 10460eae32dcSDimitry Andric ExtraPasses.addPass(EarlyCSEPass()); 10470eae32dcSDimitry Andric ExtraPasses.addPass(CorrelatedValuePropagationPass()); 10480eae32dcSDimitry Andric ExtraPasses.addPass(InstCombinePass()); 1049349cc55cSDimitry Andric LoopPassManager LPM; 1050fb03ea46SDimitry Andric LPM.addPass(LICMPass(PTO.LicmMssaOptCap, PTO.LicmMssaNoAccForPromotionCap, 1051fb03ea46SDimitry Andric /*AllowSpeculation=*/true)); 1052349cc55cSDimitry Andric LPM.addPass(SimpleLoopUnswitchPass(/* NonTrivial */ Level == 1053349cc55cSDimitry Andric OptimizationLevel::O3)); 10540eae32dcSDimitry Andric ExtraPasses.addPass( 1055349cc55cSDimitry Andric RequireAnalysisPass<OptimizationRemarkEmitterAnalysis, Function>()); 10560eae32dcSDimitry Andric ExtraPasses.addPass( 1057349cc55cSDimitry Andric createFunctionToLoopPassAdaptor(std::move(LPM), /*UseMemorySSA=*/true, 1058349cc55cSDimitry Andric /*UseBlockFrequencyInfo=*/true)); 1059fb03ea46SDimitry Andric ExtraPasses.addPass( 1060fb03ea46SDimitry Andric SimplifyCFGPass(SimplifyCFGOptions().convertSwitchRangeToICmp(true))); 10610eae32dcSDimitry Andric ExtraPasses.addPass(InstCombinePass()); 10620eae32dcSDimitry Andric FPM.addPass(std::move(ExtraPasses)); 1063349cc55cSDimitry Andric } 1064349cc55cSDimitry Andric 1065349cc55cSDimitry Andric // Now that we've formed fast to execute loop structures, we do further 1066349cc55cSDimitry Andric // optimizations. These are run afterward as they might block doing complex 1067349cc55cSDimitry Andric // analyses and transforms such as what are needed for loop vectorization. 1068349cc55cSDimitry Andric 1069349cc55cSDimitry Andric // Cleanup after loop vectorization, etc. Simplification passes like CVP and 1070349cc55cSDimitry Andric // GVN, loop transforms, and others have already run, so it's now better to 1071349cc55cSDimitry Andric // convert to more optimized IR using more aggressive simplify CFG options. 1072349cc55cSDimitry Andric // The extra sinking transform can create larger basic blocks, so do this 1073349cc55cSDimitry Andric // before SLP vectorization. 1074349cc55cSDimitry Andric FPM.addPass(SimplifyCFGPass(SimplifyCFGOptions() 1075349cc55cSDimitry Andric .forwardSwitchCondToPhi(true) 1076fb03ea46SDimitry Andric .convertSwitchRangeToICmp(true) 1077349cc55cSDimitry Andric .convertSwitchToLookupTable(true) 1078349cc55cSDimitry Andric .needCanonicalLoops(false) 1079349cc55cSDimitry Andric .hoistCommonInsts(true) 1080349cc55cSDimitry Andric .sinkCommonInsts(true))); 1081349cc55cSDimitry Andric 1082349cc55cSDimitry Andric if (IsFullLTO) { 1083349cc55cSDimitry Andric FPM.addPass(SCCPPass()); 1084349cc55cSDimitry Andric FPM.addPass(InstCombinePass()); 1085349cc55cSDimitry Andric FPM.addPass(BDCEPass()); 1086349cc55cSDimitry Andric } 1087349cc55cSDimitry Andric 1088349cc55cSDimitry Andric // Optimize parallel scalar instruction chains into SIMD instructions. 1089349cc55cSDimitry Andric if (PTO.SLPVectorization) { 1090349cc55cSDimitry Andric FPM.addPass(SLPVectorizerPass()); 1091349cc55cSDimitry Andric if (Level.getSpeedupLevel() > 1 && ExtraVectorizerPasses) { 1092349cc55cSDimitry Andric FPM.addPass(EarlyCSEPass()); 1093349cc55cSDimitry Andric } 1094349cc55cSDimitry Andric } 1095349cc55cSDimitry Andric // Enhance/cleanup vector code. 1096349cc55cSDimitry Andric FPM.addPass(VectorCombinePass()); 1097349cc55cSDimitry Andric 1098349cc55cSDimitry Andric if (!IsFullLTO) { 1099349cc55cSDimitry Andric FPM.addPass(InstCombinePass()); 1100349cc55cSDimitry Andric // Unroll small loops to hide loop backedge latency and saturate any 1101349cc55cSDimitry Andric // parallel execution resources of an out-of-order processor. We also then 1102349cc55cSDimitry Andric // need to clean up redundancies and loop invariant code. 1103349cc55cSDimitry Andric // FIXME: It would be really good to use a loop-integrated instruction 1104349cc55cSDimitry Andric // combiner for cleanup here so that the unrolling and LICM can be pipelined 1105349cc55cSDimitry Andric // across the loop nests. 1106349cc55cSDimitry Andric // We do UnrollAndJam in a separate LPM to ensure it happens before unroll 1107349cc55cSDimitry Andric if (EnableUnrollAndJam && PTO.LoopUnrolling) { 1108349cc55cSDimitry Andric FPM.addPass(createFunctionToLoopPassAdaptor( 1109349cc55cSDimitry Andric LoopUnrollAndJamPass(Level.getSpeedupLevel()))); 1110349cc55cSDimitry Andric } 1111349cc55cSDimitry Andric FPM.addPass(LoopUnrollPass(LoopUnrollOptions( 1112349cc55cSDimitry Andric Level.getSpeedupLevel(), /*OnlyWhenForced=*/!PTO.LoopUnrolling, 1113349cc55cSDimitry Andric PTO.ForgetAllSCEVInLoopUnroll))); 1114349cc55cSDimitry Andric FPM.addPass(WarnMissedTransformationsPass()); 1115349cc55cSDimitry Andric FPM.addPass(InstCombinePass()); 1116349cc55cSDimitry Andric FPM.addPass( 1117349cc55cSDimitry Andric RequireAnalysisPass<OptimizationRemarkEmitterAnalysis, Function>()); 1118349cc55cSDimitry Andric FPM.addPass(createFunctionToLoopPassAdaptor( 1119fb03ea46SDimitry Andric LICMPass(PTO.LicmMssaOptCap, PTO.LicmMssaNoAccForPromotionCap, 1120fb03ea46SDimitry Andric /*AllowSpeculation=*/true), 1121349cc55cSDimitry Andric /*UseMemorySSA=*/true, /*UseBlockFrequencyInfo=*/true)); 1122349cc55cSDimitry Andric } 1123349cc55cSDimitry Andric 1124349cc55cSDimitry Andric // Now that we've vectorized and unrolled loops, we may have more refined 1125349cc55cSDimitry Andric // alignment information, try to re-derive it here. 1126349cc55cSDimitry Andric FPM.addPass(AlignmentFromAssumptionsPass()); 1127349cc55cSDimitry Andric 1128349cc55cSDimitry Andric if (IsFullLTO) 1129349cc55cSDimitry Andric FPM.addPass(InstCombinePass()); 1130349cc55cSDimitry Andric } 1131349cc55cSDimitry Andric 1132349cc55cSDimitry Andric ModulePassManager 1133349cc55cSDimitry Andric PassBuilder::buildModuleOptimizationPipeline(OptimizationLevel Level, 113481ad6265SDimitry Andric ThinOrFullLTOPhase LTOPhase) { 113581ad6265SDimitry Andric const bool LTOPreLink = (LTOPhase == ThinOrFullLTOPhase::ThinLTOPreLink || 113681ad6265SDimitry Andric LTOPhase == ThinOrFullLTOPhase::FullLTOPreLink); 1137349cc55cSDimitry Andric ModulePassManager MPM; 1138349cc55cSDimitry Andric 1139349cc55cSDimitry Andric // Optimize globals now that the module is fully simplified. 1140349cc55cSDimitry Andric MPM.addPass(GlobalOptPass()); 1141349cc55cSDimitry Andric MPM.addPass(GlobalDCEPass()); 1142349cc55cSDimitry Andric 1143349cc55cSDimitry Andric // Run partial inlining pass to partially inline functions that have 1144349cc55cSDimitry Andric // large bodies. 1145349cc55cSDimitry Andric if (RunPartialInlining) 1146349cc55cSDimitry Andric MPM.addPass(PartialInlinerPass()); 1147349cc55cSDimitry Andric 1148349cc55cSDimitry Andric // Remove avail extern fns and globals definitions since we aren't compiling 1149349cc55cSDimitry Andric // an object file for later LTO. For LTO we want to preserve these so they 1150349cc55cSDimitry Andric // are eligible for inlining at link-time. Note if they are unreferenced they 1151349cc55cSDimitry Andric // will be removed by GlobalDCE later, so this only impacts referenced 1152349cc55cSDimitry Andric // available externally globals. Eventually they will be suppressed during 1153349cc55cSDimitry Andric // codegen, but eliminating here enables more opportunity for GlobalDCE as it 1154349cc55cSDimitry Andric // may make globals referenced by available external functions dead and saves 1155349cc55cSDimitry Andric // running remaining passes on the eliminated functions. These should be 1156349cc55cSDimitry Andric // preserved during prelinking for link-time inlining decisions. 1157349cc55cSDimitry Andric if (!LTOPreLink) 1158349cc55cSDimitry Andric MPM.addPass(EliminateAvailableExternallyPass()); 1159349cc55cSDimitry Andric 1160349cc55cSDimitry Andric if (EnableOrderFileInstrumentation) 1161349cc55cSDimitry Andric MPM.addPass(InstrOrderFilePass()); 1162349cc55cSDimitry Andric 1163349cc55cSDimitry Andric // Do RPO function attribute inference across the module to forward-propagate 1164349cc55cSDimitry Andric // attributes where applicable. 1165349cc55cSDimitry Andric // FIXME: Is this really an optimization rather than a canonicalization? 1166349cc55cSDimitry Andric MPM.addPass(ReversePostOrderFunctionAttrsPass()); 1167349cc55cSDimitry Andric 1168349cc55cSDimitry Andric // Do a post inline PGO instrumentation and use pass. This is a context 1169349cc55cSDimitry Andric // sensitive PGO pass. We don't want to do this in LTOPreLink phrase as 1170349cc55cSDimitry Andric // cross-module inline has not been done yet. The context sensitive 1171349cc55cSDimitry Andric // instrumentation is after all the inlines are done. 1172349cc55cSDimitry Andric if (!LTOPreLink && PGOOpt) { 1173349cc55cSDimitry Andric if (PGOOpt->CSAction == PGOOptions::CSIRInstr) 1174349cc55cSDimitry Andric addPGOInstrPasses(MPM, Level, /* RunProfileGen */ true, 1175349cc55cSDimitry Andric /* IsCS */ true, PGOOpt->CSProfileGenFile, 117681ad6265SDimitry Andric PGOOpt->ProfileRemappingFile, LTOPhase); 1177349cc55cSDimitry Andric else if (PGOOpt->CSAction == PGOOptions::CSIRUse) 1178349cc55cSDimitry Andric addPGOInstrPasses(MPM, Level, /* RunProfileGen */ false, 1179349cc55cSDimitry Andric /* IsCS */ true, PGOOpt->ProfileFile, 118081ad6265SDimitry Andric PGOOpt->ProfileRemappingFile, LTOPhase); 1181349cc55cSDimitry Andric } 1182349cc55cSDimitry Andric 118381ad6265SDimitry Andric // Re-compute GlobalsAA here prior to function passes. This is particularly 1184349cc55cSDimitry Andric // useful as the above will have inlined, DCE'ed, and function-attr 1185349cc55cSDimitry Andric // propagated everything. We should at this point have a reasonably minimal 1186349cc55cSDimitry Andric // and richly annotated call graph. By computing aliasing and mod/ref 1187349cc55cSDimitry Andric // information for all local globals here, the late loop passes and notably 1188349cc55cSDimitry Andric // the vectorizer will be able to use them to help recognize vectorizable 1189349cc55cSDimitry Andric // memory operations. 119081ad6265SDimitry Andric MPM.addPass(RecomputeGlobalsAAPass()); 119181ad6265SDimitry Andric 119281ad6265SDimitry Andric for (auto &C : OptimizerEarlyEPCallbacks) 119381ad6265SDimitry Andric C(MPM, Level); 1194349cc55cSDimitry Andric 1195349cc55cSDimitry Andric FunctionPassManager OptimizePM; 1196349cc55cSDimitry Andric OptimizePM.addPass(Float2IntPass()); 1197349cc55cSDimitry Andric OptimizePM.addPass(LowerConstantIntrinsicsPass()); 1198349cc55cSDimitry Andric 1199349cc55cSDimitry Andric if (EnableMatrix) { 1200349cc55cSDimitry Andric OptimizePM.addPass(LowerMatrixIntrinsicsPass()); 1201349cc55cSDimitry Andric OptimizePM.addPass(EarlyCSEPass()); 1202349cc55cSDimitry Andric } 1203349cc55cSDimitry Andric 1204349cc55cSDimitry Andric // FIXME: We need to run some loop optimizations to re-rotate loops after 1205349cc55cSDimitry Andric // simplifycfg and others undo their rotation. 1206349cc55cSDimitry Andric 1207349cc55cSDimitry Andric // Optimize the loop execution. These passes operate on entire loop nests 1208349cc55cSDimitry Andric // rather than on each loop in an inside-out manner, and so they are actually 1209349cc55cSDimitry Andric // function passes. 1210349cc55cSDimitry Andric 1211349cc55cSDimitry Andric for (auto &C : VectorizerStartEPCallbacks) 1212349cc55cSDimitry Andric C(OptimizePM, Level); 1213349cc55cSDimitry Andric 1214349cc55cSDimitry Andric LoopPassManager LPM; 1215349cc55cSDimitry Andric // First rotate loops that may have been un-rotated by prior passes. 1216349cc55cSDimitry Andric // Disable header duplication at -Oz. 1217349cc55cSDimitry Andric LPM.addPass(LoopRotatePass(Level != OptimizationLevel::Oz, LTOPreLink)); 1218349cc55cSDimitry Andric // Some loops may have become dead by now. Try to delete them. 12190eae32dcSDimitry Andric // FIXME: see discussion in https://reviews.llvm.org/D112851, 12200eae32dcSDimitry Andric // this may need to be revisited once we run GVN before loop deletion 12210eae32dcSDimitry Andric // in the simplification pipeline. 1222349cc55cSDimitry Andric LPM.addPass(LoopDeletionPass()); 1223349cc55cSDimitry Andric OptimizePM.addPass(createFunctionToLoopPassAdaptor( 1224349cc55cSDimitry Andric std::move(LPM), /*UseMemorySSA=*/false, /*UseBlockFrequencyInfo=*/false)); 1225349cc55cSDimitry Andric 1226349cc55cSDimitry Andric // Distribute loops to allow partial vectorization. I.e. isolate dependences 1227349cc55cSDimitry Andric // into separate loop that would otherwise inhibit vectorization. This is 1228349cc55cSDimitry Andric // currently only performed for loops marked with the metadata 1229349cc55cSDimitry Andric // llvm.loop.distribute=true or when -enable-loop-distribute is specified. 1230349cc55cSDimitry Andric OptimizePM.addPass(LoopDistributePass()); 1231349cc55cSDimitry Andric 1232349cc55cSDimitry Andric // Populates the VFABI attribute with the scalar-to-vector mappings 1233349cc55cSDimitry Andric // from the TargetLibraryInfo. 1234349cc55cSDimitry Andric OptimizePM.addPass(InjectTLIMappings()); 1235349cc55cSDimitry Andric 1236349cc55cSDimitry Andric addVectorPasses(Level, OptimizePM, /* IsFullLTO */ false); 1237349cc55cSDimitry Andric 1238349cc55cSDimitry Andric // LoopSink pass sinks instructions hoisted by LICM, which serves as a 1239349cc55cSDimitry Andric // canonicalization pass that enables other optimizations. As a result, 1240349cc55cSDimitry Andric // LoopSink pass needs to be a very late IR pass to avoid undoing LICM 1241349cc55cSDimitry Andric // result too early. 1242349cc55cSDimitry Andric OptimizePM.addPass(LoopSinkPass()); 1243349cc55cSDimitry Andric 1244349cc55cSDimitry Andric // And finally clean up LCSSA form before generating code. 1245349cc55cSDimitry Andric OptimizePM.addPass(InstSimplifyPass()); 1246349cc55cSDimitry Andric 1247349cc55cSDimitry Andric // This hoists/decomposes div/rem ops. It should run after other sink/hoist 1248349cc55cSDimitry Andric // passes to avoid re-sinking, but before SimplifyCFG because it can allow 1249349cc55cSDimitry Andric // flattening of blocks. 1250349cc55cSDimitry Andric OptimizePM.addPass(DivRemPairsPass()); 1251349cc55cSDimitry Andric 1252*972a253aSDimitry Andric // Try to annotate calls that were created during optimization. 1253*972a253aSDimitry Andric OptimizePM.addPass(TailCallElimPass()); 1254*972a253aSDimitry Andric 1255349cc55cSDimitry Andric // LoopSink (and other loop passes since the last simplifyCFG) might have 1256349cc55cSDimitry Andric // resulted in single-entry-single-exit or empty blocks. Clean up the CFG. 1257fb03ea46SDimitry Andric OptimizePM.addPass( 1258fb03ea46SDimitry Andric SimplifyCFGPass(SimplifyCFGOptions().convertSwitchRangeToICmp(true))); 1259349cc55cSDimitry Andric 1260349cc55cSDimitry Andric // Add the core optimizing pipeline. 1261349cc55cSDimitry Andric MPM.addPass(createModuleToFunctionPassAdaptor(std::move(OptimizePM), 1262349cc55cSDimitry Andric PTO.EagerlyInvalidateAnalyses)); 1263349cc55cSDimitry Andric 1264349cc55cSDimitry Andric for (auto &C : OptimizerLastEPCallbacks) 1265349cc55cSDimitry Andric C(MPM, Level); 1266349cc55cSDimitry Andric 12670eae32dcSDimitry Andric // Split out cold code. Splitting is done late to avoid hiding context from 12680eae32dcSDimitry Andric // other optimizations and inadvertently regressing performance. The tradeoff 12690eae32dcSDimitry Andric // is that this has a higher code size cost than splitting early. 12700eae32dcSDimitry Andric if (EnableHotColdSplit && !LTOPreLink) 12710eae32dcSDimitry Andric MPM.addPass(HotColdSplittingPass()); 12720eae32dcSDimitry Andric 12730eae32dcSDimitry Andric // Search the code for similar regions of code. If enough similar regions can 12740eae32dcSDimitry Andric // be found where extracting the regions into their own function will decrease 12750eae32dcSDimitry Andric // the size of the program, we extract the regions, a deduplicate the 12760eae32dcSDimitry Andric // structurally similar regions. 12770eae32dcSDimitry Andric if (EnableIROutliner) 12780eae32dcSDimitry Andric MPM.addPass(IROutlinerPass()); 12790eae32dcSDimitry Andric 12800eae32dcSDimitry Andric // Merge functions if requested. 12810eae32dcSDimitry Andric if (PTO.MergeFunctions) 12820eae32dcSDimitry Andric MPM.addPass(MergeFunctionsPass()); 12830eae32dcSDimitry Andric 1284349cc55cSDimitry Andric // Now we need to do some global optimization transforms. 1285349cc55cSDimitry Andric // FIXME: It would seem like these should come first in the optimization 1286349cc55cSDimitry Andric // pipeline and maybe be the bottom of the canonicalization pipeline? Weird 1287349cc55cSDimitry Andric // ordering here. 1288349cc55cSDimitry Andric MPM.addPass(GlobalDCEPass()); 1289349cc55cSDimitry Andric MPM.addPass(ConstantMergePass()); 1290349cc55cSDimitry Andric 129181ad6265SDimitry Andric if (PTO.CallGraphProfile && !LTOPreLink) 129281ad6265SDimitry Andric MPM.addPass(CGProfilePass()); 129381ad6265SDimitry Andric 1294349cc55cSDimitry Andric // TODO: Relative look table converter pass caused an issue when full lto is 1295349cc55cSDimitry Andric // enabled. See https://reviews.llvm.org/D94355 for more details. 1296349cc55cSDimitry Andric // Until the issue fixed, disable this pass during pre-linking phase. 1297349cc55cSDimitry Andric if (!LTOPreLink) 1298349cc55cSDimitry Andric MPM.addPass(RelLookupTableConverterPass()); 1299349cc55cSDimitry Andric 1300349cc55cSDimitry Andric return MPM; 1301349cc55cSDimitry Andric } 1302349cc55cSDimitry Andric 1303349cc55cSDimitry Andric ModulePassManager 1304349cc55cSDimitry Andric PassBuilder::buildPerModuleDefaultPipeline(OptimizationLevel Level, 1305349cc55cSDimitry Andric bool LTOPreLink) { 1306349cc55cSDimitry Andric assert(Level != OptimizationLevel::O0 && 1307349cc55cSDimitry Andric "Must request optimizations for the default pipeline!"); 1308349cc55cSDimitry Andric 1309349cc55cSDimitry Andric ModulePassManager MPM; 1310349cc55cSDimitry Andric 1311349cc55cSDimitry Andric // Convert @llvm.global.annotations to !annotation metadata. 1312349cc55cSDimitry Andric MPM.addPass(Annotation2MetadataPass()); 1313349cc55cSDimitry Andric 1314349cc55cSDimitry Andric // Force any function attributes we want the rest of the pipeline to observe. 1315349cc55cSDimitry Andric MPM.addPass(ForceFunctionAttrsPass()); 1316349cc55cSDimitry Andric 1317349cc55cSDimitry Andric // Apply module pipeline start EP callback. 1318349cc55cSDimitry Andric for (auto &C : PipelineStartEPCallbacks) 1319349cc55cSDimitry Andric C(MPM, Level); 1320349cc55cSDimitry Andric 1321349cc55cSDimitry Andric if (PGOOpt && PGOOpt->DebugInfoForProfiling) 1322349cc55cSDimitry Andric MPM.addPass(createModuleToFunctionPassAdaptor(AddDiscriminatorsPass())); 1323349cc55cSDimitry Andric 132481ad6265SDimitry Andric const ThinOrFullLTOPhase LTOPhase = LTOPreLink 132581ad6265SDimitry Andric ? ThinOrFullLTOPhase::FullLTOPreLink 132681ad6265SDimitry Andric : ThinOrFullLTOPhase::None; 1327349cc55cSDimitry Andric // Add the core simplification pipeline. 132881ad6265SDimitry Andric MPM.addPass(buildModuleSimplificationPipeline(Level, LTOPhase)); 1329349cc55cSDimitry Andric 1330349cc55cSDimitry Andric // Now add the optimization pipeline. 133181ad6265SDimitry Andric MPM.addPass(buildModuleOptimizationPipeline(Level, LTOPhase)); 1332349cc55cSDimitry Andric 1333349cc55cSDimitry Andric if (PGOOpt && PGOOpt->PseudoProbeForProfiling && 1334349cc55cSDimitry Andric PGOOpt->Action == PGOOptions::SampleUse) 1335349cc55cSDimitry Andric MPM.addPass(PseudoProbeUpdatePass()); 1336349cc55cSDimitry Andric 1337349cc55cSDimitry Andric // Emit annotation remarks. 1338349cc55cSDimitry Andric addAnnotationRemarksPass(MPM); 1339349cc55cSDimitry Andric 1340349cc55cSDimitry Andric if (LTOPreLink) 1341349cc55cSDimitry Andric addRequiredLTOPreLinkPasses(MPM); 1342349cc55cSDimitry Andric 1343349cc55cSDimitry Andric return MPM; 1344349cc55cSDimitry Andric } 1345349cc55cSDimitry Andric 1346349cc55cSDimitry Andric ModulePassManager 1347349cc55cSDimitry Andric PassBuilder::buildThinLTOPreLinkDefaultPipeline(OptimizationLevel Level) { 1348349cc55cSDimitry Andric assert(Level != OptimizationLevel::O0 && 1349349cc55cSDimitry Andric "Must request optimizations for the default pipeline!"); 1350349cc55cSDimitry Andric 1351349cc55cSDimitry Andric ModulePassManager MPM; 1352349cc55cSDimitry Andric 1353349cc55cSDimitry Andric // Convert @llvm.global.annotations to !annotation metadata. 1354349cc55cSDimitry Andric MPM.addPass(Annotation2MetadataPass()); 1355349cc55cSDimitry Andric 1356349cc55cSDimitry Andric // Force any function attributes we want the rest of the pipeline to observe. 1357349cc55cSDimitry Andric MPM.addPass(ForceFunctionAttrsPass()); 1358349cc55cSDimitry Andric 1359349cc55cSDimitry Andric if (PGOOpt && PGOOpt->DebugInfoForProfiling) 1360349cc55cSDimitry Andric MPM.addPass(createModuleToFunctionPassAdaptor(AddDiscriminatorsPass())); 1361349cc55cSDimitry Andric 1362349cc55cSDimitry Andric // Apply module pipeline start EP callback. 1363349cc55cSDimitry Andric for (auto &C : PipelineStartEPCallbacks) 1364349cc55cSDimitry Andric C(MPM, Level); 1365349cc55cSDimitry Andric 1366349cc55cSDimitry Andric // If we are planning to perform ThinLTO later, we don't bloat the code with 1367349cc55cSDimitry Andric // unrolling/vectorization/... now. Just simplify the module as much as we 1368349cc55cSDimitry Andric // can. 1369349cc55cSDimitry Andric MPM.addPass(buildModuleSimplificationPipeline( 1370349cc55cSDimitry Andric Level, ThinOrFullLTOPhase::ThinLTOPreLink)); 1371349cc55cSDimitry Andric 1372349cc55cSDimitry Andric // Run partial inlining pass to partially inline functions that have 1373349cc55cSDimitry Andric // large bodies. 1374349cc55cSDimitry Andric // FIXME: It isn't clear whether this is really the right place to run this 1375349cc55cSDimitry Andric // in ThinLTO. Because there is another canonicalization and simplification 1376349cc55cSDimitry Andric // phase that will run after the thin link, running this here ends up with 1377349cc55cSDimitry Andric // less information than will be available later and it may grow functions in 1378349cc55cSDimitry Andric // ways that aren't beneficial. 1379349cc55cSDimitry Andric if (RunPartialInlining) 1380349cc55cSDimitry Andric MPM.addPass(PartialInlinerPass()); 1381349cc55cSDimitry Andric 1382349cc55cSDimitry Andric // Reduce the size of the IR as much as possible. 1383349cc55cSDimitry Andric MPM.addPass(GlobalOptPass()); 1384349cc55cSDimitry Andric 1385349cc55cSDimitry Andric if (PGOOpt && PGOOpt->PseudoProbeForProfiling && 1386349cc55cSDimitry Andric PGOOpt->Action == PGOOptions::SampleUse) 1387349cc55cSDimitry Andric MPM.addPass(PseudoProbeUpdatePass()); 1388349cc55cSDimitry Andric 1389349cc55cSDimitry Andric // Handle OptimizerLastEPCallbacks added by clang on PreLink. Actual 1390349cc55cSDimitry Andric // optimization is going to be done in PostLink stage, but clang can't 1391349cc55cSDimitry Andric // add callbacks there in case of in-process ThinLTO called by linker. 1392349cc55cSDimitry Andric for (auto &C : OptimizerLastEPCallbacks) 1393349cc55cSDimitry Andric C(MPM, Level); 1394349cc55cSDimitry Andric 1395349cc55cSDimitry Andric // Emit annotation remarks. 1396349cc55cSDimitry Andric addAnnotationRemarksPass(MPM); 1397349cc55cSDimitry Andric 1398349cc55cSDimitry Andric addRequiredLTOPreLinkPasses(MPM); 1399349cc55cSDimitry Andric 1400349cc55cSDimitry Andric return MPM; 1401349cc55cSDimitry Andric } 1402349cc55cSDimitry Andric 1403349cc55cSDimitry Andric ModulePassManager PassBuilder::buildThinLTODefaultPipeline( 1404349cc55cSDimitry Andric OptimizationLevel Level, const ModuleSummaryIndex *ImportSummary) { 1405349cc55cSDimitry Andric ModulePassManager MPM; 1406349cc55cSDimitry Andric 1407349cc55cSDimitry Andric // Convert @llvm.global.annotations to !annotation metadata. 1408349cc55cSDimitry Andric MPM.addPass(Annotation2MetadataPass()); 1409349cc55cSDimitry Andric 1410349cc55cSDimitry Andric if (ImportSummary) { 1411349cc55cSDimitry Andric // These passes import type identifier resolutions for whole-program 1412349cc55cSDimitry Andric // devirtualization and CFI. They must run early because other passes may 1413349cc55cSDimitry Andric // disturb the specific instruction patterns that these passes look for, 1414349cc55cSDimitry Andric // creating dependencies on resolutions that may not appear in the summary. 1415349cc55cSDimitry Andric // 1416349cc55cSDimitry Andric // For example, GVN may transform the pattern assume(type.test) appearing in 1417349cc55cSDimitry Andric // two basic blocks into assume(phi(type.test, type.test)), which would 1418349cc55cSDimitry Andric // transform a dependency on a WPD resolution into a dependency on a type 1419349cc55cSDimitry Andric // identifier resolution for CFI. 1420349cc55cSDimitry Andric // 1421349cc55cSDimitry Andric // Also, WPD has access to more precise information than ICP and can 1422349cc55cSDimitry Andric // devirtualize more effectively, so it should operate on the IR first. 1423349cc55cSDimitry Andric // 1424349cc55cSDimitry Andric // The WPD and LowerTypeTest passes need to run at -O0 to lower type 1425349cc55cSDimitry Andric // metadata and intrinsics. 1426349cc55cSDimitry Andric MPM.addPass(WholeProgramDevirtPass(nullptr, ImportSummary)); 1427349cc55cSDimitry Andric MPM.addPass(LowerTypeTestsPass(nullptr, ImportSummary)); 1428349cc55cSDimitry Andric } 1429349cc55cSDimitry Andric 1430349cc55cSDimitry Andric if (Level == OptimizationLevel::O0) { 1431349cc55cSDimitry Andric // Run a second time to clean up any type tests left behind by WPD for use 1432349cc55cSDimitry Andric // in ICP. 1433349cc55cSDimitry Andric MPM.addPass(LowerTypeTestsPass(nullptr, nullptr, true)); 1434349cc55cSDimitry Andric // Drop available_externally and unreferenced globals. This is necessary 1435349cc55cSDimitry Andric // with ThinLTO in order to avoid leaving undefined references to dead 1436349cc55cSDimitry Andric // globals in the object file. 1437349cc55cSDimitry Andric MPM.addPass(EliminateAvailableExternallyPass()); 1438349cc55cSDimitry Andric MPM.addPass(GlobalDCEPass()); 1439349cc55cSDimitry Andric return MPM; 1440349cc55cSDimitry Andric } 1441349cc55cSDimitry Andric 1442349cc55cSDimitry Andric // Force any function attributes we want the rest of the pipeline to observe. 1443349cc55cSDimitry Andric MPM.addPass(ForceFunctionAttrsPass()); 1444349cc55cSDimitry Andric 1445349cc55cSDimitry Andric // Add the core simplification pipeline. 1446349cc55cSDimitry Andric MPM.addPass(buildModuleSimplificationPipeline( 1447349cc55cSDimitry Andric Level, ThinOrFullLTOPhase::ThinLTOPostLink)); 1448349cc55cSDimitry Andric 1449349cc55cSDimitry Andric // Now add the optimization pipeline. 145081ad6265SDimitry Andric MPM.addPass(buildModuleOptimizationPipeline( 145181ad6265SDimitry Andric Level, ThinOrFullLTOPhase::ThinLTOPostLink)); 1452349cc55cSDimitry Andric 1453349cc55cSDimitry Andric // Emit annotation remarks. 1454349cc55cSDimitry Andric addAnnotationRemarksPass(MPM); 1455349cc55cSDimitry Andric 1456349cc55cSDimitry Andric return MPM; 1457349cc55cSDimitry Andric } 1458349cc55cSDimitry Andric 1459349cc55cSDimitry Andric ModulePassManager 1460349cc55cSDimitry Andric PassBuilder::buildLTOPreLinkDefaultPipeline(OptimizationLevel Level) { 1461349cc55cSDimitry Andric assert(Level != OptimizationLevel::O0 && 1462349cc55cSDimitry Andric "Must request optimizations for the default pipeline!"); 1463349cc55cSDimitry Andric // FIXME: We should use a customized pre-link pipeline! 1464349cc55cSDimitry Andric return buildPerModuleDefaultPipeline(Level, 1465349cc55cSDimitry Andric /* LTOPreLink */ true); 1466349cc55cSDimitry Andric } 1467349cc55cSDimitry Andric 1468349cc55cSDimitry Andric ModulePassManager 1469349cc55cSDimitry Andric PassBuilder::buildLTODefaultPipeline(OptimizationLevel Level, 1470349cc55cSDimitry Andric ModuleSummaryIndex *ExportSummary) { 1471349cc55cSDimitry Andric ModulePassManager MPM; 1472349cc55cSDimitry Andric 1473349cc55cSDimitry Andric // Convert @llvm.global.annotations to !annotation metadata. 1474349cc55cSDimitry Andric MPM.addPass(Annotation2MetadataPass()); 1475349cc55cSDimitry Andric 147681ad6265SDimitry Andric for (auto &C : FullLinkTimeOptimizationEarlyEPCallbacks) 147781ad6265SDimitry Andric C(MPM, Level); 147881ad6265SDimitry Andric 1479349cc55cSDimitry Andric // Create a function that performs CFI checks for cross-DSO calls with targets 1480349cc55cSDimitry Andric // in the current module. 1481349cc55cSDimitry Andric MPM.addPass(CrossDSOCFIPass()); 1482349cc55cSDimitry Andric 1483349cc55cSDimitry Andric if (Level == OptimizationLevel::O0) { 1484349cc55cSDimitry Andric // The WPD and LowerTypeTest passes need to run at -O0 to lower type 1485349cc55cSDimitry Andric // metadata and intrinsics. 1486349cc55cSDimitry Andric MPM.addPass(WholeProgramDevirtPass(ExportSummary, nullptr)); 1487349cc55cSDimitry Andric MPM.addPass(LowerTypeTestsPass(ExportSummary, nullptr)); 1488349cc55cSDimitry Andric // Run a second time to clean up any type tests left behind by WPD for use 1489349cc55cSDimitry Andric // in ICP. 1490349cc55cSDimitry Andric MPM.addPass(LowerTypeTestsPass(nullptr, nullptr, true)); 1491349cc55cSDimitry Andric 149281ad6265SDimitry Andric for (auto &C : FullLinkTimeOptimizationLastEPCallbacks) 149381ad6265SDimitry Andric C(MPM, Level); 149481ad6265SDimitry Andric 1495349cc55cSDimitry Andric // Emit annotation remarks. 1496349cc55cSDimitry Andric addAnnotationRemarksPass(MPM); 1497349cc55cSDimitry Andric 1498349cc55cSDimitry Andric return MPM; 1499349cc55cSDimitry Andric } 1500349cc55cSDimitry Andric 1501349cc55cSDimitry Andric if (PGOOpt && PGOOpt->Action == PGOOptions::SampleUse) { 1502349cc55cSDimitry Andric // Load sample profile before running the LTO optimization pipeline. 1503349cc55cSDimitry Andric MPM.addPass(SampleProfileLoaderPass(PGOOpt->ProfileFile, 1504349cc55cSDimitry Andric PGOOpt->ProfileRemappingFile, 1505349cc55cSDimitry Andric ThinOrFullLTOPhase::FullLTOPostLink)); 1506349cc55cSDimitry Andric // Cache ProfileSummaryAnalysis once to avoid the potential need to insert 1507349cc55cSDimitry Andric // RequireAnalysisPass for PSI before subsequent non-module passes. 1508349cc55cSDimitry Andric MPM.addPass(RequireAnalysisPass<ProfileSummaryAnalysis, Module>()); 1509349cc55cSDimitry Andric } 1510349cc55cSDimitry Andric 15111fd87a68SDimitry Andric // Try to run OpenMP optimizations, quick no-op if no OpenMP metadata present. 15121fd87a68SDimitry Andric MPM.addPass(OpenMPOptPass()); 15131fd87a68SDimitry Andric 1514349cc55cSDimitry Andric // Remove unused virtual tables to improve the quality of code generated by 1515349cc55cSDimitry Andric // whole-program devirtualization and bitset lowering. 1516349cc55cSDimitry Andric MPM.addPass(GlobalDCEPass()); 1517349cc55cSDimitry Andric 1518349cc55cSDimitry Andric // Force any function attributes we want the rest of the pipeline to observe. 1519349cc55cSDimitry Andric MPM.addPass(ForceFunctionAttrsPass()); 1520349cc55cSDimitry Andric 1521349cc55cSDimitry Andric // Do basic inference of function attributes from known properties of system 1522349cc55cSDimitry Andric // libraries and other oracles. 1523349cc55cSDimitry Andric MPM.addPass(InferFunctionAttrsPass()); 1524349cc55cSDimitry Andric 1525349cc55cSDimitry Andric if (Level.getSpeedupLevel() > 1) { 1526349cc55cSDimitry Andric MPM.addPass(createModuleToFunctionPassAdaptor( 152781ad6265SDimitry Andric CallSiteSplittingPass(), PTO.EagerlyInvalidateAnalyses)); 1528349cc55cSDimitry Andric 1529349cc55cSDimitry Andric // Indirect call promotion. This should promote all the targets that are 1530349cc55cSDimitry Andric // left by the earlier promotion pass that promotes intra-module targets. 1531349cc55cSDimitry Andric // This two-step promotion is to save the compile time. For LTO, it should 1532349cc55cSDimitry Andric // produce the same result as if we only do promotion here. 1533349cc55cSDimitry Andric MPM.addPass(PGOIndirectCallPromotion( 1534349cc55cSDimitry Andric true /* InLTO */, PGOOpt && PGOOpt->Action == PGOOptions::SampleUse)); 1535349cc55cSDimitry Andric 1536349cc55cSDimitry Andric if (EnableFunctionSpecialization && Level == OptimizationLevel::O3) 1537349cc55cSDimitry Andric MPM.addPass(FunctionSpecializationPass()); 1538349cc55cSDimitry Andric // Propagate constants at call sites into the functions they call. This 1539349cc55cSDimitry Andric // opens opportunities for globalopt (and inlining) by substituting function 1540349cc55cSDimitry Andric // pointers passed as arguments to direct uses of functions. 1541349cc55cSDimitry Andric MPM.addPass(IPSCCPPass()); 1542349cc55cSDimitry Andric 1543349cc55cSDimitry Andric // Attach metadata to indirect call sites indicating the set of functions 1544349cc55cSDimitry Andric // they may target at run-time. This should follow IPSCCP. 1545349cc55cSDimitry Andric MPM.addPass(CalledValuePropagationPass()); 1546349cc55cSDimitry Andric } 1547349cc55cSDimitry Andric 1548349cc55cSDimitry Andric // Now deduce any function attributes based in the current code. 1549349cc55cSDimitry Andric MPM.addPass( 1550349cc55cSDimitry Andric createModuleToPostOrderCGSCCPassAdaptor(PostOrderFunctionAttrsPass())); 1551349cc55cSDimitry Andric 1552349cc55cSDimitry Andric // Do RPO function attribute inference across the module to forward-propagate 1553349cc55cSDimitry Andric // attributes where applicable. 1554349cc55cSDimitry Andric // FIXME: Is this really an optimization rather than a canonicalization? 1555349cc55cSDimitry Andric MPM.addPass(ReversePostOrderFunctionAttrsPass()); 1556349cc55cSDimitry Andric 1557349cc55cSDimitry Andric // Use in-range annotations on GEP indices to split globals where beneficial. 1558349cc55cSDimitry Andric MPM.addPass(GlobalSplitPass()); 1559349cc55cSDimitry Andric 1560349cc55cSDimitry Andric // Run whole program optimization of virtual call when the list of callees 1561349cc55cSDimitry Andric // is fixed. 1562349cc55cSDimitry Andric MPM.addPass(WholeProgramDevirtPass(ExportSummary, nullptr)); 1563349cc55cSDimitry Andric 1564349cc55cSDimitry Andric // Stop here at -O1. 1565349cc55cSDimitry Andric if (Level == OptimizationLevel::O1) { 1566349cc55cSDimitry Andric // The LowerTypeTestsPass needs to run to lower type metadata and the 1567349cc55cSDimitry Andric // type.test intrinsics. The pass does nothing if CFI is disabled. 1568349cc55cSDimitry Andric MPM.addPass(LowerTypeTestsPass(ExportSummary, nullptr)); 1569349cc55cSDimitry Andric // Run a second time to clean up any type tests left behind by WPD for use 1570349cc55cSDimitry Andric // in ICP (which is performed earlier than this in the regular LTO 1571349cc55cSDimitry Andric // pipeline). 1572349cc55cSDimitry Andric MPM.addPass(LowerTypeTestsPass(nullptr, nullptr, true)); 1573349cc55cSDimitry Andric 157481ad6265SDimitry Andric for (auto &C : FullLinkTimeOptimizationLastEPCallbacks) 157581ad6265SDimitry Andric C(MPM, Level); 157681ad6265SDimitry Andric 1577349cc55cSDimitry Andric // Emit annotation remarks. 1578349cc55cSDimitry Andric addAnnotationRemarksPass(MPM); 1579349cc55cSDimitry Andric 1580349cc55cSDimitry Andric return MPM; 1581349cc55cSDimitry Andric } 1582349cc55cSDimitry Andric 1583349cc55cSDimitry Andric // Optimize globals to try and fold them into constants. 1584349cc55cSDimitry Andric MPM.addPass(GlobalOptPass()); 1585349cc55cSDimitry Andric 1586349cc55cSDimitry Andric // Promote any localized globals to SSA registers. 1587349cc55cSDimitry Andric MPM.addPass(createModuleToFunctionPassAdaptor(PromotePass())); 1588349cc55cSDimitry Andric 1589349cc55cSDimitry Andric // Linking modules together can lead to duplicate global constant, only 1590349cc55cSDimitry Andric // keep one copy of each constant. 1591349cc55cSDimitry Andric MPM.addPass(ConstantMergePass()); 1592349cc55cSDimitry Andric 1593349cc55cSDimitry Andric // Remove unused arguments from functions. 1594349cc55cSDimitry Andric MPM.addPass(DeadArgumentEliminationPass()); 1595349cc55cSDimitry Andric 1596349cc55cSDimitry Andric // Reduce the code after globalopt and ipsccp. Both can open up significant 1597349cc55cSDimitry Andric // simplification opportunities, and both can propagate functions through 1598349cc55cSDimitry Andric // function pointers. When this happens, we often have to resolve varargs 1599349cc55cSDimitry Andric // calls, etc, so let instcombine do this. 1600349cc55cSDimitry Andric FunctionPassManager PeepholeFPM; 16010eae32dcSDimitry Andric PeepholeFPM.addPass(InstCombinePass()); 1602349cc55cSDimitry Andric if (Level == OptimizationLevel::O3) 1603349cc55cSDimitry Andric PeepholeFPM.addPass(AggressiveInstCombinePass()); 1604349cc55cSDimitry Andric invokePeepholeEPCallbacks(PeepholeFPM, Level); 1605349cc55cSDimitry Andric 1606349cc55cSDimitry Andric MPM.addPass(createModuleToFunctionPassAdaptor(std::move(PeepholeFPM), 1607349cc55cSDimitry Andric PTO.EagerlyInvalidateAnalyses)); 1608349cc55cSDimitry Andric 1609349cc55cSDimitry Andric // Note: historically, the PruneEH pass was run first to deduce nounwind and 1610349cc55cSDimitry Andric // generally clean up exception handling overhead. It isn't clear this is 1611349cc55cSDimitry Andric // valuable as the inliner doesn't currently care whether it is inlining an 1612349cc55cSDimitry Andric // invoke or a call. 1613349cc55cSDimitry Andric // Run the inliner now. 161481ad6265SDimitry Andric MPM.addPass(ModuleInlinerWrapperPass( 161581ad6265SDimitry Andric getInlineParamsFromOptLevel(Level), 161681ad6265SDimitry Andric /* MandatoryFirst */ true, 161781ad6265SDimitry Andric InlineContext{ThinOrFullLTOPhase::FullLTOPostLink, 161881ad6265SDimitry Andric InlinePass::CGSCCInliner})); 1619349cc55cSDimitry Andric 1620349cc55cSDimitry Andric // Optimize globals again after we ran the inliner. 1621349cc55cSDimitry Andric MPM.addPass(GlobalOptPass()); 1622349cc55cSDimitry Andric 1623349cc55cSDimitry Andric // Garbage collect dead functions. 1624349cc55cSDimitry Andric MPM.addPass(GlobalDCEPass()); 1625349cc55cSDimitry Andric 1626349cc55cSDimitry Andric // If we didn't decide to inline a function, check to see if we can 1627349cc55cSDimitry Andric // transform it to pass arguments by value instead of by reference. 1628349cc55cSDimitry Andric MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(ArgumentPromotionPass())); 1629349cc55cSDimitry Andric 1630349cc55cSDimitry Andric FunctionPassManager FPM; 1631349cc55cSDimitry Andric // The IPO Passes may leave cruft around. Clean up after them. 1632349cc55cSDimitry Andric FPM.addPass(InstCombinePass()); 1633349cc55cSDimitry Andric invokePeepholeEPCallbacks(FPM, Level); 1634349cc55cSDimitry Andric 163581ad6265SDimitry Andric FPM.addPass(JumpThreadingPass()); 1636349cc55cSDimitry Andric 1637349cc55cSDimitry Andric // Do a post inline PGO instrumentation and use pass. This is a context 1638349cc55cSDimitry Andric // sensitive PGO pass. 1639349cc55cSDimitry Andric if (PGOOpt) { 1640349cc55cSDimitry Andric if (PGOOpt->CSAction == PGOOptions::CSIRInstr) 1641349cc55cSDimitry Andric addPGOInstrPasses(MPM, Level, /* RunProfileGen */ true, 1642349cc55cSDimitry Andric /* IsCS */ true, PGOOpt->CSProfileGenFile, 164381ad6265SDimitry Andric PGOOpt->ProfileRemappingFile, 164481ad6265SDimitry Andric ThinOrFullLTOPhase::FullLTOPostLink); 1645349cc55cSDimitry Andric else if (PGOOpt->CSAction == PGOOptions::CSIRUse) 1646349cc55cSDimitry Andric addPGOInstrPasses(MPM, Level, /* RunProfileGen */ false, 1647349cc55cSDimitry Andric /* IsCS */ true, PGOOpt->ProfileFile, 164881ad6265SDimitry Andric PGOOpt->ProfileRemappingFile, 164981ad6265SDimitry Andric ThinOrFullLTOPhase::FullLTOPostLink); 1650349cc55cSDimitry Andric } 1651349cc55cSDimitry Andric 1652349cc55cSDimitry Andric // Break up allocas 1653349cc55cSDimitry Andric FPM.addPass(SROAPass()); 1654349cc55cSDimitry Andric 1655349cc55cSDimitry Andric // LTO provides additional opportunities for tailcall elimination due to 1656349cc55cSDimitry Andric // link-time inlining, and visibility of nocapture attribute. 1657349cc55cSDimitry Andric FPM.addPass(TailCallElimPass()); 1658349cc55cSDimitry Andric 1659349cc55cSDimitry Andric // Run a few AA driver optimizations here and now to cleanup the code. 1660349cc55cSDimitry Andric MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM), 1661349cc55cSDimitry Andric PTO.EagerlyInvalidateAnalyses)); 1662349cc55cSDimitry Andric 1663349cc55cSDimitry Andric MPM.addPass( 1664349cc55cSDimitry Andric createModuleToPostOrderCGSCCPassAdaptor(PostOrderFunctionAttrsPass())); 1665349cc55cSDimitry Andric 1666349cc55cSDimitry Andric // Require the GlobalsAA analysis for the module so we can query it within 1667349cc55cSDimitry Andric // MainFPM. 1668349cc55cSDimitry Andric MPM.addPass(RequireAnalysisPass<GlobalsAA, Module>()); 1669349cc55cSDimitry Andric // Invalidate AAManager so it can be recreated and pick up the newly available 1670349cc55cSDimitry Andric // GlobalsAA. 1671349cc55cSDimitry Andric MPM.addPass( 1672349cc55cSDimitry Andric createModuleToFunctionPassAdaptor(InvalidateAnalysisPass<AAManager>())); 1673349cc55cSDimitry Andric 1674349cc55cSDimitry Andric FunctionPassManager MainFPM; 1675349cc55cSDimitry Andric MainFPM.addPass(createFunctionToLoopPassAdaptor( 1676fb03ea46SDimitry Andric LICMPass(PTO.LicmMssaOptCap, PTO.LicmMssaNoAccForPromotionCap, 1677fb03ea46SDimitry Andric /*AllowSpeculation=*/true), 1678349cc55cSDimitry Andric /*USeMemorySSA=*/true, /*UseBlockFrequencyInfo=*/true)); 1679349cc55cSDimitry Andric 1680349cc55cSDimitry Andric if (RunNewGVN) 1681349cc55cSDimitry Andric MainFPM.addPass(NewGVNPass()); 1682349cc55cSDimitry Andric else 1683349cc55cSDimitry Andric MainFPM.addPass(GVNPass()); 1684349cc55cSDimitry Andric 1685349cc55cSDimitry Andric // Remove dead memcpy()'s. 1686349cc55cSDimitry Andric MainFPM.addPass(MemCpyOptPass()); 1687349cc55cSDimitry Andric 1688349cc55cSDimitry Andric // Nuke dead stores. 1689349cc55cSDimitry Andric MainFPM.addPass(DSEPass()); 1690349cc55cSDimitry Andric MainFPM.addPass(MergedLoadStoreMotionPass()); 1691349cc55cSDimitry Andric 1692349cc55cSDimitry Andric 1693349cc55cSDimitry Andric if (EnableConstraintElimination) 1694349cc55cSDimitry Andric MainFPM.addPass(ConstraintEliminationPass()); 1695349cc55cSDimitry Andric 1696349cc55cSDimitry Andric LoopPassManager LPM; 169704eeddc0SDimitry Andric if (EnableLoopFlatten && Level.getSpeedupLevel() > 1) 169804eeddc0SDimitry Andric LPM.addPass(LoopFlattenPass()); 1699349cc55cSDimitry Andric LPM.addPass(IndVarSimplifyPass()); 1700349cc55cSDimitry Andric LPM.addPass(LoopDeletionPass()); 1701349cc55cSDimitry Andric // FIXME: Add loop interchange. 1702349cc55cSDimitry Andric 1703349cc55cSDimitry Andric // Unroll small loops and perform peeling. 1704349cc55cSDimitry Andric LPM.addPass(LoopFullUnrollPass(Level.getSpeedupLevel(), 1705349cc55cSDimitry Andric /* OnlyWhenForced= */ !PTO.LoopUnrolling, 1706349cc55cSDimitry Andric PTO.ForgetAllSCEVInLoopUnroll)); 1707349cc55cSDimitry Andric // The loop passes in LPM (LoopFullUnrollPass) do not preserve MemorySSA. 1708349cc55cSDimitry Andric // *All* loop passes must preserve it, in order to be able to use it. 1709349cc55cSDimitry Andric MainFPM.addPass(createFunctionToLoopPassAdaptor( 1710349cc55cSDimitry Andric std::move(LPM), /*UseMemorySSA=*/false, /*UseBlockFrequencyInfo=*/true)); 1711349cc55cSDimitry Andric 1712349cc55cSDimitry Andric MainFPM.addPass(LoopDistributePass()); 1713349cc55cSDimitry Andric 1714349cc55cSDimitry Andric addVectorPasses(Level, MainFPM, /* IsFullLTO */ true); 1715349cc55cSDimitry Andric 17161fd87a68SDimitry Andric // Run the OpenMPOpt CGSCC pass again late. 17171fd87a68SDimitry Andric MPM.addPass( 17181fd87a68SDimitry Andric createModuleToPostOrderCGSCCPassAdaptor(OpenMPOptCGSCCPass())); 17191fd87a68SDimitry Andric 1720349cc55cSDimitry Andric invokePeepholeEPCallbacks(MainFPM, Level); 172181ad6265SDimitry Andric MainFPM.addPass(JumpThreadingPass()); 1722349cc55cSDimitry Andric MPM.addPass(createModuleToFunctionPassAdaptor(std::move(MainFPM), 1723349cc55cSDimitry Andric PTO.EagerlyInvalidateAnalyses)); 1724349cc55cSDimitry Andric 1725349cc55cSDimitry Andric // Lower type metadata and the type.test intrinsic. This pass supports 1726349cc55cSDimitry Andric // clang's control flow integrity mechanisms (-fsanitize=cfi*) and needs 1727349cc55cSDimitry Andric // to be run at link time if CFI is enabled. This pass does nothing if 1728349cc55cSDimitry Andric // CFI is disabled. 1729349cc55cSDimitry Andric MPM.addPass(LowerTypeTestsPass(ExportSummary, nullptr)); 1730349cc55cSDimitry Andric // Run a second time to clean up any type tests left behind by WPD for use 1731349cc55cSDimitry Andric // in ICP (which is performed earlier than this in the regular LTO pipeline). 1732349cc55cSDimitry Andric MPM.addPass(LowerTypeTestsPass(nullptr, nullptr, true)); 1733349cc55cSDimitry Andric 1734753f127fSDimitry Andric // Enable splitting late in the FullLTO post-link pipeline. 1735349cc55cSDimitry Andric if (EnableHotColdSplit) 1736349cc55cSDimitry Andric MPM.addPass(HotColdSplittingPass()); 1737349cc55cSDimitry Andric 1738349cc55cSDimitry Andric // Add late LTO optimization passes. 1739349cc55cSDimitry Andric // Delete basic blocks, which optimization passes may have killed. 1740fb03ea46SDimitry Andric MPM.addPass(createModuleToFunctionPassAdaptor(SimplifyCFGPass( 1741fb03ea46SDimitry Andric SimplifyCFGOptions().convertSwitchRangeToICmp(true).hoistCommonInsts( 1742fb03ea46SDimitry Andric true)))); 1743349cc55cSDimitry Andric 1744349cc55cSDimitry Andric // Drop bodies of available eternally objects to improve GlobalDCE. 1745349cc55cSDimitry Andric MPM.addPass(EliminateAvailableExternallyPass()); 1746349cc55cSDimitry Andric 1747349cc55cSDimitry Andric // Now that we have optimized the program, discard unreachable functions. 1748349cc55cSDimitry Andric MPM.addPass(GlobalDCEPass()); 1749349cc55cSDimitry Andric 1750349cc55cSDimitry Andric if (PTO.MergeFunctions) 1751349cc55cSDimitry Andric MPM.addPass(MergeFunctionsPass()); 1752349cc55cSDimitry Andric 175381ad6265SDimitry Andric if (PTO.CallGraphProfile) 175481ad6265SDimitry Andric MPM.addPass(CGProfilePass()); 175581ad6265SDimitry Andric 175681ad6265SDimitry Andric for (auto &C : FullLinkTimeOptimizationLastEPCallbacks) 175781ad6265SDimitry Andric C(MPM, Level); 175881ad6265SDimitry Andric 1759349cc55cSDimitry Andric // Emit annotation remarks. 1760349cc55cSDimitry Andric addAnnotationRemarksPass(MPM); 1761349cc55cSDimitry Andric 1762349cc55cSDimitry Andric return MPM; 1763349cc55cSDimitry Andric } 1764349cc55cSDimitry Andric 1765349cc55cSDimitry Andric ModulePassManager PassBuilder::buildO0DefaultPipeline(OptimizationLevel Level, 1766349cc55cSDimitry Andric bool LTOPreLink) { 1767349cc55cSDimitry Andric assert(Level == OptimizationLevel::O0 && 1768349cc55cSDimitry Andric "buildO0DefaultPipeline should only be used with O0"); 1769349cc55cSDimitry Andric 1770349cc55cSDimitry Andric ModulePassManager MPM; 1771349cc55cSDimitry Andric 1772349cc55cSDimitry Andric // Perform pseudo probe instrumentation in O0 mode. This is for the 1773349cc55cSDimitry Andric // consistency between different build modes. For example, a LTO build can be 1774349cc55cSDimitry Andric // mixed with an O0 prelink and an O2 postlink. Loading a sample profile in 1775349cc55cSDimitry Andric // the postlink will require pseudo probe instrumentation in the prelink. 1776349cc55cSDimitry Andric if (PGOOpt && PGOOpt->PseudoProbeForProfiling) 1777349cc55cSDimitry Andric MPM.addPass(SampleProfileProbePass(TM)); 1778349cc55cSDimitry Andric 1779349cc55cSDimitry Andric if (PGOOpt && (PGOOpt->Action == PGOOptions::IRInstr || 1780349cc55cSDimitry Andric PGOOpt->Action == PGOOptions::IRUse)) 1781349cc55cSDimitry Andric addPGOInstrPassesForO0( 1782349cc55cSDimitry Andric MPM, 1783349cc55cSDimitry Andric /* RunProfileGen */ (PGOOpt->Action == PGOOptions::IRInstr), 1784349cc55cSDimitry Andric /* IsCS */ false, PGOOpt->ProfileFile, PGOOpt->ProfileRemappingFile); 1785349cc55cSDimitry Andric 1786349cc55cSDimitry Andric for (auto &C : PipelineStartEPCallbacks) 1787349cc55cSDimitry Andric C(MPM, Level); 1788349cc55cSDimitry Andric 1789349cc55cSDimitry Andric if (PGOOpt && PGOOpt->DebugInfoForProfiling) 1790349cc55cSDimitry Andric MPM.addPass(createModuleToFunctionPassAdaptor(AddDiscriminatorsPass())); 1791349cc55cSDimitry Andric 1792349cc55cSDimitry Andric for (auto &C : PipelineEarlySimplificationEPCallbacks) 1793349cc55cSDimitry Andric C(MPM, Level); 1794349cc55cSDimitry Andric 1795349cc55cSDimitry Andric // Build a minimal pipeline based on the semantics required by LLVM, 1796349cc55cSDimitry Andric // which is just that always inlining occurs. Further, disable generating 1797349cc55cSDimitry Andric // lifetime intrinsics to avoid enabling further optimizations during 1798349cc55cSDimitry Andric // code generation. 1799349cc55cSDimitry Andric MPM.addPass(AlwaysInlinerPass( 1800349cc55cSDimitry Andric /*InsertLifetimeIntrinsics=*/false)); 1801349cc55cSDimitry Andric 1802349cc55cSDimitry Andric if (PTO.MergeFunctions) 1803349cc55cSDimitry Andric MPM.addPass(MergeFunctionsPass()); 1804349cc55cSDimitry Andric 1805349cc55cSDimitry Andric if (EnableMatrix) 1806349cc55cSDimitry Andric MPM.addPass( 1807349cc55cSDimitry Andric createModuleToFunctionPassAdaptor(LowerMatrixIntrinsicsPass(true))); 1808349cc55cSDimitry Andric 1809349cc55cSDimitry Andric if (!CGSCCOptimizerLateEPCallbacks.empty()) { 1810349cc55cSDimitry Andric CGSCCPassManager CGPM; 1811349cc55cSDimitry Andric for (auto &C : CGSCCOptimizerLateEPCallbacks) 1812349cc55cSDimitry Andric C(CGPM, Level); 1813349cc55cSDimitry Andric if (!CGPM.isEmpty()) 1814349cc55cSDimitry Andric MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM))); 1815349cc55cSDimitry Andric } 1816349cc55cSDimitry Andric if (!LateLoopOptimizationsEPCallbacks.empty()) { 1817349cc55cSDimitry Andric LoopPassManager LPM; 1818349cc55cSDimitry Andric for (auto &C : LateLoopOptimizationsEPCallbacks) 1819349cc55cSDimitry Andric C(LPM, Level); 1820349cc55cSDimitry Andric if (!LPM.isEmpty()) { 1821349cc55cSDimitry Andric MPM.addPass(createModuleToFunctionPassAdaptor( 1822349cc55cSDimitry Andric createFunctionToLoopPassAdaptor(std::move(LPM)))); 1823349cc55cSDimitry Andric } 1824349cc55cSDimitry Andric } 1825349cc55cSDimitry Andric if (!LoopOptimizerEndEPCallbacks.empty()) { 1826349cc55cSDimitry Andric LoopPassManager LPM; 1827349cc55cSDimitry Andric for (auto &C : LoopOptimizerEndEPCallbacks) 1828349cc55cSDimitry Andric C(LPM, Level); 1829349cc55cSDimitry Andric if (!LPM.isEmpty()) { 1830349cc55cSDimitry Andric MPM.addPass(createModuleToFunctionPassAdaptor( 1831349cc55cSDimitry Andric createFunctionToLoopPassAdaptor(std::move(LPM)))); 1832349cc55cSDimitry Andric } 1833349cc55cSDimitry Andric } 1834349cc55cSDimitry Andric if (!ScalarOptimizerLateEPCallbacks.empty()) { 1835349cc55cSDimitry Andric FunctionPassManager FPM; 1836349cc55cSDimitry Andric for (auto &C : ScalarOptimizerLateEPCallbacks) 1837349cc55cSDimitry Andric C(FPM, Level); 1838349cc55cSDimitry Andric if (!FPM.isEmpty()) 1839349cc55cSDimitry Andric MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); 1840349cc55cSDimitry Andric } 184181ad6265SDimitry Andric 184281ad6265SDimitry Andric for (auto &C : OptimizerEarlyEPCallbacks) 184381ad6265SDimitry Andric C(MPM, Level); 184481ad6265SDimitry Andric 1845349cc55cSDimitry Andric if (!VectorizerStartEPCallbacks.empty()) { 1846349cc55cSDimitry Andric FunctionPassManager FPM; 1847349cc55cSDimitry Andric for (auto &C : VectorizerStartEPCallbacks) 1848349cc55cSDimitry Andric C(FPM, Level); 1849349cc55cSDimitry Andric if (!FPM.isEmpty()) 1850349cc55cSDimitry Andric MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); 1851349cc55cSDimitry Andric } 1852349cc55cSDimitry Andric 185381ad6265SDimitry Andric ModulePassManager CoroPM; 185481ad6265SDimitry Andric CoroPM.addPass(CoroEarlyPass()); 1855349cc55cSDimitry Andric CGSCCPassManager CGPM; 1856349cc55cSDimitry Andric CGPM.addPass(CoroSplitPass()); 185781ad6265SDimitry Andric CoroPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM))); 185881ad6265SDimitry Andric CoroPM.addPass(CoroCleanupPass()); 185981ad6265SDimitry Andric CoroPM.addPass(GlobalDCEPass()); 186081ad6265SDimitry Andric MPM.addPass(CoroConditionalWrapper(std::move(CoroPM))); 1861349cc55cSDimitry Andric 1862349cc55cSDimitry Andric for (auto &C : OptimizerLastEPCallbacks) 1863349cc55cSDimitry Andric C(MPM, Level); 1864349cc55cSDimitry Andric 1865349cc55cSDimitry Andric if (LTOPreLink) 1866349cc55cSDimitry Andric addRequiredLTOPreLinkPasses(MPM); 1867349cc55cSDimitry Andric 18684824e7fdSDimitry Andric MPM.addPass(createModuleToFunctionPassAdaptor(AnnotationRemarksPass())); 18694824e7fdSDimitry Andric 1870349cc55cSDimitry Andric return MPM; 1871349cc55cSDimitry Andric } 1872349cc55cSDimitry Andric 1873349cc55cSDimitry Andric AAManager PassBuilder::buildDefaultAAPipeline() { 1874349cc55cSDimitry Andric AAManager AA; 1875349cc55cSDimitry Andric 1876349cc55cSDimitry Andric // The order in which these are registered determines their priority when 1877349cc55cSDimitry Andric // being queried. 1878349cc55cSDimitry Andric 1879349cc55cSDimitry Andric // First we register the basic alias analysis that provides the majority of 1880349cc55cSDimitry Andric // per-function local AA logic. This is a stateless, on-demand local set of 1881349cc55cSDimitry Andric // AA techniques. 1882349cc55cSDimitry Andric AA.registerFunctionAnalysis<BasicAA>(); 1883349cc55cSDimitry Andric 1884349cc55cSDimitry Andric // Next we query fast, specialized alias analyses that wrap IR-embedded 1885349cc55cSDimitry Andric // information about aliasing. 1886349cc55cSDimitry Andric AA.registerFunctionAnalysis<ScopedNoAliasAA>(); 1887349cc55cSDimitry Andric AA.registerFunctionAnalysis<TypeBasedAA>(); 1888349cc55cSDimitry Andric 1889349cc55cSDimitry Andric // Add support for querying global aliasing information when available. 1890349cc55cSDimitry Andric // Because the `AAManager` is a function analysis and `GlobalsAA` is a module 1891349cc55cSDimitry Andric // analysis, all that the `AAManager` can do is query for any *cached* 1892349cc55cSDimitry Andric // results from `GlobalsAA` through a readonly proxy. 1893349cc55cSDimitry Andric AA.registerModuleAnalysis<GlobalsAA>(); 1894349cc55cSDimitry Andric 1895349cc55cSDimitry Andric // Add target-specific alias analyses. 1896349cc55cSDimitry Andric if (TM) 1897349cc55cSDimitry Andric TM->registerDefaultAliasAnalyses(AA); 1898349cc55cSDimitry Andric 1899349cc55cSDimitry Andric return AA; 1900349cc55cSDimitry Andric } 1901