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