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