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