Path: blob/main/contrib/llvm-project/llvm/lib/Passes/PassBuilder.cpp
35262 views
//===- Parsing and selection of pass pipelines ----------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7/// \file8///9/// This file provides the implementation of the PassBuilder based on our10/// static pass registry as well as related functionality. It also provides11/// helpers to aid in analyzing, debugging, and testing passes and pass12/// pipelines.13///14//===----------------------------------------------------------------------===//1516#include "llvm/Passes/PassBuilder.h"17#include "llvm/ADT/StringSwitch.h"18#include "llvm/Analysis/AliasAnalysisEvaluator.h"19#include "llvm/Analysis/AliasSetTracker.h"20#include "llvm/Analysis/AssumptionCache.h"21#include "llvm/Analysis/BasicAliasAnalysis.h"22#include "llvm/Analysis/BlockFrequencyInfo.h"23#include "llvm/Analysis/BranchProbabilityInfo.h"24#include "llvm/Analysis/CFGPrinter.h"25#include "llvm/Analysis/CFGSCCPrinter.h"26#include "llvm/Analysis/CGSCCPassManager.h"27#include "llvm/Analysis/CallGraph.h"28#include "llvm/Analysis/CallPrinter.h"29#include "llvm/Analysis/CostModel.h"30#include "llvm/Analysis/CycleAnalysis.h"31#include "llvm/Analysis/DDG.h"32#include "llvm/Analysis/DDGPrinter.h"33#include "llvm/Analysis/Delinearization.h"34#include "llvm/Analysis/DemandedBits.h"35#include "llvm/Analysis/DependenceAnalysis.h"36#include "llvm/Analysis/DomPrinter.h"37#include "llvm/Analysis/DominanceFrontier.h"38#include "llvm/Analysis/FunctionPropertiesAnalysis.h"39#include "llvm/Analysis/GlobalsModRef.h"40#include "llvm/Analysis/IRSimilarityIdentifier.h"41#include "llvm/Analysis/IVUsers.h"42#include "llvm/Analysis/InlineAdvisor.h"43#include "llvm/Analysis/InlineSizeEstimatorAnalysis.h"44#include "llvm/Analysis/InstCount.h"45#include "llvm/Analysis/LazyCallGraph.h"46#include "llvm/Analysis/LazyValueInfo.h"47#include "llvm/Analysis/Lint.h"48#include "llvm/Analysis/LoopAccessAnalysis.h"49#include "llvm/Analysis/LoopCacheAnalysis.h"50#include "llvm/Analysis/LoopInfo.h"51#include "llvm/Analysis/LoopNestAnalysis.h"52#include "llvm/Analysis/MemDerefPrinter.h"53#include "llvm/Analysis/MemoryDependenceAnalysis.h"54#include "llvm/Analysis/MemorySSA.h"55#include "llvm/Analysis/ModuleDebugInfoPrinter.h"56#include "llvm/Analysis/ModuleSummaryAnalysis.h"57#include "llvm/Analysis/MustExecute.h"58#include "llvm/Analysis/ObjCARCAliasAnalysis.h"59#include "llvm/Analysis/OptimizationRemarkEmitter.h"60#include "llvm/Analysis/PhiValues.h"61#include "llvm/Analysis/PostDominators.h"62#include "llvm/Analysis/ProfileSummaryInfo.h"63#include "llvm/Analysis/RegionInfo.h"64#include "llvm/Analysis/ScalarEvolution.h"65#include "llvm/Analysis/ScalarEvolutionAliasAnalysis.h"66#include "llvm/Analysis/ScopedNoAliasAA.h"67#include "llvm/Analysis/StackLifetime.h"68#include "llvm/Analysis/StackSafetyAnalysis.h"69#include "llvm/Analysis/StructuralHash.h"70#include "llvm/Analysis/TargetLibraryInfo.h"71#include "llvm/Analysis/TargetTransformInfo.h"72#include "llvm/Analysis/TypeBasedAliasAnalysis.h"73#include "llvm/Analysis/UniformityAnalysis.h"74#include "llvm/CodeGen/AssignmentTrackingAnalysis.h"75#include "llvm/CodeGen/AtomicExpand.h"76#include "llvm/CodeGen/BasicBlockSectionsProfileReader.h"77#include "llvm/CodeGen/CallBrPrepare.h"78#include "llvm/CodeGen/CodeGenPrepare.h"79#include "llvm/CodeGen/DeadMachineInstructionElim.h"80#include "llvm/CodeGen/DwarfEHPrepare.h"81#include "llvm/CodeGen/ExpandLargeDivRem.h"82#include "llvm/CodeGen/ExpandLargeFpConvert.h"83#include "llvm/CodeGen/ExpandMemCmp.h"84#include "llvm/CodeGen/FinalizeISel.h"85#include "llvm/CodeGen/GCMetadata.h"86#include "llvm/CodeGen/GlobalMerge.h"87#include "llvm/CodeGen/HardwareLoops.h"88#include "llvm/CodeGen/IndirectBrExpand.h"89#include "llvm/CodeGen/InterleavedAccess.h"90#include "llvm/CodeGen/InterleavedLoadCombine.h"91#include "llvm/CodeGen/JMCInstrumenter.h"92#include "llvm/CodeGen/LiveIntervals.h"93#include "llvm/CodeGen/LiveVariables.h"94#include "llvm/CodeGen/LocalStackSlotAllocation.h"95#include "llvm/CodeGen/LowerEmuTLS.h"96#include "llvm/CodeGen/MIRPrinter.h"97#include "llvm/CodeGen/MachineBlockFrequencyInfo.h"98#include "llvm/CodeGen/MachineBranchProbabilityInfo.h"99#include "llvm/CodeGen/MachineDominators.h"100#include "llvm/CodeGen/MachineFunctionAnalysis.h"101#include "llvm/CodeGen/MachineLoopInfo.h"102#include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"103#include "llvm/CodeGen/MachinePassManager.h"104#include "llvm/CodeGen/MachinePostDominators.h"105#include "llvm/CodeGen/MachineRegisterInfo.h"106#include "llvm/CodeGen/MachineVerifier.h"107#include "llvm/CodeGen/PHIElimination.h"108#include "llvm/CodeGen/PreISelIntrinsicLowering.h"109#include "llvm/CodeGen/RegAllocFast.h"110#include "llvm/CodeGen/SafeStack.h"111#include "llvm/CodeGen/SelectOptimize.h"112#include "llvm/CodeGen/ShadowStackGCLowering.h"113#include "llvm/CodeGen/SjLjEHPrepare.h"114#include "llvm/CodeGen/SlotIndexes.h"115#include "llvm/CodeGen/StackProtector.h"116#include "llvm/CodeGen/TargetPassConfig.h"117#include "llvm/CodeGen/TwoAddressInstructionPass.h"118#include "llvm/CodeGen/TypePromotion.h"119#include "llvm/CodeGen/WasmEHPrepare.h"120#include "llvm/CodeGen/WinEHPrepare.h"121#include "llvm/IR/DebugInfo.h"122#include "llvm/IR/Dominators.h"123#include "llvm/IR/PassManager.h"124#include "llvm/IR/PrintPasses.h"125#include "llvm/IR/SafepointIRVerifier.h"126#include "llvm/IR/Verifier.h"127#include "llvm/IRPrinter/IRPrintingPasses.h"128#include "llvm/Passes/OptimizationLevel.h"129#include "llvm/Support/CommandLine.h"130#include "llvm/Support/Debug.h"131#include "llvm/Support/ErrorHandling.h"132#include "llvm/Support/FormatVariadic.h"133#include "llvm/Support/Regex.h"134#include "llvm/Target/TargetMachine.h"135#include "llvm/Transforms/AggressiveInstCombine/AggressiveInstCombine.h"136#include "llvm/Transforms/CFGuard.h"137#include "llvm/Transforms/Coroutines/CoroCleanup.h"138#include "llvm/Transforms/Coroutines/CoroConditionalWrapper.h"139#include "llvm/Transforms/Coroutines/CoroEarly.h"140#include "llvm/Transforms/Coroutines/CoroElide.h"141#include "llvm/Transforms/Coroutines/CoroSplit.h"142#include "llvm/Transforms/HipStdPar/HipStdPar.h"143#include "llvm/Transforms/IPO/AlwaysInliner.h"144#include "llvm/Transforms/IPO/Annotation2Metadata.h"145#include "llvm/Transforms/IPO/ArgumentPromotion.h"146#include "llvm/Transforms/IPO/Attributor.h"147#include "llvm/Transforms/IPO/BlockExtractor.h"148#include "llvm/Transforms/IPO/CalledValuePropagation.h"149#include "llvm/Transforms/IPO/ConstantMerge.h"150#include "llvm/Transforms/IPO/CrossDSOCFI.h"151#include "llvm/Transforms/IPO/DeadArgumentElimination.h"152#include "llvm/Transforms/IPO/ElimAvailExtern.h"153#include "llvm/Transforms/IPO/EmbedBitcodePass.h"154#include "llvm/Transforms/IPO/ExpandVariadics.h"155#include "llvm/Transforms/IPO/ForceFunctionAttrs.h"156#include "llvm/Transforms/IPO/FunctionAttrs.h"157#include "llvm/Transforms/IPO/FunctionImport.h"158#include "llvm/Transforms/IPO/GlobalDCE.h"159#include "llvm/Transforms/IPO/GlobalOpt.h"160#include "llvm/Transforms/IPO/GlobalSplit.h"161#include "llvm/Transforms/IPO/HotColdSplitting.h"162#include "llvm/Transforms/IPO/IROutliner.h"163#include "llvm/Transforms/IPO/InferFunctionAttrs.h"164#include "llvm/Transforms/IPO/Inliner.h"165#include "llvm/Transforms/IPO/Internalize.h"166#include "llvm/Transforms/IPO/LoopExtractor.h"167#include "llvm/Transforms/IPO/LowerTypeTests.h"168#include "llvm/Transforms/IPO/MemProfContextDisambiguation.h"169#include "llvm/Transforms/IPO/MergeFunctions.h"170#include "llvm/Transforms/IPO/ModuleInliner.h"171#include "llvm/Transforms/IPO/OpenMPOpt.h"172#include "llvm/Transforms/IPO/PartialInlining.h"173#include "llvm/Transforms/IPO/SCCP.h"174#include "llvm/Transforms/IPO/SampleProfile.h"175#include "llvm/Transforms/IPO/SampleProfileProbe.h"176#include "llvm/Transforms/IPO/StripDeadPrototypes.h"177#include "llvm/Transforms/IPO/StripSymbols.h"178#include "llvm/Transforms/IPO/SyntheticCountsPropagation.h"179#include "llvm/Transforms/IPO/WholeProgramDevirt.h"180#include "llvm/Transforms/InstCombine/InstCombine.h"181#include "llvm/Transforms/Instrumentation.h"182#include "llvm/Transforms/Instrumentation/AddressSanitizer.h"183#include "llvm/Transforms/Instrumentation/BoundsChecking.h"184#include "llvm/Transforms/Instrumentation/CGProfile.h"185#include "llvm/Transforms/Instrumentation/ControlHeightReduction.h"186#include "llvm/Transforms/Instrumentation/DataFlowSanitizer.h"187#include "llvm/Transforms/Instrumentation/GCOVProfiler.h"188#include "llvm/Transforms/Instrumentation/HWAddressSanitizer.h"189#include "llvm/Transforms/Instrumentation/InstrOrderFile.h"190#include "llvm/Transforms/Instrumentation/InstrProfiling.h"191#include "llvm/Transforms/Instrumentation/KCFI.h"192#include "llvm/Transforms/Instrumentation/LowerAllowCheckPass.h"193#include "llvm/Transforms/Instrumentation/MemProfiler.h"194#include "llvm/Transforms/Instrumentation/MemorySanitizer.h"195#include "llvm/Transforms/Instrumentation/NumericalStabilitySanitizer.h"196#include "llvm/Transforms/Instrumentation/PGOCtxProfLowering.h"197#include "llvm/Transforms/Instrumentation/PGOForceFunctionAttrs.h"198#include "llvm/Transforms/Instrumentation/PGOInstrumentation.h"199#include "llvm/Transforms/Instrumentation/PoisonChecking.h"200#include "llvm/Transforms/Instrumentation/SanitizerBinaryMetadata.h"201#include "llvm/Transforms/Instrumentation/SanitizerCoverage.h"202#include "llvm/Transforms/Instrumentation/ThreadSanitizer.h"203#include "llvm/Transforms/ObjCARC.h"204#include "llvm/Transforms/Scalar/ADCE.h"205#include "llvm/Transforms/Scalar/AlignmentFromAssumptions.h"206#include "llvm/Transforms/Scalar/AnnotationRemarks.h"207#include "llvm/Transforms/Scalar/BDCE.h"208#include "llvm/Transforms/Scalar/CallSiteSplitting.h"209#include "llvm/Transforms/Scalar/ConstantHoisting.h"210#include "llvm/Transforms/Scalar/ConstraintElimination.h"211#include "llvm/Transforms/Scalar/CorrelatedValuePropagation.h"212#include "llvm/Transforms/Scalar/DCE.h"213#include "llvm/Transforms/Scalar/DFAJumpThreading.h"214#include "llvm/Transforms/Scalar/DeadStoreElimination.h"215#include "llvm/Transforms/Scalar/DivRemPairs.h"216#include "llvm/Transforms/Scalar/EarlyCSE.h"217#include "llvm/Transforms/Scalar/FlattenCFG.h"218#include "llvm/Transforms/Scalar/Float2Int.h"219#include "llvm/Transforms/Scalar/GVN.h"220#include "llvm/Transforms/Scalar/GuardWidening.h"221#include "llvm/Transforms/Scalar/IVUsersPrinter.h"222#include "llvm/Transforms/Scalar/IndVarSimplify.h"223#include "llvm/Transforms/Scalar/InductiveRangeCheckElimination.h"224#include "llvm/Transforms/Scalar/InferAddressSpaces.h"225#include "llvm/Transforms/Scalar/InferAlignment.h"226#include "llvm/Transforms/Scalar/InstSimplifyPass.h"227#include "llvm/Transforms/Scalar/JumpTableToSwitch.h"228#include "llvm/Transforms/Scalar/JumpThreading.h"229#include "llvm/Transforms/Scalar/LICM.h"230#include "llvm/Transforms/Scalar/LoopAccessAnalysisPrinter.h"231#include "llvm/Transforms/Scalar/LoopBoundSplit.h"232#include "llvm/Transforms/Scalar/LoopDataPrefetch.h"233#include "llvm/Transforms/Scalar/LoopDeletion.h"234#include "llvm/Transforms/Scalar/LoopDistribute.h"235#include "llvm/Transforms/Scalar/LoopFlatten.h"236#include "llvm/Transforms/Scalar/LoopFuse.h"237#include "llvm/Transforms/Scalar/LoopIdiomRecognize.h"238#include "llvm/Transforms/Scalar/LoopInstSimplify.h"239#include "llvm/Transforms/Scalar/LoopInterchange.h"240#include "llvm/Transforms/Scalar/LoopLoadElimination.h"241#include "llvm/Transforms/Scalar/LoopPassManager.h"242#include "llvm/Transforms/Scalar/LoopPredication.h"243#include "llvm/Transforms/Scalar/LoopRotation.h"244#include "llvm/Transforms/Scalar/LoopSimplifyCFG.h"245#include "llvm/Transforms/Scalar/LoopSink.h"246#include "llvm/Transforms/Scalar/LoopStrengthReduce.h"247#include "llvm/Transforms/Scalar/LoopUnrollAndJamPass.h"248#include "llvm/Transforms/Scalar/LoopUnrollPass.h"249#include "llvm/Transforms/Scalar/LoopVersioningLICM.h"250#include "llvm/Transforms/Scalar/LowerAtomicPass.h"251#include "llvm/Transforms/Scalar/LowerConstantIntrinsics.h"252#include "llvm/Transforms/Scalar/LowerExpectIntrinsic.h"253#include "llvm/Transforms/Scalar/LowerGuardIntrinsic.h"254#include "llvm/Transforms/Scalar/LowerMatrixIntrinsics.h"255#include "llvm/Transforms/Scalar/LowerWidenableCondition.h"256#include "llvm/Transforms/Scalar/MakeGuardsExplicit.h"257#include "llvm/Transforms/Scalar/MemCpyOptimizer.h"258#include "llvm/Transforms/Scalar/MergeICmps.h"259#include "llvm/Transforms/Scalar/MergedLoadStoreMotion.h"260#include "llvm/Transforms/Scalar/NaryReassociate.h"261#include "llvm/Transforms/Scalar/NewGVN.h"262#include "llvm/Transforms/Scalar/PartiallyInlineLibCalls.h"263#include "llvm/Transforms/Scalar/PlaceSafepoints.h"264#include "llvm/Transforms/Scalar/Reassociate.h"265#include "llvm/Transforms/Scalar/Reg2Mem.h"266#include "llvm/Transforms/Scalar/RewriteStatepointsForGC.h"267#include "llvm/Transforms/Scalar/SCCP.h"268#include "llvm/Transforms/Scalar/SROA.h"269#include "llvm/Transforms/Scalar/ScalarizeMaskedMemIntrin.h"270#include "llvm/Transforms/Scalar/Scalarizer.h"271#include "llvm/Transforms/Scalar/SeparateConstOffsetFromGEP.h"272#include "llvm/Transforms/Scalar/SimpleLoopUnswitch.h"273#include "llvm/Transforms/Scalar/SimplifyCFG.h"274#include "llvm/Transforms/Scalar/Sink.h"275#include "llvm/Transforms/Scalar/SpeculativeExecution.h"276#include "llvm/Transforms/Scalar/StraightLineStrengthReduce.h"277#include "llvm/Transforms/Scalar/StructurizeCFG.h"278#include "llvm/Transforms/Scalar/TLSVariableHoist.h"279#include "llvm/Transforms/Scalar/TailRecursionElimination.h"280#include "llvm/Transforms/Scalar/WarnMissedTransforms.h"281#include "llvm/Transforms/Utils/AddDiscriminators.h"282#include "llvm/Transforms/Utils/AssumeBundleBuilder.h"283#include "llvm/Transforms/Utils/BreakCriticalEdges.h"284#include "llvm/Transforms/Utils/CanonicalizeAliases.h"285#include "llvm/Transforms/Utils/CanonicalizeFreezeInLoops.h"286#include "llvm/Transforms/Utils/CountVisits.h"287#include "llvm/Transforms/Utils/DXILUpgrade.h"288#include "llvm/Transforms/Utils/Debugify.h"289#include "llvm/Transforms/Utils/EntryExitInstrumenter.h"290#include "llvm/Transforms/Utils/FixIrreducible.h"291#include "llvm/Transforms/Utils/HelloWorld.h"292#include "llvm/Transforms/Utils/InjectTLIMappings.h"293#include "llvm/Transforms/Utils/InstructionNamer.h"294#include "llvm/Transforms/Utils/LCSSA.h"295#include "llvm/Transforms/Utils/LibCallsShrinkWrap.h"296#include "llvm/Transforms/Utils/LoopSimplify.h"297#include "llvm/Transforms/Utils/LoopVersioning.h"298#include "llvm/Transforms/Utils/LowerGlobalDtors.h"299#include "llvm/Transforms/Utils/LowerIFunc.h"300#include "llvm/Transforms/Utils/LowerInvoke.h"301#include "llvm/Transforms/Utils/LowerSwitch.h"302#include "llvm/Transforms/Utils/Mem2Reg.h"303#include "llvm/Transforms/Utils/MetaRenamer.h"304#include "llvm/Transforms/Utils/MoveAutoInit.h"305#include "llvm/Transforms/Utils/NameAnonGlobals.h"306#include "llvm/Transforms/Utils/PredicateInfo.h"307#include "llvm/Transforms/Utils/RelLookupTableConverter.h"308#include "llvm/Transforms/Utils/StripGCRelocates.h"309#include "llvm/Transforms/Utils/StripNonLineTableDebugInfo.h"310#include "llvm/Transforms/Utils/SymbolRewriter.h"311#include "llvm/Transforms/Utils/UnifyFunctionExitNodes.h"312#include "llvm/Transforms/Utils/UnifyLoopExits.h"313#include "llvm/Transforms/Vectorize/LoadStoreVectorizer.h"314#include "llvm/Transforms/Vectorize/LoopIdiomVectorize.h"315#include "llvm/Transforms/Vectorize/LoopVectorize.h"316#include "llvm/Transforms/Vectorize/SLPVectorizer.h"317#include "llvm/Transforms/Vectorize/VectorCombine.h"318#include <optional>319320using namespace llvm;321322static const Regex DefaultAliasRegex(323"^(default|thinlto-pre-link|thinlto|lto-pre-link|lto)<(O[0123sz])>$");324325namespace llvm {326cl::opt<bool> PrintPipelinePasses(327"print-pipeline-passes",328cl::desc("Print a '-passes' compatible string describing the pipeline "329"(best-effort only)."));330} // namespace llvm331332AnalysisKey NoOpModuleAnalysis::Key;333AnalysisKey NoOpCGSCCAnalysis::Key;334AnalysisKey NoOpFunctionAnalysis::Key;335AnalysisKey NoOpLoopAnalysis::Key;336337namespace {338339// Passes for testing crashes.340// DO NOT USE THIS EXCEPT FOR TESTING!341class TriggerCrashModulePass : public PassInfoMixin<TriggerCrashModulePass> {342public:343PreservedAnalyses run(Module &, ModuleAnalysisManager &) {344abort();345return PreservedAnalyses::all();346}347static StringRef name() { return "TriggerCrashModulePass"; }348};349350class TriggerCrashFunctionPass351: public PassInfoMixin<TriggerCrashFunctionPass> {352public:353PreservedAnalyses run(Function &, FunctionAnalysisManager &) {354abort();355return PreservedAnalyses::all();356}357static StringRef name() { return "TriggerCrashFunctionPass"; }358};359360// A pass for testing message reporting of -verify-each failures.361// DO NOT USE THIS EXCEPT FOR TESTING!362class TriggerVerifierErrorPass363: public PassInfoMixin<TriggerVerifierErrorPass> {364public:365PreservedAnalyses run(Module &M, ModuleAnalysisManager &) {366// Intentionally break the Module by creating an alias without setting the367// aliasee.368auto *PtrTy = llvm::PointerType::getUnqual(M.getContext());369GlobalAlias::create(PtrTy, PtrTy->getAddressSpace(),370GlobalValue::LinkageTypes::InternalLinkage,371"__bad_alias", nullptr, &M);372return PreservedAnalyses::none();373}374375PreservedAnalyses run(Function &F, FunctionAnalysisManager &) {376// Intentionally break the Function by inserting a terminator377// instruction in the middle of a basic block.378BasicBlock &BB = F.getEntryBlock();379new UnreachableInst(F.getContext(), BB.getTerminator()->getIterator());380return PreservedAnalyses::none();381}382383PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &) {384// Intentionally create a virtual register and set NoVRegs property.385auto &MRI = MF.getRegInfo();386MRI.createGenericVirtualRegister(LLT::scalar(8));387MF.getProperties().set(MachineFunctionProperties::Property::NoVRegs);388return PreservedAnalyses::all();389}390391static StringRef name() { return "TriggerVerifierErrorPass"; }392};393394// A pass requires all MachineFunctionProperties.395// DO NOT USE THIS EXCEPT FOR TESTING!396class RequireAllMachineFunctionPropertiesPass397: public PassInfoMixin<RequireAllMachineFunctionPropertiesPass> {398public:399PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &) {400MFPropsModifier _(*this, MF);401return PreservedAnalyses::none();402}403404static MachineFunctionProperties getRequiredProperties() {405MachineFunctionProperties MFProps;406MFProps.set(MachineFunctionProperties::Property::FailedISel);407MFProps.set(MachineFunctionProperties::Property::FailsVerification);408MFProps.set(MachineFunctionProperties::Property::IsSSA);409MFProps.set(MachineFunctionProperties::Property::Legalized);410MFProps.set(MachineFunctionProperties::Property::NoPHIs);411MFProps.set(MachineFunctionProperties::Property::NoVRegs);412MFProps.set(MachineFunctionProperties::Property::RegBankSelected);413MFProps.set(MachineFunctionProperties::Property::Selected);414MFProps.set(MachineFunctionProperties::Property::TiedOpsRewritten);415MFProps.set(MachineFunctionProperties::Property::TracksDebugUserValues);416MFProps.set(MachineFunctionProperties::Property::TracksLiveness);417return MFProps;418}419static StringRef name() { return "RequireAllMachineFunctionPropertiesPass"; }420};421422} // namespace423424PassBuilder::PassBuilder(TargetMachine *TM, PipelineTuningOptions PTO,425std::optional<PGOOptions> PGOOpt,426PassInstrumentationCallbacks *PIC)427: TM(TM), PTO(PTO), PGOOpt(PGOOpt), PIC(PIC) {428if (TM)429TM->registerPassBuilderCallbacks(*this);430if (PIC) {431PIC->registerClassToPassNameCallback([this, PIC]() {432// MSVC requires this to be captured if it's used inside decltype.433// Other compilers consider it an unused lambda capture.434(void)this;435#define MODULE_PASS(NAME, CREATE_PASS) \436PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME);437#define MODULE_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \438PIC->addClassToPassName(CLASS, NAME);439#define MODULE_ANALYSIS(NAME, CREATE_PASS) \440PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME);441#define FUNCTION_PASS(NAME, CREATE_PASS) \442PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME);443#define FUNCTION_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \444PIC->addClassToPassName(CLASS, NAME);445#define FUNCTION_ANALYSIS(NAME, CREATE_PASS) \446PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME);447#define LOOPNEST_PASS(NAME, CREATE_PASS) \448PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME);449#define LOOP_PASS(NAME, CREATE_PASS) \450PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME);451#define LOOP_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \452PIC->addClassToPassName(CLASS, NAME);453#define LOOP_ANALYSIS(NAME, CREATE_PASS) \454PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME);455#define CGSCC_PASS(NAME, CREATE_PASS) \456PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME);457#define CGSCC_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \458PIC->addClassToPassName(CLASS, NAME);459#define CGSCC_ANALYSIS(NAME, CREATE_PASS) \460PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME);461#include "PassRegistry.def"462463#define MACHINE_FUNCTION_ANALYSIS(NAME, CREATE_PASS) \464PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME);465#define MACHINE_FUNCTION_PASS(NAME, CREATE_PASS) \466PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME);467#include "llvm/Passes/MachinePassRegistry.def"468});469}470}471472void PassBuilder::registerModuleAnalyses(ModuleAnalysisManager &MAM) {473#define MODULE_ANALYSIS(NAME, CREATE_PASS) \474MAM.registerPass([&] { return CREATE_PASS; });475#include "PassRegistry.def"476477for (auto &C : ModuleAnalysisRegistrationCallbacks)478C(MAM);479}480481void PassBuilder::registerCGSCCAnalyses(CGSCCAnalysisManager &CGAM) {482#define CGSCC_ANALYSIS(NAME, CREATE_PASS) \483CGAM.registerPass([&] { return CREATE_PASS; });484#include "PassRegistry.def"485486for (auto &C : CGSCCAnalysisRegistrationCallbacks)487C(CGAM);488}489490void PassBuilder::registerFunctionAnalyses(FunctionAnalysisManager &FAM) {491// We almost always want the default alias analysis pipeline.492// If a user wants a different one, they can register their own before calling493// registerFunctionAnalyses().494FAM.registerPass([&] { return buildDefaultAAPipeline(); });495496#define FUNCTION_ANALYSIS(NAME, CREATE_PASS) \497FAM.registerPass([&] { return CREATE_PASS; });498#include "PassRegistry.def"499500for (auto &C : FunctionAnalysisRegistrationCallbacks)501C(FAM);502}503504void PassBuilder::registerMachineFunctionAnalyses(505MachineFunctionAnalysisManager &MFAM) {506507#define MACHINE_FUNCTION_ANALYSIS(NAME, CREATE_PASS) \508MFAM.registerPass([&] { return CREATE_PASS; });509#include "llvm/Passes/MachinePassRegistry.def"510511for (auto &C : MachineFunctionAnalysisRegistrationCallbacks)512C(MFAM);513}514515void PassBuilder::registerLoopAnalyses(LoopAnalysisManager &LAM) {516#define LOOP_ANALYSIS(NAME, CREATE_PASS) \517LAM.registerPass([&] { return CREATE_PASS; });518#include "PassRegistry.def"519520for (auto &C : LoopAnalysisRegistrationCallbacks)521C(LAM);522}523524static std::optional<std::pair<bool, bool>>525parseFunctionPipelineName(StringRef Name) {526std::pair<bool, bool> Params;527if (!Name.consume_front("function"))528return std::nullopt;529if (Name.empty())530return Params;531if (!Name.consume_front("<") || !Name.consume_back(">"))532return std::nullopt;533while (!Name.empty()) {534auto [Front, Back] = Name.split(';');535Name = Back;536if (Front == "eager-inv")537Params.first = true;538else if (Front == "no-rerun")539Params.second = true;540else541return std::nullopt;542}543return Params;544}545546static std::optional<int> parseDevirtPassName(StringRef Name) {547if (!Name.consume_front("devirt<") || !Name.consume_back(">"))548return std::nullopt;549int Count;550if (Name.getAsInteger(0, Count) || Count < 0)551return std::nullopt;552return Count;553}554555static std::optional<OptimizationLevel> parseOptLevel(StringRef S) {556return StringSwitch<std::optional<OptimizationLevel>>(S)557.Case("O0", OptimizationLevel::O0)558.Case("O1", OptimizationLevel::O1)559.Case("O2", OptimizationLevel::O2)560.Case("O3", OptimizationLevel::O3)561.Case("Os", OptimizationLevel::Os)562.Case("Oz", OptimizationLevel::Oz)563.Default(std::nullopt);564}565566Expected<bool> PassBuilder::parseSinglePassOption(StringRef Params,567StringRef OptionName,568StringRef PassName) {569bool Result = false;570while (!Params.empty()) {571StringRef ParamName;572std::tie(ParamName, Params) = Params.split(';');573574if (ParamName == OptionName) {575Result = true;576} else {577return make_error<StringError>(578formatv("invalid {1} pass parameter '{0}' ", ParamName, PassName)579.str(),580inconvertibleErrorCode());581}582}583return Result;584}585586namespace {587588/// Parser of parameters for HardwareLoops pass.589Expected<HardwareLoopOptions> parseHardwareLoopOptions(StringRef Params) {590HardwareLoopOptions HardwareLoopOpts;591592while (!Params.empty()) {593StringRef ParamName;594std::tie(ParamName, Params) = Params.split(';');595if (ParamName.consume_front("hardware-loop-decrement=")) {596int Count;597if (ParamName.getAsInteger(0, Count))598return make_error<StringError>(599formatv("invalid HardwareLoopPass parameter '{0}' ", ParamName).str(),600inconvertibleErrorCode());601HardwareLoopOpts.setDecrement(Count);602continue;603}604if (ParamName.consume_front("hardware-loop-counter-bitwidth=")) {605int Count;606if (ParamName.getAsInteger(0, Count))607return make_error<StringError>(608formatv("invalid HardwareLoopPass parameter '{0}' ", ParamName).str(),609inconvertibleErrorCode());610HardwareLoopOpts.setCounterBitwidth(Count);611continue;612}613if (ParamName == "force-hardware-loops") {614HardwareLoopOpts.setForce(true);615} else if (ParamName == "force-hardware-loop-phi") {616HardwareLoopOpts.setForcePhi(true);617} else if (ParamName == "force-nested-hardware-loop") {618HardwareLoopOpts.setForceNested(true);619} else if (ParamName == "force-hardware-loop-guard") {620HardwareLoopOpts.setForceGuard(true);621} else {622return make_error<StringError>(623formatv("invalid HardwarePass parameter '{0}' ", ParamName).str(),624inconvertibleErrorCode());625}626}627return HardwareLoopOpts;628}629630/// Parser of parameters for LoopUnroll pass.631Expected<LoopUnrollOptions> parseLoopUnrollOptions(StringRef Params) {632LoopUnrollOptions UnrollOpts;633while (!Params.empty()) {634StringRef ParamName;635std::tie(ParamName, Params) = Params.split(';');636std::optional<OptimizationLevel> OptLevel = parseOptLevel(ParamName);637// Don't accept -Os/-Oz.638if (OptLevel && !OptLevel->isOptimizingForSize()) {639UnrollOpts.setOptLevel(OptLevel->getSpeedupLevel());640continue;641}642if (ParamName.consume_front("full-unroll-max=")) {643int Count;644if (ParamName.getAsInteger(0, Count))645return make_error<StringError>(646formatv("invalid LoopUnrollPass parameter '{0}' ", ParamName).str(),647inconvertibleErrorCode());648UnrollOpts.setFullUnrollMaxCount(Count);649continue;650}651652bool Enable = !ParamName.consume_front("no-");653if (ParamName == "partial") {654UnrollOpts.setPartial(Enable);655} else if (ParamName == "peeling") {656UnrollOpts.setPeeling(Enable);657} else if (ParamName == "profile-peeling") {658UnrollOpts.setProfileBasedPeeling(Enable);659} else if (ParamName == "runtime") {660UnrollOpts.setRuntime(Enable);661} else if (ParamName == "upperbound") {662UnrollOpts.setUpperBound(Enable);663} else {664return make_error<StringError>(665formatv("invalid LoopUnrollPass parameter '{0}' ", ParamName).str(),666inconvertibleErrorCode());667}668}669return UnrollOpts;670}671672Expected<bool> parseGlobalDCEPassOptions(StringRef Params) {673return PassBuilder::parseSinglePassOption(674Params, "vfe-linkage-unit-visibility", "GlobalDCE");675}676677Expected<bool> parseCGProfilePassOptions(StringRef Params) {678return PassBuilder::parseSinglePassOption(Params, "in-lto-post-link",679"CGProfile");680}681682Expected<bool> parseInlinerPassOptions(StringRef Params) {683return PassBuilder::parseSinglePassOption(Params, "only-mandatory",684"InlinerPass");685}686687Expected<bool> parseCoroSplitPassOptions(StringRef Params) {688return PassBuilder::parseSinglePassOption(Params, "reuse-storage",689"CoroSplitPass");690}691692Expected<bool> parsePostOrderFunctionAttrsPassOptions(StringRef Params) {693return PassBuilder::parseSinglePassOption(694Params, "skip-non-recursive-function-attrs", "PostOrderFunctionAttrs");695}696697Expected<CFGuardPass::Mechanism> parseCFGuardPassOptions(StringRef Params) {698if (Params.empty())699return CFGuardPass::Mechanism::Check;700701auto [Param, RHS] = Params.split(';');702if (!RHS.empty())703return make_error<StringError>(704formatv("too many CFGuardPass parameters '{0}' ", Params).str(),705inconvertibleErrorCode());706707if (Param == "check")708return CFGuardPass::Mechanism::Check;709if (Param == "dispatch")710return CFGuardPass::Mechanism::Dispatch;711712return make_error<StringError>(713formatv("invalid CFGuardPass mechanism: '{0}' ", Param).str(),714inconvertibleErrorCode());715}716717Expected<bool> parseEarlyCSEPassOptions(StringRef Params) {718return PassBuilder::parseSinglePassOption(Params, "memssa", "EarlyCSE");719}720721Expected<bool> parseEntryExitInstrumenterPassOptions(StringRef Params) {722return PassBuilder::parseSinglePassOption(Params, "post-inline",723"EntryExitInstrumenter");724}725726Expected<bool> parseLoopExtractorPassOptions(StringRef Params) {727return PassBuilder::parseSinglePassOption(Params, "single", "LoopExtractor");728}729730Expected<bool> parseLowerMatrixIntrinsicsPassOptions(StringRef Params) {731return PassBuilder::parseSinglePassOption(Params, "minimal",732"LowerMatrixIntrinsics");733}734735Expected<AddressSanitizerOptions> parseASanPassOptions(StringRef Params) {736AddressSanitizerOptions Result;737while (!Params.empty()) {738StringRef ParamName;739std::tie(ParamName, Params) = Params.split(';');740741if (ParamName == "kernel") {742Result.CompileKernel = true;743} else {744return make_error<StringError>(745formatv("invalid AddressSanitizer pass parameter '{0}' ", ParamName)746.str(),747inconvertibleErrorCode());748}749}750return Result;751}752753Expected<HWAddressSanitizerOptions> parseHWASanPassOptions(StringRef Params) {754HWAddressSanitizerOptions Result;755while (!Params.empty()) {756StringRef ParamName;757std::tie(ParamName, Params) = Params.split(';');758759if (ParamName == "recover") {760Result.Recover = true;761} else if (ParamName == "kernel") {762Result.CompileKernel = true;763} else {764return make_error<StringError>(765formatv("invalid HWAddressSanitizer pass parameter '{0}' ", ParamName)766.str(),767inconvertibleErrorCode());768}769}770return Result;771}772773Expected<EmbedBitcodeOptions> parseEmbedBitcodePassOptions(StringRef Params) {774EmbedBitcodeOptions Result;775while (!Params.empty()) {776StringRef ParamName;777std::tie(ParamName, Params) = Params.split(';');778779if (ParamName == "thinlto") {780Result.IsThinLTO = true;781} else if (ParamName == "emit-summary") {782Result.EmitLTOSummary = true;783} else {784return make_error<StringError>(785formatv("invalid EmbedBitcode pass parameter '{0}' ", ParamName)786.str(),787inconvertibleErrorCode());788}789}790return Result;791}792793Expected<MemorySanitizerOptions> parseMSanPassOptions(StringRef Params) {794MemorySanitizerOptions Result;795while (!Params.empty()) {796StringRef ParamName;797std::tie(ParamName, Params) = Params.split(';');798799if (ParamName == "recover") {800Result.Recover = true;801} else if (ParamName == "kernel") {802Result.Kernel = true;803} else if (ParamName.consume_front("track-origins=")) {804if (ParamName.getAsInteger(0, Result.TrackOrigins))805return make_error<StringError>(806formatv("invalid argument to MemorySanitizer pass track-origins "807"parameter: '{0}' ",808ParamName)809.str(),810inconvertibleErrorCode());811} else if (ParamName == "eager-checks") {812Result.EagerChecks = true;813} else {814return make_error<StringError>(815formatv("invalid MemorySanitizer pass parameter '{0}' ", ParamName)816.str(),817inconvertibleErrorCode());818}819}820return Result;821}822823/// Parser of parameters for SimplifyCFG pass.824Expected<SimplifyCFGOptions> parseSimplifyCFGOptions(StringRef Params) {825SimplifyCFGOptions Result;826while (!Params.empty()) {827StringRef ParamName;828std::tie(ParamName, Params) = Params.split(';');829830bool Enable = !ParamName.consume_front("no-");831if (ParamName == "speculate-blocks") {832Result.speculateBlocks(Enable);833} else if (ParamName == "simplify-cond-branch") {834Result.setSimplifyCondBranch(Enable);835} else if (ParamName == "forward-switch-cond") {836Result.forwardSwitchCondToPhi(Enable);837} else if (ParamName == "switch-range-to-icmp") {838Result.convertSwitchRangeToICmp(Enable);839} else if (ParamName == "switch-to-lookup") {840Result.convertSwitchToLookupTable(Enable);841} else if (ParamName == "keep-loops") {842Result.needCanonicalLoops(Enable);843} else if (ParamName == "hoist-common-insts") {844Result.hoistCommonInsts(Enable);845} else if (ParamName == "sink-common-insts") {846Result.sinkCommonInsts(Enable);847} else if (ParamName == "speculate-unpredictables") {848Result.speculateUnpredictables(Enable);849} else if (Enable && ParamName.consume_front("bonus-inst-threshold=")) {850APInt BonusInstThreshold;851if (ParamName.getAsInteger(0, BonusInstThreshold))852return make_error<StringError>(853formatv("invalid argument to SimplifyCFG pass bonus-threshold "854"parameter: '{0}' ",855ParamName).str(),856inconvertibleErrorCode());857Result.bonusInstThreshold(BonusInstThreshold.getSExtValue());858} else {859return make_error<StringError>(860formatv("invalid SimplifyCFG pass parameter '{0}' ", ParamName).str(),861inconvertibleErrorCode());862}863}864return Result;865}866867Expected<InstCombineOptions> parseInstCombineOptions(StringRef Params) {868InstCombineOptions Result;869// When specifying "instcombine" in -passes enable fix-point verification by870// default, as this is what most tests should use.871Result.setVerifyFixpoint(true);872while (!Params.empty()) {873StringRef ParamName;874std::tie(ParamName, Params) = Params.split(';');875876bool Enable = !ParamName.consume_front("no-");877if (ParamName == "use-loop-info") {878Result.setUseLoopInfo(Enable);879} else if (ParamName == "verify-fixpoint") {880Result.setVerifyFixpoint(Enable);881} else if (Enable && ParamName.consume_front("max-iterations=")) {882APInt MaxIterations;883if (ParamName.getAsInteger(0, MaxIterations))884return make_error<StringError>(885formatv("invalid argument to InstCombine pass max-iterations "886"parameter: '{0}' ",887ParamName).str(),888inconvertibleErrorCode());889Result.setMaxIterations((unsigned)MaxIterations.getZExtValue());890} else {891return make_error<StringError>(892formatv("invalid InstCombine pass parameter '{0}' ", ParamName).str(),893inconvertibleErrorCode());894}895}896return Result;897}898899/// Parser of parameters for LoopVectorize pass.900Expected<LoopVectorizeOptions> parseLoopVectorizeOptions(StringRef Params) {901LoopVectorizeOptions Opts;902while (!Params.empty()) {903StringRef ParamName;904std::tie(ParamName, Params) = Params.split(';');905906bool Enable = !ParamName.consume_front("no-");907if (ParamName == "interleave-forced-only") {908Opts.setInterleaveOnlyWhenForced(Enable);909} else if (ParamName == "vectorize-forced-only") {910Opts.setVectorizeOnlyWhenForced(Enable);911} else {912return make_error<StringError>(913formatv("invalid LoopVectorize parameter '{0}' ", ParamName).str(),914inconvertibleErrorCode());915}916}917return Opts;918}919920Expected<std::pair<bool, bool>> parseLoopUnswitchOptions(StringRef Params) {921std::pair<bool, bool> Result = {false, true};922while (!Params.empty()) {923StringRef ParamName;924std::tie(ParamName, Params) = Params.split(';');925926bool Enable = !ParamName.consume_front("no-");927if (ParamName == "nontrivial") {928Result.first = Enable;929} else if (ParamName == "trivial") {930Result.second = Enable;931} else {932return make_error<StringError>(933formatv("invalid LoopUnswitch pass parameter '{0}' ", ParamName)934.str(),935inconvertibleErrorCode());936}937}938return Result;939}940941Expected<LICMOptions> parseLICMOptions(StringRef Params) {942LICMOptions Result;943while (!Params.empty()) {944StringRef ParamName;945std::tie(ParamName, Params) = Params.split(';');946947bool Enable = !ParamName.consume_front("no-");948if (ParamName == "allowspeculation") {949Result.AllowSpeculation = Enable;950} else {951return make_error<StringError>(952formatv("invalid LICM pass parameter '{0}' ", ParamName).str(),953inconvertibleErrorCode());954}955}956return Result;957}958959Expected<std::pair<bool, bool>> parseLoopRotateOptions(StringRef Params) {960std::pair<bool, bool> Result = {true, false};961while (!Params.empty()) {962StringRef ParamName;963std::tie(ParamName, Params) = Params.split(';');964965bool Enable = !ParamName.consume_front("no-");966if (ParamName == "header-duplication") {967Result.first = Enable;968} else if (ParamName == "prepare-for-lto") {969Result.second = Enable;970} else {971return make_error<StringError>(972formatv("invalid LoopRotate pass parameter '{0}' ", ParamName).str(),973inconvertibleErrorCode());974}975}976return Result;977}978979Expected<bool> parseMergedLoadStoreMotionOptions(StringRef Params) {980bool Result = false;981while (!Params.empty()) {982StringRef ParamName;983std::tie(ParamName, Params) = Params.split(';');984985bool Enable = !ParamName.consume_front("no-");986if (ParamName == "split-footer-bb") {987Result = Enable;988} else {989return make_error<StringError>(990formatv("invalid MergedLoadStoreMotion pass parameter '{0}' ",991ParamName)992.str(),993inconvertibleErrorCode());994}995}996return Result;997}998999Expected<GVNOptions> parseGVNOptions(StringRef Params) {1000GVNOptions Result;1001while (!Params.empty()) {1002StringRef ParamName;1003std::tie(ParamName, Params) = Params.split(';');10041005bool Enable = !ParamName.consume_front("no-");1006if (ParamName == "pre") {1007Result.setPRE(Enable);1008} else if (ParamName == "load-pre") {1009Result.setLoadPRE(Enable);1010} else if (ParamName == "split-backedge-load-pre") {1011Result.setLoadPRESplitBackedge(Enable);1012} else if (ParamName == "memdep") {1013Result.setMemDep(Enable);1014} else {1015return make_error<StringError>(1016formatv("invalid GVN pass parameter '{0}' ", ParamName).str(),1017inconvertibleErrorCode());1018}1019}1020return Result;1021}10221023Expected<IPSCCPOptions> parseIPSCCPOptions(StringRef Params) {1024IPSCCPOptions Result;1025while (!Params.empty()) {1026StringRef ParamName;1027std::tie(ParamName, Params) = Params.split(';');10281029bool Enable = !ParamName.consume_front("no-");1030if (ParamName == "func-spec")1031Result.setFuncSpec(Enable);1032else1033return make_error<StringError>(1034formatv("invalid IPSCCP pass parameter '{0}' ", ParamName).str(),1035inconvertibleErrorCode());1036}1037return Result;1038}10391040Expected<SROAOptions> parseSROAOptions(StringRef Params) {1041if (Params.empty() || Params == "modify-cfg")1042return SROAOptions::ModifyCFG;1043if (Params == "preserve-cfg")1044return SROAOptions::PreserveCFG;1045return make_error<StringError>(1046formatv("invalid SROA pass parameter '{0}' (either preserve-cfg or "1047"modify-cfg can be specified)",1048Params)1049.str(),1050inconvertibleErrorCode());1051}10521053Expected<StackLifetime::LivenessType>1054parseStackLifetimeOptions(StringRef Params) {1055StackLifetime::LivenessType Result = StackLifetime::LivenessType::May;1056while (!Params.empty()) {1057StringRef ParamName;1058std::tie(ParamName, Params) = Params.split(';');10591060if (ParamName == "may") {1061Result = StackLifetime::LivenessType::May;1062} else if (ParamName == "must") {1063Result = StackLifetime::LivenessType::Must;1064} else {1065return make_error<StringError>(1066formatv("invalid StackLifetime parameter '{0}' ", ParamName).str(),1067inconvertibleErrorCode());1068}1069}1070return Result;1071}10721073Expected<bool> parseDependenceAnalysisPrinterOptions(StringRef Params) {1074return PassBuilder::parseSinglePassOption(Params, "normalized-results",1075"DependenceAnalysisPrinter");1076}10771078Expected<bool> parseSeparateConstOffsetFromGEPPassOptions(StringRef Params) {1079return PassBuilder::parseSinglePassOption(Params, "lower-gep",1080"SeparateConstOffsetFromGEP");1081}10821083Expected<OptimizationLevel>1084parseFunctionSimplificationPipelineOptions(StringRef Params) {1085std::optional<OptimizationLevel> L = parseOptLevel(Params);1086if (!L || *L == OptimizationLevel::O0) {1087return make_error<StringError>(1088formatv("invalid function-simplification parameter '{0}' ", Params)1089.str(),1090inconvertibleErrorCode());1091};1092return *L;1093}10941095Expected<bool> parseMemorySSAPrinterPassOptions(StringRef Params) {1096return PassBuilder::parseSinglePassOption(Params, "no-ensure-optimized-uses",1097"MemorySSAPrinterPass");1098}10991100Expected<bool> parseSpeculativeExecutionPassOptions(StringRef Params) {1101return PassBuilder::parseSinglePassOption(Params, "only-if-divergent-target",1102"SpeculativeExecutionPass");1103}11041105Expected<std::string> parseMemProfUsePassOptions(StringRef Params) {1106std::string Result;1107while (!Params.empty()) {1108StringRef ParamName;1109std::tie(ParamName, Params) = Params.split(';');11101111if (ParamName.consume_front("profile-filename=")) {1112Result = ParamName.str();1113} else {1114return make_error<StringError>(1115formatv("invalid MemProfUse pass parameter '{0}' ", ParamName).str(),1116inconvertibleErrorCode());1117}1118}1119return Result;1120}11211122Expected<bool> parseStructuralHashPrinterPassOptions(StringRef Params) {1123return PassBuilder::parseSinglePassOption(Params, "detailed",1124"StructuralHashPrinterPass");1125}11261127Expected<bool> parseWinEHPrepareOptions(StringRef Params) {1128return PassBuilder::parseSinglePassOption(Params, "demote-catchswitch-only",1129"WinEHPreparePass");1130}11311132Expected<GlobalMergeOptions> parseGlobalMergeOptions(StringRef Params) {1133GlobalMergeOptions Result;1134while (!Params.empty()) {1135StringRef ParamName;1136std::tie(ParamName, Params) = Params.split(';');11371138bool Enable = !ParamName.consume_front("no-");1139if (ParamName == "group-by-use")1140Result.GroupByUse = Enable;1141else if (ParamName == "ignore-single-use")1142Result.IgnoreSingleUse = Enable;1143else if (ParamName == "merge-const")1144Result.MergeConst = Enable;1145else if (ParamName == "merge-external")1146Result.MergeExternal = Enable;1147else if (ParamName.consume_front("max-offset=")) {1148if (ParamName.getAsInteger(0, Result.MaxOffset))1149return make_error<StringError>(1150formatv("invalid GlobalMergePass parameter '{0}' ", ParamName)1151.str(),1152inconvertibleErrorCode());1153}1154}1155return Result;1156}11571158Expected<SmallVector<std::string, 0>> parseInternalizeGVs(StringRef Params) {1159SmallVector<std::string, 1> PreservedGVs;1160while (!Params.empty()) {1161StringRef ParamName;1162std::tie(ParamName, Params) = Params.split(';');11631164if (ParamName.consume_front("preserve-gv=")) {1165PreservedGVs.push_back(ParamName.str());1166} else {1167return make_error<StringError>(1168formatv("invalid Internalize pass parameter '{0}' ", ParamName).str(),1169inconvertibleErrorCode());1170}1171}11721173return Expected<SmallVector<std::string, 0>>(std::move(PreservedGVs));1174}11751176Expected<RegAllocFastPassOptions>1177parseRegAllocFastPassOptions(PassBuilder &PB, StringRef Params) {1178RegAllocFastPassOptions Opts;1179while (!Params.empty()) {1180StringRef ParamName;1181std::tie(ParamName, Params) = Params.split(';');11821183if (ParamName.consume_front("filter=")) {1184std::optional<RegAllocFilterFunc> Filter =1185PB.parseRegAllocFilter(ParamName);1186if (!Filter) {1187return make_error<StringError>(1188formatv("invalid regallocfast register filter '{0}' ", ParamName)1189.str(),1190inconvertibleErrorCode());1191}1192Opts.Filter = *Filter;1193Opts.FilterName = ParamName;1194continue;1195}11961197if (ParamName == "no-clear-vregs") {1198Opts.ClearVRegs = false;1199continue;1200}12011202return make_error<StringError>(1203formatv("invalid regallocfast pass parameter '{0}' ", ParamName).str(),1204inconvertibleErrorCode());1205}1206return Opts;1207}12081209} // namespace12101211/// Tests whether a pass name starts with a valid prefix for a default pipeline1212/// alias.1213static bool startsWithDefaultPipelineAliasPrefix(StringRef Name) {1214return Name.starts_with("default") || Name.starts_with("thinlto") ||1215Name.starts_with("lto");1216}12171218/// Tests whether registered callbacks will accept a given pass name.1219///1220/// When parsing a pipeline text, the type of the outermost pipeline may be1221/// omitted, in which case the type is automatically determined from the first1222/// pass name in the text. This may be a name that is handled through one of the1223/// callbacks. We check this through the oridinary parsing callbacks by setting1224/// up a dummy PassManager in order to not force the client to also handle this1225/// type of query.1226template <typename PassManagerT, typename CallbacksT>1227static bool callbacksAcceptPassName(StringRef Name, CallbacksT &Callbacks) {1228if (!Callbacks.empty()) {1229PassManagerT DummyPM;1230for (auto &CB : Callbacks)1231if (CB(Name, DummyPM, {}))1232return true;1233}1234return false;1235}12361237template <typename CallbacksT>1238static bool isModulePassName(StringRef Name, CallbacksT &Callbacks) {1239// Manually handle aliases for pre-configured pipeline fragments.1240if (startsWithDefaultPipelineAliasPrefix(Name))1241return DefaultAliasRegex.match(Name);12421243StringRef NameNoBracket = Name.take_until([](char C) { return C == '<'; });12441245// Explicitly handle pass manager names.1246if (Name == "module")1247return true;1248if (Name == "cgscc")1249return true;1250if (NameNoBracket == "function")1251return true;1252if (Name == "coro-cond")1253return true;12541255#define MODULE_PASS(NAME, CREATE_PASS) \1256if (Name == NAME) \1257return true;1258#define MODULE_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \1259if (PassBuilder::checkParametrizedPassName(Name, NAME)) \1260return true;1261#define MODULE_ANALYSIS(NAME, CREATE_PASS) \1262if (Name == "require<" NAME ">" || Name == "invalidate<" NAME ">") \1263return true;1264#include "PassRegistry.def"12651266return callbacksAcceptPassName<ModulePassManager>(Name, Callbacks);1267}12681269template <typename CallbacksT>1270static bool isCGSCCPassName(StringRef Name, CallbacksT &Callbacks) {1271// Explicitly handle pass manager names.1272StringRef NameNoBracket = Name.take_until([](char C) { return C == '<'; });1273if (Name == "cgscc")1274return true;1275if (NameNoBracket == "function")1276return true;12771278// Explicitly handle custom-parsed pass names.1279if (parseDevirtPassName(Name))1280return true;12811282#define CGSCC_PASS(NAME, CREATE_PASS) \1283if (Name == NAME) \1284return true;1285#define CGSCC_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \1286if (PassBuilder::checkParametrizedPassName(Name, NAME)) \1287return true;1288#define CGSCC_ANALYSIS(NAME, CREATE_PASS) \1289if (Name == "require<" NAME ">" || Name == "invalidate<" NAME ">") \1290return true;1291#include "PassRegistry.def"12921293return callbacksAcceptPassName<CGSCCPassManager>(Name, Callbacks);1294}12951296template <typename CallbacksT>1297static bool isFunctionPassName(StringRef Name, CallbacksT &Callbacks) {1298// Explicitly handle pass manager names.1299StringRef NameNoBracket = Name.take_until([](char C) { return C == '<'; });1300if (NameNoBracket == "function")1301return true;1302if (Name == "loop" || Name == "loop-mssa" || Name == "machine-function")1303return true;13041305#define FUNCTION_PASS(NAME, CREATE_PASS) \1306if (Name == NAME) \1307return true;1308#define FUNCTION_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \1309if (PassBuilder::checkParametrizedPassName(Name, NAME)) \1310return true;1311#define FUNCTION_ANALYSIS(NAME, CREATE_PASS) \1312if (Name == "require<" NAME ">" || Name == "invalidate<" NAME ">") \1313return true;1314#include "PassRegistry.def"13151316return callbacksAcceptPassName<FunctionPassManager>(Name, Callbacks);1317}13181319template <typename CallbacksT>1320static bool isMachineFunctionPassName(StringRef Name, CallbacksT &Callbacks) {1321// Explicitly handle pass manager names.1322if (Name == "machine-function")1323return true;13241325#define MACHINE_FUNCTION_PASS(NAME, CREATE_PASS) \1326if (Name == NAME) \1327return true;1328#define MACHINE_FUNCTION_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, \1329PARAMS) \1330if (PassBuilder::checkParametrizedPassName(Name, NAME)) \1331return true;13321333#define MACHINE_FUNCTION_ANALYSIS(NAME, CREATE_PASS) \1334if (Name == "require<" NAME ">" || Name == "invalidate<" NAME ">") \1335return true;13361337#include "llvm/Passes/MachinePassRegistry.def"13381339return callbacksAcceptPassName<MachineFunctionPassManager>(Name, Callbacks);1340}13411342template <typename CallbacksT>1343static bool isLoopNestPassName(StringRef Name, CallbacksT &Callbacks,1344bool &UseMemorySSA) {1345UseMemorySSA = false;13461347if (PassBuilder::checkParametrizedPassName(Name, "lnicm")) {1348UseMemorySSA = true;1349return true;1350}13511352#define LOOPNEST_PASS(NAME, CREATE_PASS) \1353if (Name == NAME) \1354return true;1355#include "PassRegistry.def"13561357return callbacksAcceptPassName<LoopPassManager>(Name, Callbacks);1358}13591360template <typename CallbacksT>1361static bool isLoopPassName(StringRef Name, CallbacksT &Callbacks,1362bool &UseMemorySSA) {1363UseMemorySSA = false;13641365if (PassBuilder::checkParametrizedPassName(Name, "licm")) {1366UseMemorySSA = true;1367return true;1368}13691370#define LOOP_PASS(NAME, CREATE_PASS) \1371if (Name == NAME) \1372return true;1373#define LOOP_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \1374if (PassBuilder::checkParametrizedPassName(Name, NAME)) \1375return true;1376#define LOOP_ANALYSIS(NAME, CREATE_PASS) \1377if (Name == "require<" NAME ">" || Name == "invalidate<" NAME ">") \1378return true;1379#include "PassRegistry.def"13801381return callbacksAcceptPassName<LoopPassManager>(Name, Callbacks);1382}13831384std::optional<std::vector<PassBuilder::PipelineElement>>1385PassBuilder::parsePipelineText(StringRef Text) {1386std::vector<PipelineElement> ResultPipeline;13871388SmallVector<std::vector<PipelineElement> *, 4> PipelineStack = {1389&ResultPipeline};1390for (;;) {1391std::vector<PipelineElement> &Pipeline = *PipelineStack.back();1392size_t Pos = Text.find_first_of(",()");1393Pipeline.push_back({Text.substr(0, Pos), {}});13941395// If we have a single terminating name, we're done.1396if (Pos == Text.npos)1397break;13981399char Sep = Text[Pos];1400Text = Text.substr(Pos + 1);1401if (Sep == ',')1402// Just a name ending in a comma, continue.1403continue;14041405if (Sep == '(') {1406// Push the inner pipeline onto the stack to continue processing.1407PipelineStack.push_back(&Pipeline.back().InnerPipeline);1408continue;1409}14101411assert(Sep == ')' && "Bogus separator!");1412// When handling the close parenthesis, we greedily consume them to avoid1413// empty strings in the pipeline.1414do {1415// If we try to pop the outer pipeline we have unbalanced parentheses.1416if (PipelineStack.size() == 1)1417return std::nullopt;14181419PipelineStack.pop_back();1420} while (Text.consume_front(")"));14211422// Check if we've finished parsing.1423if (Text.empty())1424break;14251426// Otherwise, the end of an inner pipeline always has to be followed by1427// a comma, and then we can continue.1428if (!Text.consume_front(","))1429return std::nullopt;1430}14311432if (PipelineStack.size() > 1)1433// Unbalanced paretheses.1434return std::nullopt;14351436assert(PipelineStack.back() == &ResultPipeline &&1437"Wrong pipeline at the bottom of the stack!");1438return {std::move(ResultPipeline)};1439}14401441Error PassBuilder::parseModulePass(ModulePassManager &MPM,1442const PipelineElement &E) {1443auto &Name = E.Name;1444auto &InnerPipeline = E.InnerPipeline;14451446// First handle complex passes like the pass managers which carry pipelines.1447if (!InnerPipeline.empty()) {1448if (Name == "module") {1449ModulePassManager NestedMPM;1450if (auto Err = parseModulePassPipeline(NestedMPM, InnerPipeline))1451return Err;1452MPM.addPass(std::move(NestedMPM));1453return Error::success();1454}1455if (Name == "coro-cond") {1456ModulePassManager NestedMPM;1457if (auto Err = parseModulePassPipeline(NestedMPM, InnerPipeline))1458return Err;1459MPM.addPass(CoroConditionalWrapper(std::move(NestedMPM)));1460return Error::success();1461}1462if (Name == "cgscc") {1463CGSCCPassManager CGPM;1464if (auto Err = parseCGSCCPassPipeline(CGPM, InnerPipeline))1465return Err;1466MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));1467return Error::success();1468}1469if (auto Params = parseFunctionPipelineName(Name)) {1470if (Params->second)1471return make_error<StringError>(1472"cannot have a no-rerun module to function adaptor",1473inconvertibleErrorCode());1474FunctionPassManager FPM;1475if (auto Err = parseFunctionPassPipeline(FPM, InnerPipeline))1476return Err;1477MPM.addPass(1478createModuleToFunctionPassAdaptor(std::move(FPM), Params->first));1479return Error::success();1480}14811482for (auto &C : ModulePipelineParsingCallbacks)1483if (C(Name, MPM, InnerPipeline))1484return Error::success();14851486// Normal passes can't have pipelines.1487return make_error<StringError>(1488formatv("invalid use of '{0}' pass as module pipeline", Name).str(),1489inconvertibleErrorCode());1490;1491}14921493// Manually handle aliases for pre-configured pipeline fragments.1494if (startsWithDefaultPipelineAliasPrefix(Name)) {1495SmallVector<StringRef, 3> Matches;1496if (!DefaultAliasRegex.match(Name, &Matches))1497return make_error<StringError>(1498formatv("unknown default pipeline alias '{0}'", Name).str(),1499inconvertibleErrorCode());15001501assert(Matches.size() == 3 && "Must capture two matched strings!");15021503OptimizationLevel L = *parseOptLevel(Matches[2]);15041505// This is consistent with old pass manager invoked via opt, but1506// inconsistent with clang. Clang doesn't enable loop vectorization1507// but does enable slp vectorization at Oz.1508PTO.LoopVectorization =1509L.getSpeedupLevel() > 1 && L != OptimizationLevel::Oz;1510PTO.SLPVectorization =1511L.getSpeedupLevel() > 1 && L != OptimizationLevel::Oz;15121513if (Matches[1] == "default") {1514MPM.addPass(buildPerModuleDefaultPipeline(L));1515} else if (Matches[1] == "thinlto-pre-link") {1516MPM.addPass(buildThinLTOPreLinkDefaultPipeline(L));1517} else if (Matches[1] == "thinlto") {1518MPM.addPass(buildThinLTODefaultPipeline(L, nullptr));1519} else if (Matches[1] == "lto-pre-link") {1520if (PTO.UnifiedLTO)1521// When UnifiedLTO is enabled, use the ThinLTO pre-link pipeline. This1522// avoids compile-time performance regressions and keeps the pre-link1523// LTO pipeline "unified" for both LTO modes.1524MPM.addPass(buildThinLTOPreLinkDefaultPipeline(L));1525else1526MPM.addPass(buildLTOPreLinkDefaultPipeline(L));1527} else {1528assert(Matches[1] == "lto" && "Not one of the matched options!");1529MPM.addPass(buildLTODefaultPipeline(L, nullptr));1530}1531return Error::success();1532}15331534// Finally expand the basic registered passes from the .inc file.1535#define MODULE_PASS(NAME, CREATE_PASS) \1536if (Name == NAME) { \1537MPM.addPass(CREATE_PASS); \1538return Error::success(); \1539}1540#define MODULE_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \1541if (checkParametrizedPassName(Name, NAME)) { \1542auto Params = parsePassParameters(PARSER, Name, NAME); \1543if (!Params) \1544return Params.takeError(); \1545MPM.addPass(CREATE_PASS(Params.get())); \1546return Error::success(); \1547}1548#define MODULE_ANALYSIS(NAME, CREATE_PASS) \1549if (Name == "require<" NAME ">") { \1550MPM.addPass( \1551RequireAnalysisPass< \1552std::remove_reference_t<decltype(CREATE_PASS)>, Module>()); \1553return Error::success(); \1554} \1555if (Name == "invalidate<" NAME ">") { \1556MPM.addPass(InvalidateAnalysisPass< \1557std::remove_reference_t<decltype(CREATE_PASS)>>()); \1558return Error::success(); \1559}1560#define CGSCC_PASS(NAME, CREATE_PASS) \1561if (Name == NAME) { \1562MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(CREATE_PASS)); \1563return Error::success(); \1564}1565#define CGSCC_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \1566if (checkParametrizedPassName(Name, NAME)) { \1567auto Params = parsePassParameters(PARSER, Name, NAME); \1568if (!Params) \1569return Params.takeError(); \1570MPM.addPass( \1571createModuleToPostOrderCGSCCPassAdaptor(CREATE_PASS(Params.get()))); \1572return Error::success(); \1573}1574#define FUNCTION_PASS(NAME, CREATE_PASS) \1575if (Name == NAME) { \1576MPM.addPass(createModuleToFunctionPassAdaptor(CREATE_PASS)); \1577return Error::success(); \1578}1579#define FUNCTION_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \1580if (checkParametrizedPassName(Name, NAME)) { \1581auto Params = parsePassParameters(PARSER, Name, NAME); \1582if (!Params) \1583return Params.takeError(); \1584MPM.addPass(createModuleToFunctionPassAdaptor(CREATE_PASS(Params.get()))); \1585return Error::success(); \1586}1587#define LOOPNEST_PASS(NAME, CREATE_PASS) \1588if (Name == NAME) { \1589MPM.addPass(createModuleToFunctionPassAdaptor( \1590createFunctionToLoopPassAdaptor(CREATE_PASS, false, false))); \1591return Error::success(); \1592}1593#define LOOP_PASS(NAME, CREATE_PASS) \1594if (Name == NAME) { \1595MPM.addPass(createModuleToFunctionPassAdaptor( \1596createFunctionToLoopPassAdaptor(CREATE_PASS, false, false))); \1597return Error::success(); \1598}1599#define LOOP_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \1600if (checkParametrizedPassName(Name, NAME)) { \1601auto Params = parsePassParameters(PARSER, Name, NAME); \1602if (!Params) \1603return Params.takeError(); \1604MPM.addPass( \1605createModuleToFunctionPassAdaptor(createFunctionToLoopPassAdaptor( \1606CREATE_PASS(Params.get()), false, false))); \1607return Error::success(); \1608}1609#include "PassRegistry.def"16101611for (auto &C : ModulePipelineParsingCallbacks)1612if (C(Name, MPM, InnerPipeline))1613return Error::success();1614return make_error<StringError>(1615formatv("unknown module pass '{0}'", Name).str(),1616inconvertibleErrorCode());1617}16181619Error PassBuilder::parseCGSCCPass(CGSCCPassManager &CGPM,1620const PipelineElement &E) {1621auto &Name = E.Name;1622auto &InnerPipeline = E.InnerPipeline;16231624// First handle complex passes like the pass managers which carry pipelines.1625if (!InnerPipeline.empty()) {1626if (Name == "cgscc") {1627CGSCCPassManager NestedCGPM;1628if (auto Err = parseCGSCCPassPipeline(NestedCGPM, InnerPipeline))1629return Err;1630// Add the nested pass manager with the appropriate adaptor.1631CGPM.addPass(std::move(NestedCGPM));1632return Error::success();1633}1634if (auto Params = parseFunctionPipelineName(Name)) {1635FunctionPassManager FPM;1636if (auto Err = parseFunctionPassPipeline(FPM, InnerPipeline))1637return Err;1638// Add the nested pass manager with the appropriate adaptor.1639CGPM.addPass(createCGSCCToFunctionPassAdaptor(1640std::move(FPM), Params->first, Params->second));1641return Error::success();1642}1643if (auto MaxRepetitions = parseDevirtPassName(Name)) {1644CGSCCPassManager NestedCGPM;1645if (auto Err = parseCGSCCPassPipeline(NestedCGPM, InnerPipeline))1646return Err;1647CGPM.addPass(1648createDevirtSCCRepeatedPass(std::move(NestedCGPM), *MaxRepetitions));1649return Error::success();1650}16511652for (auto &C : CGSCCPipelineParsingCallbacks)1653if (C(Name, CGPM, InnerPipeline))1654return Error::success();16551656// Normal passes can't have pipelines.1657return make_error<StringError>(1658formatv("invalid use of '{0}' pass as cgscc pipeline", Name).str(),1659inconvertibleErrorCode());1660}16611662// Now expand the basic registered passes from the .inc file.1663#define CGSCC_PASS(NAME, CREATE_PASS) \1664if (Name == NAME) { \1665CGPM.addPass(CREATE_PASS); \1666return Error::success(); \1667}1668#define CGSCC_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \1669if (checkParametrizedPassName(Name, NAME)) { \1670auto Params = parsePassParameters(PARSER, Name, NAME); \1671if (!Params) \1672return Params.takeError(); \1673CGPM.addPass(CREATE_PASS(Params.get())); \1674return Error::success(); \1675}1676#define CGSCC_ANALYSIS(NAME, CREATE_PASS) \1677if (Name == "require<" NAME ">") { \1678CGPM.addPass(RequireAnalysisPass< \1679std::remove_reference_t<decltype(CREATE_PASS)>, \1680LazyCallGraph::SCC, CGSCCAnalysisManager, LazyCallGraph &, \1681CGSCCUpdateResult &>()); \1682return Error::success(); \1683} \1684if (Name == "invalidate<" NAME ">") { \1685CGPM.addPass(InvalidateAnalysisPass< \1686std::remove_reference_t<decltype(CREATE_PASS)>>()); \1687return Error::success(); \1688}1689#define FUNCTION_PASS(NAME, CREATE_PASS) \1690if (Name == NAME) { \1691CGPM.addPass(createCGSCCToFunctionPassAdaptor(CREATE_PASS)); \1692return Error::success(); \1693}1694#define FUNCTION_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \1695if (checkParametrizedPassName(Name, NAME)) { \1696auto Params = parsePassParameters(PARSER, Name, NAME); \1697if (!Params) \1698return Params.takeError(); \1699CGPM.addPass(createCGSCCToFunctionPassAdaptor(CREATE_PASS(Params.get()))); \1700return Error::success(); \1701}1702#define LOOPNEST_PASS(NAME, CREATE_PASS) \1703if (Name == NAME) { \1704CGPM.addPass(createCGSCCToFunctionPassAdaptor( \1705createFunctionToLoopPassAdaptor(CREATE_PASS, false, false))); \1706return Error::success(); \1707}1708#define LOOP_PASS(NAME, CREATE_PASS) \1709if (Name == NAME) { \1710CGPM.addPass(createCGSCCToFunctionPassAdaptor( \1711createFunctionToLoopPassAdaptor(CREATE_PASS, false, false))); \1712return Error::success(); \1713}1714#define LOOP_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \1715if (checkParametrizedPassName(Name, NAME)) { \1716auto Params = parsePassParameters(PARSER, Name, NAME); \1717if (!Params) \1718return Params.takeError(); \1719CGPM.addPass( \1720createCGSCCToFunctionPassAdaptor(createFunctionToLoopPassAdaptor( \1721CREATE_PASS(Params.get()), false, false))); \1722return Error::success(); \1723}1724#include "PassRegistry.def"17251726for (auto &C : CGSCCPipelineParsingCallbacks)1727if (C(Name, CGPM, InnerPipeline))1728return Error::success();1729return make_error<StringError>(1730formatv("unknown cgscc pass '{0}'", Name).str(),1731inconvertibleErrorCode());1732}17331734Error PassBuilder::parseFunctionPass(FunctionPassManager &FPM,1735const PipelineElement &E) {1736auto &Name = E.Name;1737auto &InnerPipeline = E.InnerPipeline;17381739// First handle complex passes like the pass managers which carry pipelines.1740if (!InnerPipeline.empty()) {1741if (Name == "function") {1742FunctionPassManager NestedFPM;1743if (auto Err = parseFunctionPassPipeline(NestedFPM, InnerPipeline))1744return Err;1745// Add the nested pass manager with the appropriate adaptor.1746FPM.addPass(std::move(NestedFPM));1747return Error::success();1748}1749if (Name == "loop" || Name == "loop-mssa") {1750LoopPassManager LPM;1751if (auto Err = parseLoopPassPipeline(LPM, InnerPipeline))1752return Err;1753// Add the nested pass manager with the appropriate adaptor.1754bool UseMemorySSA = (Name == "loop-mssa");1755bool UseBFI = llvm::any_of(InnerPipeline, [](auto Pipeline) {1756return Pipeline.Name.contains("simple-loop-unswitch");1757});1758bool UseBPI = llvm::any_of(InnerPipeline, [](auto Pipeline) {1759return Pipeline.Name == "loop-predication";1760});1761FPM.addPass(createFunctionToLoopPassAdaptor(std::move(LPM), UseMemorySSA,1762UseBFI, UseBPI));1763return Error::success();1764}1765if (Name == "machine-function") {1766MachineFunctionPassManager MFPM;1767if (auto Err = parseMachinePassPipeline(MFPM, InnerPipeline))1768return Err;1769FPM.addPass(createFunctionToMachineFunctionPassAdaptor(std::move(MFPM)));1770return Error::success();1771}17721773for (auto &C : FunctionPipelineParsingCallbacks)1774if (C(Name, FPM, InnerPipeline))1775return Error::success();17761777// Normal passes can't have pipelines.1778return make_error<StringError>(1779formatv("invalid use of '{0}' pass as function pipeline", Name).str(),1780inconvertibleErrorCode());1781}17821783// Now expand the basic registered passes from the .inc file.1784#define FUNCTION_PASS(NAME, CREATE_PASS) \1785if (Name == NAME) { \1786FPM.addPass(CREATE_PASS); \1787return Error::success(); \1788}1789#define FUNCTION_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \1790if (checkParametrizedPassName(Name, NAME)) { \1791auto Params = parsePassParameters(PARSER, Name, NAME); \1792if (!Params) \1793return Params.takeError(); \1794FPM.addPass(CREATE_PASS(Params.get())); \1795return Error::success(); \1796}1797#define FUNCTION_ANALYSIS(NAME, CREATE_PASS) \1798if (Name == "require<" NAME ">") { \1799FPM.addPass( \1800RequireAnalysisPass< \1801std::remove_reference_t<decltype(CREATE_PASS)>, Function>()); \1802return Error::success(); \1803} \1804if (Name == "invalidate<" NAME ">") { \1805FPM.addPass(InvalidateAnalysisPass< \1806std::remove_reference_t<decltype(CREATE_PASS)>>()); \1807return Error::success(); \1808}1809// FIXME: UseMemorySSA is set to false. Maybe we could do things like:1810// bool UseMemorySSA = !("canon-freeze" || "loop-predication" ||1811// "guard-widening");1812// The risk is that it may become obsolete if we're not careful.1813#define LOOPNEST_PASS(NAME, CREATE_PASS) \1814if (Name == NAME) { \1815FPM.addPass(createFunctionToLoopPassAdaptor(CREATE_PASS, false, false)); \1816return Error::success(); \1817}1818#define LOOP_PASS(NAME, CREATE_PASS) \1819if (Name == NAME) { \1820FPM.addPass(createFunctionToLoopPassAdaptor(CREATE_PASS, false, false)); \1821return Error::success(); \1822}1823#define LOOP_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \1824if (checkParametrizedPassName(Name, NAME)) { \1825auto Params = parsePassParameters(PARSER, Name, NAME); \1826if (!Params) \1827return Params.takeError(); \1828FPM.addPass(createFunctionToLoopPassAdaptor(CREATE_PASS(Params.get()), \1829false, false)); \1830return Error::success(); \1831}1832#include "PassRegistry.def"18331834for (auto &C : FunctionPipelineParsingCallbacks)1835if (C(Name, FPM, InnerPipeline))1836return Error::success();1837return make_error<StringError>(1838formatv("unknown function pass '{0}'", Name).str(),1839inconvertibleErrorCode());1840}18411842Error PassBuilder::parseLoopPass(LoopPassManager &LPM,1843const PipelineElement &E) {1844StringRef Name = E.Name;1845auto &InnerPipeline = E.InnerPipeline;18461847// First handle complex passes like the pass managers which carry pipelines.1848if (!InnerPipeline.empty()) {1849if (Name == "loop") {1850LoopPassManager NestedLPM;1851if (auto Err = parseLoopPassPipeline(NestedLPM, InnerPipeline))1852return Err;1853// Add the nested pass manager with the appropriate adaptor.1854LPM.addPass(std::move(NestedLPM));1855return Error::success();1856}18571858for (auto &C : LoopPipelineParsingCallbacks)1859if (C(Name, LPM, InnerPipeline))1860return Error::success();18611862// Normal passes can't have pipelines.1863return make_error<StringError>(1864formatv("invalid use of '{0}' pass as loop pipeline", Name).str(),1865inconvertibleErrorCode());1866}18671868// Now expand the basic registered passes from the .inc file.1869#define LOOPNEST_PASS(NAME, CREATE_PASS) \1870if (Name == NAME) { \1871LPM.addPass(CREATE_PASS); \1872return Error::success(); \1873}1874#define LOOP_PASS(NAME, CREATE_PASS) \1875if (Name == NAME) { \1876LPM.addPass(CREATE_PASS); \1877return Error::success(); \1878}1879#define LOOP_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \1880if (checkParametrizedPassName(Name, NAME)) { \1881auto Params = parsePassParameters(PARSER, Name, NAME); \1882if (!Params) \1883return Params.takeError(); \1884LPM.addPass(CREATE_PASS(Params.get())); \1885return Error::success(); \1886}1887#define LOOP_ANALYSIS(NAME, CREATE_PASS) \1888if (Name == "require<" NAME ">") { \1889LPM.addPass(RequireAnalysisPass< \1890std::remove_reference_t<decltype(CREATE_PASS)>, Loop, \1891LoopAnalysisManager, LoopStandardAnalysisResults &, \1892LPMUpdater &>()); \1893return Error::success(); \1894} \1895if (Name == "invalidate<" NAME ">") { \1896LPM.addPass(InvalidateAnalysisPass< \1897std::remove_reference_t<decltype(CREATE_PASS)>>()); \1898return Error::success(); \1899}1900#include "PassRegistry.def"19011902for (auto &C : LoopPipelineParsingCallbacks)1903if (C(Name, LPM, InnerPipeline))1904return Error::success();1905return make_error<StringError>(formatv("unknown loop pass '{0}'", Name).str(),1906inconvertibleErrorCode());1907}19081909Error PassBuilder::parseMachinePass(MachineFunctionPassManager &MFPM,1910const PipelineElement &E) {1911StringRef Name = E.Name;1912if (!E.InnerPipeline.empty())1913return make_error<StringError>("invalid pipeline",1914inconvertibleErrorCode());19151916#define MACHINE_MODULE_PASS(NAME, CREATE_PASS) \1917if (Name == NAME) { \1918MFPM.addPass(CREATE_PASS); \1919return Error::success(); \1920}1921#define MACHINE_FUNCTION_PASS(NAME, CREATE_PASS) \1922if (Name == NAME) { \1923MFPM.addPass(CREATE_PASS); \1924return Error::success(); \1925}1926#define MACHINE_FUNCTION_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, \1927PARAMS) \1928if (checkParametrizedPassName(Name, NAME)) { \1929auto Params = parsePassParameters(PARSER, Name, NAME); \1930if (!Params) \1931return Params.takeError(); \1932MFPM.addPass(CREATE_PASS(Params.get())); \1933return Error::success(); \1934}1935#define MACHINE_FUNCTION_ANALYSIS(NAME, CREATE_PASS) \1936if (Name == "require<" NAME ">") { \1937MFPM.addPass( \1938RequireAnalysisPass<std::remove_reference_t<decltype(CREATE_PASS)>, \1939MachineFunction>()); \1940return Error::success(); \1941} \1942if (Name == "invalidate<" NAME ">") { \1943MFPM.addPass(InvalidateAnalysisPass< \1944std::remove_reference_t<decltype(CREATE_PASS)>>()); \1945return Error::success(); \1946}1947#include "llvm/Passes/MachinePassRegistry.def"19481949for (auto &C : MachineFunctionPipelineParsingCallbacks)1950if (C(Name, MFPM, E.InnerPipeline))1951return Error::success();1952return make_error<StringError>(1953formatv("unknown machine pass '{0}'", Name).str(),1954inconvertibleErrorCode());1955}19561957bool PassBuilder::parseAAPassName(AAManager &AA, StringRef Name) {1958#define MODULE_ALIAS_ANALYSIS(NAME, CREATE_PASS) \1959if (Name == NAME) { \1960AA.registerModuleAnalysis< \1961std::remove_reference_t<decltype(CREATE_PASS)>>(); \1962return true; \1963}1964#define FUNCTION_ALIAS_ANALYSIS(NAME, CREATE_PASS) \1965if (Name == NAME) { \1966AA.registerFunctionAnalysis< \1967std::remove_reference_t<decltype(CREATE_PASS)>>(); \1968return true; \1969}1970#include "PassRegistry.def"19711972for (auto &C : AAParsingCallbacks)1973if (C(Name, AA))1974return true;1975return false;1976}19771978Error PassBuilder::parseMachinePassPipeline(1979MachineFunctionPassManager &MFPM, ArrayRef<PipelineElement> Pipeline) {1980for (const auto &Element : Pipeline) {1981if (auto Err = parseMachinePass(MFPM, Element))1982return Err;1983}1984return Error::success();1985}19861987Error PassBuilder::parseLoopPassPipeline(LoopPassManager &LPM,1988ArrayRef<PipelineElement> Pipeline) {1989for (const auto &Element : Pipeline) {1990if (auto Err = parseLoopPass(LPM, Element))1991return Err;1992}1993return Error::success();1994}19951996Error PassBuilder::parseFunctionPassPipeline(1997FunctionPassManager &FPM, ArrayRef<PipelineElement> Pipeline) {1998for (const auto &Element : Pipeline) {1999if (auto Err = parseFunctionPass(FPM, Element))2000return Err;2001}2002return Error::success();2003}20042005Error PassBuilder::parseCGSCCPassPipeline(CGSCCPassManager &CGPM,2006ArrayRef<PipelineElement> Pipeline) {2007for (const auto &Element : Pipeline) {2008if (auto Err = parseCGSCCPass(CGPM, Element))2009return Err;2010}2011return Error::success();2012}20132014void PassBuilder::crossRegisterProxies(LoopAnalysisManager &LAM,2015FunctionAnalysisManager &FAM,2016CGSCCAnalysisManager &CGAM,2017ModuleAnalysisManager &MAM,2018MachineFunctionAnalysisManager *MFAM) {2019MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); });2020MAM.registerPass([&] { return CGSCCAnalysisManagerModuleProxy(CGAM); });2021CGAM.registerPass([&] { return ModuleAnalysisManagerCGSCCProxy(MAM); });2022FAM.registerPass([&] { return CGSCCAnalysisManagerFunctionProxy(CGAM); });2023FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); });2024FAM.registerPass([&] { return LoopAnalysisManagerFunctionProxy(LAM); });2025LAM.registerPass([&] { return FunctionAnalysisManagerLoopProxy(FAM); });2026if (MFAM) {2027MAM.registerPass(2028[&] { return MachineFunctionAnalysisManagerModuleProxy(*MFAM); });2029FAM.registerPass(2030[&] { return MachineFunctionAnalysisManagerFunctionProxy(*MFAM); });2031MFAM->registerPass(2032[&] { return ModuleAnalysisManagerMachineFunctionProxy(MAM); });2033MFAM->registerPass(2034[&] { return FunctionAnalysisManagerMachineFunctionProxy(FAM); });2035}2036}20372038Error PassBuilder::parseModulePassPipeline(ModulePassManager &MPM,2039ArrayRef<PipelineElement> Pipeline) {2040for (const auto &Element : Pipeline) {2041if (auto Err = parseModulePass(MPM, Element))2042return Err;2043}2044return Error::success();2045}20462047// Primary pass pipeline description parsing routine for a \c ModulePassManager2048// FIXME: Should this routine accept a TargetMachine or require the caller to2049// pre-populate the analysis managers with target-specific stuff?2050Error PassBuilder::parsePassPipeline(ModulePassManager &MPM,2051StringRef PipelineText) {2052auto Pipeline = parsePipelineText(PipelineText);2053if (!Pipeline || Pipeline->empty())2054return make_error<StringError>(2055formatv("invalid pipeline '{0}'", PipelineText).str(),2056inconvertibleErrorCode());20572058// If the first name isn't at the module layer, wrap the pipeline up2059// automatically.2060StringRef FirstName = Pipeline->front().Name;20612062if (!isModulePassName(FirstName, ModulePipelineParsingCallbacks)) {2063bool UseMemorySSA;2064if (isCGSCCPassName(FirstName, CGSCCPipelineParsingCallbacks)) {2065Pipeline = {{"cgscc", std::move(*Pipeline)}};2066} else if (isFunctionPassName(FirstName,2067FunctionPipelineParsingCallbacks)) {2068Pipeline = {{"function", std::move(*Pipeline)}};2069} else if (isLoopNestPassName(FirstName, LoopPipelineParsingCallbacks,2070UseMemorySSA)) {2071Pipeline = {{"function", {{UseMemorySSA ? "loop-mssa" : "loop",2072std::move(*Pipeline)}}}};2073} else if (isLoopPassName(FirstName, LoopPipelineParsingCallbacks,2074UseMemorySSA)) {2075Pipeline = {{"function", {{UseMemorySSA ? "loop-mssa" : "loop",2076std::move(*Pipeline)}}}};2077} else if (isMachineFunctionPassName(2078FirstName, MachineFunctionPipelineParsingCallbacks)) {2079Pipeline = {{"function", {{"machine-function", std::move(*Pipeline)}}}};2080} else {2081for (auto &C : TopLevelPipelineParsingCallbacks)2082if (C(MPM, *Pipeline))2083return Error::success();20842085// Unknown pass or pipeline name!2086auto &InnerPipeline = Pipeline->front().InnerPipeline;2087return make_error<StringError>(2088formatv("unknown {0} name '{1}'",2089(InnerPipeline.empty() ? "pass" : "pipeline"), FirstName)2090.str(),2091inconvertibleErrorCode());2092}2093}20942095if (auto Err = parseModulePassPipeline(MPM, *Pipeline))2096return Err;2097return Error::success();2098}20992100// Primary pass pipeline description parsing routine for a \c CGSCCPassManager2101Error PassBuilder::parsePassPipeline(CGSCCPassManager &CGPM,2102StringRef PipelineText) {2103auto Pipeline = parsePipelineText(PipelineText);2104if (!Pipeline || Pipeline->empty())2105return make_error<StringError>(2106formatv("invalid pipeline '{0}'", PipelineText).str(),2107inconvertibleErrorCode());21082109StringRef FirstName = Pipeline->front().Name;2110if (!isCGSCCPassName(FirstName, CGSCCPipelineParsingCallbacks))2111return make_error<StringError>(2112formatv("unknown cgscc pass '{0}' in pipeline '{1}'", FirstName,2113PipelineText)2114.str(),2115inconvertibleErrorCode());21162117if (auto Err = parseCGSCCPassPipeline(CGPM, *Pipeline))2118return Err;2119return Error::success();2120}21212122// Primary pass pipeline description parsing routine for a \c2123// FunctionPassManager2124Error PassBuilder::parsePassPipeline(FunctionPassManager &FPM,2125StringRef PipelineText) {2126auto Pipeline = parsePipelineText(PipelineText);2127if (!Pipeline || Pipeline->empty())2128return make_error<StringError>(2129formatv("invalid pipeline '{0}'", PipelineText).str(),2130inconvertibleErrorCode());21312132StringRef FirstName = Pipeline->front().Name;2133if (!isFunctionPassName(FirstName, FunctionPipelineParsingCallbacks))2134return make_error<StringError>(2135formatv("unknown function pass '{0}' in pipeline '{1}'", FirstName,2136PipelineText)2137.str(),2138inconvertibleErrorCode());21392140if (auto Err = parseFunctionPassPipeline(FPM, *Pipeline))2141return Err;2142return Error::success();2143}21442145// Primary pass pipeline description parsing routine for a \c LoopPassManager2146Error PassBuilder::parsePassPipeline(LoopPassManager &CGPM,2147StringRef PipelineText) {2148auto Pipeline = parsePipelineText(PipelineText);2149if (!Pipeline || Pipeline->empty())2150return make_error<StringError>(2151formatv("invalid pipeline '{0}'", PipelineText).str(),2152inconvertibleErrorCode());21532154if (auto Err = parseLoopPassPipeline(CGPM, *Pipeline))2155return Err;21562157return Error::success();2158}21592160Error PassBuilder::parsePassPipeline(MachineFunctionPassManager &MFPM,2161StringRef PipelineText) {2162auto Pipeline = parsePipelineText(PipelineText);2163if (!Pipeline || Pipeline->empty())2164return make_error<StringError>(2165formatv("invalid machine pass pipeline '{0}'", PipelineText).str(),2166inconvertibleErrorCode());21672168if (auto Err = parseMachinePassPipeline(MFPM, *Pipeline))2169return Err;21702171return Error::success();2172}21732174Error PassBuilder::parseAAPipeline(AAManager &AA, StringRef PipelineText) {2175// If the pipeline just consists of the word 'default' just replace the AA2176// manager with our default one.2177if (PipelineText == "default") {2178AA = buildDefaultAAPipeline();2179return Error::success();2180}21812182while (!PipelineText.empty()) {2183StringRef Name;2184std::tie(Name, PipelineText) = PipelineText.split(',');2185if (!parseAAPassName(AA, Name))2186return make_error<StringError>(2187formatv("unknown alias analysis name '{0}'", Name).str(),2188inconvertibleErrorCode());2189}21902191return Error::success();2192}21932194std::optional<RegAllocFilterFunc>2195PassBuilder::parseRegAllocFilter(StringRef FilterName) {2196if (FilterName == "all")2197return nullptr;2198for (auto &C : RegClassFilterParsingCallbacks)2199if (auto F = C(FilterName))2200return F;2201return std::nullopt;2202}22032204static void printPassName(StringRef PassName, raw_ostream &OS) {2205OS << " " << PassName << "\n";2206}2207static void printPassName(StringRef PassName, StringRef Params,2208raw_ostream &OS) {2209OS << " " << PassName << "<" << Params << ">\n";2210}22112212void PassBuilder::printPassNames(raw_ostream &OS) {2213// TODO: print pass descriptions when they are available22142215OS << "Module passes:\n";2216#define MODULE_PASS(NAME, CREATE_PASS) printPassName(NAME, OS);2217#include "PassRegistry.def"22182219OS << "Module passes with params:\n";2220#define MODULE_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \2221printPassName(NAME, PARAMS, OS);2222#include "PassRegistry.def"22232224OS << "Module analyses:\n";2225#define MODULE_ANALYSIS(NAME, CREATE_PASS) printPassName(NAME, OS);2226#include "PassRegistry.def"22272228OS << "Module alias analyses:\n";2229#define MODULE_ALIAS_ANALYSIS(NAME, CREATE_PASS) printPassName(NAME, OS);2230#include "PassRegistry.def"22312232OS << "CGSCC passes:\n";2233#define CGSCC_PASS(NAME, CREATE_PASS) printPassName(NAME, OS);2234#include "PassRegistry.def"22352236OS << "CGSCC passes with params:\n";2237#define CGSCC_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \2238printPassName(NAME, PARAMS, OS);2239#include "PassRegistry.def"22402241OS << "CGSCC analyses:\n";2242#define CGSCC_ANALYSIS(NAME, CREATE_PASS) printPassName(NAME, OS);2243#include "PassRegistry.def"22442245OS << "Function passes:\n";2246#define FUNCTION_PASS(NAME, CREATE_PASS) printPassName(NAME, OS);2247#include "PassRegistry.def"22482249OS << "Function passes with params:\n";2250#define FUNCTION_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \2251printPassName(NAME, PARAMS, OS);2252#include "PassRegistry.def"22532254OS << "Function analyses:\n";2255#define FUNCTION_ANALYSIS(NAME, CREATE_PASS) printPassName(NAME, OS);2256#include "PassRegistry.def"22572258OS << "Function alias analyses:\n";2259#define FUNCTION_ALIAS_ANALYSIS(NAME, CREATE_PASS) printPassName(NAME, OS);2260#include "PassRegistry.def"22612262OS << "LoopNest passes:\n";2263#define LOOPNEST_PASS(NAME, CREATE_PASS) printPassName(NAME, OS);2264#include "PassRegistry.def"22652266OS << "Loop passes:\n";2267#define LOOP_PASS(NAME, CREATE_PASS) printPassName(NAME, OS);2268#include "PassRegistry.def"22692270OS << "Loop passes with params:\n";2271#define LOOP_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \2272printPassName(NAME, PARAMS, OS);2273#include "PassRegistry.def"22742275OS << "Loop analyses:\n";2276#define LOOP_ANALYSIS(NAME, CREATE_PASS) printPassName(NAME, OS);2277#include "PassRegistry.def"22782279OS << "Machine module passes (WIP):\n";2280#define MACHINE_MODULE_PASS(NAME, CREATE_PASS) printPassName(NAME, OS);2281#include "llvm/Passes/MachinePassRegistry.def"22822283OS << "Machine function passes (WIP):\n";2284#define MACHINE_FUNCTION_PASS(NAME, CREATE_PASS) printPassName(NAME, OS);2285#include "llvm/Passes/MachinePassRegistry.def"22862287OS << "Machine function analyses (WIP):\n";2288#define MACHINE_FUNCTION_ANALYSIS(NAME, CREATE_PASS) printPassName(NAME, OS);2289#include "llvm/Passes/MachinePassRegistry.def"2290}22912292void PassBuilder::registerParseTopLevelPipelineCallback(2293const std::function<bool(ModulePassManager &, ArrayRef<PipelineElement>)>2294&C) {2295TopLevelPipelineParsingCallbacks.push_back(C);2296}229722982299