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 1706c3fb27SDimitry Andric #include "llvm/ADT/Statistic.h" 18349cc55cSDimitry Andric #include "llvm/Analysis/AliasAnalysis.h" 19349cc55cSDimitry Andric #include "llvm/Analysis/BasicAliasAnalysis.h" 20349cc55cSDimitry Andric #include "llvm/Analysis/CGSCCPassManager.h" 21349cc55cSDimitry Andric #include "llvm/Analysis/GlobalsModRef.h" 22349cc55cSDimitry Andric #include "llvm/Analysis/InlineAdvisor.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" 3206c3fb27SDimitry Andric #include "llvm/Support/VirtualFileSystem.h" 33349cc55cSDimitry Andric #include "llvm/Target/TargetMachine.h" 34349cc55cSDimitry Andric #include "llvm/Transforms/AggressiveInstCombine/AggressiveInstCombine.h" 35349cc55cSDimitry Andric #include "llvm/Transforms/Coroutines/CoroCleanup.h" 3681ad6265SDimitry Andric #include "llvm/Transforms/Coroutines/CoroConditionalWrapper.h" 37349cc55cSDimitry Andric #include "llvm/Transforms/Coroutines/CoroEarly.h" 38349cc55cSDimitry Andric #include "llvm/Transforms/Coroutines/CoroElide.h" 39349cc55cSDimitry Andric #include "llvm/Transforms/Coroutines/CoroSplit.h" 405f757f3fSDimitry Andric #include "llvm/Transforms/HipStdPar/HipStdPar.h" 41349cc55cSDimitry Andric #include "llvm/Transforms/IPO/AlwaysInliner.h" 42349cc55cSDimitry Andric #include "llvm/Transforms/IPO/Annotation2Metadata.h" 43349cc55cSDimitry Andric #include "llvm/Transforms/IPO/ArgumentPromotion.h" 44349cc55cSDimitry Andric #include "llvm/Transforms/IPO/Attributor.h" 45349cc55cSDimitry Andric #include "llvm/Transforms/IPO/CalledValuePropagation.h" 46349cc55cSDimitry Andric #include "llvm/Transforms/IPO/ConstantMerge.h" 47349cc55cSDimitry Andric #include "llvm/Transforms/IPO/CrossDSOCFI.h" 48349cc55cSDimitry Andric #include "llvm/Transforms/IPO/DeadArgumentElimination.h" 49349cc55cSDimitry Andric #include "llvm/Transforms/IPO/ElimAvailExtern.h" 5006c3fb27SDimitry Andric #include "llvm/Transforms/IPO/EmbedBitcodePass.h" 51349cc55cSDimitry Andric #include "llvm/Transforms/IPO/ForceFunctionAttrs.h" 52349cc55cSDimitry Andric #include "llvm/Transforms/IPO/FunctionAttrs.h" 53349cc55cSDimitry Andric #include "llvm/Transforms/IPO/GlobalDCE.h" 54349cc55cSDimitry Andric #include "llvm/Transforms/IPO/GlobalOpt.h" 55349cc55cSDimitry Andric #include "llvm/Transforms/IPO/GlobalSplit.h" 56349cc55cSDimitry Andric #include "llvm/Transforms/IPO/HotColdSplitting.h" 57349cc55cSDimitry Andric #include "llvm/Transforms/IPO/IROutliner.h" 58349cc55cSDimitry Andric #include "llvm/Transforms/IPO/InferFunctionAttrs.h" 59349cc55cSDimitry Andric #include "llvm/Transforms/IPO/Inliner.h" 60349cc55cSDimitry Andric #include "llvm/Transforms/IPO/LowerTypeTests.h" 6106c3fb27SDimitry Andric #include "llvm/Transforms/IPO/MemProfContextDisambiguation.h" 62349cc55cSDimitry Andric #include "llvm/Transforms/IPO/MergeFunctions.h" 63349cc55cSDimitry Andric #include "llvm/Transforms/IPO/ModuleInliner.h" 64349cc55cSDimitry Andric #include "llvm/Transforms/IPO/OpenMPOpt.h" 65349cc55cSDimitry Andric #include "llvm/Transforms/IPO/PartialInlining.h" 66349cc55cSDimitry Andric #include "llvm/Transforms/IPO/SCCP.h" 67349cc55cSDimitry Andric #include "llvm/Transforms/IPO/SampleProfile.h" 68349cc55cSDimitry Andric #include "llvm/Transforms/IPO/SampleProfileProbe.h" 69349cc55cSDimitry Andric #include "llvm/Transforms/IPO/SyntheticCountsPropagation.h" 70349cc55cSDimitry Andric #include "llvm/Transforms/IPO/WholeProgramDevirt.h" 71349cc55cSDimitry Andric #include "llvm/Transforms/InstCombine/InstCombine.h" 72349cc55cSDimitry Andric #include "llvm/Transforms/Instrumentation/CGProfile.h" 73349cc55cSDimitry Andric #include "llvm/Transforms/Instrumentation/ControlHeightReduction.h" 74349cc55cSDimitry Andric #include "llvm/Transforms/Instrumentation/InstrOrderFile.h" 75349cc55cSDimitry Andric #include "llvm/Transforms/Instrumentation/InstrProfiling.h" 76349cc55cSDimitry Andric #include "llvm/Transforms/Instrumentation/MemProfiler.h" 77*0fca6ea1SDimitry Andric #include "llvm/Transforms/Instrumentation/PGOCtxProfLowering.h" 78*0fca6ea1SDimitry Andric #include "llvm/Transforms/Instrumentation/PGOForceFunctionAttrs.h" 79349cc55cSDimitry Andric #include "llvm/Transforms/Instrumentation/PGOInstrumentation.h" 80349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/ADCE.h" 81349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/AlignmentFromAssumptions.h" 82349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/AnnotationRemarks.h" 83349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/BDCE.h" 84349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/CallSiteSplitting.h" 85349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/ConstraintElimination.h" 86349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/CorrelatedValuePropagation.h" 87349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/DFAJumpThreading.h" 88349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/DeadStoreElimination.h" 89349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/DivRemPairs.h" 90349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/EarlyCSE.h" 91349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/Float2Int.h" 92349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/GVN.h" 93349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/IndVarSimplify.h" 945f757f3fSDimitry Andric #include "llvm/Transforms/Scalar/InferAlignment.h" 95349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/InstSimplifyPass.h" 96*0fca6ea1SDimitry Andric #include "llvm/Transforms/Scalar/JumpTableToSwitch.h" 97349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/JumpThreading.h" 98349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/LICM.h" 99349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/LoopDeletion.h" 100349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/LoopDistribute.h" 101349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/LoopFlatten.h" 102349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/LoopIdiomRecognize.h" 103349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/LoopInstSimplify.h" 104349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/LoopInterchange.h" 105349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/LoopLoadElimination.h" 106349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/LoopPassManager.h" 107349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/LoopRotation.h" 108349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/LoopSimplifyCFG.h" 109349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/LoopSink.h" 110349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/LoopUnrollAndJamPass.h" 111349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/LoopUnrollPass.h" 1125f757f3fSDimitry Andric #include "llvm/Transforms/Scalar/LoopVersioningLICM.h" 113349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/LowerConstantIntrinsics.h" 114349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/LowerExpectIntrinsic.h" 115349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/LowerMatrixIntrinsics.h" 116349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/MemCpyOptimizer.h" 117349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/MergedLoadStoreMotion.h" 118349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/NewGVN.h" 119349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/Reassociate.h" 120349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/SCCP.h" 121349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/SROA.h" 122349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/SimpleLoopUnswitch.h" 123349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/SimplifyCFG.h" 124349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/SpeculativeExecution.h" 125349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/TailRecursionElimination.h" 126349cc55cSDimitry Andric #include "llvm/Transforms/Scalar/WarnMissedTransforms.h" 127349cc55cSDimitry Andric #include "llvm/Transforms/Utils/AddDiscriminators.h" 128349cc55cSDimitry Andric #include "llvm/Transforms/Utils/AssumeBundleBuilder.h" 129349cc55cSDimitry Andric #include "llvm/Transforms/Utils/CanonicalizeAliases.h" 13006c3fb27SDimitry Andric #include "llvm/Transforms/Utils/CountVisits.h" 131*0fca6ea1SDimitry Andric #include "llvm/Transforms/Utils/EntryExitInstrumenter.h" 132349cc55cSDimitry Andric #include "llvm/Transforms/Utils/InjectTLIMappings.h" 133349cc55cSDimitry Andric #include "llvm/Transforms/Utils/LibCallsShrinkWrap.h" 134349cc55cSDimitry Andric #include "llvm/Transforms/Utils/Mem2Reg.h" 13506c3fb27SDimitry Andric #include "llvm/Transforms/Utils/MoveAutoInit.h" 136349cc55cSDimitry Andric #include "llvm/Transforms/Utils/NameAnonGlobals.h" 137349cc55cSDimitry Andric #include "llvm/Transforms/Utils/RelLookupTableConverter.h" 138349cc55cSDimitry Andric #include "llvm/Transforms/Utils/SimplifyCFGOptions.h" 139349cc55cSDimitry Andric #include "llvm/Transforms/Vectorize/LoopVectorize.h" 140349cc55cSDimitry Andric #include "llvm/Transforms/Vectorize/SLPVectorizer.h" 141349cc55cSDimitry Andric #include "llvm/Transforms/Vectorize/VectorCombine.h" 142349cc55cSDimitry Andric 143349cc55cSDimitry Andric using namespace llvm; 144349cc55cSDimitry Andric 145349cc55cSDimitry Andric static cl::opt<InliningAdvisorMode> UseInlineAdvisor( 146349cc55cSDimitry Andric "enable-ml-inliner", cl::init(InliningAdvisorMode::Default), cl::Hidden, 147349cc55cSDimitry Andric cl::desc("Enable ML policy for inliner. Currently trained for -Oz only"), 148349cc55cSDimitry Andric cl::values(clEnumValN(InliningAdvisorMode::Default, "default", 149bdd1243dSDimitry Andric "Heuristics-based inliner version"), 150349cc55cSDimitry Andric clEnumValN(InliningAdvisorMode::Development, "development", 151bdd1243dSDimitry Andric "Use development mode (runtime-loadable model)"), 152349cc55cSDimitry Andric clEnumValN(InliningAdvisorMode::Release, "release", 153bdd1243dSDimitry Andric "Use release mode (AOT-compiled model)"))); 154349cc55cSDimitry Andric 155349cc55cSDimitry Andric static cl::opt<bool> EnableSyntheticCounts( 15681ad6265SDimitry Andric "enable-npm-synthetic-counts", cl::Hidden, 157349cc55cSDimitry Andric cl::desc("Run synthetic function entry count generation " 158349cc55cSDimitry Andric "pass")); 159349cc55cSDimitry Andric 160349cc55cSDimitry Andric /// Flag to enable inline deferral during PGO. 161349cc55cSDimitry Andric static cl::opt<bool> 162349cc55cSDimitry Andric EnablePGOInlineDeferral("enable-npm-pgo-inline-deferral", cl::init(true), 163349cc55cSDimitry Andric cl::Hidden, 164349cc55cSDimitry Andric cl::desc("Enable inline deferral during PGO")); 165349cc55cSDimitry Andric 166349cc55cSDimitry Andric static cl::opt<bool> EnableModuleInliner("enable-module-inliner", 167349cc55cSDimitry Andric cl::init(false), cl::Hidden, 168349cc55cSDimitry Andric cl::desc("Enable module inliner")); 169349cc55cSDimitry Andric 170349cc55cSDimitry Andric static cl::opt<bool> PerformMandatoryInliningsFirst( 1715f757f3fSDimitry Andric "mandatory-inlining-first", cl::init(false), cl::Hidden, 172349cc55cSDimitry Andric cl::desc("Perform mandatory inlinings module-wide, before performing " 173bdd1243dSDimitry Andric "inlining")); 174349cc55cSDimitry Andric 175349cc55cSDimitry Andric static cl::opt<bool> EnableEagerlyInvalidateAnalyses( 176349cc55cSDimitry Andric "eagerly-invalidate-analyses", cl::init(true), cl::Hidden, 177349cc55cSDimitry Andric cl::desc("Eagerly invalidate more analyses in default pipelines")); 178349cc55cSDimitry Andric 1790eae32dcSDimitry Andric static cl::opt<bool> EnableMergeFunctions( 1800eae32dcSDimitry Andric "enable-merge-functions", cl::init(false), cl::Hidden, 1810eae32dcSDimitry Andric cl::desc("Enable function merging as part of the optimization pipeline")); 1820eae32dcSDimitry Andric 183bdd1243dSDimitry Andric static cl::opt<bool> EnablePostPGOLoopRotation( 184bdd1243dSDimitry Andric "enable-post-pgo-loop-rotation", cl::init(true), cl::Hidden, 185bdd1243dSDimitry Andric cl::desc("Run the loop rotation transformation after PGO instrumentation")); 186bdd1243dSDimitry Andric 187bdd1243dSDimitry Andric static cl::opt<bool> EnableGlobalAnalyses( 188bdd1243dSDimitry Andric "enable-global-analyses", cl::init(true), cl::Hidden, 189bdd1243dSDimitry Andric cl::desc("Enable inter-procedural analyses")); 190bdd1243dSDimitry Andric 191bdd1243dSDimitry Andric static cl::opt<bool> 192bdd1243dSDimitry Andric RunPartialInlining("enable-partial-inlining", cl::init(false), cl::Hidden, 193bdd1243dSDimitry Andric cl::desc("Run Partial inlinining pass")); 194bdd1243dSDimitry Andric 195bdd1243dSDimitry Andric static cl::opt<bool> ExtraVectorizerPasses( 196bdd1243dSDimitry Andric "extra-vectorizer-passes", cl::init(false), cl::Hidden, 197bdd1243dSDimitry Andric cl::desc("Run cleanup optimization passes after vectorization")); 198bdd1243dSDimitry Andric 199bdd1243dSDimitry Andric static cl::opt<bool> RunNewGVN("enable-newgvn", cl::init(false), cl::Hidden, 200bdd1243dSDimitry Andric cl::desc("Run the NewGVN pass")); 201bdd1243dSDimitry Andric 202bdd1243dSDimitry Andric static cl::opt<bool> EnableLoopInterchange( 203bdd1243dSDimitry Andric "enable-loopinterchange", cl::init(false), cl::Hidden, 204bdd1243dSDimitry Andric cl::desc("Enable the experimental LoopInterchange Pass")); 205bdd1243dSDimitry Andric 206bdd1243dSDimitry Andric static cl::opt<bool> EnableUnrollAndJam("enable-unroll-and-jam", 207bdd1243dSDimitry Andric cl::init(false), cl::Hidden, 208bdd1243dSDimitry Andric cl::desc("Enable Unroll And Jam Pass")); 209bdd1243dSDimitry Andric 210bdd1243dSDimitry Andric static cl::opt<bool> EnableLoopFlatten("enable-loop-flatten", cl::init(false), 211bdd1243dSDimitry Andric cl::Hidden, 212bdd1243dSDimitry Andric cl::desc("Enable the LoopFlatten Pass")); 213bdd1243dSDimitry Andric 214*0fca6ea1SDimitry Andric // Experimentally allow loop header duplication. This should allow for better 215*0fca6ea1SDimitry Andric // optimization at Oz, since loop-idiom recognition can then recognize things 216*0fca6ea1SDimitry Andric // like memcpy. If this ends up being useful for many targets, we should drop 217*0fca6ea1SDimitry Andric // this flag and make a code generation option that can be controlled 218*0fca6ea1SDimitry Andric // independent of the opt level and exposed through the frontend. 219*0fca6ea1SDimitry Andric static cl::opt<bool> EnableLoopHeaderDuplication( 220*0fca6ea1SDimitry Andric "enable-loop-header-duplication", cl::init(false), cl::Hidden, 221*0fca6ea1SDimitry Andric cl::desc("Enable loop header duplication at any optimization level")); 222*0fca6ea1SDimitry Andric 223bdd1243dSDimitry Andric static cl::opt<bool> 224bdd1243dSDimitry Andric EnableDFAJumpThreading("enable-dfa-jump-thread", 225bdd1243dSDimitry Andric cl::desc("Enable DFA jump threading"), 226bdd1243dSDimitry Andric cl::init(false), cl::Hidden); 227bdd1243dSDimitry Andric 228*0fca6ea1SDimitry Andric // TODO: turn on and remove flag 229*0fca6ea1SDimitry Andric static cl::opt<bool> EnablePGOForceFunctionAttrs( 230*0fca6ea1SDimitry Andric "enable-pgo-force-function-attrs", 231*0fca6ea1SDimitry Andric cl::desc("Enable pass to set function attributes based on PGO profiles"), 232*0fca6ea1SDimitry Andric cl::init(false)); 233*0fca6ea1SDimitry Andric 234bdd1243dSDimitry Andric static cl::opt<bool> 235bdd1243dSDimitry Andric EnableHotColdSplit("hot-cold-split", 236bdd1243dSDimitry Andric cl::desc("Enable hot-cold splitting pass")); 237bdd1243dSDimitry Andric 238bdd1243dSDimitry Andric static cl::opt<bool> EnableIROutliner("ir-outliner", cl::init(false), 239bdd1243dSDimitry Andric cl::Hidden, 240bdd1243dSDimitry Andric cl::desc("Enable ir outliner pass")); 241bdd1243dSDimitry Andric 242bdd1243dSDimitry Andric static cl::opt<bool> 243bdd1243dSDimitry Andric DisablePreInliner("disable-preinline", cl::init(false), cl::Hidden, 244bdd1243dSDimitry Andric cl::desc("Disable pre-instrumentation inliner")); 245bdd1243dSDimitry Andric 246bdd1243dSDimitry Andric static cl::opt<int> PreInlineThreshold( 247bdd1243dSDimitry Andric "preinline-threshold", cl::Hidden, cl::init(75), 248bdd1243dSDimitry Andric cl::desc("Control the amount of inlining in pre-instrumentation inliner " 249bdd1243dSDimitry Andric "(default = 75)")); 250bdd1243dSDimitry Andric 251bdd1243dSDimitry Andric static cl::opt<bool> 252bdd1243dSDimitry Andric EnableGVNHoist("enable-gvn-hoist", 253bdd1243dSDimitry Andric cl::desc("Enable the GVN hoisting pass (default = off)")); 254bdd1243dSDimitry Andric 255bdd1243dSDimitry Andric static cl::opt<bool> 256bdd1243dSDimitry Andric EnableGVNSink("enable-gvn-sink", 257bdd1243dSDimitry Andric cl::desc("Enable the GVN sinking pass (default = off)")); 258bdd1243dSDimitry Andric 259*0fca6ea1SDimitry Andric static cl::opt<bool> EnableJumpTableToSwitch( 260*0fca6ea1SDimitry Andric "enable-jump-table-to-switch", 261*0fca6ea1SDimitry Andric cl::desc("Enable JumpTableToSwitch pass (default = off)")); 262*0fca6ea1SDimitry Andric 263bdd1243dSDimitry Andric // This option is used in simplifying testing SampleFDO optimizations for 264bdd1243dSDimitry Andric // profile loading. 265bdd1243dSDimitry Andric static cl::opt<bool> 266bdd1243dSDimitry Andric EnableCHR("enable-chr", cl::init(true), cl::Hidden, 267bdd1243dSDimitry Andric cl::desc("Enable control height reduction optimization (CHR)")); 268bdd1243dSDimitry Andric 269bdd1243dSDimitry Andric static cl::opt<bool> FlattenedProfileUsed( 270bdd1243dSDimitry Andric "flattened-profile-used", cl::init(false), cl::Hidden, 271bdd1243dSDimitry Andric cl::desc("Indicate the sample profile being used is flattened, i.e., " 272bdd1243dSDimitry Andric "no inline hierachy exists in the profile")); 273bdd1243dSDimitry Andric 274bdd1243dSDimitry Andric static cl::opt<bool> EnableOrderFileInstrumentation( 275bdd1243dSDimitry Andric "enable-order-file-instrumentation", cl::init(false), cl::Hidden, 276bdd1243dSDimitry Andric cl::desc("Enable order file instrumentation (default = off)")); 277bdd1243dSDimitry Andric 278bdd1243dSDimitry Andric static cl::opt<bool> 279bdd1243dSDimitry Andric EnableMatrix("enable-matrix", cl::init(false), cl::Hidden, 280bdd1243dSDimitry Andric cl::desc("Enable lowering of the matrix intrinsics")); 281bdd1243dSDimitry Andric 282bdd1243dSDimitry Andric static cl::opt<bool> EnableConstraintElimination( 28306c3fb27SDimitry Andric "enable-constraint-elimination", cl::init(true), cl::Hidden, 284bdd1243dSDimitry Andric cl::desc( 285bdd1243dSDimitry Andric "Enable pass to eliminate conditions based on linear constraints")); 286bdd1243dSDimitry Andric 287bdd1243dSDimitry Andric static cl::opt<AttributorRunOption> AttributorRun( 288bdd1243dSDimitry Andric "attributor-enable", cl::Hidden, cl::init(AttributorRunOption::NONE), 289bdd1243dSDimitry Andric cl::desc("Enable the attributor inter-procedural deduction pass"), 290bdd1243dSDimitry Andric cl::values(clEnumValN(AttributorRunOption::ALL, "all", 291bdd1243dSDimitry Andric "enable all attributor runs"), 292bdd1243dSDimitry Andric clEnumValN(AttributorRunOption::MODULE, "module", 293bdd1243dSDimitry Andric "enable module-wide attributor runs"), 294bdd1243dSDimitry Andric clEnumValN(AttributorRunOption::CGSCC, "cgscc", 295bdd1243dSDimitry Andric "enable call graph SCC attributor runs"), 296bdd1243dSDimitry Andric clEnumValN(AttributorRunOption::NONE, "none", 297bdd1243dSDimitry Andric "disable attributor runs"))); 298bdd1243dSDimitry Andric 299*0fca6ea1SDimitry Andric static cl::opt<bool> EnableSampledInstr( 300*0fca6ea1SDimitry Andric "enable-sampled-instrumentation", cl::init(false), cl::Hidden, 301*0fca6ea1SDimitry Andric cl::desc("Enable profile instrumentation sampling (default = off)")); 3025f757f3fSDimitry Andric static cl::opt<bool> UseLoopVersioningLICM( 3035f757f3fSDimitry Andric "enable-loop-versioning-licm", cl::init(false), cl::Hidden, 3045f757f3fSDimitry Andric cl::desc("Enable the experimental Loop Versioning LICM pass")); 3055f757f3fSDimitry Andric 3065f757f3fSDimitry Andric namespace llvm { 307*0fca6ea1SDimitry Andric extern cl::opt<bool> EnableMemProfContextDisambiguation; 30806c3fb27SDimitry Andric 3095f757f3fSDimitry Andric extern cl::opt<bool> EnableInferAlignmentPass; 3105f757f3fSDimitry Andric } // namespace llvm 3115f757f3fSDimitry Andric 312349cc55cSDimitry Andric PipelineTuningOptions::PipelineTuningOptions() { 313349cc55cSDimitry Andric LoopInterleaving = true; 314349cc55cSDimitry Andric LoopVectorization = true; 315349cc55cSDimitry Andric SLPVectorization = false; 316349cc55cSDimitry Andric LoopUnrolling = true; 317349cc55cSDimitry Andric ForgetAllSCEVInLoopUnroll = ForgetSCEVInLoopUnroll; 318349cc55cSDimitry Andric LicmMssaOptCap = SetLicmMssaOptCap; 319349cc55cSDimitry Andric LicmMssaNoAccForPromotionCap = SetLicmMssaNoAccForPromotionCap; 320349cc55cSDimitry Andric CallGraphProfile = true; 32106c3fb27SDimitry Andric UnifiedLTO = false; 3220eae32dcSDimitry Andric MergeFunctions = EnableMergeFunctions; 323bdd1243dSDimitry Andric InlinerThreshold = -1; 324349cc55cSDimitry Andric EagerlyInvalidateAnalyses = EnableEagerlyInvalidateAnalyses; 325349cc55cSDimitry Andric } 326349cc55cSDimitry Andric 327349cc55cSDimitry Andric namespace llvm { 328349cc55cSDimitry Andric extern cl::opt<unsigned> MaxDevirtIterations; 329349cc55cSDimitry Andric } // namespace llvm 330349cc55cSDimitry Andric 331349cc55cSDimitry Andric void PassBuilder::invokePeepholeEPCallbacks(FunctionPassManager &FPM, 332349cc55cSDimitry Andric OptimizationLevel Level) { 333349cc55cSDimitry Andric for (auto &C : PeepholeEPCallbacks) 334349cc55cSDimitry Andric C(FPM, Level); 335349cc55cSDimitry Andric } 33606c3fb27SDimitry Andric void PassBuilder::invokeLateLoopOptimizationsEPCallbacks( 33706c3fb27SDimitry Andric LoopPassManager &LPM, OptimizationLevel Level) { 33806c3fb27SDimitry Andric for (auto &C : LateLoopOptimizationsEPCallbacks) 33906c3fb27SDimitry Andric C(LPM, Level); 34006c3fb27SDimitry Andric } 34106c3fb27SDimitry Andric void PassBuilder::invokeLoopOptimizerEndEPCallbacks(LoopPassManager &LPM, 34206c3fb27SDimitry Andric OptimizationLevel Level) { 34306c3fb27SDimitry Andric for (auto &C : LoopOptimizerEndEPCallbacks) 34406c3fb27SDimitry Andric C(LPM, Level); 34506c3fb27SDimitry Andric } 34606c3fb27SDimitry Andric void PassBuilder::invokeScalarOptimizerLateEPCallbacks( 34706c3fb27SDimitry Andric FunctionPassManager &FPM, OptimizationLevel Level) { 34806c3fb27SDimitry Andric for (auto &C : ScalarOptimizerLateEPCallbacks) 34906c3fb27SDimitry Andric C(FPM, Level); 35006c3fb27SDimitry Andric } 35106c3fb27SDimitry Andric void PassBuilder::invokeCGSCCOptimizerLateEPCallbacks(CGSCCPassManager &CGPM, 35206c3fb27SDimitry Andric OptimizationLevel Level) { 35306c3fb27SDimitry Andric for (auto &C : CGSCCOptimizerLateEPCallbacks) 35406c3fb27SDimitry Andric C(CGPM, Level); 35506c3fb27SDimitry Andric } 35606c3fb27SDimitry Andric void PassBuilder::invokeVectorizerStartEPCallbacks(FunctionPassManager &FPM, 35706c3fb27SDimitry Andric OptimizationLevel Level) { 35806c3fb27SDimitry Andric for (auto &C : VectorizerStartEPCallbacks) 35906c3fb27SDimitry Andric C(FPM, Level); 36006c3fb27SDimitry Andric } 36106c3fb27SDimitry Andric void PassBuilder::invokeOptimizerEarlyEPCallbacks(ModulePassManager &MPM, 36206c3fb27SDimitry Andric OptimizationLevel Level) { 36306c3fb27SDimitry Andric for (auto &C : OptimizerEarlyEPCallbacks) 36406c3fb27SDimitry Andric C(MPM, Level); 36506c3fb27SDimitry Andric } 36606c3fb27SDimitry Andric void PassBuilder::invokeOptimizerLastEPCallbacks(ModulePassManager &MPM, 36706c3fb27SDimitry Andric OptimizationLevel Level) { 36806c3fb27SDimitry Andric for (auto &C : OptimizerLastEPCallbacks) 36906c3fb27SDimitry Andric C(MPM, Level); 37006c3fb27SDimitry Andric } 37106c3fb27SDimitry Andric void PassBuilder::invokeFullLinkTimeOptimizationEarlyEPCallbacks( 37206c3fb27SDimitry Andric ModulePassManager &MPM, OptimizationLevel Level) { 37306c3fb27SDimitry Andric for (auto &C : FullLinkTimeOptimizationEarlyEPCallbacks) 37406c3fb27SDimitry Andric C(MPM, Level); 37506c3fb27SDimitry Andric } 37606c3fb27SDimitry Andric void PassBuilder::invokeFullLinkTimeOptimizationLastEPCallbacks( 37706c3fb27SDimitry Andric ModulePassManager &MPM, OptimizationLevel Level) { 37806c3fb27SDimitry Andric for (auto &C : FullLinkTimeOptimizationLastEPCallbacks) 37906c3fb27SDimitry Andric C(MPM, Level); 38006c3fb27SDimitry Andric } 38106c3fb27SDimitry Andric void PassBuilder::invokePipelineStartEPCallbacks(ModulePassManager &MPM, 38206c3fb27SDimitry Andric OptimizationLevel Level) { 38306c3fb27SDimitry Andric for (auto &C : PipelineStartEPCallbacks) 38406c3fb27SDimitry Andric C(MPM, Level); 38506c3fb27SDimitry Andric } 38606c3fb27SDimitry Andric void PassBuilder::invokePipelineEarlySimplificationEPCallbacks( 38706c3fb27SDimitry Andric ModulePassManager &MPM, OptimizationLevel Level) { 38806c3fb27SDimitry Andric for (auto &C : PipelineEarlySimplificationEPCallbacks) 38906c3fb27SDimitry Andric C(MPM, Level); 39006c3fb27SDimitry Andric } 391349cc55cSDimitry Andric 392349cc55cSDimitry Andric // Helper to add AnnotationRemarksPass. 393349cc55cSDimitry Andric static void addAnnotationRemarksPass(ModulePassManager &MPM) { 39481ad6265SDimitry Andric MPM.addPass(createModuleToFunctionPassAdaptor(AnnotationRemarksPass())); 395349cc55cSDimitry Andric } 396349cc55cSDimitry Andric 397349cc55cSDimitry Andric // Helper to check if the current compilation phase is preparing for LTO 398349cc55cSDimitry Andric static bool isLTOPreLink(ThinOrFullLTOPhase Phase) { 399349cc55cSDimitry Andric return Phase == ThinOrFullLTOPhase::ThinLTOPreLink || 400349cc55cSDimitry Andric Phase == ThinOrFullLTOPhase::FullLTOPreLink; 401349cc55cSDimitry Andric } 402349cc55cSDimitry Andric 403349cc55cSDimitry Andric // TODO: Investigate the cost/benefit of tail call elimination on debugging. 404349cc55cSDimitry Andric FunctionPassManager 405349cc55cSDimitry Andric PassBuilder::buildO1FunctionSimplificationPipeline(OptimizationLevel Level, 406349cc55cSDimitry Andric ThinOrFullLTOPhase Phase) { 407349cc55cSDimitry Andric 408349cc55cSDimitry Andric FunctionPassManager FPM; 409349cc55cSDimitry Andric 41006c3fb27SDimitry Andric if (AreStatisticsEnabled()) 41106c3fb27SDimitry Andric FPM.addPass(CountVisitsPass()); 41206c3fb27SDimitry Andric 413349cc55cSDimitry Andric // Form SSA out of local memory accesses after breaking apart aggregates into 414349cc55cSDimitry Andric // scalars. 415bdd1243dSDimitry Andric FPM.addPass(SROAPass(SROAOptions::ModifyCFG)); 416349cc55cSDimitry Andric 417349cc55cSDimitry Andric // Catch trivial redundancies 418349cc55cSDimitry Andric FPM.addPass(EarlyCSEPass(true /* Enable mem-ssa. */)); 419349cc55cSDimitry Andric 420349cc55cSDimitry Andric // Hoisting of scalars and load expressions. 421fb03ea46SDimitry Andric FPM.addPass( 422fb03ea46SDimitry Andric SimplifyCFGPass(SimplifyCFGOptions().convertSwitchRangeToICmp(true))); 423349cc55cSDimitry Andric FPM.addPass(InstCombinePass()); 424349cc55cSDimitry Andric 425349cc55cSDimitry Andric FPM.addPass(LibCallsShrinkWrapPass()); 426349cc55cSDimitry Andric 427349cc55cSDimitry Andric invokePeepholeEPCallbacks(FPM, Level); 428349cc55cSDimitry Andric 429fb03ea46SDimitry Andric FPM.addPass( 430fb03ea46SDimitry Andric SimplifyCFGPass(SimplifyCFGOptions().convertSwitchRangeToICmp(true))); 431349cc55cSDimitry Andric 432349cc55cSDimitry Andric // Form canonically associated expression trees, and simplify the trees using 433349cc55cSDimitry Andric // basic mathematical properties. For example, this will form (nearly) 434349cc55cSDimitry Andric // minimal multiplication trees. 435349cc55cSDimitry Andric FPM.addPass(ReassociatePass()); 436349cc55cSDimitry Andric 437349cc55cSDimitry Andric // Add the primary loop simplification pipeline. 438349cc55cSDimitry Andric // FIXME: Currently this is split into two loop pass pipelines because we run 439349cc55cSDimitry Andric // some function passes in between them. These can and should be removed 440349cc55cSDimitry Andric // and/or replaced by scheduling the loop pass equivalents in the correct 441349cc55cSDimitry Andric // positions. But those equivalent passes aren't powerful enough yet. 442349cc55cSDimitry Andric // Specifically, `SimplifyCFGPass` and `InstCombinePass` are currently still 443349cc55cSDimitry Andric // used. We have `LoopSimplifyCFGPass` which isn't yet powerful enough yet to 444349cc55cSDimitry Andric // fully replace `SimplifyCFGPass`, and the closest to the other we have is 445349cc55cSDimitry Andric // `LoopInstSimplify`. 446349cc55cSDimitry Andric LoopPassManager LPM1, LPM2; 447349cc55cSDimitry Andric 448349cc55cSDimitry Andric // Simplify the loop body. We do this initially to clean up after other loop 449349cc55cSDimitry Andric // passes run, either when iterating on a loop or on inner loops with 450349cc55cSDimitry Andric // implications on the outer loop. 451349cc55cSDimitry Andric LPM1.addPass(LoopInstSimplifyPass()); 452349cc55cSDimitry Andric LPM1.addPass(LoopSimplifyCFGPass()); 453349cc55cSDimitry Andric 454349cc55cSDimitry Andric // Try to remove as much code from the loop header as possible, 455fb03ea46SDimitry Andric // to reduce amount of IR that will have to be duplicated. However, 456fb03ea46SDimitry Andric // do not perform speculative hoisting the first time as LICM 457fb03ea46SDimitry Andric // will destroy metadata that may not need to be destroyed if run 458fb03ea46SDimitry Andric // after loop rotation. 459349cc55cSDimitry Andric // TODO: Investigate promotion cap for O1. 460fb03ea46SDimitry Andric LPM1.addPass(LICMPass(PTO.LicmMssaOptCap, PTO.LicmMssaNoAccForPromotionCap, 461fb03ea46SDimitry Andric /*AllowSpeculation=*/false)); 462349cc55cSDimitry Andric 463349cc55cSDimitry Andric LPM1.addPass(LoopRotatePass(/* Disable header duplication */ true, 464349cc55cSDimitry Andric isLTOPreLink(Phase))); 465349cc55cSDimitry Andric // TODO: Investigate promotion cap for O1. 466fb03ea46SDimitry Andric LPM1.addPass(LICMPass(PTO.LicmMssaOptCap, PTO.LicmMssaNoAccForPromotionCap, 467fb03ea46SDimitry Andric /*AllowSpeculation=*/true)); 468349cc55cSDimitry Andric LPM1.addPass(SimpleLoopUnswitchPass()); 46904eeddc0SDimitry Andric if (EnableLoopFlatten) 47004eeddc0SDimitry Andric LPM1.addPass(LoopFlattenPass()); 471349cc55cSDimitry Andric 472349cc55cSDimitry Andric LPM2.addPass(LoopIdiomRecognizePass()); 473349cc55cSDimitry Andric LPM2.addPass(IndVarSimplifyPass()); 474349cc55cSDimitry Andric 47506c3fb27SDimitry Andric invokeLateLoopOptimizationsEPCallbacks(LPM2, Level); 476349cc55cSDimitry Andric 477349cc55cSDimitry Andric LPM2.addPass(LoopDeletionPass()); 478349cc55cSDimitry Andric 479349cc55cSDimitry Andric if (EnableLoopInterchange) 480349cc55cSDimitry Andric LPM2.addPass(LoopInterchangePass()); 481349cc55cSDimitry Andric 482349cc55cSDimitry Andric // Do not enable unrolling in PreLinkThinLTO phase during sample PGO 483349cc55cSDimitry Andric // because it changes IR to makes profile annotation in back compile 484349cc55cSDimitry Andric // inaccurate. The normal unroller doesn't pay attention to forced full unroll 485349cc55cSDimitry Andric // attributes so we need to make sure and allow the full unroll pass to pay 486349cc55cSDimitry Andric // attention to it. 487349cc55cSDimitry Andric if (Phase != ThinOrFullLTOPhase::ThinLTOPreLink || !PGOOpt || 488349cc55cSDimitry Andric PGOOpt->Action != PGOOptions::SampleUse) 489349cc55cSDimitry Andric LPM2.addPass(LoopFullUnrollPass(Level.getSpeedupLevel(), 490349cc55cSDimitry Andric /* OnlyWhenForced= */ !PTO.LoopUnrolling, 491349cc55cSDimitry Andric PTO.ForgetAllSCEVInLoopUnroll)); 492349cc55cSDimitry Andric 49306c3fb27SDimitry Andric invokeLoopOptimizerEndEPCallbacks(LPM2, Level); 494349cc55cSDimitry Andric 495349cc55cSDimitry Andric FPM.addPass(createFunctionToLoopPassAdaptor(std::move(LPM1), 496349cc55cSDimitry Andric /*UseMemorySSA=*/true, 497349cc55cSDimitry Andric /*UseBlockFrequencyInfo=*/true)); 498fb03ea46SDimitry Andric FPM.addPass( 499fb03ea46SDimitry Andric SimplifyCFGPass(SimplifyCFGOptions().convertSwitchRangeToICmp(true))); 500349cc55cSDimitry Andric FPM.addPass(InstCombinePass()); 501349cc55cSDimitry Andric // The loop passes in LPM2 (LoopFullUnrollPass) do not preserve MemorySSA. 502349cc55cSDimitry Andric // *All* loop passes must preserve it, in order to be able to use it. 503349cc55cSDimitry Andric FPM.addPass(createFunctionToLoopPassAdaptor(std::move(LPM2), 504349cc55cSDimitry Andric /*UseMemorySSA=*/false, 505349cc55cSDimitry Andric /*UseBlockFrequencyInfo=*/false)); 506349cc55cSDimitry Andric 507349cc55cSDimitry Andric // Delete small array after loop unroll. 508bdd1243dSDimitry Andric FPM.addPass(SROAPass(SROAOptions::ModifyCFG)); 509349cc55cSDimitry Andric 510349cc55cSDimitry Andric // Specially optimize memory movement as it doesn't look like dataflow in SSA. 511349cc55cSDimitry Andric FPM.addPass(MemCpyOptPass()); 512349cc55cSDimitry Andric 513349cc55cSDimitry Andric // Sparse conditional constant propagation. 514349cc55cSDimitry Andric // FIXME: It isn't clear why we do this *after* loop passes rather than 515349cc55cSDimitry Andric // before... 516349cc55cSDimitry Andric FPM.addPass(SCCPPass()); 517349cc55cSDimitry Andric 518349cc55cSDimitry Andric // Delete dead bit computations (instcombine runs after to fold away the dead 519349cc55cSDimitry Andric // computations, and then ADCE will run later to exploit any new DCE 520349cc55cSDimitry Andric // opportunities that creates). 521349cc55cSDimitry Andric FPM.addPass(BDCEPass()); 522349cc55cSDimitry Andric 523349cc55cSDimitry Andric // Run instcombine after redundancy and dead bit elimination to exploit 524349cc55cSDimitry Andric // opportunities opened up by them. 525349cc55cSDimitry Andric FPM.addPass(InstCombinePass()); 526349cc55cSDimitry Andric invokePeepholeEPCallbacks(FPM, Level); 527349cc55cSDimitry Andric 528349cc55cSDimitry Andric FPM.addPass(CoroElidePass()); 529349cc55cSDimitry Andric 53006c3fb27SDimitry Andric invokeScalarOptimizerLateEPCallbacks(FPM, Level); 531349cc55cSDimitry Andric 532349cc55cSDimitry Andric // Finally, do an expensive DCE pass to catch all the dead code exposed by 533349cc55cSDimitry Andric // the simplifications and basic cleanup after all the simplifications. 534349cc55cSDimitry Andric // TODO: Investigate if this is too expensive. 535349cc55cSDimitry Andric FPM.addPass(ADCEPass()); 536fb03ea46SDimitry Andric FPM.addPass( 537fb03ea46SDimitry Andric SimplifyCFGPass(SimplifyCFGOptions().convertSwitchRangeToICmp(true))); 538349cc55cSDimitry Andric FPM.addPass(InstCombinePass()); 539349cc55cSDimitry Andric invokePeepholeEPCallbacks(FPM, Level); 540349cc55cSDimitry Andric 541349cc55cSDimitry Andric return FPM; 542349cc55cSDimitry Andric } 543349cc55cSDimitry Andric 544349cc55cSDimitry Andric FunctionPassManager 545349cc55cSDimitry Andric PassBuilder::buildFunctionSimplificationPipeline(OptimizationLevel Level, 546349cc55cSDimitry Andric ThinOrFullLTOPhase Phase) { 547349cc55cSDimitry Andric assert(Level != OptimizationLevel::O0 && "Must request optimizations!"); 548349cc55cSDimitry Andric 549349cc55cSDimitry Andric // The O1 pipeline has a separate pipeline creation function to simplify 550349cc55cSDimitry Andric // construction readability. 551349cc55cSDimitry Andric if (Level.getSpeedupLevel() == 1) 552349cc55cSDimitry Andric return buildO1FunctionSimplificationPipeline(Level, Phase); 553349cc55cSDimitry Andric 554349cc55cSDimitry Andric FunctionPassManager FPM; 555349cc55cSDimitry Andric 55606c3fb27SDimitry Andric if (AreStatisticsEnabled()) 55706c3fb27SDimitry Andric FPM.addPass(CountVisitsPass()); 55806c3fb27SDimitry Andric 559349cc55cSDimitry Andric // Form SSA out of local memory accesses after breaking apart aggregates into 560349cc55cSDimitry Andric // scalars. 561bdd1243dSDimitry Andric FPM.addPass(SROAPass(SROAOptions::ModifyCFG)); 562349cc55cSDimitry Andric 563349cc55cSDimitry Andric // Catch trivial redundancies 564349cc55cSDimitry Andric FPM.addPass(EarlyCSEPass(true /* Enable mem-ssa. */)); 565349cc55cSDimitry Andric if (EnableKnowledgeRetention) 566349cc55cSDimitry Andric FPM.addPass(AssumeSimplifyPass()); 567349cc55cSDimitry Andric 568349cc55cSDimitry Andric // Hoisting of scalars and load expressions. 569349cc55cSDimitry Andric if (EnableGVNHoist) 570349cc55cSDimitry Andric FPM.addPass(GVNHoistPass()); 571349cc55cSDimitry Andric 572349cc55cSDimitry Andric // Global value numbering based sinking. 573349cc55cSDimitry Andric if (EnableGVNSink) { 574349cc55cSDimitry Andric FPM.addPass(GVNSinkPass()); 575fb03ea46SDimitry Andric FPM.addPass( 576fb03ea46SDimitry Andric SimplifyCFGPass(SimplifyCFGOptions().convertSwitchRangeToICmp(true))); 577349cc55cSDimitry Andric } 578349cc55cSDimitry Andric 579349cc55cSDimitry Andric // Speculative execution if the target has divergent branches; otherwise nop. 580349cc55cSDimitry Andric FPM.addPass(SpeculativeExecutionPass(/* OnlyIfDivergentTarget =*/true)); 581349cc55cSDimitry Andric 582349cc55cSDimitry Andric // Optimize based on known information about branches, and cleanup afterward. 583349cc55cSDimitry Andric FPM.addPass(JumpThreadingPass()); 584349cc55cSDimitry Andric FPM.addPass(CorrelatedValuePropagationPass()); 585349cc55cSDimitry Andric 586*0fca6ea1SDimitry Andric // Jump table to switch conversion. 587*0fca6ea1SDimitry Andric if (EnableJumpTableToSwitch) 588*0fca6ea1SDimitry Andric FPM.addPass(JumpTableToSwitchPass()); 589*0fca6ea1SDimitry Andric 590fb03ea46SDimitry Andric FPM.addPass( 591fb03ea46SDimitry Andric SimplifyCFGPass(SimplifyCFGOptions().convertSwitchRangeToICmp(true))); 5920eae32dcSDimitry Andric FPM.addPass(InstCombinePass()); 593349cc55cSDimitry Andric FPM.addPass(AggressiveInstCombinePass()); 594349cc55cSDimitry Andric 595349cc55cSDimitry Andric if (!Level.isOptimizingForSize()) 596349cc55cSDimitry Andric FPM.addPass(LibCallsShrinkWrapPass()); 597349cc55cSDimitry Andric 598349cc55cSDimitry Andric invokePeepholeEPCallbacks(FPM, Level); 599349cc55cSDimitry Andric 600349cc55cSDimitry Andric // For PGO use pipeline, try to optimize memory intrinsics such as memcpy 601349cc55cSDimitry Andric // using the size value profile. Don't perform this when optimizing for size. 602349cc55cSDimitry Andric if (PGOOpt && PGOOpt->Action == PGOOptions::IRUse && 603349cc55cSDimitry Andric !Level.isOptimizingForSize()) 604349cc55cSDimitry Andric FPM.addPass(PGOMemOPSizeOpt()); 605349cc55cSDimitry Andric 606349cc55cSDimitry Andric FPM.addPass(TailCallElimPass()); 607fb03ea46SDimitry Andric FPM.addPass( 608fb03ea46SDimitry Andric SimplifyCFGPass(SimplifyCFGOptions().convertSwitchRangeToICmp(true))); 609349cc55cSDimitry Andric 610349cc55cSDimitry Andric // Form canonically associated expression trees, and simplify the trees using 611349cc55cSDimitry Andric // basic mathematical properties. For example, this will form (nearly) 612349cc55cSDimitry Andric // minimal multiplication trees. 613349cc55cSDimitry Andric FPM.addPass(ReassociatePass()); 614349cc55cSDimitry Andric 6155f757f3fSDimitry Andric if (EnableConstraintElimination) 6165f757f3fSDimitry Andric FPM.addPass(ConstraintEliminationPass()); 6175f757f3fSDimitry Andric 618349cc55cSDimitry Andric // Add the primary loop simplification pipeline. 619349cc55cSDimitry Andric // FIXME: Currently this is split into two loop pass pipelines because we run 620349cc55cSDimitry Andric // some function passes in between them. These can and should be removed 621349cc55cSDimitry Andric // and/or replaced by scheduling the loop pass equivalents in the correct 622349cc55cSDimitry Andric // positions. But those equivalent passes aren't powerful enough yet. 623349cc55cSDimitry Andric // Specifically, `SimplifyCFGPass` and `InstCombinePass` are currently still 624349cc55cSDimitry Andric // used. We have `LoopSimplifyCFGPass` which isn't yet powerful enough yet to 625349cc55cSDimitry Andric // fully replace `SimplifyCFGPass`, and the closest to the other we have is 626349cc55cSDimitry Andric // `LoopInstSimplify`. 627349cc55cSDimitry Andric LoopPassManager LPM1, LPM2; 628349cc55cSDimitry Andric 629349cc55cSDimitry Andric // Simplify the loop body. We do this initially to clean up after other loop 630349cc55cSDimitry Andric // passes run, either when iterating on a loop or on inner loops with 631349cc55cSDimitry Andric // implications on the outer loop. 632349cc55cSDimitry Andric LPM1.addPass(LoopInstSimplifyPass()); 633349cc55cSDimitry Andric LPM1.addPass(LoopSimplifyCFGPass()); 634349cc55cSDimitry Andric 635349cc55cSDimitry Andric // Try to remove as much code from the loop header as possible, 636fb03ea46SDimitry Andric // to reduce amount of IR that will have to be duplicated. However, 637fb03ea46SDimitry Andric // do not perform speculative hoisting the first time as LICM 638fb03ea46SDimitry Andric // will destroy metadata that may not need to be destroyed if run 639fb03ea46SDimitry Andric // after loop rotation. 640349cc55cSDimitry Andric // TODO: Investigate promotion cap for O1. 641fb03ea46SDimitry Andric LPM1.addPass(LICMPass(PTO.LicmMssaOptCap, PTO.LicmMssaNoAccForPromotionCap, 642fb03ea46SDimitry Andric /*AllowSpeculation=*/false)); 643349cc55cSDimitry Andric 644349cc55cSDimitry Andric // Disable header duplication in loop rotation at -Oz. 645*0fca6ea1SDimitry Andric LPM1.addPass(LoopRotatePass(EnableLoopHeaderDuplication || 646*0fca6ea1SDimitry Andric Level != OptimizationLevel::Oz, 647*0fca6ea1SDimitry Andric isLTOPreLink(Phase))); 648349cc55cSDimitry Andric // TODO: Investigate promotion cap for O1. 649fb03ea46SDimitry Andric LPM1.addPass(LICMPass(PTO.LicmMssaOptCap, PTO.LicmMssaNoAccForPromotionCap, 650fb03ea46SDimitry Andric /*AllowSpeculation=*/true)); 651349cc55cSDimitry Andric LPM1.addPass( 65206c3fb27SDimitry Andric SimpleLoopUnswitchPass(/* NonTrivial */ Level == OptimizationLevel::O3)); 65304eeddc0SDimitry Andric if (EnableLoopFlatten) 65404eeddc0SDimitry Andric LPM1.addPass(LoopFlattenPass()); 65504eeddc0SDimitry Andric 656349cc55cSDimitry Andric LPM2.addPass(LoopIdiomRecognizePass()); 657349cc55cSDimitry Andric LPM2.addPass(IndVarSimplifyPass()); 658349cc55cSDimitry Andric 659*0fca6ea1SDimitry Andric { 660*0fca6ea1SDimitry Andric ExtraSimpleLoopUnswitchPassManager ExtraPasses; 661*0fca6ea1SDimitry Andric ExtraPasses.addPass(SimpleLoopUnswitchPass(/* NonTrivial */ Level == 662*0fca6ea1SDimitry Andric OptimizationLevel::O3)); 663*0fca6ea1SDimitry Andric LPM2.addPass(std::move(ExtraPasses)); 664*0fca6ea1SDimitry Andric } 665*0fca6ea1SDimitry Andric 66606c3fb27SDimitry Andric invokeLateLoopOptimizationsEPCallbacks(LPM2, Level); 667349cc55cSDimitry Andric 668349cc55cSDimitry Andric LPM2.addPass(LoopDeletionPass()); 669349cc55cSDimitry Andric 670349cc55cSDimitry Andric if (EnableLoopInterchange) 671349cc55cSDimitry Andric LPM2.addPass(LoopInterchangePass()); 672349cc55cSDimitry Andric 673349cc55cSDimitry Andric // Do not enable unrolling in PreLinkThinLTO phase during sample PGO 674349cc55cSDimitry Andric // because it changes IR to makes profile annotation in back compile 675349cc55cSDimitry Andric // inaccurate. The normal unroller doesn't pay attention to forced full unroll 676349cc55cSDimitry Andric // attributes so we need to make sure and allow the full unroll pass to pay 677349cc55cSDimitry Andric // attention to it. 678349cc55cSDimitry Andric if (Phase != ThinOrFullLTOPhase::ThinLTOPreLink || !PGOOpt || 679349cc55cSDimitry Andric PGOOpt->Action != PGOOptions::SampleUse) 680349cc55cSDimitry Andric LPM2.addPass(LoopFullUnrollPass(Level.getSpeedupLevel(), 681349cc55cSDimitry Andric /* OnlyWhenForced= */ !PTO.LoopUnrolling, 682349cc55cSDimitry Andric PTO.ForgetAllSCEVInLoopUnroll)); 683349cc55cSDimitry Andric 68406c3fb27SDimitry Andric invokeLoopOptimizerEndEPCallbacks(LPM2, Level); 685349cc55cSDimitry Andric 686349cc55cSDimitry Andric FPM.addPass(createFunctionToLoopPassAdaptor(std::move(LPM1), 687349cc55cSDimitry Andric /*UseMemorySSA=*/true, 688349cc55cSDimitry Andric /*UseBlockFrequencyInfo=*/true)); 689fb03ea46SDimitry Andric FPM.addPass( 690fb03ea46SDimitry Andric SimplifyCFGPass(SimplifyCFGOptions().convertSwitchRangeToICmp(true))); 691349cc55cSDimitry Andric FPM.addPass(InstCombinePass()); 692349cc55cSDimitry Andric // The loop passes in LPM2 (LoopIdiomRecognizePass, IndVarSimplifyPass, 693349cc55cSDimitry Andric // LoopDeletionPass and LoopFullUnrollPass) do not preserve MemorySSA. 694349cc55cSDimitry Andric // *All* loop passes must preserve it, in order to be able to use it. 695349cc55cSDimitry Andric FPM.addPass(createFunctionToLoopPassAdaptor(std::move(LPM2), 696349cc55cSDimitry Andric /*UseMemorySSA=*/false, 697349cc55cSDimitry Andric /*UseBlockFrequencyInfo=*/false)); 698349cc55cSDimitry Andric 699349cc55cSDimitry Andric // Delete small array after loop unroll. 700bdd1243dSDimitry Andric FPM.addPass(SROAPass(SROAOptions::ModifyCFG)); 701349cc55cSDimitry Andric 702bdd1243dSDimitry Andric // Try vectorization/scalarization transforms that are both improvements 703bdd1243dSDimitry Andric // themselves and can allow further folds with GVN and InstCombine. 704bdd1243dSDimitry Andric FPM.addPass(VectorCombinePass(/*TryEarlyFoldsOnly=*/true)); 705349cc55cSDimitry Andric 706349cc55cSDimitry Andric // Eliminate redundancies. 707349cc55cSDimitry Andric FPM.addPass(MergedLoadStoreMotionPass()); 708349cc55cSDimitry Andric if (RunNewGVN) 709349cc55cSDimitry Andric FPM.addPass(NewGVNPass()); 710349cc55cSDimitry Andric else 711349cc55cSDimitry Andric FPM.addPass(GVNPass()); 712349cc55cSDimitry Andric 713349cc55cSDimitry Andric // Sparse conditional constant propagation. 714349cc55cSDimitry Andric // FIXME: It isn't clear why we do this *after* loop passes rather than 715349cc55cSDimitry Andric // before... 716349cc55cSDimitry Andric FPM.addPass(SCCPPass()); 717349cc55cSDimitry Andric 718349cc55cSDimitry Andric // Delete dead bit computations (instcombine runs after to fold away the dead 719349cc55cSDimitry Andric // computations, and then ADCE will run later to exploit any new DCE 720349cc55cSDimitry Andric // opportunities that creates). 721349cc55cSDimitry Andric FPM.addPass(BDCEPass()); 722349cc55cSDimitry Andric 723349cc55cSDimitry Andric // Run instcombine after redundancy and dead bit elimination to exploit 724349cc55cSDimitry Andric // opportunities opened up by them. 725349cc55cSDimitry Andric FPM.addPass(InstCombinePass()); 726349cc55cSDimitry Andric invokePeepholeEPCallbacks(FPM, Level); 727349cc55cSDimitry Andric 728349cc55cSDimitry Andric // Re-consider control flow based optimizations after redundancy elimination, 729349cc55cSDimitry Andric // redo DCE, etc. 730*0fca6ea1SDimitry Andric if (EnableDFAJumpThreading) 731349cc55cSDimitry Andric FPM.addPass(DFAJumpThreadingPass()); 732349cc55cSDimitry Andric 733349cc55cSDimitry Andric FPM.addPass(JumpThreadingPass()); 734349cc55cSDimitry Andric FPM.addPass(CorrelatedValuePropagationPass()); 735349cc55cSDimitry Andric 736349cc55cSDimitry Andric // Finally, do an expensive DCE pass to catch all the dead code exposed by 737349cc55cSDimitry Andric // the simplifications and basic cleanup after all the simplifications. 738349cc55cSDimitry Andric // TODO: Investigate if this is too expensive. 739349cc55cSDimitry Andric FPM.addPass(ADCEPass()); 740349cc55cSDimitry Andric 741349cc55cSDimitry Andric // Specially optimize memory movement as it doesn't look like dataflow in SSA. 742349cc55cSDimitry Andric FPM.addPass(MemCpyOptPass()); 743349cc55cSDimitry Andric 744349cc55cSDimitry Andric FPM.addPass(DSEPass()); 74506c3fb27SDimitry Andric FPM.addPass(MoveAutoInitPass()); 74606c3fb27SDimitry Andric 747349cc55cSDimitry Andric FPM.addPass(createFunctionToLoopPassAdaptor( 748fb03ea46SDimitry Andric LICMPass(PTO.LicmMssaOptCap, PTO.LicmMssaNoAccForPromotionCap, 749fb03ea46SDimitry Andric /*AllowSpeculation=*/true), 75006c3fb27SDimitry Andric /*UseMemorySSA=*/true, /*UseBlockFrequencyInfo=*/false)); 751349cc55cSDimitry Andric 752349cc55cSDimitry Andric FPM.addPass(CoroElidePass()); 753349cc55cSDimitry Andric 75406c3fb27SDimitry Andric invokeScalarOptimizerLateEPCallbacks(FPM, Level); 755349cc55cSDimitry Andric 756fb03ea46SDimitry Andric FPM.addPass(SimplifyCFGPass(SimplifyCFGOptions() 757fb03ea46SDimitry Andric .convertSwitchRangeToICmp(true) 758fb03ea46SDimitry Andric .hoistCommonInsts(true) 759fb03ea46SDimitry Andric .sinkCommonInsts(true))); 760349cc55cSDimitry Andric FPM.addPass(InstCombinePass()); 761349cc55cSDimitry Andric invokePeepholeEPCallbacks(FPM, Level); 762349cc55cSDimitry Andric 763349cc55cSDimitry Andric return FPM; 764349cc55cSDimitry Andric } 765349cc55cSDimitry Andric 766349cc55cSDimitry Andric void PassBuilder::addRequiredLTOPreLinkPasses(ModulePassManager &MPM) { 767349cc55cSDimitry Andric MPM.addPass(CanonicalizeAliasesPass()); 768349cc55cSDimitry Andric MPM.addPass(NameAnonGlobalPass()); 769349cc55cSDimitry Andric } 770349cc55cSDimitry Andric 7715f757f3fSDimitry Andric void PassBuilder::addPreInlinerPasses(ModulePassManager &MPM, 7725f757f3fSDimitry Andric OptimizationLevel Level, 7735f757f3fSDimitry Andric ThinOrFullLTOPhase LTOPhase) { 774349cc55cSDimitry Andric assert(Level != OptimizationLevel::O0 && "Not expecting O0 here!"); 7755f757f3fSDimitry Andric if (DisablePreInliner) 7765f757f3fSDimitry Andric return; 777349cc55cSDimitry Andric InlineParams IP; 778349cc55cSDimitry Andric 779349cc55cSDimitry Andric IP.DefaultThreshold = PreInlineThreshold; 780349cc55cSDimitry Andric 781349cc55cSDimitry Andric // FIXME: The hint threshold has the same value used by the regular inliner 782349cc55cSDimitry Andric // when not optimzing for size. This should probably be lowered after 783349cc55cSDimitry Andric // performance testing. 784349cc55cSDimitry Andric // FIXME: this comment is cargo culted from the old pass manager, revisit). 785349cc55cSDimitry Andric IP.HintThreshold = Level.isOptimizingForSize() ? PreInlineThreshold : 325; 78681ad6265SDimitry Andric ModuleInlinerWrapperPass MIWP( 78781ad6265SDimitry Andric IP, /* MandatoryFirst */ true, 78881ad6265SDimitry Andric InlineContext{LTOPhase, InlinePass::EarlyInliner}); 789349cc55cSDimitry Andric CGSCCPassManager &CGPipeline = MIWP.getPM(); 790349cc55cSDimitry Andric 791349cc55cSDimitry Andric FunctionPassManager FPM; 792bdd1243dSDimitry Andric FPM.addPass(SROAPass(SROAOptions::ModifyCFG)); 793349cc55cSDimitry Andric FPM.addPass(EarlyCSEPass()); // Catch trivial redundancies. 794fb03ea46SDimitry Andric FPM.addPass(SimplifyCFGPass(SimplifyCFGOptions().convertSwitchRangeToICmp( 795fb03ea46SDimitry Andric true))); // Merge & remove basic blocks. 796349cc55cSDimitry Andric FPM.addPass(InstCombinePass()); // Combine silly sequences. 797349cc55cSDimitry Andric invokePeepholeEPCallbacks(FPM, Level); 798349cc55cSDimitry Andric 799349cc55cSDimitry Andric CGPipeline.addPass(createCGSCCToFunctionPassAdaptor( 800349cc55cSDimitry Andric std::move(FPM), PTO.EagerlyInvalidateAnalyses)); 801349cc55cSDimitry Andric 802349cc55cSDimitry Andric MPM.addPass(std::move(MIWP)); 803349cc55cSDimitry Andric 804349cc55cSDimitry Andric // Delete anything that is now dead to make sure that we don't instrument 805349cc55cSDimitry Andric // dead code. Instrumentation can end up keeping dead code around and 806349cc55cSDimitry Andric // dramatically increase code size. 807349cc55cSDimitry Andric MPM.addPass(GlobalDCEPass()); 808349cc55cSDimitry Andric } 809349cc55cSDimitry Andric 810*0fca6ea1SDimitry Andric void PassBuilder::addPostPGOLoopRotation(ModulePassManager &MPM, 811*0fca6ea1SDimitry Andric OptimizationLevel Level) { 812*0fca6ea1SDimitry Andric if (EnablePostPGOLoopRotation) { 813*0fca6ea1SDimitry Andric // Disable header duplication in loop rotation at -Oz. 814*0fca6ea1SDimitry Andric MPM.addPass(createModuleToFunctionPassAdaptor( 815*0fca6ea1SDimitry Andric createFunctionToLoopPassAdaptor( 816*0fca6ea1SDimitry Andric LoopRotatePass(EnableLoopHeaderDuplication || 817*0fca6ea1SDimitry Andric Level != OptimizationLevel::Oz), 818*0fca6ea1SDimitry Andric /*UseMemorySSA=*/false, 819*0fca6ea1SDimitry Andric /*UseBlockFrequencyInfo=*/false), 820*0fca6ea1SDimitry Andric PTO.EagerlyInvalidateAnalyses)); 821*0fca6ea1SDimitry Andric } 822*0fca6ea1SDimitry Andric } 823*0fca6ea1SDimitry Andric 8245f757f3fSDimitry Andric void PassBuilder::addPGOInstrPasses(ModulePassManager &MPM, 8255f757f3fSDimitry Andric OptimizationLevel Level, bool RunProfileGen, 8265f757f3fSDimitry Andric bool IsCS, bool AtomicCounterUpdate, 8275f757f3fSDimitry Andric std::string ProfileFile, 8285f757f3fSDimitry Andric std::string ProfileRemappingFile, 8295f757f3fSDimitry Andric IntrusiveRefCntPtr<vfs::FileSystem> FS) { 8305f757f3fSDimitry Andric assert(Level != OptimizationLevel::O0 && "Not expecting O0 here!"); 8315f757f3fSDimitry Andric 832349cc55cSDimitry Andric if (!RunProfileGen) { 833349cc55cSDimitry Andric assert(!ProfileFile.empty() && "Profile use expecting a profile file!"); 83406c3fb27SDimitry Andric MPM.addPass( 83506c3fb27SDimitry Andric PGOInstrumentationUse(ProfileFile, ProfileRemappingFile, IsCS, FS)); 836349cc55cSDimitry Andric // Cache ProfileSummaryAnalysis once to avoid the potential need to insert 837349cc55cSDimitry Andric // RequireAnalysisPass for PSI before subsequent non-module passes. 838349cc55cSDimitry Andric MPM.addPass(RequireAnalysisPass<ProfileSummaryAnalysis, Module>()); 839349cc55cSDimitry Andric return; 840349cc55cSDimitry Andric } 841349cc55cSDimitry Andric 842349cc55cSDimitry Andric // Perform PGO instrumentation. 843349cc55cSDimitry Andric MPM.addPass(PGOInstrumentationGen(IsCS)); 844349cc55cSDimitry Andric 845*0fca6ea1SDimitry Andric addPostPGOLoopRotation(MPM, Level); 846349cc55cSDimitry Andric // Add the profile lowering pass. 847349cc55cSDimitry Andric InstrProfOptions Options; 848349cc55cSDimitry Andric if (!ProfileFile.empty()) 849349cc55cSDimitry Andric Options.InstrProfileOutput = ProfileFile; 850349cc55cSDimitry Andric // Do counter promotion at Level greater than O0. 851349cc55cSDimitry Andric Options.DoCounterPromotion = true; 852349cc55cSDimitry Andric Options.UseBFIInPromotion = IsCS; 853*0fca6ea1SDimitry Andric if (EnableSampledInstr) { 854*0fca6ea1SDimitry Andric Options.Sampling = true; 855*0fca6ea1SDimitry Andric // With sampling, there is little beneifit to enable counter promotion. 856*0fca6ea1SDimitry Andric // But note that sampling does work with counter promotion. 857*0fca6ea1SDimitry Andric Options.DoCounterPromotion = false; 858*0fca6ea1SDimitry Andric } 8595f757f3fSDimitry Andric Options.Atomic = AtomicCounterUpdate; 8605f757f3fSDimitry Andric MPM.addPass(InstrProfilingLoweringPass(Options, IsCS)); 861349cc55cSDimitry Andric } 862349cc55cSDimitry Andric 86306c3fb27SDimitry Andric void PassBuilder::addPGOInstrPassesForO0( 86406c3fb27SDimitry Andric ModulePassManager &MPM, bool RunProfileGen, bool IsCS, 8655f757f3fSDimitry Andric bool AtomicCounterUpdate, std::string ProfileFile, 8665f757f3fSDimitry Andric std::string ProfileRemappingFile, IntrusiveRefCntPtr<vfs::FileSystem> FS) { 867349cc55cSDimitry Andric if (!RunProfileGen) { 868349cc55cSDimitry Andric assert(!ProfileFile.empty() && "Profile use expecting a profile file!"); 86906c3fb27SDimitry Andric MPM.addPass( 87006c3fb27SDimitry Andric PGOInstrumentationUse(ProfileFile, ProfileRemappingFile, IsCS, FS)); 871349cc55cSDimitry Andric // Cache ProfileSummaryAnalysis once to avoid the potential need to insert 872349cc55cSDimitry Andric // RequireAnalysisPass for PSI before subsequent non-module passes. 873349cc55cSDimitry Andric MPM.addPass(RequireAnalysisPass<ProfileSummaryAnalysis, Module>()); 874349cc55cSDimitry Andric return; 875349cc55cSDimitry Andric } 876349cc55cSDimitry Andric 877349cc55cSDimitry Andric // Perform PGO instrumentation. 878349cc55cSDimitry Andric MPM.addPass(PGOInstrumentationGen(IsCS)); 879349cc55cSDimitry Andric // Add the profile lowering pass. 880349cc55cSDimitry Andric InstrProfOptions Options; 881349cc55cSDimitry Andric if (!ProfileFile.empty()) 882349cc55cSDimitry Andric Options.InstrProfileOutput = ProfileFile; 883349cc55cSDimitry Andric // Do not do counter promotion at O0. 884349cc55cSDimitry Andric Options.DoCounterPromotion = false; 885349cc55cSDimitry Andric Options.UseBFIInPromotion = IsCS; 8865f757f3fSDimitry Andric Options.Atomic = AtomicCounterUpdate; 8875f757f3fSDimitry Andric MPM.addPass(InstrProfilingLoweringPass(Options, IsCS)); 888349cc55cSDimitry Andric } 889349cc55cSDimitry Andric 890349cc55cSDimitry Andric static InlineParams getInlineParamsFromOptLevel(OptimizationLevel Level) { 891349cc55cSDimitry Andric return getInlineParams(Level.getSpeedupLevel(), Level.getSizeLevel()); 892349cc55cSDimitry Andric } 893349cc55cSDimitry Andric 894349cc55cSDimitry Andric ModuleInlinerWrapperPass 895349cc55cSDimitry Andric PassBuilder::buildInlinerPipeline(OptimizationLevel Level, 896349cc55cSDimitry Andric ThinOrFullLTOPhase Phase) { 897bdd1243dSDimitry Andric InlineParams IP; 898bdd1243dSDimitry Andric if (PTO.InlinerThreshold == -1) 899bdd1243dSDimitry Andric IP = getInlineParamsFromOptLevel(Level); 900bdd1243dSDimitry Andric else 901bdd1243dSDimitry Andric IP = getInlineParams(PTO.InlinerThreshold); 90281ad6265SDimitry Andric // For PreLinkThinLTO + SamplePGO, set hot-caller threshold to 0 to 90381ad6265SDimitry Andric // disable hot callsite inline (as much as possible [1]) because it makes 90481ad6265SDimitry Andric // profile annotation in the backend inaccurate. 90581ad6265SDimitry Andric // 90681ad6265SDimitry Andric // [1] Note the cost of a function could be below zero due to erased 90781ad6265SDimitry Andric // prologue / epilogue. 908349cc55cSDimitry Andric if (Phase == ThinOrFullLTOPhase::ThinLTOPreLink && PGOOpt && 909349cc55cSDimitry Andric PGOOpt->Action == PGOOptions::SampleUse) 910349cc55cSDimitry Andric IP.HotCallSiteThreshold = 0; 911349cc55cSDimitry Andric 912349cc55cSDimitry Andric if (PGOOpt) 913349cc55cSDimitry Andric IP.EnableDeferral = EnablePGOInlineDeferral; 914349cc55cSDimitry Andric 915bdd1243dSDimitry Andric ModuleInlinerWrapperPass MIWP(IP, PerformMandatoryInliningsFirst, 91681ad6265SDimitry Andric InlineContext{Phase, InlinePass::CGSCCInliner}, 917349cc55cSDimitry Andric UseInlineAdvisor, MaxDevirtIterations); 918349cc55cSDimitry Andric 919349cc55cSDimitry Andric // Require the GlobalsAA analysis for the module so we can query it within 920349cc55cSDimitry Andric // the CGSCC pipeline. 9215f757f3fSDimitry Andric if (EnableGlobalAnalyses) { 922349cc55cSDimitry Andric MIWP.addModulePass(RequireAnalysisPass<GlobalsAA, Module>()); 9235f757f3fSDimitry Andric // Invalidate AAManager so it can be recreated and pick up the newly 9245f757f3fSDimitry Andric // available GlobalsAA. 925349cc55cSDimitry Andric MIWP.addModulePass( 926349cc55cSDimitry Andric createModuleToFunctionPassAdaptor(InvalidateAnalysisPass<AAManager>())); 9275f757f3fSDimitry Andric } 928349cc55cSDimitry Andric 929349cc55cSDimitry Andric // Require the ProfileSummaryAnalysis for the module so we can query it within 930349cc55cSDimitry Andric // the inliner pass. 931349cc55cSDimitry Andric MIWP.addModulePass(RequireAnalysisPass<ProfileSummaryAnalysis, Module>()); 932349cc55cSDimitry Andric 933349cc55cSDimitry Andric // Now begin the main postorder CGSCC pipeline. 934349cc55cSDimitry Andric // FIXME: The current CGSCC pipeline has its origins in the legacy pass 935349cc55cSDimitry Andric // manager and trying to emulate its precise behavior. Much of this doesn't 936349cc55cSDimitry Andric // make a lot of sense and we should revisit the core CGSCC structure. 937349cc55cSDimitry Andric CGSCCPassManager &MainCGPipeline = MIWP.getPM(); 938349cc55cSDimitry Andric 939349cc55cSDimitry Andric // Note: historically, the PruneEH pass was run first to deduce nounwind and 940349cc55cSDimitry Andric // generally clean up exception handling overhead. It isn't clear this is 941349cc55cSDimitry Andric // valuable as the inliner doesn't currently care whether it is inlining an 942349cc55cSDimitry Andric // invoke or a call. 943349cc55cSDimitry Andric 944349cc55cSDimitry Andric if (AttributorRun & AttributorRunOption::CGSCC) 945349cc55cSDimitry Andric MainCGPipeline.addPass(AttributorCGSCCPass()); 946349cc55cSDimitry Andric 94706c3fb27SDimitry Andric // Deduce function attributes. We do another run of this after the function 94806c3fb27SDimitry Andric // simplification pipeline, so this only needs to run when it could affect the 94906c3fb27SDimitry Andric // function simplification pipeline, which is only the case with recursive 95006c3fb27SDimitry Andric // functions. 95106c3fb27SDimitry Andric MainCGPipeline.addPass(PostOrderFunctionAttrsPass(/*SkipNonRecursive*/ true)); 952349cc55cSDimitry Andric 953349cc55cSDimitry Andric // When at O3 add argument promotion to the pass pipeline. 954349cc55cSDimitry Andric // FIXME: It isn't at all clear why this should be limited to O3. 955349cc55cSDimitry Andric if (Level == OptimizationLevel::O3) 956349cc55cSDimitry Andric MainCGPipeline.addPass(ArgumentPromotionPass()); 957349cc55cSDimitry Andric 958349cc55cSDimitry Andric // Try to perform OpenMP specific optimizations. This is a (quick!) no-op if 959349cc55cSDimitry Andric // there are no OpenMP runtime calls present in the module. 960349cc55cSDimitry Andric if (Level == OptimizationLevel::O2 || Level == OptimizationLevel::O3) 961349cc55cSDimitry Andric MainCGPipeline.addPass(OpenMPOptCGSCCPass()); 962349cc55cSDimitry Andric 96306c3fb27SDimitry Andric invokeCGSCCOptimizerLateEPCallbacks(MainCGPipeline, Level); 964349cc55cSDimitry Andric 96506c3fb27SDimitry Andric // Add the core function simplification pipeline nested inside the 966349cc55cSDimitry Andric // CGSCC walk. 967349cc55cSDimitry Andric MainCGPipeline.addPass(createCGSCCToFunctionPassAdaptor( 968349cc55cSDimitry Andric buildFunctionSimplificationPipeline(Level, Phase), 96906c3fb27SDimitry Andric PTO.EagerlyInvalidateAnalyses, /*NoRerun=*/true)); 97006c3fb27SDimitry Andric 97106c3fb27SDimitry Andric // Finally, deduce any function attributes based on the fully simplified 97206c3fb27SDimitry Andric // function. 97306c3fb27SDimitry Andric MainCGPipeline.addPass(PostOrderFunctionAttrsPass()); 97406c3fb27SDimitry Andric 97506c3fb27SDimitry Andric // Mark that the function is fully simplified and that it shouldn't be 97606c3fb27SDimitry Andric // simplified again if we somehow revisit it due to CGSCC mutations unless 97706c3fb27SDimitry Andric // it's been modified since. 97806c3fb27SDimitry Andric MainCGPipeline.addPass(createCGSCCToFunctionPassAdaptor( 97906c3fb27SDimitry Andric RequireAnalysisPass<ShouldNotRunFunctionPassesAnalysis, Function>())); 980349cc55cSDimitry Andric 981349cc55cSDimitry Andric MainCGPipeline.addPass(CoroSplitPass(Level != OptimizationLevel::O0)); 982349cc55cSDimitry Andric 98306c3fb27SDimitry Andric // Make sure we don't affect potential future NoRerun CGSCC adaptors. 984349cc55cSDimitry Andric MIWP.addLateModulePass(createModuleToFunctionPassAdaptor( 985349cc55cSDimitry Andric InvalidateAnalysisPass<ShouldNotRunFunctionPassesAnalysis>())); 986349cc55cSDimitry Andric 987349cc55cSDimitry Andric return MIWP; 988349cc55cSDimitry Andric } 989349cc55cSDimitry Andric 9900eae32dcSDimitry Andric ModulePassManager 991349cc55cSDimitry Andric PassBuilder::buildModuleInlinerPipeline(OptimizationLevel Level, 992349cc55cSDimitry Andric ThinOrFullLTOPhase Phase) { 9930eae32dcSDimitry Andric ModulePassManager MPM; 9940eae32dcSDimitry Andric 995349cc55cSDimitry Andric InlineParams IP = getInlineParamsFromOptLevel(Level); 99681ad6265SDimitry Andric // For PreLinkThinLTO + SamplePGO, set hot-caller threshold to 0 to 99781ad6265SDimitry Andric // disable hot callsite inline (as much as possible [1]) because it makes 99881ad6265SDimitry Andric // profile annotation in the backend inaccurate. 99981ad6265SDimitry Andric // 100081ad6265SDimitry Andric // [1] Note the cost of a function could be below zero due to erased 100181ad6265SDimitry Andric // prologue / epilogue. 1002349cc55cSDimitry Andric if (Phase == ThinOrFullLTOPhase::ThinLTOPreLink && PGOOpt && 1003349cc55cSDimitry Andric PGOOpt->Action == PGOOptions::SampleUse) 1004349cc55cSDimitry Andric IP.HotCallSiteThreshold = 0; 1005349cc55cSDimitry Andric 1006349cc55cSDimitry Andric if (PGOOpt) 1007349cc55cSDimitry Andric IP.EnableDeferral = EnablePGOInlineDeferral; 1008349cc55cSDimitry Andric 1009349cc55cSDimitry Andric // The inline deferral logic is used to avoid losing some 1010349cc55cSDimitry Andric // inlining chance in future. It is helpful in SCC inliner, in which 1011349cc55cSDimitry Andric // inlining is processed in bottom-up order. 1012349cc55cSDimitry Andric // While in module inliner, the inlining order is a priority-based order 1013349cc55cSDimitry Andric // by default. The inline deferral is unnecessary there. So we disable the 1014349cc55cSDimitry Andric // inline deferral logic in module inliner. 1015349cc55cSDimitry Andric IP.EnableDeferral = false; 1016349cc55cSDimitry Andric 101781ad6265SDimitry Andric MPM.addPass(ModuleInlinerPass(IP, UseInlineAdvisor, Phase)); 10180eae32dcSDimitry Andric 10190eae32dcSDimitry Andric MPM.addPass(createModuleToFunctionPassAdaptor( 10200eae32dcSDimitry Andric buildFunctionSimplificationPipeline(Level, Phase), 10210eae32dcSDimitry Andric PTO.EagerlyInvalidateAnalyses)); 10220eae32dcSDimitry Andric 10230eae32dcSDimitry Andric MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor( 10240eae32dcSDimitry Andric CoroSplitPass(Level != OptimizationLevel::O0))); 10250eae32dcSDimitry Andric 10260eae32dcSDimitry Andric return MPM; 1027349cc55cSDimitry Andric } 1028349cc55cSDimitry Andric 1029349cc55cSDimitry Andric ModulePassManager 1030349cc55cSDimitry Andric PassBuilder::buildModuleSimplificationPipeline(OptimizationLevel Level, 1031349cc55cSDimitry Andric ThinOrFullLTOPhase Phase) { 103206c3fb27SDimitry Andric assert(Level != OptimizationLevel::O0 && 103306c3fb27SDimitry Andric "Should not be used for O0 pipeline"); 103406c3fb27SDimitry Andric 103506c3fb27SDimitry Andric assert(Phase != ThinOrFullLTOPhase::FullLTOPostLink && 103606c3fb27SDimitry Andric "FullLTOPostLink shouldn't call buildModuleSimplificationPipeline!"); 103706c3fb27SDimitry Andric 1038349cc55cSDimitry Andric ModulePassManager MPM; 1039349cc55cSDimitry Andric 1040349cc55cSDimitry Andric // Place pseudo probe instrumentation as the first pass of the pipeline to 1041349cc55cSDimitry Andric // minimize the impact of optimization changes. 1042349cc55cSDimitry Andric if (PGOOpt && PGOOpt->PseudoProbeForProfiling && 1043349cc55cSDimitry Andric Phase != ThinOrFullLTOPhase::ThinLTOPostLink) 1044349cc55cSDimitry Andric MPM.addPass(SampleProfileProbePass(TM)); 1045349cc55cSDimitry Andric 1046349cc55cSDimitry Andric bool HasSampleProfile = PGOOpt && (PGOOpt->Action == PGOOptions::SampleUse); 1047349cc55cSDimitry Andric 1048349cc55cSDimitry Andric // In ThinLTO mode, when flattened profile is used, all the available 1049349cc55cSDimitry Andric // profile information will be annotated in PreLink phase so there is 1050349cc55cSDimitry Andric // no need to load the profile again in PostLink. 1051349cc55cSDimitry Andric bool LoadSampleProfile = 1052349cc55cSDimitry Andric HasSampleProfile && 1053349cc55cSDimitry Andric !(FlattenedProfileUsed && Phase == ThinOrFullLTOPhase::ThinLTOPostLink); 1054349cc55cSDimitry Andric 1055349cc55cSDimitry Andric // During the ThinLTO backend phase we perform early indirect call promotion 1056349cc55cSDimitry Andric // here, before globalopt. Otherwise imported available_externally functions 1057349cc55cSDimitry Andric // look unreferenced and are removed. If we are going to load the sample 1058349cc55cSDimitry Andric // profile then defer until later. 1059349cc55cSDimitry Andric // TODO: See if we can move later and consolidate with the location where 1060349cc55cSDimitry Andric // we perform ICP when we are loading a sample profile. 1061349cc55cSDimitry Andric // TODO: We pass HasSampleProfile (whether there was a sample profile file 1062349cc55cSDimitry Andric // passed to the compile) to the SamplePGO flag of ICP. This is used to 1063349cc55cSDimitry Andric // determine whether the new direct calls are annotated with prof metadata. 1064349cc55cSDimitry Andric // Ideally this should be determined from whether the IR is annotated with 1065349cc55cSDimitry Andric // sample profile, and not whether the a sample profile was provided on the 1066349cc55cSDimitry Andric // command line. E.g. for flattened profiles where we will not be reloading 1067349cc55cSDimitry Andric // the sample profile in the ThinLTO backend, we ideally shouldn't have to 1068349cc55cSDimitry Andric // provide the sample profile file. 1069349cc55cSDimitry Andric if (Phase == ThinOrFullLTOPhase::ThinLTOPostLink && !LoadSampleProfile) 1070349cc55cSDimitry Andric MPM.addPass(PGOIndirectCallPromotion(true /* InLTO */, HasSampleProfile)); 1071349cc55cSDimitry Andric 107206c3fb27SDimitry Andric // Create an early function pass manager to cleanup the output of the 107306c3fb27SDimitry Andric // frontend. Not necessary with LTO post link pipelines since the pre link 107406c3fb27SDimitry Andric // pipeline already cleaned up the frontend output. 107506c3fb27SDimitry Andric if (Phase != ThinOrFullLTOPhase::ThinLTOPostLink) { 1076349cc55cSDimitry Andric // Do basic inference of function attributes from known properties of system 1077349cc55cSDimitry Andric // libraries and other oracles. 1078349cc55cSDimitry Andric MPM.addPass(InferFunctionAttrsPass()); 107981ad6265SDimitry Andric MPM.addPass(CoroEarlyPass()); 1080349cc55cSDimitry Andric 1081349cc55cSDimitry Andric FunctionPassManager EarlyFPM; 1082*0fca6ea1SDimitry Andric EarlyFPM.addPass(EntryExitInstrumenterPass(/*PostInlining=*/false)); 1083349cc55cSDimitry Andric // Lower llvm.expect to metadata before attempting transforms. 108406c3fb27SDimitry Andric // Compare/branch metadata may alter the behavior of passes like 108506c3fb27SDimitry Andric // SimplifyCFG. 1086349cc55cSDimitry Andric EarlyFPM.addPass(LowerExpectIntrinsicPass()); 1087349cc55cSDimitry Andric EarlyFPM.addPass(SimplifyCFGPass()); 1088bdd1243dSDimitry Andric EarlyFPM.addPass(SROAPass(SROAOptions::ModifyCFG)); 1089349cc55cSDimitry Andric EarlyFPM.addPass(EarlyCSEPass()); 1090349cc55cSDimitry Andric if (Level == OptimizationLevel::O3) 1091349cc55cSDimitry Andric EarlyFPM.addPass(CallSiteSplittingPass()); 109206c3fb27SDimitry Andric MPM.addPass(createModuleToFunctionPassAdaptor( 109306c3fb27SDimitry Andric std::move(EarlyFPM), PTO.EagerlyInvalidateAnalyses)); 109406c3fb27SDimitry Andric } 1095349cc55cSDimitry Andric 1096349cc55cSDimitry Andric if (LoadSampleProfile) { 1097349cc55cSDimitry Andric // Annotate sample profile right after early FPM to ensure freshness of 1098349cc55cSDimitry Andric // the debug info. 1099349cc55cSDimitry Andric MPM.addPass(SampleProfileLoaderPass(PGOOpt->ProfileFile, 1100349cc55cSDimitry Andric PGOOpt->ProfileRemappingFile, Phase)); 1101349cc55cSDimitry Andric // Cache ProfileSummaryAnalysis once to avoid the potential need to insert 1102349cc55cSDimitry Andric // RequireAnalysisPass for PSI before subsequent non-module passes. 1103349cc55cSDimitry Andric MPM.addPass(RequireAnalysisPass<ProfileSummaryAnalysis, Module>()); 1104349cc55cSDimitry Andric // Do not invoke ICP in the LTOPrelink phase as it makes it hard 1105349cc55cSDimitry Andric // for the profile annotation to be accurate in the LTO backend. 110606c3fb27SDimitry Andric if (!isLTOPreLink(Phase)) 1107349cc55cSDimitry Andric // We perform early indirect call promotion here, before globalopt. 1108349cc55cSDimitry Andric // This is important for the ThinLTO backend phase because otherwise 1109349cc55cSDimitry Andric // imported available_externally functions look unreferenced and are 1110349cc55cSDimitry Andric // removed. 1111349cc55cSDimitry Andric MPM.addPass( 1112349cc55cSDimitry Andric PGOIndirectCallPromotion(true /* IsInLTO */, true /* SamplePGO */)); 1113349cc55cSDimitry Andric } 1114349cc55cSDimitry Andric 1115349cc55cSDimitry Andric // Try to perform OpenMP specific optimizations on the module. This is a 1116349cc55cSDimitry Andric // (quick!) no-op if there are no OpenMP runtime calls present in the module. 1117349cc55cSDimitry Andric MPM.addPass(OpenMPOptPass()); 1118349cc55cSDimitry Andric 1119349cc55cSDimitry Andric if (AttributorRun & AttributorRunOption::MODULE) 1120349cc55cSDimitry Andric MPM.addPass(AttributorPass()); 1121349cc55cSDimitry Andric 1122349cc55cSDimitry Andric // Lower type metadata and the type.test intrinsic in the ThinLTO 1123349cc55cSDimitry Andric // post link pipeline after ICP. This is to enable usage of the type 1124349cc55cSDimitry Andric // tests in ICP sequences. 1125349cc55cSDimitry Andric if (Phase == ThinOrFullLTOPhase::ThinLTOPostLink) 1126349cc55cSDimitry Andric MPM.addPass(LowerTypeTestsPass(nullptr, nullptr, true)); 1127349cc55cSDimitry Andric 112806c3fb27SDimitry Andric invokePipelineEarlySimplificationEPCallbacks(MPM, Level); 1129349cc55cSDimitry Andric 1130349cc55cSDimitry Andric // Interprocedural constant propagation now that basic cleanup has occurred 1131349cc55cSDimitry Andric // and prior to optimizing globals. 1132349cc55cSDimitry Andric // FIXME: This position in the pipeline hasn't been carefully considered in 1133349cc55cSDimitry Andric // years, it should be re-analyzed. 113406c3fb27SDimitry Andric MPM.addPass(IPSCCPPass( 113506c3fb27SDimitry Andric IPSCCPOptions(/*AllowFuncSpec=*/ 1136bdd1243dSDimitry Andric Level != OptimizationLevel::Os && 113706c3fb27SDimitry Andric Level != OptimizationLevel::Oz && 113806c3fb27SDimitry Andric !isLTOPreLink(Phase)))); 1139349cc55cSDimitry Andric 1140349cc55cSDimitry Andric // Attach metadata to indirect call sites indicating the set of functions 1141349cc55cSDimitry Andric // they may target at run-time. This should follow IPSCCP. 1142349cc55cSDimitry Andric MPM.addPass(CalledValuePropagationPass()); 1143349cc55cSDimitry Andric 1144349cc55cSDimitry Andric // Optimize globals to try and fold them into constants. 1145349cc55cSDimitry Andric MPM.addPass(GlobalOptPass()); 1146349cc55cSDimitry Andric 1147349cc55cSDimitry Andric // Create a small function pass pipeline to cleanup after all the global 1148349cc55cSDimitry Andric // optimizations. 1149349cc55cSDimitry Andric FunctionPassManager GlobalCleanupPM; 115006c3fb27SDimitry Andric // FIXME: Should this instead by a run of SROA? 115106c3fb27SDimitry Andric GlobalCleanupPM.addPass(PromotePass()); 1152349cc55cSDimitry Andric GlobalCleanupPM.addPass(InstCombinePass()); 1153349cc55cSDimitry Andric invokePeepholeEPCallbacks(GlobalCleanupPM, Level); 1154fb03ea46SDimitry Andric GlobalCleanupPM.addPass( 1155fb03ea46SDimitry Andric SimplifyCFGPass(SimplifyCFGOptions().convertSwitchRangeToICmp(true))); 1156349cc55cSDimitry Andric MPM.addPass(createModuleToFunctionPassAdaptor(std::move(GlobalCleanupPM), 1157349cc55cSDimitry Andric PTO.EagerlyInvalidateAnalyses)); 1158349cc55cSDimitry Andric 1159*0fca6ea1SDimitry Andric // We already asserted this happens in non-FullLTOPostLink earlier. 1160*0fca6ea1SDimitry Andric const bool IsPreLink = Phase != ThinOrFullLTOPhase::ThinLTOPostLink; 1161*0fca6ea1SDimitry Andric const bool IsPGOPreLink = PGOOpt && IsPreLink; 1162*0fca6ea1SDimitry Andric const bool IsPGOInstrGen = 1163*0fca6ea1SDimitry Andric IsPGOPreLink && PGOOpt->Action == PGOOptions::IRInstr; 1164*0fca6ea1SDimitry Andric const bool IsPGOInstrUse = 1165*0fca6ea1SDimitry Andric IsPGOPreLink && PGOOpt->Action == PGOOptions::IRUse; 1166*0fca6ea1SDimitry Andric const bool IsMemprofUse = IsPGOPreLink && !PGOOpt->MemoryProfile.empty(); 1167*0fca6ea1SDimitry Andric // We don't want to mix pgo ctx gen and pgo gen; we also don't currently 1168*0fca6ea1SDimitry Andric // enable ctx profiling from the frontend. 1169*0fca6ea1SDimitry Andric assert( 1170*0fca6ea1SDimitry Andric !(IsPGOInstrGen && PGOCtxProfLoweringPass::isContextualIRPGOEnabled()) && 1171*0fca6ea1SDimitry Andric "Enabling both instrumented FDO and contextual instrumentation is not " 1172*0fca6ea1SDimitry Andric "supported."); 1173*0fca6ea1SDimitry Andric // Enable contextual profiling instrumentation. 1174*0fca6ea1SDimitry Andric const bool IsCtxProfGen = !IsPGOInstrGen && IsPreLink && 1175*0fca6ea1SDimitry Andric PGOCtxProfLoweringPass::isContextualIRPGOEnabled(); 1176*0fca6ea1SDimitry Andric 1177*0fca6ea1SDimitry Andric if (IsPGOInstrGen || IsPGOInstrUse || IsMemprofUse || IsCtxProfGen) 11785f757f3fSDimitry Andric addPreInlinerPasses(MPM, Level, Phase); 11795f757f3fSDimitry Andric 1180349cc55cSDimitry Andric // Add all the requested passes for instrumentation PGO, if requested. 1181*0fca6ea1SDimitry Andric if (IsPGOInstrGen || IsPGOInstrUse) { 1182349cc55cSDimitry Andric addPGOInstrPasses(MPM, Level, 1183*0fca6ea1SDimitry Andric /*RunProfileGen=*/IsPGOInstrGen, 11845f757f3fSDimitry Andric /*IsCS=*/false, PGOOpt->AtomicCounterUpdate, 11855f757f3fSDimitry Andric PGOOpt->ProfileFile, PGOOpt->ProfileRemappingFile, 11865f757f3fSDimitry Andric PGOOpt->FS); 1187*0fca6ea1SDimitry Andric } else if (IsCtxProfGen) { 1188*0fca6ea1SDimitry Andric MPM.addPass(PGOInstrumentationGen(false)); 1189*0fca6ea1SDimitry Andric addPostPGOLoopRotation(MPM, Level); 1190*0fca6ea1SDimitry Andric MPM.addPass(PGOCtxProfLoweringPass()); 1191349cc55cSDimitry Andric } 1192349cc55cSDimitry Andric 1193*0fca6ea1SDimitry Andric if (IsPGOInstrGen || IsPGOInstrUse || IsCtxProfGen) 1194*0fca6ea1SDimitry Andric MPM.addPass(PGOIndirectCallPromotion(false, false)); 1195*0fca6ea1SDimitry Andric 1196*0fca6ea1SDimitry Andric if (IsPGOPreLink && PGOOpt->CSAction == PGOOptions::CSIRInstr) 1197*0fca6ea1SDimitry Andric MPM.addPass(PGOInstrumentationGenCreateVar(PGOOpt->CSProfileGenFile, 1198*0fca6ea1SDimitry Andric EnableSampledInstr)); 1199*0fca6ea1SDimitry Andric 1200*0fca6ea1SDimitry Andric if (IsMemprofUse) 120106c3fb27SDimitry Andric MPM.addPass(MemProfUsePass(PGOOpt->MemoryProfile, PGOOpt->FS)); 120206c3fb27SDimitry Andric 1203349cc55cSDimitry Andric // Synthesize function entry counts for non-PGO compilation. 1204349cc55cSDimitry Andric if (EnableSyntheticCounts && !PGOOpt) 1205349cc55cSDimitry Andric MPM.addPass(SyntheticCountsPropagation()); 1206349cc55cSDimitry Andric 1207*0fca6ea1SDimitry Andric if (EnablePGOForceFunctionAttrs && PGOOpt) 1208*0fca6ea1SDimitry Andric MPM.addPass(PGOForceFunctionAttrsPass(PGOOpt->ColdOptType)); 1209*0fca6ea1SDimitry Andric 12105f757f3fSDimitry Andric MPM.addPass(AlwaysInlinerPass(/*InsertLifetimeIntrinsics=*/true)); 12115f757f3fSDimitry Andric 1212349cc55cSDimitry Andric if (EnableModuleInliner) 1213349cc55cSDimitry Andric MPM.addPass(buildModuleInlinerPipeline(Level, Phase)); 1214349cc55cSDimitry Andric else 1215349cc55cSDimitry Andric MPM.addPass(buildInlinerPipeline(Level, Phase)); 1216349cc55cSDimitry Andric 1217bdd1243dSDimitry Andric // Remove any dead arguments exposed by cleanups, constant folding globals, 1218bdd1243dSDimitry Andric // and argument promotion. 1219bdd1243dSDimitry Andric MPM.addPass(DeadArgumentEliminationPass()); 1220bdd1243dSDimitry Andric 122181ad6265SDimitry Andric MPM.addPass(CoroCleanupPass()); 122281ad6265SDimitry Andric 122306c3fb27SDimitry Andric // Optimize globals now that functions are fully simplified. 122406c3fb27SDimitry Andric MPM.addPass(GlobalOptPass()); 122506c3fb27SDimitry Andric MPM.addPass(GlobalDCEPass()); 1226349cc55cSDimitry Andric 1227349cc55cSDimitry Andric return MPM; 1228349cc55cSDimitry Andric } 1229349cc55cSDimitry Andric 1230349cc55cSDimitry Andric /// TODO: Should LTO cause any differences to this set of passes? 1231349cc55cSDimitry Andric void PassBuilder::addVectorPasses(OptimizationLevel Level, 1232349cc55cSDimitry Andric FunctionPassManager &FPM, bool IsFullLTO) { 1233349cc55cSDimitry Andric FPM.addPass(LoopVectorizePass( 1234349cc55cSDimitry Andric LoopVectorizeOptions(!PTO.LoopInterleaving, !PTO.LoopVectorization))); 1235349cc55cSDimitry Andric 12365f757f3fSDimitry Andric if (EnableInferAlignmentPass) 12375f757f3fSDimitry Andric FPM.addPass(InferAlignmentPass()); 1238349cc55cSDimitry Andric if (IsFullLTO) { 1239349cc55cSDimitry Andric // The vectorizer may have significantly shortened a loop body; unroll 1240349cc55cSDimitry Andric // again. Unroll small loops to hide loop backedge latency and saturate any 1241349cc55cSDimitry Andric // parallel execution resources of an out-of-order processor. We also then 1242349cc55cSDimitry Andric // need to clean up redundancies and loop invariant code. 1243349cc55cSDimitry Andric // FIXME: It would be really good to use a loop-integrated instruction 1244349cc55cSDimitry Andric // combiner for cleanup here so that the unrolling and LICM can be pipelined 1245349cc55cSDimitry Andric // across the loop nests. 1246349cc55cSDimitry Andric // We do UnrollAndJam in a separate LPM to ensure it happens before unroll 1247349cc55cSDimitry Andric if (EnableUnrollAndJam && PTO.LoopUnrolling) 1248349cc55cSDimitry Andric FPM.addPass(createFunctionToLoopPassAdaptor( 1249349cc55cSDimitry Andric LoopUnrollAndJamPass(Level.getSpeedupLevel()))); 1250349cc55cSDimitry Andric FPM.addPass(LoopUnrollPass(LoopUnrollOptions( 1251349cc55cSDimitry Andric Level.getSpeedupLevel(), /*OnlyWhenForced=*/!PTO.LoopUnrolling, 1252349cc55cSDimitry Andric PTO.ForgetAllSCEVInLoopUnroll))); 1253349cc55cSDimitry Andric FPM.addPass(WarnMissedTransformationsPass()); 1254bdd1243dSDimitry Andric // Now that we are done with loop unrolling, be it either by LoopVectorizer, 1255bdd1243dSDimitry Andric // or LoopUnroll passes, some variable-offset GEP's into alloca's could have 1256bdd1243dSDimitry Andric // become constant-offset, thus enabling SROA and alloca promotion. Do so. 1257bdd1243dSDimitry Andric // NOTE: we are very late in the pipeline, and we don't have any LICM 1258bdd1243dSDimitry Andric // or SimplifyCFG passes scheduled after us, that would cleanup 1259bdd1243dSDimitry Andric // the CFG mess this may created if allowed to modify CFG, so forbid that. 1260bdd1243dSDimitry Andric FPM.addPass(SROAPass(SROAOptions::PreserveCFG)); 1261349cc55cSDimitry Andric } 1262349cc55cSDimitry Andric 1263349cc55cSDimitry Andric if (!IsFullLTO) { 1264349cc55cSDimitry Andric // Eliminate loads by forwarding stores from the previous iteration to loads 1265349cc55cSDimitry Andric // of the current iteration. 1266349cc55cSDimitry Andric FPM.addPass(LoopLoadEliminationPass()); 1267349cc55cSDimitry Andric } 1268349cc55cSDimitry Andric // Cleanup after the loop optimization passes. 1269349cc55cSDimitry Andric FPM.addPass(InstCombinePass()); 1270349cc55cSDimitry Andric 1271349cc55cSDimitry Andric if (Level.getSpeedupLevel() > 1 && ExtraVectorizerPasses) { 12720eae32dcSDimitry Andric ExtraVectorPassManager ExtraPasses; 1273349cc55cSDimitry Andric // At higher optimization levels, try to clean up any runtime overlap and 1274349cc55cSDimitry Andric // alignment checks inserted by the vectorizer. We want to track correlated 1275349cc55cSDimitry Andric // runtime checks for two inner loops in the same outer loop, fold any 1276349cc55cSDimitry Andric // common computations, hoist loop-invariant aspects out of any outer loop, 1277349cc55cSDimitry Andric // and unswitch the runtime checks if possible. Once hoisted, we may have 1278349cc55cSDimitry Andric // dead (or speculatable) control flows or more combining opportunities. 12790eae32dcSDimitry Andric ExtraPasses.addPass(EarlyCSEPass()); 12800eae32dcSDimitry Andric ExtraPasses.addPass(CorrelatedValuePropagationPass()); 12810eae32dcSDimitry Andric ExtraPasses.addPass(InstCombinePass()); 1282349cc55cSDimitry Andric LoopPassManager LPM; 1283fb03ea46SDimitry Andric LPM.addPass(LICMPass(PTO.LicmMssaOptCap, PTO.LicmMssaNoAccForPromotionCap, 1284fb03ea46SDimitry Andric /*AllowSpeculation=*/true)); 1285349cc55cSDimitry Andric LPM.addPass(SimpleLoopUnswitchPass(/* NonTrivial */ Level == 1286349cc55cSDimitry Andric OptimizationLevel::O3)); 12870eae32dcSDimitry Andric ExtraPasses.addPass( 1288349cc55cSDimitry Andric createFunctionToLoopPassAdaptor(std::move(LPM), /*UseMemorySSA=*/true, 1289349cc55cSDimitry Andric /*UseBlockFrequencyInfo=*/true)); 1290fb03ea46SDimitry Andric ExtraPasses.addPass( 1291fb03ea46SDimitry Andric SimplifyCFGPass(SimplifyCFGOptions().convertSwitchRangeToICmp(true))); 12920eae32dcSDimitry Andric ExtraPasses.addPass(InstCombinePass()); 12930eae32dcSDimitry Andric FPM.addPass(std::move(ExtraPasses)); 1294349cc55cSDimitry Andric } 1295349cc55cSDimitry Andric 1296349cc55cSDimitry Andric // Now that we've formed fast to execute loop structures, we do further 1297349cc55cSDimitry Andric // optimizations. These are run afterward as they might block doing complex 1298349cc55cSDimitry Andric // analyses and transforms such as what are needed for loop vectorization. 1299349cc55cSDimitry Andric 1300349cc55cSDimitry Andric // Cleanup after loop vectorization, etc. Simplification passes like CVP and 1301349cc55cSDimitry Andric // GVN, loop transforms, and others have already run, so it's now better to 1302349cc55cSDimitry Andric // convert to more optimized IR using more aggressive simplify CFG options. 1303349cc55cSDimitry Andric // The extra sinking transform can create larger basic blocks, so do this 1304349cc55cSDimitry Andric // before SLP vectorization. 1305349cc55cSDimitry Andric FPM.addPass(SimplifyCFGPass(SimplifyCFGOptions() 1306349cc55cSDimitry Andric .forwardSwitchCondToPhi(true) 1307fb03ea46SDimitry Andric .convertSwitchRangeToICmp(true) 1308349cc55cSDimitry Andric .convertSwitchToLookupTable(true) 1309349cc55cSDimitry Andric .needCanonicalLoops(false) 1310349cc55cSDimitry Andric .hoistCommonInsts(true) 1311349cc55cSDimitry Andric .sinkCommonInsts(true))); 1312349cc55cSDimitry Andric 1313349cc55cSDimitry Andric if (IsFullLTO) { 1314349cc55cSDimitry Andric FPM.addPass(SCCPPass()); 1315349cc55cSDimitry Andric FPM.addPass(InstCombinePass()); 1316349cc55cSDimitry Andric FPM.addPass(BDCEPass()); 1317349cc55cSDimitry Andric } 1318349cc55cSDimitry Andric 1319349cc55cSDimitry Andric // Optimize parallel scalar instruction chains into SIMD instructions. 1320349cc55cSDimitry Andric if (PTO.SLPVectorization) { 1321349cc55cSDimitry Andric FPM.addPass(SLPVectorizerPass()); 1322349cc55cSDimitry Andric if (Level.getSpeedupLevel() > 1 && ExtraVectorizerPasses) { 1323349cc55cSDimitry Andric FPM.addPass(EarlyCSEPass()); 1324349cc55cSDimitry Andric } 1325349cc55cSDimitry Andric } 1326349cc55cSDimitry Andric // Enhance/cleanup vector code. 1327349cc55cSDimitry Andric FPM.addPass(VectorCombinePass()); 1328349cc55cSDimitry Andric 1329349cc55cSDimitry Andric if (!IsFullLTO) { 1330349cc55cSDimitry Andric FPM.addPass(InstCombinePass()); 1331349cc55cSDimitry Andric // Unroll small loops to hide loop backedge latency and saturate any 1332349cc55cSDimitry Andric // parallel execution resources of an out-of-order processor. We also then 1333349cc55cSDimitry Andric // need to clean up redundancies and loop invariant code. 1334349cc55cSDimitry Andric // FIXME: It would be really good to use a loop-integrated instruction 1335349cc55cSDimitry Andric // combiner for cleanup here so that the unrolling and LICM can be pipelined 1336349cc55cSDimitry Andric // across the loop nests. 1337349cc55cSDimitry Andric // We do UnrollAndJam in a separate LPM to ensure it happens before unroll 1338349cc55cSDimitry Andric if (EnableUnrollAndJam && PTO.LoopUnrolling) { 1339349cc55cSDimitry Andric FPM.addPass(createFunctionToLoopPassAdaptor( 1340349cc55cSDimitry Andric LoopUnrollAndJamPass(Level.getSpeedupLevel()))); 1341349cc55cSDimitry Andric } 1342349cc55cSDimitry Andric FPM.addPass(LoopUnrollPass(LoopUnrollOptions( 1343349cc55cSDimitry Andric Level.getSpeedupLevel(), /*OnlyWhenForced=*/!PTO.LoopUnrolling, 1344349cc55cSDimitry Andric PTO.ForgetAllSCEVInLoopUnroll))); 1345349cc55cSDimitry Andric FPM.addPass(WarnMissedTransformationsPass()); 1346bdd1243dSDimitry Andric // Now that we are done with loop unrolling, be it either by LoopVectorizer, 1347bdd1243dSDimitry Andric // or LoopUnroll passes, some variable-offset GEP's into alloca's could have 1348bdd1243dSDimitry Andric // become constant-offset, thus enabling SROA and alloca promotion. Do so. 1349bdd1243dSDimitry Andric // NOTE: we are very late in the pipeline, and we don't have any LICM 1350bdd1243dSDimitry Andric // or SimplifyCFG passes scheduled after us, that would cleanup 1351bdd1243dSDimitry Andric // the CFG mess this may created if allowed to modify CFG, so forbid that. 1352bdd1243dSDimitry Andric FPM.addPass(SROAPass(SROAOptions::PreserveCFG)); 135306c3fb27SDimitry Andric } 135406c3fb27SDimitry Andric 13555f757f3fSDimitry Andric if (EnableInferAlignmentPass) 13565f757f3fSDimitry Andric FPM.addPass(InferAlignmentPass()); 1357349cc55cSDimitry Andric FPM.addPass(InstCombinePass()); 135806c3fb27SDimitry Andric 135906c3fb27SDimitry Andric // This is needed for two reasons: 136006c3fb27SDimitry Andric // 1. It works around problems that instcombine introduces, such as sinking 136106c3fb27SDimitry Andric // expensive FP divides into loops containing multiplications using the 136206c3fb27SDimitry Andric // divide result. 136306c3fb27SDimitry Andric // 2. It helps to clean up some loop-invariant code created by the loop 136406c3fb27SDimitry Andric // unroll pass when IsFullLTO=false. 1365349cc55cSDimitry Andric FPM.addPass(createFunctionToLoopPassAdaptor( 1366fb03ea46SDimitry Andric LICMPass(PTO.LicmMssaOptCap, PTO.LicmMssaNoAccForPromotionCap, 1367fb03ea46SDimitry Andric /*AllowSpeculation=*/true), 136806c3fb27SDimitry Andric /*UseMemorySSA=*/true, /*UseBlockFrequencyInfo=*/false)); 1369349cc55cSDimitry Andric 1370349cc55cSDimitry Andric // Now that we've vectorized and unrolled loops, we may have more refined 1371349cc55cSDimitry Andric // alignment information, try to re-derive it here. 1372349cc55cSDimitry Andric FPM.addPass(AlignmentFromAssumptionsPass()); 1373349cc55cSDimitry Andric } 1374349cc55cSDimitry Andric 1375349cc55cSDimitry Andric ModulePassManager 1376349cc55cSDimitry Andric PassBuilder::buildModuleOptimizationPipeline(OptimizationLevel Level, 137781ad6265SDimitry Andric ThinOrFullLTOPhase LTOPhase) { 137806c3fb27SDimitry Andric const bool LTOPreLink = isLTOPreLink(LTOPhase); 1379349cc55cSDimitry Andric ModulePassManager MPM; 1380349cc55cSDimitry Andric 1381349cc55cSDimitry Andric // Run partial inlining pass to partially inline functions that have 1382349cc55cSDimitry Andric // large bodies. 1383349cc55cSDimitry Andric if (RunPartialInlining) 1384349cc55cSDimitry Andric MPM.addPass(PartialInlinerPass()); 1385349cc55cSDimitry Andric 1386349cc55cSDimitry Andric // Remove avail extern fns and globals definitions since we aren't compiling 1387349cc55cSDimitry Andric // an object file for later LTO. For LTO we want to preserve these so they 1388349cc55cSDimitry Andric // are eligible for inlining at link-time. Note if they are unreferenced they 1389349cc55cSDimitry Andric // will be removed by GlobalDCE later, so this only impacts referenced 1390349cc55cSDimitry Andric // available externally globals. Eventually they will be suppressed during 1391349cc55cSDimitry Andric // codegen, but eliminating here enables more opportunity for GlobalDCE as it 1392349cc55cSDimitry Andric // may make globals referenced by available external functions dead and saves 1393349cc55cSDimitry Andric // running remaining passes on the eliminated functions. These should be 1394349cc55cSDimitry Andric // preserved during prelinking for link-time inlining decisions. 1395349cc55cSDimitry Andric if (!LTOPreLink) 1396349cc55cSDimitry Andric MPM.addPass(EliminateAvailableExternallyPass()); 1397349cc55cSDimitry Andric 1398349cc55cSDimitry Andric if (EnableOrderFileInstrumentation) 1399349cc55cSDimitry Andric MPM.addPass(InstrOrderFilePass()); 1400349cc55cSDimitry Andric 1401349cc55cSDimitry Andric // Do RPO function attribute inference across the module to forward-propagate 1402349cc55cSDimitry Andric // attributes where applicable. 1403349cc55cSDimitry Andric // FIXME: Is this really an optimization rather than a canonicalization? 1404349cc55cSDimitry Andric MPM.addPass(ReversePostOrderFunctionAttrsPass()); 1405349cc55cSDimitry Andric 1406349cc55cSDimitry Andric // Do a post inline PGO instrumentation and use pass. This is a context 1407349cc55cSDimitry Andric // sensitive PGO pass. We don't want to do this in LTOPreLink phrase as 1408349cc55cSDimitry Andric // cross-module inline has not been done yet. The context sensitive 1409349cc55cSDimitry Andric // instrumentation is after all the inlines are done. 1410349cc55cSDimitry Andric if (!LTOPreLink && PGOOpt) { 1411349cc55cSDimitry Andric if (PGOOpt->CSAction == PGOOptions::CSIRInstr) 14125f757f3fSDimitry Andric addPGOInstrPasses(MPM, Level, /*RunProfileGen=*/true, 14135f757f3fSDimitry Andric /*IsCS=*/true, PGOOpt->AtomicCounterUpdate, 14145f757f3fSDimitry Andric PGOOpt->CSProfileGenFile, PGOOpt->ProfileRemappingFile, 14155f757f3fSDimitry Andric PGOOpt->FS); 1416349cc55cSDimitry Andric else if (PGOOpt->CSAction == PGOOptions::CSIRUse) 14175f757f3fSDimitry Andric addPGOInstrPasses(MPM, Level, /*RunProfileGen=*/false, 14185f757f3fSDimitry Andric /*IsCS=*/true, PGOOpt->AtomicCounterUpdate, 14195f757f3fSDimitry Andric PGOOpt->ProfileFile, PGOOpt->ProfileRemappingFile, 14205f757f3fSDimitry Andric PGOOpt->FS); 1421349cc55cSDimitry Andric } 1422349cc55cSDimitry Andric 142381ad6265SDimitry Andric // Re-compute GlobalsAA here prior to function passes. This is particularly 1424349cc55cSDimitry Andric // useful as the above will have inlined, DCE'ed, and function-attr 1425349cc55cSDimitry Andric // propagated everything. We should at this point have a reasonably minimal 1426349cc55cSDimitry Andric // and richly annotated call graph. By computing aliasing and mod/ref 1427349cc55cSDimitry Andric // information for all local globals here, the late loop passes and notably 1428349cc55cSDimitry Andric // the vectorizer will be able to use them to help recognize vectorizable 1429349cc55cSDimitry Andric // memory operations. 14305f757f3fSDimitry Andric if (EnableGlobalAnalyses) 143181ad6265SDimitry Andric MPM.addPass(RecomputeGlobalsAAPass()); 143281ad6265SDimitry Andric 143306c3fb27SDimitry Andric invokeOptimizerEarlyEPCallbacks(MPM, Level); 1434349cc55cSDimitry Andric 1435349cc55cSDimitry Andric FunctionPassManager OptimizePM; 14365f757f3fSDimitry Andric // Scheduling LoopVersioningLICM when inlining is over, because after that 14375f757f3fSDimitry Andric // we may see more accurate aliasing. Reason to run this late is that too 14385f757f3fSDimitry Andric // early versioning may prevent further inlining due to increase of code 14395f757f3fSDimitry Andric // size. Other optimizations which runs later might get benefit of no-alias 14405f757f3fSDimitry Andric // assumption in clone loop. 14415f757f3fSDimitry Andric if (UseLoopVersioningLICM) { 14425f757f3fSDimitry Andric OptimizePM.addPass( 14435f757f3fSDimitry Andric createFunctionToLoopPassAdaptor(LoopVersioningLICMPass())); 14445f757f3fSDimitry Andric // LoopVersioningLICM pass might increase new LICM opportunities. 14455f757f3fSDimitry Andric OptimizePM.addPass(createFunctionToLoopPassAdaptor( 14465f757f3fSDimitry Andric LICMPass(PTO.LicmMssaOptCap, PTO.LicmMssaNoAccForPromotionCap, 14475f757f3fSDimitry Andric /*AllowSpeculation=*/true), 14485f757f3fSDimitry Andric /*USeMemorySSA=*/true, /*UseBlockFrequencyInfo=*/false)); 14495f757f3fSDimitry Andric } 14505f757f3fSDimitry Andric 1451349cc55cSDimitry Andric OptimizePM.addPass(Float2IntPass()); 1452349cc55cSDimitry Andric OptimizePM.addPass(LowerConstantIntrinsicsPass()); 1453349cc55cSDimitry Andric 1454349cc55cSDimitry Andric if (EnableMatrix) { 1455349cc55cSDimitry Andric OptimizePM.addPass(LowerMatrixIntrinsicsPass()); 1456349cc55cSDimitry Andric OptimizePM.addPass(EarlyCSEPass()); 1457349cc55cSDimitry Andric } 1458349cc55cSDimitry Andric 145906c3fb27SDimitry Andric // CHR pass should only be applied with the profile information. 146006c3fb27SDimitry Andric // The check is to check the profile summary information in CHR. 146106c3fb27SDimitry Andric if (EnableCHR && Level == OptimizationLevel::O3) 146206c3fb27SDimitry Andric OptimizePM.addPass(ControlHeightReductionPass()); 146306c3fb27SDimitry Andric 1464349cc55cSDimitry Andric // FIXME: We need to run some loop optimizations to re-rotate loops after 1465349cc55cSDimitry Andric // simplifycfg and others undo their rotation. 1466349cc55cSDimitry Andric 1467349cc55cSDimitry Andric // Optimize the loop execution. These passes operate on entire loop nests 1468349cc55cSDimitry Andric // rather than on each loop in an inside-out manner, and so they are actually 1469349cc55cSDimitry Andric // function passes. 1470349cc55cSDimitry Andric 147106c3fb27SDimitry Andric invokeVectorizerStartEPCallbacks(OptimizePM, Level); 1472349cc55cSDimitry Andric 1473349cc55cSDimitry Andric LoopPassManager LPM; 1474349cc55cSDimitry Andric // First rotate loops that may have been un-rotated by prior passes. 1475349cc55cSDimitry Andric // Disable header duplication at -Oz. 1476*0fca6ea1SDimitry Andric LPM.addPass(LoopRotatePass(EnableLoopHeaderDuplication || 1477*0fca6ea1SDimitry Andric Level != OptimizationLevel::Oz, 1478*0fca6ea1SDimitry Andric LTOPreLink)); 1479349cc55cSDimitry Andric // Some loops may have become dead by now. Try to delete them. 14800eae32dcSDimitry Andric // FIXME: see discussion in https://reviews.llvm.org/D112851, 14810eae32dcSDimitry Andric // this may need to be revisited once we run GVN before loop deletion 14820eae32dcSDimitry Andric // in the simplification pipeline. 1483349cc55cSDimitry Andric LPM.addPass(LoopDeletionPass()); 1484349cc55cSDimitry Andric OptimizePM.addPass(createFunctionToLoopPassAdaptor( 1485349cc55cSDimitry Andric std::move(LPM), /*UseMemorySSA=*/false, /*UseBlockFrequencyInfo=*/false)); 1486349cc55cSDimitry Andric 1487349cc55cSDimitry Andric // Distribute loops to allow partial vectorization. I.e. isolate dependences 1488349cc55cSDimitry Andric // into separate loop that would otherwise inhibit vectorization. This is 1489349cc55cSDimitry Andric // currently only performed for loops marked with the metadata 1490349cc55cSDimitry Andric // llvm.loop.distribute=true or when -enable-loop-distribute is specified. 1491349cc55cSDimitry Andric OptimizePM.addPass(LoopDistributePass()); 1492349cc55cSDimitry Andric 1493349cc55cSDimitry Andric // Populates the VFABI attribute with the scalar-to-vector mappings 1494349cc55cSDimitry Andric // from the TargetLibraryInfo. 1495349cc55cSDimitry Andric OptimizePM.addPass(InjectTLIMappings()); 1496349cc55cSDimitry Andric 1497349cc55cSDimitry Andric addVectorPasses(Level, OptimizePM, /* IsFullLTO */ false); 1498349cc55cSDimitry Andric 1499349cc55cSDimitry Andric // LoopSink pass sinks instructions hoisted by LICM, which serves as a 1500349cc55cSDimitry Andric // canonicalization pass that enables other optimizations. As a result, 1501349cc55cSDimitry Andric // LoopSink pass needs to be a very late IR pass to avoid undoing LICM 1502349cc55cSDimitry Andric // result too early. 1503349cc55cSDimitry Andric OptimizePM.addPass(LoopSinkPass()); 1504349cc55cSDimitry Andric 1505349cc55cSDimitry Andric // And finally clean up LCSSA form before generating code. 1506349cc55cSDimitry Andric OptimizePM.addPass(InstSimplifyPass()); 1507349cc55cSDimitry Andric 1508349cc55cSDimitry Andric // This hoists/decomposes div/rem ops. It should run after other sink/hoist 1509349cc55cSDimitry Andric // passes to avoid re-sinking, but before SimplifyCFG because it can allow 1510349cc55cSDimitry Andric // flattening of blocks. 1511349cc55cSDimitry Andric OptimizePM.addPass(DivRemPairsPass()); 1512349cc55cSDimitry Andric 1513972a253aSDimitry Andric // Try to annotate calls that were created during optimization. 1514972a253aSDimitry Andric OptimizePM.addPass(TailCallElimPass()); 1515972a253aSDimitry Andric 1516349cc55cSDimitry Andric // LoopSink (and other loop passes since the last simplifyCFG) might have 1517349cc55cSDimitry Andric // resulted in single-entry-single-exit or empty blocks. Clean up the CFG. 1518*0fca6ea1SDimitry Andric OptimizePM.addPass(SimplifyCFGPass(SimplifyCFGOptions() 1519*0fca6ea1SDimitry Andric .convertSwitchRangeToICmp(true) 1520*0fca6ea1SDimitry Andric .speculateUnpredictables(true))); 1521349cc55cSDimitry Andric 1522349cc55cSDimitry Andric // Add the core optimizing pipeline. 1523349cc55cSDimitry Andric MPM.addPass(createModuleToFunctionPassAdaptor(std::move(OptimizePM), 1524349cc55cSDimitry Andric PTO.EagerlyInvalidateAnalyses)); 1525349cc55cSDimitry Andric 152606c3fb27SDimitry Andric invokeOptimizerLastEPCallbacks(MPM, Level); 1527349cc55cSDimitry Andric 15280eae32dcSDimitry Andric // Split out cold code. Splitting is done late to avoid hiding context from 15290eae32dcSDimitry Andric // other optimizations and inadvertently regressing performance. The tradeoff 15300eae32dcSDimitry Andric // is that this has a higher code size cost than splitting early. 15310eae32dcSDimitry Andric if (EnableHotColdSplit && !LTOPreLink) 15320eae32dcSDimitry Andric MPM.addPass(HotColdSplittingPass()); 15330eae32dcSDimitry Andric 15340eae32dcSDimitry Andric // Search the code for similar regions of code. If enough similar regions can 15350eae32dcSDimitry Andric // be found where extracting the regions into their own function will decrease 15360eae32dcSDimitry Andric // the size of the program, we extract the regions, a deduplicate the 15370eae32dcSDimitry Andric // structurally similar regions. 15380eae32dcSDimitry Andric if (EnableIROutliner) 15390eae32dcSDimitry Andric MPM.addPass(IROutlinerPass()); 15400eae32dcSDimitry Andric 1541349cc55cSDimitry Andric // Now we need to do some global optimization transforms. 1542349cc55cSDimitry Andric // FIXME: It would seem like these should come first in the optimization 1543349cc55cSDimitry Andric // pipeline and maybe be the bottom of the canonicalization pipeline? Weird 1544349cc55cSDimitry Andric // ordering here. 1545349cc55cSDimitry Andric MPM.addPass(GlobalDCEPass()); 1546349cc55cSDimitry Andric MPM.addPass(ConstantMergePass()); 1547349cc55cSDimitry Andric 1548*0fca6ea1SDimitry Andric // Merge functions if requested. It has a better chance to merge functions 1549*0fca6ea1SDimitry Andric // after ConstantMerge folded jump tables. 1550*0fca6ea1SDimitry Andric if (PTO.MergeFunctions) 1551*0fca6ea1SDimitry Andric MPM.addPass(MergeFunctionsPass()); 1552*0fca6ea1SDimitry Andric 155381ad6265SDimitry Andric if (PTO.CallGraphProfile && !LTOPreLink) 15547a6dacacSDimitry Andric MPM.addPass(CGProfilePass(LTOPhase == ThinOrFullLTOPhase::FullLTOPostLink || 15557a6dacacSDimitry Andric LTOPhase == ThinOrFullLTOPhase::ThinLTOPostLink)); 155681ad6265SDimitry Andric 1557349cc55cSDimitry Andric // TODO: Relative look table converter pass caused an issue when full lto is 1558349cc55cSDimitry Andric // enabled. See https://reviews.llvm.org/D94355 for more details. 1559349cc55cSDimitry Andric // Until the issue fixed, disable this pass during pre-linking phase. 1560349cc55cSDimitry Andric if (!LTOPreLink) 1561349cc55cSDimitry Andric MPM.addPass(RelLookupTableConverterPass()); 1562349cc55cSDimitry Andric 1563349cc55cSDimitry Andric return MPM; 1564349cc55cSDimitry Andric } 1565349cc55cSDimitry Andric 1566349cc55cSDimitry Andric ModulePassManager 1567349cc55cSDimitry Andric PassBuilder::buildPerModuleDefaultPipeline(OptimizationLevel Level, 1568349cc55cSDimitry Andric bool LTOPreLink) { 156906c3fb27SDimitry Andric if (Level == OptimizationLevel::O0) 157006c3fb27SDimitry Andric return buildO0DefaultPipeline(Level, LTOPreLink); 1571349cc55cSDimitry Andric 1572349cc55cSDimitry Andric ModulePassManager MPM; 1573349cc55cSDimitry Andric 1574349cc55cSDimitry Andric // Convert @llvm.global.annotations to !annotation metadata. 1575349cc55cSDimitry Andric MPM.addPass(Annotation2MetadataPass()); 1576349cc55cSDimitry Andric 1577349cc55cSDimitry Andric // Force any function attributes we want the rest of the pipeline to observe. 1578349cc55cSDimitry Andric MPM.addPass(ForceFunctionAttrsPass()); 1579349cc55cSDimitry Andric 1580349cc55cSDimitry Andric if (PGOOpt && PGOOpt->DebugInfoForProfiling) 1581349cc55cSDimitry Andric MPM.addPass(createModuleToFunctionPassAdaptor(AddDiscriminatorsPass())); 1582349cc55cSDimitry Andric 158306c3fb27SDimitry Andric // Apply module pipeline start EP callback. 158406c3fb27SDimitry Andric invokePipelineStartEPCallbacks(MPM, Level); 158506c3fb27SDimitry Andric 158681ad6265SDimitry Andric const ThinOrFullLTOPhase LTOPhase = LTOPreLink 158781ad6265SDimitry Andric ? ThinOrFullLTOPhase::FullLTOPreLink 158881ad6265SDimitry Andric : ThinOrFullLTOPhase::None; 1589349cc55cSDimitry Andric // Add the core simplification pipeline. 159081ad6265SDimitry Andric MPM.addPass(buildModuleSimplificationPipeline(Level, LTOPhase)); 1591349cc55cSDimitry Andric 1592349cc55cSDimitry Andric // Now add the optimization pipeline. 159381ad6265SDimitry Andric MPM.addPass(buildModuleOptimizationPipeline(Level, LTOPhase)); 1594349cc55cSDimitry Andric 1595349cc55cSDimitry Andric if (PGOOpt && PGOOpt->PseudoProbeForProfiling && 1596349cc55cSDimitry Andric PGOOpt->Action == PGOOptions::SampleUse) 1597349cc55cSDimitry Andric MPM.addPass(PseudoProbeUpdatePass()); 1598349cc55cSDimitry Andric 1599349cc55cSDimitry Andric // Emit annotation remarks. 1600349cc55cSDimitry Andric addAnnotationRemarksPass(MPM); 1601349cc55cSDimitry Andric 1602349cc55cSDimitry Andric if (LTOPreLink) 1603349cc55cSDimitry Andric addRequiredLTOPreLinkPasses(MPM); 160406c3fb27SDimitry Andric return MPM; 160506c3fb27SDimitry Andric } 1606349cc55cSDimitry Andric 160706c3fb27SDimitry Andric ModulePassManager 16087a6dacacSDimitry Andric PassBuilder::buildFatLTODefaultPipeline(OptimizationLevel Level, bool ThinLTO, 16097a6dacacSDimitry Andric bool EmitSummary) { 161006c3fb27SDimitry Andric ModulePassManager MPM; 16117a6dacacSDimitry Andric if (ThinLTO) 16125f757f3fSDimitry Andric MPM.addPass(buildThinLTOPreLinkDefaultPipeline(Level)); 16137a6dacacSDimitry Andric else 16147a6dacacSDimitry Andric MPM.addPass(buildLTOPreLinkDefaultPipeline(Level)); 16157a6dacacSDimitry Andric MPM.addPass(EmbedBitcodePass(ThinLTO, EmitSummary)); 16165f757f3fSDimitry Andric 16177a6dacacSDimitry Andric // Use the ThinLTO post-link pipeline with sample profiling 16187a6dacacSDimitry Andric if (ThinLTO && PGOOpt && PGOOpt->Action == PGOOptions::SampleUse) 16195f757f3fSDimitry Andric MPM.addPass(buildThinLTODefaultPipeline(Level, /*ImportSummary=*/nullptr)); 16205f757f3fSDimitry Andric else { 16215f757f3fSDimitry Andric // otherwise, just use module optimization 16225f757f3fSDimitry Andric MPM.addPass( 16235f757f3fSDimitry Andric buildModuleOptimizationPipeline(Level, ThinOrFullLTOPhase::None)); 16245f757f3fSDimitry Andric // Emit annotation remarks. 16255f757f3fSDimitry Andric addAnnotationRemarksPass(MPM); 16265f757f3fSDimitry Andric } 1627349cc55cSDimitry Andric return MPM; 1628349cc55cSDimitry Andric } 1629349cc55cSDimitry Andric 1630349cc55cSDimitry Andric ModulePassManager 1631349cc55cSDimitry Andric PassBuilder::buildThinLTOPreLinkDefaultPipeline(OptimizationLevel Level) { 163206c3fb27SDimitry Andric if (Level == OptimizationLevel::O0) 163306c3fb27SDimitry Andric return buildO0DefaultPipeline(Level, /*LTOPreLink*/true); 1634349cc55cSDimitry Andric 1635349cc55cSDimitry Andric ModulePassManager MPM; 1636349cc55cSDimitry Andric 1637349cc55cSDimitry Andric // Convert @llvm.global.annotations to !annotation metadata. 1638349cc55cSDimitry Andric MPM.addPass(Annotation2MetadataPass()); 1639349cc55cSDimitry Andric 1640349cc55cSDimitry Andric // Force any function attributes we want the rest of the pipeline to observe. 1641349cc55cSDimitry Andric MPM.addPass(ForceFunctionAttrsPass()); 1642349cc55cSDimitry Andric 1643349cc55cSDimitry Andric if (PGOOpt && PGOOpt->DebugInfoForProfiling) 1644349cc55cSDimitry Andric MPM.addPass(createModuleToFunctionPassAdaptor(AddDiscriminatorsPass())); 1645349cc55cSDimitry Andric 1646349cc55cSDimitry Andric // Apply module pipeline start EP callback. 164706c3fb27SDimitry Andric invokePipelineStartEPCallbacks(MPM, Level); 1648349cc55cSDimitry Andric 1649349cc55cSDimitry Andric // If we are planning to perform ThinLTO later, we don't bloat the code with 1650349cc55cSDimitry Andric // unrolling/vectorization/... now. Just simplify the module as much as we 1651349cc55cSDimitry Andric // can. 1652349cc55cSDimitry Andric MPM.addPass(buildModuleSimplificationPipeline( 1653349cc55cSDimitry Andric Level, ThinOrFullLTOPhase::ThinLTOPreLink)); 1654349cc55cSDimitry Andric 1655349cc55cSDimitry Andric // Run partial inlining pass to partially inline functions that have 1656349cc55cSDimitry Andric // large bodies. 1657349cc55cSDimitry Andric // FIXME: It isn't clear whether this is really the right place to run this 1658349cc55cSDimitry Andric // in ThinLTO. Because there is another canonicalization and simplification 1659349cc55cSDimitry Andric // phase that will run after the thin link, running this here ends up with 1660349cc55cSDimitry Andric // less information than will be available later and it may grow functions in 1661349cc55cSDimitry Andric // ways that aren't beneficial. 1662349cc55cSDimitry Andric if (RunPartialInlining) 1663349cc55cSDimitry Andric MPM.addPass(PartialInlinerPass()); 1664349cc55cSDimitry Andric 1665349cc55cSDimitry Andric if (PGOOpt && PGOOpt->PseudoProbeForProfiling && 1666349cc55cSDimitry Andric PGOOpt->Action == PGOOptions::SampleUse) 1667349cc55cSDimitry Andric MPM.addPass(PseudoProbeUpdatePass()); 1668349cc55cSDimitry Andric 1669bdd1243dSDimitry Andric // Handle Optimizer{Early,Last}EPCallbacks added by clang on PreLink. Actual 1670bdd1243dSDimitry Andric // optimization is going to be done in PostLink stage, but clang can't add 1671bdd1243dSDimitry Andric // callbacks there in case of in-process ThinLTO called by linker. 167206c3fb27SDimitry Andric invokeOptimizerEarlyEPCallbacks(MPM, Level); 167306c3fb27SDimitry Andric invokeOptimizerLastEPCallbacks(MPM, Level); 1674349cc55cSDimitry Andric 1675349cc55cSDimitry Andric // Emit annotation remarks. 1676349cc55cSDimitry Andric addAnnotationRemarksPass(MPM); 1677349cc55cSDimitry Andric 1678349cc55cSDimitry Andric addRequiredLTOPreLinkPasses(MPM); 1679349cc55cSDimitry Andric 1680349cc55cSDimitry Andric return MPM; 1681349cc55cSDimitry Andric } 1682349cc55cSDimitry Andric 1683349cc55cSDimitry Andric ModulePassManager PassBuilder::buildThinLTODefaultPipeline( 1684349cc55cSDimitry Andric OptimizationLevel Level, const ModuleSummaryIndex *ImportSummary) { 1685349cc55cSDimitry Andric ModulePassManager MPM; 1686349cc55cSDimitry Andric 1687349cc55cSDimitry Andric if (ImportSummary) { 168806c3fb27SDimitry Andric // For ThinLTO we must apply the context disambiguation decisions early, to 168906c3fb27SDimitry Andric // ensure we can correctly match the callsites to summary data. 169006c3fb27SDimitry Andric if (EnableMemProfContextDisambiguation) 169106c3fb27SDimitry Andric MPM.addPass(MemProfContextDisambiguation(ImportSummary)); 169206c3fb27SDimitry Andric 1693349cc55cSDimitry Andric // These passes import type identifier resolutions for whole-program 1694349cc55cSDimitry Andric // devirtualization and CFI. They must run early because other passes may 1695349cc55cSDimitry Andric // disturb the specific instruction patterns that these passes look for, 1696349cc55cSDimitry Andric // creating dependencies on resolutions that may not appear in the summary. 1697349cc55cSDimitry Andric // 1698349cc55cSDimitry Andric // For example, GVN may transform the pattern assume(type.test) appearing in 1699349cc55cSDimitry Andric // two basic blocks into assume(phi(type.test, type.test)), which would 1700349cc55cSDimitry Andric // transform a dependency on a WPD resolution into a dependency on a type 1701349cc55cSDimitry Andric // identifier resolution for CFI. 1702349cc55cSDimitry Andric // 1703349cc55cSDimitry Andric // Also, WPD has access to more precise information than ICP and can 1704349cc55cSDimitry Andric // devirtualize more effectively, so it should operate on the IR first. 1705349cc55cSDimitry Andric // 1706349cc55cSDimitry Andric // The WPD and LowerTypeTest passes need to run at -O0 to lower type 1707349cc55cSDimitry Andric // metadata and intrinsics. 1708349cc55cSDimitry Andric MPM.addPass(WholeProgramDevirtPass(nullptr, ImportSummary)); 1709349cc55cSDimitry Andric MPM.addPass(LowerTypeTestsPass(nullptr, ImportSummary)); 1710349cc55cSDimitry Andric } 1711349cc55cSDimitry Andric 1712349cc55cSDimitry Andric if (Level == OptimizationLevel::O0) { 1713349cc55cSDimitry Andric // Run a second time to clean up any type tests left behind by WPD for use 1714349cc55cSDimitry Andric // in ICP. 1715349cc55cSDimitry Andric MPM.addPass(LowerTypeTestsPass(nullptr, nullptr, true)); 1716349cc55cSDimitry Andric // Drop available_externally and unreferenced globals. This is necessary 1717349cc55cSDimitry Andric // with ThinLTO in order to avoid leaving undefined references to dead 1718349cc55cSDimitry Andric // globals in the object file. 1719349cc55cSDimitry Andric MPM.addPass(EliminateAvailableExternallyPass()); 1720349cc55cSDimitry Andric MPM.addPass(GlobalDCEPass()); 1721349cc55cSDimitry Andric return MPM; 1722349cc55cSDimitry Andric } 1723349cc55cSDimitry Andric 1724349cc55cSDimitry Andric // Add the core simplification pipeline. 1725349cc55cSDimitry Andric MPM.addPass(buildModuleSimplificationPipeline( 1726349cc55cSDimitry Andric Level, ThinOrFullLTOPhase::ThinLTOPostLink)); 1727349cc55cSDimitry Andric 1728349cc55cSDimitry Andric // Now add the optimization pipeline. 172981ad6265SDimitry Andric MPM.addPass(buildModuleOptimizationPipeline( 173081ad6265SDimitry Andric Level, ThinOrFullLTOPhase::ThinLTOPostLink)); 1731349cc55cSDimitry Andric 1732349cc55cSDimitry Andric // Emit annotation remarks. 1733349cc55cSDimitry Andric addAnnotationRemarksPass(MPM); 1734349cc55cSDimitry Andric 1735349cc55cSDimitry Andric return MPM; 1736349cc55cSDimitry Andric } 1737349cc55cSDimitry Andric 1738349cc55cSDimitry Andric ModulePassManager 1739349cc55cSDimitry Andric PassBuilder::buildLTOPreLinkDefaultPipeline(OptimizationLevel Level) { 1740349cc55cSDimitry Andric // FIXME: We should use a customized pre-link pipeline! 1741349cc55cSDimitry Andric return buildPerModuleDefaultPipeline(Level, 1742349cc55cSDimitry Andric /* LTOPreLink */ true); 1743349cc55cSDimitry Andric } 1744349cc55cSDimitry Andric 1745349cc55cSDimitry Andric ModulePassManager 1746349cc55cSDimitry Andric PassBuilder::buildLTODefaultPipeline(OptimizationLevel Level, 1747349cc55cSDimitry Andric ModuleSummaryIndex *ExportSummary) { 1748349cc55cSDimitry Andric ModulePassManager MPM; 1749349cc55cSDimitry Andric 175006c3fb27SDimitry Andric invokeFullLinkTimeOptimizationEarlyEPCallbacks(MPM, Level); 175181ad6265SDimitry Andric 1752349cc55cSDimitry Andric // Create a function that performs CFI checks for cross-DSO calls with targets 1753349cc55cSDimitry Andric // in the current module. 1754349cc55cSDimitry Andric MPM.addPass(CrossDSOCFIPass()); 1755349cc55cSDimitry Andric 1756349cc55cSDimitry Andric if (Level == OptimizationLevel::O0) { 1757349cc55cSDimitry Andric // The WPD and LowerTypeTest passes need to run at -O0 to lower type 1758349cc55cSDimitry Andric // metadata and intrinsics. 1759349cc55cSDimitry Andric MPM.addPass(WholeProgramDevirtPass(ExportSummary, nullptr)); 1760349cc55cSDimitry Andric MPM.addPass(LowerTypeTestsPass(ExportSummary, nullptr)); 1761349cc55cSDimitry Andric // Run a second time to clean up any type tests left behind by WPD for use 1762349cc55cSDimitry Andric // in ICP. 1763349cc55cSDimitry Andric MPM.addPass(LowerTypeTestsPass(nullptr, nullptr, true)); 1764349cc55cSDimitry Andric 176506c3fb27SDimitry Andric invokeFullLinkTimeOptimizationLastEPCallbacks(MPM, Level); 176681ad6265SDimitry Andric 1767349cc55cSDimitry Andric // Emit annotation remarks. 1768349cc55cSDimitry Andric addAnnotationRemarksPass(MPM); 1769349cc55cSDimitry Andric 1770349cc55cSDimitry Andric return MPM; 1771349cc55cSDimitry Andric } 1772349cc55cSDimitry Andric 1773349cc55cSDimitry Andric if (PGOOpt && PGOOpt->Action == PGOOptions::SampleUse) { 1774349cc55cSDimitry Andric // Load sample profile before running the LTO optimization pipeline. 1775349cc55cSDimitry Andric MPM.addPass(SampleProfileLoaderPass(PGOOpt->ProfileFile, 1776349cc55cSDimitry Andric PGOOpt->ProfileRemappingFile, 1777349cc55cSDimitry Andric ThinOrFullLTOPhase::FullLTOPostLink)); 1778349cc55cSDimitry Andric // Cache ProfileSummaryAnalysis once to avoid the potential need to insert 1779349cc55cSDimitry Andric // RequireAnalysisPass for PSI before subsequent non-module passes. 1780349cc55cSDimitry Andric MPM.addPass(RequireAnalysisPass<ProfileSummaryAnalysis, Module>()); 1781349cc55cSDimitry Andric } 1782349cc55cSDimitry Andric 17831fd87a68SDimitry Andric // Try to run OpenMP optimizations, quick no-op if no OpenMP metadata present. 17841ac55f4cSDimitry Andric MPM.addPass(OpenMPOptPass(ThinOrFullLTOPhase::FullLTOPostLink)); 17851fd87a68SDimitry Andric 1786349cc55cSDimitry Andric // Remove unused virtual tables to improve the quality of code generated by 1787349cc55cSDimitry Andric // whole-program devirtualization and bitset lowering. 178806c3fb27SDimitry Andric MPM.addPass(GlobalDCEPass(/*InLTOPostLink=*/true)); 1789349cc55cSDimitry Andric 1790349cc55cSDimitry Andric // Do basic inference of function attributes from known properties of system 1791349cc55cSDimitry Andric // libraries and other oracles. 1792349cc55cSDimitry Andric MPM.addPass(InferFunctionAttrsPass()); 1793349cc55cSDimitry Andric 1794349cc55cSDimitry Andric if (Level.getSpeedupLevel() > 1) { 1795349cc55cSDimitry Andric MPM.addPass(createModuleToFunctionPassAdaptor( 179681ad6265SDimitry Andric CallSiteSplittingPass(), PTO.EagerlyInvalidateAnalyses)); 1797349cc55cSDimitry Andric 1798349cc55cSDimitry Andric // Indirect call promotion. This should promote all the targets that are 1799349cc55cSDimitry Andric // left by the earlier promotion pass that promotes intra-module targets. 1800349cc55cSDimitry Andric // This two-step promotion is to save the compile time. For LTO, it should 1801349cc55cSDimitry Andric // produce the same result as if we only do promotion here. 1802349cc55cSDimitry Andric MPM.addPass(PGOIndirectCallPromotion( 1803349cc55cSDimitry Andric true /* InLTO */, PGOOpt && PGOOpt->Action == PGOOptions::SampleUse)); 1804349cc55cSDimitry Andric 1805349cc55cSDimitry Andric // Propagate constants at call sites into the functions they call. This 1806349cc55cSDimitry Andric // opens opportunities for globalopt (and inlining) by substituting function 1807349cc55cSDimitry Andric // pointers passed as arguments to direct uses of functions. 1808bdd1243dSDimitry Andric MPM.addPass(IPSCCPPass(IPSCCPOptions(/*AllowFuncSpec=*/ 1809bdd1243dSDimitry Andric Level != OptimizationLevel::Os && 1810bdd1243dSDimitry Andric Level != OptimizationLevel::Oz))); 1811349cc55cSDimitry Andric 1812349cc55cSDimitry Andric // Attach metadata to indirect call sites indicating the set of functions 1813349cc55cSDimitry Andric // they may target at run-time. This should follow IPSCCP. 1814349cc55cSDimitry Andric MPM.addPass(CalledValuePropagationPass()); 1815349cc55cSDimitry Andric } 1816349cc55cSDimitry Andric 1817349cc55cSDimitry Andric // Now deduce any function attributes based in the current code. 1818349cc55cSDimitry Andric MPM.addPass( 1819349cc55cSDimitry Andric createModuleToPostOrderCGSCCPassAdaptor(PostOrderFunctionAttrsPass())); 1820349cc55cSDimitry Andric 1821349cc55cSDimitry Andric // Do RPO function attribute inference across the module to forward-propagate 1822349cc55cSDimitry Andric // attributes where applicable. 1823349cc55cSDimitry Andric // FIXME: Is this really an optimization rather than a canonicalization? 1824349cc55cSDimitry Andric MPM.addPass(ReversePostOrderFunctionAttrsPass()); 1825349cc55cSDimitry Andric 1826349cc55cSDimitry Andric // Use in-range annotations on GEP indices to split globals where beneficial. 1827349cc55cSDimitry Andric MPM.addPass(GlobalSplitPass()); 1828349cc55cSDimitry Andric 1829349cc55cSDimitry Andric // Run whole program optimization of virtual call when the list of callees 1830349cc55cSDimitry Andric // is fixed. 1831349cc55cSDimitry Andric MPM.addPass(WholeProgramDevirtPass(ExportSummary, nullptr)); 1832349cc55cSDimitry Andric 1833349cc55cSDimitry Andric // Stop here at -O1. 1834349cc55cSDimitry Andric if (Level == OptimizationLevel::O1) { 1835349cc55cSDimitry Andric // The LowerTypeTestsPass needs to run to lower type metadata and the 1836349cc55cSDimitry Andric // type.test intrinsics. The pass does nothing if CFI is disabled. 1837349cc55cSDimitry Andric MPM.addPass(LowerTypeTestsPass(ExportSummary, nullptr)); 1838349cc55cSDimitry Andric // Run a second time to clean up any type tests left behind by WPD for use 1839349cc55cSDimitry Andric // in ICP (which is performed earlier than this in the regular LTO 1840349cc55cSDimitry Andric // pipeline). 1841349cc55cSDimitry Andric MPM.addPass(LowerTypeTestsPass(nullptr, nullptr, true)); 1842349cc55cSDimitry Andric 184306c3fb27SDimitry Andric invokeFullLinkTimeOptimizationLastEPCallbacks(MPM, Level); 184481ad6265SDimitry Andric 1845349cc55cSDimitry Andric // Emit annotation remarks. 1846349cc55cSDimitry Andric addAnnotationRemarksPass(MPM); 1847349cc55cSDimitry Andric 1848349cc55cSDimitry Andric return MPM; 1849349cc55cSDimitry Andric } 1850349cc55cSDimitry Andric 1851349cc55cSDimitry Andric // Optimize globals to try and fold them into constants. 1852349cc55cSDimitry Andric MPM.addPass(GlobalOptPass()); 1853349cc55cSDimitry Andric 1854349cc55cSDimitry Andric // Promote any localized globals to SSA registers. 1855349cc55cSDimitry Andric MPM.addPass(createModuleToFunctionPassAdaptor(PromotePass())); 1856349cc55cSDimitry Andric 1857349cc55cSDimitry Andric // Linking modules together can lead to duplicate global constant, only 1858349cc55cSDimitry Andric // keep one copy of each constant. 1859349cc55cSDimitry Andric MPM.addPass(ConstantMergePass()); 1860349cc55cSDimitry Andric 18611ac55f4cSDimitry Andric // Remove unused arguments from functions. 18621ac55f4cSDimitry Andric MPM.addPass(DeadArgumentEliminationPass()); 18631ac55f4cSDimitry Andric 1864349cc55cSDimitry Andric // Reduce the code after globalopt and ipsccp. Both can open up significant 1865349cc55cSDimitry Andric // simplification opportunities, and both can propagate functions through 1866349cc55cSDimitry Andric // function pointers. When this happens, we often have to resolve varargs 1867349cc55cSDimitry Andric // calls, etc, so let instcombine do this. 1868349cc55cSDimitry Andric FunctionPassManager PeepholeFPM; 18690eae32dcSDimitry Andric PeepholeFPM.addPass(InstCombinePass()); 187006c3fb27SDimitry Andric if (Level.getSpeedupLevel() > 1) 1871349cc55cSDimitry Andric PeepholeFPM.addPass(AggressiveInstCombinePass()); 1872349cc55cSDimitry Andric invokePeepholeEPCallbacks(PeepholeFPM, Level); 1873349cc55cSDimitry Andric 1874349cc55cSDimitry Andric MPM.addPass(createModuleToFunctionPassAdaptor(std::move(PeepholeFPM), 1875349cc55cSDimitry Andric PTO.EagerlyInvalidateAnalyses)); 1876349cc55cSDimitry Andric 1877349cc55cSDimitry Andric // Note: historically, the PruneEH pass was run first to deduce nounwind and 1878349cc55cSDimitry Andric // generally clean up exception handling overhead. It isn't clear this is 1879349cc55cSDimitry Andric // valuable as the inliner doesn't currently care whether it is inlining an 1880349cc55cSDimitry Andric // invoke or a call. 1881349cc55cSDimitry Andric // Run the inliner now. 188206c3fb27SDimitry Andric if (EnableModuleInliner) { 188306c3fb27SDimitry Andric MPM.addPass(ModuleInlinerPass(getInlineParamsFromOptLevel(Level), 188406c3fb27SDimitry Andric UseInlineAdvisor, 188506c3fb27SDimitry Andric ThinOrFullLTOPhase::FullLTOPostLink)); 188606c3fb27SDimitry Andric } else { 188781ad6265SDimitry Andric MPM.addPass(ModuleInlinerWrapperPass( 188881ad6265SDimitry Andric getInlineParamsFromOptLevel(Level), 188981ad6265SDimitry Andric /* MandatoryFirst */ true, 189081ad6265SDimitry Andric InlineContext{ThinOrFullLTOPhase::FullLTOPostLink, 189181ad6265SDimitry Andric InlinePass::CGSCCInliner})); 189206c3fb27SDimitry Andric } 189306c3fb27SDimitry Andric 189406c3fb27SDimitry Andric // Perform context disambiguation after inlining, since that would reduce the 189506c3fb27SDimitry Andric // amount of additional cloning required to distinguish the allocation 189606c3fb27SDimitry Andric // contexts. 189706c3fb27SDimitry Andric if (EnableMemProfContextDisambiguation) 189806c3fb27SDimitry Andric MPM.addPass(MemProfContextDisambiguation()); 1899349cc55cSDimitry Andric 1900349cc55cSDimitry Andric // Optimize globals again after we ran the inliner. 1901349cc55cSDimitry Andric MPM.addPass(GlobalOptPass()); 1902349cc55cSDimitry Andric 19031ac55f4cSDimitry Andric // Run the OpenMPOpt pass again after global optimizations. 19041ac55f4cSDimitry Andric MPM.addPass(OpenMPOptPass(ThinOrFullLTOPhase::FullLTOPostLink)); 19051ac55f4cSDimitry Andric 1906349cc55cSDimitry Andric // Garbage collect dead functions. 190706c3fb27SDimitry Andric MPM.addPass(GlobalDCEPass(/*InLTOPostLink=*/true)); 1908349cc55cSDimitry Andric 1909349cc55cSDimitry Andric // If we didn't decide to inline a function, check to see if we can 1910349cc55cSDimitry Andric // transform it to pass arguments by value instead of by reference. 1911349cc55cSDimitry Andric MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(ArgumentPromotionPass())); 1912349cc55cSDimitry Andric 1913349cc55cSDimitry Andric FunctionPassManager FPM; 1914349cc55cSDimitry Andric // The IPO Passes may leave cruft around. Clean up after them. 1915349cc55cSDimitry Andric FPM.addPass(InstCombinePass()); 1916349cc55cSDimitry Andric invokePeepholeEPCallbacks(FPM, Level); 1917349cc55cSDimitry Andric 1918bdd1243dSDimitry Andric if (EnableConstraintElimination) 1919bdd1243dSDimitry Andric FPM.addPass(ConstraintEliminationPass()); 1920bdd1243dSDimitry Andric 192181ad6265SDimitry Andric FPM.addPass(JumpThreadingPass()); 1922349cc55cSDimitry Andric 1923349cc55cSDimitry Andric // Do a post inline PGO instrumentation and use pass. This is a context 1924349cc55cSDimitry Andric // sensitive PGO pass. 1925349cc55cSDimitry Andric if (PGOOpt) { 1926349cc55cSDimitry Andric if (PGOOpt->CSAction == PGOOptions::CSIRInstr) 19275f757f3fSDimitry Andric addPGOInstrPasses(MPM, Level, /*RunProfileGen=*/true, 19285f757f3fSDimitry Andric /*IsCS=*/true, PGOOpt->AtomicCounterUpdate, 19295f757f3fSDimitry Andric PGOOpt->CSProfileGenFile, PGOOpt->ProfileRemappingFile, 19305f757f3fSDimitry Andric PGOOpt->FS); 1931349cc55cSDimitry Andric else if (PGOOpt->CSAction == PGOOptions::CSIRUse) 19325f757f3fSDimitry Andric addPGOInstrPasses(MPM, Level, /*RunProfileGen=*/false, 19335f757f3fSDimitry Andric /*IsCS=*/true, PGOOpt->AtomicCounterUpdate, 19345f757f3fSDimitry Andric PGOOpt->ProfileFile, PGOOpt->ProfileRemappingFile, 19355f757f3fSDimitry Andric PGOOpt->FS); 1936349cc55cSDimitry Andric } 1937349cc55cSDimitry Andric 1938349cc55cSDimitry Andric // Break up allocas 1939bdd1243dSDimitry Andric FPM.addPass(SROAPass(SROAOptions::ModifyCFG)); 1940349cc55cSDimitry Andric 1941349cc55cSDimitry Andric // LTO provides additional opportunities for tailcall elimination due to 1942349cc55cSDimitry Andric // link-time inlining, and visibility of nocapture attribute. 1943349cc55cSDimitry Andric FPM.addPass(TailCallElimPass()); 1944349cc55cSDimitry Andric 1945349cc55cSDimitry Andric // Run a few AA driver optimizations here and now to cleanup the code. 1946349cc55cSDimitry Andric MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM), 1947349cc55cSDimitry Andric PTO.EagerlyInvalidateAnalyses)); 1948349cc55cSDimitry Andric 1949349cc55cSDimitry Andric MPM.addPass( 1950349cc55cSDimitry Andric createModuleToPostOrderCGSCCPassAdaptor(PostOrderFunctionAttrsPass())); 1951349cc55cSDimitry Andric 1952349cc55cSDimitry Andric // Require the GlobalsAA analysis for the module so we can query it within 1953349cc55cSDimitry Andric // MainFPM. 19545f757f3fSDimitry Andric if (EnableGlobalAnalyses) { 1955349cc55cSDimitry Andric MPM.addPass(RequireAnalysisPass<GlobalsAA, Module>()); 19565f757f3fSDimitry Andric // Invalidate AAManager so it can be recreated and pick up the newly 19575f757f3fSDimitry Andric // available GlobalsAA. 1958349cc55cSDimitry Andric MPM.addPass( 1959349cc55cSDimitry Andric createModuleToFunctionPassAdaptor(InvalidateAnalysisPass<AAManager>())); 19605f757f3fSDimitry Andric } 1961349cc55cSDimitry Andric 1962349cc55cSDimitry Andric FunctionPassManager MainFPM; 1963349cc55cSDimitry Andric MainFPM.addPass(createFunctionToLoopPassAdaptor( 1964fb03ea46SDimitry Andric LICMPass(PTO.LicmMssaOptCap, PTO.LicmMssaNoAccForPromotionCap, 1965fb03ea46SDimitry Andric /*AllowSpeculation=*/true), 196606c3fb27SDimitry Andric /*USeMemorySSA=*/true, /*UseBlockFrequencyInfo=*/false)); 1967349cc55cSDimitry Andric 1968349cc55cSDimitry Andric if (RunNewGVN) 1969349cc55cSDimitry Andric MainFPM.addPass(NewGVNPass()); 1970349cc55cSDimitry Andric else 1971349cc55cSDimitry Andric MainFPM.addPass(GVNPass()); 1972349cc55cSDimitry Andric 1973349cc55cSDimitry Andric // Remove dead memcpy()'s. 1974349cc55cSDimitry Andric MainFPM.addPass(MemCpyOptPass()); 1975349cc55cSDimitry Andric 1976349cc55cSDimitry Andric // Nuke dead stores. 1977349cc55cSDimitry Andric MainFPM.addPass(DSEPass()); 197806c3fb27SDimitry Andric MainFPM.addPass(MoveAutoInitPass()); 1979349cc55cSDimitry Andric MainFPM.addPass(MergedLoadStoreMotionPass()); 1980349cc55cSDimitry Andric 1981349cc55cSDimitry Andric LoopPassManager LPM; 198204eeddc0SDimitry Andric if (EnableLoopFlatten && Level.getSpeedupLevel() > 1) 198304eeddc0SDimitry Andric LPM.addPass(LoopFlattenPass()); 1984349cc55cSDimitry Andric LPM.addPass(IndVarSimplifyPass()); 1985349cc55cSDimitry Andric LPM.addPass(LoopDeletionPass()); 1986349cc55cSDimitry Andric // FIXME: Add loop interchange. 1987349cc55cSDimitry Andric 1988349cc55cSDimitry Andric // Unroll small loops and perform peeling. 1989349cc55cSDimitry Andric LPM.addPass(LoopFullUnrollPass(Level.getSpeedupLevel(), 1990349cc55cSDimitry Andric /* OnlyWhenForced= */ !PTO.LoopUnrolling, 1991349cc55cSDimitry Andric PTO.ForgetAllSCEVInLoopUnroll)); 1992349cc55cSDimitry Andric // The loop passes in LPM (LoopFullUnrollPass) do not preserve MemorySSA. 1993349cc55cSDimitry Andric // *All* loop passes must preserve it, in order to be able to use it. 1994349cc55cSDimitry Andric MainFPM.addPass(createFunctionToLoopPassAdaptor( 1995349cc55cSDimitry Andric std::move(LPM), /*UseMemorySSA=*/false, /*UseBlockFrequencyInfo=*/true)); 1996349cc55cSDimitry Andric 1997349cc55cSDimitry Andric MainFPM.addPass(LoopDistributePass()); 1998349cc55cSDimitry Andric 1999349cc55cSDimitry Andric addVectorPasses(Level, MainFPM, /* IsFullLTO */ true); 2000349cc55cSDimitry Andric 20011fd87a68SDimitry Andric // Run the OpenMPOpt CGSCC pass again late. 20021ac55f4cSDimitry Andric MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor( 20031ac55f4cSDimitry Andric OpenMPOptCGSCCPass(ThinOrFullLTOPhase::FullLTOPostLink))); 20041fd87a68SDimitry Andric 2005349cc55cSDimitry Andric invokePeepholeEPCallbacks(MainFPM, Level); 200681ad6265SDimitry Andric MainFPM.addPass(JumpThreadingPass()); 2007349cc55cSDimitry Andric MPM.addPass(createModuleToFunctionPassAdaptor(std::move(MainFPM), 2008349cc55cSDimitry Andric PTO.EagerlyInvalidateAnalyses)); 2009349cc55cSDimitry Andric 2010349cc55cSDimitry Andric // Lower type metadata and the type.test intrinsic. This pass supports 2011349cc55cSDimitry Andric // clang's control flow integrity mechanisms (-fsanitize=cfi*) and needs 2012349cc55cSDimitry Andric // to be run at link time if CFI is enabled. This pass does nothing if 2013349cc55cSDimitry Andric // CFI is disabled. 2014349cc55cSDimitry Andric MPM.addPass(LowerTypeTestsPass(ExportSummary, nullptr)); 2015349cc55cSDimitry Andric // Run a second time to clean up any type tests left behind by WPD for use 2016349cc55cSDimitry Andric // in ICP (which is performed earlier than this in the regular LTO pipeline). 2017349cc55cSDimitry Andric MPM.addPass(LowerTypeTestsPass(nullptr, nullptr, true)); 2018349cc55cSDimitry Andric 2019753f127fSDimitry Andric // Enable splitting late in the FullLTO post-link pipeline. 2020349cc55cSDimitry Andric if (EnableHotColdSplit) 2021349cc55cSDimitry Andric MPM.addPass(HotColdSplittingPass()); 2022349cc55cSDimitry Andric 2023349cc55cSDimitry Andric // Add late LTO optimization passes. 202406c3fb27SDimitry Andric FunctionPassManager LateFPM; 202506c3fb27SDimitry Andric 202606c3fb27SDimitry Andric // LoopSink pass sinks instructions hoisted by LICM, which serves as a 202706c3fb27SDimitry Andric // canonicalization pass that enables other optimizations. As a result, 202806c3fb27SDimitry Andric // LoopSink pass needs to be a very late IR pass to avoid undoing LICM 202906c3fb27SDimitry Andric // result too early. 203006c3fb27SDimitry Andric LateFPM.addPass(LoopSinkPass()); 203106c3fb27SDimitry Andric 203206c3fb27SDimitry Andric // This hoists/decomposes div/rem ops. It should run after other sink/hoist 203306c3fb27SDimitry Andric // passes to avoid re-sinking, but before SimplifyCFG because it can allow 203406c3fb27SDimitry Andric // flattening of blocks. 203506c3fb27SDimitry Andric LateFPM.addPass(DivRemPairsPass()); 203606c3fb27SDimitry Andric 2037349cc55cSDimitry Andric // Delete basic blocks, which optimization passes may have killed. 2038*0fca6ea1SDimitry Andric LateFPM.addPass(SimplifyCFGPass(SimplifyCFGOptions() 2039*0fca6ea1SDimitry Andric .convertSwitchRangeToICmp(true) 2040*0fca6ea1SDimitry Andric .hoistCommonInsts(true) 2041*0fca6ea1SDimitry Andric .speculateUnpredictables(true))); 204206c3fb27SDimitry Andric MPM.addPass(createModuleToFunctionPassAdaptor(std::move(LateFPM))); 2043349cc55cSDimitry Andric 2044349cc55cSDimitry Andric // Drop bodies of available eternally objects to improve GlobalDCE. 2045349cc55cSDimitry Andric MPM.addPass(EliminateAvailableExternallyPass()); 2046349cc55cSDimitry Andric 2047349cc55cSDimitry Andric // Now that we have optimized the program, discard unreachable functions. 204806c3fb27SDimitry Andric MPM.addPass(GlobalDCEPass(/*InLTOPostLink=*/true)); 2049349cc55cSDimitry Andric 2050349cc55cSDimitry Andric if (PTO.MergeFunctions) 2051349cc55cSDimitry Andric MPM.addPass(MergeFunctionsPass()); 2052349cc55cSDimitry Andric 205381ad6265SDimitry Andric if (PTO.CallGraphProfile) 20547a6dacacSDimitry Andric MPM.addPass(CGProfilePass(/*InLTOPostLink=*/true)); 205581ad6265SDimitry Andric 205606c3fb27SDimitry Andric invokeFullLinkTimeOptimizationLastEPCallbacks(MPM, Level); 205781ad6265SDimitry Andric 2058349cc55cSDimitry Andric // Emit annotation remarks. 2059349cc55cSDimitry Andric addAnnotationRemarksPass(MPM); 2060349cc55cSDimitry Andric 2061349cc55cSDimitry Andric return MPM; 2062349cc55cSDimitry Andric } 2063349cc55cSDimitry Andric 2064349cc55cSDimitry Andric ModulePassManager PassBuilder::buildO0DefaultPipeline(OptimizationLevel Level, 2065349cc55cSDimitry Andric bool LTOPreLink) { 2066349cc55cSDimitry Andric assert(Level == OptimizationLevel::O0 && 2067349cc55cSDimitry Andric "buildO0DefaultPipeline should only be used with O0"); 2068349cc55cSDimitry Andric 2069349cc55cSDimitry Andric ModulePassManager MPM; 2070349cc55cSDimitry Andric 2071349cc55cSDimitry Andric // Perform pseudo probe instrumentation in O0 mode. This is for the 2072349cc55cSDimitry Andric // consistency between different build modes. For example, a LTO build can be 2073349cc55cSDimitry Andric // mixed with an O0 prelink and an O2 postlink. Loading a sample profile in 2074349cc55cSDimitry Andric // the postlink will require pseudo probe instrumentation in the prelink. 2075349cc55cSDimitry Andric if (PGOOpt && PGOOpt->PseudoProbeForProfiling) 2076349cc55cSDimitry Andric MPM.addPass(SampleProfileProbePass(TM)); 2077349cc55cSDimitry Andric 2078349cc55cSDimitry Andric if (PGOOpt && (PGOOpt->Action == PGOOptions::IRInstr || 2079349cc55cSDimitry Andric PGOOpt->Action == PGOOptions::IRUse)) 2080349cc55cSDimitry Andric addPGOInstrPassesForO0( 2081349cc55cSDimitry Andric MPM, 20825f757f3fSDimitry Andric /*RunProfileGen=*/(PGOOpt->Action == PGOOptions::IRInstr), 20835f757f3fSDimitry Andric /*IsCS=*/false, PGOOpt->AtomicCounterUpdate, PGOOpt->ProfileFile, 20845f757f3fSDimitry Andric PGOOpt->ProfileRemappingFile, PGOOpt->FS); 2085349cc55cSDimitry Andric 2086*0fca6ea1SDimitry Andric // Instrument function entry and exit before all inlining. 2087*0fca6ea1SDimitry Andric MPM.addPass(createModuleToFunctionPassAdaptor( 2088*0fca6ea1SDimitry Andric EntryExitInstrumenterPass(/*PostInlining=*/false))); 2089*0fca6ea1SDimitry Andric 209006c3fb27SDimitry Andric invokePipelineStartEPCallbacks(MPM, Level); 2091349cc55cSDimitry Andric 2092349cc55cSDimitry Andric if (PGOOpt && PGOOpt->DebugInfoForProfiling) 2093349cc55cSDimitry Andric MPM.addPass(createModuleToFunctionPassAdaptor(AddDiscriminatorsPass())); 2094349cc55cSDimitry Andric 209506c3fb27SDimitry Andric invokePipelineEarlySimplificationEPCallbacks(MPM, Level); 2096349cc55cSDimitry Andric 2097349cc55cSDimitry Andric // Build a minimal pipeline based on the semantics required by LLVM, 2098349cc55cSDimitry Andric // which is just that always inlining occurs. Further, disable generating 2099349cc55cSDimitry Andric // lifetime intrinsics to avoid enabling further optimizations during 2100349cc55cSDimitry Andric // code generation. 2101349cc55cSDimitry Andric MPM.addPass(AlwaysInlinerPass( 2102349cc55cSDimitry Andric /*InsertLifetimeIntrinsics=*/false)); 2103349cc55cSDimitry Andric 2104349cc55cSDimitry Andric if (PTO.MergeFunctions) 2105349cc55cSDimitry Andric MPM.addPass(MergeFunctionsPass()); 2106349cc55cSDimitry Andric 2107349cc55cSDimitry Andric if (EnableMatrix) 2108349cc55cSDimitry Andric MPM.addPass( 2109349cc55cSDimitry Andric createModuleToFunctionPassAdaptor(LowerMatrixIntrinsicsPass(true))); 2110349cc55cSDimitry Andric 2111349cc55cSDimitry Andric if (!CGSCCOptimizerLateEPCallbacks.empty()) { 2112349cc55cSDimitry Andric CGSCCPassManager CGPM; 211306c3fb27SDimitry Andric invokeCGSCCOptimizerLateEPCallbacks(CGPM, Level); 2114349cc55cSDimitry Andric if (!CGPM.isEmpty()) 2115349cc55cSDimitry Andric MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM))); 2116349cc55cSDimitry Andric } 2117349cc55cSDimitry Andric if (!LateLoopOptimizationsEPCallbacks.empty()) { 2118349cc55cSDimitry Andric LoopPassManager LPM; 211906c3fb27SDimitry Andric invokeLateLoopOptimizationsEPCallbacks(LPM, Level); 2120349cc55cSDimitry Andric if (!LPM.isEmpty()) { 2121349cc55cSDimitry Andric MPM.addPass(createModuleToFunctionPassAdaptor( 2122349cc55cSDimitry Andric createFunctionToLoopPassAdaptor(std::move(LPM)))); 2123349cc55cSDimitry Andric } 2124349cc55cSDimitry Andric } 2125349cc55cSDimitry Andric if (!LoopOptimizerEndEPCallbacks.empty()) { 2126349cc55cSDimitry Andric LoopPassManager LPM; 212706c3fb27SDimitry Andric invokeLoopOptimizerEndEPCallbacks(LPM, Level); 2128349cc55cSDimitry Andric if (!LPM.isEmpty()) { 2129349cc55cSDimitry Andric MPM.addPass(createModuleToFunctionPassAdaptor( 2130349cc55cSDimitry Andric createFunctionToLoopPassAdaptor(std::move(LPM)))); 2131349cc55cSDimitry Andric } 2132349cc55cSDimitry Andric } 2133349cc55cSDimitry Andric if (!ScalarOptimizerLateEPCallbacks.empty()) { 2134349cc55cSDimitry Andric FunctionPassManager FPM; 213506c3fb27SDimitry Andric invokeScalarOptimizerLateEPCallbacks(FPM, Level); 2136349cc55cSDimitry Andric if (!FPM.isEmpty()) 2137349cc55cSDimitry Andric MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); 2138349cc55cSDimitry Andric } 213981ad6265SDimitry Andric 214006c3fb27SDimitry Andric invokeOptimizerEarlyEPCallbacks(MPM, Level); 214181ad6265SDimitry Andric 2142349cc55cSDimitry Andric if (!VectorizerStartEPCallbacks.empty()) { 2143349cc55cSDimitry Andric FunctionPassManager FPM; 214406c3fb27SDimitry Andric invokeVectorizerStartEPCallbacks(FPM, Level); 2145349cc55cSDimitry Andric if (!FPM.isEmpty()) 2146349cc55cSDimitry Andric MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); 2147349cc55cSDimitry Andric } 2148349cc55cSDimitry Andric 214981ad6265SDimitry Andric ModulePassManager CoroPM; 215081ad6265SDimitry Andric CoroPM.addPass(CoroEarlyPass()); 2151349cc55cSDimitry Andric CGSCCPassManager CGPM; 2152349cc55cSDimitry Andric CGPM.addPass(CoroSplitPass()); 215381ad6265SDimitry Andric CoroPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM))); 215481ad6265SDimitry Andric CoroPM.addPass(CoroCleanupPass()); 215581ad6265SDimitry Andric CoroPM.addPass(GlobalDCEPass()); 215681ad6265SDimitry Andric MPM.addPass(CoroConditionalWrapper(std::move(CoroPM))); 2157349cc55cSDimitry Andric 215806c3fb27SDimitry Andric invokeOptimizerLastEPCallbacks(MPM, Level); 2159349cc55cSDimitry Andric 2160349cc55cSDimitry Andric if (LTOPreLink) 2161349cc55cSDimitry Andric addRequiredLTOPreLinkPasses(MPM); 2162349cc55cSDimitry Andric 21634824e7fdSDimitry Andric MPM.addPass(createModuleToFunctionPassAdaptor(AnnotationRemarksPass())); 21644824e7fdSDimitry Andric 2165349cc55cSDimitry Andric return MPM; 2166349cc55cSDimitry Andric } 2167349cc55cSDimitry Andric 2168349cc55cSDimitry Andric AAManager PassBuilder::buildDefaultAAPipeline() { 2169349cc55cSDimitry Andric AAManager AA; 2170349cc55cSDimitry Andric 2171349cc55cSDimitry Andric // The order in which these are registered determines their priority when 2172349cc55cSDimitry Andric // being queried. 2173349cc55cSDimitry Andric 2174349cc55cSDimitry Andric // First we register the basic alias analysis that provides the majority of 2175349cc55cSDimitry Andric // per-function local AA logic. This is a stateless, on-demand local set of 2176349cc55cSDimitry Andric // AA techniques. 2177349cc55cSDimitry Andric AA.registerFunctionAnalysis<BasicAA>(); 2178349cc55cSDimitry Andric 2179349cc55cSDimitry Andric // Next we query fast, specialized alias analyses that wrap IR-embedded 2180349cc55cSDimitry Andric // information about aliasing. 2181349cc55cSDimitry Andric AA.registerFunctionAnalysis<ScopedNoAliasAA>(); 2182349cc55cSDimitry Andric AA.registerFunctionAnalysis<TypeBasedAA>(); 2183349cc55cSDimitry Andric 2184349cc55cSDimitry Andric // Add support for querying global aliasing information when available. 2185349cc55cSDimitry Andric // Because the `AAManager` is a function analysis and `GlobalsAA` is a module 2186349cc55cSDimitry Andric // analysis, all that the `AAManager` can do is query for any *cached* 2187349cc55cSDimitry Andric // results from `GlobalsAA` through a readonly proxy. 2188bdd1243dSDimitry Andric if (EnableGlobalAnalyses) 2189349cc55cSDimitry Andric AA.registerModuleAnalysis<GlobalsAA>(); 2190349cc55cSDimitry Andric 2191349cc55cSDimitry Andric // Add target-specific alias analyses. 2192349cc55cSDimitry Andric if (TM) 2193349cc55cSDimitry Andric TM->registerDefaultAliasAnalyses(AA); 2194349cc55cSDimitry Andric 2195349cc55cSDimitry Andric return AA; 2196349cc55cSDimitry Andric } 2197