2849 lines · cpp
1//===- Parsing and selection of pass pipelines ----------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8/// \file9///10/// This file provides the implementation of the PassBuilder based on our11/// static pass registry as well as related functionality. It also provides12/// helpers to aid in analyzing, debugging, and testing passes and pass13/// pipelines.14///15//===----------------------------------------------------------------------===//16 17#include "llvm/Passes/PassBuilder.h"18#include "llvm/ADT/StringSwitch.h"19#include "llvm/Analysis/AliasAnalysisEvaluator.h"20#include "llvm/Analysis/AliasSetTracker.h"21#include "llvm/Analysis/AssumptionCache.h"22#include "llvm/Analysis/BasicAliasAnalysis.h"23#include "llvm/Analysis/BlockFrequencyInfo.h"24#include "llvm/Analysis/BranchProbabilityInfo.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/CtxProfAnalysis.h"31#include "llvm/Analysis/CycleAnalysis.h"32#include "llvm/Analysis/DDG.h"33#include "llvm/Analysis/DDGPrinter.h"34#include "llvm/Analysis/DXILMetadataAnalysis.h"35#include "llvm/Analysis/DXILResource.h"36#include "llvm/Analysis/Delinearization.h"37#include "llvm/Analysis/DemandedBits.h"38#include "llvm/Analysis/DependenceAnalysis.h"39#include "llvm/Analysis/DomPrinter.h"40#include "llvm/Analysis/DominanceFrontier.h"41#include "llvm/Analysis/EphemeralValuesCache.h"42#include "llvm/Analysis/FunctionPropertiesAnalysis.h"43#include "llvm/Analysis/GlobalsModRef.h"44#include "llvm/Analysis/HashRecognize.h"45#include "llvm/Analysis/IR2Vec.h"46#include "llvm/Analysis/IVUsers.h"47#include "llvm/Analysis/InlineAdvisor.h"48#include "llvm/Analysis/InstCount.h"49#include "llvm/Analysis/KernelInfo.h"50#include "llvm/Analysis/LastRunTrackingAnalysis.h"51#include "llvm/Analysis/LazyCallGraph.h"52#include "llvm/Analysis/LazyValueInfo.h"53#include "llvm/Analysis/Lint.h"54#include "llvm/Analysis/LoopAccessAnalysis.h"55#include "llvm/Analysis/LoopCacheAnalysis.h"56#include "llvm/Analysis/LoopInfo.h"57#include "llvm/Analysis/LoopNestAnalysis.h"58#include "llvm/Analysis/MemDerefPrinter.h"59#include "llvm/Analysis/MemoryDependenceAnalysis.h"60#include "llvm/Analysis/MemorySSA.h"61#include "llvm/Analysis/ModuleDebugInfoPrinter.h"62#include "llvm/Analysis/ModuleSummaryAnalysis.h"63#include "llvm/Analysis/MustExecute.h"64#include "llvm/Analysis/ObjCARCAliasAnalysis.h"65#include "llvm/Analysis/PhiValues.h"66#include "llvm/Analysis/PostDominators.h"67#include "llvm/Analysis/ProfileSummaryInfo.h"68#include "llvm/Analysis/RegionInfo.h"69#include "llvm/Analysis/RuntimeLibcallInfo.h"70#include "llvm/Analysis/ScalarEvolution.h"71#include "llvm/Analysis/ScalarEvolutionAliasAnalysis.h"72#include "llvm/Analysis/ScalarEvolutionDivision.h"73#include "llvm/Analysis/ScopedNoAliasAA.h"74#include "llvm/Analysis/StackLifetime.h"75#include "llvm/Analysis/StackSafetyAnalysis.h"76#include "llvm/Analysis/StructuralHash.h"77#include "llvm/Analysis/TargetLibraryInfo.h"78#include "llvm/Analysis/TargetTransformInfo.h"79#include "llvm/Analysis/TypeBasedAliasAnalysis.h"80#include "llvm/Analysis/UniformityAnalysis.h"81#include "llvm/CodeGen/AssignmentTrackingAnalysis.h"82#include "llvm/CodeGen/AtomicExpand.h"83#include "llvm/CodeGen/BasicBlockSectionsProfileReader.h"84#include "llvm/CodeGen/BranchFoldingPass.h"85#include "llvm/CodeGen/BranchRelaxation.h"86#include "llvm/CodeGen/CallBrPrepare.h"87#include "llvm/CodeGen/CodeGenPrepare.h"88#include "llvm/CodeGen/ComplexDeinterleavingPass.h"89#include "llvm/CodeGen/DeadMachineInstructionElim.h"90#include "llvm/CodeGen/DetectDeadLanes.h"91#include "llvm/CodeGen/DwarfEHPrepare.h"92#include "llvm/CodeGen/EarlyIfConversion.h"93#include "llvm/CodeGen/EdgeBundles.h"94#include "llvm/CodeGen/ExpandFp.h"95#include "llvm/CodeGen/ExpandLargeDivRem.h"96#include "llvm/CodeGen/ExpandMemCmp.h"97#include "llvm/CodeGen/ExpandPostRAPseudos.h"98#include "llvm/CodeGen/ExpandReductions.h"99#include "llvm/CodeGen/FEntryInserter.h"100#include "llvm/CodeGen/FinalizeISel.h"101#include "llvm/CodeGen/FixupStatepointCallerSaved.h"102#include "llvm/CodeGen/GCMetadata.h"103#include "llvm/CodeGen/GlobalISel/GISelValueTracking.h"104#include "llvm/CodeGen/GlobalMerge.h"105#include "llvm/CodeGen/GlobalMergeFunctions.h"106#include "llvm/CodeGen/HardwareLoops.h"107#include "llvm/CodeGen/IndirectBrExpand.h"108#include "llvm/CodeGen/InitUndef.h"109#include "llvm/CodeGen/InterleavedAccess.h"110#include "llvm/CodeGen/InterleavedLoadCombine.h"111#include "llvm/CodeGen/JMCInstrumenter.h"112#include "llvm/CodeGen/LiveDebugValuesPass.h"113#include "llvm/CodeGen/LiveDebugVariables.h"114#include "llvm/CodeGen/LiveIntervals.h"115#include "llvm/CodeGen/LiveRegMatrix.h"116#include "llvm/CodeGen/LiveStacks.h"117#include "llvm/CodeGen/LiveVariables.h"118#include "llvm/CodeGen/LocalStackSlotAllocation.h"119#include "llvm/CodeGen/LowerEmuTLS.h"120#include "llvm/CodeGen/MIRPrinter.h"121#include "llvm/CodeGen/MachineBlockFrequencyInfo.h"122#include "llvm/CodeGen/MachineBlockPlacement.h"123#include "llvm/CodeGen/MachineBranchProbabilityInfo.h"124#include "llvm/CodeGen/MachineCSE.h"125#include "llvm/CodeGen/MachineCopyPropagation.h"126#include "llvm/CodeGen/MachineDominators.h"127#include "llvm/CodeGen/MachineFunctionAnalysis.h"128#include "llvm/CodeGen/MachineLICM.h"129#include "llvm/CodeGen/MachineLateInstrsCleanup.h"130#include "llvm/CodeGen/MachinePassManager.h"131#include "llvm/CodeGen/MachinePostDominators.h"132#include "llvm/CodeGen/MachineRegisterInfo.h"133#include "llvm/CodeGen/MachineScheduler.h"134#include "llvm/CodeGen/MachineSink.h"135#include "llvm/CodeGen/MachineTraceMetrics.h"136#include "llvm/CodeGen/MachineUniformityAnalysis.h"137#include "llvm/CodeGen/MachineVerifier.h"138#include "llvm/CodeGen/OptimizePHIs.h"139#include "llvm/CodeGen/PEI.h"140#include "llvm/CodeGen/PHIElimination.h"141#include "llvm/CodeGen/PatchableFunction.h"142#include "llvm/CodeGen/PeepholeOptimizer.h"143#include "llvm/CodeGen/PostRAHazardRecognizer.h"144#include "llvm/CodeGen/PostRAMachineSink.h"145#include "llvm/CodeGen/PostRASchedulerList.h"146#include "llvm/CodeGen/PreISelIntrinsicLowering.h"147#include "llvm/CodeGen/ProcessImplicitDefs.h"148#include "llvm/CodeGen/ReachingDefAnalysis.h"149#include "llvm/CodeGen/RegAllocEvictionAdvisor.h"150#include "llvm/CodeGen/RegAllocFast.h"151#include "llvm/CodeGen/RegAllocGreedyPass.h"152#include "llvm/CodeGen/RegAllocPriorityAdvisor.h"153#include "llvm/CodeGen/RegUsageInfoCollector.h"154#include "llvm/CodeGen/RegUsageInfoPropagate.h"155#include "llvm/CodeGen/RegisterCoalescerPass.h"156#include "llvm/CodeGen/RegisterUsageInfo.h"157#include "llvm/CodeGen/RemoveLoadsIntoFakeUses.h"158#include "llvm/CodeGen/RemoveRedundantDebugValues.h"159#include "llvm/CodeGen/RenameIndependentSubregs.h"160#include "llvm/CodeGen/ReplaceWithVeclib.h"161#include "llvm/CodeGen/SafeStack.h"162#include "llvm/CodeGen/SanitizerBinaryMetadata.h"163#include "llvm/CodeGen/SelectOptimize.h"164#include "llvm/CodeGen/ShadowStackGCLowering.h"165#include "llvm/CodeGen/ShrinkWrap.h"166#include "llvm/CodeGen/SjLjEHPrepare.h"167#include "llvm/CodeGen/SlotIndexes.h"168#include "llvm/CodeGen/SpillPlacement.h"169#include "llvm/CodeGen/StackColoring.h"170#include "llvm/CodeGen/StackFrameLayoutAnalysisPass.h"171#include "llvm/CodeGen/StackProtector.h"172#include "llvm/CodeGen/StackSlotColoring.h"173#include "llvm/CodeGen/TailDuplication.h"174#include "llvm/CodeGen/TargetPassConfig.h"175#include "llvm/CodeGen/TwoAddressInstructionPass.h"176#include "llvm/CodeGen/TypePromotion.h"177#include "llvm/CodeGen/UnreachableBlockElim.h"178#include "llvm/CodeGen/VirtRegMap.h"179#include "llvm/CodeGen/WasmEHPrepare.h"180#include "llvm/CodeGen/WinEHPrepare.h"181#include "llvm/CodeGen/XRayInstrumentation.h"182#include "llvm/IR/DebugInfo.h"183#include "llvm/IR/Dominators.h"184#include "llvm/IR/PassManager.h"185#include "llvm/IR/SafepointIRVerifier.h"186#include "llvm/IR/Verifier.h"187#include "llvm/IRPrinter/IRPrintingPasses.h"188#include "llvm/Passes/OptimizationLevel.h"189#include "llvm/Support/CodeGen.h"190#include "llvm/Support/CommandLine.h"191#include "llvm/Support/Debug.h"192#include "llvm/Support/Error.h"193#include "llvm/Support/ErrorHandling.h"194#include "llvm/Support/FormatVariadic.h"195#include "llvm/Support/Regex.h"196#include "llvm/Target/TargetMachine.h"197#include "llvm/Transforms/AggressiveInstCombine/AggressiveInstCombine.h"198#include "llvm/Transforms/CFGuard.h"199#include "llvm/Transforms/Coroutines/CoroAnnotationElide.h"200#include "llvm/Transforms/Coroutines/CoroCleanup.h"201#include "llvm/Transforms/Coroutines/CoroConditionalWrapper.h"202#include "llvm/Transforms/Coroutines/CoroEarly.h"203#include "llvm/Transforms/Coroutines/CoroElide.h"204#include "llvm/Transforms/Coroutines/CoroSplit.h"205#include "llvm/Transforms/HipStdPar/HipStdPar.h"206#include "llvm/Transforms/IPO/AlwaysInliner.h"207#include "llvm/Transforms/IPO/Annotation2Metadata.h"208#include "llvm/Transforms/IPO/ArgumentPromotion.h"209#include "llvm/Transforms/IPO/Attributor.h"210#include "llvm/Transforms/IPO/BlockExtractor.h"211#include "llvm/Transforms/IPO/CalledValuePropagation.h"212#include "llvm/Transforms/IPO/ConstantMerge.h"213#include "llvm/Transforms/IPO/CrossDSOCFI.h"214#include "llvm/Transforms/IPO/DeadArgumentElimination.h"215#include "llvm/Transforms/IPO/ElimAvailExtern.h"216#include "llvm/Transforms/IPO/EmbedBitcodePass.h"217#include "llvm/Transforms/IPO/ExpandVariadics.h"218#include "llvm/Transforms/IPO/FatLTOCleanup.h"219#include "llvm/Transforms/IPO/ForceFunctionAttrs.h"220#include "llvm/Transforms/IPO/FunctionAttrs.h"221#include "llvm/Transforms/IPO/FunctionImport.h"222#include "llvm/Transforms/IPO/GlobalDCE.h"223#include "llvm/Transforms/IPO/GlobalOpt.h"224#include "llvm/Transforms/IPO/GlobalSplit.h"225#include "llvm/Transforms/IPO/HotColdSplitting.h"226#include "llvm/Transforms/IPO/IROutliner.h"227#include "llvm/Transforms/IPO/InferFunctionAttrs.h"228#include "llvm/Transforms/IPO/Internalize.h"229#include "llvm/Transforms/IPO/LoopExtractor.h"230#include "llvm/Transforms/IPO/LowerTypeTests.h"231#include "llvm/Transforms/IPO/MemProfContextDisambiguation.h"232#include "llvm/Transforms/IPO/MergeFunctions.h"233#include "llvm/Transforms/IPO/OpenMPOpt.h"234#include "llvm/Transforms/IPO/PartialInlining.h"235#include "llvm/Transforms/IPO/SCCP.h"236#include "llvm/Transforms/IPO/SampleProfile.h"237#include "llvm/Transforms/IPO/SampleProfileProbe.h"238#include "llvm/Transforms/IPO/StripDeadPrototypes.h"239#include "llvm/Transforms/IPO/StripSymbols.h"240#include "llvm/Transforms/IPO/WholeProgramDevirt.h"241#include "llvm/Transforms/InstCombine/InstCombine.h"242#include "llvm/Transforms/Instrumentation/AddressSanitizer.h"243#include "llvm/Transforms/Instrumentation/AllocToken.h"244#include "llvm/Transforms/Instrumentation/BoundsChecking.h"245#include "llvm/Transforms/Instrumentation/CGProfile.h"246#include "llvm/Transforms/Instrumentation/ControlHeightReduction.h"247#include "llvm/Transforms/Instrumentation/DataFlowSanitizer.h"248#include "llvm/Transforms/Instrumentation/GCOVProfiler.h"249#include "llvm/Transforms/Instrumentation/HWAddressSanitizer.h"250#include "llvm/Transforms/Instrumentation/InstrProfiling.h"251#include "llvm/Transforms/Instrumentation/KCFI.h"252#include "llvm/Transforms/Instrumentation/LowerAllowCheckPass.h"253#include "llvm/Transforms/Instrumentation/MemProfInstrumentation.h"254#include "llvm/Transforms/Instrumentation/MemProfUse.h"255#include "llvm/Transforms/Instrumentation/MemorySanitizer.h"256#include "llvm/Transforms/Instrumentation/NumericalStabilitySanitizer.h"257#include "llvm/Transforms/Instrumentation/PGOCtxProfFlattening.h"258#include "llvm/Transforms/Instrumentation/PGOCtxProfLowering.h"259#include "llvm/Transforms/Instrumentation/PGOForceFunctionAttrs.h"260#include "llvm/Transforms/Instrumentation/PGOInstrumentation.h"261#include "llvm/Transforms/Instrumentation/RealtimeSanitizer.h"262#include "llvm/Transforms/Instrumentation/SanitizerBinaryMetadata.h"263#include "llvm/Transforms/Instrumentation/SanitizerCoverage.h"264#include "llvm/Transforms/Instrumentation/ThreadSanitizer.h"265#include "llvm/Transforms/Instrumentation/TypeSanitizer.h"266#include "llvm/Transforms/ObjCARC.h"267#include "llvm/Transforms/Scalar/ADCE.h"268#include "llvm/Transforms/Scalar/AlignmentFromAssumptions.h"269#include "llvm/Transforms/Scalar/AnnotationRemarks.h"270#include "llvm/Transforms/Scalar/BDCE.h"271#include "llvm/Transforms/Scalar/CallSiteSplitting.h"272#include "llvm/Transforms/Scalar/ConstantHoisting.h"273#include "llvm/Transforms/Scalar/ConstraintElimination.h"274#include "llvm/Transforms/Scalar/CorrelatedValuePropagation.h"275#include "llvm/Transforms/Scalar/DCE.h"276#include "llvm/Transforms/Scalar/DFAJumpThreading.h"277#include "llvm/Transforms/Scalar/DeadStoreElimination.h"278#include "llvm/Transforms/Scalar/DivRemPairs.h"279#include "llvm/Transforms/Scalar/DropUnnecessaryAssumes.h"280#include "llvm/Transforms/Scalar/EarlyCSE.h"281#include "llvm/Transforms/Scalar/FlattenCFG.h"282#include "llvm/Transforms/Scalar/Float2Int.h"283#include "llvm/Transforms/Scalar/GVN.h"284#include "llvm/Transforms/Scalar/GuardWidening.h"285#include "llvm/Transforms/Scalar/IVUsersPrinter.h"286#include "llvm/Transforms/Scalar/IndVarSimplify.h"287#include "llvm/Transforms/Scalar/InductiveRangeCheckElimination.h"288#include "llvm/Transforms/Scalar/InferAddressSpaces.h"289#include "llvm/Transforms/Scalar/InferAlignment.h"290#include "llvm/Transforms/Scalar/InstSimplifyPass.h"291#include "llvm/Transforms/Scalar/JumpTableToSwitch.h"292#include "llvm/Transforms/Scalar/JumpThreading.h"293#include "llvm/Transforms/Scalar/LICM.h"294#include "llvm/Transforms/Scalar/LoopAccessAnalysisPrinter.h"295#include "llvm/Transforms/Scalar/LoopBoundSplit.h"296#include "llvm/Transforms/Scalar/LoopDataPrefetch.h"297#include "llvm/Transforms/Scalar/LoopDeletion.h"298#include "llvm/Transforms/Scalar/LoopDistribute.h"299#include "llvm/Transforms/Scalar/LoopFlatten.h"300#include "llvm/Transforms/Scalar/LoopFuse.h"301#include "llvm/Transforms/Scalar/LoopIdiomRecognize.h"302#include "llvm/Transforms/Scalar/LoopInstSimplify.h"303#include "llvm/Transforms/Scalar/LoopInterchange.h"304#include "llvm/Transforms/Scalar/LoopLoadElimination.h"305#include "llvm/Transforms/Scalar/LoopPassManager.h"306#include "llvm/Transforms/Scalar/LoopPredication.h"307#include "llvm/Transforms/Scalar/LoopRotation.h"308#include "llvm/Transforms/Scalar/LoopSimplifyCFG.h"309#include "llvm/Transforms/Scalar/LoopSink.h"310#include "llvm/Transforms/Scalar/LoopStrengthReduce.h"311#include "llvm/Transforms/Scalar/LoopTermFold.h"312#include "llvm/Transforms/Scalar/LoopUnrollAndJamPass.h"313#include "llvm/Transforms/Scalar/LoopUnrollPass.h"314#include "llvm/Transforms/Scalar/LoopVersioningLICM.h"315#include "llvm/Transforms/Scalar/LowerAtomicPass.h"316#include "llvm/Transforms/Scalar/LowerConstantIntrinsics.h"317#include "llvm/Transforms/Scalar/LowerExpectIntrinsic.h"318#include "llvm/Transforms/Scalar/LowerGuardIntrinsic.h"319#include "llvm/Transforms/Scalar/LowerMatrixIntrinsics.h"320#include "llvm/Transforms/Scalar/LowerWidenableCondition.h"321#include "llvm/Transforms/Scalar/MakeGuardsExplicit.h"322#include "llvm/Transforms/Scalar/MemCpyOptimizer.h"323#include "llvm/Transforms/Scalar/MergeICmps.h"324#include "llvm/Transforms/Scalar/MergedLoadStoreMotion.h"325#include "llvm/Transforms/Scalar/NaryReassociate.h"326#include "llvm/Transforms/Scalar/NewGVN.h"327#include "llvm/Transforms/Scalar/PartiallyInlineLibCalls.h"328#include "llvm/Transforms/Scalar/PlaceSafepoints.h"329#include "llvm/Transforms/Scalar/Reassociate.h"330#include "llvm/Transforms/Scalar/Reg2Mem.h"331#include "llvm/Transforms/Scalar/RewriteStatepointsForGC.h"332#include "llvm/Transforms/Scalar/SCCP.h"333#include "llvm/Transforms/Scalar/SROA.h"334#include "llvm/Transforms/Scalar/ScalarizeMaskedMemIntrin.h"335#include "llvm/Transforms/Scalar/Scalarizer.h"336#include "llvm/Transforms/Scalar/SeparateConstOffsetFromGEP.h"337#include "llvm/Transforms/Scalar/SimpleLoopUnswitch.h"338#include "llvm/Transforms/Scalar/SimplifyCFG.h"339#include "llvm/Transforms/Scalar/Sink.h"340#include "llvm/Transforms/Scalar/SpeculativeExecution.h"341#include "llvm/Transforms/Scalar/StraightLineStrengthReduce.h"342#include "llvm/Transforms/Scalar/StructurizeCFG.h"343#include "llvm/Transforms/Scalar/TailRecursionElimination.h"344#include "llvm/Transforms/Scalar/WarnMissedTransforms.h"345#include "llvm/Transforms/Utils/AddDiscriminators.h"346#include "llvm/Transforms/Utils/AssumeBundleBuilder.h"347#include "llvm/Transforms/Utils/BreakCriticalEdges.h"348#include "llvm/Transforms/Utils/CanonicalizeAliases.h"349#include "llvm/Transforms/Utils/CanonicalizeFreezeInLoops.h"350#include "llvm/Transforms/Utils/CountVisits.h"351#include "llvm/Transforms/Utils/DXILUpgrade.h"352#include "llvm/Transforms/Utils/Debugify.h"353#include "llvm/Transforms/Utils/DeclareRuntimeLibcalls.h"354#include "llvm/Transforms/Utils/EntryExitInstrumenter.h"355#include "llvm/Transforms/Utils/FixIrreducible.h"356#include "llvm/Transforms/Utils/HelloWorld.h"357#include "llvm/Transforms/Utils/IRNormalizer.h"358#include "llvm/Transforms/Utils/InjectTLIMappings.h"359#include "llvm/Transforms/Utils/InstructionNamer.h"360#include "llvm/Transforms/Utils/LibCallsShrinkWrap.h"361#include "llvm/Transforms/Utils/LoopSimplify.h"362#include "llvm/Transforms/Utils/LoopVersioning.h"363#include "llvm/Transforms/Utils/LowerGlobalDtors.h"364#include "llvm/Transforms/Utils/LowerIFunc.h"365#include "llvm/Transforms/Utils/LowerInvoke.h"366#include "llvm/Transforms/Utils/LowerSwitch.h"367#include "llvm/Transforms/Utils/Mem2Reg.h"368#include "llvm/Transforms/Utils/MetaRenamer.h"369#include "llvm/Transforms/Utils/MoveAutoInit.h"370#include "llvm/Transforms/Utils/NameAnonGlobals.h"371#include "llvm/Transforms/Utils/PredicateInfo.h"372#include "llvm/Transforms/Utils/ProfileVerify.h"373#include "llvm/Transforms/Utils/RelLookupTableConverter.h"374#include "llvm/Transforms/Utils/StripGCRelocates.h"375#include "llvm/Transforms/Utils/StripNonLineTableDebugInfo.h"376#include "llvm/Transforms/Utils/SymbolRewriter.h"377#include "llvm/Transforms/Utils/UnifyFunctionExitNodes.h"378#include "llvm/Transforms/Utils/UnifyLoopExits.h"379#include "llvm/Transforms/Vectorize/LoadStoreVectorizer.h"380#include "llvm/Transforms/Vectorize/LoopIdiomVectorize.h"381#include "llvm/Transforms/Vectorize/LoopVectorize.h"382#include "llvm/Transforms/Vectorize/SLPVectorizer.h"383#include "llvm/Transforms/Vectorize/SandboxVectorizer/SandboxVectorizer.h"384#include "llvm/Transforms/Vectorize/VectorCombine.h"385#include <optional>386 387using namespace llvm;388 389cl::opt<bool> llvm::PrintPipelinePasses(390 "print-pipeline-passes",391 cl::desc("Print a '-passes' compatible string describing the pipeline "392 "(best-effort only)."));393 394AnalysisKey NoOpModuleAnalysis::Key;395AnalysisKey NoOpCGSCCAnalysis::Key;396AnalysisKey NoOpFunctionAnalysis::Key;397AnalysisKey NoOpLoopAnalysis::Key;398 399namespace {400 401// Passes for testing crashes.402// DO NOT USE THIS EXCEPT FOR TESTING!403class TriggerCrashModulePass : public PassInfoMixin<TriggerCrashModulePass> {404public:405 PreservedAnalyses run(Module &, ModuleAnalysisManager &) {406 abort();407 return PreservedAnalyses::all();408 }409 static StringRef name() { return "TriggerCrashModulePass"; }410};411 412class TriggerCrashFunctionPass413 : public PassInfoMixin<TriggerCrashFunctionPass> {414public:415 PreservedAnalyses run(Function &, FunctionAnalysisManager &) {416 abort();417 return PreservedAnalyses::all();418 }419 static StringRef name() { return "TriggerCrashFunctionPass"; }420};421 422// A pass for testing message reporting of -verify-each failures.423// DO NOT USE THIS EXCEPT FOR TESTING!424class TriggerVerifierErrorPass425 : public PassInfoMixin<TriggerVerifierErrorPass> {426public:427 PreservedAnalyses run(Module &M, ModuleAnalysisManager &) {428 // Intentionally break the Module by creating an alias without setting the429 // aliasee.430 auto *PtrTy = PointerType::getUnqual(M.getContext());431 GlobalAlias::create(PtrTy, PtrTy->getAddressSpace(),432 GlobalValue::LinkageTypes::InternalLinkage,433 "__bad_alias", nullptr, &M);434 return PreservedAnalyses::none();435 }436 437 PreservedAnalyses run(Function &F, FunctionAnalysisManager &) {438 // Intentionally break the Function by inserting a terminator439 // instruction in the middle of a basic block.440 BasicBlock &BB = F.getEntryBlock();441 new UnreachableInst(F.getContext(), BB.getTerminator()->getIterator());442 return PreservedAnalyses::none();443 }444 445 PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &) {446 // Intentionally create a virtual register and set NoVRegs property.447 auto &MRI = MF.getRegInfo();448 MRI.createGenericVirtualRegister(LLT::scalar(8));449 MF.getProperties().setNoVRegs();450 return PreservedAnalyses::all();451 }452 453 static StringRef name() { return "TriggerVerifierErrorPass"; }454};455 456// A pass requires all MachineFunctionProperties.457// DO NOT USE THIS EXCEPT FOR TESTING!458class RequireAllMachineFunctionPropertiesPass459 : public PassInfoMixin<RequireAllMachineFunctionPropertiesPass> {460public:461 PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &) {462 MFPropsModifier _(*this, MF);463 return PreservedAnalyses::none();464 }465 466 static MachineFunctionProperties getRequiredProperties() {467 return MachineFunctionProperties()468 .setFailedISel()469 .setFailsVerification()470 .setIsSSA()471 .setLegalized()472 .setNoPHIs()473 .setNoVRegs()474 .setRegBankSelected()475 .setSelected()476 .setTiedOpsRewritten()477 .setTracksDebugUserValues()478 .setTracksLiveness();479 }480 static StringRef name() { return "RequireAllMachineFunctionPropertiesPass"; }481};482 483} // namespace484 485static std::optional<OptimizationLevel> parseOptLevel(StringRef S) {486 return StringSwitch<std::optional<OptimizationLevel>>(S)487 .Case("O0", OptimizationLevel::O0)488 .Case("O1", OptimizationLevel::O1)489 .Case("O2", OptimizationLevel::O2)490 .Case("O3", OptimizationLevel::O3)491 .Case("Os", OptimizationLevel::Os)492 .Case("Oz", OptimizationLevel::Oz)493 .Default(std::nullopt);494}495 496static Expected<OptimizationLevel> parseOptLevelParam(StringRef S) {497 std::optional<OptimizationLevel> OptLevel = parseOptLevel(S);498 if (OptLevel)499 return *OptLevel;500 return make_error<StringError>(501 formatv("invalid optimization level '{}'", S).str(),502 inconvertibleErrorCode());503}504 505PassBuilder::PassBuilder(TargetMachine *TM, PipelineTuningOptions PTO,506 std::optional<PGOOptions> PGOOpt,507 PassInstrumentationCallbacks *PIC,508 IntrusiveRefCntPtr<vfs::FileSystem> FS)509 : TM(TM), PTO(PTO), PGOOpt(PGOOpt), PIC(PIC), FS(std::move(FS)) {510 if (TM)511 TM->registerPassBuilderCallbacks(*this);512 if (PIC) {513 PIC->registerClassToPassNameCallback([this, PIC]() {514 // MSVC requires this to be captured if it's used inside decltype.515 // Other compilers consider it an unused lambda capture.516 (void)this;517#define MODULE_PASS(NAME, CREATE_PASS) \518 PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME);519#define MODULE_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \520 PIC->addClassToPassName(CLASS, NAME);521#define MODULE_ANALYSIS(NAME, CREATE_PASS) \522 PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME);523#define FUNCTION_PASS(NAME, CREATE_PASS) \524 PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME);525#define FUNCTION_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \526 PIC->addClassToPassName(CLASS, NAME);527#define FUNCTION_ANALYSIS(NAME, CREATE_PASS) \528 PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME);529#define LOOPNEST_PASS(NAME, CREATE_PASS) \530 PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME);531#define LOOP_PASS(NAME, CREATE_PASS) \532 PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME);533#define LOOP_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \534 PIC->addClassToPassName(CLASS, NAME);535#define LOOP_ANALYSIS(NAME, CREATE_PASS) \536 PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME);537#define CGSCC_PASS(NAME, CREATE_PASS) \538 PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME);539#define CGSCC_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \540 PIC->addClassToPassName(CLASS, NAME);541#define CGSCC_ANALYSIS(NAME, CREATE_PASS) \542 PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME);543#include "PassRegistry.def"544 545#define MACHINE_FUNCTION_ANALYSIS(NAME, CREATE_PASS) \546 PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME);547#define MACHINE_FUNCTION_PASS(NAME, CREATE_PASS) \548 PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME);549#define MACHINE_FUNCTION_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, \550 PARAMS) \551 PIC->addClassToPassName(CLASS, NAME);552#include "llvm/Passes/MachinePassRegistry.def"553 });554 }555 556 // Module-level callbacks without LTO phase557 registerPipelineParsingCallback(558 [this](StringRef Name, ModulePassManager &PM,559 ArrayRef<PassBuilder::PipelineElement>) {560#define MODULE_CALLBACK(NAME, INVOKE) \561 if (PassBuilder::checkParametrizedPassName(Name, NAME)) { \562 auto L = PassBuilder::parsePassParameters(parseOptLevelParam, Name, NAME); \563 if (!L) { \564 errs() << NAME ": " << toString(L.takeError()) << '\n'; \565 return false; \566 } \567 INVOKE(PM, L.get()); \568 return true; \569 }570#include "PassRegistry.def"571 return false;572 });573 574 // Module-level callbacks with LTO phase (use Phase::None for string API)575 registerPipelineParsingCallback(576 [this](StringRef Name, ModulePassManager &PM,577 ArrayRef<PassBuilder::PipelineElement>) {578#define MODULE_LTO_CALLBACK(NAME, INVOKE) \579 if (PassBuilder::checkParametrizedPassName(Name, NAME)) { \580 auto L = PassBuilder::parsePassParameters(parseOptLevelParam, Name, NAME); \581 if (!L) { \582 errs() << NAME ": " << toString(L.takeError()) << '\n'; \583 return false; \584 } \585 INVOKE(PM, L.get(), ThinOrFullLTOPhase::None); \586 return true; \587 }588#include "PassRegistry.def"589 return false;590 });591 592 // Function-level callbacks593 registerPipelineParsingCallback(594 [this](StringRef Name, FunctionPassManager &PM,595 ArrayRef<PassBuilder::PipelineElement>) {596#define FUNCTION_CALLBACK(NAME, INVOKE) \597 if (PassBuilder::checkParametrizedPassName(Name, NAME)) { \598 auto L = PassBuilder::parsePassParameters(parseOptLevelParam, Name, NAME); \599 if (!L) { \600 errs() << NAME ": " << toString(L.takeError()) << '\n'; \601 return false; \602 } \603 INVOKE(PM, L.get()); \604 return true; \605 }606#include "PassRegistry.def"607 return false;608 });609 610 // CGSCC-level callbacks611 registerPipelineParsingCallback(612 [this](StringRef Name, CGSCCPassManager &PM,613 ArrayRef<PassBuilder::PipelineElement>) {614#define CGSCC_CALLBACK(NAME, INVOKE) \615 if (PassBuilder::checkParametrizedPassName(Name, NAME)) { \616 auto L = PassBuilder::parsePassParameters(parseOptLevelParam, Name, NAME); \617 if (!L) { \618 errs() << NAME ": " << toString(L.takeError()) << '\n'; \619 return false; \620 } \621 INVOKE(PM, L.get()); \622 return true; \623 }624#include "PassRegistry.def"625 return false;626 });627 628 // Loop-level callbacks629 registerPipelineParsingCallback(630 [this](StringRef Name, LoopPassManager &PM,631 ArrayRef<PassBuilder::PipelineElement>) {632#define LOOP_CALLBACK(NAME, INVOKE) \633 if (PassBuilder::checkParametrizedPassName(Name, NAME)) { \634 auto L = PassBuilder::parsePassParameters(parseOptLevelParam, Name, NAME); \635 if (!L) { \636 errs() << NAME ": " << toString(L.takeError()) << '\n'; \637 return false; \638 } \639 INVOKE(PM, L.get()); \640 return true; \641 }642#include "PassRegistry.def"643 return false;644 });645}646 647void PassBuilder::registerModuleAnalyses(ModuleAnalysisManager &MAM) {648#define MODULE_ANALYSIS(NAME, CREATE_PASS) \649 MAM.registerPass([&] { return CREATE_PASS; });650#include "PassRegistry.def"651 652 for (auto &C : ModuleAnalysisRegistrationCallbacks)653 C(MAM);654}655 656void PassBuilder::registerCGSCCAnalyses(CGSCCAnalysisManager &CGAM) {657#define CGSCC_ANALYSIS(NAME, CREATE_PASS) \658 CGAM.registerPass([&] { return CREATE_PASS; });659#include "PassRegistry.def"660 661 for (auto &C : CGSCCAnalysisRegistrationCallbacks)662 C(CGAM);663}664 665void PassBuilder::registerFunctionAnalyses(FunctionAnalysisManager &FAM) {666 // We almost always want the default alias analysis pipeline.667 // If a user wants a different one, they can register their own before calling668 // registerFunctionAnalyses().669 FAM.registerPass([&] { return buildDefaultAAPipeline(); });670 671#define FUNCTION_ANALYSIS(NAME, CREATE_PASS) \672 if constexpr (std::is_constructible_v< \673 std::remove_reference_t<decltype(CREATE_PASS)>, \674 const TargetMachine &>) { \675 if (TM) \676 FAM.registerPass([&] { return CREATE_PASS; }); \677 } else { \678 FAM.registerPass([&] { return CREATE_PASS; }); \679 }680#include "PassRegistry.def"681 682 for (auto &C : FunctionAnalysisRegistrationCallbacks)683 C(FAM);684}685 686void PassBuilder::registerMachineFunctionAnalyses(687 MachineFunctionAnalysisManager &MFAM) {688 689#define MACHINE_FUNCTION_ANALYSIS(NAME, CREATE_PASS) \690 MFAM.registerPass([&] { return CREATE_PASS; });691#include "llvm/Passes/MachinePassRegistry.def"692 693 for (auto &C : MachineFunctionAnalysisRegistrationCallbacks)694 C(MFAM);695}696 697void PassBuilder::registerLoopAnalyses(LoopAnalysisManager &LAM) {698#define LOOP_ANALYSIS(NAME, CREATE_PASS) \699 LAM.registerPass([&] { return CREATE_PASS; });700#include "PassRegistry.def"701 702 for (auto &C : LoopAnalysisRegistrationCallbacks)703 C(LAM);704}705 706static std::optional<std::pair<bool, bool>>707parseFunctionPipelineName(StringRef Name) {708 std::pair<bool, bool> Params;709 if (!Name.consume_front("function"))710 return std::nullopt;711 if (Name.empty())712 return Params;713 if (!Name.consume_front("<") || !Name.consume_back(">"))714 return std::nullopt;715 while (!Name.empty()) {716 auto [Front, Back] = Name.split(';');717 Name = Back;718 if (Front == "eager-inv")719 Params.first = true;720 else if (Front == "no-rerun")721 Params.second = true;722 else723 return std::nullopt;724 }725 return Params;726}727 728static std::optional<int> parseDevirtPassName(StringRef Name) {729 if (!Name.consume_front("devirt<") || !Name.consume_back(">"))730 return std::nullopt;731 int Count;732 if (Name.getAsInteger(0, Count) || Count < 0)733 return std::nullopt;734 return Count;735}736 737Expected<bool> PassBuilder::parseSinglePassOption(StringRef Params,738 StringRef OptionName,739 StringRef PassName) {740 bool Result = false;741 while (!Params.empty()) {742 StringRef ParamName;743 std::tie(ParamName, Params) = Params.split(';');744 745 if (ParamName == OptionName) {746 Result = true;747 } else {748 return make_error<StringError>(749 formatv("invalid {} pass parameter '{}'", PassName, ParamName).str(),750 inconvertibleErrorCode());751 }752 }753 return Result;754}755 756namespace {757 758/// Parser of parameters for HardwareLoops pass.759Expected<HardwareLoopOptions> parseHardwareLoopOptions(StringRef Params) {760 HardwareLoopOptions HardwareLoopOpts;761 762 while (!Params.empty()) {763 StringRef ParamName;764 std::tie(ParamName, Params) = Params.split(';');765 if (ParamName.consume_front("hardware-loop-decrement=")) {766 int Count;767 if (ParamName.getAsInteger(0, Count))768 return make_error<StringError>(769 formatv("invalid HardwareLoopPass parameter '{}'", ParamName).str(),770 inconvertibleErrorCode());771 HardwareLoopOpts.setDecrement(Count);772 continue;773 }774 if (ParamName.consume_front("hardware-loop-counter-bitwidth=")) {775 int Count;776 if (ParamName.getAsInteger(0, Count))777 return make_error<StringError>(778 formatv("invalid HardwareLoopPass parameter '{}'", ParamName).str(),779 inconvertibleErrorCode());780 HardwareLoopOpts.setCounterBitwidth(Count);781 continue;782 }783 if (ParamName == "force-hardware-loops") {784 HardwareLoopOpts.setForce(true);785 } else if (ParamName == "force-hardware-loop-phi") {786 HardwareLoopOpts.setForcePhi(true);787 } else if (ParamName == "force-nested-hardware-loop") {788 HardwareLoopOpts.setForceNested(true);789 } else if (ParamName == "force-hardware-loop-guard") {790 HardwareLoopOpts.setForceGuard(true);791 } else {792 return make_error<StringError>(793 formatv("invalid HardwarePass parameter '{}'", ParamName).str(),794 inconvertibleErrorCode());795 }796 }797 return HardwareLoopOpts;798}799 800/// Parser of parameters for Lint pass.801Expected<bool> parseLintOptions(StringRef Params) {802 return PassBuilder::parseSinglePassOption(Params, "abort-on-error",803 "LintPass");804}805 806/// Parser of parameters for LoopUnroll pass.807Expected<LoopUnrollOptions> parseLoopUnrollOptions(StringRef Params) {808 LoopUnrollOptions UnrollOpts;809 while (!Params.empty()) {810 StringRef ParamName;811 std::tie(ParamName, Params) = Params.split(';');812 std::optional<OptimizationLevel> OptLevel = parseOptLevel(ParamName);813 // Don't accept -Os/-Oz.814 if (OptLevel && !OptLevel->isOptimizingForSize()) {815 UnrollOpts.setOptLevel(OptLevel->getSpeedupLevel());816 continue;817 }818 if (ParamName.consume_front("full-unroll-max=")) {819 int Count;820 if (ParamName.getAsInteger(0, Count))821 return make_error<StringError>(822 formatv("invalid LoopUnrollPass parameter '{}'", ParamName).str(),823 inconvertibleErrorCode());824 UnrollOpts.setFullUnrollMaxCount(Count);825 continue;826 }827 828 bool Enable = !ParamName.consume_front("no-");829 if (ParamName == "partial") {830 UnrollOpts.setPartial(Enable);831 } else if (ParamName == "peeling") {832 UnrollOpts.setPeeling(Enable);833 } else if (ParamName == "profile-peeling") {834 UnrollOpts.setProfileBasedPeeling(Enable);835 } else if (ParamName == "runtime") {836 UnrollOpts.setRuntime(Enable);837 } else if (ParamName == "upperbound") {838 UnrollOpts.setUpperBound(Enable);839 } else {840 return make_error<StringError>(841 formatv("invalid LoopUnrollPass parameter '{}'", ParamName).str(),842 inconvertibleErrorCode());843 }844 }845 return UnrollOpts;846}847 848Expected<bool> parseGlobalDCEPassOptions(StringRef Params) {849 return PassBuilder::parseSinglePassOption(850 Params, "vfe-linkage-unit-visibility", "GlobalDCE");851}852 853Expected<bool> parseCGProfilePassOptions(StringRef Params) {854 return PassBuilder::parseSinglePassOption(Params, "in-lto-post-link",855 "CGProfile");856}857 858Expected<bool> parseInlinerPassOptions(StringRef Params) {859 return PassBuilder::parseSinglePassOption(Params, "only-mandatory",860 "InlinerPass");861}862 863Expected<bool> parseCoroSplitPassOptions(StringRef Params) {864 return PassBuilder::parseSinglePassOption(Params, "reuse-storage",865 "CoroSplitPass");866}867 868Expected<bool> parsePostOrderFunctionAttrsPassOptions(StringRef Params) {869 return PassBuilder::parseSinglePassOption(870 Params, "skip-non-recursive-function-attrs", "PostOrderFunctionAttrs");871}872 873Expected<CFGuardPass::Mechanism> parseCFGuardPassOptions(StringRef Params) {874 if (Params.empty())875 return CFGuardPass::Mechanism::Check;876 877 auto [Param, RHS] = Params.split(';');878 if (!RHS.empty())879 return make_error<StringError>(880 formatv("too many CFGuardPass parameters '{}'", Params).str(),881 inconvertibleErrorCode());882 883 if (Param == "check")884 return CFGuardPass::Mechanism::Check;885 if (Param == "dispatch")886 return CFGuardPass::Mechanism::Dispatch;887 888 return make_error<StringError>(889 formatv("invalid CFGuardPass mechanism: '{}'", Param).str(),890 inconvertibleErrorCode());891}892 893Expected<bool> parseEarlyCSEPassOptions(StringRef Params) {894 return PassBuilder::parseSinglePassOption(Params, "memssa", "EarlyCSE");895}896 897Expected<bool> parseEntryExitInstrumenterPassOptions(StringRef Params) {898 return PassBuilder::parseSinglePassOption(Params, "post-inline",899 "EntryExitInstrumenter");900}901 902Expected<bool> parseDropUnnecessaryAssumesPassOptions(StringRef Params) {903 return PassBuilder::parseSinglePassOption(Params, "drop-deref",904 "DropUnnecessaryAssumes");905}906 907Expected<bool> parseLoopExtractorPassOptions(StringRef Params) {908 return PassBuilder::parseSinglePassOption(Params, "single", "LoopExtractor");909}910 911Expected<bool> parseLowerMatrixIntrinsicsPassOptions(StringRef Params) {912 return PassBuilder::parseSinglePassOption(Params, "minimal",913 "LowerMatrixIntrinsics");914}915 916Expected<IRNormalizerOptions> parseIRNormalizerPassOptions(StringRef Params) {917 IRNormalizerOptions Result;918 while (!Params.empty()) {919 StringRef ParamName;920 std::tie(ParamName, Params) = Params.split(';');921 922 bool Enable = !ParamName.consume_front("no-");923 if (ParamName == "preserve-order")924 Result.PreserveOrder = Enable;925 else if (ParamName == "rename-all")926 Result.RenameAll = Enable;927 else if (ParamName == "fold-all") // FIXME: Name mismatch928 Result.FoldPreOutputs = Enable;929 else if (ParamName == "reorder-operands")930 Result.ReorderOperands = Enable;931 else {932 return make_error<StringError>(933 formatv("invalid normalize pass parameter '{}'", ParamName).str(),934 inconvertibleErrorCode());935 }936 }937 938 return Result;939}940 941Expected<AddressSanitizerOptions> parseASanPassOptions(StringRef Params) {942 AddressSanitizerOptions Result;943 while (!Params.empty()) {944 StringRef ParamName;945 std::tie(ParamName, Params) = Params.split(';');946 947 if (ParamName == "kernel") {948 Result.CompileKernel = true;949 } else if (ParamName == "use-after-scope") {950 Result.UseAfterScope = true;951 } else {952 return make_error<StringError>(953 formatv("invalid AddressSanitizer pass parameter '{}'", ParamName)954 .str(),955 inconvertibleErrorCode());956 }957 }958 return Result;959}960 961Expected<HWAddressSanitizerOptions> parseHWASanPassOptions(StringRef Params) {962 HWAddressSanitizerOptions Result;963 while (!Params.empty()) {964 StringRef ParamName;965 std::tie(ParamName, Params) = Params.split(';');966 967 if (ParamName == "recover") {968 Result.Recover = true;969 } else if (ParamName == "kernel") {970 Result.CompileKernel = true;971 } else {972 return make_error<StringError>(973 formatv("invalid HWAddressSanitizer pass parameter '{}'", ParamName)974 .str(),975 inconvertibleErrorCode());976 }977 }978 return Result;979}980 981Expected<EmbedBitcodeOptions> parseEmbedBitcodePassOptions(StringRef Params) {982 EmbedBitcodeOptions Result;983 while (!Params.empty()) {984 StringRef ParamName;985 std::tie(ParamName, Params) = Params.split(';');986 987 if (ParamName == "thinlto") {988 Result.IsThinLTO = true;989 } else if (ParamName == "emit-summary") {990 Result.EmitLTOSummary = true;991 } else {992 return make_error<StringError>(993 formatv("invalid EmbedBitcode pass parameter '{}'", ParamName).str(),994 inconvertibleErrorCode());995 }996 }997 return Result;998}999 1000Expected<LowerAllowCheckPass::Options>1001parseLowerAllowCheckPassOptions(StringRef Params) {1002 LowerAllowCheckPass::Options Result;1003 while (!Params.empty()) {1004 StringRef ParamName;1005 std::tie(ParamName, Params) = Params.split(';');1006 1007 // Format is <cutoffs[1,2,3]=70000;cutoffs[5,6,8]=90000>1008 //1009 // Parsing allows duplicate indices (last one takes precedence).1010 // It would technically be in spec to specify1011 // cutoffs[0]=70000,cutoffs[1]=90000,cutoffs[0]=80000,...1012 if (ParamName.starts_with("cutoffs[")) {1013 StringRef IndicesStr;1014 StringRef CutoffStr;1015 1016 std::tie(IndicesStr, CutoffStr) = ParamName.split("]=");1017 // cutoffs[1,2,31018 // 700001019 1020 int cutoff;1021 if (CutoffStr.getAsInteger(0, cutoff))1022 return make_error<StringError>(1023 formatv("invalid LowerAllowCheck pass cutoffs parameter '{}' ({})",1024 CutoffStr, Params)1025 .str(),1026 inconvertibleErrorCode());1027 1028 if (!IndicesStr.consume_front("cutoffs[") || IndicesStr == "")1029 return make_error<StringError>(1030 formatv("invalid LowerAllowCheck pass index parameter '{}' ({})",1031 IndicesStr, CutoffStr)1032 .str(),1033 inconvertibleErrorCode());1034 1035 while (IndicesStr != "") {1036 StringRef firstIndexStr;1037 std::tie(firstIndexStr, IndicesStr) = IndicesStr.split('|');1038 1039 unsigned int index;1040 if (firstIndexStr.getAsInteger(0, index))1041 return make_error<StringError>(1042 formatv(1043 "invalid LowerAllowCheck pass index parameter '{}' ({}) {}",1044 firstIndexStr, IndicesStr)1045 .str(),1046 inconvertibleErrorCode());1047 1048 // In the common case (sequentially increasing indices), we will issue1049 // O(n) resize requests. We assume the underlying data structure has1050 // O(1) runtime for each added element.1051 if (index >= Result.cutoffs.size())1052 Result.cutoffs.resize(index + 1, 0);1053 1054 Result.cutoffs[index] = cutoff;1055 }1056 } else if (ParamName.starts_with("runtime_check")) {1057 StringRef ValueString;1058 std::tie(std::ignore, ValueString) = ParamName.split("=");1059 int runtime_check;1060 if (ValueString.getAsInteger(0, runtime_check)) {1061 return make_error<StringError>(1062 formatv("invalid LowerAllowCheck pass runtime_check parameter '{}' "1063 "({})",1064 ValueString, Params)1065 .str(),1066 inconvertibleErrorCode());1067 }1068 Result.runtime_check = runtime_check;1069 } else {1070 return make_error<StringError>(1071 formatv("invalid LowerAllowCheck pass parameter '{}'", ParamName)1072 .str(),1073 inconvertibleErrorCode());1074 }1075 }1076 1077 return Result;1078}1079 1080Expected<MemorySanitizerOptions> parseMSanPassOptions(StringRef Params) {1081 MemorySanitizerOptions Result;1082 while (!Params.empty()) {1083 StringRef ParamName;1084 std::tie(ParamName, Params) = Params.split(';');1085 1086 if (ParamName == "recover") {1087 Result.Recover = true;1088 } else if (ParamName == "kernel") {1089 Result.Kernel = true;1090 } else if (ParamName.consume_front("track-origins=")) {1091 if (ParamName.getAsInteger(0, Result.TrackOrigins))1092 return make_error<StringError>(1093 formatv("invalid argument to MemorySanitizer pass track-origins "1094 "parameter: '{}'",1095 ParamName)1096 .str(),1097 inconvertibleErrorCode());1098 } else if (ParamName == "eager-checks") {1099 Result.EagerChecks = true;1100 } else {1101 return make_error<StringError>(1102 formatv("invalid MemorySanitizer pass parameter '{}'", ParamName)1103 .str(),1104 inconvertibleErrorCode());1105 }1106 }1107 return Result;1108}1109 1110Expected<AllocTokenOptions> parseAllocTokenPassOptions(StringRef Params) {1111 AllocTokenOptions Result;1112 while (!Params.empty()) {1113 StringRef ParamName;1114 std::tie(ParamName, Params) = Params.split(';');1115 1116 if (ParamName.consume_front("mode=")) {1117 if (auto Mode = getAllocTokenModeFromString(ParamName))1118 Result.Mode = *Mode;1119 else1120 return make_error<StringError>(1121 formatv("invalid argument to AllocToken pass mode "1122 "parameter: '{}'",1123 ParamName)1124 .str(),1125 inconvertibleErrorCode());1126 } else {1127 return make_error<StringError>(1128 formatv("invalid AllocToken pass parameter '{}'", ParamName).str(),1129 inconvertibleErrorCode());1130 }1131 }1132 return Result;1133}1134 1135/// Parser of parameters for SimplifyCFG pass.1136Expected<SimplifyCFGOptions> parseSimplifyCFGOptions(StringRef Params) {1137 SimplifyCFGOptions Result;1138 while (!Params.empty()) {1139 StringRef ParamName;1140 std::tie(ParamName, Params) = Params.split(';');1141 1142 bool Enable = !ParamName.consume_front("no-");1143 if (ParamName == "speculate-blocks") {1144 Result.speculateBlocks(Enable);1145 } else if (ParamName == "simplify-cond-branch") {1146 Result.setSimplifyCondBranch(Enable);1147 } else if (ParamName == "forward-switch-cond") {1148 Result.forwardSwitchCondToPhi(Enable);1149 } else if (ParamName == "switch-range-to-icmp") {1150 Result.convertSwitchRangeToICmp(Enable);1151 } else if (ParamName == "switch-to-arithmetic") {1152 Result.convertSwitchToArithmetic(Enable);1153 } else if (ParamName == "switch-to-lookup") {1154 Result.convertSwitchToLookupTable(Enable);1155 } else if (ParamName == "keep-loops") {1156 Result.needCanonicalLoops(Enable);1157 } else if (ParamName == "hoist-common-insts") {1158 Result.hoistCommonInsts(Enable);1159 } else if (ParamName == "hoist-loads-stores-with-cond-faulting") {1160 Result.hoistLoadsStoresWithCondFaulting(Enable);1161 } else if (ParamName == "sink-common-insts") {1162 Result.sinkCommonInsts(Enable);1163 } else if (ParamName == "speculate-unpredictables") {1164 Result.speculateUnpredictables(Enable);1165 } else if (Enable && ParamName.consume_front("bonus-inst-threshold=")) {1166 APInt BonusInstThreshold;1167 if (ParamName.getAsInteger(0, BonusInstThreshold))1168 return make_error<StringError>(1169 formatv("invalid argument to SimplifyCFG pass bonus-threshold "1170 "parameter: '{}'",1171 ParamName)1172 .str(),1173 inconvertibleErrorCode());1174 Result.bonusInstThreshold(BonusInstThreshold.getSExtValue());1175 } else {1176 return make_error<StringError>(1177 formatv("invalid SimplifyCFG pass parameter '{}'", ParamName).str(),1178 inconvertibleErrorCode());1179 }1180 }1181 return Result;1182}1183 1184Expected<InstCombineOptions> parseInstCombineOptions(StringRef Params) {1185 InstCombineOptions Result;1186 // When specifying "instcombine" in -passes enable fix-point verification by1187 // default, as this is what most tests should use.1188 Result.setVerifyFixpoint(true);1189 while (!Params.empty()) {1190 StringRef ParamName;1191 std::tie(ParamName, Params) = Params.split(';');1192 1193 bool Enable = !ParamName.consume_front("no-");1194 if (ParamName == "verify-fixpoint") {1195 Result.setVerifyFixpoint(Enable);1196 } else if (Enable && ParamName.consume_front("max-iterations=")) {1197 APInt MaxIterations;1198 if (ParamName.getAsInteger(0, MaxIterations))1199 return make_error<StringError>(1200 formatv("invalid argument to InstCombine pass max-iterations "1201 "parameter: '{}'",1202 ParamName)1203 .str(),1204 inconvertibleErrorCode());1205 Result.setMaxIterations((unsigned)MaxIterations.getZExtValue());1206 } else {1207 return make_error<StringError>(1208 formatv("invalid InstCombine pass parameter '{}'", ParamName).str(),1209 inconvertibleErrorCode());1210 }1211 }1212 return Result;1213}1214 1215/// Parser of parameters for LoopVectorize pass.1216Expected<LoopVectorizeOptions> parseLoopVectorizeOptions(StringRef Params) {1217 LoopVectorizeOptions Opts;1218 while (!Params.empty()) {1219 StringRef ParamName;1220 std::tie(ParamName, Params) = Params.split(';');1221 1222 bool Enable = !ParamName.consume_front("no-");1223 if (ParamName == "interleave-forced-only") {1224 Opts.setInterleaveOnlyWhenForced(Enable);1225 } else if (ParamName == "vectorize-forced-only") {1226 Opts.setVectorizeOnlyWhenForced(Enable);1227 } else {1228 return make_error<StringError>(1229 formatv("invalid LoopVectorize parameter '{}'", ParamName).str(),1230 inconvertibleErrorCode());1231 }1232 }1233 return Opts;1234}1235 1236Expected<std::pair<bool, bool>> parseLoopUnswitchOptions(StringRef Params) {1237 std::pair<bool, bool> Result = {false, true};1238 while (!Params.empty()) {1239 StringRef ParamName;1240 std::tie(ParamName, Params) = Params.split(';');1241 1242 bool Enable = !ParamName.consume_front("no-");1243 if (ParamName == "nontrivial") {1244 Result.first = Enable;1245 } else if (ParamName == "trivial") {1246 Result.second = Enable;1247 } else {1248 return make_error<StringError>(1249 formatv("invalid LoopUnswitch pass parameter '{}'", ParamName).str(),1250 inconvertibleErrorCode());1251 }1252 }1253 return Result;1254}1255 1256Expected<LICMOptions> parseLICMOptions(StringRef Params) {1257 LICMOptions Result;1258 while (!Params.empty()) {1259 StringRef ParamName;1260 std::tie(ParamName, Params) = Params.split(';');1261 1262 bool Enable = !ParamName.consume_front("no-");1263 if (ParamName == "allowspeculation") {1264 Result.AllowSpeculation = Enable;1265 } else {1266 return make_error<StringError>(1267 formatv("invalid LICM pass parameter '{}'", ParamName).str(),1268 inconvertibleErrorCode());1269 }1270 }1271 return Result;1272}1273 1274Expected<std::pair<bool, bool>> parseLoopRotateOptions(StringRef Params) {1275 std::pair<bool, bool> Result = {true, false};1276 while (!Params.empty()) {1277 StringRef ParamName;1278 std::tie(ParamName, Params) = Params.split(';');1279 1280 bool Enable = !ParamName.consume_front("no-");1281 if (ParamName == "header-duplication") {1282 Result.first = Enable;1283 } else if (ParamName == "prepare-for-lto") {1284 Result.second = Enable;1285 } else {1286 return make_error<StringError>(1287 formatv("invalid LoopRotate pass parameter '{}'", ParamName).str(),1288 inconvertibleErrorCode());1289 }1290 }1291 return Result;1292}1293 1294Expected<bool> parseMergedLoadStoreMotionOptions(StringRef Params) {1295 bool Result = false;1296 while (!Params.empty()) {1297 StringRef ParamName;1298 std::tie(ParamName, Params) = Params.split(';');1299 1300 bool Enable = !ParamName.consume_front("no-");1301 if (ParamName == "split-footer-bb") {1302 Result = Enable;1303 } else {1304 return make_error<StringError>(1305 formatv("invalid MergedLoadStoreMotion pass parameter '{}'",1306 ParamName)1307 .str(),1308 inconvertibleErrorCode());1309 }1310 }1311 return Result;1312}1313 1314Expected<GVNOptions> parseGVNOptions(StringRef Params) {1315 GVNOptions Result;1316 while (!Params.empty()) {1317 StringRef ParamName;1318 std::tie(ParamName, Params) = Params.split(';');1319 1320 bool Enable = !ParamName.consume_front("no-");1321 if (ParamName == "pre") {1322 Result.setPRE(Enable);1323 } else if (ParamName == "load-pre") {1324 Result.setLoadPRE(Enable);1325 } else if (ParamName == "split-backedge-load-pre") {1326 Result.setLoadPRESplitBackedge(Enable);1327 } else if (ParamName == "memdep") {1328 // MemDep and MemorySSA are mutually exclusive.1329 Result.setMemDep(Enable);1330 Result.setMemorySSA(!Enable);1331 } else if (ParamName == "memoryssa") {1332 // MemDep and MemorySSA are mutually exclusive.1333 Result.setMemorySSA(Enable);1334 Result.setMemDep(!Enable);1335 } else {1336 return make_error<StringError>(1337 formatv("invalid GVN pass parameter '{}'", ParamName).str(),1338 inconvertibleErrorCode());1339 }1340 }1341 return Result;1342}1343 1344Expected<IPSCCPOptions> parseIPSCCPOptions(StringRef Params) {1345 IPSCCPOptions Result;1346 while (!Params.empty()) {1347 StringRef ParamName;1348 std::tie(ParamName, Params) = Params.split(';');1349 1350 bool Enable = !ParamName.consume_front("no-");1351 if (ParamName == "func-spec")1352 Result.setFuncSpec(Enable);1353 else1354 return make_error<StringError>(1355 formatv("invalid IPSCCP pass parameter '{}'", ParamName).str(),1356 inconvertibleErrorCode());1357 }1358 return Result;1359}1360 1361Expected<ScalarizerPassOptions> parseScalarizerOptions(StringRef Params) {1362 ScalarizerPassOptions Result;1363 while (!Params.empty()) {1364 StringRef ParamName;1365 std::tie(ParamName, Params) = Params.split(';');1366 1367 if (ParamName.consume_front("min-bits=")) {1368 if (ParamName.getAsInteger(0, Result.ScalarizeMinBits)) {1369 return make_error<StringError>(1370 formatv("invalid argument to Scalarizer pass min-bits "1371 "parameter: '{}'",1372 ParamName)1373 .str(),1374 inconvertibleErrorCode());1375 }1376 1377 continue;1378 }1379 1380 bool Enable = !ParamName.consume_front("no-");1381 if (ParamName == "load-store")1382 Result.ScalarizeLoadStore = Enable;1383 else if (ParamName == "variable-insert-extract")1384 Result.ScalarizeVariableInsertExtract = Enable;1385 else {1386 return make_error<StringError>(1387 formatv("invalid Scalarizer pass parameter '{}'", ParamName).str(),1388 inconvertibleErrorCode());1389 }1390 }1391 1392 return Result;1393}1394 1395Expected<SROAOptions> parseSROAOptions(StringRef Params) {1396 if (Params.empty() || Params == "modify-cfg")1397 return SROAOptions::ModifyCFG;1398 if (Params == "preserve-cfg")1399 return SROAOptions::PreserveCFG;1400 return make_error<StringError>(1401 formatv("invalid SROA pass parameter '{}' (either preserve-cfg or "1402 "modify-cfg can be specified)",1403 Params)1404 .str(),1405 inconvertibleErrorCode());1406}1407 1408Expected<StackLifetime::LivenessType>1409parseStackLifetimeOptions(StringRef Params) {1410 StackLifetime::LivenessType Result = StackLifetime::LivenessType::May;1411 while (!Params.empty()) {1412 StringRef ParamName;1413 std::tie(ParamName, Params) = Params.split(';');1414 1415 if (ParamName == "may") {1416 Result = StackLifetime::LivenessType::May;1417 } else if (ParamName == "must") {1418 Result = StackLifetime::LivenessType::Must;1419 } else {1420 return make_error<StringError>(1421 formatv("invalid StackLifetime parameter '{}'", ParamName).str(),1422 inconvertibleErrorCode());1423 }1424 }1425 return Result;1426}1427 1428Expected<bool> parseDependenceAnalysisPrinterOptions(StringRef Params) {1429 return PassBuilder::parseSinglePassOption(Params, "normalized-results",1430 "DependenceAnalysisPrinter");1431}1432 1433Expected<bool> parseSeparateConstOffsetFromGEPPassOptions(StringRef Params) {1434 return PassBuilder::parseSinglePassOption(Params, "lower-gep",1435 "SeparateConstOffsetFromGEP");1436}1437 1438Expected<bool> parseStructurizeCFGPassOptions(StringRef Params) {1439 return PassBuilder::parseSinglePassOption(Params, "skip-uniform-regions",1440 "StructurizeCFG");1441}1442 1443Expected<OptimizationLevel>1444parseFunctionSimplificationPipelineOptions(StringRef Params) {1445 std::optional<OptimizationLevel> L = parseOptLevel(Params);1446 if (!L || *L == OptimizationLevel::O0) {1447 return make_error<StringError>(1448 formatv("invalid function-simplification parameter '{}'", Params).str(),1449 inconvertibleErrorCode());1450 };1451 return *L;1452}1453 1454Expected<bool> parseMemorySSAPrinterPassOptions(StringRef Params) {1455 return PassBuilder::parseSinglePassOption(Params, "no-ensure-optimized-uses",1456 "MemorySSAPrinterPass");1457}1458 1459Expected<bool> parseSpeculativeExecutionPassOptions(StringRef Params) {1460 return PassBuilder::parseSinglePassOption(Params, "only-if-divergent-target",1461 "SpeculativeExecutionPass");1462}1463 1464Expected<std::string> parseMemProfUsePassOptions(StringRef Params) {1465 std::string Result;1466 while (!Params.empty()) {1467 StringRef ParamName;1468 std::tie(ParamName, Params) = Params.split(';');1469 1470 if (ParamName.consume_front("profile-filename=")) {1471 Result = ParamName.str();1472 } else {1473 return make_error<StringError>(1474 formatv("invalid MemProfUse pass parameter '{}'", ParamName).str(),1475 inconvertibleErrorCode());1476 }1477 }1478 return Result;1479}1480 1481Expected<StructuralHashOptions>1482parseStructuralHashPrinterPassOptions(StringRef Params) {1483 if (Params.empty())1484 return StructuralHashOptions::None;1485 if (Params == "detailed")1486 return StructuralHashOptions::Detailed;1487 if (Params == "call-target-ignored")1488 return StructuralHashOptions::CallTargetIgnored;1489 return make_error<StringError>(1490 formatv("invalid structural hash printer parameter '{}'", Params).str(),1491 inconvertibleErrorCode());1492}1493 1494Expected<bool> parseWinEHPrepareOptions(StringRef Params) {1495 return PassBuilder::parseSinglePassOption(Params, "demote-catchswitch-only",1496 "WinEHPreparePass");1497}1498 1499Expected<GlobalMergeOptions> parseGlobalMergeOptions(StringRef Params) {1500 GlobalMergeOptions Result;1501 while (!Params.empty()) {1502 StringRef ParamName;1503 std::tie(ParamName, Params) = Params.split(';');1504 1505 bool Enable = !ParamName.consume_front("no-");1506 if (ParamName == "group-by-use")1507 Result.GroupByUse = Enable;1508 else if (ParamName == "ignore-single-use")1509 Result.IgnoreSingleUse = Enable;1510 else if (ParamName == "merge-const")1511 Result.MergeConstantGlobals = Enable;1512 else if (ParamName == "merge-const-aggressive")1513 Result.MergeConstAggressive = Enable;1514 else if (ParamName == "merge-external")1515 Result.MergeExternal = Enable;1516 else if (ParamName.consume_front("max-offset=")) {1517 if (ParamName.getAsInteger(0, Result.MaxOffset))1518 return make_error<StringError>(1519 formatv("invalid GlobalMergePass parameter '{}'", ParamName).str(),1520 inconvertibleErrorCode());1521 } else {1522 return make_error<StringError>(1523 formatv("invalid global-merge pass parameter '{}'", Params).str(),1524 inconvertibleErrorCode());1525 }1526 }1527 return Result;1528}1529 1530Expected<SmallVector<std::string, 0>> parseInternalizeGVs(StringRef Params) {1531 SmallVector<std::string, 1> PreservedGVs;1532 while (!Params.empty()) {1533 StringRef ParamName;1534 std::tie(ParamName, Params) = Params.split(';');1535 1536 if (ParamName.consume_front("preserve-gv=")) {1537 PreservedGVs.push_back(ParamName.str());1538 } else {1539 return make_error<StringError>(1540 formatv("invalid Internalize pass parameter '{}'", ParamName).str(),1541 inconvertibleErrorCode());1542 }1543 }1544 1545 return Expected<SmallVector<std::string, 0>>(std::move(PreservedGVs));1546}1547 1548Expected<RegAllocFastPass::Options>1549parseRegAllocFastPassOptions(PassBuilder &PB, StringRef Params) {1550 RegAllocFastPass::Options Opts;1551 while (!Params.empty()) {1552 StringRef ParamName;1553 std::tie(ParamName, Params) = Params.split(';');1554 1555 if (ParamName.consume_front("filter=")) {1556 std::optional<RegAllocFilterFunc> Filter =1557 PB.parseRegAllocFilter(ParamName);1558 if (!Filter) {1559 return make_error<StringError>(1560 formatv("invalid regallocfast register filter '{}'", ParamName)1561 .str(),1562 inconvertibleErrorCode());1563 }1564 Opts.Filter = *Filter;1565 Opts.FilterName = ParamName;1566 continue;1567 }1568 1569 if (ParamName == "no-clear-vregs") {1570 Opts.ClearVRegs = false;1571 continue;1572 }1573 1574 return make_error<StringError>(1575 formatv("invalid regallocfast pass parameter '{}'", ParamName).str(),1576 inconvertibleErrorCode());1577 }1578 return Opts;1579}1580 1581Expected<BoundsCheckingPass::Options>1582parseBoundsCheckingOptions(StringRef Params) {1583 BoundsCheckingPass::Options Options;1584 while (!Params.empty()) {1585 StringRef ParamName;1586 std::tie(ParamName, Params) = Params.split(';');1587 if (ParamName == "trap") {1588 Options.Rt = std::nullopt;1589 } else if (ParamName == "rt") {1590 Options.Rt = {1591 /*MinRuntime=*/false,1592 /*MayReturn=*/true,1593 /*HandlerPreserveAllRegs=*/false,1594 };1595 } else if (ParamName == "rt-abort") {1596 Options.Rt = {1597 /*MinRuntime=*/false,1598 /*MayReturn=*/false,1599 /*HandlerPreserveAllRegs=*/false,1600 };1601 } else if (ParamName == "min-rt") {1602 Options.Rt = {1603 /*MinRuntime=*/true,1604 /*MayReturn=*/true,1605 /*HandlerPreserveAllRegs=*/false,1606 };1607 } else if (ParamName == "min-rt-abort") {1608 Options.Rt = {1609 /*MinRuntime=*/true,1610 /*MayReturn=*/false,1611 /*HandlerPreserveAllRegs=*/false,1612 };1613 } else if (ParamName == "merge") {1614 Options.Merge = true;1615 } else if (ParamName == "handler-preserve-all-regs") {1616 if (Options.Rt)1617 Options.Rt->HandlerPreserveAllRegs = true;1618 } else {1619 StringRef ParamEQ;1620 StringRef Val;1621 std::tie(ParamEQ, Val) = ParamName.split('=');1622 int8_t Id;1623 if (ParamEQ == "guard" && !Val.getAsInteger(0, Id)) {1624 Options.GuardKind = Id;1625 } else {1626 return make_error<StringError>(1627 formatv("invalid BoundsChecking pass parameter '{}'", ParamName)1628 .str(),1629 inconvertibleErrorCode());1630 }1631 }1632 }1633 return Options;1634}1635 1636Expected<CodeGenOptLevel> parseExpandFpOptions(StringRef Param) {1637 if (Param.empty())1638 return CodeGenOptLevel::None;1639 1640 // Parse a CodeGenOptLevel, e.g. "O1", "O2", "O3".1641 auto [Prefix, Digit] = Param.split('O');1642 1643 uint8_t N;1644 if (!Prefix.empty() || Digit.getAsInteger(10, N))1645 return createStringError("invalid expand-fp pass parameter '%s'",1646 Param.str().c_str());1647 1648 std::optional<CodeGenOptLevel> Level = CodeGenOpt::getLevel(N);1649 if (!Level.has_value())1650 return createStringError(1651 "invalid optimization level for expand-fp pass: %s",1652 Digit.str().c_str());1653 1654 return *Level;1655}1656 1657Expected<RAGreedyPass::Options>1658parseRegAllocGreedyFilterFunc(PassBuilder &PB, StringRef Params) {1659 if (Params.empty() || Params == "all")1660 return RAGreedyPass::Options();1661 1662 std::optional<RegAllocFilterFunc> Filter = PB.parseRegAllocFilter(Params);1663 if (Filter)1664 return RAGreedyPass::Options{*Filter, Params};1665 1666 return make_error<StringError>(1667 formatv("invalid regallocgreedy register filter '{}'", Params).str(),1668 inconvertibleErrorCode());1669}1670 1671Expected<bool> parseMachineSinkingPassOptions(StringRef Params) {1672 return PassBuilder::parseSinglePassOption(Params, "enable-sink-fold",1673 "MachineSinkingPass");1674}1675 1676Expected<bool> parseMachineBlockPlacementPassOptions(StringRef Params) {1677 bool AllowTailMerge = true;1678 if (!Params.empty()) {1679 AllowTailMerge = !Params.consume_front("no-");1680 if (Params != "tail-merge")1681 return make_error<StringError>(1682 formatv("invalid MachineBlockPlacementPass parameter '{}'", Params)1683 .str(),1684 inconvertibleErrorCode());1685 }1686 return AllowTailMerge;1687}1688 1689Expected<bool> parseVirtRegRewriterPassOptions(StringRef Params) {1690 bool ClearVirtRegs = true;1691 if (!Params.empty()) {1692 ClearVirtRegs = !Params.consume_front("no-");1693 if (Params != "clear-vregs")1694 return make_error<StringError>(1695 formatv("invalid VirtRegRewriter pass parameter '{}'", Params).str(),1696 inconvertibleErrorCode());1697 }1698 return ClearVirtRegs;1699}1700 1701struct FatLTOOptions {1702 OptimizationLevel OptLevel;1703 bool ThinLTO = false;1704 bool EmitSummary = false;1705};1706 1707Expected<FatLTOOptions> parseFatLTOOptions(StringRef Params) {1708 FatLTOOptions Result;1709 bool HaveOptLevel = false;1710 while (!Params.empty()) {1711 StringRef ParamName;1712 std::tie(ParamName, Params) = Params.split(';');1713 1714 if (ParamName == "thinlto") {1715 Result.ThinLTO = true;1716 } else if (ParamName == "emit-summary") {1717 Result.EmitSummary = true;1718 } else if (std::optional<OptimizationLevel> OptLevel =1719 parseOptLevel(ParamName)) {1720 Result.OptLevel = *OptLevel;1721 HaveOptLevel = true;1722 } else {1723 return make_error<StringError>(1724 formatv("invalid fatlto-pre-link pass parameter '{}'", ParamName)1725 .str(),1726 inconvertibleErrorCode());1727 }1728 }1729 if (!HaveOptLevel)1730 return make_error<StringError>(1731 "missing optimization level for fatlto-pre-link pipeline",1732 inconvertibleErrorCode());1733 return Result;1734}1735 1736} // namespace1737 1738/// Tests whether registered callbacks will accept a given pass name.1739///1740/// When parsing a pipeline text, the type of the outermost pipeline may be1741/// omitted, in which case the type is automatically determined from the first1742/// pass name in the text. This may be a name that is handled through one of the1743/// callbacks. We check this through the oridinary parsing callbacks by setting1744/// up a dummy PassManager in order to not force the client to also handle this1745/// type of query.1746template <typename PassManagerT, typename CallbacksT>1747static bool callbacksAcceptPassName(StringRef Name, CallbacksT &Callbacks) {1748 if (!Callbacks.empty()) {1749 PassManagerT DummyPM;1750 for (auto &CB : Callbacks)1751 if (CB(Name, DummyPM, {}))1752 return true;1753 }1754 return false;1755}1756 1757template <typename CallbacksT>1758static bool isModulePassName(StringRef Name, CallbacksT &Callbacks) {1759 StringRef NameNoBracket = Name.take_until([](char C) { return C == '<'; });1760 1761 // Explicitly handle pass manager names.1762 if (Name == "module")1763 return true;1764 if (Name == "cgscc")1765 return true;1766 if (NameNoBracket == "function")1767 return true;1768 if (Name == "coro-cond")1769 return true;1770 1771#define MODULE_PASS(NAME, CREATE_PASS) \1772 if (Name == NAME) \1773 return true;1774#define MODULE_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \1775 if (PassBuilder::checkParametrizedPassName(Name, NAME)) \1776 return true;1777#define MODULE_ANALYSIS(NAME, CREATE_PASS) \1778 if (Name == "require<" NAME ">" || Name == "invalidate<" NAME ">") \1779 return true;1780#include "PassRegistry.def"1781 1782 return callbacksAcceptPassName<ModulePassManager>(Name, Callbacks);1783}1784 1785template <typename CallbacksT>1786static bool isCGSCCPassName(StringRef Name, CallbacksT &Callbacks) {1787 // Explicitly handle pass manager names.1788 StringRef NameNoBracket = Name.take_until([](char C) { return C == '<'; });1789 if (Name == "cgscc")1790 return true;1791 if (NameNoBracket == "function")1792 return true;1793 1794 // Explicitly handle custom-parsed pass names.1795 if (parseDevirtPassName(Name))1796 return true;1797 1798#define CGSCC_PASS(NAME, CREATE_PASS) \1799 if (Name == NAME) \1800 return true;1801#define CGSCC_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \1802 if (PassBuilder::checkParametrizedPassName(Name, NAME)) \1803 return true;1804#define CGSCC_ANALYSIS(NAME, CREATE_PASS) \1805 if (Name == "require<" NAME ">" || Name == "invalidate<" NAME ">") \1806 return true;1807#include "PassRegistry.def"1808 1809 return callbacksAcceptPassName<CGSCCPassManager>(Name, Callbacks);1810}1811 1812template <typename CallbacksT>1813static bool isFunctionPassName(StringRef Name, CallbacksT &Callbacks) {1814 // Explicitly handle pass manager names.1815 StringRef NameNoBracket = Name.take_until([](char C) { return C == '<'; });1816 if (NameNoBracket == "function")1817 return true;1818 if (Name == "loop" || Name == "loop-mssa" || Name == "machine-function")1819 return true;1820 1821#define FUNCTION_PASS(NAME, CREATE_PASS) \1822 if (Name == NAME) \1823 return true;1824#define FUNCTION_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \1825 if (PassBuilder::checkParametrizedPassName(Name, NAME)) \1826 return true;1827#define FUNCTION_ANALYSIS(NAME, CREATE_PASS) \1828 if (Name == "require<" NAME ">" || Name == "invalidate<" NAME ">") \1829 return true;1830#include "PassRegistry.def"1831 1832 return callbacksAcceptPassName<FunctionPassManager>(Name, Callbacks);1833}1834 1835template <typename CallbacksT>1836static bool isMachineFunctionPassName(StringRef Name, CallbacksT &Callbacks) {1837 // Explicitly handle pass manager names.1838 if (Name == "machine-function")1839 return true;1840 1841#define MACHINE_FUNCTION_PASS(NAME, CREATE_PASS) \1842 if (Name == NAME) \1843 return true;1844#define MACHINE_FUNCTION_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, \1845 PARAMS) \1846 if (PassBuilder::checkParametrizedPassName(Name, NAME)) \1847 return true;1848 1849#define MACHINE_FUNCTION_ANALYSIS(NAME, CREATE_PASS) \1850 if (Name == "require<" NAME ">" || Name == "invalidate<" NAME ">") \1851 return true;1852 1853#include "llvm/Passes/MachinePassRegistry.def"1854 1855 return callbacksAcceptPassName<MachineFunctionPassManager>(Name, Callbacks);1856}1857 1858template <typename CallbacksT>1859static bool isLoopNestPassName(StringRef Name, CallbacksT &Callbacks,1860 bool &UseMemorySSA) {1861 UseMemorySSA = false;1862 1863 if (PassBuilder::checkParametrizedPassName(Name, "lnicm")) {1864 UseMemorySSA = true;1865 return true;1866 }1867 1868#define LOOPNEST_PASS(NAME, CREATE_PASS) \1869 if (Name == NAME) \1870 return true;1871#include "PassRegistry.def"1872 1873 return callbacksAcceptPassName<LoopPassManager>(Name, Callbacks);1874}1875 1876template <typename CallbacksT>1877static bool isLoopPassName(StringRef Name, CallbacksT &Callbacks,1878 bool &UseMemorySSA) {1879 UseMemorySSA = false;1880 1881 if (PassBuilder::checkParametrizedPassName(Name, "licm")) {1882 UseMemorySSA = true;1883 return true;1884 }1885 1886#define LOOP_PASS(NAME, CREATE_PASS) \1887 if (Name == NAME) \1888 return true;1889#define LOOP_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \1890 if (PassBuilder::checkParametrizedPassName(Name, NAME)) \1891 return true;1892#define LOOP_ANALYSIS(NAME, CREATE_PASS) \1893 if (Name == "require<" NAME ">" || Name == "invalidate<" NAME ">") \1894 return true;1895#include "PassRegistry.def"1896 1897 return callbacksAcceptPassName<LoopPassManager>(Name, Callbacks);1898}1899 1900std::optional<std::vector<PassBuilder::PipelineElement>>1901PassBuilder::parsePipelineText(StringRef Text) {1902 std::vector<PipelineElement> ResultPipeline;1903 1904 SmallVector<std::vector<PipelineElement> *, 4> PipelineStack = {1905 &ResultPipeline};1906 for (;;) {1907 std::vector<PipelineElement> &Pipeline = *PipelineStack.back();1908 size_t Pos = Text.find_first_of(",()");1909 Pipeline.push_back({Text.substr(0, Pos), {}});1910 1911 // If we have a single terminating name, we're done.1912 if (Pos == Text.npos)1913 break;1914 1915 char Sep = Text[Pos];1916 Text = Text.substr(Pos + 1);1917 if (Sep == ',')1918 // Just a name ending in a comma, continue.1919 continue;1920 1921 if (Sep == '(') {1922 // Push the inner pipeline onto the stack to continue processing.1923 PipelineStack.push_back(&Pipeline.back().InnerPipeline);1924 continue;1925 }1926 1927 assert(Sep == ')' && "Bogus separator!");1928 // When handling the close parenthesis, we greedily consume them to avoid1929 // empty strings in the pipeline.1930 do {1931 // If we try to pop the outer pipeline we have unbalanced parentheses.1932 if (PipelineStack.size() == 1)1933 return std::nullopt;1934 1935 PipelineStack.pop_back();1936 } while (Text.consume_front(")"));1937 1938 // Check if we've finished parsing.1939 if (Text.empty())1940 break;1941 1942 // Otherwise, the end of an inner pipeline always has to be followed by1943 // a comma, and then we can continue.1944 if (!Text.consume_front(","))1945 return std::nullopt;1946 }1947 1948 if (PipelineStack.size() > 1)1949 // Unbalanced paretheses.1950 return std::nullopt;1951 1952 assert(PipelineStack.back() == &ResultPipeline &&1953 "Wrong pipeline at the bottom of the stack!");1954 return {std::move(ResultPipeline)};1955}1956 1957static void setupOptionsForPipelineAlias(PipelineTuningOptions &PTO,1958 OptimizationLevel L) {1959 // This is consistent with old pass manager invoked via opt, but1960 // inconsistent with clang. Clang doesn't enable loop vectorization1961 // but does enable slp vectorization at Oz.1962 PTO.LoopVectorization = L.getSpeedupLevel() > 1 && L != OptimizationLevel::Oz;1963 PTO.SLPVectorization = L.getSpeedupLevel() > 1 && L != OptimizationLevel::Oz;1964}1965 1966Error PassBuilder::parseModulePass(ModulePassManager &MPM,1967 const PipelineElement &E) {1968 auto &Name = E.Name;1969 auto &InnerPipeline = E.InnerPipeline;1970 1971 // First handle complex passes like the pass managers which carry pipelines.1972 if (!InnerPipeline.empty()) {1973 if (Name == "module") {1974 ModulePassManager NestedMPM;1975 if (auto Err = parseModulePassPipeline(NestedMPM, InnerPipeline))1976 return Err;1977 MPM.addPass(std::move(NestedMPM));1978 return Error::success();1979 }1980 if (Name == "coro-cond") {1981 ModulePassManager NestedMPM;1982 if (auto Err = parseModulePassPipeline(NestedMPM, InnerPipeline))1983 return Err;1984 MPM.addPass(CoroConditionalWrapper(std::move(NestedMPM)));1985 return Error::success();1986 }1987 if (Name == "cgscc") {1988 CGSCCPassManager CGPM;1989 if (auto Err = parseCGSCCPassPipeline(CGPM, InnerPipeline))1990 return Err;1991 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));1992 return Error::success();1993 }1994 if (auto Params = parseFunctionPipelineName(Name)) {1995 if (Params->second)1996 return make_error<StringError>(1997 "cannot have a no-rerun module to function adaptor",1998 inconvertibleErrorCode());1999 FunctionPassManager FPM;2000 if (auto Err = parseFunctionPassPipeline(FPM, InnerPipeline))2001 return Err;2002 MPM.addPass(2003 createModuleToFunctionPassAdaptor(std::move(FPM), Params->first));2004 return Error::success();2005 }2006 2007 for (auto &C : ModulePipelineParsingCallbacks)2008 if (C(Name, MPM, InnerPipeline))2009 return Error::success();2010 2011 // Normal passes can't have pipelines.2012 return make_error<StringError>(2013 formatv("invalid use of '{}' pass as module pipeline", Name).str(),2014 inconvertibleErrorCode());2015 ;2016 }2017 2018 // Finally expand the basic registered passes from the .inc file.2019#define MODULE_PASS(NAME, CREATE_PASS) \2020 if (Name == NAME) { \2021 MPM.addPass(CREATE_PASS); \2022 return Error::success(); \2023 }2024#define MODULE_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \2025 if (checkParametrizedPassName(Name, NAME)) { \2026 auto Params = parsePassParameters(PARSER, Name, NAME); \2027 if (!Params) \2028 return Params.takeError(); \2029 MPM.addPass(CREATE_PASS(Params.get())); \2030 return Error::success(); \2031 }2032#define MODULE_ANALYSIS(NAME, CREATE_PASS) \2033 if (Name == "require<" NAME ">") { \2034 MPM.addPass( \2035 RequireAnalysisPass< \2036 std::remove_reference_t<decltype(CREATE_PASS)>, Module>()); \2037 return Error::success(); \2038 } \2039 if (Name == "invalidate<" NAME ">") { \2040 MPM.addPass(InvalidateAnalysisPass< \2041 std::remove_reference_t<decltype(CREATE_PASS)>>()); \2042 return Error::success(); \2043 }2044#define CGSCC_PASS(NAME, CREATE_PASS) \2045 if (Name == NAME) { \2046 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(CREATE_PASS)); \2047 return Error::success(); \2048 }2049#define CGSCC_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \2050 if (checkParametrizedPassName(Name, NAME)) { \2051 auto Params = parsePassParameters(PARSER, Name, NAME); \2052 if (!Params) \2053 return Params.takeError(); \2054 MPM.addPass( \2055 createModuleToPostOrderCGSCCPassAdaptor(CREATE_PASS(Params.get()))); \2056 return Error::success(); \2057 }2058#define FUNCTION_PASS(NAME, CREATE_PASS) \2059 if (Name == NAME) { \2060 if constexpr (std::is_constructible_v< \2061 std::remove_reference_t<decltype(CREATE_PASS)>, \2062 const TargetMachine &>) { \2063 if (!TM) \2064 return make_error<StringError>( \2065 formatv("pass '{0}' requires TargetMachine", Name).str(), \2066 inconvertibleErrorCode()); \2067 } \2068 MPM.addPass(createModuleToFunctionPassAdaptor(CREATE_PASS)); \2069 return Error::success(); \2070 }2071#define FUNCTION_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \2072 if (checkParametrizedPassName(Name, NAME)) { \2073 auto Params = parsePassParameters(PARSER, Name, NAME); \2074 if (!Params) \2075 return Params.takeError(); \2076 auto CreatePass = CREATE_PASS; \2077 if constexpr (std::is_constructible_v< \2078 std::remove_reference_t<decltype(CreatePass( \2079 Params.get()))>, \2080 const TargetMachine &, \2081 std::remove_reference_t<decltype(Params.get())>>) { \2082 if (!TM) { \2083 return make_error<StringError>( \2084 formatv("pass '{0}' requires TargetMachine", Name).str(), \2085 inconvertibleErrorCode()); \2086 } \2087 } \2088 MPM.addPass(createModuleToFunctionPassAdaptor(CREATE_PASS(Params.get()))); \2089 return Error::success(); \2090 }2091#define LOOPNEST_PASS(NAME, CREATE_PASS) \2092 if (Name == NAME) { \2093 MPM.addPass(createModuleToFunctionPassAdaptor( \2094 createFunctionToLoopPassAdaptor(CREATE_PASS, false))); \2095 return Error::success(); \2096 }2097#define LOOP_PASS(NAME, CREATE_PASS) \2098 if (Name == NAME) { \2099 MPM.addPass(createModuleToFunctionPassAdaptor( \2100 createFunctionToLoopPassAdaptor(CREATE_PASS, false))); \2101 return Error::success(); \2102 }2103#define LOOP_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \2104 if (checkParametrizedPassName(Name, NAME)) { \2105 auto Params = parsePassParameters(PARSER, Name, NAME); \2106 if (!Params) \2107 return Params.takeError(); \2108 MPM.addPass(createModuleToFunctionPassAdaptor( \2109 createFunctionToLoopPassAdaptor(CREATE_PASS(Params.get()), false))); \2110 return Error::success(); \2111 }2112#include "PassRegistry.def"2113 2114 for (auto &C : ModulePipelineParsingCallbacks)2115 if (C(Name, MPM, InnerPipeline))2116 return Error::success();2117 return make_error<StringError>(2118 formatv("unknown module pass '{}'", Name).str(),2119 inconvertibleErrorCode());2120}2121 2122Error PassBuilder::parseCGSCCPass(CGSCCPassManager &CGPM,2123 const PipelineElement &E) {2124 auto &Name = E.Name;2125 auto &InnerPipeline = E.InnerPipeline;2126 2127 // First handle complex passes like the pass managers which carry pipelines.2128 if (!InnerPipeline.empty()) {2129 if (Name == "cgscc") {2130 CGSCCPassManager NestedCGPM;2131 if (auto Err = parseCGSCCPassPipeline(NestedCGPM, InnerPipeline))2132 return Err;2133 // Add the nested pass manager with the appropriate adaptor.2134 CGPM.addPass(std::move(NestedCGPM));2135 return Error::success();2136 }2137 if (auto Params = parseFunctionPipelineName(Name)) {2138 FunctionPassManager FPM;2139 if (auto Err = parseFunctionPassPipeline(FPM, InnerPipeline))2140 return Err;2141 // Add the nested pass manager with the appropriate adaptor.2142 CGPM.addPass(createCGSCCToFunctionPassAdaptor(2143 std::move(FPM), Params->first, Params->second));2144 return Error::success();2145 }2146 if (auto MaxRepetitions = parseDevirtPassName(Name)) {2147 CGSCCPassManager NestedCGPM;2148 if (auto Err = parseCGSCCPassPipeline(NestedCGPM, InnerPipeline))2149 return Err;2150 CGPM.addPass(2151 createDevirtSCCRepeatedPass(std::move(NestedCGPM), *MaxRepetitions));2152 return Error::success();2153 }2154 2155 for (auto &C : CGSCCPipelineParsingCallbacks)2156 if (C(Name, CGPM, InnerPipeline))2157 return Error::success();2158 2159 // Normal passes can't have pipelines.2160 return make_error<StringError>(2161 formatv("invalid use of '{}' pass as cgscc pipeline", Name).str(),2162 inconvertibleErrorCode());2163 }2164 2165// Now expand the basic registered passes from the .inc file.2166#define CGSCC_PASS(NAME, CREATE_PASS) \2167 if (Name == NAME) { \2168 CGPM.addPass(CREATE_PASS); \2169 return Error::success(); \2170 }2171#define CGSCC_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \2172 if (checkParametrizedPassName(Name, NAME)) { \2173 auto Params = parsePassParameters(PARSER, Name, NAME); \2174 if (!Params) \2175 return Params.takeError(); \2176 CGPM.addPass(CREATE_PASS(Params.get())); \2177 return Error::success(); \2178 }2179#define CGSCC_ANALYSIS(NAME, CREATE_PASS) \2180 if (Name == "require<" NAME ">") { \2181 CGPM.addPass(RequireAnalysisPass< \2182 std::remove_reference_t<decltype(CREATE_PASS)>, \2183 LazyCallGraph::SCC, CGSCCAnalysisManager, LazyCallGraph &, \2184 CGSCCUpdateResult &>()); \2185 return Error::success(); \2186 } \2187 if (Name == "invalidate<" NAME ">") { \2188 CGPM.addPass(InvalidateAnalysisPass< \2189 std::remove_reference_t<decltype(CREATE_PASS)>>()); \2190 return Error::success(); \2191 }2192#define FUNCTION_PASS(NAME, CREATE_PASS) \2193 if (Name == NAME) { \2194 if constexpr (std::is_constructible_v< \2195 std::remove_reference_t<decltype(CREATE_PASS)>, \2196 const TargetMachine &>) { \2197 if (!TM) \2198 return make_error<StringError>( \2199 formatv("pass '{0}' requires TargetMachine", Name).str(), \2200 inconvertibleErrorCode()); \2201 } \2202 CGPM.addPass(createCGSCCToFunctionPassAdaptor(CREATE_PASS)); \2203 return Error::success(); \2204 }2205#define FUNCTION_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \2206 if (checkParametrizedPassName(Name, NAME)) { \2207 auto Params = parsePassParameters(PARSER, Name, NAME); \2208 if (!Params) \2209 return Params.takeError(); \2210 auto CreatePass = CREATE_PASS; \2211 if constexpr (std::is_constructible_v< \2212 std::remove_reference_t<decltype(CreatePass( \2213 Params.get()))>, \2214 const TargetMachine &, \2215 std::remove_reference_t<decltype(Params.get())>>) { \2216 if (!TM) { \2217 return make_error<StringError>( \2218 formatv("pass '{0}' requires TargetMachine", Name).str(), \2219 inconvertibleErrorCode()); \2220 } \2221 } \2222 CGPM.addPass(createCGSCCToFunctionPassAdaptor(CREATE_PASS(Params.get()))); \2223 return Error::success(); \2224 }2225#define LOOPNEST_PASS(NAME, CREATE_PASS) \2226 if (Name == NAME) { \2227 CGPM.addPass(createCGSCCToFunctionPassAdaptor( \2228 createFunctionToLoopPassAdaptor(CREATE_PASS, false))); \2229 return Error::success(); \2230 }2231#define LOOP_PASS(NAME, CREATE_PASS) \2232 if (Name == NAME) { \2233 CGPM.addPass(createCGSCCToFunctionPassAdaptor( \2234 createFunctionToLoopPassAdaptor(CREATE_PASS, false))); \2235 return Error::success(); \2236 }2237#define LOOP_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \2238 if (checkParametrizedPassName(Name, NAME)) { \2239 auto Params = parsePassParameters(PARSER, Name, NAME); \2240 if (!Params) \2241 return Params.takeError(); \2242 CGPM.addPass(createCGSCCToFunctionPassAdaptor( \2243 createFunctionToLoopPassAdaptor(CREATE_PASS(Params.get()), false))); \2244 return Error::success(); \2245 }2246#include "PassRegistry.def"2247 2248 for (auto &C : CGSCCPipelineParsingCallbacks)2249 if (C(Name, CGPM, InnerPipeline))2250 return Error::success();2251 return make_error<StringError>(formatv("unknown cgscc pass '{}'", Name).str(),2252 inconvertibleErrorCode());2253}2254 2255Error PassBuilder::parseFunctionPass(FunctionPassManager &FPM,2256 const PipelineElement &E) {2257 auto &Name = E.Name;2258 auto &InnerPipeline = E.InnerPipeline;2259 2260 // First handle complex passes like the pass managers which carry pipelines.2261 if (!InnerPipeline.empty()) {2262 if (Name == "function") {2263 FunctionPassManager NestedFPM;2264 if (auto Err = parseFunctionPassPipeline(NestedFPM, InnerPipeline))2265 return Err;2266 // Add the nested pass manager with the appropriate adaptor.2267 FPM.addPass(std::move(NestedFPM));2268 return Error::success();2269 }2270 if (Name == "loop" || Name == "loop-mssa") {2271 LoopPassManager LPM;2272 if (auto Err = parseLoopPassPipeline(LPM, InnerPipeline))2273 return Err;2274 // Add the nested pass manager with the appropriate adaptor.2275 bool UseMemorySSA = (Name == "loop-mssa");2276 FPM.addPass(2277 createFunctionToLoopPassAdaptor(std::move(LPM), UseMemorySSA));2278 return Error::success();2279 }2280 if (Name == "machine-function") {2281 MachineFunctionPassManager MFPM;2282 if (auto Err = parseMachinePassPipeline(MFPM, InnerPipeline))2283 return Err;2284 FPM.addPass(createFunctionToMachineFunctionPassAdaptor(std::move(MFPM)));2285 return Error::success();2286 }2287 2288 for (auto &C : FunctionPipelineParsingCallbacks)2289 if (C(Name, FPM, InnerPipeline))2290 return Error::success();2291 2292 // Normal passes can't have pipelines.2293 return make_error<StringError>(2294 formatv("invalid use of '{}' pass as function pipeline", Name).str(),2295 inconvertibleErrorCode());2296 }2297 2298// Now expand the basic registered passes from the .inc file.2299#define FUNCTION_PASS(NAME, CREATE_PASS) \2300 if (Name == NAME) { \2301 if constexpr (std::is_constructible_v< \2302 std::remove_reference_t<decltype(CREATE_PASS)>, \2303 const TargetMachine &>) { \2304 if (!TM) \2305 return make_error<StringError>( \2306 formatv("pass '{0}' requires TargetMachine", Name).str(), \2307 inconvertibleErrorCode()); \2308 } \2309 FPM.addPass(CREATE_PASS); \2310 return Error::success(); \2311 }2312#define FUNCTION_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \2313 if (checkParametrizedPassName(Name, NAME)) { \2314 auto Params = parsePassParameters(PARSER, Name, NAME); \2315 if (!Params) \2316 return Params.takeError(); \2317 auto CreatePass = CREATE_PASS; \2318 if constexpr (std::is_constructible_v< \2319 std::remove_reference_t<decltype(CreatePass( \2320 Params.get()))>, \2321 const TargetMachine &, \2322 std::remove_reference_t<decltype(Params.get())>>) { \2323 if (!TM) { \2324 return make_error<StringError>( \2325 formatv("pass '{0}' requires TargetMachine", Name).str(), \2326 inconvertibleErrorCode()); \2327 } \2328 } \2329 FPM.addPass(CREATE_PASS(Params.get())); \2330 return Error::success(); \2331 }2332#define FUNCTION_ANALYSIS(NAME, CREATE_PASS) \2333 if (Name == "require<" NAME ">") { \2334 if constexpr (std::is_constructible_v< \2335 std::remove_reference_t<decltype(CREATE_PASS)>, \2336 const TargetMachine &>) { \2337 if (!TM) \2338 return make_error<StringError>( \2339 formatv("pass '{0}' requires TargetMachine", Name).str(), \2340 inconvertibleErrorCode()); \2341 } \2342 FPM.addPass( \2343 RequireAnalysisPass<std::remove_reference_t<decltype(CREATE_PASS)>, \2344 Function>()); \2345 return Error::success(); \2346 } \2347 if (Name == "invalidate<" NAME ">") { \2348 FPM.addPass(InvalidateAnalysisPass< \2349 std::remove_reference_t<decltype(CREATE_PASS)>>()); \2350 return Error::success(); \2351 }2352// FIXME: UseMemorySSA is set to false. Maybe we could do things like:2353// bool UseMemorySSA = !("canon-freeze" || "loop-predication" ||2354// "guard-widening");2355// The risk is that it may become obsolete if we're not careful.2356#define LOOPNEST_PASS(NAME, CREATE_PASS) \2357 if (Name == NAME) { \2358 FPM.addPass(createFunctionToLoopPassAdaptor(CREATE_PASS, false)); \2359 return Error::success(); \2360 }2361#define LOOP_PASS(NAME, CREATE_PASS) \2362 if (Name == NAME) { \2363 FPM.addPass(createFunctionToLoopPassAdaptor(CREATE_PASS, false)); \2364 return Error::success(); \2365 }2366#define LOOP_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \2367 if (checkParametrizedPassName(Name, NAME)) { \2368 auto Params = parsePassParameters(PARSER, Name, NAME); \2369 if (!Params) \2370 return Params.takeError(); \2371 FPM.addPass( \2372 createFunctionToLoopPassAdaptor(CREATE_PASS(Params.get()), false)); \2373 return Error::success(); \2374 }2375#include "PassRegistry.def"2376 2377 for (auto &C : FunctionPipelineParsingCallbacks)2378 if (C(Name, FPM, InnerPipeline))2379 return Error::success();2380 return make_error<StringError>(2381 formatv("unknown function pass '{}'", Name).str(),2382 inconvertibleErrorCode());2383}2384 2385Error PassBuilder::parseLoopPass(LoopPassManager &LPM,2386 const PipelineElement &E) {2387 StringRef Name = E.Name;2388 auto &InnerPipeline = E.InnerPipeline;2389 2390 // First handle complex passes like the pass managers which carry pipelines.2391 if (!InnerPipeline.empty()) {2392 if (Name == "loop") {2393 LoopPassManager NestedLPM;2394 if (auto Err = parseLoopPassPipeline(NestedLPM, InnerPipeline))2395 return Err;2396 // Add the nested pass manager with the appropriate adaptor.2397 LPM.addPass(std::move(NestedLPM));2398 return Error::success();2399 }2400 2401 for (auto &C : LoopPipelineParsingCallbacks)2402 if (C(Name, LPM, InnerPipeline))2403 return Error::success();2404 2405 // Normal passes can't have pipelines.2406 return make_error<StringError>(2407 formatv("invalid use of '{}' pass as loop pipeline", Name).str(),2408 inconvertibleErrorCode());2409 }2410 2411// Now expand the basic registered passes from the .inc file.2412#define LOOPNEST_PASS(NAME, CREATE_PASS) \2413 if (Name == NAME) { \2414 LPM.addPass(CREATE_PASS); \2415 return Error::success(); \2416 }2417#define LOOP_PASS(NAME, CREATE_PASS) \2418 if (Name == NAME) { \2419 LPM.addPass(CREATE_PASS); \2420 return Error::success(); \2421 }2422#define LOOP_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \2423 if (checkParametrizedPassName(Name, NAME)) { \2424 auto Params = parsePassParameters(PARSER, Name, NAME); \2425 if (!Params) \2426 return Params.takeError(); \2427 LPM.addPass(CREATE_PASS(Params.get())); \2428 return Error::success(); \2429 }2430#define LOOP_ANALYSIS(NAME, CREATE_PASS) \2431 if (Name == "require<" NAME ">") { \2432 LPM.addPass(RequireAnalysisPass< \2433 std::remove_reference_t<decltype(CREATE_PASS)>, Loop, \2434 LoopAnalysisManager, LoopStandardAnalysisResults &, \2435 LPMUpdater &>()); \2436 return Error::success(); \2437 } \2438 if (Name == "invalidate<" NAME ">") { \2439 LPM.addPass(InvalidateAnalysisPass< \2440 std::remove_reference_t<decltype(CREATE_PASS)>>()); \2441 return Error::success(); \2442 }2443#include "PassRegistry.def"2444 2445 for (auto &C : LoopPipelineParsingCallbacks)2446 if (C(Name, LPM, InnerPipeline))2447 return Error::success();2448 return make_error<StringError>(formatv("unknown loop pass '{}'", Name).str(),2449 inconvertibleErrorCode());2450}2451 2452Error PassBuilder::parseMachinePass(MachineFunctionPassManager &MFPM,2453 const PipelineElement &E) {2454 StringRef Name = E.Name;2455 // Handle any nested pass managers.2456 if (!E.InnerPipeline.empty()) {2457 if (E.Name == "machine-function") {2458 MachineFunctionPassManager NestedPM;2459 if (auto Err = parseMachinePassPipeline(NestedPM, E.InnerPipeline))2460 return Err;2461 MFPM.addPass(std::move(NestedPM));2462 return Error::success();2463 }2464 return make_error<StringError>("invalid pipeline",2465 inconvertibleErrorCode());2466 }2467 2468#define MACHINE_MODULE_PASS(NAME, CREATE_PASS) \2469 if (Name == NAME) { \2470 MFPM.addPass(CREATE_PASS); \2471 return Error::success(); \2472 }2473#define MACHINE_FUNCTION_PASS(NAME, CREATE_PASS) \2474 if (Name == NAME) { \2475 MFPM.addPass(CREATE_PASS); \2476 return Error::success(); \2477 }2478#define MACHINE_FUNCTION_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, \2479 PARAMS) \2480 if (checkParametrizedPassName(Name, NAME)) { \2481 auto Params = parsePassParameters(PARSER, Name, NAME); \2482 if (!Params) \2483 return Params.takeError(); \2484 MFPM.addPass(CREATE_PASS(Params.get())); \2485 return Error::success(); \2486 }2487#define MACHINE_FUNCTION_ANALYSIS(NAME, CREATE_PASS) \2488 if (Name == "require<" NAME ">") { \2489 MFPM.addPass( \2490 RequireAnalysisPass<std::remove_reference_t<decltype(CREATE_PASS)>, \2491 MachineFunction>()); \2492 return Error::success(); \2493 } \2494 if (Name == "invalidate<" NAME ">") { \2495 MFPM.addPass(InvalidateAnalysisPass< \2496 std::remove_reference_t<decltype(CREATE_PASS)>>()); \2497 return Error::success(); \2498 }2499#include "llvm/Passes/MachinePassRegistry.def"2500 2501 for (auto &C : MachineFunctionPipelineParsingCallbacks)2502 if (C(Name, MFPM, E.InnerPipeline))2503 return Error::success();2504 return make_error<StringError>(2505 formatv("unknown machine pass '{}'", Name).str(),2506 inconvertibleErrorCode());2507}2508 2509bool PassBuilder::parseAAPassName(AAManager &AA, StringRef Name) {2510#define MODULE_ALIAS_ANALYSIS(NAME, CREATE_PASS) \2511 if (Name == NAME) { \2512 AA.registerModuleAnalysis< \2513 std::remove_reference_t<decltype(CREATE_PASS)>>(); \2514 return true; \2515 }2516#define FUNCTION_ALIAS_ANALYSIS(NAME, CREATE_PASS) \2517 if (Name == NAME) { \2518 AA.registerFunctionAnalysis< \2519 std::remove_reference_t<decltype(CREATE_PASS)>>(); \2520 return true; \2521 }2522#include "PassRegistry.def"2523 2524 for (auto &C : AAParsingCallbacks)2525 if (C(Name, AA))2526 return true;2527 return false;2528}2529 2530Error PassBuilder::parseMachinePassPipeline(2531 MachineFunctionPassManager &MFPM, ArrayRef<PipelineElement> Pipeline) {2532 for (const auto &Element : Pipeline) {2533 if (auto Err = parseMachinePass(MFPM, Element))2534 return Err;2535 }2536 return Error::success();2537}2538 2539Error PassBuilder::parseLoopPassPipeline(LoopPassManager &LPM,2540 ArrayRef<PipelineElement> Pipeline) {2541 for (const auto &Element : Pipeline) {2542 if (auto Err = parseLoopPass(LPM, Element))2543 return Err;2544 }2545 return Error::success();2546}2547 2548Error PassBuilder::parseFunctionPassPipeline(2549 FunctionPassManager &FPM, ArrayRef<PipelineElement> Pipeline) {2550 for (const auto &Element : Pipeline) {2551 if (auto Err = parseFunctionPass(FPM, Element))2552 return Err;2553 }2554 return Error::success();2555}2556 2557Error PassBuilder::parseCGSCCPassPipeline(CGSCCPassManager &CGPM,2558 ArrayRef<PipelineElement> Pipeline) {2559 for (const auto &Element : Pipeline) {2560 if (auto Err = parseCGSCCPass(CGPM, Element))2561 return Err;2562 }2563 return Error::success();2564}2565 2566void PassBuilder::crossRegisterProxies(LoopAnalysisManager &LAM,2567 FunctionAnalysisManager &FAM,2568 CGSCCAnalysisManager &CGAM,2569 ModuleAnalysisManager &MAM,2570 MachineFunctionAnalysisManager *MFAM) {2571 MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); });2572 MAM.registerPass([&] { return CGSCCAnalysisManagerModuleProxy(CGAM); });2573 CGAM.registerPass([&] { return ModuleAnalysisManagerCGSCCProxy(MAM); });2574 FAM.registerPass([&] { return CGSCCAnalysisManagerFunctionProxy(CGAM); });2575 FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); });2576 FAM.registerPass([&] { return LoopAnalysisManagerFunctionProxy(LAM); });2577 LAM.registerPass([&] { return FunctionAnalysisManagerLoopProxy(FAM); });2578 if (MFAM) {2579 MAM.registerPass(2580 [&] { return MachineFunctionAnalysisManagerModuleProxy(*MFAM); });2581 FAM.registerPass(2582 [&] { return MachineFunctionAnalysisManagerFunctionProxy(*MFAM); });2583 MFAM->registerPass(2584 [&] { return ModuleAnalysisManagerMachineFunctionProxy(MAM); });2585 MFAM->registerPass(2586 [&] { return FunctionAnalysisManagerMachineFunctionProxy(FAM); });2587 }2588}2589 2590Error PassBuilder::parseModulePassPipeline(ModulePassManager &MPM,2591 ArrayRef<PipelineElement> Pipeline) {2592 for (const auto &Element : Pipeline) {2593 if (auto Err = parseModulePass(MPM, Element))2594 return Err;2595 }2596 return Error::success();2597}2598 2599// Primary pass pipeline description parsing routine for a \c ModulePassManager2600// FIXME: Should this routine accept a TargetMachine or require the caller to2601// pre-populate the analysis managers with target-specific stuff?2602Error PassBuilder::parsePassPipeline(ModulePassManager &MPM,2603 StringRef PipelineText) {2604 auto Pipeline = parsePipelineText(PipelineText);2605 if (!Pipeline || Pipeline->empty())2606 return make_error<StringError>(2607 formatv("invalid pipeline '{}'", PipelineText).str(),2608 inconvertibleErrorCode());2609 2610 // If the first name isn't at the module layer, wrap the pipeline up2611 // automatically.2612 StringRef FirstName = Pipeline->front().Name;2613 2614 if (!isModulePassName(FirstName, ModulePipelineParsingCallbacks)) {2615 bool UseMemorySSA;2616 if (isCGSCCPassName(FirstName, CGSCCPipelineParsingCallbacks)) {2617 Pipeline = {{"cgscc", std::move(*Pipeline)}};2618 } else if (isFunctionPassName(FirstName,2619 FunctionPipelineParsingCallbacks)) {2620 Pipeline = {{"function", std::move(*Pipeline)}};2621 } else if (isLoopNestPassName(FirstName, LoopPipelineParsingCallbacks,2622 UseMemorySSA)) {2623 Pipeline = {{"function", {{UseMemorySSA ? "loop-mssa" : "loop",2624 std::move(*Pipeline)}}}};2625 } else if (isLoopPassName(FirstName, LoopPipelineParsingCallbacks,2626 UseMemorySSA)) {2627 Pipeline = {{"function", {{UseMemorySSA ? "loop-mssa" : "loop",2628 std::move(*Pipeline)}}}};2629 } else if (isMachineFunctionPassName(2630 FirstName, MachineFunctionPipelineParsingCallbacks)) {2631 Pipeline = {{"function", {{"machine-function", std::move(*Pipeline)}}}};2632 } else {2633 for (auto &C : TopLevelPipelineParsingCallbacks)2634 if (C(MPM, *Pipeline))2635 return Error::success();2636 2637 // Unknown pass or pipeline name!2638 auto &InnerPipeline = Pipeline->front().InnerPipeline;2639 return make_error<StringError>(2640 formatv("unknown {} name '{}'",2641 (InnerPipeline.empty() ? "pass" : "pipeline"), FirstName)2642 .str(),2643 inconvertibleErrorCode());2644 }2645 }2646 2647 if (auto Err = parseModulePassPipeline(MPM, *Pipeline))2648 return Err;2649 return Error::success();2650}2651 2652// Primary pass pipeline description parsing routine for a \c CGSCCPassManager2653Error PassBuilder::parsePassPipeline(CGSCCPassManager &CGPM,2654 StringRef PipelineText) {2655 auto Pipeline = parsePipelineText(PipelineText);2656 if (!Pipeline || Pipeline->empty())2657 return make_error<StringError>(2658 formatv("invalid pipeline '{}'", PipelineText).str(),2659 inconvertibleErrorCode());2660 2661 StringRef FirstName = Pipeline->front().Name;2662 if (!isCGSCCPassName(FirstName, CGSCCPipelineParsingCallbacks))2663 return make_error<StringError>(2664 formatv("unknown cgscc pass '{}' in pipeline '{}'", FirstName,2665 PipelineText)2666 .str(),2667 inconvertibleErrorCode());2668 2669 if (auto Err = parseCGSCCPassPipeline(CGPM, *Pipeline))2670 return Err;2671 return Error::success();2672}2673 2674// Primary pass pipeline description parsing routine for a \c2675// FunctionPassManager2676Error PassBuilder::parsePassPipeline(FunctionPassManager &FPM,2677 StringRef PipelineText) {2678 auto Pipeline = parsePipelineText(PipelineText);2679 if (!Pipeline || Pipeline->empty())2680 return make_error<StringError>(2681 formatv("invalid pipeline '{}'", PipelineText).str(),2682 inconvertibleErrorCode());2683 2684 StringRef FirstName = Pipeline->front().Name;2685 if (!isFunctionPassName(FirstName, FunctionPipelineParsingCallbacks))2686 return make_error<StringError>(2687 formatv("unknown function pass '{}' in pipeline '{}'", FirstName,2688 PipelineText)2689 .str(),2690 inconvertibleErrorCode());2691 2692 if (auto Err = parseFunctionPassPipeline(FPM, *Pipeline))2693 return Err;2694 return Error::success();2695}2696 2697// Primary pass pipeline description parsing routine for a \c LoopPassManager2698Error PassBuilder::parsePassPipeline(LoopPassManager &CGPM,2699 StringRef PipelineText) {2700 auto Pipeline = parsePipelineText(PipelineText);2701 if (!Pipeline || Pipeline->empty())2702 return make_error<StringError>(2703 formatv("invalid pipeline '{}'", PipelineText).str(),2704 inconvertibleErrorCode());2705 2706 if (auto Err = parseLoopPassPipeline(CGPM, *Pipeline))2707 return Err;2708 2709 return Error::success();2710}2711 2712Error PassBuilder::parsePassPipeline(MachineFunctionPassManager &MFPM,2713 StringRef PipelineText) {2714 auto Pipeline = parsePipelineText(PipelineText);2715 if (!Pipeline || Pipeline->empty())2716 return make_error<StringError>(2717 formatv("invalid machine pass pipeline '{}'", PipelineText).str(),2718 inconvertibleErrorCode());2719 2720 if (auto Err = parseMachinePassPipeline(MFPM, *Pipeline))2721 return Err;2722 2723 return Error::success();2724}2725 2726Error PassBuilder::parseAAPipeline(AAManager &AA, StringRef PipelineText) {2727 // If the pipeline just consists of the word 'default' just replace the AA2728 // manager with our default one.2729 if (PipelineText == "default") {2730 AA = buildDefaultAAPipeline();2731 return Error::success();2732 }2733 2734 while (!PipelineText.empty()) {2735 StringRef Name;2736 std::tie(Name, PipelineText) = PipelineText.split(',');2737 if (!parseAAPassName(AA, Name))2738 return make_error<StringError>(2739 formatv("unknown alias analysis name '{}'", Name).str(),2740 inconvertibleErrorCode());2741 }2742 2743 return Error::success();2744}2745 2746std::optional<RegAllocFilterFunc>2747PassBuilder::parseRegAllocFilter(StringRef FilterName) {2748 if (FilterName == "all")2749 return nullptr;2750 for (auto &C : RegClassFilterParsingCallbacks)2751 if (auto F = C(FilterName))2752 return F;2753 return std::nullopt;2754}2755 2756static void printPassName(StringRef PassName, raw_ostream &OS) {2757 OS << " " << PassName << "\n";2758}2759static void printPassName(StringRef PassName, StringRef Params,2760 raw_ostream &OS) {2761 OS << " " << PassName << "<" << Params << ">\n";2762}2763 2764void PassBuilder::printPassNames(raw_ostream &OS) {2765 // TODO: print pass descriptions when they are available2766 2767 OS << "Module passes:\n";2768#define MODULE_PASS(NAME, CREATE_PASS) printPassName(NAME, OS);2769#include "PassRegistry.def"2770 2771 OS << "Module passes with params:\n";2772#define MODULE_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \2773 printPassName(NAME, PARAMS, OS);2774#include "PassRegistry.def"2775 2776 OS << "Module analyses:\n";2777#define MODULE_ANALYSIS(NAME, CREATE_PASS) printPassName(NAME, OS);2778#include "PassRegistry.def"2779 2780 OS << "Module alias analyses:\n";2781#define MODULE_ALIAS_ANALYSIS(NAME, CREATE_PASS) printPassName(NAME, OS);2782#include "PassRegistry.def"2783 2784 OS << "CGSCC passes:\n";2785#define CGSCC_PASS(NAME, CREATE_PASS) printPassName(NAME, OS);2786#include "PassRegistry.def"2787 2788 OS << "CGSCC passes with params:\n";2789#define CGSCC_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \2790 printPassName(NAME, PARAMS, OS);2791#include "PassRegistry.def"2792 2793 OS << "CGSCC analyses:\n";2794#define CGSCC_ANALYSIS(NAME, CREATE_PASS) printPassName(NAME, OS);2795#include "PassRegistry.def"2796 2797 OS << "Function passes:\n";2798#define FUNCTION_PASS(NAME, CREATE_PASS) printPassName(NAME, OS);2799#include "PassRegistry.def"2800 2801 OS << "Function passes with params:\n";2802#define FUNCTION_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \2803 printPassName(NAME, PARAMS, OS);2804#include "PassRegistry.def"2805 2806 OS << "Function analyses:\n";2807#define FUNCTION_ANALYSIS(NAME, CREATE_PASS) printPassName(NAME, OS);2808#include "PassRegistry.def"2809 2810 OS << "Function alias analyses:\n";2811#define FUNCTION_ALIAS_ANALYSIS(NAME, CREATE_PASS) printPassName(NAME, OS);2812#include "PassRegistry.def"2813 2814 OS << "LoopNest passes:\n";2815#define LOOPNEST_PASS(NAME, CREATE_PASS) printPassName(NAME, OS);2816#include "PassRegistry.def"2817 2818 OS << "Loop passes:\n";2819#define LOOP_PASS(NAME, CREATE_PASS) printPassName(NAME, OS);2820#include "PassRegistry.def"2821 2822 OS << "Loop passes with params:\n";2823#define LOOP_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \2824 printPassName(NAME, PARAMS, OS);2825#include "PassRegistry.def"2826 2827 OS << "Loop analyses:\n";2828#define LOOP_ANALYSIS(NAME, CREATE_PASS) printPassName(NAME, OS);2829#include "PassRegistry.def"2830 2831 OS << "Machine module passes (WIP):\n";2832#define MACHINE_MODULE_PASS(NAME, CREATE_PASS) printPassName(NAME, OS);2833#include "llvm/Passes/MachinePassRegistry.def"2834 2835 OS << "Machine function passes (WIP):\n";2836#define MACHINE_FUNCTION_PASS(NAME, CREATE_PASS) printPassName(NAME, OS);2837#include "llvm/Passes/MachinePassRegistry.def"2838 2839 OS << "Machine function analyses (WIP):\n";2840#define MACHINE_FUNCTION_ANALYSIS(NAME, CREATE_PASS) printPassName(NAME, OS);2841#include "llvm/Passes/MachinePassRegistry.def"2842}2843 2844void PassBuilder::registerParseTopLevelPipelineCallback(2845 const std::function<bool(ModulePassManager &, ArrayRef<PipelineElement>)>2846 &C) {2847 TopLevelPipelineParsingCallbacks.push_back(C);2848}2849