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