1349cc55cSDimitry Andric //===- Parsing and selection of pass pipelines ----------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric /// \file
90b57cec5SDimitry Andric ///
100b57cec5SDimitry Andric /// This file provides the implementation of the PassBuilder based on our
110b57cec5SDimitry Andric /// static pass registry as well as related functionality. It also provides
120b57cec5SDimitry Andric /// helpers to aid in analyzing, debugging, and testing passes and pass
130b57cec5SDimitry Andric /// pipelines.
140b57cec5SDimitry Andric ///
150b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
160b57cec5SDimitry Andric
170b57cec5SDimitry Andric #include "llvm/Passes/PassBuilder.h"
180b57cec5SDimitry Andric #include "llvm/ADT/StringSwitch.h"
190b57cec5SDimitry Andric #include "llvm/Analysis/AliasAnalysisEvaluator.h"
20e8d8bef9SDimitry Andric #include "llvm/Analysis/AliasSetTracker.h"
210b57cec5SDimitry Andric #include "llvm/Analysis/AssumptionCache.h"
220b57cec5SDimitry Andric #include "llvm/Analysis/BasicAliasAnalysis.h"
230b57cec5SDimitry Andric #include "llvm/Analysis/BlockFrequencyInfo.h"
240b57cec5SDimitry Andric #include "llvm/Analysis/BranchProbabilityInfo.h"
250b57cec5SDimitry Andric #include "llvm/Analysis/CFGPrinter.h"
26bdd1243dSDimitry Andric #include "llvm/Analysis/CFGSCCPrinter.h"
270b57cec5SDimitry Andric #include "llvm/Analysis/CGSCCPassManager.h"
280b57cec5SDimitry Andric #include "llvm/Analysis/CallGraph.h"
2981ad6265SDimitry Andric #include "llvm/Analysis/CallPrinter.h"
30349cc55cSDimitry Andric #include "llvm/Analysis/CostModel.h"
310eae32dcSDimitry Andric #include "llvm/Analysis/CycleAnalysis.h"
328bcb0991SDimitry Andric #include "llvm/Analysis/DDG.h"
33e8d8bef9SDimitry Andric #include "llvm/Analysis/DDGPrinter.h"
34e8d8bef9SDimitry Andric #include "llvm/Analysis/Delinearization.h"
350b57cec5SDimitry Andric #include "llvm/Analysis/DemandedBits.h"
360b57cec5SDimitry Andric #include "llvm/Analysis/DependenceAnalysis.h"
3704eeddc0SDimitry Andric #include "llvm/Analysis/DomPrinter.h"
380b57cec5SDimitry Andric #include "llvm/Analysis/DominanceFrontier.h"
39e8d8bef9SDimitry Andric #include "llvm/Analysis/FunctionPropertiesAnalysis.h"
400b57cec5SDimitry Andric #include "llvm/Analysis/GlobalsModRef.h"
41e8d8bef9SDimitry Andric #include "llvm/Analysis/IRSimilarityIdentifier.h"
420b57cec5SDimitry Andric #include "llvm/Analysis/IVUsers.h"
435ffd83dbSDimitry Andric #include "llvm/Analysis/InlineAdvisor.h"
445ffd83dbSDimitry Andric #include "llvm/Analysis/InlineSizeEstimatorAnalysis.h"
45e8d8bef9SDimitry Andric #include "llvm/Analysis/InstCount.h"
460b57cec5SDimitry Andric #include "llvm/Analysis/LazyCallGraph.h"
470b57cec5SDimitry Andric #include "llvm/Analysis/LazyValueInfo.h"
48e8d8bef9SDimitry Andric #include "llvm/Analysis/Lint.h"
490b57cec5SDimitry Andric #include "llvm/Analysis/LoopAccessAnalysis.h"
508bcb0991SDimitry Andric #include "llvm/Analysis/LoopCacheAnalysis.h"
510b57cec5SDimitry Andric #include "llvm/Analysis/LoopInfo.h"
525ffd83dbSDimitry Andric #include "llvm/Analysis/LoopNestAnalysis.h"
53e8d8bef9SDimitry Andric #include "llvm/Analysis/MemDerefPrinter.h"
540b57cec5SDimitry Andric #include "llvm/Analysis/MemoryDependenceAnalysis.h"
550b57cec5SDimitry Andric #include "llvm/Analysis/MemorySSA.h"
56e8d8bef9SDimitry Andric #include "llvm/Analysis/ModuleDebugInfoPrinter.h"
570b57cec5SDimitry Andric #include "llvm/Analysis/ModuleSummaryAnalysis.h"
58e8d8bef9SDimitry Andric #include "llvm/Analysis/MustExecute.h"
59e8d8bef9SDimitry Andric #include "llvm/Analysis/ObjCARCAliasAnalysis.h"
600b57cec5SDimitry Andric #include "llvm/Analysis/OptimizationRemarkEmitter.h"
610b57cec5SDimitry Andric #include "llvm/Analysis/PhiValues.h"
620b57cec5SDimitry Andric #include "llvm/Analysis/PostDominators.h"
630b57cec5SDimitry Andric #include "llvm/Analysis/ProfileSummaryInfo.h"
640b57cec5SDimitry Andric #include "llvm/Analysis/RegionInfo.h"
650b57cec5SDimitry Andric #include "llvm/Analysis/ScalarEvolution.h"
660b57cec5SDimitry Andric #include "llvm/Analysis/ScalarEvolutionAliasAnalysis.h"
670b57cec5SDimitry Andric #include "llvm/Analysis/ScopedNoAliasAA.h"
685ffd83dbSDimitry Andric #include "llvm/Analysis/StackLifetime.h"
690b57cec5SDimitry Andric #include "llvm/Analysis/StackSafetyAnalysis.h"
705f757f3fSDimitry Andric #include "llvm/Analysis/StructuralHash.h"
710b57cec5SDimitry Andric #include "llvm/Analysis/TargetLibraryInfo.h"
720b57cec5SDimitry Andric #include "llvm/Analysis/TargetTransformInfo.h"
730b57cec5SDimitry Andric #include "llvm/Analysis/TypeBasedAliasAnalysis.h"
74bdd1243dSDimitry Andric #include "llvm/Analysis/UniformityAnalysis.h"
75297eecfbSDimitry Andric #include "llvm/CodeGen/AssignmentTrackingAnalysis.h"
76*0fca6ea1SDimitry Andric #include "llvm/CodeGen/AtomicExpand.h"
771db9f3b2SDimitry Andric #include "llvm/CodeGen/BasicBlockSectionsProfileReader.h"
785f757f3fSDimitry Andric #include "llvm/CodeGen/CallBrPrepare.h"
791db9f3b2SDimitry Andric #include "llvm/CodeGen/CodeGenPrepare.h"
80*0fca6ea1SDimitry Andric #include "llvm/CodeGen/DeadMachineInstructionElim.h"
815f757f3fSDimitry Andric #include "llvm/CodeGen/DwarfEHPrepare.h"
825f757f3fSDimitry Andric #include "llvm/CodeGen/ExpandLargeDivRem.h"
835f757f3fSDimitry Andric #include "llvm/CodeGen/ExpandLargeFpConvert.h"
845f757f3fSDimitry Andric #include "llvm/CodeGen/ExpandMemCmp.h"
85*0fca6ea1SDimitry Andric #include "llvm/CodeGen/FinalizeISel.h"
865f757f3fSDimitry Andric #include "llvm/CodeGen/GCMetadata.h"
877a6dacacSDimitry Andric #include "llvm/CodeGen/GlobalMerge.h"
8806c3fb27SDimitry Andric #include "llvm/CodeGen/HardwareLoops.h"
895f757f3fSDimitry Andric #include "llvm/CodeGen/IndirectBrExpand.h"
905f757f3fSDimitry Andric #include "llvm/CodeGen/InterleavedAccess.h"
915f757f3fSDimitry Andric #include "llvm/CodeGen/InterleavedLoadCombine.h"
925f757f3fSDimitry Andric #include "llvm/CodeGen/JMCInstrumenter.h"
93*0fca6ea1SDimitry Andric #include "llvm/CodeGen/LiveIntervals.h"
94*0fca6ea1SDimitry Andric #include "llvm/CodeGen/LiveVariables.h"
95*0fca6ea1SDimitry Andric #include "llvm/CodeGen/LocalStackSlotAllocation.h"
96cb14a3feSDimitry Andric #include "llvm/CodeGen/LowerEmuTLS.h"
97*0fca6ea1SDimitry Andric #include "llvm/CodeGen/MIRPrinter.h"
98*0fca6ea1SDimitry Andric #include "llvm/CodeGen/MachineBlockFrequencyInfo.h"
99*0fca6ea1SDimitry Andric #include "llvm/CodeGen/MachineBranchProbabilityInfo.h"
100*0fca6ea1SDimitry Andric #include "llvm/CodeGen/MachineDominators.h"
101*0fca6ea1SDimitry Andric #include "llvm/CodeGen/MachineFunctionAnalysis.h"
102*0fca6ea1SDimitry Andric #include "llvm/CodeGen/MachineLoopInfo.h"
103*0fca6ea1SDimitry Andric #include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
104*0fca6ea1SDimitry Andric #include "llvm/CodeGen/MachinePassManager.h"
105*0fca6ea1SDimitry Andric #include "llvm/CodeGen/MachinePostDominators.h"
106*0fca6ea1SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
107*0fca6ea1SDimitry Andric #include "llvm/CodeGen/MachineVerifier.h"
108*0fca6ea1SDimitry Andric #include "llvm/CodeGen/PHIElimination.h"
109*0fca6ea1SDimitry Andric #include "llvm/CodeGen/PreISelIntrinsicLowering.h"
110*0fca6ea1SDimitry Andric #include "llvm/CodeGen/RegAllocFast.h"
1115f757f3fSDimitry Andric #include "llvm/CodeGen/SafeStack.h"
1125f757f3fSDimitry Andric #include "llvm/CodeGen/SelectOptimize.h"
1131db9f3b2SDimitry Andric #include "llvm/CodeGen/ShadowStackGCLowering.h"
1145f757f3fSDimitry Andric #include "llvm/CodeGen/SjLjEHPrepare.h"
115*0fca6ea1SDimitry Andric #include "llvm/CodeGen/SlotIndexes.h"
1161db9f3b2SDimitry Andric #include "llvm/CodeGen/StackProtector.h"
1177a6dacacSDimitry Andric #include "llvm/CodeGen/TargetPassConfig.h"
118*0fca6ea1SDimitry Andric #include "llvm/CodeGen/TwoAddressInstructionPass.h"
119bdd1243dSDimitry Andric #include "llvm/CodeGen/TypePromotion.h"
1205f757f3fSDimitry Andric #include "llvm/CodeGen/WasmEHPrepare.h"
1215f757f3fSDimitry Andric #include "llvm/CodeGen/WinEHPrepare.h"
122bdd1243dSDimitry Andric #include "llvm/IR/DebugInfo.h"
1230b57cec5SDimitry Andric #include "llvm/IR/Dominators.h"
1240b57cec5SDimitry Andric #include "llvm/IR/PassManager.h"
125e8d8bef9SDimitry Andric #include "llvm/IR/PrintPasses.h"
1260b57cec5SDimitry Andric #include "llvm/IR/SafepointIRVerifier.h"
1270b57cec5SDimitry Andric #include "llvm/IR/Verifier.h"
128bdd1243dSDimitry Andric #include "llvm/IRPrinter/IRPrintingPasses.h"
12906c3fb27SDimitry Andric #include "llvm/Passes/OptimizationLevel.h"
130480093f4SDimitry Andric #include "llvm/Support/CommandLine.h"
1310b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
132e8d8bef9SDimitry Andric #include "llvm/Support/ErrorHandling.h"
1330b57cec5SDimitry Andric #include "llvm/Support/FormatVariadic.h"
1340b57cec5SDimitry Andric #include "llvm/Support/Regex.h"
1350b57cec5SDimitry Andric #include "llvm/Target/TargetMachine.h"
1360b57cec5SDimitry Andric #include "llvm/Transforms/AggressiveInstCombine/AggressiveInstCombine.h"
1375f757f3fSDimitry Andric #include "llvm/Transforms/CFGuard.h"
1385ffd83dbSDimitry Andric #include "llvm/Transforms/Coroutines/CoroCleanup.h"
139bdd1243dSDimitry Andric #include "llvm/Transforms/Coroutines/CoroConditionalWrapper.h"
1405ffd83dbSDimitry Andric #include "llvm/Transforms/Coroutines/CoroEarly.h"
1415ffd83dbSDimitry Andric #include "llvm/Transforms/Coroutines/CoroElide.h"
1425ffd83dbSDimitry Andric #include "llvm/Transforms/Coroutines/CoroSplit.h"
1435f757f3fSDimitry Andric #include "llvm/Transforms/HipStdPar/HipStdPar.h"
1440b57cec5SDimitry Andric #include "llvm/Transforms/IPO/AlwaysInliner.h"
145e8d8bef9SDimitry Andric #include "llvm/Transforms/IPO/Annotation2Metadata.h"
1460b57cec5SDimitry Andric #include "llvm/Transforms/IPO/ArgumentPromotion.h"
1470b57cec5SDimitry Andric #include "llvm/Transforms/IPO/Attributor.h"
148e8d8bef9SDimitry Andric #include "llvm/Transforms/IPO/BlockExtractor.h"
1490b57cec5SDimitry Andric #include "llvm/Transforms/IPO/CalledValuePropagation.h"
1500b57cec5SDimitry Andric #include "llvm/Transforms/IPO/ConstantMerge.h"
1510b57cec5SDimitry Andric #include "llvm/Transforms/IPO/CrossDSOCFI.h"
1520b57cec5SDimitry Andric #include "llvm/Transforms/IPO/DeadArgumentElimination.h"
1530b57cec5SDimitry Andric #include "llvm/Transforms/IPO/ElimAvailExtern.h"
15406c3fb27SDimitry Andric #include "llvm/Transforms/IPO/EmbedBitcodePass.h"
155*0fca6ea1SDimitry Andric #include "llvm/Transforms/IPO/ExpandVariadics.h"
1560b57cec5SDimitry Andric #include "llvm/Transforms/IPO/ForceFunctionAttrs.h"
1570b57cec5SDimitry Andric #include "llvm/Transforms/IPO/FunctionAttrs.h"
1580b57cec5SDimitry Andric #include "llvm/Transforms/IPO/FunctionImport.h"
1590b57cec5SDimitry Andric #include "llvm/Transforms/IPO/GlobalDCE.h"
1600b57cec5SDimitry Andric #include "llvm/Transforms/IPO/GlobalOpt.h"
1610b57cec5SDimitry Andric #include "llvm/Transforms/IPO/GlobalSplit.h"
1620b57cec5SDimitry Andric #include "llvm/Transforms/IPO/HotColdSplitting.h"
163e8d8bef9SDimitry Andric #include "llvm/Transforms/IPO/IROutliner.h"
1640b57cec5SDimitry Andric #include "llvm/Transforms/IPO/InferFunctionAttrs.h"
1650b57cec5SDimitry Andric #include "llvm/Transforms/IPO/Inliner.h"
1660b57cec5SDimitry Andric #include "llvm/Transforms/IPO/Internalize.h"
167e8d8bef9SDimitry Andric #include "llvm/Transforms/IPO/LoopExtractor.h"
1680b57cec5SDimitry Andric #include "llvm/Transforms/IPO/LowerTypeTests.h"
16906c3fb27SDimitry Andric #include "llvm/Transforms/IPO/MemProfContextDisambiguation.h"
170480093f4SDimitry Andric #include "llvm/Transforms/IPO/MergeFunctions.h"
171349cc55cSDimitry Andric #include "llvm/Transforms/IPO/ModuleInliner.h"
1725ffd83dbSDimitry Andric #include "llvm/Transforms/IPO/OpenMPOpt.h"
1730b57cec5SDimitry Andric #include "llvm/Transforms/IPO/PartialInlining.h"
1740b57cec5SDimitry Andric #include "llvm/Transforms/IPO/SCCP.h"
1750b57cec5SDimitry Andric #include "llvm/Transforms/IPO/SampleProfile.h"
176e8d8bef9SDimitry Andric #include "llvm/Transforms/IPO/SampleProfileProbe.h"
1770b57cec5SDimitry Andric #include "llvm/Transforms/IPO/StripDeadPrototypes.h"
178e8d8bef9SDimitry Andric #include "llvm/Transforms/IPO/StripSymbols.h"
1790b57cec5SDimitry Andric #include "llvm/Transforms/IPO/SyntheticCountsPropagation.h"
1800b57cec5SDimitry Andric #include "llvm/Transforms/IPO/WholeProgramDevirt.h"
1810b57cec5SDimitry Andric #include "llvm/Transforms/InstCombine/InstCombine.h"
1820b57cec5SDimitry Andric #include "llvm/Transforms/Instrumentation.h"
1830b57cec5SDimitry Andric #include "llvm/Transforms/Instrumentation/AddressSanitizer.h"
1840b57cec5SDimitry Andric #include "llvm/Transforms/Instrumentation/BoundsChecking.h"
1850b57cec5SDimitry Andric #include "llvm/Transforms/Instrumentation/CGProfile.h"
1860b57cec5SDimitry Andric #include "llvm/Transforms/Instrumentation/ControlHeightReduction.h"
187e8d8bef9SDimitry Andric #include "llvm/Transforms/Instrumentation/DataFlowSanitizer.h"
1880b57cec5SDimitry Andric #include "llvm/Transforms/Instrumentation/GCOVProfiler.h"
1890b57cec5SDimitry Andric #include "llvm/Transforms/Instrumentation/HWAddressSanitizer.h"
1900b57cec5SDimitry Andric #include "llvm/Transforms/Instrumentation/InstrOrderFile.h"
1910b57cec5SDimitry Andric #include "llvm/Transforms/Instrumentation/InstrProfiling.h"
192bdd1243dSDimitry Andric #include "llvm/Transforms/Instrumentation/KCFI.h"
193*0fca6ea1SDimitry Andric #include "llvm/Transforms/Instrumentation/LowerAllowCheckPass.h"
194e8d8bef9SDimitry Andric #include "llvm/Transforms/Instrumentation/MemProfiler.h"
1950b57cec5SDimitry Andric #include "llvm/Transforms/Instrumentation/MemorySanitizer.h"
196*0fca6ea1SDimitry Andric #include "llvm/Transforms/Instrumentation/NumericalStabilitySanitizer.h"
197*0fca6ea1SDimitry Andric #include "llvm/Transforms/Instrumentation/PGOCtxProfLowering.h"
198*0fca6ea1SDimitry Andric #include "llvm/Transforms/Instrumentation/PGOForceFunctionAttrs.h"
1990b57cec5SDimitry Andric #include "llvm/Transforms/Instrumentation/PGOInstrumentation.h"
2000b57cec5SDimitry Andric #include "llvm/Transforms/Instrumentation/PoisonChecking.h"
201bdd1243dSDimitry Andric #include "llvm/Transforms/Instrumentation/SanitizerBinaryMetadata.h"
2028bcb0991SDimitry Andric #include "llvm/Transforms/Instrumentation/SanitizerCoverage.h"
2030b57cec5SDimitry Andric #include "llvm/Transforms/Instrumentation/ThreadSanitizer.h"
204e8d8bef9SDimitry Andric #include "llvm/Transforms/ObjCARC.h"
2050b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/ADCE.h"
2060b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/AlignmentFromAssumptions.h"
207e8d8bef9SDimitry Andric #include "llvm/Transforms/Scalar/AnnotationRemarks.h"
2080b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/BDCE.h"
2090b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/CallSiteSplitting.h"
2100b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/ConstantHoisting.h"
211e8d8bef9SDimitry Andric #include "llvm/Transforms/Scalar/ConstraintElimination.h"
2120b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/CorrelatedValuePropagation.h"
2130b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/DCE.h"
214fe6060f1SDimitry Andric #include "llvm/Transforms/Scalar/DFAJumpThreading.h"
2150b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/DeadStoreElimination.h"
2160b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/DivRemPairs.h"
2170b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/EarlyCSE.h"
2180eae32dcSDimitry Andric #include "llvm/Transforms/Scalar/FlattenCFG.h"
2190b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/Float2Int.h"
2200b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/GVN.h"
2210b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/GuardWidening.h"
2220b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/IVUsersPrinter.h"
2230b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/IndVarSimplify.h"
2240b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/InductiveRangeCheckElimination.h"
225e8d8bef9SDimitry Andric #include "llvm/Transforms/Scalar/InferAddressSpaces.h"
2265f757f3fSDimitry Andric #include "llvm/Transforms/Scalar/InferAlignment.h"
2270b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/InstSimplifyPass.h"
228*0fca6ea1SDimitry Andric #include "llvm/Transforms/Scalar/JumpTableToSwitch.h"
2290b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/JumpThreading.h"
2300b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/LICM.h"
2310b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/LoopAccessAnalysisPrinter.h"
232fe6060f1SDimitry Andric #include "llvm/Transforms/Scalar/LoopBoundSplit.h"
2330b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/LoopDataPrefetch.h"
2340b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/LoopDeletion.h"
2350b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/LoopDistribute.h"
236e8d8bef9SDimitry Andric #include "llvm/Transforms/Scalar/LoopFlatten.h"
2370b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/LoopFuse.h"
2380b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/LoopIdiomRecognize.h"
2390b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/LoopInstSimplify.h"
240e8d8bef9SDimitry Andric #include "llvm/Transforms/Scalar/LoopInterchange.h"
2410b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/LoopLoadElimination.h"
2420b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/LoopPassManager.h"
2430b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/LoopPredication.h"
2440b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/LoopRotation.h"
2450b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/LoopSimplifyCFG.h"
2460b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/LoopSink.h"
2470b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/LoopStrengthReduce.h"
2480b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/LoopUnrollAndJamPass.h"
2490b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/LoopUnrollPass.h"
250e8d8bef9SDimitry Andric #include "llvm/Transforms/Scalar/LoopVersioningLICM.h"
25181ad6265SDimitry Andric #include "llvm/Transforms/Scalar/LowerAtomicPass.h"
2528bcb0991SDimitry Andric #include "llvm/Transforms/Scalar/LowerConstantIntrinsics.h"
2530b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/LowerExpectIntrinsic.h"
2540b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/LowerGuardIntrinsic.h"
255480093f4SDimitry Andric #include "llvm/Transforms/Scalar/LowerMatrixIntrinsics.h"
2560b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/LowerWidenableCondition.h"
2570b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/MakeGuardsExplicit.h"
2580b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/MemCpyOptimizer.h"
2590b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/MergeICmps.h"
2608bcb0991SDimitry Andric #include "llvm/Transforms/Scalar/MergedLoadStoreMotion.h"
2610b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/NaryReassociate.h"
2620b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/NewGVN.h"
2630b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/PartiallyInlineLibCalls.h"
26406c3fb27SDimitry Andric #include "llvm/Transforms/Scalar/PlaceSafepoints.h"
2650b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/Reassociate.h"
266e8d8bef9SDimitry Andric #include "llvm/Transforms/Scalar/Reg2Mem.h"
2670b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/RewriteStatepointsForGC.h"
2680b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/SCCP.h"
2690b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/SROA.h"
270e8d8bef9SDimitry Andric #include "llvm/Transforms/Scalar/ScalarizeMaskedMemIntrin.h"
2710b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/Scalarizer.h"
272e8d8bef9SDimitry Andric #include "llvm/Transforms/Scalar/SeparateConstOffsetFromGEP.h"
2730b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/SimpleLoopUnswitch.h"
2740b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/SimplifyCFG.h"
2750b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/Sink.h"
2760b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/SpeculativeExecution.h"
277e8d8bef9SDimitry Andric #include "llvm/Transforms/Scalar/StraightLineStrengthReduce.h"
278e8d8bef9SDimitry Andric #include "llvm/Transforms/Scalar/StructurizeCFG.h"
27981ad6265SDimitry Andric #include "llvm/Transforms/Scalar/TLSVariableHoist.h"
2800b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/TailRecursionElimination.h"
2810b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/WarnMissedTransforms.h"
2820b57cec5SDimitry Andric #include "llvm/Transforms/Utils/AddDiscriminators.h"
2835ffd83dbSDimitry Andric #include "llvm/Transforms/Utils/AssumeBundleBuilder.h"
2840b57cec5SDimitry Andric #include "llvm/Transforms/Utils/BreakCriticalEdges.h"
2850b57cec5SDimitry Andric #include "llvm/Transforms/Utils/CanonicalizeAliases.h"
2865ffd83dbSDimitry Andric #include "llvm/Transforms/Utils/CanonicalizeFreezeInLoops.h"
28706c3fb27SDimitry Andric #include "llvm/Transforms/Utils/CountVisits.h"
2885f757f3fSDimitry Andric #include "llvm/Transforms/Utils/DXILUpgrade.h"
28904eeddc0SDimitry Andric #include "llvm/Transforms/Utils/Debugify.h"
2900b57cec5SDimitry Andric #include "llvm/Transforms/Utils/EntryExitInstrumenter.h"
291e8d8bef9SDimitry Andric #include "llvm/Transforms/Utils/FixIrreducible.h"
292fe6060f1SDimitry Andric #include "llvm/Transforms/Utils/HelloWorld.h"
293480093f4SDimitry Andric #include "llvm/Transforms/Utils/InjectTLIMappings.h"
294e8d8bef9SDimitry Andric #include "llvm/Transforms/Utils/InstructionNamer.h"
2950b57cec5SDimitry Andric #include "llvm/Transforms/Utils/LCSSA.h"
2960b57cec5SDimitry Andric #include "llvm/Transforms/Utils/LibCallsShrinkWrap.h"
2970b57cec5SDimitry Andric #include "llvm/Transforms/Utils/LoopSimplify.h"
298e8d8bef9SDimitry Andric #include "llvm/Transforms/Utils/LoopVersioning.h"
29981ad6265SDimitry Andric #include "llvm/Transforms/Utils/LowerGlobalDtors.h"
300bdd1243dSDimitry Andric #include "llvm/Transforms/Utils/LowerIFunc.h"
3010b57cec5SDimitry Andric #include "llvm/Transforms/Utils/LowerInvoke.h"
302e8d8bef9SDimitry Andric #include "llvm/Transforms/Utils/LowerSwitch.h"
3030b57cec5SDimitry Andric #include "llvm/Transforms/Utils/Mem2Reg.h"
304e8d8bef9SDimitry Andric #include "llvm/Transforms/Utils/MetaRenamer.h"
30506c3fb27SDimitry Andric #include "llvm/Transforms/Utils/MoveAutoInit.h"
3060b57cec5SDimitry Andric #include "llvm/Transforms/Utils/NameAnonGlobals.h"
30781ad6265SDimitry Andric #include "llvm/Transforms/Utils/PredicateInfo.h"
308fe6060f1SDimitry Andric #include "llvm/Transforms/Utils/RelLookupTableConverter.h"
309e8d8bef9SDimitry Andric #include "llvm/Transforms/Utils/StripGCRelocates.h"
310e8d8bef9SDimitry Andric #include "llvm/Transforms/Utils/StripNonLineTableDebugInfo.h"
3110b57cec5SDimitry Andric #include "llvm/Transforms/Utils/SymbolRewriter.h"
312e8d8bef9SDimitry Andric #include "llvm/Transforms/Utils/UnifyFunctionExitNodes.h"
313e8d8bef9SDimitry Andric #include "llvm/Transforms/Utils/UnifyLoopExits.h"
3140b57cec5SDimitry Andric #include "llvm/Transforms/Vectorize/LoadStoreVectorizer.h"
315*0fca6ea1SDimitry Andric #include "llvm/Transforms/Vectorize/LoopIdiomVectorize.h"
3160b57cec5SDimitry Andric #include "llvm/Transforms/Vectorize/LoopVectorize.h"
3170b57cec5SDimitry Andric #include "llvm/Transforms/Vectorize/SLPVectorizer.h"
3185ffd83dbSDimitry Andric #include "llvm/Transforms/Vectorize/VectorCombine.h"
319bdd1243dSDimitry Andric #include <optional>
3200b57cec5SDimitry Andric
3210b57cec5SDimitry Andric using namespace llvm;
3220b57cec5SDimitry Andric
3238bcb0991SDimitry Andric static const Regex DefaultAliasRegex(
3240b57cec5SDimitry Andric "^(default|thinlto-pre-link|thinlto|lto-pre-link|lto)<(O[0123sz])>$");
3250b57cec5SDimitry Andric
326fe6060f1SDimitry Andric namespace llvm {
327349cc55cSDimitry Andric cl::opt<bool> PrintPipelinePasses(
328349cc55cSDimitry Andric "print-pipeline-passes",
329349cc55cSDimitry Andric cl::desc("Print a '-passes' compatible string describing the pipeline "
330349cc55cSDimitry Andric "(best-effort only)."));
331fe6060f1SDimitry Andric } // namespace llvm
332e8d8bef9SDimitry Andric
3330b57cec5SDimitry Andric AnalysisKey NoOpModuleAnalysis::Key;
3340b57cec5SDimitry Andric AnalysisKey NoOpCGSCCAnalysis::Key;
3350b57cec5SDimitry Andric AnalysisKey NoOpFunctionAnalysis::Key;
3360b57cec5SDimitry Andric AnalysisKey NoOpLoopAnalysis::Key;
3370b57cec5SDimitry Andric
3387a6dacacSDimitry Andric namespace {
3397a6dacacSDimitry Andric
340*0fca6ea1SDimitry Andric // Passes for testing crashes.
34181ad6265SDimitry Andric // DO NOT USE THIS EXCEPT FOR TESTING!
342*0fca6ea1SDimitry Andric class TriggerCrashModulePass : public PassInfoMixin<TriggerCrashModulePass> {
34381ad6265SDimitry Andric public:
run(Module &,ModuleAnalysisManager &)34481ad6265SDimitry Andric PreservedAnalyses run(Module &, ModuleAnalysisManager &) {
34581ad6265SDimitry Andric abort();
34681ad6265SDimitry Andric return PreservedAnalyses::all();
34781ad6265SDimitry Andric }
name()348*0fca6ea1SDimitry Andric static StringRef name() { return "TriggerCrashModulePass"; }
349*0fca6ea1SDimitry Andric };
350*0fca6ea1SDimitry Andric
351*0fca6ea1SDimitry Andric class TriggerCrashFunctionPass
352*0fca6ea1SDimitry Andric : public PassInfoMixin<TriggerCrashFunctionPass> {
353*0fca6ea1SDimitry Andric public:
run(Function &,FunctionAnalysisManager &)354*0fca6ea1SDimitry Andric PreservedAnalyses run(Function &, FunctionAnalysisManager &) {
355*0fca6ea1SDimitry Andric abort();
356*0fca6ea1SDimitry Andric return PreservedAnalyses::all();
357*0fca6ea1SDimitry Andric }
name()358*0fca6ea1SDimitry Andric static StringRef name() { return "TriggerCrashFunctionPass"; }
35981ad6265SDimitry Andric };
36081ad6265SDimitry Andric
3615f757f3fSDimitry Andric // A pass for testing message reporting of -verify-each failures.
3625f757f3fSDimitry Andric // DO NOT USE THIS EXCEPT FOR TESTING!
3635f757f3fSDimitry Andric class TriggerVerifierErrorPass
3645f757f3fSDimitry Andric : public PassInfoMixin<TriggerVerifierErrorPass> {
3655f757f3fSDimitry Andric public:
run(Module & M,ModuleAnalysisManager &)3665f757f3fSDimitry Andric PreservedAnalyses run(Module &M, ModuleAnalysisManager &) {
3675f757f3fSDimitry Andric // Intentionally break the Module by creating an alias without setting the
3685f757f3fSDimitry Andric // aliasee.
3695f757f3fSDimitry Andric auto *PtrTy = llvm::PointerType::getUnqual(M.getContext());
3705f757f3fSDimitry Andric GlobalAlias::create(PtrTy, PtrTy->getAddressSpace(),
3715f757f3fSDimitry Andric GlobalValue::LinkageTypes::InternalLinkage,
3725f757f3fSDimitry Andric "__bad_alias", nullptr, &M);
3735f757f3fSDimitry Andric return PreservedAnalyses::none();
3745f757f3fSDimitry Andric }
3755f757f3fSDimitry Andric
run(Function & F,FunctionAnalysisManager &)3765f757f3fSDimitry Andric PreservedAnalyses run(Function &F, FunctionAnalysisManager &) {
3775f757f3fSDimitry Andric // Intentionally break the Function by inserting a terminator
3785f757f3fSDimitry Andric // instruction in the middle of a basic block.
3795f757f3fSDimitry Andric BasicBlock &BB = F.getEntryBlock();
380*0fca6ea1SDimitry Andric new UnreachableInst(F.getContext(), BB.getTerminator()->getIterator());
3815f757f3fSDimitry Andric return PreservedAnalyses::none();
3825f757f3fSDimitry Andric }
3835f757f3fSDimitry Andric
run(MachineFunction & MF,MachineFunctionAnalysisManager &)384*0fca6ea1SDimitry Andric PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &) {
385*0fca6ea1SDimitry Andric // Intentionally create a virtual register and set NoVRegs property.
386*0fca6ea1SDimitry Andric auto &MRI = MF.getRegInfo();
387*0fca6ea1SDimitry Andric MRI.createGenericVirtualRegister(LLT::scalar(8));
388*0fca6ea1SDimitry Andric MF.getProperties().set(MachineFunctionProperties::Property::NoVRegs);
389*0fca6ea1SDimitry Andric return PreservedAnalyses::all();
390*0fca6ea1SDimitry Andric }
391*0fca6ea1SDimitry Andric
name()3925f757f3fSDimitry Andric static StringRef name() { return "TriggerVerifierErrorPass"; }
3935f757f3fSDimitry Andric };
3945f757f3fSDimitry Andric
395*0fca6ea1SDimitry Andric // A pass requires all MachineFunctionProperties.
396*0fca6ea1SDimitry Andric // DO NOT USE THIS EXCEPT FOR TESTING!
397*0fca6ea1SDimitry Andric class RequireAllMachineFunctionPropertiesPass
398*0fca6ea1SDimitry Andric : public PassInfoMixin<RequireAllMachineFunctionPropertiesPass> {
399*0fca6ea1SDimitry Andric public:
run(MachineFunction & MF,MachineFunctionAnalysisManager &)400*0fca6ea1SDimitry Andric PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &) {
401*0fca6ea1SDimitry Andric MFPropsModifier _(*this, MF);
402*0fca6ea1SDimitry Andric return PreservedAnalyses::none();
403*0fca6ea1SDimitry Andric }
404*0fca6ea1SDimitry Andric
getRequiredProperties()405*0fca6ea1SDimitry Andric static MachineFunctionProperties getRequiredProperties() {
406*0fca6ea1SDimitry Andric MachineFunctionProperties MFProps;
407*0fca6ea1SDimitry Andric MFProps.set(MachineFunctionProperties::Property::FailedISel);
408*0fca6ea1SDimitry Andric MFProps.set(MachineFunctionProperties::Property::FailsVerification);
409*0fca6ea1SDimitry Andric MFProps.set(MachineFunctionProperties::Property::IsSSA);
410*0fca6ea1SDimitry Andric MFProps.set(MachineFunctionProperties::Property::Legalized);
411*0fca6ea1SDimitry Andric MFProps.set(MachineFunctionProperties::Property::NoPHIs);
412*0fca6ea1SDimitry Andric MFProps.set(MachineFunctionProperties::Property::NoVRegs);
413*0fca6ea1SDimitry Andric MFProps.set(MachineFunctionProperties::Property::RegBankSelected);
414*0fca6ea1SDimitry Andric MFProps.set(MachineFunctionProperties::Property::Selected);
415*0fca6ea1SDimitry Andric MFProps.set(MachineFunctionProperties::Property::TiedOpsRewritten);
416*0fca6ea1SDimitry Andric MFProps.set(MachineFunctionProperties::Property::TracksDebugUserValues);
417*0fca6ea1SDimitry Andric MFProps.set(MachineFunctionProperties::Property::TracksLiveness);
418*0fca6ea1SDimitry Andric return MFProps;
419*0fca6ea1SDimitry Andric }
name()420*0fca6ea1SDimitry Andric static StringRef name() { return "RequireAllMachineFunctionPropertiesPass"; }
421*0fca6ea1SDimitry Andric };
422*0fca6ea1SDimitry Andric
4235ffd83dbSDimitry Andric } // namespace
4240b57cec5SDimitry Andric
PassBuilder(TargetMachine * TM,PipelineTuningOptions PTO,std::optional<PGOOptions> PGOOpt,PassInstrumentationCallbacks * PIC)425fe6060f1SDimitry Andric PassBuilder::PassBuilder(TargetMachine *TM, PipelineTuningOptions PTO,
426bdd1243dSDimitry Andric std::optional<PGOOptions> PGOOpt,
427e8d8bef9SDimitry Andric PassInstrumentationCallbacks *PIC)
428fe6060f1SDimitry Andric : TM(TM), PTO(PTO), PGOOpt(PGOOpt), PIC(PIC) {
429e8d8bef9SDimitry Andric if (TM)
430*0fca6ea1SDimitry Andric TM->registerPassBuilderCallbacks(*this);
431*0fca6ea1SDimitry Andric if (PIC) {
432*0fca6ea1SDimitry Andric PIC->registerClassToPassNameCallback([this, PIC]() {
433*0fca6ea1SDimitry Andric // MSVC requires this to be captured if it's used inside decltype.
434*0fca6ea1SDimitry Andric // Other compilers consider it an unused lambda capture.
435*0fca6ea1SDimitry Andric (void)this;
436e8d8bef9SDimitry Andric #define MODULE_PASS(NAME, CREATE_PASS) \
437e8d8bef9SDimitry Andric PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME);
438349cc55cSDimitry Andric #define MODULE_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \
439349cc55cSDimitry Andric PIC->addClassToPassName(CLASS, NAME);
440e8d8bef9SDimitry Andric #define MODULE_ANALYSIS(NAME, CREATE_PASS) \
441e8d8bef9SDimitry Andric PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME);
442e8d8bef9SDimitry Andric #define FUNCTION_PASS(NAME, CREATE_PASS) \
443e8d8bef9SDimitry Andric PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME);
444fe6060f1SDimitry Andric #define FUNCTION_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \
445fe6060f1SDimitry Andric PIC->addClassToPassName(CLASS, NAME);
446e8d8bef9SDimitry Andric #define FUNCTION_ANALYSIS(NAME, CREATE_PASS) \
447e8d8bef9SDimitry Andric PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME);
448349cc55cSDimitry Andric #define LOOPNEST_PASS(NAME, CREATE_PASS) \
449349cc55cSDimitry Andric PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME);
450e8d8bef9SDimitry Andric #define LOOP_PASS(NAME, CREATE_PASS) \
451e8d8bef9SDimitry Andric PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME);
452fe6060f1SDimitry Andric #define LOOP_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \
453fe6060f1SDimitry Andric PIC->addClassToPassName(CLASS, NAME);
454e8d8bef9SDimitry Andric #define LOOP_ANALYSIS(NAME, CREATE_PASS) \
455e8d8bef9SDimitry Andric PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME);
456e8d8bef9SDimitry Andric #define CGSCC_PASS(NAME, CREATE_PASS) \
457e8d8bef9SDimitry Andric PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME);
458349cc55cSDimitry Andric #define CGSCC_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \
459349cc55cSDimitry Andric PIC->addClassToPassName(CLASS, NAME);
460e8d8bef9SDimitry Andric #define CGSCC_ANALYSIS(NAME, CREATE_PASS) \
461e8d8bef9SDimitry Andric PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME);
462e8d8bef9SDimitry Andric #include "PassRegistry.def"
4637a6dacacSDimitry Andric
464*0fca6ea1SDimitry Andric #define MACHINE_FUNCTION_ANALYSIS(NAME, CREATE_PASS) \
465*0fca6ea1SDimitry Andric PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME);
466*0fca6ea1SDimitry Andric #define MACHINE_FUNCTION_PASS(NAME, CREATE_PASS) \
467*0fca6ea1SDimitry Andric PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME);
468*0fca6ea1SDimitry Andric #include "llvm/Passes/MachinePassRegistry.def"
469*0fca6ea1SDimitry Andric });
470e8d8bef9SDimitry Andric }
471e8d8bef9SDimitry Andric }
472e8d8bef9SDimitry Andric
registerModuleAnalyses(ModuleAnalysisManager & MAM)4730b57cec5SDimitry Andric void PassBuilder::registerModuleAnalyses(ModuleAnalysisManager &MAM) {
4740b57cec5SDimitry Andric #define MODULE_ANALYSIS(NAME, CREATE_PASS) \
4750b57cec5SDimitry Andric MAM.registerPass([&] { return CREATE_PASS; });
4760b57cec5SDimitry Andric #include "PassRegistry.def"
4770b57cec5SDimitry Andric
4780b57cec5SDimitry Andric for (auto &C : ModuleAnalysisRegistrationCallbacks)
4790b57cec5SDimitry Andric C(MAM);
4800b57cec5SDimitry Andric }
4810b57cec5SDimitry Andric
registerCGSCCAnalyses(CGSCCAnalysisManager & CGAM)4820b57cec5SDimitry Andric void PassBuilder::registerCGSCCAnalyses(CGSCCAnalysisManager &CGAM) {
4830b57cec5SDimitry Andric #define CGSCC_ANALYSIS(NAME, CREATE_PASS) \
4840b57cec5SDimitry Andric CGAM.registerPass([&] { return CREATE_PASS; });
4850b57cec5SDimitry Andric #include "PassRegistry.def"
4860b57cec5SDimitry Andric
4870b57cec5SDimitry Andric for (auto &C : CGSCCAnalysisRegistrationCallbacks)
4880b57cec5SDimitry Andric C(CGAM);
4890b57cec5SDimitry Andric }
4900b57cec5SDimitry Andric
registerFunctionAnalyses(FunctionAnalysisManager & FAM)4910b57cec5SDimitry Andric void PassBuilder::registerFunctionAnalyses(FunctionAnalysisManager &FAM) {
492349cc55cSDimitry Andric // We almost always want the default alias analysis pipeline.
493349cc55cSDimitry Andric // If a user wants a different one, they can register their own before calling
494349cc55cSDimitry Andric // registerFunctionAnalyses().
495349cc55cSDimitry Andric FAM.registerPass([&] { return buildDefaultAAPipeline(); });
496349cc55cSDimitry Andric
4970b57cec5SDimitry Andric #define FUNCTION_ANALYSIS(NAME, CREATE_PASS) \
4980b57cec5SDimitry Andric FAM.registerPass([&] { return CREATE_PASS; });
4990b57cec5SDimitry Andric #include "PassRegistry.def"
5000b57cec5SDimitry Andric
5010b57cec5SDimitry Andric for (auto &C : FunctionAnalysisRegistrationCallbacks)
5020b57cec5SDimitry Andric C(FAM);
5030b57cec5SDimitry Andric }
5040b57cec5SDimitry Andric
registerMachineFunctionAnalyses(MachineFunctionAnalysisManager & MFAM)5057a6dacacSDimitry Andric void PassBuilder::registerMachineFunctionAnalyses(
5067a6dacacSDimitry Andric MachineFunctionAnalysisManager &MFAM) {
5077a6dacacSDimitry Andric
508*0fca6ea1SDimitry Andric #define MACHINE_FUNCTION_ANALYSIS(NAME, CREATE_PASS) \
509*0fca6ea1SDimitry Andric MFAM.registerPass([&] { return CREATE_PASS; });
510*0fca6ea1SDimitry Andric #include "llvm/Passes/MachinePassRegistry.def"
5117a6dacacSDimitry Andric
5127a6dacacSDimitry Andric for (auto &C : MachineFunctionAnalysisRegistrationCallbacks)
5137a6dacacSDimitry Andric C(MFAM);
5147a6dacacSDimitry Andric }
5157a6dacacSDimitry Andric
registerLoopAnalyses(LoopAnalysisManager & LAM)5160b57cec5SDimitry Andric void PassBuilder::registerLoopAnalyses(LoopAnalysisManager &LAM) {
5170b57cec5SDimitry Andric #define LOOP_ANALYSIS(NAME, CREATE_PASS) \
5180b57cec5SDimitry Andric LAM.registerPass([&] { return CREATE_PASS; });
5190b57cec5SDimitry Andric #include "PassRegistry.def"
5200b57cec5SDimitry Andric
5210b57cec5SDimitry Andric for (auto &C : LoopAnalysisRegistrationCallbacks)
5220b57cec5SDimitry Andric C(LAM);
5230b57cec5SDimitry Andric }
5240b57cec5SDimitry Andric
52506c3fb27SDimitry Andric static std::optional<std::pair<bool, bool>>
parseFunctionPipelineName(StringRef Name)52606c3fb27SDimitry Andric parseFunctionPipelineName(StringRef Name) {
52706c3fb27SDimitry Andric std::pair<bool, bool> Params;
52806c3fb27SDimitry Andric if (!Name.consume_front("function"))
52906c3fb27SDimitry Andric return std::nullopt;
53006c3fb27SDimitry Andric if (Name.empty())
53106c3fb27SDimitry Andric return Params;
53206c3fb27SDimitry Andric if (!Name.consume_front("<") || !Name.consume_back(">"))
53306c3fb27SDimitry Andric return std::nullopt;
53406c3fb27SDimitry Andric while (!Name.empty()) {
53506c3fb27SDimitry Andric auto [Front, Back] = Name.split(';');
53606c3fb27SDimitry Andric Name = Back;
53706c3fb27SDimitry Andric if (Front == "eager-inv")
53806c3fb27SDimitry Andric Params.first = true;
53906c3fb27SDimitry Andric else if (Front == "no-rerun")
54006c3fb27SDimitry Andric Params.second = true;
54106c3fb27SDimitry Andric else
54206c3fb27SDimitry Andric return std::nullopt;
54306c3fb27SDimitry Andric }
54406c3fb27SDimitry Andric return Params;
54506c3fb27SDimitry Andric }
54606c3fb27SDimitry Andric
parseDevirtPassName(StringRef Name)547bdd1243dSDimitry Andric static std::optional<int> parseDevirtPassName(StringRef Name) {
5480b57cec5SDimitry Andric if (!Name.consume_front("devirt<") || !Name.consume_back(">"))
549bdd1243dSDimitry Andric return std::nullopt;
5500b57cec5SDimitry Andric int Count;
551e8d8bef9SDimitry Andric if (Name.getAsInteger(0, Count) || Count < 0)
552bdd1243dSDimitry Andric return std::nullopt;
5530b57cec5SDimitry Andric return Count;
5540b57cec5SDimitry Andric }
5550b57cec5SDimitry Andric
parseOptLevel(StringRef S)55606c3fb27SDimitry Andric static std::optional<OptimizationLevel> parseOptLevel(StringRef S) {
55706c3fb27SDimitry Andric return StringSwitch<std::optional<OptimizationLevel>>(S)
55806c3fb27SDimitry Andric .Case("O0", OptimizationLevel::O0)
55906c3fb27SDimitry Andric .Case("O1", OptimizationLevel::O1)
56006c3fb27SDimitry Andric .Case("O2", OptimizationLevel::O2)
56106c3fb27SDimitry Andric .Case("O3", OptimizationLevel::O3)
56206c3fb27SDimitry Andric .Case("Os", OptimizationLevel::Os)
56306c3fb27SDimitry Andric .Case("Oz", OptimizationLevel::Oz)
56406c3fb27SDimitry Andric .Default(std::nullopt);
56506c3fb27SDimitry Andric }
56606c3fb27SDimitry Andric
parseSinglePassOption(StringRef Params,StringRef OptionName,StringRef PassName)567*0fca6ea1SDimitry Andric Expected<bool> PassBuilder::parseSinglePassOption(StringRef Params,
568*0fca6ea1SDimitry Andric StringRef OptionName,
569*0fca6ea1SDimitry Andric StringRef PassName) {
570*0fca6ea1SDimitry Andric bool Result = false;
571*0fca6ea1SDimitry Andric while (!Params.empty()) {
572*0fca6ea1SDimitry Andric StringRef ParamName;
573*0fca6ea1SDimitry Andric std::tie(ParamName, Params) = Params.split(';');
5740b57cec5SDimitry Andric
575*0fca6ea1SDimitry Andric if (ParamName == OptionName) {
576*0fca6ea1SDimitry Andric Result = true;
577*0fca6ea1SDimitry Andric } else {
578*0fca6ea1SDimitry Andric return make_error<StringError>(
579*0fca6ea1SDimitry Andric formatv("invalid {1} pass parameter '{0}' ", ParamName, PassName)
580*0fca6ea1SDimitry Andric .str(),
581*0fca6ea1SDimitry Andric inconvertibleErrorCode());
5820b57cec5SDimitry Andric }
5830b57cec5SDimitry Andric }
584480093f4SDimitry Andric return Result;
5850b57cec5SDimitry Andric }
5860b57cec5SDimitry Andric
587*0fca6ea1SDimitry Andric namespace {
588*0fca6ea1SDimitry Andric
58906c3fb27SDimitry Andric /// Parser of parameters for HardwareLoops pass.
parseHardwareLoopOptions(StringRef Params)59006c3fb27SDimitry Andric Expected<HardwareLoopOptions> parseHardwareLoopOptions(StringRef Params) {
59106c3fb27SDimitry Andric HardwareLoopOptions HardwareLoopOpts;
59206c3fb27SDimitry Andric
59306c3fb27SDimitry Andric while (!Params.empty()) {
59406c3fb27SDimitry Andric StringRef ParamName;
59506c3fb27SDimitry Andric std::tie(ParamName, Params) = Params.split(';');
59606c3fb27SDimitry Andric if (ParamName.consume_front("hardware-loop-decrement=")) {
59706c3fb27SDimitry Andric int Count;
59806c3fb27SDimitry Andric if (ParamName.getAsInteger(0, Count))
59906c3fb27SDimitry Andric return make_error<StringError>(
60006c3fb27SDimitry Andric formatv("invalid HardwareLoopPass parameter '{0}' ", ParamName).str(),
60106c3fb27SDimitry Andric inconvertibleErrorCode());
60206c3fb27SDimitry Andric HardwareLoopOpts.setDecrement(Count);
60306c3fb27SDimitry Andric continue;
60406c3fb27SDimitry Andric }
60506c3fb27SDimitry Andric if (ParamName.consume_front("hardware-loop-counter-bitwidth=")) {
60606c3fb27SDimitry Andric int Count;
60706c3fb27SDimitry Andric if (ParamName.getAsInteger(0, Count))
60806c3fb27SDimitry Andric return make_error<StringError>(
60906c3fb27SDimitry Andric formatv("invalid HardwareLoopPass parameter '{0}' ", ParamName).str(),
61006c3fb27SDimitry Andric inconvertibleErrorCode());
61106c3fb27SDimitry Andric HardwareLoopOpts.setCounterBitwidth(Count);
61206c3fb27SDimitry Andric continue;
61306c3fb27SDimitry Andric }
61406c3fb27SDimitry Andric if (ParamName == "force-hardware-loops") {
61506c3fb27SDimitry Andric HardwareLoopOpts.setForce(true);
61606c3fb27SDimitry Andric } else if (ParamName == "force-hardware-loop-phi") {
61706c3fb27SDimitry Andric HardwareLoopOpts.setForcePhi(true);
61806c3fb27SDimitry Andric } else if (ParamName == "force-nested-hardware-loop") {
61906c3fb27SDimitry Andric HardwareLoopOpts.setForceNested(true);
62006c3fb27SDimitry Andric } else if (ParamName == "force-hardware-loop-guard") {
62106c3fb27SDimitry Andric HardwareLoopOpts.setForceGuard(true);
62206c3fb27SDimitry Andric } else {
62306c3fb27SDimitry Andric return make_error<StringError>(
62406c3fb27SDimitry Andric formatv("invalid HardwarePass parameter '{0}' ", ParamName).str(),
62506c3fb27SDimitry Andric inconvertibleErrorCode());
62606c3fb27SDimitry Andric }
62706c3fb27SDimitry Andric }
62806c3fb27SDimitry Andric return HardwareLoopOpts;
62906c3fb27SDimitry Andric }
63006c3fb27SDimitry Andric
6310b57cec5SDimitry Andric /// Parser of parameters for LoopUnroll pass.
parseLoopUnrollOptions(StringRef Params)6320b57cec5SDimitry Andric Expected<LoopUnrollOptions> parseLoopUnrollOptions(StringRef Params) {
6330b57cec5SDimitry Andric LoopUnrollOptions UnrollOpts;
6340b57cec5SDimitry Andric while (!Params.empty()) {
6350b57cec5SDimitry Andric StringRef ParamName;
6360b57cec5SDimitry Andric std::tie(ParamName, Params) = Params.split(';');
63706c3fb27SDimitry Andric std::optional<OptimizationLevel> OptLevel = parseOptLevel(ParamName);
63806c3fb27SDimitry Andric // Don't accept -Os/-Oz.
63906c3fb27SDimitry Andric if (OptLevel && !OptLevel->isOptimizingForSize()) {
64006c3fb27SDimitry Andric UnrollOpts.setOptLevel(OptLevel->getSpeedupLevel());
6410b57cec5SDimitry Andric continue;
6420b57cec5SDimitry Andric }
6438bcb0991SDimitry Andric if (ParamName.consume_front("full-unroll-max=")) {
6448bcb0991SDimitry Andric int Count;
6458bcb0991SDimitry Andric if (ParamName.getAsInteger(0, Count))
6468bcb0991SDimitry Andric return make_error<StringError>(
6478bcb0991SDimitry Andric formatv("invalid LoopUnrollPass parameter '{0}' ", ParamName).str(),
6488bcb0991SDimitry Andric inconvertibleErrorCode());
6498bcb0991SDimitry Andric UnrollOpts.setFullUnrollMaxCount(Count);
6508bcb0991SDimitry Andric continue;
6518bcb0991SDimitry Andric }
6520b57cec5SDimitry Andric
6530b57cec5SDimitry Andric bool Enable = !ParamName.consume_front("no-");
6540b57cec5SDimitry Andric if (ParamName == "partial") {
6550b57cec5SDimitry Andric UnrollOpts.setPartial(Enable);
6560b57cec5SDimitry Andric } else if (ParamName == "peeling") {
6570b57cec5SDimitry Andric UnrollOpts.setPeeling(Enable);
6588bcb0991SDimitry Andric } else if (ParamName == "profile-peeling") {
6598bcb0991SDimitry Andric UnrollOpts.setProfileBasedPeeling(Enable);
6600b57cec5SDimitry Andric } else if (ParamName == "runtime") {
6610b57cec5SDimitry Andric UnrollOpts.setRuntime(Enable);
6620b57cec5SDimitry Andric } else if (ParamName == "upperbound") {
6630b57cec5SDimitry Andric UnrollOpts.setUpperBound(Enable);
6640b57cec5SDimitry Andric } else {
6650b57cec5SDimitry Andric return make_error<StringError>(
6660b57cec5SDimitry Andric formatv("invalid LoopUnrollPass parameter '{0}' ", ParamName).str(),
6670b57cec5SDimitry Andric inconvertibleErrorCode());
6680b57cec5SDimitry Andric }
6690b57cec5SDimitry Andric }
6700b57cec5SDimitry Andric return UnrollOpts;
6710b57cec5SDimitry Andric }
6720b57cec5SDimitry Andric
parseGlobalDCEPassOptions(StringRef Params)67306c3fb27SDimitry Andric Expected<bool> parseGlobalDCEPassOptions(StringRef Params) {
674*0fca6ea1SDimitry Andric return PassBuilder::parseSinglePassOption(
675*0fca6ea1SDimitry Andric Params, "vfe-linkage-unit-visibility", "GlobalDCE");
67606c3fb27SDimitry Andric }
67706c3fb27SDimitry Andric
parseCGProfilePassOptions(StringRef Params)6787a6dacacSDimitry Andric Expected<bool> parseCGProfilePassOptions(StringRef Params) {
679*0fca6ea1SDimitry Andric return PassBuilder::parseSinglePassOption(Params, "in-lto-post-link",
680*0fca6ea1SDimitry Andric "CGProfile");
6817a6dacacSDimitry Andric }
6827a6dacacSDimitry Andric
parseInlinerPassOptions(StringRef Params)683349cc55cSDimitry Andric Expected<bool> parseInlinerPassOptions(StringRef Params) {
684*0fca6ea1SDimitry Andric return PassBuilder::parseSinglePassOption(Params, "only-mandatory",
685*0fca6ea1SDimitry Andric "InlinerPass");
686349cc55cSDimitry Andric }
687349cc55cSDimitry Andric
parseCoroSplitPassOptions(StringRef Params)68881ad6265SDimitry Andric Expected<bool> parseCoroSplitPassOptions(StringRef Params) {
689*0fca6ea1SDimitry Andric return PassBuilder::parseSinglePassOption(Params, "reuse-storage",
690*0fca6ea1SDimitry Andric "CoroSplitPass");
69181ad6265SDimitry Andric }
69281ad6265SDimitry Andric
parsePostOrderFunctionAttrsPassOptions(StringRef Params)69306c3fb27SDimitry Andric Expected<bool> parsePostOrderFunctionAttrsPassOptions(StringRef Params) {
694*0fca6ea1SDimitry Andric return PassBuilder::parseSinglePassOption(
695*0fca6ea1SDimitry Andric Params, "skip-non-recursive-function-attrs", "PostOrderFunctionAttrs");
69606c3fb27SDimitry Andric }
69706c3fb27SDimitry Andric
parseCFGuardPassOptions(StringRef Params)6985f757f3fSDimitry Andric Expected<CFGuardPass::Mechanism> parseCFGuardPassOptions(StringRef Params) {
6995f757f3fSDimitry Andric if (Params.empty())
7005f757f3fSDimitry Andric return CFGuardPass::Mechanism::Check;
7015f757f3fSDimitry Andric
7025f757f3fSDimitry Andric auto [Param, RHS] = Params.split(';');
7035f757f3fSDimitry Andric if (!RHS.empty())
7045f757f3fSDimitry Andric return make_error<StringError>(
7055f757f3fSDimitry Andric formatv("too many CFGuardPass parameters '{0}' ", Params).str(),
7065f757f3fSDimitry Andric inconvertibleErrorCode());
7075f757f3fSDimitry Andric
7085f757f3fSDimitry Andric if (Param == "check")
7095f757f3fSDimitry Andric return CFGuardPass::Mechanism::Check;
7105f757f3fSDimitry Andric if (Param == "dispatch")
7115f757f3fSDimitry Andric return CFGuardPass::Mechanism::Dispatch;
7125f757f3fSDimitry Andric
7135f757f3fSDimitry Andric return make_error<StringError>(
7145f757f3fSDimitry Andric formatv("invalid CFGuardPass mechanism: '{0}' ", Param).str(),
7155f757f3fSDimitry Andric inconvertibleErrorCode());
7165f757f3fSDimitry Andric }
7175f757f3fSDimitry Andric
parseEarlyCSEPassOptions(StringRef Params)718349cc55cSDimitry Andric Expected<bool> parseEarlyCSEPassOptions(StringRef Params) {
719*0fca6ea1SDimitry Andric return PassBuilder::parseSinglePassOption(Params, "memssa", "EarlyCSE");
720349cc55cSDimitry Andric }
721349cc55cSDimitry Andric
parseEntryExitInstrumenterPassOptions(StringRef Params)722349cc55cSDimitry Andric Expected<bool> parseEntryExitInstrumenterPassOptions(StringRef Params) {
723*0fca6ea1SDimitry Andric return PassBuilder::parseSinglePassOption(Params, "post-inline",
724*0fca6ea1SDimitry Andric "EntryExitInstrumenter");
725349cc55cSDimitry Andric }
726349cc55cSDimitry Andric
parseLoopExtractorPassOptions(StringRef Params)727349cc55cSDimitry Andric Expected<bool> parseLoopExtractorPassOptions(StringRef Params) {
728*0fca6ea1SDimitry Andric return PassBuilder::parseSinglePassOption(Params, "single", "LoopExtractor");
729349cc55cSDimitry Andric }
730349cc55cSDimitry Andric
parseLowerMatrixIntrinsicsPassOptions(StringRef Params)731349cc55cSDimitry Andric Expected<bool> parseLowerMatrixIntrinsicsPassOptions(StringRef Params) {
732*0fca6ea1SDimitry Andric return PassBuilder::parseSinglePassOption(Params, "minimal",
733*0fca6ea1SDimitry Andric "LowerMatrixIntrinsics");
734349cc55cSDimitry Andric }
735349cc55cSDimitry Andric
parseASanPassOptions(StringRef Params)736349cc55cSDimitry Andric Expected<AddressSanitizerOptions> parseASanPassOptions(StringRef Params) {
737349cc55cSDimitry Andric AddressSanitizerOptions Result;
738349cc55cSDimitry Andric while (!Params.empty()) {
739349cc55cSDimitry Andric StringRef ParamName;
740349cc55cSDimitry Andric std::tie(ParamName, Params) = Params.split(';');
741349cc55cSDimitry Andric
742349cc55cSDimitry Andric if (ParamName == "kernel") {
743349cc55cSDimitry Andric Result.CompileKernel = true;
744349cc55cSDimitry Andric } else {
745349cc55cSDimitry Andric return make_error<StringError>(
746349cc55cSDimitry Andric formatv("invalid AddressSanitizer pass parameter '{0}' ", ParamName)
747349cc55cSDimitry Andric .str(),
748349cc55cSDimitry Andric inconvertibleErrorCode());
749349cc55cSDimitry Andric }
750349cc55cSDimitry Andric }
751349cc55cSDimitry Andric return Result;
752349cc55cSDimitry Andric }
753349cc55cSDimitry Andric
parseHWASanPassOptions(StringRef Params)754349cc55cSDimitry Andric Expected<HWAddressSanitizerOptions> parseHWASanPassOptions(StringRef Params) {
755349cc55cSDimitry Andric HWAddressSanitizerOptions Result;
756349cc55cSDimitry Andric while (!Params.empty()) {
757349cc55cSDimitry Andric StringRef ParamName;
758349cc55cSDimitry Andric std::tie(ParamName, Params) = Params.split(';');
759349cc55cSDimitry Andric
760349cc55cSDimitry Andric if (ParamName == "recover") {
761349cc55cSDimitry Andric Result.Recover = true;
762349cc55cSDimitry Andric } else if (ParamName == "kernel") {
763349cc55cSDimitry Andric Result.CompileKernel = true;
764349cc55cSDimitry Andric } else {
765349cc55cSDimitry Andric return make_error<StringError>(
766349cc55cSDimitry Andric formatv("invalid HWAddressSanitizer pass parameter '{0}' ", ParamName)
767349cc55cSDimitry Andric .str(),
768349cc55cSDimitry Andric inconvertibleErrorCode());
769349cc55cSDimitry Andric }
770349cc55cSDimitry Andric }
771349cc55cSDimitry Andric return Result;
772349cc55cSDimitry Andric }
773349cc55cSDimitry Andric
parseEmbedBitcodePassOptions(StringRef Params)7747a6dacacSDimitry Andric Expected<EmbedBitcodeOptions> parseEmbedBitcodePassOptions(StringRef Params) {
7757a6dacacSDimitry Andric EmbedBitcodeOptions Result;
7767a6dacacSDimitry Andric while (!Params.empty()) {
7777a6dacacSDimitry Andric StringRef ParamName;
7787a6dacacSDimitry Andric std::tie(ParamName, Params) = Params.split(';');
7797a6dacacSDimitry Andric
7807a6dacacSDimitry Andric if (ParamName == "thinlto") {
7817a6dacacSDimitry Andric Result.IsThinLTO = true;
7827a6dacacSDimitry Andric } else if (ParamName == "emit-summary") {
7837a6dacacSDimitry Andric Result.EmitLTOSummary = true;
7847a6dacacSDimitry Andric } else {
7857a6dacacSDimitry Andric return make_error<StringError>(
7867a6dacacSDimitry Andric formatv("invalid EmbedBitcode pass parameter '{0}' ", ParamName)
7877a6dacacSDimitry Andric .str(),
7887a6dacacSDimitry Andric inconvertibleErrorCode());
7897a6dacacSDimitry Andric }
7907a6dacacSDimitry Andric }
7917a6dacacSDimitry Andric return Result;
7927a6dacacSDimitry Andric }
7937a6dacacSDimitry Andric
parseMSanPassOptions(StringRef Params)7940b57cec5SDimitry Andric Expected<MemorySanitizerOptions> parseMSanPassOptions(StringRef Params) {
7950b57cec5SDimitry Andric MemorySanitizerOptions Result;
7960b57cec5SDimitry Andric while (!Params.empty()) {
7970b57cec5SDimitry Andric StringRef ParamName;
7980b57cec5SDimitry Andric std::tie(ParamName, Params) = Params.split(';');
7990b57cec5SDimitry Andric
8000b57cec5SDimitry Andric if (ParamName == "recover") {
8010b57cec5SDimitry Andric Result.Recover = true;
8020b57cec5SDimitry Andric } else if (ParamName == "kernel") {
8030b57cec5SDimitry Andric Result.Kernel = true;
8040b57cec5SDimitry Andric } else if (ParamName.consume_front("track-origins=")) {
8050b57cec5SDimitry Andric if (ParamName.getAsInteger(0, Result.TrackOrigins))
8060b57cec5SDimitry Andric return make_error<StringError>(
8070b57cec5SDimitry Andric formatv("invalid argument to MemorySanitizer pass track-origins "
8080b57cec5SDimitry Andric "parameter: '{0}' ",
8090b57cec5SDimitry Andric ParamName)
8100b57cec5SDimitry Andric .str(),
8110b57cec5SDimitry Andric inconvertibleErrorCode());
81204eeddc0SDimitry Andric } else if (ParamName == "eager-checks") {
81304eeddc0SDimitry Andric Result.EagerChecks = true;
8140b57cec5SDimitry Andric } else {
8150b57cec5SDimitry Andric return make_error<StringError>(
8160b57cec5SDimitry Andric formatv("invalid MemorySanitizer pass parameter '{0}' ", ParamName)
8170b57cec5SDimitry Andric .str(),
8180b57cec5SDimitry Andric inconvertibleErrorCode());
8190b57cec5SDimitry Andric }
8200b57cec5SDimitry Andric }
8210b57cec5SDimitry Andric return Result;
8220b57cec5SDimitry Andric }
8230b57cec5SDimitry Andric
8240b57cec5SDimitry Andric /// Parser of parameters for SimplifyCFG pass.
parseSimplifyCFGOptions(StringRef Params)8250b57cec5SDimitry Andric Expected<SimplifyCFGOptions> parseSimplifyCFGOptions(StringRef Params) {
8260b57cec5SDimitry Andric SimplifyCFGOptions Result;
8270b57cec5SDimitry Andric while (!Params.empty()) {
8280b57cec5SDimitry Andric StringRef ParamName;
8290b57cec5SDimitry Andric std::tie(ParamName, Params) = Params.split(';');
8300b57cec5SDimitry Andric
8310b57cec5SDimitry Andric bool Enable = !ParamName.consume_front("no-");
83206c3fb27SDimitry Andric if (ParamName == "speculate-blocks") {
83306c3fb27SDimitry Andric Result.speculateBlocks(Enable);
83406c3fb27SDimitry Andric } else if (ParamName == "simplify-cond-branch") {
83506c3fb27SDimitry Andric Result.setSimplifyCondBranch(Enable);
83606c3fb27SDimitry Andric } else if (ParamName == "forward-switch-cond") {
8370b57cec5SDimitry Andric Result.forwardSwitchCondToPhi(Enable);
838fb03ea46SDimitry Andric } else if (ParamName == "switch-range-to-icmp") {
839fb03ea46SDimitry Andric Result.convertSwitchRangeToICmp(Enable);
8400b57cec5SDimitry Andric } else if (ParamName == "switch-to-lookup") {
8410b57cec5SDimitry Andric Result.convertSwitchToLookupTable(Enable);
8420b57cec5SDimitry Andric } else if (ParamName == "keep-loops") {
8430b57cec5SDimitry Andric Result.needCanonicalLoops(Enable);
844e8d8bef9SDimitry Andric } else if (ParamName == "hoist-common-insts") {
845e8d8bef9SDimitry Andric Result.hoistCommonInsts(Enable);
8460b57cec5SDimitry Andric } else if (ParamName == "sink-common-insts") {
8470b57cec5SDimitry Andric Result.sinkCommonInsts(Enable);
848*0fca6ea1SDimitry Andric } else if (ParamName == "speculate-unpredictables") {
849*0fca6ea1SDimitry Andric Result.speculateUnpredictables(Enable);
8500b57cec5SDimitry Andric } else if (Enable && ParamName.consume_front("bonus-inst-threshold=")) {
8510b57cec5SDimitry Andric APInt BonusInstThreshold;
8520b57cec5SDimitry Andric if (ParamName.getAsInteger(0, BonusInstThreshold))
8530b57cec5SDimitry Andric return make_error<StringError>(
8540b57cec5SDimitry Andric formatv("invalid argument to SimplifyCFG pass bonus-threshold "
8550b57cec5SDimitry Andric "parameter: '{0}' ",
8560b57cec5SDimitry Andric ParamName).str(),
8570b57cec5SDimitry Andric inconvertibleErrorCode());
8580b57cec5SDimitry Andric Result.bonusInstThreshold(BonusInstThreshold.getSExtValue());
8590b57cec5SDimitry Andric } else {
8600b57cec5SDimitry Andric return make_error<StringError>(
8610b57cec5SDimitry Andric formatv("invalid SimplifyCFG pass parameter '{0}' ", ParamName).str(),
8620b57cec5SDimitry Andric inconvertibleErrorCode());
8630b57cec5SDimitry Andric }
8640b57cec5SDimitry Andric }
8650b57cec5SDimitry Andric return Result;
8660b57cec5SDimitry Andric }
8670b57cec5SDimitry Andric
parseInstCombineOptions(StringRef Params)86806c3fb27SDimitry Andric Expected<InstCombineOptions> parseInstCombineOptions(StringRef Params) {
86906c3fb27SDimitry Andric InstCombineOptions Result;
8705f757f3fSDimitry Andric // When specifying "instcombine" in -passes enable fix-point verification by
8715f757f3fSDimitry Andric // default, as this is what most tests should use.
8725f757f3fSDimitry Andric Result.setVerifyFixpoint(true);
87306c3fb27SDimitry Andric while (!Params.empty()) {
87406c3fb27SDimitry Andric StringRef ParamName;
87506c3fb27SDimitry Andric std::tie(ParamName, Params) = Params.split(';');
87606c3fb27SDimitry Andric
87706c3fb27SDimitry Andric bool Enable = !ParamName.consume_front("no-");
87806c3fb27SDimitry Andric if (ParamName == "use-loop-info") {
87906c3fb27SDimitry Andric Result.setUseLoopInfo(Enable);
8805f757f3fSDimitry Andric } else if (ParamName == "verify-fixpoint") {
8815f757f3fSDimitry Andric Result.setVerifyFixpoint(Enable);
88206c3fb27SDimitry Andric } else if (Enable && ParamName.consume_front("max-iterations=")) {
88306c3fb27SDimitry Andric APInt MaxIterations;
88406c3fb27SDimitry Andric if (ParamName.getAsInteger(0, MaxIterations))
88506c3fb27SDimitry Andric return make_error<StringError>(
88606c3fb27SDimitry Andric formatv("invalid argument to InstCombine pass max-iterations "
88706c3fb27SDimitry Andric "parameter: '{0}' ",
88806c3fb27SDimitry Andric ParamName).str(),
88906c3fb27SDimitry Andric inconvertibleErrorCode());
89006c3fb27SDimitry Andric Result.setMaxIterations((unsigned)MaxIterations.getZExtValue());
89106c3fb27SDimitry Andric } else {
89206c3fb27SDimitry Andric return make_error<StringError>(
89306c3fb27SDimitry Andric formatv("invalid InstCombine pass parameter '{0}' ", ParamName).str(),
89406c3fb27SDimitry Andric inconvertibleErrorCode());
89506c3fb27SDimitry Andric }
89606c3fb27SDimitry Andric }
89706c3fb27SDimitry Andric return Result;
89806c3fb27SDimitry Andric }
89906c3fb27SDimitry Andric
9000b57cec5SDimitry Andric /// Parser of parameters for LoopVectorize pass.
parseLoopVectorizeOptions(StringRef Params)9010b57cec5SDimitry Andric Expected<LoopVectorizeOptions> parseLoopVectorizeOptions(StringRef Params) {
9020b57cec5SDimitry Andric LoopVectorizeOptions Opts;
9030b57cec5SDimitry Andric while (!Params.empty()) {
9040b57cec5SDimitry Andric StringRef ParamName;
9050b57cec5SDimitry Andric std::tie(ParamName, Params) = Params.split(';');
9060b57cec5SDimitry Andric
9070b57cec5SDimitry Andric bool Enable = !ParamName.consume_front("no-");
9080b57cec5SDimitry Andric if (ParamName == "interleave-forced-only") {
9090b57cec5SDimitry Andric Opts.setInterleaveOnlyWhenForced(Enable);
9100b57cec5SDimitry Andric } else if (ParamName == "vectorize-forced-only") {
9110b57cec5SDimitry Andric Opts.setVectorizeOnlyWhenForced(Enable);
9120b57cec5SDimitry Andric } else {
9130b57cec5SDimitry Andric return make_error<StringError>(
9140b57cec5SDimitry Andric formatv("invalid LoopVectorize parameter '{0}' ", ParamName).str(),
9150b57cec5SDimitry Andric inconvertibleErrorCode());
9160b57cec5SDimitry Andric }
9170b57cec5SDimitry Andric }
9180b57cec5SDimitry Andric return Opts;
9190b57cec5SDimitry Andric }
9200b57cec5SDimitry Andric
parseLoopUnswitchOptions(StringRef Params)921fe6060f1SDimitry Andric Expected<std::pair<bool, bool>> parseLoopUnswitchOptions(StringRef Params) {
922fe6060f1SDimitry Andric std::pair<bool, bool> Result = {false, true};
9230b57cec5SDimitry Andric while (!Params.empty()) {
9240b57cec5SDimitry Andric StringRef ParamName;
9250b57cec5SDimitry Andric std::tie(ParamName, Params) = Params.split(';');
9260b57cec5SDimitry Andric
9270b57cec5SDimitry Andric bool Enable = !ParamName.consume_front("no-");
9280b57cec5SDimitry Andric if (ParamName == "nontrivial") {
929fe6060f1SDimitry Andric Result.first = Enable;
930fe6060f1SDimitry Andric } else if (ParamName == "trivial") {
931fe6060f1SDimitry Andric Result.second = Enable;
9320b57cec5SDimitry Andric } else {
9330b57cec5SDimitry Andric return make_error<StringError>(
9340b57cec5SDimitry Andric formatv("invalid LoopUnswitch pass parameter '{0}' ", ParamName)
9350b57cec5SDimitry Andric .str(),
9360b57cec5SDimitry Andric inconvertibleErrorCode());
9370b57cec5SDimitry Andric }
9380b57cec5SDimitry Andric }
9390b57cec5SDimitry Andric return Result;
9400b57cec5SDimitry Andric }
9418bcb0991SDimitry Andric
parseLICMOptions(StringRef Params)94281ad6265SDimitry Andric Expected<LICMOptions> parseLICMOptions(StringRef Params) {
94381ad6265SDimitry Andric LICMOptions Result;
94481ad6265SDimitry Andric while (!Params.empty()) {
94581ad6265SDimitry Andric StringRef ParamName;
94681ad6265SDimitry Andric std::tie(ParamName, Params) = Params.split(';');
94781ad6265SDimitry Andric
94881ad6265SDimitry Andric bool Enable = !ParamName.consume_front("no-");
94981ad6265SDimitry Andric if (ParamName == "allowspeculation") {
95081ad6265SDimitry Andric Result.AllowSpeculation = Enable;
95181ad6265SDimitry Andric } else {
95281ad6265SDimitry Andric return make_error<StringError>(
95381ad6265SDimitry Andric formatv("invalid LICM pass parameter '{0}' ", ParamName).str(),
95481ad6265SDimitry Andric inconvertibleErrorCode());
95581ad6265SDimitry Andric }
95681ad6265SDimitry Andric }
95781ad6265SDimitry Andric return Result;
95881ad6265SDimitry Andric }
95981ad6265SDimitry Andric
parseLoopRotateOptions(StringRef Params)96006c3fb27SDimitry Andric Expected<std::pair<bool, bool>> parseLoopRotateOptions(StringRef Params) {
96106c3fb27SDimitry Andric std::pair<bool, bool> Result = {true, false};
96206c3fb27SDimitry Andric while (!Params.empty()) {
96306c3fb27SDimitry Andric StringRef ParamName;
96406c3fb27SDimitry Andric std::tie(ParamName, Params) = Params.split(';');
96506c3fb27SDimitry Andric
96606c3fb27SDimitry Andric bool Enable = !ParamName.consume_front("no-");
96706c3fb27SDimitry Andric if (ParamName == "header-duplication") {
96806c3fb27SDimitry Andric Result.first = Enable;
96906c3fb27SDimitry Andric } else if (ParamName == "prepare-for-lto") {
97006c3fb27SDimitry Andric Result.second = Enable;
97106c3fb27SDimitry Andric } else {
97206c3fb27SDimitry Andric return make_error<StringError>(
97306c3fb27SDimitry Andric formatv("invalid LoopRotate pass parameter '{0}' ", ParamName).str(),
97406c3fb27SDimitry Andric inconvertibleErrorCode());
97506c3fb27SDimitry Andric }
97606c3fb27SDimitry Andric }
97706c3fb27SDimitry Andric return Result;
97806c3fb27SDimitry Andric }
97906c3fb27SDimitry Andric
parseMergedLoadStoreMotionOptions(StringRef Params)9808bcb0991SDimitry Andric Expected<bool> parseMergedLoadStoreMotionOptions(StringRef Params) {
9818bcb0991SDimitry Andric bool Result = false;
9828bcb0991SDimitry Andric while (!Params.empty()) {
9838bcb0991SDimitry Andric StringRef ParamName;
9848bcb0991SDimitry Andric std::tie(ParamName, Params) = Params.split(';');
9858bcb0991SDimitry Andric
9868bcb0991SDimitry Andric bool Enable = !ParamName.consume_front("no-");
9878bcb0991SDimitry Andric if (ParamName == "split-footer-bb") {
9888bcb0991SDimitry Andric Result = Enable;
9898bcb0991SDimitry Andric } else {
9908bcb0991SDimitry Andric return make_error<StringError>(
9918bcb0991SDimitry Andric formatv("invalid MergedLoadStoreMotion pass parameter '{0}' ",
9928bcb0991SDimitry Andric ParamName)
9938bcb0991SDimitry Andric .str(),
9948bcb0991SDimitry Andric inconvertibleErrorCode());
9958bcb0991SDimitry Andric }
9968bcb0991SDimitry Andric }
9978bcb0991SDimitry Andric return Result;
9988bcb0991SDimitry Andric }
9995ffd83dbSDimitry Andric
parseGVNOptions(StringRef Params)10005ffd83dbSDimitry Andric Expected<GVNOptions> parseGVNOptions(StringRef Params) {
10015ffd83dbSDimitry Andric GVNOptions Result;
10025ffd83dbSDimitry Andric while (!Params.empty()) {
10035ffd83dbSDimitry Andric StringRef ParamName;
10045ffd83dbSDimitry Andric std::tie(ParamName, Params) = Params.split(';');
10055ffd83dbSDimitry Andric
10065ffd83dbSDimitry Andric bool Enable = !ParamName.consume_front("no-");
10075ffd83dbSDimitry Andric if (ParamName == "pre") {
10085ffd83dbSDimitry Andric Result.setPRE(Enable);
10095ffd83dbSDimitry Andric } else if (ParamName == "load-pre") {
10105ffd83dbSDimitry Andric Result.setLoadPRE(Enable);
1011e8d8bef9SDimitry Andric } else if (ParamName == "split-backedge-load-pre") {
1012e8d8bef9SDimitry Andric Result.setLoadPRESplitBackedge(Enable);
10135ffd83dbSDimitry Andric } else if (ParamName == "memdep") {
10145ffd83dbSDimitry Andric Result.setMemDep(Enable);
10155ffd83dbSDimitry Andric } else {
10165ffd83dbSDimitry Andric return make_error<StringError>(
10175ffd83dbSDimitry Andric formatv("invalid GVN pass parameter '{0}' ", ParamName).str(),
10185ffd83dbSDimitry Andric inconvertibleErrorCode());
10195ffd83dbSDimitry Andric }
10205ffd83dbSDimitry Andric }
10215ffd83dbSDimitry Andric return Result;
10225ffd83dbSDimitry Andric }
10235ffd83dbSDimitry Andric
parseIPSCCPOptions(StringRef Params)1024bdd1243dSDimitry Andric Expected<IPSCCPOptions> parseIPSCCPOptions(StringRef Params) {
1025bdd1243dSDimitry Andric IPSCCPOptions Result;
1026bdd1243dSDimitry Andric while (!Params.empty()) {
1027bdd1243dSDimitry Andric StringRef ParamName;
1028bdd1243dSDimitry Andric std::tie(ParamName, Params) = Params.split(';');
1029bdd1243dSDimitry Andric
1030bdd1243dSDimitry Andric bool Enable = !ParamName.consume_front("no-");
1031bdd1243dSDimitry Andric if (ParamName == "func-spec")
1032bdd1243dSDimitry Andric Result.setFuncSpec(Enable);
1033bdd1243dSDimitry Andric else
1034bdd1243dSDimitry Andric return make_error<StringError>(
1035bdd1243dSDimitry Andric formatv("invalid IPSCCP pass parameter '{0}' ", ParamName).str(),
1036bdd1243dSDimitry Andric inconvertibleErrorCode());
1037bdd1243dSDimitry Andric }
1038bdd1243dSDimitry Andric return Result;
1039bdd1243dSDimitry Andric }
1040bdd1243dSDimitry Andric
parseSROAOptions(StringRef Params)1041bdd1243dSDimitry Andric Expected<SROAOptions> parseSROAOptions(StringRef Params) {
1042bdd1243dSDimitry Andric if (Params.empty() || Params == "modify-cfg")
1043bdd1243dSDimitry Andric return SROAOptions::ModifyCFG;
1044bdd1243dSDimitry Andric if (Params == "preserve-cfg")
1045bdd1243dSDimitry Andric return SROAOptions::PreserveCFG;
1046bdd1243dSDimitry Andric return make_error<StringError>(
1047bdd1243dSDimitry Andric formatv("invalid SROA pass parameter '{0}' (either preserve-cfg or "
1048bdd1243dSDimitry Andric "modify-cfg can be specified)",
1049bdd1243dSDimitry Andric Params)
1050bdd1243dSDimitry Andric .str(),
1051bdd1243dSDimitry Andric inconvertibleErrorCode());
1052bdd1243dSDimitry Andric }
1053bdd1243dSDimitry Andric
10545ffd83dbSDimitry Andric Expected<StackLifetime::LivenessType>
parseStackLifetimeOptions(StringRef Params)10555ffd83dbSDimitry Andric parseStackLifetimeOptions(StringRef Params) {
10565ffd83dbSDimitry Andric StackLifetime::LivenessType Result = StackLifetime::LivenessType::May;
10575ffd83dbSDimitry Andric while (!Params.empty()) {
10585ffd83dbSDimitry Andric StringRef ParamName;
10595ffd83dbSDimitry Andric std::tie(ParamName, Params) = Params.split(';');
10605ffd83dbSDimitry Andric
10615ffd83dbSDimitry Andric if (ParamName == "may") {
10625ffd83dbSDimitry Andric Result = StackLifetime::LivenessType::May;
10635ffd83dbSDimitry Andric } else if (ParamName == "must") {
10645ffd83dbSDimitry Andric Result = StackLifetime::LivenessType::Must;
10655ffd83dbSDimitry Andric } else {
10665ffd83dbSDimitry Andric return make_error<StringError>(
10675ffd83dbSDimitry Andric formatv("invalid StackLifetime parameter '{0}' ", ParamName).str(),
10685ffd83dbSDimitry Andric inconvertibleErrorCode());
10695ffd83dbSDimitry Andric }
10705ffd83dbSDimitry Andric }
10715ffd83dbSDimitry Andric return Result;
10725ffd83dbSDimitry Andric }
10735ffd83dbSDimitry Andric
parseDependenceAnalysisPrinterOptions(StringRef Params)1074bdd1243dSDimitry Andric Expected<bool> parseDependenceAnalysisPrinterOptions(StringRef Params) {
1075*0fca6ea1SDimitry Andric return PassBuilder::parseSinglePassOption(Params, "normalized-results",
1076bdd1243dSDimitry Andric "DependenceAnalysisPrinter");
1077bdd1243dSDimitry Andric }
1078bdd1243dSDimitry Andric
parseSeparateConstOffsetFromGEPPassOptions(StringRef Params)107906c3fb27SDimitry Andric Expected<bool> parseSeparateConstOffsetFromGEPPassOptions(StringRef Params) {
1080*0fca6ea1SDimitry Andric return PassBuilder::parseSinglePassOption(Params, "lower-gep",
108106c3fb27SDimitry Andric "SeparateConstOffsetFromGEP");
108206c3fb27SDimitry Andric }
108306c3fb27SDimitry Andric
108406c3fb27SDimitry Andric Expected<OptimizationLevel>
parseFunctionSimplificationPipelineOptions(StringRef Params)108506c3fb27SDimitry Andric parseFunctionSimplificationPipelineOptions(StringRef Params) {
108606c3fb27SDimitry Andric std::optional<OptimizationLevel> L = parseOptLevel(Params);
108706c3fb27SDimitry Andric if (!L || *L == OptimizationLevel::O0) {
108806c3fb27SDimitry Andric return make_error<StringError>(
108906c3fb27SDimitry Andric formatv("invalid function-simplification parameter '{0}' ", Params)
109006c3fb27SDimitry Andric .str(),
109106c3fb27SDimitry Andric inconvertibleErrorCode());
109206c3fb27SDimitry Andric };
109306c3fb27SDimitry Andric return *L;
109406c3fb27SDimitry Andric }
109506c3fb27SDimitry Andric
parseMemorySSAPrinterPassOptions(StringRef Params)109606c3fb27SDimitry Andric Expected<bool> parseMemorySSAPrinterPassOptions(StringRef Params) {
1097*0fca6ea1SDimitry Andric return PassBuilder::parseSinglePassOption(Params, "no-ensure-optimized-uses",
109806c3fb27SDimitry Andric "MemorySSAPrinterPass");
109906c3fb27SDimitry Andric }
110006c3fb27SDimitry Andric
parseSpeculativeExecutionPassOptions(StringRef Params)11015f757f3fSDimitry Andric Expected<bool> parseSpeculativeExecutionPassOptions(StringRef Params) {
1102*0fca6ea1SDimitry Andric return PassBuilder::parseSinglePassOption(Params, "only-if-divergent-target",
11035f757f3fSDimitry Andric "SpeculativeExecutionPass");
11045f757f3fSDimitry Andric }
11055f757f3fSDimitry Andric
parseMemProfUsePassOptions(StringRef Params)110606c3fb27SDimitry Andric Expected<std::string> parseMemProfUsePassOptions(StringRef Params) {
110706c3fb27SDimitry Andric std::string Result;
110806c3fb27SDimitry Andric while (!Params.empty()) {
110906c3fb27SDimitry Andric StringRef ParamName;
111006c3fb27SDimitry Andric std::tie(ParamName, Params) = Params.split(';');
111106c3fb27SDimitry Andric
111206c3fb27SDimitry Andric if (ParamName.consume_front("profile-filename=")) {
111306c3fb27SDimitry Andric Result = ParamName.str();
111406c3fb27SDimitry Andric } else {
111506c3fb27SDimitry Andric return make_error<StringError>(
111606c3fb27SDimitry Andric formatv("invalid MemProfUse pass parameter '{0}' ", ParamName).str(),
111706c3fb27SDimitry Andric inconvertibleErrorCode());
111806c3fb27SDimitry Andric }
111906c3fb27SDimitry Andric }
112006c3fb27SDimitry Andric return Result;
112106c3fb27SDimitry Andric }
112206c3fb27SDimitry Andric
parseStructuralHashPrinterPassOptions(StringRef Params)11235f757f3fSDimitry Andric Expected<bool> parseStructuralHashPrinterPassOptions(StringRef Params) {
1124*0fca6ea1SDimitry Andric return PassBuilder::parseSinglePassOption(Params, "detailed",
11255f757f3fSDimitry Andric "StructuralHashPrinterPass");
11265f757f3fSDimitry Andric }
11275f757f3fSDimitry Andric
parseWinEHPrepareOptions(StringRef Params)11285f757f3fSDimitry Andric Expected<bool> parseWinEHPrepareOptions(StringRef Params) {
1129*0fca6ea1SDimitry Andric return PassBuilder::parseSinglePassOption(Params, "demote-catchswitch-only",
11305f757f3fSDimitry Andric "WinEHPreparePass");
11315f757f3fSDimitry Andric }
11325f757f3fSDimitry Andric
parseGlobalMergeOptions(StringRef Params)11337a6dacacSDimitry Andric Expected<GlobalMergeOptions> parseGlobalMergeOptions(StringRef Params) {
11347a6dacacSDimitry Andric GlobalMergeOptions Result;
11357a6dacacSDimitry Andric while (!Params.empty()) {
11367a6dacacSDimitry Andric StringRef ParamName;
11377a6dacacSDimitry Andric std::tie(ParamName, Params) = Params.split(';');
11387a6dacacSDimitry Andric
11397a6dacacSDimitry Andric bool Enable = !ParamName.consume_front("no-");
11407a6dacacSDimitry Andric if (ParamName == "group-by-use")
11417a6dacacSDimitry Andric Result.GroupByUse = Enable;
11427a6dacacSDimitry Andric else if (ParamName == "ignore-single-use")
11437a6dacacSDimitry Andric Result.IgnoreSingleUse = Enable;
11447a6dacacSDimitry Andric else if (ParamName == "merge-const")
11457a6dacacSDimitry Andric Result.MergeConst = Enable;
11467a6dacacSDimitry Andric else if (ParamName == "merge-external")
11477a6dacacSDimitry Andric Result.MergeExternal = Enable;
11487a6dacacSDimitry Andric else if (ParamName.consume_front("max-offset=")) {
11497a6dacacSDimitry Andric if (ParamName.getAsInteger(0, Result.MaxOffset))
11507a6dacacSDimitry Andric return make_error<StringError>(
11517a6dacacSDimitry Andric formatv("invalid GlobalMergePass parameter '{0}' ", ParamName)
11527a6dacacSDimitry Andric .str(),
11537a6dacacSDimitry Andric inconvertibleErrorCode());
11547a6dacacSDimitry Andric }
11557a6dacacSDimitry Andric }
11567a6dacacSDimitry Andric return Result;
11577a6dacacSDimitry Andric }
11587a6dacacSDimitry Andric
parseInternalizeGVs(StringRef Params)1159*0fca6ea1SDimitry Andric Expected<SmallVector<std::string, 0>> parseInternalizeGVs(StringRef Params) {
1160*0fca6ea1SDimitry Andric SmallVector<std::string, 1> PreservedGVs;
1161*0fca6ea1SDimitry Andric while (!Params.empty()) {
1162*0fca6ea1SDimitry Andric StringRef ParamName;
1163*0fca6ea1SDimitry Andric std::tie(ParamName, Params) = Params.split(';');
1164*0fca6ea1SDimitry Andric
1165*0fca6ea1SDimitry Andric if (ParamName.consume_front("preserve-gv=")) {
1166*0fca6ea1SDimitry Andric PreservedGVs.push_back(ParamName.str());
1167*0fca6ea1SDimitry Andric } else {
1168*0fca6ea1SDimitry Andric return make_error<StringError>(
1169*0fca6ea1SDimitry Andric formatv("invalid Internalize pass parameter '{0}' ", ParamName).str(),
1170*0fca6ea1SDimitry Andric inconvertibleErrorCode());
1171*0fca6ea1SDimitry Andric }
1172*0fca6ea1SDimitry Andric }
1173*0fca6ea1SDimitry Andric
1174*0fca6ea1SDimitry Andric return Expected<SmallVector<std::string, 0>>(std::move(PreservedGVs));
1175*0fca6ea1SDimitry Andric }
1176*0fca6ea1SDimitry Andric
1177*0fca6ea1SDimitry Andric Expected<RegAllocFastPassOptions>
parseRegAllocFastPassOptions(PassBuilder & PB,StringRef Params)1178*0fca6ea1SDimitry Andric parseRegAllocFastPassOptions(PassBuilder &PB, StringRef Params) {
1179*0fca6ea1SDimitry Andric RegAllocFastPassOptions Opts;
1180*0fca6ea1SDimitry Andric while (!Params.empty()) {
1181*0fca6ea1SDimitry Andric StringRef ParamName;
1182*0fca6ea1SDimitry Andric std::tie(ParamName, Params) = Params.split(';');
1183*0fca6ea1SDimitry Andric
1184*0fca6ea1SDimitry Andric if (ParamName.consume_front("filter=")) {
1185*0fca6ea1SDimitry Andric std::optional<RegAllocFilterFunc> Filter =
1186*0fca6ea1SDimitry Andric PB.parseRegAllocFilter(ParamName);
1187*0fca6ea1SDimitry Andric if (!Filter) {
1188*0fca6ea1SDimitry Andric return make_error<StringError>(
1189*0fca6ea1SDimitry Andric formatv("invalid regallocfast register filter '{0}' ", ParamName)
1190*0fca6ea1SDimitry Andric .str(),
1191*0fca6ea1SDimitry Andric inconvertibleErrorCode());
1192*0fca6ea1SDimitry Andric }
1193*0fca6ea1SDimitry Andric Opts.Filter = *Filter;
1194*0fca6ea1SDimitry Andric Opts.FilterName = ParamName;
1195*0fca6ea1SDimitry Andric continue;
1196*0fca6ea1SDimitry Andric }
1197*0fca6ea1SDimitry Andric
1198*0fca6ea1SDimitry Andric if (ParamName == "no-clear-vregs") {
1199*0fca6ea1SDimitry Andric Opts.ClearVRegs = false;
1200*0fca6ea1SDimitry Andric continue;
1201*0fca6ea1SDimitry Andric }
1202*0fca6ea1SDimitry Andric
1203*0fca6ea1SDimitry Andric return make_error<StringError>(
1204*0fca6ea1SDimitry Andric formatv("invalid regallocfast pass parameter '{0}' ", ParamName).str(),
1205*0fca6ea1SDimitry Andric inconvertibleErrorCode());
1206*0fca6ea1SDimitry Andric }
1207*0fca6ea1SDimitry Andric return Opts;
1208*0fca6ea1SDimitry Andric }
1209*0fca6ea1SDimitry Andric
12100b57cec5SDimitry Andric } // namespace
12110b57cec5SDimitry Andric
12120b57cec5SDimitry Andric /// Tests whether a pass name starts with a valid prefix for a default pipeline
12130b57cec5SDimitry Andric /// alias.
startsWithDefaultPipelineAliasPrefix(StringRef Name)12140b57cec5SDimitry Andric static bool startsWithDefaultPipelineAliasPrefix(StringRef Name) {
12155f757f3fSDimitry Andric return Name.starts_with("default") || Name.starts_with("thinlto") ||
12165f757f3fSDimitry Andric Name.starts_with("lto");
12170b57cec5SDimitry Andric }
12180b57cec5SDimitry Andric
12190b57cec5SDimitry Andric /// Tests whether registered callbacks will accept a given pass name.
12200b57cec5SDimitry Andric ///
12210b57cec5SDimitry Andric /// When parsing a pipeline text, the type of the outermost pipeline may be
12220b57cec5SDimitry Andric /// omitted, in which case the type is automatically determined from the first
12230b57cec5SDimitry Andric /// pass name in the text. This may be a name that is handled through one of the
12240b57cec5SDimitry Andric /// callbacks. We check this through the oridinary parsing callbacks by setting
12250b57cec5SDimitry Andric /// up a dummy PassManager in order to not force the client to also handle this
12260b57cec5SDimitry Andric /// type of query.
12270b57cec5SDimitry Andric template <typename PassManagerT, typename CallbacksT>
callbacksAcceptPassName(StringRef Name,CallbacksT & Callbacks)12280b57cec5SDimitry Andric static bool callbacksAcceptPassName(StringRef Name, CallbacksT &Callbacks) {
12290b57cec5SDimitry Andric if (!Callbacks.empty()) {
12300b57cec5SDimitry Andric PassManagerT DummyPM;
12310b57cec5SDimitry Andric for (auto &CB : Callbacks)
12320b57cec5SDimitry Andric if (CB(Name, DummyPM, {}))
12330b57cec5SDimitry Andric return true;
12340b57cec5SDimitry Andric }
12350b57cec5SDimitry Andric return false;
12360b57cec5SDimitry Andric }
12370b57cec5SDimitry Andric
12380b57cec5SDimitry Andric template <typename CallbacksT>
isModulePassName(StringRef Name,CallbacksT & Callbacks)12390b57cec5SDimitry Andric static bool isModulePassName(StringRef Name, CallbacksT &Callbacks) {
12400b57cec5SDimitry Andric // Manually handle aliases for pre-configured pipeline fragments.
12410b57cec5SDimitry Andric if (startsWithDefaultPipelineAliasPrefix(Name))
12420b57cec5SDimitry Andric return DefaultAliasRegex.match(Name);
12430b57cec5SDimitry Andric
124406c3fb27SDimitry Andric StringRef NameNoBracket = Name.take_until([](char C) { return C == '<'; });
124506c3fb27SDimitry Andric
12460b57cec5SDimitry Andric // Explicitly handle pass manager names.
12470b57cec5SDimitry Andric if (Name == "module")
12480b57cec5SDimitry Andric return true;
12490b57cec5SDimitry Andric if (Name == "cgscc")
12500b57cec5SDimitry Andric return true;
125106c3fb27SDimitry Andric if (NameNoBracket == "function")
12520b57cec5SDimitry Andric return true;
1253bdd1243dSDimitry Andric if (Name == "coro-cond")
1254bdd1243dSDimitry Andric return true;
12550b57cec5SDimitry Andric
12560b57cec5SDimitry Andric #define MODULE_PASS(NAME, CREATE_PASS) \
12570b57cec5SDimitry Andric if (Name == NAME) \
12580b57cec5SDimitry Andric return true;
1259349cc55cSDimitry Andric #define MODULE_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \
1260*0fca6ea1SDimitry Andric if (PassBuilder::checkParametrizedPassName(Name, NAME)) \
1261349cc55cSDimitry Andric return true;
12620b57cec5SDimitry Andric #define MODULE_ANALYSIS(NAME, CREATE_PASS) \
12630b57cec5SDimitry Andric if (Name == "require<" NAME ">" || Name == "invalidate<" NAME ">") \
12640b57cec5SDimitry Andric return true;
12650b57cec5SDimitry Andric #include "PassRegistry.def"
12660b57cec5SDimitry Andric
12670b57cec5SDimitry Andric return callbacksAcceptPassName<ModulePassManager>(Name, Callbacks);
12680b57cec5SDimitry Andric }
12690b57cec5SDimitry Andric
12700b57cec5SDimitry Andric template <typename CallbacksT>
isCGSCCPassName(StringRef Name,CallbacksT & Callbacks)12710b57cec5SDimitry Andric static bool isCGSCCPassName(StringRef Name, CallbacksT &Callbacks) {
12720b57cec5SDimitry Andric // Explicitly handle pass manager names.
127306c3fb27SDimitry Andric StringRef NameNoBracket = Name.take_until([](char C) { return C == '<'; });
12740b57cec5SDimitry Andric if (Name == "cgscc")
12750b57cec5SDimitry Andric return true;
127606c3fb27SDimitry Andric if (NameNoBracket == "function")
12770b57cec5SDimitry Andric return true;
12780b57cec5SDimitry Andric
12790b57cec5SDimitry Andric // Explicitly handle custom-parsed pass names.
12800b57cec5SDimitry Andric if (parseDevirtPassName(Name))
12810b57cec5SDimitry Andric return true;
12820b57cec5SDimitry Andric
12830b57cec5SDimitry Andric #define CGSCC_PASS(NAME, CREATE_PASS) \
12840b57cec5SDimitry Andric if (Name == NAME) \
12850b57cec5SDimitry Andric return true;
1286349cc55cSDimitry Andric #define CGSCC_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \
1287*0fca6ea1SDimitry Andric if (PassBuilder::checkParametrizedPassName(Name, NAME)) \
1288349cc55cSDimitry Andric return true;
12890b57cec5SDimitry Andric #define CGSCC_ANALYSIS(NAME, CREATE_PASS) \
12900b57cec5SDimitry Andric if (Name == "require<" NAME ">" || Name == "invalidate<" NAME ">") \
12910b57cec5SDimitry Andric return true;
12920b57cec5SDimitry Andric #include "PassRegistry.def"
12930b57cec5SDimitry Andric
12940b57cec5SDimitry Andric return callbacksAcceptPassName<CGSCCPassManager>(Name, Callbacks);
12950b57cec5SDimitry Andric }
12960b57cec5SDimitry Andric
12970b57cec5SDimitry Andric template <typename CallbacksT>
isFunctionPassName(StringRef Name,CallbacksT & Callbacks)12980b57cec5SDimitry Andric static bool isFunctionPassName(StringRef Name, CallbacksT &Callbacks) {
12990b57cec5SDimitry Andric // Explicitly handle pass manager names.
130006c3fb27SDimitry Andric StringRef NameNoBracket = Name.take_until([](char C) { return C == '<'; });
130106c3fb27SDimitry Andric if (NameNoBracket == "function")
13020b57cec5SDimitry Andric return true;
1303*0fca6ea1SDimitry Andric if (Name == "loop" || Name == "loop-mssa" || Name == "machine-function")
13040b57cec5SDimitry Andric return true;
13050b57cec5SDimitry Andric
13060b57cec5SDimitry Andric #define FUNCTION_PASS(NAME, CREATE_PASS) \
13070b57cec5SDimitry Andric if (Name == NAME) \
13080b57cec5SDimitry Andric return true;
1309fe6060f1SDimitry Andric #define FUNCTION_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \
1310*0fca6ea1SDimitry Andric if (PassBuilder::checkParametrizedPassName(Name, NAME)) \
13110b57cec5SDimitry Andric return true;
13120b57cec5SDimitry Andric #define FUNCTION_ANALYSIS(NAME, CREATE_PASS) \
13130b57cec5SDimitry Andric if (Name == "require<" NAME ">" || Name == "invalidate<" NAME ">") \
13140b57cec5SDimitry Andric return true;
13150b57cec5SDimitry Andric #include "PassRegistry.def"
13160b57cec5SDimitry Andric
13170b57cec5SDimitry Andric return callbacksAcceptPassName<FunctionPassManager>(Name, Callbacks);
13180b57cec5SDimitry Andric }
13190b57cec5SDimitry Andric
13200b57cec5SDimitry Andric template <typename CallbacksT>
isMachineFunctionPassName(StringRef Name,CallbacksT & Callbacks)1321*0fca6ea1SDimitry Andric static bool isMachineFunctionPassName(StringRef Name, CallbacksT &Callbacks) {
1322*0fca6ea1SDimitry Andric // Explicitly handle pass manager names.
1323*0fca6ea1SDimitry Andric if (Name == "machine-function")
1324*0fca6ea1SDimitry Andric return true;
1325*0fca6ea1SDimitry Andric
1326*0fca6ea1SDimitry Andric #define MACHINE_FUNCTION_PASS(NAME, CREATE_PASS) \
1327*0fca6ea1SDimitry Andric if (Name == NAME) \
1328*0fca6ea1SDimitry Andric return true;
1329*0fca6ea1SDimitry Andric #define MACHINE_FUNCTION_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, \
1330*0fca6ea1SDimitry Andric PARAMS) \
1331*0fca6ea1SDimitry Andric if (PassBuilder::checkParametrizedPassName(Name, NAME)) \
1332*0fca6ea1SDimitry Andric return true;
1333*0fca6ea1SDimitry Andric
1334*0fca6ea1SDimitry Andric #define MACHINE_FUNCTION_ANALYSIS(NAME, CREATE_PASS) \
1335*0fca6ea1SDimitry Andric if (Name == "require<" NAME ">" || Name == "invalidate<" NAME ">") \
1336*0fca6ea1SDimitry Andric return true;
1337*0fca6ea1SDimitry Andric
1338*0fca6ea1SDimitry Andric #include "llvm/Passes/MachinePassRegistry.def"
1339*0fca6ea1SDimitry Andric
1340*0fca6ea1SDimitry Andric return callbacksAcceptPassName<MachineFunctionPassManager>(Name, Callbacks);
1341*0fca6ea1SDimitry Andric }
1342*0fca6ea1SDimitry Andric
1343*0fca6ea1SDimitry Andric template <typename CallbacksT>
isLoopNestPassName(StringRef Name,CallbacksT & Callbacks,bool & UseMemorySSA)1344349cc55cSDimitry Andric static bool isLoopNestPassName(StringRef Name, CallbacksT &Callbacks,
1345349cc55cSDimitry Andric bool &UseMemorySSA) {
1346349cc55cSDimitry Andric UseMemorySSA = false;
13470b57cec5SDimitry Andric
1348*0fca6ea1SDimitry Andric if (PassBuilder::checkParametrizedPassName(Name, "lnicm")) {
1349349cc55cSDimitry Andric UseMemorySSA = true;
1350349cc55cSDimitry Andric return true;
1351349cc55cSDimitry Andric }
1352349cc55cSDimitry Andric
1353349cc55cSDimitry Andric #define LOOPNEST_PASS(NAME, CREATE_PASS) \
1354349cc55cSDimitry Andric if (Name == NAME) \
1355349cc55cSDimitry Andric return true;
1356349cc55cSDimitry Andric #include "PassRegistry.def"
1357349cc55cSDimitry Andric
1358349cc55cSDimitry Andric return callbacksAcceptPassName<LoopPassManager>(Name, Callbacks);
1359349cc55cSDimitry Andric }
1360349cc55cSDimitry Andric
1361349cc55cSDimitry Andric template <typename CallbacksT>
isLoopPassName(StringRef Name,CallbacksT & Callbacks,bool & UseMemorySSA)1362349cc55cSDimitry Andric static bool isLoopPassName(StringRef Name, CallbacksT &Callbacks,
1363349cc55cSDimitry Andric bool &UseMemorySSA) {
1364349cc55cSDimitry Andric UseMemorySSA = false;
1365349cc55cSDimitry Andric
1366*0fca6ea1SDimitry Andric if (PassBuilder::checkParametrizedPassName(Name, "licm")) {
1367349cc55cSDimitry Andric UseMemorySSA = true;
1368349cc55cSDimitry Andric return true;
1369349cc55cSDimitry Andric }
1370349cc55cSDimitry Andric
13710b57cec5SDimitry Andric #define LOOP_PASS(NAME, CREATE_PASS) \
13720b57cec5SDimitry Andric if (Name == NAME) \
13730b57cec5SDimitry Andric return true;
1374fe6060f1SDimitry Andric #define LOOP_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \
1375*0fca6ea1SDimitry Andric if (PassBuilder::checkParametrizedPassName(Name, NAME)) \
13760b57cec5SDimitry Andric return true;
13770b57cec5SDimitry Andric #define LOOP_ANALYSIS(NAME, CREATE_PASS) \
13780b57cec5SDimitry Andric if (Name == "require<" NAME ">" || Name == "invalidate<" NAME ">") \
13790b57cec5SDimitry Andric return true;
13800b57cec5SDimitry Andric #include "PassRegistry.def"
13810b57cec5SDimitry Andric
13820b57cec5SDimitry Andric return callbacksAcceptPassName<LoopPassManager>(Name, Callbacks);
13830b57cec5SDimitry Andric }
13840b57cec5SDimitry Andric
1385bdd1243dSDimitry Andric std::optional<std::vector<PassBuilder::PipelineElement>>
parsePipelineText(StringRef Text)13860b57cec5SDimitry Andric PassBuilder::parsePipelineText(StringRef Text) {
13870b57cec5SDimitry Andric std::vector<PipelineElement> ResultPipeline;
13880b57cec5SDimitry Andric
13890b57cec5SDimitry Andric SmallVector<std::vector<PipelineElement> *, 4> PipelineStack = {
13900b57cec5SDimitry Andric &ResultPipeline};
13910b57cec5SDimitry Andric for (;;) {
13920b57cec5SDimitry Andric std::vector<PipelineElement> &Pipeline = *PipelineStack.back();
13930b57cec5SDimitry Andric size_t Pos = Text.find_first_of(",()");
13940b57cec5SDimitry Andric Pipeline.push_back({Text.substr(0, Pos), {}});
13950b57cec5SDimitry Andric
13960b57cec5SDimitry Andric // If we have a single terminating name, we're done.
13970b57cec5SDimitry Andric if (Pos == Text.npos)
13980b57cec5SDimitry Andric break;
13990b57cec5SDimitry Andric
14000b57cec5SDimitry Andric char Sep = Text[Pos];
14010b57cec5SDimitry Andric Text = Text.substr(Pos + 1);
14020b57cec5SDimitry Andric if (Sep == ',')
14030b57cec5SDimitry Andric // Just a name ending in a comma, continue.
14040b57cec5SDimitry Andric continue;
14050b57cec5SDimitry Andric
14060b57cec5SDimitry Andric if (Sep == '(') {
14070b57cec5SDimitry Andric // Push the inner pipeline onto the stack to continue processing.
14080b57cec5SDimitry Andric PipelineStack.push_back(&Pipeline.back().InnerPipeline);
14090b57cec5SDimitry Andric continue;
14100b57cec5SDimitry Andric }
14110b57cec5SDimitry Andric
14120b57cec5SDimitry Andric assert(Sep == ')' && "Bogus separator!");
14130b57cec5SDimitry Andric // When handling the close parenthesis, we greedily consume them to avoid
14140b57cec5SDimitry Andric // empty strings in the pipeline.
14150b57cec5SDimitry Andric do {
14160b57cec5SDimitry Andric // If we try to pop the outer pipeline we have unbalanced parentheses.
14170b57cec5SDimitry Andric if (PipelineStack.size() == 1)
1418bdd1243dSDimitry Andric return std::nullopt;
14190b57cec5SDimitry Andric
14200b57cec5SDimitry Andric PipelineStack.pop_back();
14210b57cec5SDimitry Andric } while (Text.consume_front(")"));
14220b57cec5SDimitry Andric
14230b57cec5SDimitry Andric // Check if we've finished parsing.
14240b57cec5SDimitry Andric if (Text.empty())
14250b57cec5SDimitry Andric break;
14260b57cec5SDimitry Andric
14270b57cec5SDimitry Andric // Otherwise, the end of an inner pipeline always has to be followed by
14280b57cec5SDimitry Andric // a comma, and then we can continue.
14290b57cec5SDimitry Andric if (!Text.consume_front(","))
1430bdd1243dSDimitry Andric return std::nullopt;
14310b57cec5SDimitry Andric }
14320b57cec5SDimitry Andric
14330b57cec5SDimitry Andric if (PipelineStack.size() > 1)
14340b57cec5SDimitry Andric // Unbalanced paretheses.
1435bdd1243dSDimitry Andric return std::nullopt;
14360b57cec5SDimitry Andric
14370b57cec5SDimitry Andric assert(PipelineStack.back() == &ResultPipeline &&
14380b57cec5SDimitry Andric "Wrong pipeline at the bottom of the stack!");
14390b57cec5SDimitry Andric return {std::move(ResultPipeline)};
14400b57cec5SDimitry Andric }
14410b57cec5SDimitry Andric
parseModulePass(ModulePassManager & MPM,const PipelineElement & E)14420b57cec5SDimitry Andric Error PassBuilder::parseModulePass(ModulePassManager &MPM,
1443e8d8bef9SDimitry Andric const PipelineElement &E) {
14440b57cec5SDimitry Andric auto &Name = E.Name;
14450b57cec5SDimitry Andric auto &InnerPipeline = E.InnerPipeline;
14460b57cec5SDimitry Andric
14470b57cec5SDimitry Andric // First handle complex passes like the pass managers which carry pipelines.
14480b57cec5SDimitry Andric if (!InnerPipeline.empty()) {
14490b57cec5SDimitry Andric if (Name == "module") {
1450fe6060f1SDimitry Andric ModulePassManager NestedMPM;
1451e8d8bef9SDimitry Andric if (auto Err = parseModulePassPipeline(NestedMPM, InnerPipeline))
14520b57cec5SDimitry Andric return Err;
14530b57cec5SDimitry Andric MPM.addPass(std::move(NestedMPM));
14540b57cec5SDimitry Andric return Error::success();
14550b57cec5SDimitry Andric }
1456bdd1243dSDimitry Andric if (Name == "coro-cond") {
1457bdd1243dSDimitry Andric ModulePassManager NestedMPM;
1458bdd1243dSDimitry Andric if (auto Err = parseModulePassPipeline(NestedMPM, InnerPipeline))
1459bdd1243dSDimitry Andric return Err;
1460bdd1243dSDimitry Andric MPM.addPass(CoroConditionalWrapper(std::move(NestedMPM)));
1461bdd1243dSDimitry Andric return Error::success();
1462bdd1243dSDimitry Andric }
14630b57cec5SDimitry Andric if (Name == "cgscc") {
1464fe6060f1SDimitry Andric CGSCCPassManager CGPM;
1465e8d8bef9SDimitry Andric if (auto Err = parseCGSCCPassPipeline(CGPM, InnerPipeline))
14660b57cec5SDimitry Andric return Err;
14670b57cec5SDimitry Andric MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
14680b57cec5SDimitry Andric return Error::success();
14690b57cec5SDimitry Andric }
147006c3fb27SDimitry Andric if (auto Params = parseFunctionPipelineName(Name)) {
147106c3fb27SDimitry Andric if (Params->second)
147206c3fb27SDimitry Andric return make_error<StringError>(
147306c3fb27SDimitry Andric "cannot have a no-rerun module to function adaptor",
147406c3fb27SDimitry Andric inconvertibleErrorCode());
1475fe6060f1SDimitry Andric FunctionPassManager FPM;
1476e8d8bef9SDimitry Andric if (auto Err = parseFunctionPassPipeline(FPM, InnerPipeline))
14770b57cec5SDimitry Andric return Err;
147806c3fb27SDimitry Andric MPM.addPass(
147906c3fb27SDimitry Andric createModuleToFunctionPassAdaptor(std::move(FPM), Params->first));
14800b57cec5SDimitry Andric return Error::success();
14810b57cec5SDimitry Andric }
14820b57cec5SDimitry Andric
14830b57cec5SDimitry Andric for (auto &C : ModulePipelineParsingCallbacks)
14840b57cec5SDimitry Andric if (C(Name, MPM, InnerPipeline))
14850b57cec5SDimitry Andric return Error::success();
14860b57cec5SDimitry Andric
14870b57cec5SDimitry Andric // Normal passes can't have pipelines.
14880b57cec5SDimitry Andric return make_error<StringError>(
14890b57cec5SDimitry Andric formatv("invalid use of '{0}' pass as module pipeline", Name).str(),
14900b57cec5SDimitry Andric inconvertibleErrorCode());
14910b57cec5SDimitry Andric ;
14920b57cec5SDimitry Andric }
14930b57cec5SDimitry Andric
14940b57cec5SDimitry Andric // Manually handle aliases for pre-configured pipeline fragments.
14950b57cec5SDimitry Andric if (startsWithDefaultPipelineAliasPrefix(Name)) {
14960b57cec5SDimitry Andric SmallVector<StringRef, 3> Matches;
14970b57cec5SDimitry Andric if (!DefaultAliasRegex.match(Name, &Matches))
14980b57cec5SDimitry Andric return make_error<StringError>(
14990b57cec5SDimitry Andric formatv("unknown default pipeline alias '{0}'", Name).str(),
15000b57cec5SDimitry Andric inconvertibleErrorCode());
15010b57cec5SDimitry Andric
15020b57cec5SDimitry Andric assert(Matches.size() == 3 && "Must capture two matched strings!");
15030b57cec5SDimitry Andric
150406c3fb27SDimitry Andric OptimizationLevel L = *parseOptLevel(Matches[2]);
15050b57cec5SDimitry Andric
1506480093f4SDimitry Andric // This is consistent with old pass manager invoked via opt, but
1507480093f4SDimitry Andric // inconsistent with clang. Clang doesn't enable loop vectorization
1508480093f4SDimitry Andric // but does enable slp vectorization at Oz.
15095ffd83dbSDimitry Andric PTO.LoopVectorization =
15105ffd83dbSDimitry Andric L.getSpeedupLevel() > 1 && L != OptimizationLevel::Oz;
15115ffd83dbSDimitry Andric PTO.SLPVectorization =
15125ffd83dbSDimitry Andric L.getSpeedupLevel() > 1 && L != OptimizationLevel::Oz;
1513480093f4SDimitry Andric
15140b57cec5SDimitry Andric if (Matches[1] == "default") {
1515e8d8bef9SDimitry Andric MPM.addPass(buildPerModuleDefaultPipeline(L));
15160b57cec5SDimitry Andric } else if (Matches[1] == "thinlto-pre-link") {
1517e8d8bef9SDimitry Andric MPM.addPass(buildThinLTOPreLinkDefaultPipeline(L));
15180b57cec5SDimitry Andric } else if (Matches[1] == "thinlto") {
1519e8d8bef9SDimitry Andric MPM.addPass(buildThinLTODefaultPipeline(L, nullptr));
15200b57cec5SDimitry Andric } else if (Matches[1] == "lto-pre-link") {
152106c3fb27SDimitry Andric if (PTO.UnifiedLTO)
152206c3fb27SDimitry Andric // When UnifiedLTO is enabled, use the ThinLTO pre-link pipeline. This
152306c3fb27SDimitry Andric // avoids compile-time performance regressions and keeps the pre-link
152406c3fb27SDimitry Andric // LTO pipeline "unified" for both LTO modes.
152506c3fb27SDimitry Andric MPM.addPass(buildThinLTOPreLinkDefaultPipeline(L));
152606c3fb27SDimitry Andric else
1527e8d8bef9SDimitry Andric MPM.addPass(buildLTOPreLinkDefaultPipeline(L));
15280b57cec5SDimitry Andric } else {
15290b57cec5SDimitry Andric assert(Matches[1] == "lto" && "Not one of the matched options!");
1530e8d8bef9SDimitry Andric MPM.addPass(buildLTODefaultPipeline(L, nullptr));
15310b57cec5SDimitry Andric }
15320b57cec5SDimitry Andric return Error::success();
15330b57cec5SDimitry Andric }
15340b57cec5SDimitry Andric
15350b57cec5SDimitry Andric // Finally expand the basic registered passes from the .inc file.
15360b57cec5SDimitry Andric #define MODULE_PASS(NAME, CREATE_PASS) \
15370b57cec5SDimitry Andric if (Name == NAME) { \
15380b57cec5SDimitry Andric MPM.addPass(CREATE_PASS); \
15390b57cec5SDimitry Andric return Error::success(); \
15400b57cec5SDimitry Andric }
1541349cc55cSDimitry Andric #define MODULE_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \
1542349cc55cSDimitry Andric if (checkParametrizedPassName(Name, NAME)) { \
1543349cc55cSDimitry Andric auto Params = parsePassParameters(PARSER, Name, NAME); \
1544349cc55cSDimitry Andric if (!Params) \
1545349cc55cSDimitry Andric return Params.takeError(); \
1546349cc55cSDimitry Andric MPM.addPass(CREATE_PASS(Params.get())); \
1547349cc55cSDimitry Andric return Error::success(); \
1548349cc55cSDimitry Andric }
15490b57cec5SDimitry Andric #define MODULE_ANALYSIS(NAME, CREATE_PASS) \
15500b57cec5SDimitry Andric if (Name == "require<" NAME ">") { \
15510b57cec5SDimitry Andric MPM.addPass( \
15520b57cec5SDimitry Andric RequireAnalysisPass< \
1553bdd1243dSDimitry Andric std::remove_reference_t<decltype(CREATE_PASS)>, Module>()); \
15540b57cec5SDimitry Andric return Error::success(); \
15550b57cec5SDimitry Andric } \
15560b57cec5SDimitry Andric if (Name == "invalidate<" NAME ">") { \
15570b57cec5SDimitry Andric MPM.addPass(InvalidateAnalysisPass< \
1558bdd1243dSDimitry Andric std::remove_reference_t<decltype(CREATE_PASS)>>()); \
15590b57cec5SDimitry Andric return Error::success(); \
15600b57cec5SDimitry Andric }
1561e8d8bef9SDimitry Andric #define CGSCC_PASS(NAME, CREATE_PASS) \
1562e8d8bef9SDimitry Andric if (Name == NAME) { \
1563e8d8bef9SDimitry Andric MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(CREATE_PASS)); \
1564e8d8bef9SDimitry Andric return Error::success(); \
1565e8d8bef9SDimitry Andric }
1566349cc55cSDimitry Andric #define CGSCC_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \
1567349cc55cSDimitry Andric if (checkParametrizedPassName(Name, NAME)) { \
1568349cc55cSDimitry Andric auto Params = parsePassParameters(PARSER, Name, NAME); \
1569349cc55cSDimitry Andric if (!Params) \
1570349cc55cSDimitry Andric return Params.takeError(); \
1571349cc55cSDimitry Andric MPM.addPass( \
1572349cc55cSDimitry Andric createModuleToPostOrderCGSCCPassAdaptor(CREATE_PASS(Params.get()))); \
1573349cc55cSDimitry Andric return Error::success(); \
1574349cc55cSDimitry Andric }
1575e8d8bef9SDimitry Andric #define FUNCTION_PASS(NAME, CREATE_PASS) \
1576e8d8bef9SDimitry Andric if (Name == NAME) { \
1577e8d8bef9SDimitry Andric MPM.addPass(createModuleToFunctionPassAdaptor(CREATE_PASS)); \
1578e8d8bef9SDimitry Andric return Error::success(); \
1579e8d8bef9SDimitry Andric }
1580fe6060f1SDimitry Andric #define FUNCTION_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \
1581e8d8bef9SDimitry Andric if (checkParametrizedPassName(Name, NAME)) { \
1582e8d8bef9SDimitry Andric auto Params = parsePassParameters(PARSER, Name, NAME); \
1583e8d8bef9SDimitry Andric if (!Params) \
1584e8d8bef9SDimitry Andric return Params.takeError(); \
1585e8d8bef9SDimitry Andric MPM.addPass(createModuleToFunctionPassAdaptor(CREATE_PASS(Params.get()))); \
1586e8d8bef9SDimitry Andric return Error::success(); \
1587e8d8bef9SDimitry Andric }
1588349cc55cSDimitry Andric #define LOOPNEST_PASS(NAME, CREATE_PASS) \
1589349cc55cSDimitry Andric if (Name == NAME) { \
1590349cc55cSDimitry Andric MPM.addPass(createModuleToFunctionPassAdaptor( \
1591349cc55cSDimitry Andric createFunctionToLoopPassAdaptor(CREATE_PASS, false, false))); \
1592349cc55cSDimitry Andric return Error::success(); \
1593349cc55cSDimitry Andric }
1594e8d8bef9SDimitry Andric #define LOOP_PASS(NAME, CREATE_PASS) \
1595e8d8bef9SDimitry Andric if (Name == NAME) { \
1596fe6060f1SDimitry Andric MPM.addPass(createModuleToFunctionPassAdaptor( \
1597fe6060f1SDimitry Andric createFunctionToLoopPassAdaptor(CREATE_PASS, false, false))); \
1598e8d8bef9SDimitry Andric return Error::success(); \
1599e8d8bef9SDimitry Andric }
1600fe6060f1SDimitry Andric #define LOOP_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \
1601e8d8bef9SDimitry Andric if (checkParametrizedPassName(Name, NAME)) { \
1602e8d8bef9SDimitry Andric auto Params = parsePassParameters(PARSER, Name, NAME); \
1603e8d8bef9SDimitry Andric if (!Params) \
1604e8d8bef9SDimitry Andric return Params.takeError(); \
1605e8d8bef9SDimitry Andric MPM.addPass( \
1606e8d8bef9SDimitry Andric createModuleToFunctionPassAdaptor(createFunctionToLoopPassAdaptor( \
1607fe6060f1SDimitry Andric CREATE_PASS(Params.get()), false, false))); \
1608e8d8bef9SDimitry Andric return Error::success(); \
1609e8d8bef9SDimitry Andric }
16100b57cec5SDimitry Andric #include "PassRegistry.def"
16110b57cec5SDimitry Andric
16120b57cec5SDimitry Andric for (auto &C : ModulePipelineParsingCallbacks)
16130b57cec5SDimitry Andric if (C(Name, MPM, InnerPipeline))
16140b57cec5SDimitry Andric return Error::success();
16150b57cec5SDimitry Andric return make_error<StringError>(
16160b57cec5SDimitry Andric formatv("unknown module pass '{0}'", Name).str(),
16170b57cec5SDimitry Andric inconvertibleErrorCode());
16180b57cec5SDimitry Andric }
16190b57cec5SDimitry Andric
parseCGSCCPass(CGSCCPassManager & CGPM,const PipelineElement & E)16200b57cec5SDimitry Andric Error PassBuilder::parseCGSCCPass(CGSCCPassManager &CGPM,
1621e8d8bef9SDimitry Andric const PipelineElement &E) {
16220b57cec5SDimitry Andric auto &Name = E.Name;
16230b57cec5SDimitry Andric auto &InnerPipeline = E.InnerPipeline;
16240b57cec5SDimitry Andric
16250b57cec5SDimitry Andric // First handle complex passes like the pass managers which carry pipelines.
16260b57cec5SDimitry Andric if (!InnerPipeline.empty()) {
16270b57cec5SDimitry Andric if (Name == "cgscc") {
1628fe6060f1SDimitry Andric CGSCCPassManager NestedCGPM;
1629e8d8bef9SDimitry Andric if (auto Err = parseCGSCCPassPipeline(NestedCGPM, InnerPipeline))
16300b57cec5SDimitry Andric return Err;
16310b57cec5SDimitry Andric // Add the nested pass manager with the appropriate adaptor.
16320b57cec5SDimitry Andric CGPM.addPass(std::move(NestedCGPM));
16330b57cec5SDimitry Andric return Error::success();
16340b57cec5SDimitry Andric }
163506c3fb27SDimitry Andric if (auto Params = parseFunctionPipelineName(Name)) {
1636fe6060f1SDimitry Andric FunctionPassManager FPM;
1637e8d8bef9SDimitry Andric if (auto Err = parseFunctionPassPipeline(FPM, InnerPipeline))
16380b57cec5SDimitry Andric return Err;
16390b57cec5SDimitry Andric // Add the nested pass manager with the appropriate adaptor.
164006c3fb27SDimitry Andric CGPM.addPass(createCGSCCToFunctionPassAdaptor(
164106c3fb27SDimitry Andric std::move(FPM), Params->first, Params->second));
16420b57cec5SDimitry Andric return Error::success();
16430b57cec5SDimitry Andric }
16440b57cec5SDimitry Andric if (auto MaxRepetitions = parseDevirtPassName(Name)) {
1645fe6060f1SDimitry Andric CGSCCPassManager NestedCGPM;
1646e8d8bef9SDimitry Andric if (auto Err = parseCGSCCPassPipeline(NestedCGPM, InnerPipeline))
16470b57cec5SDimitry Andric return Err;
16480b57cec5SDimitry Andric CGPM.addPass(
16490b57cec5SDimitry Andric createDevirtSCCRepeatedPass(std::move(NestedCGPM), *MaxRepetitions));
16500b57cec5SDimitry Andric return Error::success();
16510b57cec5SDimitry Andric }
16520b57cec5SDimitry Andric
16530b57cec5SDimitry Andric for (auto &C : CGSCCPipelineParsingCallbacks)
16540b57cec5SDimitry Andric if (C(Name, CGPM, InnerPipeline))
16550b57cec5SDimitry Andric return Error::success();
16560b57cec5SDimitry Andric
16570b57cec5SDimitry Andric // Normal passes can't have pipelines.
16580b57cec5SDimitry Andric return make_error<StringError>(
16590b57cec5SDimitry Andric formatv("invalid use of '{0}' pass as cgscc pipeline", Name).str(),
16600b57cec5SDimitry Andric inconvertibleErrorCode());
16610b57cec5SDimitry Andric }
16620b57cec5SDimitry Andric
16630b57cec5SDimitry Andric // Now expand the basic registered passes from the .inc file.
16640b57cec5SDimitry Andric #define CGSCC_PASS(NAME, CREATE_PASS) \
16650b57cec5SDimitry Andric if (Name == NAME) { \
16660b57cec5SDimitry Andric CGPM.addPass(CREATE_PASS); \
16670b57cec5SDimitry Andric return Error::success(); \
16680b57cec5SDimitry Andric }
1669349cc55cSDimitry Andric #define CGSCC_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \
1670349cc55cSDimitry Andric if (checkParametrizedPassName(Name, NAME)) { \
1671349cc55cSDimitry Andric auto Params = parsePassParameters(PARSER, Name, NAME); \
1672349cc55cSDimitry Andric if (!Params) \
1673349cc55cSDimitry Andric return Params.takeError(); \
1674349cc55cSDimitry Andric CGPM.addPass(CREATE_PASS(Params.get())); \
1675349cc55cSDimitry Andric return Error::success(); \
1676349cc55cSDimitry Andric }
16770b57cec5SDimitry Andric #define CGSCC_ANALYSIS(NAME, CREATE_PASS) \
16780b57cec5SDimitry Andric if (Name == "require<" NAME ">") { \
16790b57cec5SDimitry Andric CGPM.addPass(RequireAnalysisPass< \
1680bdd1243dSDimitry Andric std::remove_reference_t<decltype(CREATE_PASS)>, \
16810b57cec5SDimitry Andric LazyCallGraph::SCC, CGSCCAnalysisManager, LazyCallGraph &, \
16820b57cec5SDimitry Andric CGSCCUpdateResult &>()); \
16830b57cec5SDimitry Andric return Error::success(); \
16840b57cec5SDimitry Andric } \
16850b57cec5SDimitry Andric if (Name == "invalidate<" NAME ">") { \
16860b57cec5SDimitry Andric CGPM.addPass(InvalidateAnalysisPass< \
1687bdd1243dSDimitry Andric std::remove_reference_t<decltype(CREATE_PASS)>>()); \
16880b57cec5SDimitry Andric return Error::success(); \
16890b57cec5SDimitry Andric }
1690e8d8bef9SDimitry Andric #define FUNCTION_PASS(NAME, CREATE_PASS) \
1691e8d8bef9SDimitry Andric if (Name == NAME) { \
1692e8d8bef9SDimitry Andric CGPM.addPass(createCGSCCToFunctionPassAdaptor(CREATE_PASS)); \
1693e8d8bef9SDimitry Andric return Error::success(); \
1694e8d8bef9SDimitry Andric }
1695fe6060f1SDimitry Andric #define FUNCTION_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \
1696e8d8bef9SDimitry Andric if (checkParametrizedPassName(Name, NAME)) { \
1697e8d8bef9SDimitry Andric auto Params = parsePassParameters(PARSER, Name, NAME); \
1698e8d8bef9SDimitry Andric if (!Params) \
1699e8d8bef9SDimitry Andric return Params.takeError(); \
1700e8d8bef9SDimitry Andric CGPM.addPass(createCGSCCToFunctionPassAdaptor(CREATE_PASS(Params.get()))); \
1701e8d8bef9SDimitry Andric return Error::success(); \
1702e8d8bef9SDimitry Andric }
1703349cc55cSDimitry Andric #define LOOPNEST_PASS(NAME, CREATE_PASS) \
1704349cc55cSDimitry Andric if (Name == NAME) { \
1705349cc55cSDimitry Andric CGPM.addPass(createCGSCCToFunctionPassAdaptor( \
1706349cc55cSDimitry Andric createFunctionToLoopPassAdaptor(CREATE_PASS, false, false))); \
1707349cc55cSDimitry Andric return Error::success(); \
1708349cc55cSDimitry Andric }
1709e8d8bef9SDimitry Andric #define LOOP_PASS(NAME, CREATE_PASS) \
1710e8d8bef9SDimitry Andric if (Name == NAME) { \
1711fe6060f1SDimitry Andric CGPM.addPass(createCGSCCToFunctionPassAdaptor( \
1712fe6060f1SDimitry Andric createFunctionToLoopPassAdaptor(CREATE_PASS, false, false))); \
1713e8d8bef9SDimitry Andric return Error::success(); \
1714e8d8bef9SDimitry Andric }
1715fe6060f1SDimitry Andric #define LOOP_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \
1716e8d8bef9SDimitry Andric if (checkParametrizedPassName(Name, NAME)) { \
1717e8d8bef9SDimitry Andric auto Params = parsePassParameters(PARSER, Name, NAME); \
1718e8d8bef9SDimitry Andric if (!Params) \
1719e8d8bef9SDimitry Andric return Params.takeError(); \
1720e8d8bef9SDimitry Andric CGPM.addPass( \
1721e8d8bef9SDimitry Andric createCGSCCToFunctionPassAdaptor(createFunctionToLoopPassAdaptor( \
1722fe6060f1SDimitry Andric CREATE_PASS(Params.get()), false, false))); \
1723e8d8bef9SDimitry Andric return Error::success(); \
1724e8d8bef9SDimitry Andric }
17250b57cec5SDimitry Andric #include "PassRegistry.def"
17260b57cec5SDimitry Andric
17270b57cec5SDimitry Andric for (auto &C : CGSCCPipelineParsingCallbacks)
17280b57cec5SDimitry Andric if (C(Name, CGPM, InnerPipeline))
17290b57cec5SDimitry Andric return Error::success();
17300b57cec5SDimitry Andric return make_error<StringError>(
17310b57cec5SDimitry Andric formatv("unknown cgscc pass '{0}'", Name).str(),
17320b57cec5SDimitry Andric inconvertibleErrorCode());
17330b57cec5SDimitry Andric }
17340b57cec5SDimitry Andric
parseFunctionPass(FunctionPassManager & FPM,const PipelineElement & E)17350b57cec5SDimitry Andric Error PassBuilder::parseFunctionPass(FunctionPassManager &FPM,
1736e8d8bef9SDimitry Andric const PipelineElement &E) {
17370b57cec5SDimitry Andric auto &Name = E.Name;
17380b57cec5SDimitry Andric auto &InnerPipeline = E.InnerPipeline;
17390b57cec5SDimitry Andric
17400b57cec5SDimitry Andric // First handle complex passes like the pass managers which carry pipelines.
17410b57cec5SDimitry Andric if (!InnerPipeline.empty()) {
17420b57cec5SDimitry Andric if (Name == "function") {
1743fe6060f1SDimitry Andric FunctionPassManager NestedFPM;
1744e8d8bef9SDimitry Andric if (auto Err = parseFunctionPassPipeline(NestedFPM, InnerPipeline))
17450b57cec5SDimitry Andric return Err;
17460b57cec5SDimitry Andric // Add the nested pass manager with the appropriate adaptor.
17470b57cec5SDimitry Andric FPM.addPass(std::move(NestedFPM));
17480b57cec5SDimitry Andric return Error::success();
17490b57cec5SDimitry Andric }
17508bcb0991SDimitry Andric if (Name == "loop" || Name == "loop-mssa") {
1751fe6060f1SDimitry Andric LoopPassManager LPM;
1752e8d8bef9SDimitry Andric if (auto Err = parseLoopPassPipeline(LPM, InnerPipeline))
17530b57cec5SDimitry Andric return Err;
17540b57cec5SDimitry Andric // Add the nested pass manager with the appropriate adaptor.
17558bcb0991SDimitry Andric bool UseMemorySSA = (Name == "loop-mssa");
1756bdd1243dSDimitry Andric bool UseBFI = llvm::any_of(InnerPipeline, [](auto Pipeline) {
1757bdd1243dSDimitry Andric return Pipeline.Name.contains("simple-loop-unswitch");
1758bdd1243dSDimitry Andric });
1759349cc55cSDimitry Andric bool UseBPI = llvm::any_of(InnerPipeline, [](auto Pipeline) {
1760349cc55cSDimitry Andric return Pipeline.Name == "loop-predication";
1761349cc55cSDimitry Andric });
17628bcb0991SDimitry Andric FPM.addPass(createFunctionToLoopPassAdaptor(std::move(LPM), UseMemorySSA,
1763349cc55cSDimitry Andric UseBFI, UseBPI));
17640b57cec5SDimitry Andric return Error::success();
17650b57cec5SDimitry Andric }
1766*0fca6ea1SDimitry Andric if (Name == "machine-function") {
1767*0fca6ea1SDimitry Andric MachineFunctionPassManager MFPM;
1768*0fca6ea1SDimitry Andric if (auto Err = parseMachinePassPipeline(MFPM, InnerPipeline))
17690b57cec5SDimitry Andric return Err;
1770*0fca6ea1SDimitry Andric FPM.addPass(createFunctionToMachineFunctionPassAdaptor(std::move(MFPM)));
17710b57cec5SDimitry Andric return Error::success();
17720b57cec5SDimitry Andric }
17730b57cec5SDimitry Andric
17740b57cec5SDimitry Andric for (auto &C : FunctionPipelineParsingCallbacks)
17750b57cec5SDimitry Andric if (C(Name, FPM, InnerPipeline))
17760b57cec5SDimitry Andric return Error::success();
17770b57cec5SDimitry Andric
17780b57cec5SDimitry Andric // Normal passes can't have pipelines.
17790b57cec5SDimitry Andric return make_error<StringError>(
17800b57cec5SDimitry Andric formatv("invalid use of '{0}' pass as function pipeline", Name).str(),
17810b57cec5SDimitry Andric inconvertibleErrorCode());
17820b57cec5SDimitry Andric }
17830b57cec5SDimitry Andric
17840b57cec5SDimitry Andric // Now expand the basic registered passes from the .inc file.
17850b57cec5SDimitry Andric #define FUNCTION_PASS(NAME, CREATE_PASS) \
17860b57cec5SDimitry Andric if (Name == NAME) { \
17870b57cec5SDimitry Andric FPM.addPass(CREATE_PASS); \
17880b57cec5SDimitry Andric return Error::success(); \
17890b57cec5SDimitry Andric }
1790fe6060f1SDimitry Andric #define FUNCTION_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \
17910b57cec5SDimitry Andric if (checkParametrizedPassName(Name, NAME)) { \
17920b57cec5SDimitry Andric auto Params = parsePassParameters(PARSER, Name, NAME); \
17930b57cec5SDimitry Andric if (!Params) \
17940b57cec5SDimitry Andric return Params.takeError(); \
17950b57cec5SDimitry Andric FPM.addPass(CREATE_PASS(Params.get())); \
17960b57cec5SDimitry Andric return Error::success(); \
17970b57cec5SDimitry Andric }
17980b57cec5SDimitry Andric #define FUNCTION_ANALYSIS(NAME, CREATE_PASS) \
17990b57cec5SDimitry Andric if (Name == "require<" NAME ">") { \
18000b57cec5SDimitry Andric FPM.addPass( \
18010b57cec5SDimitry Andric RequireAnalysisPass< \
1802bdd1243dSDimitry Andric std::remove_reference_t<decltype(CREATE_PASS)>, Function>()); \
18030b57cec5SDimitry Andric return Error::success(); \
18040b57cec5SDimitry Andric } \
18050b57cec5SDimitry Andric if (Name == "invalidate<" NAME ">") { \
18060b57cec5SDimitry Andric FPM.addPass(InvalidateAnalysisPass< \
1807bdd1243dSDimitry Andric std::remove_reference_t<decltype(CREATE_PASS)>>()); \
18080b57cec5SDimitry Andric return Error::success(); \
18090b57cec5SDimitry Andric }
1810e8d8bef9SDimitry Andric // FIXME: UseMemorySSA is set to false. Maybe we could do things like:
1811e8d8bef9SDimitry Andric // bool UseMemorySSA = !("canon-freeze" || "loop-predication" ||
1812e8d8bef9SDimitry Andric // "guard-widening");
1813e8d8bef9SDimitry Andric // The risk is that it may become obsolete if we're not careful.
1814349cc55cSDimitry Andric #define LOOPNEST_PASS(NAME, CREATE_PASS) \
1815349cc55cSDimitry Andric if (Name == NAME) { \
1816349cc55cSDimitry Andric FPM.addPass(createFunctionToLoopPassAdaptor(CREATE_PASS, false, false)); \
1817349cc55cSDimitry Andric return Error::success(); \
1818349cc55cSDimitry Andric }
1819e8d8bef9SDimitry Andric #define LOOP_PASS(NAME, CREATE_PASS) \
1820e8d8bef9SDimitry Andric if (Name == NAME) { \
1821fe6060f1SDimitry Andric FPM.addPass(createFunctionToLoopPassAdaptor(CREATE_PASS, false, false)); \
1822e8d8bef9SDimitry Andric return Error::success(); \
1823e8d8bef9SDimitry Andric }
1824fe6060f1SDimitry Andric #define LOOP_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \
1825e8d8bef9SDimitry Andric if (checkParametrizedPassName(Name, NAME)) { \
1826e8d8bef9SDimitry Andric auto Params = parsePassParameters(PARSER, Name, NAME); \
1827e8d8bef9SDimitry Andric if (!Params) \
1828e8d8bef9SDimitry Andric return Params.takeError(); \
1829e8d8bef9SDimitry Andric FPM.addPass(createFunctionToLoopPassAdaptor(CREATE_PASS(Params.get()), \
1830fe6060f1SDimitry Andric false, false)); \
1831e8d8bef9SDimitry Andric return Error::success(); \
1832e8d8bef9SDimitry Andric }
18330b57cec5SDimitry Andric #include "PassRegistry.def"
18340b57cec5SDimitry Andric
18350b57cec5SDimitry Andric for (auto &C : FunctionPipelineParsingCallbacks)
18360b57cec5SDimitry Andric if (C(Name, FPM, InnerPipeline))
18370b57cec5SDimitry Andric return Error::success();
18380b57cec5SDimitry Andric return make_error<StringError>(
18390b57cec5SDimitry Andric formatv("unknown function pass '{0}'", Name).str(),
18400b57cec5SDimitry Andric inconvertibleErrorCode());
18410b57cec5SDimitry Andric }
18420b57cec5SDimitry Andric
parseLoopPass(LoopPassManager & LPM,const PipelineElement & E)1843e8d8bef9SDimitry Andric Error PassBuilder::parseLoopPass(LoopPassManager &LPM,
1844e8d8bef9SDimitry Andric const PipelineElement &E) {
18450b57cec5SDimitry Andric StringRef Name = E.Name;
18460b57cec5SDimitry Andric auto &InnerPipeline = E.InnerPipeline;
18470b57cec5SDimitry Andric
18480b57cec5SDimitry Andric // First handle complex passes like the pass managers which carry pipelines.
18490b57cec5SDimitry Andric if (!InnerPipeline.empty()) {
18500b57cec5SDimitry Andric if (Name == "loop") {
1851fe6060f1SDimitry Andric LoopPassManager NestedLPM;
1852e8d8bef9SDimitry Andric if (auto Err = parseLoopPassPipeline(NestedLPM, InnerPipeline))
18530b57cec5SDimitry Andric return Err;
18540b57cec5SDimitry Andric // Add the nested pass manager with the appropriate adaptor.
18550b57cec5SDimitry Andric LPM.addPass(std::move(NestedLPM));
18560b57cec5SDimitry Andric return Error::success();
18570b57cec5SDimitry Andric }
18580b57cec5SDimitry Andric
18590b57cec5SDimitry Andric for (auto &C : LoopPipelineParsingCallbacks)
18600b57cec5SDimitry Andric if (C(Name, LPM, InnerPipeline))
18610b57cec5SDimitry Andric return Error::success();
18620b57cec5SDimitry Andric
18630b57cec5SDimitry Andric // Normal passes can't have pipelines.
18640b57cec5SDimitry Andric return make_error<StringError>(
18650b57cec5SDimitry Andric formatv("invalid use of '{0}' pass as loop pipeline", Name).str(),
18660b57cec5SDimitry Andric inconvertibleErrorCode());
18670b57cec5SDimitry Andric }
18680b57cec5SDimitry Andric
18690b57cec5SDimitry Andric // Now expand the basic registered passes from the .inc file.
1870349cc55cSDimitry Andric #define LOOPNEST_PASS(NAME, CREATE_PASS) \
1871349cc55cSDimitry Andric if (Name == NAME) { \
1872349cc55cSDimitry Andric LPM.addPass(CREATE_PASS); \
1873349cc55cSDimitry Andric return Error::success(); \
1874349cc55cSDimitry Andric }
18750b57cec5SDimitry Andric #define LOOP_PASS(NAME, CREATE_PASS) \
18760b57cec5SDimitry Andric if (Name == NAME) { \
18770b57cec5SDimitry Andric LPM.addPass(CREATE_PASS); \
18780b57cec5SDimitry Andric return Error::success(); \
18790b57cec5SDimitry Andric }
1880fe6060f1SDimitry Andric #define LOOP_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \
18810b57cec5SDimitry Andric if (checkParametrizedPassName(Name, NAME)) { \
18820b57cec5SDimitry Andric auto Params = parsePassParameters(PARSER, Name, NAME); \
18830b57cec5SDimitry Andric if (!Params) \
18840b57cec5SDimitry Andric return Params.takeError(); \
18850b57cec5SDimitry Andric LPM.addPass(CREATE_PASS(Params.get())); \
18860b57cec5SDimitry Andric return Error::success(); \
18870b57cec5SDimitry Andric }
18880b57cec5SDimitry Andric #define LOOP_ANALYSIS(NAME, CREATE_PASS) \
18890b57cec5SDimitry Andric if (Name == "require<" NAME ">") { \
18900b57cec5SDimitry Andric LPM.addPass(RequireAnalysisPass< \
1891bdd1243dSDimitry Andric std::remove_reference_t<decltype(CREATE_PASS)>, Loop, \
18920b57cec5SDimitry Andric LoopAnalysisManager, LoopStandardAnalysisResults &, \
18930b57cec5SDimitry Andric LPMUpdater &>()); \
18940b57cec5SDimitry Andric return Error::success(); \
18950b57cec5SDimitry Andric } \
18960b57cec5SDimitry Andric if (Name == "invalidate<" NAME ">") { \
18970b57cec5SDimitry Andric LPM.addPass(InvalidateAnalysisPass< \
1898bdd1243dSDimitry Andric std::remove_reference_t<decltype(CREATE_PASS)>>()); \
18990b57cec5SDimitry Andric return Error::success(); \
19000b57cec5SDimitry Andric }
19010b57cec5SDimitry Andric #include "PassRegistry.def"
19020b57cec5SDimitry Andric
19030b57cec5SDimitry Andric for (auto &C : LoopPipelineParsingCallbacks)
19040b57cec5SDimitry Andric if (C(Name, LPM, InnerPipeline))
19050b57cec5SDimitry Andric return Error::success();
19060b57cec5SDimitry Andric return make_error<StringError>(formatv("unknown loop pass '{0}'", Name).str(),
19070b57cec5SDimitry Andric inconvertibleErrorCode());
19080b57cec5SDimitry Andric }
19090b57cec5SDimitry Andric
parseMachinePass(MachineFunctionPassManager & MFPM,const PipelineElement & E)19107a6dacacSDimitry Andric Error PassBuilder::parseMachinePass(MachineFunctionPassManager &MFPM,
19117a6dacacSDimitry Andric const PipelineElement &E) {
19127a6dacacSDimitry Andric StringRef Name = E.Name;
19137a6dacacSDimitry Andric if (!E.InnerPipeline.empty())
19147a6dacacSDimitry Andric return make_error<StringError>("invalid pipeline",
19157a6dacacSDimitry Andric inconvertibleErrorCode());
19167a6dacacSDimitry Andric
1917*0fca6ea1SDimitry Andric #define MACHINE_MODULE_PASS(NAME, CREATE_PASS) \
19187a6dacacSDimitry Andric if (Name == NAME) { \
1919*0fca6ea1SDimitry Andric MFPM.addPass(CREATE_PASS); \
19207a6dacacSDimitry Andric return Error::success(); \
19217a6dacacSDimitry Andric }
1922*0fca6ea1SDimitry Andric #define MACHINE_FUNCTION_PASS(NAME, CREATE_PASS) \
19237a6dacacSDimitry Andric if (Name == NAME) { \
1924*0fca6ea1SDimitry Andric MFPM.addPass(CREATE_PASS); \
19257a6dacacSDimitry Andric return Error::success(); \
19267a6dacacSDimitry Andric }
1927*0fca6ea1SDimitry Andric #define MACHINE_FUNCTION_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, \
1928*0fca6ea1SDimitry Andric PARAMS) \
1929*0fca6ea1SDimitry Andric if (checkParametrizedPassName(Name, NAME)) { \
1930*0fca6ea1SDimitry Andric auto Params = parsePassParameters(PARSER, Name, NAME); \
1931*0fca6ea1SDimitry Andric if (!Params) \
1932*0fca6ea1SDimitry Andric return Params.takeError(); \
1933*0fca6ea1SDimitry Andric MFPM.addPass(CREATE_PASS(Params.get())); \
1934*0fca6ea1SDimitry Andric return Error::success(); \
1935*0fca6ea1SDimitry Andric }
1936*0fca6ea1SDimitry Andric #define MACHINE_FUNCTION_ANALYSIS(NAME, CREATE_PASS) \
1937*0fca6ea1SDimitry Andric if (Name == "require<" NAME ">") { \
1938*0fca6ea1SDimitry Andric MFPM.addPass( \
1939*0fca6ea1SDimitry Andric RequireAnalysisPass<std::remove_reference_t<decltype(CREATE_PASS)>, \
1940*0fca6ea1SDimitry Andric MachineFunction>()); \
1941*0fca6ea1SDimitry Andric return Error::success(); \
1942*0fca6ea1SDimitry Andric } \
1943*0fca6ea1SDimitry Andric if (Name == "invalidate<" NAME ">") { \
1944*0fca6ea1SDimitry Andric MFPM.addPass(InvalidateAnalysisPass< \
1945*0fca6ea1SDimitry Andric std::remove_reference_t<decltype(CREATE_PASS)>>()); \
1946*0fca6ea1SDimitry Andric return Error::success(); \
1947*0fca6ea1SDimitry Andric }
1948*0fca6ea1SDimitry Andric #include "llvm/Passes/MachinePassRegistry.def"
19497a6dacacSDimitry Andric
1950*0fca6ea1SDimitry Andric for (auto &C : MachineFunctionPipelineParsingCallbacks)
1951*0fca6ea1SDimitry Andric if (C(Name, MFPM, E.InnerPipeline))
19527a6dacacSDimitry Andric return Error::success();
19537a6dacacSDimitry Andric return make_error<StringError>(
19547a6dacacSDimitry Andric formatv("unknown machine pass '{0}'", Name).str(),
19557a6dacacSDimitry Andric inconvertibleErrorCode());
19567a6dacacSDimitry Andric }
19577a6dacacSDimitry Andric
parseAAPassName(AAManager & AA,StringRef Name)19580b57cec5SDimitry Andric bool PassBuilder::parseAAPassName(AAManager &AA, StringRef Name) {
19590b57cec5SDimitry Andric #define MODULE_ALIAS_ANALYSIS(NAME, CREATE_PASS) \
19600b57cec5SDimitry Andric if (Name == NAME) { \
19610b57cec5SDimitry Andric AA.registerModuleAnalysis< \
1962bdd1243dSDimitry Andric std::remove_reference_t<decltype(CREATE_PASS)>>(); \
19630b57cec5SDimitry Andric return true; \
19640b57cec5SDimitry Andric }
19650b57cec5SDimitry Andric #define FUNCTION_ALIAS_ANALYSIS(NAME, CREATE_PASS) \
19660b57cec5SDimitry Andric if (Name == NAME) { \
19670b57cec5SDimitry Andric AA.registerFunctionAnalysis< \
1968bdd1243dSDimitry Andric std::remove_reference_t<decltype(CREATE_PASS)>>(); \
19690b57cec5SDimitry Andric return true; \
19700b57cec5SDimitry Andric }
19710b57cec5SDimitry Andric #include "PassRegistry.def"
19720b57cec5SDimitry Andric
19730b57cec5SDimitry Andric for (auto &C : AAParsingCallbacks)
19740b57cec5SDimitry Andric if (C(Name, AA))
19750b57cec5SDimitry Andric return true;
19760b57cec5SDimitry Andric return false;
19770b57cec5SDimitry Andric }
19780b57cec5SDimitry Andric
parseMachinePassPipeline(MachineFunctionPassManager & MFPM,ArrayRef<PipelineElement> Pipeline)19797a6dacacSDimitry Andric Error PassBuilder::parseMachinePassPipeline(
19807a6dacacSDimitry Andric MachineFunctionPassManager &MFPM, ArrayRef<PipelineElement> Pipeline) {
19817a6dacacSDimitry Andric for (const auto &Element : Pipeline) {
19827a6dacacSDimitry Andric if (auto Err = parseMachinePass(MFPM, Element))
19837a6dacacSDimitry Andric return Err;
19847a6dacacSDimitry Andric }
19857a6dacacSDimitry Andric return Error::success();
19867a6dacacSDimitry Andric }
19877a6dacacSDimitry Andric
parseLoopPassPipeline(LoopPassManager & LPM,ArrayRef<PipelineElement> Pipeline)19880b57cec5SDimitry Andric Error PassBuilder::parseLoopPassPipeline(LoopPassManager &LPM,
1989e8d8bef9SDimitry Andric ArrayRef<PipelineElement> Pipeline) {
19900b57cec5SDimitry Andric for (const auto &Element : Pipeline) {
1991e8d8bef9SDimitry Andric if (auto Err = parseLoopPass(LPM, Element))
19920b57cec5SDimitry Andric return Err;
19930b57cec5SDimitry Andric }
19940b57cec5SDimitry Andric return Error::success();
19950b57cec5SDimitry Andric }
19960b57cec5SDimitry Andric
parseFunctionPassPipeline(FunctionPassManager & FPM,ArrayRef<PipelineElement> Pipeline)1997e8d8bef9SDimitry Andric Error PassBuilder::parseFunctionPassPipeline(
1998e8d8bef9SDimitry Andric FunctionPassManager &FPM, ArrayRef<PipelineElement> Pipeline) {
19990b57cec5SDimitry Andric for (const auto &Element : Pipeline) {
2000e8d8bef9SDimitry Andric if (auto Err = parseFunctionPass(FPM, Element))
20010b57cec5SDimitry Andric return Err;
20020b57cec5SDimitry Andric }
20030b57cec5SDimitry Andric return Error::success();
20040b57cec5SDimitry Andric }
20050b57cec5SDimitry Andric
parseCGSCCPassPipeline(CGSCCPassManager & CGPM,ArrayRef<PipelineElement> Pipeline)20060b57cec5SDimitry Andric Error PassBuilder::parseCGSCCPassPipeline(CGSCCPassManager &CGPM,
2007e8d8bef9SDimitry Andric ArrayRef<PipelineElement> Pipeline) {
20080b57cec5SDimitry Andric for (const auto &Element : Pipeline) {
2009e8d8bef9SDimitry Andric if (auto Err = parseCGSCCPass(CGPM, Element))
20100b57cec5SDimitry Andric return Err;
20110b57cec5SDimitry Andric }
20120b57cec5SDimitry Andric return Error::success();
20130b57cec5SDimitry Andric }
20140b57cec5SDimitry Andric
crossRegisterProxies(LoopAnalysisManager & LAM,FunctionAnalysisManager & FAM,CGSCCAnalysisManager & CGAM,ModuleAnalysisManager & MAM,MachineFunctionAnalysisManager * MFAM)20150b57cec5SDimitry Andric void PassBuilder::crossRegisterProxies(LoopAnalysisManager &LAM,
20160b57cec5SDimitry Andric FunctionAnalysisManager &FAM,
20170b57cec5SDimitry Andric CGSCCAnalysisManager &CGAM,
2018*0fca6ea1SDimitry Andric ModuleAnalysisManager &MAM,
2019*0fca6ea1SDimitry Andric MachineFunctionAnalysisManager *MFAM) {
20200b57cec5SDimitry Andric MAM.registerPass([&] { return FunctionAnalysisManagerModuleProxy(FAM); });
20210b57cec5SDimitry Andric MAM.registerPass([&] { return CGSCCAnalysisManagerModuleProxy(CGAM); });
20220b57cec5SDimitry Andric CGAM.registerPass([&] { return ModuleAnalysisManagerCGSCCProxy(MAM); });
20230b57cec5SDimitry Andric FAM.registerPass([&] { return CGSCCAnalysisManagerFunctionProxy(CGAM); });
20240b57cec5SDimitry Andric FAM.registerPass([&] { return ModuleAnalysisManagerFunctionProxy(MAM); });
20250b57cec5SDimitry Andric FAM.registerPass([&] { return LoopAnalysisManagerFunctionProxy(LAM); });
20260b57cec5SDimitry Andric LAM.registerPass([&] { return FunctionAnalysisManagerLoopProxy(FAM); });
2027*0fca6ea1SDimitry Andric if (MFAM) {
2028*0fca6ea1SDimitry Andric MAM.registerPass(
2029*0fca6ea1SDimitry Andric [&] { return MachineFunctionAnalysisManagerModuleProxy(*MFAM); });
2030*0fca6ea1SDimitry Andric FAM.registerPass(
2031*0fca6ea1SDimitry Andric [&] { return MachineFunctionAnalysisManagerFunctionProxy(*MFAM); });
2032*0fca6ea1SDimitry Andric MFAM->registerPass(
2033*0fca6ea1SDimitry Andric [&] { return ModuleAnalysisManagerMachineFunctionProxy(MAM); });
2034*0fca6ea1SDimitry Andric MFAM->registerPass(
2035*0fca6ea1SDimitry Andric [&] { return FunctionAnalysisManagerMachineFunctionProxy(FAM); });
2036*0fca6ea1SDimitry Andric }
20370b57cec5SDimitry Andric }
20380b57cec5SDimitry Andric
parseModulePassPipeline(ModulePassManager & MPM,ArrayRef<PipelineElement> Pipeline)20390b57cec5SDimitry Andric Error PassBuilder::parseModulePassPipeline(ModulePassManager &MPM,
2040e8d8bef9SDimitry Andric ArrayRef<PipelineElement> Pipeline) {
20410b57cec5SDimitry Andric for (const auto &Element : Pipeline) {
2042e8d8bef9SDimitry Andric if (auto Err = parseModulePass(MPM, Element))
20430b57cec5SDimitry Andric return Err;
20440b57cec5SDimitry Andric }
20450b57cec5SDimitry Andric return Error::success();
20460b57cec5SDimitry Andric }
20470b57cec5SDimitry Andric
20480b57cec5SDimitry Andric // Primary pass pipeline description parsing routine for a \c ModulePassManager
20490b57cec5SDimitry Andric // FIXME: Should this routine accept a TargetMachine or require the caller to
20500b57cec5SDimitry Andric // pre-populate the analysis managers with target-specific stuff?
parsePassPipeline(ModulePassManager & MPM,StringRef PipelineText)20510b57cec5SDimitry Andric Error PassBuilder::parsePassPipeline(ModulePassManager &MPM,
2052e8d8bef9SDimitry Andric StringRef PipelineText) {
20530b57cec5SDimitry Andric auto Pipeline = parsePipelineText(PipelineText);
20540b57cec5SDimitry Andric if (!Pipeline || Pipeline->empty())
20550b57cec5SDimitry Andric return make_error<StringError>(
20560b57cec5SDimitry Andric formatv("invalid pipeline '{0}'", PipelineText).str(),
20570b57cec5SDimitry Andric inconvertibleErrorCode());
20580b57cec5SDimitry Andric
20590b57cec5SDimitry Andric // If the first name isn't at the module layer, wrap the pipeline up
20600b57cec5SDimitry Andric // automatically.
20610b57cec5SDimitry Andric StringRef FirstName = Pipeline->front().Name;
20620b57cec5SDimitry Andric
20630b57cec5SDimitry Andric if (!isModulePassName(FirstName, ModulePipelineParsingCallbacks)) {
2064349cc55cSDimitry Andric bool UseMemorySSA;
20650b57cec5SDimitry Andric if (isCGSCCPassName(FirstName, CGSCCPipelineParsingCallbacks)) {
20660b57cec5SDimitry Andric Pipeline = {{"cgscc", std::move(*Pipeline)}};
20670b57cec5SDimitry Andric } else if (isFunctionPassName(FirstName,
20680b57cec5SDimitry Andric FunctionPipelineParsingCallbacks)) {
20690b57cec5SDimitry Andric Pipeline = {{"function", std::move(*Pipeline)}};
2070349cc55cSDimitry Andric } else if (isLoopNestPassName(FirstName, LoopPipelineParsingCallbacks,
2071349cc55cSDimitry Andric UseMemorySSA)) {
2072349cc55cSDimitry Andric Pipeline = {{"function", {{UseMemorySSA ? "loop-mssa" : "loop",
2073349cc55cSDimitry Andric std::move(*Pipeline)}}}};
2074349cc55cSDimitry Andric } else if (isLoopPassName(FirstName, LoopPipelineParsingCallbacks,
2075349cc55cSDimitry Andric UseMemorySSA)) {
2076349cc55cSDimitry Andric Pipeline = {{"function", {{UseMemorySSA ? "loop-mssa" : "loop",
2077349cc55cSDimitry Andric std::move(*Pipeline)}}}};
2078*0fca6ea1SDimitry Andric } else if (isMachineFunctionPassName(
2079*0fca6ea1SDimitry Andric FirstName, MachineFunctionPipelineParsingCallbacks)) {
2080*0fca6ea1SDimitry Andric Pipeline = {{"function", {{"machine-function", std::move(*Pipeline)}}}};
20810b57cec5SDimitry Andric } else {
20820b57cec5SDimitry Andric for (auto &C : TopLevelPipelineParsingCallbacks)
2083fe6060f1SDimitry Andric if (C(MPM, *Pipeline))
20840b57cec5SDimitry Andric return Error::success();
20850b57cec5SDimitry Andric
20860b57cec5SDimitry Andric // Unknown pass or pipeline name!
20870b57cec5SDimitry Andric auto &InnerPipeline = Pipeline->front().InnerPipeline;
20880b57cec5SDimitry Andric return make_error<StringError>(
20890b57cec5SDimitry Andric formatv("unknown {0} name '{1}'",
20900b57cec5SDimitry Andric (InnerPipeline.empty() ? "pass" : "pipeline"), FirstName)
20910b57cec5SDimitry Andric .str(),
20920b57cec5SDimitry Andric inconvertibleErrorCode());
20930b57cec5SDimitry Andric }
20940b57cec5SDimitry Andric }
20950b57cec5SDimitry Andric
2096e8d8bef9SDimitry Andric if (auto Err = parseModulePassPipeline(MPM, *Pipeline))
20970b57cec5SDimitry Andric return Err;
20980b57cec5SDimitry Andric return Error::success();
20990b57cec5SDimitry Andric }
21000b57cec5SDimitry Andric
21010b57cec5SDimitry Andric // Primary pass pipeline description parsing routine for a \c CGSCCPassManager
parsePassPipeline(CGSCCPassManager & CGPM,StringRef PipelineText)21020b57cec5SDimitry Andric Error PassBuilder::parsePassPipeline(CGSCCPassManager &CGPM,
2103e8d8bef9SDimitry Andric StringRef PipelineText) {
21040b57cec5SDimitry Andric auto Pipeline = parsePipelineText(PipelineText);
21050b57cec5SDimitry Andric if (!Pipeline || Pipeline->empty())
21060b57cec5SDimitry Andric return make_error<StringError>(
21070b57cec5SDimitry Andric formatv("invalid pipeline '{0}'", PipelineText).str(),
21080b57cec5SDimitry Andric inconvertibleErrorCode());
21090b57cec5SDimitry Andric
21100b57cec5SDimitry Andric StringRef FirstName = Pipeline->front().Name;
21110b57cec5SDimitry Andric if (!isCGSCCPassName(FirstName, CGSCCPipelineParsingCallbacks))
21120b57cec5SDimitry Andric return make_error<StringError>(
21130b57cec5SDimitry Andric formatv("unknown cgscc pass '{0}' in pipeline '{1}'", FirstName,
21140b57cec5SDimitry Andric PipelineText)
21150b57cec5SDimitry Andric .str(),
21160b57cec5SDimitry Andric inconvertibleErrorCode());
21170b57cec5SDimitry Andric
2118e8d8bef9SDimitry Andric if (auto Err = parseCGSCCPassPipeline(CGPM, *Pipeline))
21190b57cec5SDimitry Andric return Err;
21200b57cec5SDimitry Andric return Error::success();
21210b57cec5SDimitry Andric }
21220b57cec5SDimitry Andric
21230b57cec5SDimitry Andric // Primary pass pipeline description parsing routine for a \c
21240b57cec5SDimitry Andric // FunctionPassManager
parsePassPipeline(FunctionPassManager & FPM,StringRef PipelineText)21250b57cec5SDimitry Andric Error PassBuilder::parsePassPipeline(FunctionPassManager &FPM,
2126e8d8bef9SDimitry Andric StringRef PipelineText) {
21270b57cec5SDimitry Andric auto Pipeline = parsePipelineText(PipelineText);
21280b57cec5SDimitry Andric if (!Pipeline || Pipeline->empty())
21290b57cec5SDimitry Andric return make_error<StringError>(
21300b57cec5SDimitry Andric formatv("invalid pipeline '{0}'", PipelineText).str(),
21310b57cec5SDimitry Andric inconvertibleErrorCode());
21320b57cec5SDimitry Andric
21330b57cec5SDimitry Andric StringRef FirstName = Pipeline->front().Name;
21340b57cec5SDimitry Andric if (!isFunctionPassName(FirstName, FunctionPipelineParsingCallbacks))
21350b57cec5SDimitry Andric return make_error<StringError>(
21360b57cec5SDimitry Andric formatv("unknown function pass '{0}' in pipeline '{1}'", FirstName,
21370b57cec5SDimitry Andric PipelineText)
21380b57cec5SDimitry Andric .str(),
21390b57cec5SDimitry Andric inconvertibleErrorCode());
21400b57cec5SDimitry Andric
2141e8d8bef9SDimitry Andric if (auto Err = parseFunctionPassPipeline(FPM, *Pipeline))
21420b57cec5SDimitry Andric return Err;
21430b57cec5SDimitry Andric return Error::success();
21440b57cec5SDimitry Andric }
21450b57cec5SDimitry Andric
21460b57cec5SDimitry Andric // Primary pass pipeline description parsing routine for a \c LoopPassManager
parsePassPipeline(LoopPassManager & CGPM,StringRef PipelineText)21470b57cec5SDimitry Andric Error PassBuilder::parsePassPipeline(LoopPassManager &CGPM,
2148e8d8bef9SDimitry Andric StringRef PipelineText) {
21490b57cec5SDimitry Andric auto Pipeline = parsePipelineText(PipelineText);
21500b57cec5SDimitry Andric if (!Pipeline || Pipeline->empty())
21510b57cec5SDimitry Andric return make_error<StringError>(
21520b57cec5SDimitry Andric formatv("invalid pipeline '{0}'", PipelineText).str(),
21530b57cec5SDimitry Andric inconvertibleErrorCode());
21540b57cec5SDimitry Andric
2155e8d8bef9SDimitry Andric if (auto Err = parseLoopPassPipeline(CGPM, *Pipeline))
21560b57cec5SDimitry Andric return Err;
21570b57cec5SDimitry Andric
21580b57cec5SDimitry Andric return Error::success();
21590b57cec5SDimitry Andric }
21600b57cec5SDimitry Andric
parsePassPipeline(MachineFunctionPassManager & MFPM,StringRef PipelineText)21617a6dacacSDimitry Andric Error PassBuilder::parsePassPipeline(MachineFunctionPassManager &MFPM,
21627a6dacacSDimitry Andric StringRef PipelineText) {
21637a6dacacSDimitry Andric auto Pipeline = parsePipelineText(PipelineText);
21647a6dacacSDimitry Andric if (!Pipeline || Pipeline->empty())
21657a6dacacSDimitry Andric return make_error<StringError>(
21667a6dacacSDimitry Andric formatv("invalid machine pass pipeline '{0}'", PipelineText).str(),
21677a6dacacSDimitry Andric inconvertibleErrorCode());
21687a6dacacSDimitry Andric
21697a6dacacSDimitry Andric if (auto Err = parseMachinePassPipeline(MFPM, *Pipeline))
21707a6dacacSDimitry Andric return Err;
21717a6dacacSDimitry Andric
21727a6dacacSDimitry Andric return Error::success();
21737a6dacacSDimitry Andric }
21747a6dacacSDimitry Andric
parseAAPipeline(AAManager & AA,StringRef PipelineText)21750b57cec5SDimitry Andric Error PassBuilder::parseAAPipeline(AAManager &AA, StringRef PipelineText) {
21760b57cec5SDimitry Andric // If the pipeline just consists of the word 'default' just replace the AA
21770b57cec5SDimitry Andric // manager with our default one.
21780b57cec5SDimitry Andric if (PipelineText == "default") {
21790b57cec5SDimitry Andric AA = buildDefaultAAPipeline();
21800b57cec5SDimitry Andric return Error::success();
21810b57cec5SDimitry Andric }
21820b57cec5SDimitry Andric
21830b57cec5SDimitry Andric while (!PipelineText.empty()) {
21840b57cec5SDimitry Andric StringRef Name;
21850b57cec5SDimitry Andric std::tie(Name, PipelineText) = PipelineText.split(',');
21860b57cec5SDimitry Andric if (!parseAAPassName(AA, Name))
21870b57cec5SDimitry Andric return make_error<StringError>(
21880b57cec5SDimitry Andric formatv("unknown alias analysis name '{0}'", Name).str(),
21890b57cec5SDimitry Andric inconvertibleErrorCode());
21900b57cec5SDimitry Andric }
21910b57cec5SDimitry Andric
21920b57cec5SDimitry Andric return Error::success();
21930b57cec5SDimitry Andric }
21945ffd83dbSDimitry Andric
2195*0fca6ea1SDimitry Andric std::optional<RegAllocFilterFunc>
parseRegAllocFilter(StringRef FilterName)2196*0fca6ea1SDimitry Andric PassBuilder::parseRegAllocFilter(StringRef FilterName) {
2197*0fca6ea1SDimitry Andric if (FilterName == "all")
2198*0fca6ea1SDimitry Andric return nullptr;
2199*0fca6ea1SDimitry Andric for (auto &C : RegClassFilterParsingCallbacks)
2200*0fca6ea1SDimitry Andric if (auto F = C(FilterName))
2201*0fca6ea1SDimitry Andric return F;
2202*0fca6ea1SDimitry Andric return std::nullopt;
2203*0fca6ea1SDimitry Andric }
2204*0fca6ea1SDimitry Andric
printPassName(StringRef PassName,raw_ostream & OS)2205fe6060f1SDimitry Andric static void printPassName(StringRef PassName, raw_ostream &OS) {
2206fe6060f1SDimitry Andric OS << " " << PassName << "\n";
2207fe6060f1SDimitry Andric }
printPassName(StringRef PassName,StringRef Params,raw_ostream & OS)2208fe6060f1SDimitry Andric static void printPassName(StringRef PassName, StringRef Params,
2209fe6060f1SDimitry Andric raw_ostream &OS) {
2210fe6060f1SDimitry Andric OS << " " << PassName << "<" << Params << ">\n";
2211fe6060f1SDimitry Andric }
2212fe6060f1SDimitry Andric
printPassNames(raw_ostream & OS)2213fe6060f1SDimitry Andric void PassBuilder::printPassNames(raw_ostream &OS) {
2214fe6060f1SDimitry Andric // TODO: print pass descriptions when they are available
2215fe6060f1SDimitry Andric
2216fe6060f1SDimitry Andric OS << "Module passes:\n";
2217fe6060f1SDimitry Andric #define MODULE_PASS(NAME, CREATE_PASS) printPassName(NAME, OS);
2218fe6060f1SDimitry Andric #include "PassRegistry.def"
2219fe6060f1SDimitry Andric
2220349cc55cSDimitry Andric OS << "Module passes with params:\n";
2221349cc55cSDimitry Andric #define MODULE_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \
2222349cc55cSDimitry Andric printPassName(NAME, PARAMS, OS);
2223349cc55cSDimitry Andric #include "PassRegistry.def"
2224349cc55cSDimitry Andric
2225fe6060f1SDimitry Andric OS << "Module analyses:\n";
2226fe6060f1SDimitry Andric #define MODULE_ANALYSIS(NAME, CREATE_PASS) printPassName(NAME, OS);
2227fe6060f1SDimitry Andric #include "PassRegistry.def"
2228fe6060f1SDimitry Andric
2229fe6060f1SDimitry Andric OS << "Module alias analyses:\n";
2230fe6060f1SDimitry Andric #define MODULE_ALIAS_ANALYSIS(NAME, CREATE_PASS) printPassName(NAME, OS);
2231fe6060f1SDimitry Andric #include "PassRegistry.def"
2232fe6060f1SDimitry Andric
2233fe6060f1SDimitry Andric OS << "CGSCC passes:\n";
2234fe6060f1SDimitry Andric #define CGSCC_PASS(NAME, CREATE_PASS) printPassName(NAME, OS);
2235fe6060f1SDimitry Andric #include "PassRegistry.def"
2236fe6060f1SDimitry Andric
2237349cc55cSDimitry Andric OS << "CGSCC passes with params:\n";
2238349cc55cSDimitry Andric #define CGSCC_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \
2239349cc55cSDimitry Andric printPassName(NAME, PARAMS, OS);
2240349cc55cSDimitry Andric #include "PassRegistry.def"
2241349cc55cSDimitry Andric
2242fe6060f1SDimitry Andric OS << "CGSCC analyses:\n";
2243fe6060f1SDimitry Andric #define CGSCC_ANALYSIS(NAME, CREATE_PASS) printPassName(NAME, OS);
2244fe6060f1SDimitry Andric #include "PassRegistry.def"
2245fe6060f1SDimitry Andric
2246fe6060f1SDimitry Andric OS << "Function passes:\n";
2247fe6060f1SDimitry Andric #define FUNCTION_PASS(NAME, CREATE_PASS) printPassName(NAME, OS);
2248fe6060f1SDimitry Andric #include "PassRegistry.def"
2249fe6060f1SDimitry Andric
2250fe6060f1SDimitry Andric OS << "Function passes with params:\n";
2251fe6060f1SDimitry Andric #define FUNCTION_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \
2252fe6060f1SDimitry Andric printPassName(NAME, PARAMS, OS);
2253fe6060f1SDimitry Andric #include "PassRegistry.def"
2254fe6060f1SDimitry Andric
2255fe6060f1SDimitry Andric OS << "Function analyses:\n";
2256fe6060f1SDimitry Andric #define FUNCTION_ANALYSIS(NAME, CREATE_PASS) printPassName(NAME, OS);
2257fe6060f1SDimitry Andric #include "PassRegistry.def"
2258fe6060f1SDimitry Andric
2259fe6060f1SDimitry Andric OS << "Function alias analyses:\n";
2260fe6060f1SDimitry Andric #define FUNCTION_ALIAS_ANALYSIS(NAME, CREATE_PASS) printPassName(NAME, OS);
2261fe6060f1SDimitry Andric #include "PassRegistry.def"
2262fe6060f1SDimitry Andric
2263349cc55cSDimitry Andric OS << "LoopNest passes:\n";
2264349cc55cSDimitry Andric #define LOOPNEST_PASS(NAME, CREATE_PASS) printPassName(NAME, OS);
2265349cc55cSDimitry Andric #include "PassRegistry.def"
2266349cc55cSDimitry Andric
2267fe6060f1SDimitry Andric OS << "Loop passes:\n";
2268fe6060f1SDimitry Andric #define LOOP_PASS(NAME, CREATE_PASS) printPassName(NAME, OS);
2269fe6060f1SDimitry Andric #include "PassRegistry.def"
2270fe6060f1SDimitry Andric
2271fe6060f1SDimitry Andric OS << "Loop passes with params:\n";
2272fe6060f1SDimitry Andric #define LOOP_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \
2273fe6060f1SDimitry Andric printPassName(NAME, PARAMS, OS);
2274fe6060f1SDimitry Andric #include "PassRegistry.def"
2275fe6060f1SDimitry Andric
2276fe6060f1SDimitry Andric OS << "Loop analyses:\n";
2277fe6060f1SDimitry Andric #define LOOP_ANALYSIS(NAME, CREATE_PASS) printPassName(NAME, OS);
2278fe6060f1SDimitry Andric #include "PassRegistry.def"
22797a6dacacSDimitry Andric
22807a6dacacSDimitry Andric OS << "Machine module passes (WIP):\n";
2281*0fca6ea1SDimitry Andric #define MACHINE_MODULE_PASS(NAME, CREATE_PASS) printPassName(NAME, OS);
2282*0fca6ea1SDimitry Andric #include "llvm/Passes/MachinePassRegistry.def"
22837a6dacacSDimitry Andric
22847a6dacacSDimitry Andric OS << "Machine function passes (WIP):\n";
2285*0fca6ea1SDimitry Andric #define MACHINE_FUNCTION_PASS(NAME, CREATE_PASS) printPassName(NAME, OS);
2286*0fca6ea1SDimitry Andric #include "llvm/Passes/MachinePassRegistry.def"
22877a6dacacSDimitry Andric
22887a6dacacSDimitry Andric OS << "Machine function analyses (WIP):\n";
2289*0fca6ea1SDimitry Andric #define MACHINE_FUNCTION_ANALYSIS(NAME, CREATE_PASS) printPassName(NAME, OS);
2290*0fca6ea1SDimitry Andric #include "llvm/Passes/MachinePassRegistry.def"
2291fe6060f1SDimitry Andric }
2292fe6060f1SDimitry Andric
registerParseTopLevelPipelineCallback(const std::function<bool (ModulePassManager &,ArrayRef<PipelineElement>)> & C)2293e8d8bef9SDimitry Andric void PassBuilder::registerParseTopLevelPipelineCallback(
2294fe6060f1SDimitry Andric const std::function<bool(ModulePassManager &, ArrayRef<PipelineElement>)>
2295fe6060f1SDimitry Andric &C) {
2296e8d8bef9SDimitry Andric TopLevelPipelineParsingCallbacks.push_back(C);
2297e8d8bef9SDimitry Andric }
2298