diff options
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Passes/PassBuilder.cpp')
-rw-r--r-- | contrib/llvm-project/llvm/lib/Passes/PassBuilder.cpp | 847 |
1 files changed, 604 insertions, 243 deletions
diff --git a/contrib/llvm-project/llvm/lib/Passes/PassBuilder.cpp b/contrib/llvm-project/llvm/lib/Passes/PassBuilder.cpp index 4db7bebcb77c..6c1a7c75d30a 100644 --- a/contrib/llvm-project/llvm/lib/Passes/PassBuilder.cpp +++ b/contrib/llvm-project/llvm/lib/Passes/PassBuilder.cpp @@ -16,8 +16,8 @@ #include "llvm/Passes/PassBuilder.h" #include "llvm/ADT/StringSwitch.h" -#include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Analysis/AliasAnalysisEvaluator.h" +#include "llvm/Analysis/AliasSetTracker.h" #include "llvm/Analysis/AssumptionCache.h" #include "llvm/Analysis/BasicAliasAnalysis.h" #include "llvm/Analysis/BlockFrequencyInfo.h" @@ -28,23 +28,32 @@ #include "llvm/Analysis/CGSCCPassManager.h" #include "llvm/Analysis/CallGraph.h" #include "llvm/Analysis/DDG.h" +#include "llvm/Analysis/DDGPrinter.h" +#include "llvm/Analysis/Delinearization.h" #include "llvm/Analysis/DemandedBits.h" #include "llvm/Analysis/DependenceAnalysis.h" #include "llvm/Analysis/DominanceFrontier.h" +#include "llvm/Analysis/FunctionPropertiesAnalysis.h" #include "llvm/Analysis/GlobalsModRef.h" +#include "llvm/Analysis/IRSimilarityIdentifier.h" #include "llvm/Analysis/IVUsers.h" #include "llvm/Analysis/InlineAdvisor.h" -#include "llvm/Analysis/InlineFeaturesAnalysis.h" #include "llvm/Analysis/InlineSizeEstimatorAnalysis.h" +#include "llvm/Analysis/InstCount.h" #include "llvm/Analysis/LazyCallGraph.h" #include "llvm/Analysis/LazyValueInfo.h" +#include "llvm/Analysis/Lint.h" #include "llvm/Analysis/LoopAccessAnalysis.h" #include "llvm/Analysis/LoopCacheAnalysis.h" #include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/LoopNestAnalysis.h" +#include "llvm/Analysis/MemDerefPrinter.h" #include "llvm/Analysis/MemoryDependenceAnalysis.h" #include "llvm/Analysis/MemorySSA.h" +#include "llvm/Analysis/ModuleDebugInfoPrinter.h" #include "llvm/Analysis/ModuleSummaryAnalysis.h" +#include "llvm/Analysis/MustExecute.h" +#include "llvm/Analysis/ObjCARCAliasAnalysis.h" #include "llvm/Analysis/OptimizationRemarkEmitter.h" #include "llvm/Analysis/PhiValues.h" #include "llvm/Analysis/PostDominators.h" @@ -61,10 +70,12 @@ #include "llvm/IR/Dominators.h" #include "llvm/IR/IRPrintingPasses.h" #include "llvm/IR/PassManager.h" +#include "llvm/IR/PrintPasses.h" #include "llvm/IR/SafepointIRVerifier.h" #include "llvm/IR/Verifier.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FormatVariadic.h" #include "llvm/Support/Regex.h" #include "llvm/Target/TargetMachine.h" @@ -73,9 +84,12 @@ #include "llvm/Transforms/Coroutines/CoroEarly.h" #include "llvm/Transforms/Coroutines/CoroElide.h" #include "llvm/Transforms/Coroutines/CoroSplit.h" +#include "llvm/Transforms/HelloNew/HelloWorld.h" #include "llvm/Transforms/IPO/AlwaysInliner.h" +#include "llvm/Transforms/IPO/Annotation2Metadata.h" #include "llvm/Transforms/IPO/ArgumentPromotion.h" #include "llvm/Transforms/IPO/Attributor.h" +#include "llvm/Transforms/IPO/BlockExtractor.h" #include "llvm/Transforms/IPO/CalledValuePropagation.h" #include "llvm/Transforms/IPO/ConstantMerge.h" #include "llvm/Transforms/IPO/CrossDSOCFI.h" @@ -88,16 +102,20 @@ #include "llvm/Transforms/IPO/GlobalOpt.h" #include "llvm/Transforms/IPO/GlobalSplit.h" #include "llvm/Transforms/IPO/HotColdSplitting.h" +#include "llvm/Transforms/IPO/IROutliner.h" #include "llvm/Transforms/IPO/InferFunctionAttrs.h" #include "llvm/Transforms/IPO/Inliner.h" #include "llvm/Transforms/IPO/Internalize.h" +#include "llvm/Transforms/IPO/LoopExtractor.h" #include "llvm/Transforms/IPO/LowerTypeTests.h" #include "llvm/Transforms/IPO/MergeFunctions.h" #include "llvm/Transforms/IPO/OpenMPOpt.h" #include "llvm/Transforms/IPO/PartialInlining.h" #include "llvm/Transforms/IPO/SCCP.h" #include "llvm/Transforms/IPO/SampleProfile.h" +#include "llvm/Transforms/IPO/SampleProfileProbe.h" #include "llvm/Transforms/IPO/StripDeadPrototypes.h" +#include "llvm/Transforms/IPO/StripSymbols.h" #include "llvm/Transforms/IPO/SyntheticCountsPropagation.h" #include "llvm/Transforms/IPO/WholeProgramDevirt.h" #include "llvm/Transforms/InstCombine/InstCombine.h" @@ -106,20 +124,25 @@ #include "llvm/Transforms/Instrumentation/BoundsChecking.h" #include "llvm/Transforms/Instrumentation/CGProfile.h" #include "llvm/Transforms/Instrumentation/ControlHeightReduction.h" +#include "llvm/Transforms/Instrumentation/DataFlowSanitizer.h" #include "llvm/Transforms/Instrumentation/GCOVProfiler.h" #include "llvm/Transforms/Instrumentation/HWAddressSanitizer.h" #include "llvm/Transforms/Instrumentation/InstrOrderFile.h" #include "llvm/Transforms/Instrumentation/InstrProfiling.h" +#include "llvm/Transforms/Instrumentation/MemProfiler.h" #include "llvm/Transforms/Instrumentation/MemorySanitizer.h" #include "llvm/Transforms/Instrumentation/PGOInstrumentation.h" #include "llvm/Transforms/Instrumentation/PoisonChecking.h" #include "llvm/Transforms/Instrumentation/SanitizerCoverage.h" #include "llvm/Transforms/Instrumentation/ThreadSanitizer.h" +#include "llvm/Transforms/ObjCARC.h" #include "llvm/Transforms/Scalar/ADCE.h" #include "llvm/Transforms/Scalar/AlignmentFromAssumptions.h" +#include "llvm/Transforms/Scalar/AnnotationRemarks.h" #include "llvm/Transforms/Scalar/BDCE.h" #include "llvm/Transforms/Scalar/CallSiteSplitting.h" #include "llvm/Transforms/Scalar/ConstantHoisting.h" +#include "llvm/Transforms/Scalar/ConstraintElimination.h" #include "llvm/Transforms/Scalar/CorrelatedValuePropagation.h" #include "llvm/Transforms/Scalar/DCE.h" #include "llvm/Transforms/Scalar/DeadStoreElimination.h" @@ -131,6 +154,7 @@ #include "llvm/Transforms/Scalar/IVUsersPrinter.h" #include "llvm/Transforms/Scalar/IndVarSimplify.h" #include "llvm/Transforms/Scalar/InductiveRangeCheckElimination.h" +#include "llvm/Transforms/Scalar/InferAddressSpaces.h" #include "llvm/Transforms/Scalar/InstSimplifyPass.h" #include "llvm/Transforms/Scalar/JumpThreading.h" #include "llvm/Transforms/Scalar/LICM.h" @@ -138,18 +162,22 @@ #include "llvm/Transforms/Scalar/LoopDataPrefetch.h" #include "llvm/Transforms/Scalar/LoopDeletion.h" #include "llvm/Transforms/Scalar/LoopDistribute.h" +#include "llvm/Transforms/Scalar/LoopFlatten.h" #include "llvm/Transforms/Scalar/LoopFuse.h" #include "llvm/Transforms/Scalar/LoopIdiomRecognize.h" #include "llvm/Transforms/Scalar/LoopInstSimplify.h" +#include "llvm/Transforms/Scalar/LoopInterchange.h" #include "llvm/Transforms/Scalar/LoopLoadElimination.h" #include "llvm/Transforms/Scalar/LoopPassManager.h" #include "llvm/Transforms/Scalar/LoopPredication.h" +#include "llvm/Transforms/Scalar/LoopReroll.h" #include "llvm/Transforms/Scalar/LoopRotation.h" #include "llvm/Transforms/Scalar/LoopSimplifyCFG.h" #include "llvm/Transforms/Scalar/LoopSink.h" #include "llvm/Transforms/Scalar/LoopStrengthReduce.h" #include "llvm/Transforms/Scalar/LoopUnrollAndJamPass.h" #include "llvm/Transforms/Scalar/LoopUnrollPass.h" +#include "llvm/Transforms/Scalar/LoopVersioningLICM.h" #include "llvm/Transforms/Scalar/LowerAtomic.h" #include "llvm/Transforms/Scalar/LowerConstantIntrinsics.h" #include "llvm/Transforms/Scalar/LowerExpectIntrinsic.h" @@ -164,15 +192,20 @@ #include "llvm/Transforms/Scalar/NewGVN.h" #include "llvm/Transforms/Scalar/PartiallyInlineLibCalls.h" #include "llvm/Transforms/Scalar/Reassociate.h" +#include "llvm/Transforms/Scalar/Reg2Mem.h" #include "llvm/Transforms/Scalar/RewriteStatepointsForGC.h" #include "llvm/Transforms/Scalar/SCCP.h" #include "llvm/Transforms/Scalar/SROA.h" +#include "llvm/Transforms/Scalar/ScalarizeMaskedMemIntrin.h" #include "llvm/Transforms/Scalar/Scalarizer.h" +#include "llvm/Transforms/Scalar/SeparateConstOffsetFromGEP.h" #include "llvm/Transforms/Scalar/SimpleLoopUnswitch.h" #include "llvm/Transforms/Scalar/SimplifyCFG.h" #include "llvm/Transforms/Scalar/Sink.h" #include "llvm/Transforms/Scalar/SpeculateAroundPHIs.h" #include "llvm/Transforms/Scalar/SpeculativeExecution.h" +#include "llvm/Transforms/Scalar/StraightLineStrengthReduce.h" +#include "llvm/Transforms/Scalar/StructurizeCFG.h" #include "llvm/Transforms/Scalar/TailRecursionElimination.h" #include "llvm/Transforms/Scalar/WarnMissedTransforms.h" #include "llvm/Transforms/Utils/AddDiscriminators.h" @@ -181,14 +214,24 @@ #include "llvm/Transforms/Utils/CanonicalizeAliases.h" #include "llvm/Transforms/Utils/CanonicalizeFreezeInLoops.h" #include "llvm/Transforms/Utils/EntryExitInstrumenter.h" +#include "llvm/Transforms/Utils/FixIrreducible.h" #include "llvm/Transforms/Utils/InjectTLIMappings.h" +#include "llvm/Transforms/Utils/InstructionNamer.h" #include "llvm/Transforms/Utils/LCSSA.h" #include "llvm/Transforms/Utils/LibCallsShrinkWrap.h" #include "llvm/Transforms/Utils/LoopSimplify.h" +#include "llvm/Transforms/Utils/LoopVersioning.h" #include "llvm/Transforms/Utils/LowerInvoke.h" +#include "llvm/Transforms/Utils/LowerSwitch.h" #include "llvm/Transforms/Utils/Mem2Reg.h" +#include "llvm/Transforms/Utils/MetaRenamer.h" #include "llvm/Transforms/Utils/NameAnonGlobals.h" +#include "llvm/Transforms/Utils/StripGCRelocates.h" +#include "llvm/Transforms/Utils/StripNonLineTableDebugInfo.h" #include "llvm/Transforms/Utils/SymbolRewriter.h" +#include "llvm/Transforms/Utils/UnifyFunctionExitNodes.h" +#include "llvm/Transforms/Utils/UnifyLoopExits.h" +#include "llvm/Transforms/Utils/UniqueInternalLinkageNames.h" #include "llvm/Transforms/Vectorize/LoadStoreVectorizer.h" #include "llvm/Transforms/Vectorize/LoopVectorize.h" #include "llvm/Transforms/Vectorize/SLPVectorizer.h" @@ -196,26 +239,7 @@ using namespace llvm; -static cl::opt<unsigned> MaxDevirtIterations("pm-max-devirt-iterations", - cl::ReallyHidden, cl::init(4)); -static cl::opt<bool> - RunPartialInlining("enable-npm-partial-inlining", cl::init(false), - cl::Hidden, cl::ZeroOrMore, - cl::desc("Run Partial inlinining pass")); - -static cl::opt<int> PreInlineThreshold( - "npm-preinline-threshold", cl::Hidden, cl::init(75), cl::ZeroOrMore, - cl::desc("Control the amount of inlining in pre-instrumentation inliner " - "(default = 75)")); - -static cl::opt<bool> - RunNewGVN("enable-npm-newgvn", cl::init(false), - cl::Hidden, cl::ZeroOrMore, - cl::desc("Run NewGVN instead of GVN")); - -static cl::opt<bool> EnableGVNHoist( - "enable-npm-gvn-hoist", cl::init(false), cl::Hidden, - cl::desc("Enable the GVN hoisting pass for the new PM (default = off)")); +extern cl::opt<unsigned> MaxDevirtIterations; static cl::opt<InliningAdvisorMode> UseInlineAdvisor( "enable-ml-inliner", cl::init(InliningAdvisorMode::Default), cl::Hidden, @@ -227,14 +251,6 @@ static cl::opt<InliningAdvisorMode> UseInlineAdvisor( clEnumValN(InliningAdvisorMode::Release, "release", "Use release mode (AOT-compiled model)."))); -static cl::opt<bool> EnableGVNSink( - "enable-npm-gvn-sink", cl::init(false), cl::Hidden, - cl::desc("Enable the GVN hoisting pass for the new PM (default = off)")); - -static cl::opt<bool> EnableUnrollAndJam( - "enable-npm-unroll-and-jam", cl::init(false), cl::Hidden, - cl::desc("Enable the Unroll and Jam pass for the new PM (default = off)")); - static cl::opt<bool> EnableSyntheticCounts( "enable-npm-synthetic-counts", cl::init(false), cl::Hidden, cl::ZeroOrMore, cl::desc("Run synthetic function entry count generation " @@ -243,18 +259,21 @@ static cl::opt<bool> EnableSyntheticCounts( static const Regex DefaultAliasRegex( "^(default|thinlto-pre-link|thinlto|lto-pre-link|lto)<(O[0123sz])>$"); -// This option is used in simplifying testing SampleFDO optimizations for -// profile loading. -static cl::opt<bool> - EnableCHR("enable-chr-npm", cl::init(true), cl::Hidden, - cl::desc("Enable control height reduction optimization (CHR)")); - /// Flag to enable inline deferral during PGO. static cl::opt<bool> EnablePGOInlineDeferral("enable-npm-pgo-inline-deferral", cl::init(true), cl::Hidden, cl::desc("Enable inline deferral during PGO")); +static cl::opt<bool> EnableMemProfiler("enable-mem-prof", cl::init(false), + cl::Hidden, cl::ZeroOrMore, + cl::desc("Enable memory profiler")); + +static cl::opt<bool> PerformMandatoryInliningsFirst( + "mandatory-inlining-first", cl::init(true), cl::Hidden, cl::ZeroOrMore, + cl::desc("Perform mandatory inlinings module-wide, before performing " + "inlining.")); + PipelineTuningOptions::PipelineTuningOptions() { LoopInterleaving = true; LoopVectorization = true; @@ -265,16 +284,33 @@ PipelineTuningOptions::PipelineTuningOptions() { LicmMssaOptCap = SetLicmMssaOptCap; LicmMssaNoAccForPromotionCap = SetLicmMssaNoAccForPromotionCap; CallGraphProfile = true; + MergeFunctions = false; + UniqueLinkageNames = false; } +extern cl::opt<bool> ExtraVectorizerPasses; +extern cl::opt<bool> EnableConstraintElimination; +extern cl::opt<bool> EnableGVNHoist; +extern cl::opt<bool> EnableGVNSink; extern cl::opt<bool> EnableHotColdSplit; +extern cl::opt<bool> EnableIROutliner; extern cl::opt<bool> EnableOrderFileInstrumentation; +extern cl::opt<bool> EnableCHR; +extern cl::opt<bool> EnableUnrollAndJam; +extern cl::opt<bool> EnableLoopFlatten; +extern cl::opt<bool> RunNewGVN; +extern cl::opt<bool> RunPartialInlining; extern cl::opt<bool> FlattenedProfileUsed; extern cl::opt<AttributorRunOption> AttributorRun; extern cl::opt<bool> EnableKnowledgeRetention; +extern cl::opt<bool> EnableMatrix; + +extern cl::opt<bool> DisablePreInliner; +extern cl::opt<int> PreInlineThreshold; + const PassBuilder::OptimizationLevel PassBuilder::OptimizationLevel::O0 = { /*SpeedLevel*/ 0, /*SizeLevel*/ 0}; @@ -388,8 +424,45 @@ AnalysisKey NoOpCGSCCAnalysis::Key; AnalysisKey NoOpFunctionAnalysis::Key; AnalysisKey NoOpLoopAnalysis::Key; +/// Whether or not we should populate a PassInstrumentationCallbacks's class to +/// pass name map. +/// +/// This is for optimization purposes so we don't populate it if we never use +/// it. This should be updated if new pass instrumentation wants to use the map. +/// We currently only use this for --print-before/after. +bool shouldPopulateClassToPassNames() { + return !printBeforePasses().empty() || !printAfterPasses().empty(); +} + } // namespace +PassBuilder::PassBuilder(bool DebugLogging, TargetMachine *TM, + PipelineTuningOptions PTO, Optional<PGOOptions> PGOOpt, + PassInstrumentationCallbacks *PIC) + : DebugLogging(DebugLogging), TM(TM), PTO(PTO), PGOOpt(PGOOpt), PIC(PIC) { + if (TM) + TM->registerPassBuilderCallbacks(*this, DebugLogging); + if (PIC && shouldPopulateClassToPassNames()) { +#define MODULE_PASS(NAME, CREATE_PASS) \ + PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME); +#define MODULE_ANALYSIS(NAME, CREATE_PASS) \ + PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME); +#define FUNCTION_PASS(NAME, CREATE_PASS) \ + PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME); +#define FUNCTION_ANALYSIS(NAME, CREATE_PASS) \ + PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME); +#define LOOP_PASS(NAME, CREATE_PASS) \ + PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME); +#define LOOP_ANALYSIS(NAME, CREATE_PASS) \ + PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME); +#define CGSCC_PASS(NAME, CREATE_PASS) \ + PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME); +#define CGSCC_ANALYSIS(NAME, CREATE_PASS) \ + PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME); +#include "PassRegistry.def" + } +} + void PassBuilder::invokePeepholeEPCallbacks( FunctionPassManager &FPM, PassBuilder::OptimizationLevel Level) { for (auto &C : PeepholeEPCallbacks) @@ -432,9 +505,17 @@ void PassBuilder::registerLoopAnalyses(LoopAnalysisManager &LAM) { C(LAM); } +// Helper to add AnnotationRemarksPass. +static void addAnnotationRemarksPass(ModulePassManager &MPM) { + FunctionPassManager FPM; + FPM.addPass(AnnotationRemarksPass()); + MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); +} + // TODO: Investigate the cost/benefit of tail call elimination on debugging. -FunctionPassManager PassBuilder::buildO1FunctionSimplificationPipeline( - OptimizationLevel Level, ThinLTOPhase Phase, bool DebugLogging) { +FunctionPassManager +PassBuilder::buildO1FunctionSimplificationPipeline(OptimizationLevel Level, + ThinOrFullLTOPhase Phase) { FunctionPassManager FPM(DebugLogging); @@ -481,8 +562,9 @@ FunctionPassManager PassBuilder::buildO1FunctionSimplificationPipeline( // TODO: Investigate promotion cap for O1. LPM1.addPass(LICMPass(PTO.LicmMssaOptCap, PTO.LicmMssaNoAccForPromotionCap)); LPM1.addPass(SimpleLoopUnswitchPass()); - LPM2.addPass(IndVarSimplifyPass()); + LPM2.addPass(LoopIdiomRecognizePass()); + LPM2.addPass(IndVarSimplifyPass()); for (auto &C : LateLoopOptimizationsEPCallbacks) C(LPM2, Level); @@ -493,7 +575,7 @@ FunctionPassManager PassBuilder::buildO1FunctionSimplificationPipeline( // inaccurate. The normal unroller doesn't pay attention to forced full unroll // attributes so we need to make sure and allow the full unroll pass to pay // attention to it. - if (Phase != ThinLTOPhase::PreLink || !PGOOpt || + if (Phase != ThinOrFullLTOPhase::ThinLTOPreLink || !PGOOpt || PGOOpt->Action != PGOOptions::SampleUse) LPM2.addPass(LoopFullUnrollPass(Level.getSpeedupLevel(), /* OnlyWhenForced= */ !PTO.LoopUnrolling, @@ -507,13 +589,17 @@ FunctionPassManager PassBuilder::buildO1FunctionSimplificationPipeline( FPM.addPass( RequireAnalysisPass<OptimizationRemarkEmitterAnalysis, Function>()); FPM.addPass(createFunctionToLoopPassAdaptor( - std::move(LPM1), EnableMSSALoopDependency, DebugLogging)); + std::move(LPM1), EnableMSSALoopDependency, /*UseBlockFrequencyInfo=*/true, + DebugLogging)); FPM.addPass(SimplifyCFGPass()); FPM.addPass(InstCombinePass()); + if (EnableLoopFlatten) + FPM.addPass(LoopFlattenPass()); // The loop passes in LPM2 (LoopFullUnrollPass) do not preserve MemorySSA. // *All* loop passes must preserve it, in order to be able to use it. FPM.addPass(createFunctionToLoopPassAdaptor( - std::move(LPM2), /*UseMemorySSA=*/false, DebugLogging)); + std::move(LPM2), /*UseMemorySSA=*/false, /*UseBlockFrequencyInfo=*/false, + DebugLogging)); // Delete small array after loop unroll. FPM.addPass(SROA()); @@ -555,14 +641,13 @@ FunctionPassManager PassBuilder::buildO1FunctionSimplificationPipeline( FunctionPassManager PassBuilder::buildFunctionSimplificationPipeline(OptimizationLevel Level, - ThinLTOPhase Phase, - bool DebugLogging) { + ThinOrFullLTOPhase Phase) { assert(Level != OptimizationLevel::O0 && "Must request optimizations!"); // The O1 pipeline has a separate pipeline creation function to simplify // construction readability. if (Level.getSpeedupLevel() == 1) - return buildO1FunctionSimplificationPipeline(Level, Phase, DebugLogging); + return buildO1FunctionSimplificationPipeline(Level, Phase); FunctionPassManager FPM(DebugLogging); @@ -585,6 +670,9 @@ PassBuilder::buildFunctionSimplificationPipeline(OptimizationLevel Level, FPM.addPass(SimplifyCFGPass()); } + if (EnableConstraintElimination) + FPM.addPass(ConstraintEliminationPass()); + // Speculative execution if the target has divergent branches; otherwise nop. FPM.addPass(SpeculativeExecutionPass(/* OnlyIfDivergentTarget =*/true)); @@ -633,13 +721,14 @@ PassBuilder::buildFunctionSimplificationPipeline(OptimizationLevel Level, LPM1.addPass(LoopInstSimplifyPass()); LPM1.addPass(LoopSimplifyCFGPass()); - // Rotate Loop - disable header duplication at -Oz + // Disable header duplication in loop rotation at -Oz. LPM1.addPass(LoopRotatePass(Level != OptimizationLevel::Oz)); // TODO: Investigate promotion cap for O1. LPM1.addPass(LICMPass(PTO.LicmMssaOptCap, PTO.LicmMssaNoAccForPromotionCap)); - LPM1.addPass(SimpleLoopUnswitchPass()); - LPM2.addPass(IndVarSimplifyPass()); + LPM1.addPass( + SimpleLoopUnswitchPass(/* NonTrivial */ Level == OptimizationLevel::O3)); LPM2.addPass(LoopIdiomRecognizePass()); + LPM2.addPass(IndVarSimplifyPass()); for (auto &C : LateLoopOptimizationsEPCallbacks) C(LPM2, Level); @@ -650,7 +739,7 @@ PassBuilder::buildFunctionSimplificationPipeline(OptimizationLevel Level, // inaccurate. The normal unroller doesn't pay attention to forced full unroll // attributes so we need to make sure and allow the full unroll pass to pay // attention to it. - if (Phase != ThinLTOPhase::PreLink || !PGOOpt || + if (Phase != ThinOrFullLTOPhase::ThinLTOPreLink || !PGOOpt || PGOOpt->Action != PGOOptions::SampleUse) LPM2.addPass(LoopFullUnrollPass(Level.getSpeedupLevel(), /* OnlyWhenForced= */ !PTO.LoopUnrolling, @@ -664,14 +753,18 @@ PassBuilder::buildFunctionSimplificationPipeline(OptimizationLevel Level, FPM.addPass( RequireAnalysisPass<OptimizationRemarkEmitterAnalysis, Function>()); FPM.addPass(createFunctionToLoopPassAdaptor( - std::move(LPM1), EnableMSSALoopDependency, DebugLogging)); + std::move(LPM1), EnableMSSALoopDependency, /*UseBlockFrequencyInfo=*/true, + DebugLogging)); FPM.addPass(SimplifyCFGPass()); FPM.addPass(InstCombinePass()); - // The loop passes in LPM2 (IndVarSimplifyPass, LoopIdiomRecognizePass, + if (EnableLoopFlatten) + FPM.addPass(LoopFlattenPass()); + // The loop passes in LPM2 (LoopIdiomRecognizePass, IndVarSimplifyPass, // LoopDeletionPass and LoopFullUnrollPass) do not preserve MemorySSA. // *All* loop passes must preserve it, in order to be able to use it. FPM.addPass(createFunctionToLoopPassAdaptor( - std::move(LPM2), /*UseMemorySSA=*/false, DebugLogging)); + std::move(LPM2), /*UseMemorySSA=*/false, /*UseBlockFrequencyInfo=*/false, + DebugLogging)); // Delete small array after loop unroll. FPM.addPass(SROA()); @@ -705,10 +798,16 @@ PassBuilder::buildFunctionSimplificationPipeline(OptimizationLevel Level, // redo DCE, etc. FPM.addPass(JumpThreadingPass()); FPM.addPass(CorrelatedValuePropagationPass()); + + // Finally, do an expensive DCE pass to catch all the dead code exposed by + // the simplifications and basic cleanup after all the simplifications. + // TODO: Investigate if this is too expensive. + FPM.addPass(ADCEPass()); + FPM.addPass(DSEPass()); FPM.addPass(createFunctionToLoopPassAdaptor( LICMPass(PTO.LicmMssaOptCap, PTO.LicmMssaNoAccForPromotionCap), - EnableMSSALoopDependency, DebugLogging)); + EnableMSSALoopDependency, /*UseBlockFrequencyInfo=*/true, DebugLogging)); if (PTO.Coroutines) FPM.addPass(CoroElidePass()); @@ -716,10 +815,6 @@ PassBuilder::buildFunctionSimplificationPipeline(OptimizationLevel Level, for (auto &C : ScalarOptimizerLateEPCallbacks) C(FPM, Level); - // Finally, do an expensive DCE pass to catch all the dead code exposed by - // the simplifications and basic cleanup after all the simplifications. - // TODO: Investigate if this is too expensive. - FPM.addPass(ADCEPass()); FPM.addPass(SimplifyCFGPass()); FPM.addPass(InstCombinePass()); invokePeepholeEPCallbacks(FPM, Level); @@ -732,26 +827,27 @@ PassBuilder::buildFunctionSimplificationPipeline(OptimizationLevel Level, return FPM; } -void PassBuilder::addPGOInstrPasses(ModulePassManager &MPM, bool DebugLogging, +void PassBuilder::addRequiredLTOPreLinkPasses(ModulePassManager &MPM) { + MPM.addPass(CanonicalizeAliasesPass()); + MPM.addPass(NameAnonGlobalPass()); +} + +void PassBuilder::addPGOInstrPasses(ModulePassManager &MPM, PassBuilder::OptimizationLevel Level, bool RunProfileGen, bool IsCS, std::string ProfileFile, std::string ProfileRemappingFile) { assert(Level != OptimizationLevel::O0 && "Not expecting O0 here!"); - // Generally running simplification passes and the inliner with an high - // threshold results in smaller executables, but there may be cases where - // the size grows, so let's be conservative here and skip this simplification - // at -Os/Oz. We will not do this inline for context sensistive PGO (when - // IsCS is true). - if (!Level.isOptimizingForSize() && !IsCS) { + if (!IsCS && !DisablePreInliner) { InlineParams IP; IP.DefaultThreshold = PreInlineThreshold; - // FIXME: The hint threshold has the same value used by the regular inliner. - // This should probably be lowered after performance testing. + // FIXME: The hint threshold has the same value used by the regular inliner + // when not optimzing for size. This should probably be lowered after + // performance testing. // FIXME: this comment is cargo culted from the old pass manager, revisit). - IP.HintThreshold = 325; + IP.HintThreshold = Level.isOptimizingForSize() ? PreInlineThreshold : 325; ModuleInlinerWrapperPass MIWP(IP, DebugLogging); CGSCCPassManager &CGPipeline = MIWP.getPM(); @@ -785,8 +881,10 @@ void PassBuilder::addPGOInstrPasses(ModulePassManager &MPM, bool DebugLogging, MPM.addPass(PGOInstrumentationGen(IsCS)); FunctionPassManager FPM; + // Disable header duplication in loop rotation at -Oz. FPM.addPass(createFunctionToLoopPassAdaptor( - LoopRotatePass(), EnableMSSALoopDependency, DebugLogging)); + LoopRotatePass(Level != OptimizationLevel::Oz), EnableMSSALoopDependency, + /*UseBlockFrequencyInfo=*/false, DebugLogging)); MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); // Add the profile lowering pass. @@ -800,8 +898,8 @@ void PassBuilder::addPGOInstrPasses(ModulePassManager &MPM, bool DebugLogging, } void PassBuilder::addPGOInstrPassesForO0(ModulePassManager &MPM, - bool DebugLogging, bool RunProfileGen, - bool IsCS, std::string ProfileFile, + bool RunProfileGen, bool IsCS, + std::string ProfileFile, std::string ProfileRemappingFile) { if (!RunProfileGen) { assert(!ProfileFile.empty() && "Profile use expecting a profile file!"); @@ -830,18 +928,19 @@ getInlineParamsFromOptLevel(PassBuilder::OptimizationLevel Level) { } ModuleInlinerWrapperPass -PassBuilder::buildInlinerPipeline(OptimizationLevel Level, ThinLTOPhase Phase, - bool DebugLogging) { +PassBuilder::buildInlinerPipeline(OptimizationLevel Level, + ThinOrFullLTOPhase Phase) { InlineParams IP = getInlineParamsFromOptLevel(Level); - if (Phase == PassBuilder::ThinLTOPhase::PreLink && PGOOpt && + if (Phase == ThinOrFullLTOPhase::ThinLTOPreLink && PGOOpt && PGOOpt->Action == PGOOptions::SampleUse) IP.HotCallSiteThreshold = 0; if (PGOOpt) IP.EnableDeferral = EnablePGOInlineDeferral; - ModuleInlinerWrapperPass MIWP(IP, DebugLogging, UseInlineAdvisor, - MaxDevirtIterations); + ModuleInlinerWrapperPass MIWP(IP, DebugLogging, + PerformMandatoryInliningsFirst, + UseInlineAdvisor, MaxDevirtIterations); // Require the GlobalsAA analysis for the module so we can query it within // the CGSCC pipeline. @@ -866,7 +965,7 @@ PassBuilder::buildInlinerPipeline(OptimizationLevel Level, ThinLTOPhase Phase, MainCGPipeline.addPass(AttributorCGSCCPass()); if (PTO.Coroutines) - MainCGPipeline.addPass(CoroSplitPass()); + MainCGPipeline.addPass(CoroSplitPass(Level != OptimizationLevel::O0)); // Now deduce any function attributes based in the current code. MainCGPipeline.addPass(PostOrderFunctionAttrsPass()); @@ -881,21 +980,33 @@ PassBuilder::buildInlinerPipeline(OptimizationLevel Level, ThinLTOPhase Phase, if (Level == OptimizationLevel::O2 || Level == OptimizationLevel::O3) MainCGPipeline.addPass(OpenMPOptPass()); + for (auto &C : CGSCCOptimizerLateEPCallbacks) + C(MainCGPipeline, Level); + // Lastly, add the core function simplification pipeline nested inside the // CGSCC walk. MainCGPipeline.addPass(createCGSCCToFunctionPassAdaptor( - buildFunctionSimplificationPipeline(Level, Phase, DebugLogging))); - - for (auto &C : CGSCCOptimizerLateEPCallbacks) - C(MainCGPipeline, Level); + buildFunctionSimplificationPipeline(Level, Phase))); return MIWP; } -ModulePassManager PassBuilder::buildModuleSimplificationPipeline( - OptimizationLevel Level, ThinLTOPhase Phase, bool DebugLogging) { +ModulePassManager +PassBuilder::buildModuleSimplificationPipeline(OptimizationLevel Level, + ThinOrFullLTOPhase Phase) { ModulePassManager MPM(DebugLogging); + // Add UniqueInternalLinkageNames Pass which renames internal linkage + // symbols with unique names. + if (PTO.UniqueLinkageNames) + MPM.addPass(UniqueInternalLinkageNamesPass()); + + // Place pseudo probe instrumentation as the first pass of the pipeline to + // minimize the impact of optimization changes. + if (PGOOpt && PGOOpt->PseudoProbeForProfiling && + Phase != ThinOrFullLTOPhase::ThinLTOPostLink) + MPM.addPass(SampleProfileProbePass(TM)); + bool HasSampleProfile = PGOOpt && (PGOOpt->Action == PGOOptions::SampleUse); // In ThinLTO mode, when flattened profile is used, all the available @@ -903,7 +1014,7 @@ ModulePassManager PassBuilder::buildModuleSimplificationPipeline( // no need to load the profile again in PostLink. bool LoadSampleProfile = HasSampleProfile && - !(FlattenedProfileUsed && Phase == ThinLTOPhase::PostLink); + !(FlattenedProfileUsed && Phase == ThinOrFullLTOPhase::ThinLTOPostLink); // During the ThinLTO backend phase we perform early indirect call promotion // here, before globalopt. Otherwise imported available_externally functions @@ -919,7 +1030,7 @@ ModulePassManager PassBuilder::buildModuleSimplificationPipeline( // command line. E.g. for flattened profiles where we will not be reloading // the sample profile in the ThinLTO backend, we ideally shouldn't have to // provide the sample profile file. - if (Phase == ThinLTOPhase::PostLink && !LoadSampleProfile) + if (Phase == ThinOrFullLTOPhase::ThinLTOPostLink && !LoadSampleProfile) MPM.addPass(PGOIndirectCallPromotion(true /* InLTO */, HasSampleProfile)); // Do basic inference of function attributes from known properties of system @@ -952,20 +1063,19 @@ ModulePassManager PassBuilder::buildModuleSimplificationPipeline( // Annotate sample profile right after early FPM to ensure freshness of // the debug info. MPM.addPass(SampleProfileLoaderPass(PGOOpt->ProfileFile, - PGOOpt->ProfileRemappingFile, - Phase == ThinLTOPhase::PreLink)); + PGOOpt->ProfileRemappingFile, Phase)); // Cache ProfileSummaryAnalysis once to avoid the potential need to insert // RequireAnalysisPass for PSI before subsequent non-module passes. MPM.addPass(RequireAnalysisPass<ProfileSummaryAnalysis, Module>()); // Do not invoke ICP in the ThinLTOPrelink phase as it makes it hard // for the profile annotation to be accurate in the ThinLTO backend. - if (Phase != ThinLTOPhase::PreLink) + if (Phase != ThinOrFullLTOPhase::ThinLTOPreLink) // We perform early indirect call promotion here, before globalopt. // This is important for the ThinLTO backend phase because otherwise // imported available_externally functions look unreferenced and are // removed. - MPM.addPass(PGOIndirectCallPromotion(Phase == ThinLTOPhase::PostLink, - true /* SamplePGO */)); + MPM.addPass(PGOIndirectCallPromotion( + Phase == ThinOrFullLTOPhase::ThinLTOPostLink, true /* SamplePGO */)); } if (AttributorRun & AttributorRunOption::MODULE) @@ -974,9 +1084,12 @@ ModulePassManager PassBuilder::buildModuleSimplificationPipeline( // Lower type metadata and the type.test intrinsic in the ThinLTO // post link pipeline after ICP. This is to enable usage of the type // tests in ICP sequences. - if (Phase == ThinLTOPhase::PostLink) + if (Phase == ThinOrFullLTOPhase::ThinLTOPostLink) MPM.addPass(LowerTypeTestsPass(nullptr, nullptr, true)); + for (auto &C : PipelineEarlySimplificationEPCallbacks) + C(MPM, Level); + // Interprocedural constant propagation now that basic cleanup has occurred // and prior to optimizing globals. // FIXME: This position in the pipeline hasn't been carefully considered in @@ -1011,16 +1124,16 @@ ModulePassManager PassBuilder::buildModuleSimplificationPipeline( MPM.addPass(createModuleToFunctionPassAdaptor(std::move(GlobalCleanupPM))); // Add all the requested passes for instrumentation PGO, if requested. - if (PGOOpt && Phase != ThinLTOPhase::PostLink && + if (PGOOpt && Phase != ThinOrFullLTOPhase::ThinLTOPostLink && (PGOOpt->Action == PGOOptions::IRInstr || PGOOpt->Action == PGOOptions::IRUse)) { - addPGOInstrPasses(MPM, DebugLogging, Level, + addPGOInstrPasses(MPM, Level, /* RunProfileGen */ PGOOpt->Action == PGOOptions::IRInstr, /* IsCS */ false, PGOOpt->ProfileFile, PGOOpt->ProfileRemappingFile); MPM.addPass(PGOIndirectCallPromotion(false, false)); } - if (PGOOpt && Phase != ThinLTOPhase::PostLink && + if (PGOOpt && Phase != ThinOrFullLTOPhase::ThinLTOPostLink && PGOOpt->CSAction == PGOOptions::CSIRInstr) MPM.addPass(PGOInstrumentationGenCreateVar(PGOOpt->CSProfileGenFile)); @@ -1028,12 +1141,19 @@ ModulePassManager PassBuilder::buildModuleSimplificationPipeline( if (EnableSyntheticCounts && !PGOOpt) MPM.addPass(SyntheticCountsPropagation()); - MPM.addPass(buildInlinerPipeline(Level, Phase, DebugLogging)); + MPM.addPass(buildInlinerPipeline(Level, Phase)); + + if (EnableMemProfiler && Phase != ThinOrFullLTOPhase::ThinLTOPreLink) { + MPM.addPass(createModuleToFunctionPassAdaptor(MemProfilerPass())); + MPM.addPass(ModuleMemProfilerPass()); + } + return MPM; } -ModulePassManager PassBuilder::buildModuleOptimizationPipeline( - OptimizationLevel Level, bool DebugLogging, bool LTOPreLink) { +ModulePassManager +PassBuilder::buildModuleOptimizationPipeline(OptimizationLevel Level, + bool LTOPreLink) { ModulePassManager MPM(DebugLogging); // Optimize globals now that the module is fully simplified. @@ -1071,11 +1191,11 @@ ModulePassManager PassBuilder::buildModuleOptimizationPipeline( // instrumentation is after all the inlines are done. if (!LTOPreLink && PGOOpt) { if (PGOOpt->CSAction == PGOOptions::CSIRInstr) - addPGOInstrPasses(MPM, DebugLogging, Level, /* RunProfileGen */ true, + addPGOInstrPasses(MPM, Level, /* RunProfileGen */ true, /* IsCS */ true, PGOOpt->CSProfileGenFile, PGOOpt->ProfileRemappingFile); else if (PGOOpt->CSAction == PGOOptions::CSIRUse) - addPGOInstrPasses(MPM, DebugLogging, Level, /* RunProfileGen */ false, + addPGOInstrPasses(MPM, Level, /* RunProfileGen */ false, /* IsCS */ true, PGOOpt->ProfileFile, PGOOpt->ProfileRemappingFile); } @@ -1093,6 +1213,11 @@ ModulePassManager PassBuilder::buildModuleOptimizationPipeline( OptimizePM.addPass(Float2IntPass()); OptimizePM.addPass(LowerConstantIntrinsicsPass()); + if (EnableMatrix) { + OptimizePM.addPass(LowerMatrixIntrinsicsPass()); + OptimizePM.addPass(EarlyCSEPass()); + } + // FIXME: We need to run some loop optimizations to re-rotate loops after // simplify-cfg and others undo their rotation. @@ -1104,8 +1229,11 @@ ModulePassManager PassBuilder::buildModuleOptimizationPipeline( C(OptimizePM, Level); // First rotate loops that may have been un-rotated by prior passes. + // Disable header duplication at -Oz. OptimizePM.addPass(createFunctionToLoopPassAdaptor( - LoopRotatePass(), EnableMSSALoopDependency, DebugLogging)); + LoopRotatePass(Level != OptimizationLevel::Oz, LTOPreLink), + EnableMSSALoopDependency, + /*UseBlockFrequencyInfo=*/false, DebugLogging)); // Distribute loops to allow partial vectorization. I.e. isolate dependences // into separate loop that would otherwise inhibit vectorization. This is @@ -1128,6 +1256,28 @@ ModulePassManager PassBuilder::buildModuleOptimizationPipeline( // Cleanup after the loop optimization passes. OptimizePM.addPass(InstCombinePass()); + if (Level.getSpeedupLevel() > 1 && ExtraVectorizerPasses) { + // At higher optimization levels, try to clean up any runtime overlap and + // alignment checks inserted by the vectorizer. We want to track correlated + // runtime checks for two inner loops in the same outer loop, fold any + // common computations, hoist loop-invariant aspects out of any outer loop, + // and unswitch the runtime checks if possible. Once hoisted, we may have + // dead (or speculatable) control flows or more combining opportunities. + OptimizePM.addPass(EarlyCSEPass()); + OptimizePM.addPass(CorrelatedValuePropagationPass()); + OptimizePM.addPass(InstCombinePass()); + LoopPassManager LPM(DebugLogging); + LPM.addPass(LICMPass(PTO.LicmMssaOptCap, PTO.LicmMssaNoAccForPromotionCap)); + LPM.addPass( + SimpleLoopUnswitchPass(/* NonTrivial */ Level == OptimizationLevel::O3)); + OptimizePM.addPass(RequireAnalysisPass<OptimizationRemarkEmitterAnalysis, Function>()); + OptimizePM.addPass(createFunctionToLoopPassAdaptor( + std::move(LPM), EnableMSSALoopDependency, /*UseBlockFrequencyInfo=*/true, + DebugLogging)); + OptimizePM.addPass(SimplifyCFGPass()); + OptimizePM.addPass(InstCombinePass()); + } + // Now that we've formed fast to execute loop structures, we do further // optimizations. These are run afterward as they might block doing complex // analyses and transforms such as what are needed for loop vectorization. @@ -1137,15 +1287,22 @@ ModulePassManager PassBuilder::buildModuleOptimizationPipeline( // convert to more optimized IR using more aggressive simplify CFG options. // The extra sinking transform can create larger basic blocks, so do this // before SLP vectorization. - OptimizePM.addPass(SimplifyCFGPass(SimplifyCFGOptions(). - forwardSwitchCondToPhi(true). - convertSwitchToLookupTable(true). - needCanonicalLoops(false). - sinkCommonInsts(true))); + // FIXME: study whether hoisting and/or sinking of common instructions should + // be delayed until after SLP vectorizer. + OptimizePM.addPass(SimplifyCFGPass(SimplifyCFGOptions() + .forwardSwitchCondToPhi(true) + .convertSwitchToLookupTable(true) + .needCanonicalLoops(false) + .hoistCommonInsts(true) + .sinkCommonInsts(true))); // Optimize parallel scalar instruction chains into SIMD instructions. - if (PTO.SLPVectorization) + if (PTO.SLPVectorization) { OptimizePM.addPass(SLPVectorizerPass()); + if (Level.getSpeedupLevel() > 1 && ExtraVectorizerPasses) { + OptimizePM.addPass(EarlyCSEPass()); + } + } // Enhance/cleanup vector code. OptimizePM.addPass(VectorCombinePass()); @@ -1169,7 +1326,7 @@ ModulePassManager PassBuilder::buildModuleOptimizationPipeline( OptimizePM.addPass(RequireAnalysisPass<OptimizationRemarkEmitterAnalysis, Function>()); OptimizePM.addPass(createFunctionToLoopPassAdaptor( LICMPass(PTO.LicmMssaOptCap, PTO.LicmMssaNoAccForPromotionCap), - EnableMSSALoopDependency, DebugLogging)); + EnableMSSALoopDependency, /*UseBlockFrequencyInfo=*/true, DebugLogging)); // Now that we've vectorized and unrolled loops, we may have more refined // alignment information, try to re-derive it here. @@ -1181,6 +1338,17 @@ ModulePassManager PassBuilder::buildModuleOptimizationPipeline( if (EnableHotColdSplit && !LTOPreLink) MPM.addPass(HotColdSplittingPass()); + // Search the code for similar regions of code. If enough similar regions can + // be found where extracting the regions into their own function will decrease + // the size of the program, we extract the regions, a deduplicate the + // structurally similar regions. + if (EnableIROutliner) + MPM.addPass(IROutlinerPass()); + + // Merge functions if requested. + if (PTO.MergeFunctions) + MPM.addPass(MergeFunctionsPass()); + // LoopSink pass sinks instructions hoisted by LICM, which serves as a // canonicalization pass that enables other optimizations. As a result, // LoopSink pass needs to be a very late IR pass to avoid undoing LICM @@ -1228,55 +1396,70 @@ ModulePassManager PassBuilder::buildModuleOptimizationPipeline( ModulePassManager PassBuilder::buildPerModuleDefaultPipeline(OptimizationLevel Level, - bool DebugLogging, bool LTOPreLink) { + bool LTOPreLink) { assert(Level != OptimizationLevel::O0 && "Must request optimizations for the default pipeline!"); ModulePassManager MPM(DebugLogging); + // Convert @llvm.global.annotations to !annotation metadata. + MPM.addPass(Annotation2MetadataPass()); + // Force any function attributes we want the rest of the pipeline to observe. MPM.addPass(ForceFunctionAttrsPass()); // Apply module pipeline start EP callback. for (auto &C : PipelineStartEPCallbacks) - C(MPM); + C(MPM, Level); - if (PGOOpt && PGOOpt->SamplePGOSupport) + if (PGOOpt && PGOOpt->DebugInfoForProfiling) MPM.addPass(createModuleToFunctionPassAdaptor(AddDiscriminatorsPass())); // Add the core simplification pipeline. - MPM.addPass(buildModuleSimplificationPipeline(Level, ThinLTOPhase::None, - DebugLogging)); + MPM.addPass(buildModuleSimplificationPipeline( + Level, LTOPreLink ? ThinOrFullLTOPhase::FullLTOPreLink + : ThinOrFullLTOPhase::None)); // Now add the optimization pipeline. - MPM.addPass(buildModuleOptimizationPipeline(Level, DebugLogging, LTOPreLink)); + MPM.addPass(buildModuleOptimizationPipeline(Level, LTOPreLink)); + + if (PGOOpt && PGOOpt->PseudoProbeForProfiling) + MPM.addPass(PseudoProbeUpdatePass()); + + // Emit annotation remarks. + addAnnotationRemarksPass(MPM); + + if (LTOPreLink) + addRequiredLTOPreLinkPasses(MPM); return MPM; } ModulePassManager -PassBuilder::buildThinLTOPreLinkDefaultPipeline(OptimizationLevel Level, - bool DebugLogging) { +PassBuilder::buildThinLTOPreLinkDefaultPipeline(OptimizationLevel Level) { assert(Level != OptimizationLevel::O0 && "Must request optimizations for the default pipeline!"); ModulePassManager MPM(DebugLogging); + // Convert @llvm.global.annotations to !annotation metadata. + MPM.addPass(Annotation2MetadataPass()); + // Force any function attributes we want the rest of the pipeline to observe. MPM.addPass(ForceFunctionAttrsPass()); - if (PGOOpt && PGOOpt->SamplePGOSupport) + if (PGOOpt && PGOOpt->DebugInfoForProfiling) MPM.addPass(createModuleToFunctionPassAdaptor(AddDiscriminatorsPass())); // Apply module pipeline start EP callback. for (auto &C : PipelineStartEPCallbacks) - C(MPM); + C(MPM, Level); // If we are planning to perform ThinLTO later, we don't bloat the code with // unrolling/vectorization/... now. Just simplify the module as much as we // can. - MPM.addPass(buildModuleSimplificationPipeline(Level, ThinLTOPhase::PreLink, - DebugLogging)); + MPM.addPass(buildModuleSimplificationPipeline( + Level, ThinOrFullLTOPhase::ThinLTOPreLink)); // Run partial inlining pass to partially inline functions that have // large bodies. @@ -1297,14 +1480,24 @@ PassBuilder::buildThinLTOPreLinkDefaultPipeline(OptimizationLevel Level, if (PTO.Coroutines) MPM.addPass(createModuleToFunctionPassAdaptor(CoroCleanupPass())); + if (PGOOpt && PGOOpt->PseudoProbeForProfiling) + MPM.addPass(PseudoProbeUpdatePass()); + + // Emit annotation remarks. + addAnnotationRemarksPass(MPM); + + addRequiredLTOPreLinkPasses(MPM); + return MPM; } ModulePassManager PassBuilder::buildThinLTODefaultPipeline( - OptimizationLevel Level, bool DebugLogging, - const ModuleSummaryIndex *ImportSummary) { + OptimizationLevel Level, const ModuleSummaryIndex *ImportSummary) { ModulePassManager MPM(DebugLogging); + // Convert @llvm.global.annotations to !annotation metadata. + MPM.addPass(Annotation2MetadataPass()); + if (ImportSummary) { // These passes import type identifier resolutions for whole-program // devirtualization and CFI. They must run early because other passes may @@ -1332,30 +1525,35 @@ ModulePassManager PassBuilder::buildThinLTODefaultPipeline( MPM.addPass(ForceFunctionAttrsPass()); // Add the core simplification pipeline. - MPM.addPass(buildModuleSimplificationPipeline(Level, ThinLTOPhase::PostLink, - DebugLogging)); + MPM.addPass(buildModuleSimplificationPipeline( + Level, ThinOrFullLTOPhase::ThinLTOPostLink)); // Now add the optimization pipeline. - MPM.addPass(buildModuleOptimizationPipeline(Level, DebugLogging)); + MPM.addPass(buildModuleOptimizationPipeline(Level)); + + // Emit annotation remarks. + addAnnotationRemarksPass(MPM); return MPM; } ModulePassManager -PassBuilder::buildLTOPreLinkDefaultPipeline(OptimizationLevel Level, - bool DebugLogging) { +PassBuilder::buildLTOPreLinkDefaultPipeline(OptimizationLevel Level) { assert(Level != OptimizationLevel::O0 && "Must request optimizations for the default pipeline!"); // FIXME: We should use a customized pre-link pipeline! - return buildPerModuleDefaultPipeline(Level, DebugLogging, + return buildPerModuleDefaultPipeline(Level, /* LTOPreLink */ true); } ModulePassManager -PassBuilder::buildLTODefaultPipeline(OptimizationLevel Level, bool DebugLogging, +PassBuilder::buildLTODefaultPipeline(OptimizationLevel Level, ModuleSummaryIndex *ExportSummary) { ModulePassManager MPM(DebugLogging); + // Convert @llvm.global.annotations to !annotation metadata. + MPM.addPass(Annotation2MetadataPass()); + if (Level == OptimizationLevel::O0) { // The WPD and LowerTypeTest passes need to run at -O0 to lower type // metadata and intrinsics. @@ -1364,6 +1562,10 @@ PassBuilder::buildLTODefaultPipeline(OptimizationLevel Level, bool DebugLogging, // Run a second time to clean up any type tests left behind by WPD for use // in ICP. MPM.addPass(LowerTypeTestsPass(nullptr, nullptr, true)); + + // Emit annotation remarks. + addAnnotationRemarksPass(MPM); + return MPM; } @@ -1371,7 +1573,7 @@ PassBuilder::buildLTODefaultPipeline(OptimizationLevel Level, bool DebugLogging, // Load sample profile before running the LTO optimization pipeline. MPM.addPass(SampleProfileLoaderPass(PGOOpt->ProfileFile, PGOOpt->ProfileRemappingFile, - false /* ThinLTOPhase::PreLink */)); + ThinOrFullLTOPhase::FullLTOPostLink)); // Cache ProfileSummaryAnalysis once to avoid the potential need to insert // RequireAnalysisPass for PSI before subsequent non-module passes. MPM.addPass(RequireAnalysisPass<ProfileSummaryAnalysis, Module>()); @@ -1434,6 +1636,10 @@ PassBuilder::buildLTODefaultPipeline(OptimizationLevel Level, bool DebugLogging, // in ICP (which is performed earlier than this in the regular LTO // pipeline). MPM.addPass(LowerTypeTestsPass(nullptr, nullptr, true)); + + // Emit annotation remarks. + addAnnotationRemarksPass(MPM); + return MPM; } @@ -1482,17 +1688,17 @@ PassBuilder::buildLTODefaultPipeline(OptimizationLevel Level, bool DebugLogging, FPM.addPass(InstCombinePass()); invokePeepholeEPCallbacks(FPM, Level); - FPM.addPass(JumpThreadingPass()); + FPM.addPass(JumpThreadingPass(/*InsertFreezeWhenUnfoldingSelect*/ true)); // Do a post inline PGO instrumentation and use pass. This is a context // sensitive PGO pass. if (PGOOpt) { if (PGOOpt->CSAction == PGOOptions::CSIRInstr) - addPGOInstrPasses(MPM, DebugLogging, Level, /* RunProfileGen */ true, + addPGOInstrPasses(MPM, Level, /* RunProfileGen */ true, /* IsCS */ true, PGOOpt->CSProfileGenFile, PGOOpt->ProfileRemappingFile); else if (PGOOpt->CSAction == PGOOptions::CSIRUse) - addPGOInstrPasses(MPM, DebugLogging, Level, /* RunProfileGen */ false, + addPGOInstrPasses(MPM, Level, /* RunProfileGen */ false, /* IsCS */ true, PGOOpt->ProfileFile, PGOOpt->ProfileRemappingFile); } @@ -1532,7 +1738,7 @@ PassBuilder::buildLTODefaultPipeline(OptimizationLevel Level, bool DebugLogging, // are sorted out. MainFPM.addPass(InstCombinePass()); - MainFPM.addPass(SimplifyCFGPass()); + MainFPM.addPass(SimplifyCFGPass(SimplifyCFGOptions().hoistCommonInsts(true))); MainFPM.addPass(SCCPPass()); MainFPM.addPass(InstCombinePass()); MainFPM.addPass(BDCEPass()); @@ -1549,7 +1755,7 @@ PassBuilder::buildLTODefaultPipeline(OptimizationLevel Level, bool DebugLogging, MainFPM.addPass(InstCombinePass()); invokePeepholeEPCallbacks(MainFPM, Level); - MainFPM.addPass(JumpThreadingPass()); + MainFPM.addPass(JumpThreadingPass(/*InsertFreezeWhenUnfoldingSelect*/ true)); MPM.addPass(createModuleToFunctionPassAdaptor(std::move(MainFPM))); // Create a function that performs CFI checks for cross-DSO calls with @@ -1572,7 +1778,8 @@ PassBuilder::buildLTODefaultPipeline(OptimizationLevel Level, bool DebugLogging, // Add late LTO optimization passes. // Delete basic blocks, which optimization passes may have killed. - MPM.addPass(createModuleToFunctionPassAdaptor(SimplifyCFGPass())); + MPM.addPass(createModuleToFunctionPassAdaptor( + SimplifyCFGPass(SimplifyCFGOptions().hoistCommonInsts(true)))); // Drop bodies of available eternally objects to improve GlobalDCE. MPM.addPass(EliminateAvailableExternallyPass()); @@ -1580,7 +1787,112 @@ PassBuilder::buildLTODefaultPipeline(OptimizationLevel Level, bool DebugLogging, // Now that we have optimized the program, discard unreachable functions. MPM.addPass(GlobalDCEPass()); - // FIXME: Maybe enable MergeFuncs conditionally after it's ported. + if (PTO.MergeFunctions) + MPM.addPass(MergeFunctionsPass()); + + // Emit annotation remarks. + addAnnotationRemarksPass(MPM); + + return MPM; +} + +ModulePassManager PassBuilder::buildO0DefaultPipeline(OptimizationLevel Level, + bool LTOPreLink) { + assert(Level == OptimizationLevel::O0 && + "buildO0DefaultPipeline should only be used with O0"); + + ModulePassManager MPM(DebugLogging); + + // Add UniqueInternalLinkageNames Pass which renames internal linkage + // symbols with unique names. + if (PTO.UniqueLinkageNames) + MPM.addPass(UniqueInternalLinkageNamesPass()); + + if (PGOOpt && (PGOOpt->Action == PGOOptions::IRInstr || + PGOOpt->Action == PGOOptions::IRUse)) + addPGOInstrPassesForO0( + MPM, + /* RunProfileGen */ (PGOOpt->Action == PGOOptions::IRInstr), + /* IsCS */ false, PGOOpt->ProfileFile, PGOOpt->ProfileRemappingFile); + + for (auto &C : PipelineStartEPCallbacks) + C(MPM, Level); + for (auto &C : PipelineEarlySimplificationEPCallbacks) + C(MPM, Level); + + // Build a minimal pipeline based on the semantics required by LLVM, + // which is just that always inlining occurs. Further, disable generating + // lifetime intrinsics to avoid enabling further optimizations during + // code generation. + // However, we need to insert lifetime intrinsics to avoid invalid access + // caused by multithreaded coroutines. + MPM.addPass(AlwaysInlinerPass( + /*InsertLifetimeIntrinsics=*/PTO.Coroutines)); + + if (PTO.MergeFunctions) + MPM.addPass(MergeFunctionsPass()); + + if (EnableMatrix) + MPM.addPass( + createModuleToFunctionPassAdaptor(LowerMatrixIntrinsicsPass(true))); + + if (!CGSCCOptimizerLateEPCallbacks.empty()) { + CGSCCPassManager CGPM(DebugLogging); + for (auto &C : CGSCCOptimizerLateEPCallbacks) + C(CGPM, Level); + if (!CGPM.isEmpty()) + MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM))); + } + if (!LateLoopOptimizationsEPCallbacks.empty()) { + LoopPassManager LPM(DebugLogging); + for (auto &C : LateLoopOptimizationsEPCallbacks) + C(LPM, Level); + if (!LPM.isEmpty()) { + MPM.addPass(createModuleToFunctionPassAdaptor( + createFunctionToLoopPassAdaptor(std::move(LPM)))); + } + } + if (!LoopOptimizerEndEPCallbacks.empty()) { + LoopPassManager LPM(DebugLogging); + for (auto &C : LoopOptimizerEndEPCallbacks) + C(LPM, Level); + if (!LPM.isEmpty()) { + MPM.addPass(createModuleToFunctionPassAdaptor( + createFunctionToLoopPassAdaptor(std::move(LPM)))); + } + } + if (!ScalarOptimizerLateEPCallbacks.empty()) { + FunctionPassManager FPM(DebugLogging); + for (auto &C : ScalarOptimizerLateEPCallbacks) + C(FPM, Level); + if (!FPM.isEmpty()) + MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); + } + if (!VectorizerStartEPCallbacks.empty()) { + FunctionPassManager FPM(DebugLogging); + for (auto &C : VectorizerStartEPCallbacks) + C(FPM, Level); + if (!FPM.isEmpty()) + MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); + } + + if (PTO.Coroutines) { + MPM.addPass(createModuleToFunctionPassAdaptor(CoroEarlyPass())); + + CGSCCPassManager CGPM(DebugLogging); + CGPM.addPass(CoroSplitPass()); + CGPM.addPass(createCGSCCToFunctionPassAdaptor(CoroElidePass())); + MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM))); + + MPM.addPass(createModuleToFunctionPassAdaptor(CoroCleanupPass())); + } + + for (auto &C : OptimizerLastEPCallbacks) + C(MPM, Level); + + if (LTOPreLink) + addRequiredLTOPreLinkPasses(MPM); + return MPM; } @@ -1606,6 +1918,10 @@ AAManager PassBuilder::buildDefaultAAPipeline() { // results from `GlobalsAA` through a readonly proxy. AA.registerModuleAnalysis<GlobalsAA>(); + // Add target-specific alias analyses. + if (TM) + TM->registerDefaultAliasAnalyses(AA); + return AA; } @@ -1622,7 +1938,7 @@ static Optional<int> parseDevirtPassName(StringRef Name) { if (!Name.consume_front("devirt<") || !Name.consume_back(">")) return None; int Count; - if (Name.getAsInteger(0, Count) || Count <= 0) + if (Name.getAsInteger(0, Count) || Count < 0) return None; return Count; } @@ -1763,6 +2079,8 @@ Expected<SimplifyCFGOptions> parseSimplifyCFGOptions(StringRef Params) { Result.convertSwitchToLookupTable(Enable); } else if (ParamName == "keep-loops") { Result.needCanonicalLoops(Enable); + } else if (ParamName == "hoist-common-insts") { + Result.hoistCommonInsts(Enable); } else if (ParamName == "sink-common-insts") { Result.sinkCommonInsts(Enable); } else if (Enable && ParamName.consume_front("bonus-inst-threshold=")) { @@ -1854,6 +2172,8 @@ Expected<GVNOptions> parseGVNOptions(StringRef Params) { Result.setPRE(Enable); } else if (ParamName == "load-pre") { Result.setLoadPRE(Enable); + } else if (ParamName == "split-backedge-load-pre") { + Result.setLoadPRESplitBackedge(Enable); } else if (ParamName == "memdep") { Result.setMemDep(Enable); } else { @@ -2075,8 +2395,7 @@ PassBuilder::parsePipelineText(StringRef Text) { } Error PassBuilder::parseModulePass(ModulePassManager &MPM, - const PipelineElement &E, - bool VerifyEachPass, bool DebugLogging) { + const PipelineElement &E) { auto &Name = E.Name; auto &InnerPipeline = E.InnerPipeline; @@ -2084,32 +2403,28 @@ Error PassBuilder::parseModulePass(ModulePassManager &MPM, if (!InnerPipeline.empty()) { if (Name == "module") { ModulePassManager NestedMPM(DebugLogging); - if (auto Err = parseModulePassPipeline(NestedMPM, InnerPipeline, - VerifyEachPass, DebugLogging)) + if (auto Err = parseModulePassPipeline(NestedMPM, InnerPipeline)) return Err; MPM.addPass(std::move(NestedMPM)); return Error::success(); } if (Name == "cgscc") { CGSCCPassManager CGPM(DebugLogging); - if (auto Err = parseCGSCCPassPipeline(CGPM, InnerPipeline, VerifyEachPass, - DebugLogging)) + if (auto Err = parseCGSCCPassPipeline(CGPM, InnerPipeline)) return Err; MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM))); return Error::success(); } if (Name == "function") { FunctionPassManager FPM(DebugLogging); - if (auto Err = parseFunctionPassPipeline(FPM, InnerPipeline, - VerifyEachPass, DebugLogging)) + if (auto Err = parseFunctionPassPipeline(FPM, InnerPipeline)) return Err; MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); return Error::success(); } if (auto Count = parseRepeatPassName(Name)) { ModulePassManager NestedMPM(DebugLogging); - if (auto Err = parseModulePassPipeline(NestedMPM, InnerPipeline, - VerifyEachPass, DebugLogging)) + if (auto Err = parseModulePassPipeline(NestedMPM, InnerPipeline)) return Err; MPM.addPass(createRepeatedPass(*Count, std::move(NestedMPM))); return Error::success(); @@ -2143,31 +2458,10 @@ Error PassBuilder::parseModulePass(ModulePassManager &MPM, .Case("O3", OptimizationLevel::O3) .Case("Os", OptimizationLevel::Os) .Case("Oz", OptimizationLevel::Oz); - if (L == OptimizationLevel::O0) { - // Add instrumentation PGO passes -- at O0 we can still do PGO. - if (PGOOpt && Matches[1] != "thinlto" && - (PGOOpt->Action == PGOOptions::IRInstr || - PGOOpt->Action == PGOOptions::IRUse)) - addPGOInstrPassesForO0( - MPM, DebugLogging, - /* RunProfileGen */ (PGOOpt->Action == PGOOptions::IRInstr), - /* IsCS */ false, PGOOpt->ProfileFile, - PGOOpt->ProfileRemappingFile); - - // For IR that makes use of coroutines intrinsics, coroutine passes must - // be run, even at -O0. - if (PTO.Coroutines) { - MPM.addPass(createModuleToFunctionPassAdaptor(CoroEarlyPass())); - - CGSCCPassManager CGPM(DebugLogging); - CGPM.addPass(CoroSplitPass()); - CGPM.addPass(createCGSCCToFunctionPassAdaptor(CoroElidePass())); - MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM))); - - MPM.addPass(createModuleToFunctionPassAdaptor(CoroCleanupPass())); - } - - // Do nothing else at all! + if (L == OptimizationLevel::O0 && Matches[1] != "thinlto" && + Matches[1] != "lto") { + MPM.addPass(buildO0DefaultPipeline(L, Matches[1] == "thinlto-pre-link" || + Matches[1] == "lto-pre-link")); return Error::success(); } @@ -2180,16 +2474,16 @@ Error PassBuilder::parseModulePass(ModulePassManager &MPM, L.getSpeedupLevel() > 1 && L != OptimizationLevel::Oz; if (Matches[1] == "default") { - MPM.addPass(buildPerModuleDefaultPipeline(L, DebugLogging)); + MPM.addPass(buildPerModuleDefaultPipeline(L)); } else if (Matches[1] == "thinlto-pre-link") { - MPM.addPass(buildThinLTOPreLinkDefaultPipeline(L, DebugLogging)); + MPM.addPass(buildThinLTOPreLinkDefaultPipeline(L)); } else if (Matches[1] == "thinlto") { - MPM.addPass(buildThinLTODefaultPipeline(L, DebugLogging, nullptr)); + MPM.addPass(buildThinLTODefaultPipeline(L, nullptr)); } else if (Matches[1] == "lto-pre-link") { - MPM.addPass(buildLTOPreLinkDefaultPipeline(L, DebugLogging)); + MPM.addPass(buildLTOPreLinkDefaultPipeline(L)); } else { assert(Matches[1] == "lto" && "Not one of the matched options!"); - MPM.addPass(buildLTODefaultPipeline(L, DebugLogging, nullptr)); + MPM.addPass(buildLTODefaultPipeline(L, nullptr)); } return Error::success(); } @@ -2212,6 +2506,41 @@ Error PassBuilder::parseModulePass(ModulePassManager &MPM, std::remove_reference<decltype(CREATE_PASS)>::type>()); \ return Error::success(); \ } +#define CGSCC_PASS(NAME, CREATE_PASS) \ + if (Name == NAME) { \ + MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(CREATE_PASS)); \ + return Error::success(); \ + } +#define FUNCTION_PASS(NAME, CREATE_PASS) \ + if (Name == NAME) { \ + MPM.addPass(createModuleToFunctionPassAdaptor(CREATE_PASS)); \ + return Error::success(); \ + } +#define FUNCTION_PASS_WITH_PARAMS(NAME, CREATE_PASS, PARSER) \ + if (checkParametrizedPassName(Name, NAME)) { \ + auto Params = parsePassParameters(PARSER, Name, NAME); \ + if (!Params) \ + return Params.takeError(); \ + MPM.addPass(createModuleToFunctionPassAdaptor(CREATE_PASS(Params.get()))); \ + return Error::success(); \ + } +#define LOOP_PASS(NAME, CREATE_PASS) \ + if (Name == NAME) { \ + MPM.addPass( \ + createModuleToFunctionPassAdaptor(createFunctionToLoopPassAdaptor( \ + CREATE_PASS, false, false, DebugLogging))); \ + return Error::success(); \ + } +#define LOOP_PASS_WITH_PARAMS(NAME, CREATE_PASS, PARSER) \ + if (checkParametrizedPassName(Name, NAME)) { \ + auto Params = parsePassParameters(PARSER, Name, NAME); \ + if (!Params) \ + return Params.takeError(); \ + MPM.addPass( \ + createModuleToFunctionPassAdaptor(createFunctionToLoopPassAdaptor( \ + CREATE_PASS(Params.get()), false, false, DebugLogging))); \ + return Error::success(); \ + } #include "PassRegistry.def" for (auto &C : ModulePipelineParsingCallbacks) @@ -2223,8 +2552,7 @@ Error PassBuilder::parseModulePass(ModulePassManager &MPM, } Error PassBuilder::parseCGSCCPass(CGSCCPassManager &CGPM, - const PipelineElement &E, bool VerifyEachPass, - bool DebugLogging) { + const PipelineElement &E) { auto &Name = E.Name; auto &InnerPipeline = E.InnerPipeline; @@ -2232,8 +2560,7 @@ Error PassBuilder::parseCGSCCPass(CGSCCPassManager &CGPM, if (!InnerPipeline.empty()) { if (Name == "cgscc") { CGSCCPassManager NestedCGPM(DebugLogging); - if (auto Err = parseCGSCCPassPipeline(NestedCGPM, InnerPipeline, - VerifyEachPass, DebugLogging)) + if (auto Err = parseCGSCCPassPipeline(NestedCGPM, InnerPipeline)) return Err; // Add the nested pass manager with the appropriate adaptor. CGPM.addPass(std::move(NestedCGPM)); @@ -2241,8 +2568,7 @@ Error PassBuilder::parseCGSCCPass(CGSCCPassManager &CGPM, } if (Name == "function") { FunctionPassManager FPM(DebugLogging); - if (auto Err = parseFunctionPassPipeline(FPM, InnerPipeline, - VerifyEachPass, DebugLogging)) + if (auto Err = parseFunctionPassPipeline(FPM, InnerPipeline)) return Err; // Add the nested pass manager with the appropriate adaptor. CGPM.addPass(createCGSCCToFunctionPassAdaptor(std::move(FPM))); @@ -2250,16 +2576,14 @@ Error PassBuilder::parseCGSCCPass(CGSCCPassManager &CGPM, } if (auto Count = parseRepeatPassName(Name)) { CGSCCPassManager NestedCGPM(DebugLogging); - if (auto Err = parseCGSCCPassPipeline(NestedCGPM, InnerPipeline, - VerifyEachPass, DebugLogging)) + if (auto Err = parseCGSCCPassPipeline(NestedCGPM, InnerPipeline)) return Err; CGPM.addPass(createRepeatedPass(*Count, std::move(NestedCGPM))); return Error::success(); } if (auto MaxRepetitions = parseDevirtPassName(Name)) { CGSCCPassManager NestedCGPM(DebugLogging); - if (auto Err = parseCGSCCPassPipeline(NestedCGPM, InnerPipeline, - VerifyEachPass, DebugLogging)) + if (auto Err = parseCGSCCPassPipeline(NestedCGPM, InnerPipeline)) return Err; CGPM.addPass( createDevirtSCCRepeatedPass(std::move(NestedCGPM), *MaxRepetitions)); @@ -2295,6 +2619,36 @@ Error PassBuilder::parseCGSCCPass(CGSCCPassManager &CGPM, std::remove_reference<decltype(CREATE_PASS)>::type>()); \ return Error::success(); \ } +#define FUNCTION_PASS(NAME, CREATE_PASS) \ + if (Name == NAME) { \ + CGPM.addPass(createCGSCCToFunctionPassAdaptor(CREATE_PASS)); \ + return Error::success(); \ + } +#define FUNCTION_PASS_WITH_PARAMS(NAME, CREATE_PASS, PARSER) \ + if (checkParametrizedPassName(Name, NAME)) { \ + auto Params = parsePassParameters(PARSER, Name, NAME); \ + if (!Params) \ + return Params.takeError(); \ + CGPM.addPass(createCGSCCToFunctionPassAdaptor(CREATE_PASS(Params.get()))); \ + return Error::success(); \ + } +#define LOOP_PASS(NAME, CREATE_PASS) \ + if (Name == NAME) { \ + CGPM.addPass( \ + createCGSCCToFunctionPassAdaptor(createFunctionToLoopPassAdaptor( \ + CREATE_PASS, false, false, DebugLogging))); \ + return Error::success(); \ + } +#define LOOP_PASS_WITH_PARAMS(NAME, CREATE_PASS, PARSER) \ + if (checkParametrizedPassName(Name, NAME)) { \ + auto Params = parsePassParameters(PARSER, Name, NAME); \ + if (!Params) \ + return Params.takeError(); \ + CGPM.addPass( \ + createCGSCCToFunctionPassAdaptor(createFunctionToLoopPassAdaptor( \ + CREATE_PASS(Params.get()), false, false, DebugLogging))); \ + return Error::success(); \ + } #include "PassRegistry.def" for (auto &C : CGSCCPipelineParsingCallbacks) @@ -2306,8 +2660,7 @@ Error PassBuilder::parseCGSCCPass(CGSCCPassManager &CGPM, } Error PassBuilder::parseFunctionPass(FunctionPassManager &FPM, - const PipelineElement &E, - bool VerifyEachPass, bool DebugLogging) { + const PipelineElement &E) { auto &Name = E.Name; auto &InnerPipeline = E.InnerPipeline; @@ -2315,8 +2668,7 @@ Error PassBuilder::parseFunctionPass(FunctionPassManager &FPM, if (!InnerPipeline.empty()) { if (Name == "function") { FunctionPassManager NestedFPM(DebugLogging); - if (auto Err = parseFunctionPassPipeline(NestedFPM, InnerPipeline, - VerifyEachPass, DebugLogging)) + if (auto Err = parseFunctionPassPipeline(NestedFPM, InnerPipeline)) return Err; // Add the nested pass manager with the appropriate adaptor. FPM.addPass(std::move(NestedFPM)); @@ -2324,19 +2676,19 @@ Error PassBuilder::parseFunctionPass(FunctionPassManager &FPM, } if (Name == "loop" || Name == "loop-mssa") { LoopPassManager LPM(DebugLogging); - if (auto Err = parseLoopPassPipeline(LPM, InnerPipeline, VerifyEachPass, - DebugLogging)) + if (auto Err = parseLoopPassPipeline(LPM, InnerPipeline)) return Err; // Add the nested pass manager with the appropriate adaptor. bool UseMemorySSA = (Name == "loop-mssa"); + bool UseBFI = llvm::any_of( + InnerPipeline, [](auto Pipeline) { return Pipeline.Name == "licm"; }); FPM.addPass(createFunctionToLoopPassAdaptor(std::move(LPM), UseMemorySSA, - DebugLogging)); + UseBFI, DebugLogging)); return Error::success(); } if (auto Count = parseRepeatPassName(Name)) { FunctionPassManager NestedFPM(DebugLogging); - if (auto Err = parseFunctionPassPipeline(NestedFPM, InnerPipeline, - VerifyEachPass, DebugLogging)) + if (auto Err = parseFunctionPassPipeline(NestedFPM, InnerPipeline)) return Err; FPM.addPass(createRepeatedPass(*Count, std::move(NestedFPM))); return Error::success(); @@ -2378,6 +2730,25 @@ Error PassBuilder::parseFunctionPass(FunctionPassManager &FPM, std::remove_reference<decltype(CREATE_PASS)>::type>()); \ return Error::success(); \ } +// FIXME: UseMemorySSA is set to false. Maybe we could do things like: +// bool UseMemorySSA = !("canon-freeze" || "loop-predication" || +// "guard-widening"); +// The risk is that it may become obsolete if we're not careful. +#define LOOP_PASS(NAME, CREATE_PASS) \ + if (Name == NAME) { \ + FPM.addPass(createFunctionToLoopPassAdaptor(CREATE_PASS, false, false, \ + DebugLogging)); \ + return Error::success(); \ + } +#define LOOP_PASS_WITH_PARAMS(NAME, CREATE_PASS, PARSER) \ + if (checkParametrizedPassName(Name, NAME)) { \ + auto Params = parsePassParameters(PARSER, Name, NAME); \ + if (!Params) \ + return Params.takeError(); \ + FPM.addPass(createFunctionToLoopPassAdaptor(CREATE_PASS(Params.get()), \ + false, false, DebugLogging)); \ + return Error::success(); \ + } #include "PassRegistry.def" for (auto &C : FunctionPipelineParsingCallbacks) @@ -2388,8 +2759,8 @@ Error PassBuilder::parseFunctionPass(FunctionPassManager &FPM, inconvertibleErrorCode()); } -Error PassBuilder::parseLoopPass(LoopPassManager &LPM, const PipelineElement &E, - bool VerifyEachPass, bool DebugLogging) { +Error PassBuilder::parseLoopPass(LoopPassManager &LPM, + const PipelineElement &E) { StringRef Name = E.Name; auto &InnerPipeline = E.InnerPipeline; @@ -2397,8 +2768,7 @@ Error PassBuilder::parseLoopPass(LoopPassManager &LPM, const PipelineElement &E, if (!InnerPipeline.empty()) { if (Name == "loop") { LoopPassManager NestedLPM(DebugLogging); - if (auto Err = parseLoopPassPipeline(NestedLPM, InnerPipeline, - VerifyEachPass, DebugLogging)) + if (auto Err = parseLoopPassPipeline(NestedLPM, InnerPipeline)) return Err; // Add the nested pass manager with the appropriate adaptor. LPM.addPass(std::move(NestedLPM)); @@ -2406,8 +2776,7 @@ Error PassBuilder::parseLoopPass(LoopPassManager &LPM, const PipelineElement &E, } if (auto Count = parseRepeatPassName(Name)) { LoopPassManager NestedLPM(DebugLogging); - if (auto Err = parseLoopPassPipeline(NestedLPM, InnerPipeline, - VerifyEachPass, DebugLogging)) + if (auto Err = parseLoopPassPipeline(NestedLPM, InnerPipeline)) return Err; LPM.addPass(createRepeatedPass(*Count, std::move(NestedLPM))); return Error::success(); @@ -2481,39 +2850,28 @@ bool PassBuilder::parseAAPassName(AAManager &AA, StringRef Name) { } Error PassBuilder::parseLoopPassPipeline(LoopPassManager &LPM, - ArrayRef<PipelineElement> Pipeline, - bool VerifyEachPass, - bool DebugLogging) { + ArrayRef<PipelineElement> Pipeline) { for (const auto &Element : Pipeline) { - if (auto Err = parseLoopPass(LPM, Element, VerifyEachPass, DebugLogging)) + if (auto Err = parseLoopPass(LPM, Element)) return Err; - // FIXME: No verifier support for Loop passes! } return Error::success(); } -Error PassBuilder::parseFunctionPassPipeline(FunctionPassManager &FPM, - ArrayRef<PipelineElement> Pipeline, - bool VerifyEachPass, - bool DebugLogging) { +Error PassBuilder::parseFunctionPassPipeline( + FunctionPassManager &FPM, ArrayRef<PipelineElement> Pipeline) { for (const auto &Element : Pipeline) { - if (auto Err = - parseFunctionPass(FPM, Element, VerifyEachPass, DebugLogging)) + if (auto Err = parseFunctionPass(FPM, Element)) return Err; - if (VerifyEachPass) - FPM.addPass(VerifierPass()); } return Error::success(); } Error PassBuilder::parseCGSCCPassPipeline(CGSCCPassManager &CGPM, - ArrayRef<PipelineElement> Pipeline, - bool VerifyEachPass, - bool DebugLogging) { + ArrayRef<PipelineElement> Pipeline) { for (const auto &Element : Pipeline) { - if (auto Err = parseCGSCCPass(CGPM, Element, VerifyEachPass, DebugLogging)) + if (auto Err = parseCGSCCPass(CGPM, Element)) return Err; - // FIXME: No verifier support for CGSCC passes! } return Error::success(); } @@ -2532,14 +2890,10 @@ void PassBuilder::crossRegisterProxies(LoopAnalysisManager &LAM, } Error PassBuilder::parseModulePassPipeline(ModulePassManager &MPM, - ArrayRef<PipelineElement> Pipeline, - bool VerifyEachPass, - bool DebugLogging) { + ArrayRef<PipelineElement> Pipeline) { for (const auto &Element : Pipeline) { - if (auto Err = parseModulePass(MPM, Element, VerifyEachPass, DebugLogging)) + if (auto Err = parseModulePass(MPM, Element)) return Err; - if (VerifyEachPass) - MPM.addPass(VerifierPass()); } return Error::success(); } @@ -2548,8 +2902,7 @@ Error PassBuilder::parseModulePassPipeline(ModulePassManager &MPM, // FIXME: Should this routine accept a TargetMachine or require the caller to // pre-populate the analysis managers with target-specific stuff? Error PassBuilder::parsePassPipeline(ModulePassManager &MPM, - StringRef PipelineText, - bool VerifyEachPass, bool DebugLogging) { + StringRef PipelineText) { auto Pipeline = parsePipelineText(PipelineText); if (!Pipeline || Pipeline->empty()) return make_error<StringError>( @@ -2570,7 +2923,7 @@ Error PassBuilder::parsePassPipeline(ModulePassManager &MPM, Pipeline = {{"function", {{"loop", std::move(*Pipeline)}}}}; } else { for (auto &C : TopLevelPipelineParsingCallbacks) - if (C(MPM, *Pipeline, VerifyEachPass, DebugLogging)) + if (C(MPM, *Pipeline, DebugLogging)) return Error::success(); // Unknown pass or pipeline name! @@ -2583,16 +2936,14 @@ Error PassBuilder::parsePassPipeline(ModulePassManager &MPM, } } - if (auto Err = - parseModulePassPipeline(MPM, *Pipeline, VerifyEachPass, DebugLogging)) + if (auto Err = parseModulePassPipeline(MPM, *Pipeline)) return Err; return Error::success(); } // Primary pass pipeline description parsing routine for a \c CGSCCPassManager Error PassBuilder::parsePassPipeline(CGSCCPassManager &CGPM, - StringRef PipelineText, - bool VerifyEachPass, bool DebugLogging) { + StringRef PipelineText) { auto Pipeline = parsePipelineText(PipelineText); if (!Pipeline || Pipeline->empty()) return make_error<StringError>( @@ -2607,8 +2958,7 @@ Error PassBuilder::parsePassPipeline(CGSCCPassManager &CGPM, .str(), inconvertibleErrorCode()); - if (auto Err = - parseCGSCCPassPipeline(CGPM, *Pipeline, VerifyEachPass, DebugLogging)) + if (auto Err = parseCGSCCPassPipeline(CGPM, *Pipeline)) return Err; return Error::success(); } @@ -2616,8 +2966,7 @@ Error PassBuilder::parsePassPipeline(CGSCCPassManager &CGPM, // Primary pass pipeline description parsing routine for a \c // FunctionPassManager Error PassBuilder::parsePassPipeline(FunctionPassManager &FPM, - StringRef PipelineText, - bool VerifyEachPass, bool DebugLogging) { + StringRef PipelineText) { auto Pipeline = parsePipelineText(PipelineText); if (!Pipeline || Pipeline->empty()) return make_error<StringError>( @@ -2632,24 +2981,21 @@ Error PassBuilder::parsePassPipeline(FunctionPassManager &FPM, .str(), inconvertibleErrorCode()); - if (auto Err = parseFunctionPassPipeline(FPM, *Pipeline, VerifyEachPass, - DebugLogging)) + if (auto Err = parseFunctionPassPipeline(FPM, *Pipeline)) return Err; return Error::success(); } // Primary pass pipeline description parsing routine for a \c LoopPassManager Error PassBuilder::parsePassPipeline(LoopPassManager &CGPM, - StringRef PipelineText, - bool VerifyEachPass, bool DebugLogging) { + StringRef PipelineText) { auto Pipeline = parsePipelineText(PipelineText); if (!Pipeline || Pipeline->empty()) return make_error<StringError>( formatv("invalid pipeline '{0}'", PipelineText).str(), inconvertibleErrorCode()); - if (auto Err = - parseLoopPassPipeline(CGPM, *Pipeline, VerifyEachPass, DebugLogging)) + if (auto Err = parseLoopPassPipeline(CGPM, *Pipeline)) return Err; return Error::success(); @@ -2676,6 +3022,9 @@ Error PassBuilder::parseAAPipeline(AAManager &AA, StringRef PipelineText) { } bool PassBuilder::isAAPassName(StringRef PassName) { +#define MODULE_ALIAS_ANALYSIS(NAME, CREATE_PASS) \ + if (PassName == NAME) \ + return true; #define FUNCTION_ALIAS_ANALYSIS(NAME, CREATE_PASS) \ if (PassName == NAME) \ return true; @@ -2693,9 +3042,21 @@ bool PassBuilder::isAnalysisPassName(StringRef PassName) { #define LOOP_ANALYSIS(NAME, CREATE_PASS) \ if (PassName == NAME) \ return true; -#define CGSSC_ANALYSIS(NAME, CREATE_PASS) \ +#define CGSCC_ANALYSIS(NAME, CREATE_PASS) \ + if (PassName == NAME) \ + return true; +#define MODULE_ALIAS_ANALYSIS(NAME, CREATE_PASS) \ + if (PassName == NAME) \ + return true; +#define FUNCTION_ALIAS_ANALYSIS(NAME, CREATE_PASS) \ if (PassName == NAME) \ return true; #include "PassRegistry.def" return false; } + +void PassBuilder::registerParseTopLevelPipelineCallback( + const std::function<bool(ModulePassManager &, ArrayRef<PipelineElement>, + bool DebugLogging)> &C) { + TopLevelPipelineParsingCallbacks.push_back(C); +} |