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 : LibraryOptions(PTO.LibraryOptions ? PTO.LibraryOptions
574 : TM ? TM->Options.MCOptions.LibraryOptions
575 : nullptr),
576 Opts(cl::LibraryOptionsContext::get<PassesOptions>(C: LibraryOptions)),
577 TM(TM), PTO(PTO), PGOOpt(PGOOpt), PIC(PIC), FS(std::move(FS)) {
578 if (TM)
579 TM->registerPassBuilderCallbacks(*this);
580 if (PIC) {
581 PIC->registerClassToPassNameCallback(C: [this, PIC]() {
582 // MSVC requires this to be captured if it's used inside decltype.
583 // Other compilers consider it an unused lambda capture.
584 (void)this;
585#define MODULE_PASS(NAME, CREATE_PASS) \
586 PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME);
587#define MODULE_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \
588 PIC->addClassToPassName(CLASS, NAME);
589#define MODULE_ANALYSIS(NAME, CREATE_PASS) \
590 PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME);
591#define FUNCTION_PASS(NAME, CREATE_PASS) \
592 PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME);
593#define FUNCTION_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \
594 PIC->addClassToPassName(CLASS, NAME);
595#define FUNCTION_ANALYSIS(NAME, CREATE_PASS) \
596 PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME);
597#define LOOPNEST_PASS(NAME, CREATE_PASS) \
598 PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME);
599#define LOOP_PASS(NAME, CREATE_PASS) \
600 PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME);
601#define LOOP_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \
602 PIC->addClassToPassName(CLASS, NAME);
603#define LOOP_ANALYSIS(NAME, CREATE_PASS) \
604 PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME);
605#define CGSCC_PASS(NAME, CREATE_PASS) \
606 PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME);
607#define CGSCC_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \
608 PIC->addClassToPassName(CLASS, NAME);
609#define CGSCC_ANALYSIS(NAME, CREATE_PASS) \
610 PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME);
611#include "PassRegistry.def"
612
613#define MACHINE_FUNCTION_ANALYSIS(NAME, CREATE_PASS) \
614 PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME);
615#define MACHINE_FUNCTION_PASS(NAME, CREATE_PASS) \
616 PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME);
617#define MACHINE_FUNCTION_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, \
618 PARAMS) \
619 PIC->addClassToPassName(CLASS, NAME);
620#include "llvm/Passes/MachinePassRegistry.def"
621 });
622 }
623
624 // Module-level callbacks without LTO phase
625 registerPipelineParsingCallback(
626 C: [this](StringRef Name, ModulePassManager &PM,
627 ArrayRef<PassBuilder::PipelineElement>) {
628#define MODULE_CALLBACK(NAME, INVOKE) \
629 if (PassBuilder::checkParametrizedPassName(Name, NAME)) { \
630 auto L = PassBuilder::parsePassParameters(parseOptLevelParam, Name, NAME); \
631 if (!L) { \
632 errs() << NAME ": " << toString(L.takeError()) << '\n'; \
633 return false; \
634 } \
635 INVOKE(PM, L.get()); \
636 return true; \
637 }
638#include "PassRegistry.def"
639 return false;
640 });
641
642 // Module-level callbacks with LTO phase (use Phase::None for string API)
643 registerPipelineParsingCallback(
644 C: [this](StringRef Name, ModulePassManager &PM,
645 ArrayRef<PassBuilder::PipelineElement>) {
646#define MODULE_LTO_CALLBACK(NAME, INVOKE) \
647 if (PassBuilder::checkParametrizedPassName(Name, NAME)) { \
648 auto L = PassBuilder::parsePassParameters(parseOptLevelParam, Name, NAME); \
649 if (!L) { \
650 errs() << NAME ": " << toString(L.takeError()) << '\n'; \
651 return false; \
652 } \
653 INVOKE(PM, L.get(), ThinOrFullLTOPhase::None); \
654 return true; \
655 }
656#include "PassRegistry.def"
657 return false;
658 });
659
660 // Function-level callbacks
661 registerPipelineParsingCallback(
662 C: [this](StringRef Name, FunctionPassManager &PM,
663 ArrayRef<PassBuilder::PipelineElement>) {
664#define FUNCTION_CALLBACK(NAME, INVOKE) \
665 if (PassBuilder::checkParametrizedPassName(Name, NAME)) { \
666 auto L = PassBuilder::parsePassParameters(parseOptLevelParam, Name, NAME); \
667 if (!L) { \
668 errs() << NAME ": " << toString(L.takeError()) << '\n'; \
669 return false; \
670 } \
671 INVOKE(PM, L.get()); \
672 return true; \
673 }
674#include "PassRegistry.def"
675 return false;
676 });
677
678 // CGSCC-level callbacks
679 registerPipelineParsingCallback(
680 C: [this](StringRef Name, CGSCCPassManager &PM,
681 ArrayRef<PassBuilder::PipelineElement>) {
682#define CGSCC_CALLBACK(NAME, INVOKE) \
683 if (PassBuilder::checkParametrizedPassName(Name, NAME)) { \
684 auto L = PassBuilder::parsePassParameters(parseOptLevelParam, Name, NAME); \
685 if (!L) { \
686 errs() << NAME ": " << toString(L.takeError()) << '\n'; \
687 return false; \
688 } \
689 INVOKE(PM, L.get()); \
690 return true; \
691 }
692#include "PassRegistry.def"
693 return false;
694 });
695
696 // Loop-level callbacks
697 registerPipelineParsingCallback(
698 C: [this](StringRef Name, LoopPassManager &PM,
699 ArrayRef<PassBuilder::PipelineElement>) {
700#define LOOP_CALLBACK(NAME, INVOKE) \
701 if (PassBuilder::checkParametrizedPassName(Name, NAME)) { \
702 auto L = PassBuilder::parsePassParameters(parseOptLevelParam, Name, NAME); \
703 if (!L) { \
704 errs() << NAME ": " << toString(L.takeError()) << '\n'; \
705 return false; \
706 } \
707 INVOKE(PM, L.get()); \
708 return true; \
709 }
710#include "PassRegistry.def"
711 return false;
712 });
713}
714
715void PassBuilder::registerModuleAnalyses(ModuleAnalysisManager &MAM) {
716#define MODULE_ANALYSIS(NAME, CREATE_PASS) \
717 MAM.registerPass([&] { return CREATE_PASS; });
718#include "PassRegistry.def"
719
720 for (auto &C : ModuleAnalysisRegistrationCallbacks)
721 C(MAM);
722}
723
724void PassBuilder::registerCGSCCAnalyses(CGSCCAnalysisManager &CGAM) {
725#define CGSCC_ANALYSIS(NAME, CREATE_PASS) \
726 CGAM.registerPass([&] { return CREATE_PASS; });
727#include "PassRegistry.def"
728
729 for (auto &C : CGSCCAnalysisRegistrationCallbacks)
730 C(CGAM);
731}
732
733void PassBuilder::registerFunctionAnalyses(FunctionAnalysisManager &FAM) {
734 // We almost always want the default alias analysis pipeline.
735 // If a user wants a different one, they can register their own before calling
736 // registerFunctionAnalyses().
737 FAM.registerPass(PassBuilder: [&] { return buildDefaultAAPipeline(); });
738
739#define FUNCTION_ANALYSIS(NAME, CREATE_PASS) \
740 if constexpr (std::is_constructible_v< \
741 std::remove_reference_t<decltype(CREATE_PASS)>, \
742 const TargetMachine &>) { \
743 if (TM) \
744 FAM.registerPass([&] { return CREATE_PASS; }); \
745 } else { \
746 FAM.registerPass([&] { return CREATE_PASS; }); \
747 }
748#include "PassRegistry.def"
749
750 for (auto &C : FunctionAnalysisRegistrationCallbacks)
751 C(FAM);
752}
753
754void PassBuilder::registerMachineFunctionAnalyses(
755 MachineFunctionAnalysisManager &MFAM) {
756
757#define MACHINE_FUNCTION_ANALYSIS(NAME, CREATE_PASS) \
758 MFAM.registerPass([&] { return CREATE_PASS; });
759#include "llvm/Passes/MachinePassRegistry.def"
760
761 for (auto &C : MachineFunctionAnalysisRegistrationCallbacks)
762 C(MFAM);
763}
764
765void PassBuilder::registerLoopAnalyses(LoopAnalysisManager &LAM) {
766#define LOOP_ANALYSIS(NAME, CREATE_PASS) \
767 LAM.registerPass([&] { return CREATE_PASS; });
768#include "PassRegistry.def"
769
770 for (auto &C : LoopAnalysisRegistrationCallbacks)
771 C(LAM);
772}
773
774static std::optional<std::pair<bool, bool>>
775parseFunctionPipelineName(StringRef Name) {
776 std::pair<bool, bool> Params;
777 if (!Name.consume_front(Prefix: "function"))
778 return std::nullopt;
779 if (Name.empty())
780 return Params;
781 if (!Name.consume_front(Prefix: "<") || !Name.consume_back(Suffix: ">"))
782 return std::nullopt;
783 while (!Name.empty()) {
784 auto [Front, Back] = Name.split(Separator: ';');
785 Name = Back;
786 if (Front == "eager-inv")
787 Params.first = true;
788 else if (Front == "no-rerun")
789 Params.second = true;
790 else
791 return std::nullopt;
792 }
793 return Params;
794}
795
796static std::optional<int> parseDevirtPassName(StringRef Name) {
797 if (!Name.consume_front(Prefix: "devirt<") || !Name.consume_back(Suffix: ">"))
798 return std::nullopt;
799 int Count;
800 if (Name.getAsInteger(Radix: 0, Result&: Count) || Count < 0)
801 return std::nullopt;
802 return Count;
803}
804
805Expected<bool> PassBuilder::parseSinglePassOption(StringRef Params,
806 StringRef OptionName,
807 StringRef PassName) {
808 bool Result = false;
809 while (!Params.empty()) {
810 StringRef ParamName;
811 std::tie(args&: ParamName, args&: Params) = Params.split(Separator: ';');
812
813 if (ParamName == OptionName) {
814 Result = true;
815 } else {
816 return make_error<StringError>(
817 Args: formatv(Fmt: "invalid {} pass parameter '{}'", Vals&: PassName, Vals&: ParamName).str(),
818 Args: inconvertibleErrorCode());
819 }
820 }
821 return Result;
822}
823
824namespace {
825
826/// Parser of parameters for HardwareLoops pass.
827Expected<HardwareLoopOptions> parseHardwareLoopOptions(StringRef Params) {
828 HardwareLoopOptions HardwareLoopOpts;
829
830 while (!Params.empty()) {
831 StringRef ParamName;
832 std::tie(args&: ParamName, args&: Params) = Params.split(Separator: ';');
833 if (ParamName.consume_front(Prefix: "hardware-loop-decrement=")) {
834 int Count;
835 if (ParamName.getAsInteger(Radix: 0, Result&: Count))
836 return make_error<StringError>(
837 Args: formatv(Fmt: "invalid HardwareLoopPass parameter '{}'", Vals&: ParamName).str(),
838 Args: inconvertibleErrorCode());
839 HardwareLoopOpts.setDecrement(Count);
840 continue;
841 }
842 if (ParamName.consume_front(Prefix: "hardware-loop-counter-bitwidth=")) {
843 int Count;
844 if (ParamName.getAsInteger(Radix: 0, Result&: Count))
845 return make_error<StringError>(
846 Args: formatv(Fmt: "invalid HardwareLoopPass parameter '{}'", Vals&: ParamName).str(),
847 Args: inconvertibleErrorCode());
848 HardwareLoopOpts.setCounterBitwidth(Count);
849 continue;
850 }
851 if (ParamName == "force-hardware-loops") {
852 HardwareLoopOpts.setForce(true);
853 } else if (ParamName == "force-hardware-loop-phi") {
854 HardwareLoopOpts.setForcePhi(true);
855 } else if (ParamName == "force-nested-hardware-loop") {
856 HardwareLoopOpts.setForceNested(true);
857 } else if (ParamName == "force-hardware-loop-guard") {
858 HardwareLoopOpts.setForceGuard(true);
859 } else {
860 return make_error<StringError>(
861 Args: formatv(Fmt: "invalid HardwarePass parameter '{}'", Vals&: ParamName).str(),
862 Args: inconvertibleErrorCode());
863 }
864 }
865 return HardwareLoopOpts;
866}
867
868/// Parser of parameters for Lint pass.
869Expected<bool> parseLintOptions(StringRef Params) {
870 return PassBuilder::parseSinglePassOption(Params, OptionName: "abort-on-error",
871 PassName: "LintPass");
872}
873
874/// Parser of parameters for FunctionPropertiesStatistics pass.
875Expected<bool> parseFunctionPropertiesStatisticsOptions(StringRef Params) {
876 return PassBuilder::parseSinglePassOption(Params, OptionName: "pre-opt",
877 PassName: "FunctionPropertiesStatisticsPass");
878}
879
880/// Parser of parameters for InstCount pass.
881Expected<bool> parseInstCountOptions(StringRef Params) {
882 return PassBuilder::parseSinglePassOption(Params, OptionName: "pre-opt", PassName: "InstCountPass");
883}
884
885Expected<bool> parseInferAddressSpacesPassOptions(StringRef Params) {
886 return PassBuilder::parseSinglePassOption(
887 Params, OptionName: "assume-default-is-flat-addrspace", PassName: "InferAddressSpacesPass");
888}
889
890/// Parser of parameters for LoopUnroll pass.
891Expected<LoopUnrollOptions> parseLoopUnrollOptions(StringRef Params) {
892 LoopUnrollOptions UnrollOpts;
893 while (!Params.empty()) {
894 StringRef ParamName;
895 std::tie(args&: ParamName, args&: Params) = Params.split(Separator: ';');
896 std::optional<OptimizationLevel> OptLevel = parseOptLevel(S: ParamName);
897 if (OptLevel) {
898 UnrollOpts.setOptLevel(static_cast<int>(*OptLevel));
899 continue;
900 }
901 if (ParamName.consume_front(Prefix: "full-unroll-max=")) {
902 int Count;
903 if (ParamName.getAsInteger(Radix: 0, Result&: Count))
904 return make_error<StringError>(
905 Args: formatv(Fmt: "invalid LoopUnrollPass parameter '{}'", Vals&: ParamName).str(),
906 Args: inconvertibleErrorCode());
907 UnrollOpts.setFullUnrollMaxCount(Count);
908 continue;
909 }
910
911 bool Enable = !ParamName.consume_front(Prefix: "no-");
912 if (ParamName == "partial") {
913 UnrollOpts.setPartial(Enable);
914 } else if (ParamName == "peeling") {
915 UnrollOpts.setPeeling(Enable);
916 } else if (ParamName == "profile-peeling") {
917 UnrollOpts.setProfileBasedPeeling(Enable);
918 } else if (ParamName == "runtime") {
919 UnrollOpts.setRuntime(Enable);
920 } else if (ParamName == "upperbound") {
921 UnrollOpts.setUpperBound(Enable);
922 } else if (ParamName == "prepare-for-lto") {
923 UnrollOpts.setPrepareForLTO(Enable);
924 } else {
925 return make_error<StringError>(
926 Args: formatv(Fmt: "invalid LoopUnrollPass parameter '{}'", Vals&: ParamName).str(),
927 Args: inconvertibleErrorCode());
928 }
929 }
930 return UnrollOpts;
931}
932
933Expected<bool> parseGlobalDCEPassOptions(StringRef Params) {
934 return PassBuilder::parseSinglePassOption(
935 Params, OptionName: "vfe-linkage-unit-visibility", PassName: "GlobalDCE");
936}
937
938Expected<bool> parseCGProfilePassOptions(StringRef Params) {
939 return PassBuilder::parseSinglePassOption(Params, OptionName: "in-lto-post-link",
940 PassName: "CGProfile");
941}
942
943Expected<bool> parseInlinerPassOptions(StringRef Params) {
944 return PassBuilder::parseSinglePassOption(Params, OptionName: "only-mandatory",
945 PassName: "InlinerPass");
946}
947
948Expected<bool> parseCoroSplitPassOptions(StringRef Params) {
949 return PassBuilder::parseSinglePassOption(Params, OptionName: "reuse-storage",
950 PassName: "CoroSplitPass");
951}
952
953Expected<bool> parsePostOrderFunctionAttrsPassOptions(StringRef Params) {
954 return PassBuilder::parseSinglePassOption(
955 Params, OptionName: "skip-non-recursive-function-attrs", PassName: "PostOrderFunctionAttrs");
956}
957
958Expected<bool> parseEarlyCSEPassOptions(StringRef Params) {
959 return PassBuilder::parseSinglePassOption(Params, OptionName: "memssa", PassName: "EarlyCSE");
960}
961
962Expected<bool> parseEntryExitInstrumenterPassOptions(StringRef Params) {
963 return PassBuilder::parseSinglePassOption(Params, OptionName: "post-inline",
964 PassName: "EntryExitInstrumenter");
965}
966
967Expected<bool> parseDropUnnecessaryAssumesPassOptions(StringRef Params) {
968 return PassBuilder::parseSinglePassOption(Params, OptionName: "drop-deref",
969 PassName: "DropUnnecessaryAssumes");
970}
971
972Expected<bool> parseLowerMatrixIntrinsicsPassOptions(StringRef Params) {
973 return PassBuilder::parseSinglePassOption(Params, OptionName: "minimal",
974 PassName: "LowerMatrixIntrinsics");
975}
976
977Expected<IRNormalizerOptions> parseIRNormalizerPassOptions(StringRef Params) {
978 IRNormalizerOptions Result;
979 while (!Params.empty()) {
980 StringRef ParamName;
981 std::tie(args&: ParamName, args&: Params) = Params.split(Separator: ';');
982
983 bool Enable = !ParamName.consume_front(Prefix: "no-");
984 if (ParamName == "preserve-order")
985 Result.PreserveOrder = Enable;
986 else if (ParamName == "rename-all")
987 Result.RenameAll = Enable;
988 else if (ParamName == "fold-all") // FIXME: Name mismatch
989 Result.FoldPreOutputs = Enable;
990 else if (ParamName == "reorder-operands")
991 Result.ReorderOperands = Enable;
992 else {
993 return make_error<StringError>(
994 Args: formatv(Fmt: "invalid normalize pass parameter '{}'", Vals&: ParamName).str(),
995 Args: inconvertibleErrorCode());
996 }
997 }
998
999 return Result;
1000}
1001
1002Expected<AddressSanitizerOptions> parseASanPassOptions(StringRef Params) {
1003 AddressSanitizerOptions Result;
1004 while (!Params.empty()) {
1005 StringRef ParamName;
1006 std::tie(args&: ParamName, args&: Params) = Params.split(Separator: ';');
1007
1008 if (ParamName == "kernel") {
1009 Result.CompileKernel = true;
1010 } else if (ParamName == "use-after-scope") {
1011 Result.UseAfterScope = true;
1012 } else {
1013 return make_error<StringError>(
1014 Args: formatv(Fmt: "invalid AddressSanitizer pass parameter '{}'", Vals&: ParamName)
1015 .str(),
1016 Args: inconvertibleErrorCode());
1017 }
1018 }
1019 return Result;
1020}
1021
1022Expected<HWAddressSanitizerOptions> parseHWASanPassOptions(StringRef Params) {
1023 HWAddressSanitizerOptions Result;
1024 while (!Params.empty()) {
1025 StringRef ParamName;
1026 std::tie(args&: ParamName, args&: Params) = Params.split(Separator: ';');
1027
1028 if (ParamName == "recover") {
1029 Result.Recover = true;
1030 } else if (ParamName == "kernel") {
1031 Result.CompileKernel = true;
1032 } else {
1033 return make_error<StringError>(
1034 Args: formatv(Fmt: "invalid HWAddressSanitizer pass parameter '{}'", Vals&: ParamName)
1035 .str(),
1036 Args: inconvertibleErrorCode());
1037 }
1038 }
1039 return Result;
1040}
1041
1042Expected<lowertypetests::DropTestKind>
1043parseDropTypeTestsPassOptions(StringRef Params) {
1044 lowertypetests::DropTestKind Result = lowertypetests::DropTestKind::Assume;
1045 while (!Params.empty()) {
1046 StringRef ParamName;
1047 std::tie(args&: ParamName, args&: Params) = Params.split(Separator: ';');
1048
1049 if (ParamName == "all") {
1050 Result = lowertypetests::DropTestKind::All;
1051 } else if (ParamName == "assume") {
1052 Result = lowertypetests::DropTestKind::Assume;
1053 } else {
1054 return make_error<StringError>(
1055 Args: formatv(Fmt: "invalid DropTypeTestsPass parameter '{}'", Vals&: ParamName).str(),
1056 Args: inconvertibleErrorCode());
1057 }
1058 }
1059 return Result;
1060}
1061
1062Expected<EmbedBitcodeOptions> parseEmbedBitcodePassOptions(StringRef Params) {
1063 EmbedBitcodeOptions Result;
1064 while (!Params.empty()) {
1065 StringRef ParamName;
1066 std::tie(args&: ParamName, args&: Params) = Params.split(Separator: ';');
1067
1068 if (ParamName == "thinlto") {
1069 Result.IsThinLTO = true;
1070 } else if (ParamName == "emit-summary") {
1071 Result.EmitLTOSummary = true;
1072 } else {
1073 return make_error<StringError>(
1074 Args: formatv(Fmt: "invalid EmbedBitcode pass parameter '{}'", Vals&: ParamName).str(),
1075 Args: inconvertibleErrorCode());
1076 }
1077 }
1078 return Result;
1079}
1080
1081Expected<LowerAllowCheckPass::Options>
1082parseLowerAllowCheckPassOptions(StringRef Params) {
1083 LowerAllowCheckPass::Options Result;
1084 while (!Params.empty()) {
1085 StringRef ParamName;
1086 std::tie(args&: ParamName, args&: Params) = Params.split(Separator: ';');
1087
1088 // Format is <cutoffs[1,2,3]=70000;cutoffs[5,6,8]=90000>
1089 //
1090 // Parsing allows duplicate indices (last one takes precedence).
1091 // It would technically be in spec to specify
1092 // cutoffs[0]=70000,cutoffs[1]=90000,cutoffs[0]=80000,...
1093 if (ParamName.starts_with(Prefix: "cutoffs[")) {
1094 StringRef IndicesStr;
1095 StringRef CutoffStr;
1096
1097 std::tie(args&: IndicesStr, args&: CutoffStr) = ParamName.split(Separator: "]=");
1098 // cutoffs[1,2,3
1099 // 70000
1100
1101 int cutoff;
1102 if (CutoffStr.getAsInteger(Radix: 0, Result&: cutoff))
1103 return make_error<StringError>(
1104 Args: formatv(Fmt: "invalid LowerAllowCheck pass cutoffs parameter '{}' ({})",
1105 Vals&: CutoffStr, Vals&: Params)
1106 .str(),
1107 Args: inconvertibleErrorCode());
1108
1109 if (!IndicesStr.consume_front(Prefix: "cutoffs[") || IndicesStr == "")
1110 return make_error<StringError>(
1111 Args: formatv(Fmt: "invalid LowerAllowCheck pass index parameter '{}' ({})",
1112 Vals&: IndicesStr, Vals&: CutoffStr)
1113 .str(),
1114 Args: inconvertibleErrorCode());
1115
1116 while (IndicesStr != "") {
1117 StringRef firstIndexStr;
1118 std::tie(args&: firstIndexStr, args&: IndicesStr) = IndicesStr.split(Separator: '|');
1119
1120 unsigned int index;
1121 if (firstIndexStr.getAsInteger(Radix: 0, Result&: index))
1122 return make_error<StringError>(
1123 Args: formatv(
1124 Fmt: "invalid LowerAllowCheck pass index parameter '{}' ({}) {}",
1125 Vals&: firstIndexStr, Vals&: IndicesStr)
1126 .str(),
1127 Args: inconvertibleErrorCode());
1128
1129 // In the common case (sequentially increasing indices), we will issue
1130 // O(n) resize requests. We assume the underlying data structure has
1131 // O(1) runtime for each added element.
1132 if (index >= Result.cutoffs.size())
1133 Result.cutoffs.resize(new_size: index + 1, x: 0);
1134
1135 Result.cutoffs[index] = cutoff;
1136 }
1137 } else if (ParamName.starts_with(Prefix: "runtime_check")) {
1138 StringRef ValueString;
1139 std::tie(args: std::ignore, args&: ValueString) = ParamName.split(Separator: "=");
1140 int runtime_check;
1141 if (ValueString.getAsInteger(Radix: 0, Result&: runtime_check)) {
1142 return make_error<StringError>(
1143 Args: formatv(Fmt: "invalid LowerAllowCheck pass runtime_check parameter '{}' "
1144 "({})",
1145 Vals&: ValueString, Vals&: Params)
1146 .str(),
1147 Args: inconvertibleErrorCode());
1148 }
1149 Result.runtime_check = runtime_check;
1150 } else {
1151 return make_error<StringError>(
1152 Args: formatv(Fmt: "invalid LowerAllowCheck pass parameter '{}'", Vals&: ParamName)
1153 .str(),
1154 Args: inconvertibleErrorCode());
1155 }
1156 }
1157
1158 return Result;
1159}
1160
1161Expected<MemorySanitizerOptions> parseMSanPassOptions(StringRef Params) {
1162 MemorySanitizerOptions Result;
1163 while (!Params.empty()) {
1164 StringRef ParamName;
1165 std::tie(args&: ParamName, args&: Params) = Params.split(Separator: ';');
1166
1167 if (ParamName == "recover") {
1168 Result.Recover = true;
1169 } else if (ParamName == "kernel") {
1170 Result.Kernel = true;
1171 } else if (ParamName.consume_front(Prefix: "track-origins=")) {
1172 if (ParamName.getAsInteger(Radix: 0, Result&: Result.TrackOrigins))
1173 return make_error<StringError>(
1174 Args: formatv(Fmt: "invalid argument to MemorySanitizer pass track-origins "
1175 "parameter: '{}'",
1176 Vals&: ParamName)
1177 .str(),
1178 Args: inconvertibleErrorCode());
1179 } else if (ParamName == "eager-checks") {
1180 Result.EagerChecks = true;
1181 } else {
1182 return make_error<StringError>(
1183 Args: formatv(Fmt: "invalid MemorySanitizer pass parameter '{}'", Vals&: ParamName)
1184 .str(),
1185 Args: inconvertibleErrorCode());
1186 }
1187 }
1188 return Result;
1189}
1190
1191Expected<AllocTokenOptions> parseAllocTokenPassOptions(StringRef Params) {
1192 AllocTokenOptions Result;
1193 while (!Params.empty()) {
1194 StringRef ParamName;
1195 std::tie(args&: ParamName, args&: Params) = Params.split(Separator: ';');
1196
1197 if (ParamName.consume_front(Prefix: "mode=")) {
1198 if (auto Mode = getAllocTokenModeFromString(Name: ParamName))
1199 Result.Mode = *Mode;
1200 else
1201 return make_error<StringError>(
1202 Args: formatv(Fmt: "invalid argument to AllocToken pass mode "
1203 "parameter: '{}'",
1204 Vals&: ParamName)
1205 .str(),
1206 Args: inconvertibleErrorCode());
1207 } else {
1208 return make_error<StringError>(
1209 Args: formatv(Fmt: "invalid AllocToken pass parameter '{}'", Vals&: ParamName).str(),
1210 Args: inconvertibleErrorCode());
1211 }
1212 }
1213 return Result;
1214}
1215
1216/// Parser of parameters for SimplifyCFG pass.
1217Expected<SimplifyCFGOptions> parseSimplifyCFGOptions(StringRef Params) {
1218 SimplifyCFGOptions Result;
1219 while (!Params.empty()) {
1220 StringRef ParamName;
1221 std::tie(args&: ParamName, args&: Params) = Params.split(Separator: ';');
1222
1223 bool Enable = !ParamName.consume_front(Prefix: "no-");
1224 if (ParamName == "speculate-blocks") {
1225 Result.speculateBlocks(B: Enable);
1226 } else if (ParamName == "simplify-cond-branch") {
1227 Result.setSimplifyCondBranch(Enable);
1228 } else if (ParamName == "forward-switch-cond") {
1229 Result.forwardSwitchCondToPhi(B: Enable);
1230 } else if (ParamName == "switch-range-to-icmp") {
1231 Result.convertSwitchRangeToICmp(B: Enable);
1232 } else if (ParamName == "switch-to-arithmetic") {
1233 Result.convertSwitchToArithmetic(B: Enable);
1234 } else if (ParamName == "switch-to-lookup") {
1235 Result.convertSwitchToLookupTable(B: Enable);
1236 } else if (ParamName == "keep-loops") {
1237 Result.needCanonicalLoops(B: Enable);
1238 } else if (ParamName == "hoist-common-insts") {
1239 Result.hoistCommonInsts(B: Enable);
1240 } else if (ParamName == "hoist-loads-stores-with-cond-faulting") {
1241 Result.hoistLoadsStoresWithCondFaulting(B: Enable);
1242 } else if (ParamName == "sink-common-insts") {
1243 Result.sinkCommonInsts(B: Enable);
1244 } else if (ParamName == "speculate-unpredictables") {
1245 Result.speculateUnpredictables(B: Enable);
1246 } else if (Enable && ParamName.consume_front(Prefix: "bonus-inst-threshold=")) {
1247 APInt BonusInstThreshold;
1248 if (ParamName.getAsInteger(Radix: 0, Result&: BonusInstThreshold))
1249 return make_error<StringError>(
1250 Args: formatv(Fmt: "invalid argument to SimplifyCFG pass bonus-threshold "
1251 "parameter: '{}'",
1252 Vals&: ParamName)
1253 .str(),
1254 Args: inconvertibleErrorCode());
1255 Result.bonusInstThreshold(I: BonusInstThreshold.getSExtValue());
1256 } else {
1257 return make_error<StringError>(
1258 Args: formatv(Fmt: "invalid SimplifyCFG pass parameter '{}'", Vals&: ParamName).str(),
1259 Args: inconvertibleErrorCode());
1260 }
1261 }
1262 return Result;
1263}
1264
1265Expected<InstCombineOptions> parseInstCombineOptions(StringRef Params) {
1266 InstCombineOptions Result;
1267 // When specifying "instcombine" in -passes enable fix-point verification by
1268 // default, as this is what most tests should use.
1269 Result.setVerifyFixpoint(true);
1270 while (!Params.empty()) {
1271 StringRef ParamName;
1272 std::tie(args&: ParamName, args&: Params) = Params.split(Separator: ';');
1273
1274 bool Enable = !ParamName.consume_front(Prefix: "no-");
1275 if (ParamName == "verify-fixpoint") {
1276 Result.setVerifyFixpoint(Enable);
1277 } else if (Enable && ParamName.consume_front(Prefix: "max-iterations=")) {
1278 APInt MaxIterations;
1279 if (ParamName.getAsInteger(Radix: 0, Result&: MaxIterations))
1280 return make_error<StringError>(
1281 Args: formatv(Fmt: "invalid argument to InstCombine pass max-iterations "
1282 "parameter: '{}'",
1283 Vals&: ParamName)
1284 .str(),
1285 Args: inconvertibleErrorCode());
1286 Result.setMaxIterations((unsigned)MaxIterations.getZExtValue());
1287 } else {
1288 return make_error<StringError>(
1289 Args: formatv(Fmt: "invalid InstCombine pass parameter '{}'", Vals&: ParamName).str(),
1290 Args: inconvertibleErrorCode());
1291 }
1292 }
1293 return Result;
1294}
1295
1296/// Parser of parameters for LoopVectorize pass.
1297Expected<LoopVectorizeOptions> parseLoopVectorizeOptions(StringRef Params) {
1298 LoopVectorizeOptions Opts;
1299 while (!Params.empty()) {
1300 StringRef ParamName;
1301 std::tie(args&: ParamName, args&: Params) = Params.split(Separator: ';');
1302
1303 bool Enable = !ParamName.consume_front(Prefix: "no-");
1304 if (ParamName == "interleave-forced-only") {
1305 Opts.setInterleaveOnlyWhenForced(Enable);
1306 } else if (ParamName == "vectorize-forced-only") {
1307 Opts.setVectorizeOnlyWhenForced(Enable);
1308 } else {
1309 return make_error<StringError>(
1310 Args: formatv(Fmt: "invalid LoopVectorize parameter '{}'", Vals&: ParamName).str(),
1311 Args: inconvertibleErrorCode());
1312 }
1313 }
1314 return Opts;
1315}
1316
1317Expected<std::pair<bool, bool>> parseLoopUnswitchOptions(StringRef Params) {
1318 std::pair<bool, bool> Result = {false, true};
1319 while (!Params.empty()) {
1320 StringRef ParamName;
1321 std::tie(args&: ParamName, args&: Params) = Params.split(Separator: ';');
1322
1323 bool Enable = !ParamName.consume_front(Prefix: "no-");
1324 if (ParamName == "nontrivial") {
1325 Result.first = Enable;
1326 } else if (ParamName == "trivial") {
1327 Result.second = Enable;
1328 } else {
1329 return make_error<StringError>(
1330 Args: formatv(Fmt: "invalid LoopUnswitch pass parameter '{}'", Vals&: ParamName).str(),
1331 Args: inconvertibleErrorCode());
1332 }
1333 }
1334 return Result;
1335}
1336
1337Expected<LICMOptions> parseLICMOptions(StringRef Params) {
1338 LICMOptions Result;
1339 while (!Params.empty()) {
1340 StringRef ParamName;
1341 std::tie(args&: ParamName, args&: Params) = Params.split(Separator: ';');
1342
1343 bool Enable = !ParamName.consume_front(Prefix: "no-");
1344 if (ParamName == "allowspeculation") {
1345 Result.AllowSpeculation = Enable;
1346 } else {
1347 return make_error<StringError>(
1348 Args: formatv(Fmt: "invalid LICM pass parameter '{}'", Vals&: ParamName).str(),
1349 Args: inconvertibleErrorCode());
1350 }
1351 }
1352 return Result;
1353}
1354
1355struct LoopRotateOptions {
1356 bool EnableHeaderDuplication = true;
1357 bool PrepareForLTO = false;
1358 bool CheckExitCount = false;
1359};
1360
1361Expected<LoopRotateOptions> parseLoopRotateOptions(StringRef Params) {
1362 LoopRotateOptions Result;
1363 while (!Params.empty()) {
1364 StringRef ParamName;
1365 std::tie(args&: ParamName, args&: Params) = Params.split(Separator: ';');
1366
1367 bool Enable = !ParamName.consume_front(Prefix: "no-");
1368 if (ParamName == "header-duplication") {
1369 Result.EnableHeaderDuplication = Enable;
1370 } else if (ParamName == "prepare-for-lto") {
1371 Result.PrepareForLTO = Enable;
1372 } else if (ParamName == "check-exit-count") {
1373 Result.CheckExitCount = Enable;
1374 } else {
1375 return make_error<StringError>(
1376 Args: formatv(Fmt: "invalid LoopRotate pass parameter '{}'", Vals&: ParamName).str(),
1377 Args: inconvertibleErrorCode());
1378 }
1379 }
1380 return Result;
1381}
1382
1383Expected<bool> parseMergedLoadStoreMotionOptions(StringRef Params) {
1384 bool Result = false;
1385 while (!Params.empty()) {
1386 StringRef ParamName;
1387 std::tie(args&: ParamName, args&: Params) = Params.split(Separator: ';');
1388
1389 bool Enable = !ParamName.consume_front(Prefix: "no-");
1390 if (ParamName == "split-footer-bb") {
1391 Result = Enable;
1392 } else {
1393 return make_error<StringError>(
1394 Args: formatv(Fmt: "invalid MergedLoadStoreMotion pass parameter '{}'",
1395 Vals&: ParamName)
1396 .str(),
1397 Args: inconvertibleErrorCode());
1398 }
1399 }
1400 return Result;
1401}
1402
1403Expected<GVNOptions> parseGVNOptions(StringRef Params) {
1404 GVNOptions Result;
1405 while (!Params.empty()) {
1406 StringRef ParamName;
1407 std::tie(args&: ParamName, args&: Params) = Params.split(Separator: ';');
1408
1409 bool Enable = !ParamName.consume_front(Prefix: "no-");
1410 if (ParamName == "scalar-pre") {
1411 Result.setScalarPRE(Enable);
1412 } else if (ParamName == "load-pre") {
1413 Result.setLoadPRE(Enable);
1414 } else if (ParamName == "split-backedge-load-pre") {
1415 Result.setLoadPRESplitBackedge(Enable);
1416 } else if (ParamName == "memdep") {
1417 // MemDep and MemorySSA are mutually exclusive.
1418 Result.setMemDep(Enable);
1419 Result.setMemorySSA(!Enable);
1420 } else if (ParamName == "memoryssa") {
1421 // MemDep and MemorySSA are mutually exclusive.
1422 Result.setMemorySSA(Enable);
1423 Result.setMemDep(!Enable);
1424 } else {
1425 return make_error<StringError>(
1426 Args: formatv(Fmt: "invalid GVN pass parameter '{}'", Vals&: ParamName).str(),
1427 Args: inconvertibleErrorCode());
1428 }
1429 }
1430 return Result;
1431}
1432
1433Expected<IPSCCPOptions> parseIPSCCPOptions(StringRef Params) {
1434 IPSCCPOptions Result;
1435 while (!Params.empty()) {
1436 StringRef ParamName;
1437 std::tie(args&: ParamName, args&: Params) = Params.split(Separator: ';');
1438
1439 bool Enable = !ParamName.consume_front(Prefix: "no-");
1440 if (ParamName == "func-spec")
1441 Result.setFuncSpec(Enable);
1442 else
1443 return make_error<StringError>(
1444 Args: formatv(Fmt: "invalid IPSCCP pass parameter '{}'", Vals&: ParamName).str(),
1445 Args: inconvertibleErrorCode());
1446 }
1447 return Result;
1448}
1449
1450Expected<ScalarizerPassOptions> parseScalarizerOptions(StringRef Params) {
1451 ScalarizerPassOptions Result;
1452 while (!Params.empty()) {
1453 StringRef ParamName;
1454 std::tie(args&: ParamName, args&: Params) = Params.split(Separator: ';');
1455
1456 if (ParamName.consume_front(Prefix: "min-bits=")) {
1457 if (ParamName.getAsInteger(Radix: 0, Result&: Result.ScalarizeMinBits)) {
1458 return make_error<StringError>(
1459 Args: formatv(Fmt: "invalid argument to Scalarizer pass min-bits "
1460 "parameter: '{}'",
1461 Vals&: ParamName)
1462 .str(),
1463 Args: inconvertibleErrorCode());
1464 }
1465
1466 continue;
1467 }
1468
1469 bool Enable = !ParamName.consume_front(Prefix: "no-");
1470 if (ParamName == "load-store")
1471 Result.ScalarizeLoadStore = Enable;
1472 else if (ParamName == "variable-insert-extract")
1473 Result.ScalarizeVariableInsertExtract = Enable;
1474 else {
1475 return make_error<StringError>(
1476 Args: formatv(Fmt: "invalid Scalarizer pass parameter '{}'", Vals&: ParamName).str(),
1477 Args: inconvertibleErrorCode());
1478 }
1479 }
1480
1481 return Result;
1482}
1483
1484Expected<SROAOptions> parseSROAOptions(StringRef Params) {
1485 SROAOptions Result(SROAOptions::ModifyCFG);
1486 bool SawCFGOption = false;
1487 while (!Params.empty()) {
1488 StringRef ParamName;
1489 std::tie(args&: ParamName, args&: Params) = Params.split(Separator: ';');
1490
1491 if (ParamName == "modify-cfg") {
1492 if (SawCFGOption)
1493 return make_error<StringError>(Args: "multiple SROA CFG options specified",
1494 Args: inconvertibleErrorCode());
1495 Result.CFG = SROAOptions::ModifyCFG;
1496 SawCFGOption = true;
1497 } else if (ParamName == "preserve-cfg") {
1498 if (SawCFGOption)
1499 return make_error<StringError>(Args: "multiple SROA CFG options specified",
1500 Args: inconvertibleErrorCode());
1501 Result.CFG = SROAOptions::PreserveCFG;
1502 SawCFGOption = true;
1503 } else if (ParamName == "aggregate-to-vector") {
1504 Result.AggregateToVector = true;
1505 } else {
1506 return make_error<StringError>(
1507 Args: formatv(Fmt: "invalid SROA pass parameter '{}' (expected preserve-cfg, "
1508 "modify-cfg, or aggregate-to-vector)",
1509 Vals&: ParamName)
1510 .str(),
1511 Args: inconvertibleErrorCode());
1512 }
1513 }
1514 return Result;
1515}
1516
1517Expected<StackLifetime::LivenessType>
1518parseStackLifetimeOptions(StringRef Params) {
1519 StackLifetime::LivenessType Result = StackLifetime::LivenessType::May;
1520 while (!Params.empty()) {
1521 StringRef ParamName;
1522 std::tie(args&: ParamName, args&: Params) = Params.split(Separator: ';');
1523
1524 if (ParamName == "may") {
1525 Result = StackLifetime::LivenessType::May;
1526 } else if (ParamName == "must") {
1527 Result = StackLifetime::LivenessType::Must;
1528 } else {
1529 return make_error<StringError>(
1530 Args: formatv(Fmt: "invalid StackLifetime parameter '{}'", Vals&: ParamName).str(),
1531 Args: inconvertibleErrorCode());
1532 }
1533 }
1534 return Result;
1535}
1536
1537Expected<bool> parseDependenceAnalysisPrinterOptions(StringRef Params) {
1538 return PassBuilder::parseSinglePassOption(Params, OptionName: "normalized-results",
1539 PassName: "DependenceAnalysisPrinter");
1540}
1541
1542Expected<bool> parseSeparateConstOffsetFromGEPPassOptions(StringRef Params) {
1543 return PassBuilder::parseSinglePassOption(Params, OptionName: "lower-gep",
1544 PassName: "SeparateConstOffsetFromGEP");
1545}
1546
1547Expected<bool> parseStructurizeCFGPassOptions(StringRef Params) {
1548 return PassBuilder::parseSinglePassOption(Params, OptionName: "skip-uniform-regions",
1549 PassName: "StructurizeCFG");
1550}
1551
1552Expected<OptimizationLevel>
1553parseFunctionSimplificationPipelineOptions(StringRef Params) {
1554 std::optional<OptimizationLevel> L = parseOptLevel(S: Params);
1555 if (!L || *L == OptimizationLevel::O0) {
1556 return make_error<StringError>(
1557 Args: formatv(Fmt: "invalid function-simplification parameter '{}'", Vals&: Params).str(),
1558 Args: inconvertibleErrorCode());
1559 };
1560 return *L;
1561}
1562
1563Expected<bool> parseMemorySSAPrinterPassOptions(StringRef Params) {
1564 return PassBuilder::parseSinglePassOption(Params, OptionName: "no-ensure-optimized-uses",
1565 PassName: "MemorySSAPrinterPass");
1566}
1567
1568Expected<bool> parseSpeculativeExecutionPassOptions(StringRef Params) {
1569 return PassBuilder::parseSinglePassOption(Params, OptionName: "only-if-divergent-target",
1570 PassName: "SpeculativeExecutionPass");
1571}
1572
1573Expected<std::string> parseMemProfUsePassOptions(StringRef Params) {
1574 std::string Result;
1575 while (!Params.empty()) {
1576 StringRef ParamName;
1577 std::tie(args&: ParamName, args&: Params) = Params.split(Separator: ';');
1578
1579 if (ParamName.consume_front(Prefix: "profile-filename=")) {
1580 Result = ParamName.str();
1581 } else {
1582 return make_error<StringError>(
1583 Args: formatv(Fmt: "invalid MemProfUse pass parameter '{}'", Vals&: ParamName).str(),
1584 Args: inconvertibleErrorCode());
1585 }
1586 }
1587 return Result;
1588}
1589
1590Expected<StructuralHashOptions>
1591parseStructuralHashPrinterPassOptions(StringRef Params) {
1592 if (Params.empty())
1593 return StructuralHashOptions::None;
1594 if (Params == "detailed")
1595 return StructuralHashOptions::Detailed;
1596 if (Params == "call-target-ignored")
1597 return StructuralHashOptions::CallTargetIgnored;
1598 return make_error<StringError>(
1599 Args: formatv(Fmt: "invalid structural hash printer parameter '{}'", Vals&: Params).str(),
1600 Args: inconvertibleErrorCode());
1601}
1602
1603Expected<GlobalMergeOptions> parseGlobalMergeOptions(StringRef Params) {
1604 GlobalMergeOptions Result;
1605 while (!Params.empty()) {
1606 StringRef ParamName;
1607 std::tie(args&: ParamName, args&: Params) = Params.split(Separator: ';');
1608
1609 bool Enable = !ParamName.consume_front(Prefix: "no-");
1610 if (ParamName == "group-by-use")
1611 Result.GroupByUse = Enable;
1612 else if (ParamName == "ignore-single-use")
1613 Result.IgnoreSingleUse = Enable;
1614 else if (ParamName == "merge-const")
1615 Result.MergeConstantGlobals = Enable;
1616 else if (ParamName == "merge-const-aggressive")
1617 Result.MergeConstAggressive = Enable;
1618 else if (ParamName == "merge-external")
1619 Result.MergeExternal = Enable;
1620 else if (ParamName.consume_front(Prefix: "max-offset=")) {
1621 if (ParamName.getAsInteger(Radix: 0, Result&: Result.MaxOffset))
1622 return make_error<StringError>(
1623 Args: formatv(Fmt: "invalid GlobalMergePass parameter '{}'", Vals&: ParamName).str(),
1624 Args: inconvertibleErrorCode());
1625 } else {
1626 return make_error<StringError>(
1627 Args: formatv(Fmt: "invalid global-merge pass parameter '{}'", Vals&: Params).str(),
1628 Args: inconvertibleErrorCode());
1629 }
1630 }
1631 return Result;
1632}
1633
1634Expected<SmallVector<std::string, 0>> parseInternalizeGVs(StringRef Params) {
1635 SmallVector<std::string, 1> PreservedGVs;
1636 while (!Params.empty()) {
1637 StringRef ParamName;
1638 std::tie(args&: ParamName, args&: Params) = Params.split(Separator: ';');
1639
1640 if (ParamName.consume_front(Prefix: "preserve-gv=")) {
1641 PreservedGVs.push_back(Elt: ParamName.str());
1642 } else {
1643 return make_error<StringError>(
1644 Args: formatv(Fmt: "invalid Internalize pass parameter '{}'", Vals&: ParamName).str(),
1645 Args: inconvertibleErrorCode());
1646 }
1647 }
1648
1649 return Expected<SmallVector<std::string, 0>>(std::move(PreservedGVs));
1650}
1651
1652Expected<RegAllocFastPass::Options>
1653parseRegAllocFastPassOptions(PassBuilder &PB, StringRef Params) {
1654 RegAllocFastPass::Options Opts;
1655 while (!Params.empty()) {
1656 StringRef ParamName;
1657 std::tie(args&: ParamName, args&: Params) = Params.split(Separator: ';');
1658
1659 if (ParamName.consume_front(Prefix: "filter=")) {
1660 std::optional<RegAllocFilterFunc> Filter =
1661 PB.parseRegAllocFilter(RegAllocFilterName: ParamName);
1662 if (!Filter) {
1663 return make_error<StringError>(
1664 Args: formatv(Fmt: "invalid regallocfast register filter '{}'", Vals&: ParamName)
1665 .str(),
1666 Args: inconvertibleErrorCode());
1667 }
1668 Opts.Filter = *Filter;
1669 Opts.FilterName = ParamName;
1670 continue;
1671 }
1672
1673 if (ParamName == "no-clear-vregs") {
1674 Opts.ClearVRegs = false;
1675 continue;
1676 }
1677
1678 return make_error<StringError>(
1679 Args: formatv(Fmt: "invalid regallocfast pass parameter '{}'", Vals&: ParamName).str(),
1680 Args: inconvertibleErrorCode());
1681 }
1682 return Opts;
1683}
1684
1685Expected<BoundsCheckingPass::Options>
1686parseBoundsCheckingOptions(StringRef Params) {
1687 BoundsCheckingPass::Options Options;
1688 while (!Params.empty()) {
1689 StringRef ParamName;
1690 std::tie(args&: ParamName, args&: Params) = Params.split(Separator: ';');
1691 if (ParamName == "trap") {
1692 Options.Rt = std::nullopt;
1693 } else if (ParamName == "rt") {
1694 Options.Rt = {
1695 /*MinRuntime=*/false,
1696 /*MayReturn=*/true,
1697 /*HandlerPreserveAllRegs=*/false,
1698 };
1699 } else if (ParamName == "rt-abort") {
1700 Options.Rt = {
1701 /*MinRuntime=*/false,
1702 /*MayReturn=*/false,
1703 /*HandlerPreserveAllRegs=*/false,
1704 };
1705 } else if (ParamName == "min-rt") {
1706 Options.Rt = {
1707 /*MinRuntime=*/true,
1708 /*MayReturn=*/true,
1709 /*HandlerPreserveAllRegs=*/false,
1710 };
1711 } else if (ParamName == "min-rt-abort") {
1712 Options.Rt = {
1713 /*MinRuntime=*/true,
1714 /*MayReturn=*/false,
1715 /*HandlerPreserveAllRegs=*/false,
1716 };
1717 } else if (ParamName == "merge") {
1718 Options.Merge = true;
1719 } else if (ParamName == "handler-preserve-all-regs") {
1720 if (Options.Rt)
1721 Options.Rt->HandlerPreserveAllRegs = true;
1722 } else {
1723 StringRef ParamEQ;
1724 StringRef Val;
1725 std::tie(args&: ParamEQ, args&: Val) = ParamName.split(Separator: '=');
1726 int8_t Id;
1727 if (ParamEQ == "guard" && !Val.getAsInteger(Radix: 0, Result&: Id)) {
1728 Options.GuardKind = Id;
1729 } else {
1730 return make_error<StringError>(
1731 Args: formatv(Fmt: "invalid BoundsChecking pass parameter '{}'", Vals&: ParamName)
1732 .str(),
1733 Args: inconvertibleErrorCode());
1734 }
1735 }
1736 }
1737 return Options;
1738}
1739
1740Expected<CodeGenOptLevel> parseExpandIRInstsOptions(StringRef Param) {
1741 if (Param.empty())
1742 return CodeGenOptLevel::None;
1743
1744 // Parse a CodeGenOptLevel, e.g. "O1", "O2", "O3".
1745 auto [Prefix, Digit] = Param.split(Separator: 'O');
1746
1747 uint8_t N;
1748 if (!Prefix.empty() || Digit.getAsInteger(Radix: 10, Result&: N))
1749 return createStringError(Fmt: "invalid expand-ir-insts pass parameter '%s'",
1750 Vals: Param.str().c_str());
1751
1752 std::optional<CodeGenOptLevel> Level = CodeGenOpt::getLevel(OL: N);
1753 if (!Level.has_value())
1754 return createStringError(
1755 Fmt: "invalid optimization level for expand-ir-insts pass: %s",
1756 Vals: Digit.str().c_str());
1757
1758 return *Level;
1759}
1760
1761Expected<RAGreedyPass::Options>
1762parseRegAllocGreedyFilterFunc(PassBuilder &PB, StringRef Params) {
1763 if (Params.empty() || Params == "all")
1764 return RAGreedyPass::Options();
1765
1766 std::optional<RegAllocFilterFunc> Filter = PB.parseRegAllocFilter(RegAllocFilterName: Params);
1767 if (Filter)
1768 return RAGreedyPass::Options{*Filter, Params};
1769
1770 return make_error<StringError>(
1771 Args: formatv(Fmt: "invalid regallocgreedy register filter '{}'", Vals&: Params).str(),
1772 Args: inconvertibleErrorCode());
1773}
1774
1775Expected<bool> parseMachineSinkingPassOptions(StringRef Params) {
1776 return PassBuilder::parseSinglePassOption(Params, OptionName: "enable-sink-fold",
1777 PassName: "MachineSinkingPass");
1778}
1779
1780Expected<bool> parseMachineBlockPlacementPassOptions(StringRef Params) {
1781 bool AllowTailMerge = true;
1782 if (!Params.empty()) {
1783 AllowTailMerge = !Params.consume_front(Prefix: "no-");
1784 if (Params != "tail-merge")
1785 return make_error<StringError>(
1786 Args: formatv(Fmt: "invalid MachineBlockPlacementPass parameter '{}'", Vals&: Params)
1787 .str(),
1788 Args: inconvertibleErrorCode());
1789 }
1790 return AllowTailMerge;
1791}
1792
1793Expected<bool> parseVirtRegRewriterPassOptions(StringRef Params) {
1794 bool ClearVirtRegs = true;
1795 if (!Params.empty()) {
1796 ClearVirtRegs = !Params.consume_front(Prefix: "no-");
1797 if (Params != "clear-vregs")
1798 return make_error<StringError>(
1799 Args: formatv(Fmt: "invalid VirtRegRewriter pass parameter '{}'", Vals&: Params).str(),
1800 Args: inconvertibleErrorCode());
1801 }
1802 return ClearVirtRegs;
1803}
1804
1805struct FatLTOOptions {
1806 OptimizationLevel OptLevel;
1807 bool ThinLTO = false;
1808 bool EmitSummary = false;
1809};
1810
1811Expected<FatLTOOptions> parseFatLTOOptions(StringRef Params) {
1812 FatLTOOptions Result;
1813 bool HaveOptLevel = false;
1814 while (!Params.empty()) {
1815 StringRef ParamName;
1816 std::tie(args&: ParamName, args&: Params) = Params.split(Separator: ';');
1817
1818 if (ParamName == "thinlto") {
1819 Result.ThinLTO = true;
1820 } else if (ParamName == "emit-summary") {
1821 Result.EmitSummary = true;
1822 } else if (std::optional<OptimizationLevel> OptLevel =
1823 parseOptLevel(S: ParamName)) {
1824 Result.OptLevel = *OptLevel;
1825 HaveOptLevel = true;
1826 } else {
1827 return make_error<StringError>(
1828 Args: formatv(Fmt: "invalid fatlto-pre-link pass parameter '{}'", Vals&: ParamName)
1829 .str(),
1830 Args: inconvertibleErrorCode());
1831 }
1832 }
1833 if (!HaveOptLevel)
1834 return make_error<StringError>(
1835 Args: "missing optimization level for fatlto-pre-link pipeline",
1836 Args: inconvertibleErrorCode());
1837 return Result;
1838}
1839
1840} // namespace
1841
1842/// Tests whether registered callbacks will accept a given pass name.
1843///
1844/// When parsing a pipeline text, the type of the outermost pipeline may be
1845/// omitted, in which case the type is automatically determined from the first
1846/// pass name in the text. This may be a name that is handled through one of the
1847/// callbacks. We check this through the oridinary parsing callbacks by setting
1848/// up a dummy PassManager in order to not force the client to also handle this
1849/// type of query.
1850template <typename PassManagerT, typename CallbacksT>
1851static bool callbacksAcceptPassName(StringRef Name, CallbacksT &Callbacks) {
1852 if (!Callbacks.empty()) {
1853 PassManagerT DummyPM;
1854 for (auto &CB : Callbacks)
1855 if (CB(Name, DummyPM, {}))
1856 return true;
1857 }
1858 return false;
1859}
1860
1861template <typename CallbacksT>
1862static bool isModulePassName(StringRef Name, CallbacksT &Callbacks) {
1863 StringRef NameNoBracket = Name.take_until(F: [](char C) { return C == '<'; });
1864
1865 // Explicitly handle pass manager names.
1866 if (Name == "module")
1867 return true;
1868 if (Name == "cgscc")
1869 return true;
1870 if (NameNoBracket == "function")
1871 return true;
1872 if (Name == "coro-cond")
1873 return true;
1874
1875#define MODULE_PASS(NAME, CREATE_PASS) \
1876 if (Name == NAME) \
1877 return true;
1878#define MODULE_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \
1879 if (PassBuilder::checkParametrizedPassName(Name, NAME)) \
1880 return true;
1881#define MODULE_ANALYSIS(NAME, CREATE_PASS) \
1882 if (Name == "require<" NAME ">" || Name == "invalidate<" NAME ">") \
1883 return true;
1884#include "PassRegistry.def"
1885
1886 return callbacksAcceptPassName<ModulePassManager>(Name, Callbacks);
1887}
1888
1889template <typename CallbacksT>
1890static bool isCGSCCPassName(StringRef Name, CallbacksT &Callbacks) {
1891 // Explicitly handle pass manager names.
1892 StringRef NameNoBracket = Name.take_until(F: [](char C) { return C == '<'; });
1893 if (Name == "cgscc")
1894 return true;
1895 if (NameNoBracket == "function")
1896 return true;
1897
1898 // Explicitly handle custom-parsed pass names.
1899 if (parseDevirtPassName(Name))
1900 return true;
1901
1902#define CGSCC_PASS(NAME, CREATE_PASS) \
1903 if (Name == NAME) \
1904 return true;
1905#define CGSCC_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \
1906 if (PassBuilder::checkParametrizedPassName(Name, NAME)) \
1907 return true;
1908#define CGSCC_ANALYSIS(NAME, CREATE_PASS) \
1909 if (Name == "require<" NAME ">" || Name == "invalidate<" NAME ">") \
1910 return true;
1911#include "PassRegistry.def"
1912
1913 return callbacksAcceptPassName<CGSCCPassManager>(Name, Callbacks);
1914}
1915
1916template <typename CallbacksT>
1917static bool isFunctionPassName(StringRef Name, CallbacksT &Callbacks) {
1918 // Explicitly handle pass manager names.
1919 StringRef NameNoBracket = Name.take_until(F: [](char C) { return C == '<'; });
1920 if (NameNoBracket == "function")
1921 return true;
1922 if (Name == "loop" || Name == "loop-mssa" || Name == "machine-function")
1923 return true;
1924
1925#define FUNCTION_PASS(NAME, CREATE_PASS) \
1926 if (Name == NAME) \
1927 return true;
1928#define FUNCTION_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \
1929 if (PassBuilder::checkParametrizedPassName(Name, NAME)) \
1930 return true;
1931#define FUNCTION_ANALYSIS(NAME, CREATE_PASS) \
1932 if (Name == "require<" NAME ">" || Name == "invalidate<" NAME ">") \
1933 return true;
1934#include "PassRegistry.def"
1935
1936 return callbacksAcceptPassName<FunctionPassManager>(Name, Callbacks);
1937}
1938
1939template <typename CallbacksT>
1940static bool isMachineFunctionPassName(StringRef Name, CallbacksT &Callbacks) {
1941 // Explicitly handle pass manager names.
1942 if (Name == "machine-function")
1943 return true;
1944
1945#define MACHINE_FUNCTION_PASS(NAME, CREATE_PASS) \
1946 if (Name == NAME) \
1947 return true;
1948#define MACHINE_FUNCTION_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, \
1949 PARAMS) \
1950 if (PassBuilder::checkParametrizedPassName(Name, NAME)) \
1951 return true;
1952
1953#define MACHINE_FUNCTION_ANALYSIS(NAME, CREATE_PASS) \
1954 if (Name == "require<" NAME ">" || Name == "invalidate<" NAME ">") \
1955 return true;
1956
1957#include "llvm/Passes/MachinePassRegistry.def"
1958
1959 return callbacksAcceptPassName<MachineFunctionPassManager>(Name, Callbacks);
1960}
1961
1962template <typename CallbacksT>
1963static bool isLoopNestPassName(StringRef Name, CallbacksT &Callbacks,
1964 bool &UseMemorySSA) {
1965 UseMemorySSA = false;
1966
1967 if (PassBuilder::checkParametrizedPassName(Name, PassName: "lnicm")) {
1968 UseMemorySSA = true;
1969 return true;
1970 }
1971
1972#define LOOPNEST_PASS(NAME, CREATE_PASS) \
1973 if (Name == NAME) \
1974 return true;
1975#include "PassRegistry.def"
1976
1977 return callbacksAcceptPassName<LoopPassManager>(Name, Callbacks);
1978}
1979
1980template <typename CallbacksT>
1981static bool isLoopPassName(StringRef Name, CallbacksT &Callbacks,
1982 bool &UseMemorySSA) {
1983 UseMemorySSA = false;
1984
1985 if (PassBuilder::checkParametrizedPassName(Name, PassName: "licm")) {
1986 UseMemorySSA = true;
1987 return true;
1988 }
1989
1990#define LOOP_PASS(NAME, CREATE_PASS) \
1991 if (Name == NAME) \
1992 return true;
1993#define LOOP_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \
1994 if (PassBuilder::checkParametrizedPassName(Name, NAME)) \
1995 return true;
1996#define LOOP_ANALYSIS(NAME, CREATE_PASS) \
1997 if (Name == "require<" NAME ">" || Name == "invalidate<" NAME ">") \
1998 return true;
1999#include "PassRegistry.def"
2000
2001 return callbacksAcceptPassName<LoopPassManager>(Name, Callbacks);
2002}
2003
2004std::optional<std::vector<PassBuilder::PipelineElement>>
2005PassBuilder::parsePipelineText(StringRef Text) {
2006 std::vector<PipelineElement> ResultPipeline;
2007
2008 SmallVector<std::vector<PipelineElement> *, 4> PipelineStack = {
2009 &ResultPipeline};
2010 for (;;) {
2011 std::vector<PipelineElement> &Pipeline = *PipelineStack.back();
2012 size_t Pos = Text.find_first_of(Chars: ",()");
2013 Pipeline.push_back(x: {.Name: Text.substr(Start: 0, N: Pos), .InnerPipeline: {}});
2014
2015 // If we have a single terminating name, we're done.
2016 if (Pos == Text.npos)
2017 break;
2018
2019 char Sep = Text[Pos];
2020 Text = Text.substr(Start: Pos + 1);
2021 if (Sep == ',')
2022 // Just a name ending in a comma, continue.
2023 continue;
2024
2025 if (Sep == '(') {
2026 // Push the inner pipeline onto the stack to continue processing.
2027 PipelineStack.push_back(Elt: &Pipeline.back().InnerPipeline);
2028 continue;
2029 }
2030
2031 assert(Sep == ')' && "Bogus separator!");
2032 // When handling the close parenthesis, we greedily consume them to avoid
2033 // empty strings in the pipeline.
2034 do {
2035 // If we try to pop the outer pipeline we have unbalanced parentheses.
2036 if (PipelineStack.size() == 1)
2037 return std::nullopt;
2038
2039 PipelineStack.pop_back();
2040 } while (Text.consume_front(Prefix: ")"));
2041
2042 // Check if we've finished parsing.
2043 if (Text.empty())
2044 break;
2045
2046 // Otherwise, the end of an inner pipeline always has to be followed by
2047 // a comma, and then we can continue.
2048 if (!Text.consume_front(Prefix: ","))
2049 return std::nullopt;
2050 }
2051
2052 if (PipelineStack.size() > 1)
2053 // Unbalanced paretheses.
2054 return std::nullopt;
2055
2056 assert(PipelineStack.back() == &ResultPipeline &&
2057 "Wrong pipeline at the bottom of the stack!");
2058 return {std::move(ResultPipeline)};
2059}
2060
2061static void setupOptionsForPipelineAlias(PipelineTuningOptions &PTO,
2062 OptimizationLevel L) {
2063 PTO.LoopVectorization = L >= OptimizationLevel::O2;
2064 PTO.SLPVectorization = L >= OptimizationLevel::O2;
2065}
2066
2067Error PassBuilder::parseModulePass(ModulePassManager &MPM,
2068 const PipelineElement &E) {
2069 auto &Name = E.Name;
2070 auto &InnerPipeline = E.InnerPipeline;
2071
2072 // First handle complex passes like the pass managers which carry pipelines.
2073 if (!InnerPipeline.empty()) {
2074 if (Name == "module") {
2075 ModulePassManager NestedMPM;
2076 if (auto Err = parseModulePassPipeline(MPM&: NestedMPM, Pipeline: InnerPipeline))
2077 return Err;
2078 MPM.addPass(Pass: std::move(NestedMPM));
2079 return Error::success();
2080 }
2081 if (Name == "coro-cond") {
2082 ModulePassManager NestedMPM;
2083 if (auto Err = parseModulePassPipeline(MPM&: NestedMPM, Pipeline: InnerPipeline))
2084 return Err;
2085 MPM.addPass(Pass: CoroConditionalWrapper(std::move(NestedMPM)));
2086 return Error::success();
2087 }
2088 if (Name == "cgscc") {
2089 CGSCCPassManager CGPM;
2090 if (auto Err = parseCGSCCPassPipeline(CGPM, Pipeline: InnerPipeline))
2091 return Err;
2092 MPM.addPass(Pass: createModuleToPostOrderCGSCCPassAdaptor(Pass: std::move(CGPM)));
2093 return Error::success();
2094 }
2095 if (auto Params = parseFunctionPipelineName(Name)) {
2096 if (Params->second)
2097 return make_error<StringError>(
2098 Args: "cannot have a no-rerun module to function adaptor",
2099 Args: inconvertibleErrorCode());
2100 FunctionPassManager FPM;
2101 if (auto Err = parseFunctionPassPipeline(FPM, Pipeline: InnerPipeline))
2102 return Err;
2103 MPM.addPass(
2104 Pass: createModuleToFunctionPassAdaptor(Pass: std::move(FPM), EagerlyInvalidate: Params->first));
2105 return Error::success();
2106 }
2107
2108 for (auto &C : ModulePipelineParsingCallbacks)
2109 if (C(Name, MPM, InnerPipeline))
2110 return Error::success();
2111
2112 // Normal passes can't have pipelines.
2113 return make_error<StringError>(
2114 Args: formatv(Fmt: "invalid use of '{}' pass as module pipeline", Vals: Name).str(),
2115 Args: inconvertibleErrorCode());
2116 ;
2117 }
2118
2119 // Finally expand the basic registered passes from the .inc file.
2120#define MODULE_PASS(NAME, CREATE_PASS) \
2121 if (Name == NAME) { \
2122 MPM.addPass(CREATE_PASS); \
2123 return Error::success(); \
2124 }
2125#define MODULE_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \
2126 if (checkParametrizedPassName(Name, NAME)) { \
2127 auto Params = parsePassParameters(PARSER, Name, NAME); \
2128 if (!Params) \
2129 return Params.takeError(); \
2130 MPM.addPass(CREATE_PASS(Params.get())); \
2131 return Error::success(); \
2132 }
2133#define MODULE_ANALYSIS(NAME, CREATE_PASS) \
2134 if (Name == "require<" NAME ">") { \
2135 MPM.addPass( \
2136 RequireAnalysisPass< \
2137 std::remove_reference_t<decltype(CREATE_PASS)>, Module>()); \
2138 return Error::success(); \
2139 } \
2140 if (Name == "invalidate<" NAME ">") { \
2141 MPM.addPass(InvalidateAnalysisPass< \
2142 std::remove_reference_t<decltype(CREATE_PASS)>>()); \
2143 return Error::success(); \
2144 }
2145#define CGSCC_PASS(NAME, CREATE_PASS) \
2146 if (Name == NAME) { \
2147 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(CREATE_PASS)); \
2148 return Error::success(); \
2149 }
2150#define CGSCC_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \
2151 if (checkParametrizedPassName(Name, NAME)) { \
2152 auto Params = parsePassParameters(PARSER, Name, NAME); \
2153 if (!Params) \
2154 return Params.takeError(); \
2155 MPM.addPass( \
2156 createModuleToPostOrderCGSCCPassAdaptor(CREATE_PASS(Params.get()))); \
2157 return Error::success(); \
2158 }
2159#define FUNCTION_PASS(NAME, CREATE_PASS) \
2160 if (Name == NAME) { \
2161 if constexpr (std::is_constructible_v< \
2162 std::remove_reference_t<decltype(CREATE_PASS)>, \
2163 const TargetMachine &>) { \
2164 if (!TM) \
2165 return make_error<StringError>( \
2166 formatv("pass '{0}' requires TargetMachine", Name).str(), \
2167 inconvertibleErrorCode()); \
2168 } \
2169 MPM.addPass(createModuleToFunctionPassAdaptor(CREATE_PASS)); \
2170 return Error::success(); \
2171 }
2172#define FUNCTION_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \
2173 if (checkParametrizedPassName(Name, NAME)) { \
2174 auto Params = parsePassParameters(PARSER, Name, NAME); \
2175 if (!Params) \
2176 return Params.takeError(); \
2177 auto CreatePass = CREATE_PASS; \
2178 if constexpr (std::is_constructible_v< \
2179 std::remove_reference_t<decltype(CreatePass( \
2180 Params.get()))>, \
2181 const TargetMachine &, \
2182 std::remove_reference_t<decltype(Params.get())>>) { \
2183 if (!TM) { \
2184 return make_error<StringError>( \
2185 formatv("pass '{0}' requires TargetMachine", Name).str(), \
2186 inconvertibleErrorCode()); \
2187 } \
2188 } \
2189 MPM.addPass(createModuleToFunctionPassAdaptor(CREATE_PASS(Params.get()))); \
2190 return Error::success(); \
2191 }
2192#define LOOPNEST_PASS(NAME, CREATE_PASS) \
2193 if (Name == NAME) { \
2194 MPM.addPass(createModuleToFunctionPassAdaptor( \
2195 createFunctionToLoopPassAdaptor(CREATE_PASS, false))); \
2196 return Error::success(); \
2197 }
2198#define LOOP_PASS(NAME, CREATE_PASS) \
2199 if (Name == NAME) { \
2200 MPM.addPass(createModuleToFunctionPassAdaptor( \
2201 createFunctionToLoopPassAdaptor(CREATE_PASS, false))); \
2202 return Error::success(); \
2203 }
2204#define LOOP_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \
2205 if (checkParametrizedPassName(Name, NAME)) { \
2206 auto Params = parsePassParameters(PARSER, Name, NAME); \
2207 if (!Params) \
2208 return Params.takeError(); \
2209 MPM.addPass(createModuleToFunctionPassAdaptor( \
2210 createFunctionToLoopPassAdaptor(CREATE_PASS(Params.get()), false))); \
2211 return Error::success(); \
2212 }
2213#include "PassRegistry.def"
2214
2215 for (auto &C : ModulePipelineParsingCallbacks)
2216 if (C(Name, MPM, InnerPipeline))
2217 return Error::success();
2218 return make_error<StringError>(
2219 Args: formatv(Fmt: "unknown module pass '{}'", Vals: Name).str(),
2220 Args: inconvertibleErrorCode());
2221}
2222
2223Error PassBuilder::parseCGSCCPass(CGSCCPassManager &CGPM,
2224 const PipelineElement &E) {
2225 auto &Name = E.Name;
2226 auto &InnerPipeline = E.InnerPipeline;
2227
2228 // First handle complex passes like the pass managers which carry pipelines.
2229 if (!InnerPipeline.empty()) {
2230 if (Name == "cgscc") {
2231 CGSCCPassManager NestedCGPM;
2232 if (auto Err = parseCGSCCPassPipeline(CGPM&: NestedCGPM, Pipeline: InnerPipeline))
2233 return Err;
2234 // Add the nested pass manager with the appropriate adaptor.
2235 CGPM.addPass(Pass: std::move(NestedCGPM));
2236 return Error::success();
2237 }
2238 if (auto Params = parseFunctionPipelineName(Name)) {
2239 FunctionPassManager FPM;
2240 if (auto Err = parseFunctionPassPipeline(FPM, Pipeline: InnerPipeline))
2241 return Err;
2242 // Add the nested pass manager with the appropriate adaptor.
2243 CGPM.addPass(Pass: createCGSCCToFunctionPassAdaptor(
2244 Pass: std::move(FPM), EagerlyInvalidate: Params->first, NoRerun: Params->second));
2245 return Error::success();
2246 }
2247 if (auto MaxRepetitions = parseDevirtPassName(Name)) {
2248 CGSCCPassManager NestedCGPM;
2249 if (auto Err = parseCGSCCPassPipeline(CGPM&: NestedCGPM, Pipeline: InnerPipeline))
2250 return Err;
2251 CGPM.addPass(
2252 Pass: createDevirtSCCRepeatedPass(Pass: std::move(NestedCGPM), MaxIterations: *MaxRepetitions));
2253 return Error::success();
2254 }
2255
2256 for (auto &C : CGSCCPipelineParsingCallbacks)
2257 if (C(Name, CGPM, InnerPipeline))
2258 return Error::success();
2259
2260 // Normal passes can't have pipelines.
2261 return make_error<StringError>(
2262 Args: formatv(Fmt: "invalid use of '{}' pass as cgscc pipeline", Vals: Name).str(),
2263 Args: inconvertibleErrorCode());
2264 }
2265
2266// Now expand the basic registered passes from the .inc file.
2267#define CGSCC_PASS(NAME, CREATE_PASS) \
2268 if (Name == NAME) { \
2269 CGPM.addPass(CREATE_PASS); \
2270 return Error::success(); \
2271 }
2272#define CGSCC_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \
2273 if (checkParametrizedPassName(Name, NAME)) { \
2274 auto Params = parsePassParameters(PARSER, Name, NAME); \
2275 if (!Params) \
2276 return Params.takeError(); \
2277 CGPM.addPass(CREATE_PASS(Params.get())); \
2278 return Error::success(); \
2279 }
2280#define CGSCC_ANALYSIS(NAME, CREATE_PASS) \
2281 if (Name == "require<" NAME ">") { \
2282 CGPM.addPass(RequireAnalysisPass< \
2283 std::remove_reference_t<decltype(CREATE_PASS)>, \
2284 LazyCallGraph::SCC, CGSCCAnalysisManager, LazyCallGraph &, \
2285 CGSCCUpdateResult &>()); \
2286 return Error::success(); \
2287 } \
2288 if (Name == "invalidate<" NAME ">") { \
2289 CGPM.addPass(InvalidateAnalysisPass< \
2290 std::remove_reference_t<decltype(CREATE_PASS)>>()); \
2291 return Error::success(); \
2292 }
2293#define FUNCTION_PASS(NAME, CREATE_PASS) \
2294 if (Name == NAME) { \
2295 if constexpr (std::is_constructible_v< \
2296 std::remove_reference_t<decltype(CREATE_PASS)>, \
2297 const TargetMachine &>) { \
2298 if (!TM) \
2299 return make_error<StringError>( \
2300 formatv("pass '{0}' requires TargetMachine", Name).str(), \
2301 inconvertibleErrorCode()); \
2302 } \
2303 CGPM.addPass(createCGSCCToFunctionPassAdaptor(CREATE_PASS)); \
2304 return Error::success(); \
2305 }
2306#define FUNCTION_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \
2307 if (checkParametrizedPassName(Name, NAME)) { \
2308 auto Params = parsePassParameters(PARSER, Name, NAME); \
2309 if (!Params) \
2310 return Params.takeError(); \
2311 auto CreatePass = CREATE_PASS; \
2312 if constexpr (std::is_constructible_v< \
2313 std::remove_reference_t<decltype(CreatePass( \
2314 Params.get()))>, \
2315 const TargetMachine &, \
2316 std::remove_reference_t<decltype(Params.get())>>) { \
2317 if (!TM) { \
2318 return make_error<StringError>( \
2319 formatv("pass '{0}' requires TargetMachine", Name).str(), \
2320 inconvertibleErrorCode()); \
2321 } \
2322 } \
2323 CGPM.addPass(createCGSCCToFunctionPassAdaptor(CREATE_PASS(Params.get()))); \
2324 return Error::success(); \
2325 }
2326#define LOOPNEST_PASS(NAME, CREATE_PASS) \
2327 if (Name == NAME) { \
2328 CGPM.addPass(createCGSCCToFunctionPassAdaptor( \
2329 createFunctionToLoopPassAdaptor(CREATE_PASS, false))); \
2330 return Error::success(); \
2331 }
2332#define LOOP_PASS(NAME, CREATE_PASS) \
2333 if (Name == NAME) { \
2334 CGPM.addPass(createCGSCCToFunctionPassAdaptor( \
2335 createFunctionToLoopPassAdaptor(CREATE_PASS, false))); \
2336 return Error::success(); \
2337 }
2338#define LOOP_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \
2339 if (checkParametrizedPassName(Name, NAME)) { \
2340 auto Params = parsePassParameters(PARSER, Name, NAME); \
2341 if (!Params) \
2342 return Params.takeError(); \
2343 CGPM.addPass(createCGSCCToFunctionPassAdaptor( \
2344 createFunctionToLoopPassAdaptor(CREATE_PASS(Params.get()), false))); \
2345 return Error::success(); \
2346 }
2347#include "PassRegistry.def"
2348
2349 for (auto &C : CGSCCPipelineParsingCallbacks)
2350 if (C(Name, CGPM, InnerPipeline))
2351 return Error::success();
2352 return make_error<StringError>(Args: formatv(Fmt: "unknown cgscc pass '{}'", Vals: Name).str(),
2353 Args: inconvertibleErrorCode());
2354}
2355
2356Error PassBuilder::parseFunctionPass(FunctionPassManager &FPM,
2357 const PipelineElement &E) {
2358 auto &Name = E.Name;
2359 auto &InnerPipeline = E.InnerPipeline;
2360
2361 // First handle complex passes like the pass managers which carry pipelines.
2362 if (!InnerPipeline.empty()) {
2363 if (Name == "function") {
2364 FunctionPassManager NestedFPM;
2365 if (auto Err = parseFunctionPassPipeline(FPM&: NestedFPM, Pipeline: InnerPipeline))
2366 return Err;
2367 // Add the nested pass manager with the appropriate adaptor.
2368 FPM.addPass(Pass: std::move(NestedFPM));
2369 return Error::success();
2370 }
2371 if (Name == "loop" || Name == "loop-mssa") {
2372 LoopPassManager LPM;
2373 if (auto Err = parseLoopPassPipeline(LPM, Pipeline: InnerPipeline))
2374 return Err;
2375 // Add the nested pass manager with the appropriate adaptor.
2376 bool UseMemorySSA = (Name == "loop-mssa");
2377 FPM.addPass(
2378 Pass: createFunctionToLoopPassAdaptor(LPM: std::move(LPM), UseMemorySSA));
2379 return Error::success();
2380 }
2381 if (Name == "machine-function") {
2382 MachineFunctionPassManager MFPM;
2383 if (auto Err = parseMachinePassPipeline(MFPM, Pipeline: InnerPipeline))
2384 return Err;
2385 FPM.addPass(Pass: createFunctionToMachineFunctionPassAdaptor(Pass: std::move(MFPM)));
2386 return Error::success();
2387 }
2388
2389 for (auto &C : FunctionPipelineParsingCallbacks)
2390 if (C(Name, FPM, InnerPipeline))
2391 return Error::success();
2392
2393 // Normal passes can't have pipelines.
2394 return make_error<StringError>(
2395 Args: formatv(Fmt: "invalid use of '{}' pass as function pipeline", Vals: Name).str(),
2396 Args: inconvertibleErrorCode());
2397 }
2398
2399// Now expand the basic registered passes from the .inc file.
2400#define FUNCTION_PASS(NAME, CREATE_PASS) \
2401 if (Name == NAME) { \
2402 if constexpr (std::is_constructible_v< \
2403 std::remove_reference_t<decltype(CREATE_PASS)>, \
2404 const TargetMachine &>) { \
2405 if (!TM) \
2406 return make_error<StringError>( \
2407 formatv("pass '{0}' requires TargetMachine", Name).str(), \
2408 inconvertibleErrorCode()); \
2409 } \
2410 FPM.addPass(CREATE_PASS); \
2411 return Error::success(); \
2412 }
2413#define FUNCTION_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \
2414 if (checkParametrizedPassName(Name, NAME)) { \
2415 auto Params = parsePassParameters(PARSER, Name, NAME); \
2416 if (!Params) \
2417 return Params.takeError(); \
2418 auto CreatePass = CREATE_PASS; \
2419 if constexpr (std::is_constructible_v< \
2420 std::remove_reference_t<decltype(CreatePass( \
2421 Params.get()))>, \
2422 const TargetMachine &, \
2423 std::remove_reference_t<decltype(Params.get())>>) { \
2424 if (!TM) { \
2425 return make_error<StringError>( \
2426 formatv("pass '{0}' requires TargetMachine", Name).str(), \
2427 inconvertibleErrorCode()); \
2428 } \
2429 } \
2430 FPM.addPass(CREATE_PASS(Params.get())); \
2431 return Error::success(); \
2432 }
2433#define FUNCTION_ANALYSIS(NAME, CREATE_PASS) \
2434 if (Name == "require<" NAME ">") { \
2435 if constexpr (std::is_constructible_v< \
2436 std::remove_reference_t<decltype(CREATE_PASS)>, \
2437 const TargetMachine &>) { \
2438 if (!TM) \
2439 return make_error<StringError>( \
2440 formatv("pass '{0}' requires TargetMachine", Name).str(), \
2441 inconvertibleErrorCode()); \
2442 } \
2443 FPM.addPass( \
2444 RequireAnalysisPass<std::remove_reference_t<decltype(CREATE_PASS)>, \
2445 Function>()); \
2446 return Error::success(); \
2447 } \
2448 if (Name == "invalidate<" NAME ">") { \
2449 FPM.addPass(InvalidateAnalysisPass< \
2450 std::remove_reference_t<decltype(CREATE_PASS)>>()); \
2451 return Error::success(); \
2452 }
2453// FIXME: UseMemorySSA is set to false. Maybe we could do things like:
2454// bool UseMemorySSA = !("canon-freeze" || "loop-predication" ||
2455// "guard-widening");
2456// The risk is that it may become obsolete if we're not careful.
2457#define LOOPNEST_PASS(NAME, CREATE_PASS) \
2458 if (Name == NAME) { \
2459 FPM.addPass(createFunctionToLoopPassAdaptor(CREATE_PASS, false)); \
2460 return Error::success(); \
2461 }
2462#define LOOP_PASS(NAME, CREATE_PASS) \
2463 if (Name == NAME) { \
2464 FPM.addPass(createFunctionToLoopPassAdaptor(CREATE_PASS, false)); \
2465 return Error::success(); \
2466 }
2467#define LOOP_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \
2468 if (checkParametrizedPassName(Name, NAME)) { \
2469 auto Params = parsePassParameters(PARSER, Name, NAME); \
2470 if (!Params) \
2471 return Params.takeError(); \
2472 FPM.addPass( \
2473 createFunctionToLoopPassAdaptor(CREATE_PASS(Params.get()), false)); \
2474 return Error::success(); \
2475 }
2476#include "PassRegistry.def"
2477
2478 for (auto &C : FunctionPipelineParsingCallbacks)
2479 if (C(Name, FPM, InnerPipeline))
2480 return Error::success();
2481 return make_error<StringError>(
2482 Args: formatv(Fmt: "unknown function pass '{}'", Vals: Name).str(),
2483 Args: inconvertibleErrorCode());
2484}
2485
2486Error PassBuilder::parseLoopPass(LoopPassManager &LPM,
2487 const PipelineElement &E) {
2488 StringRef Name = E.Name;
2489 auto &InnerPipeline = E.InnerPipeline;
2490
2491 // First handle complex passes like the pass managers which carry pipelines.
2492 if (!InnerPipeline.empty()) {
2493 if (Name == "loop") {
2494 LoopPassManager NestedLPM;
2495 if (auto Err = parseLoopPassPipeline(LPM&: NestedLPM, Pipeline: InnerPipeline))
2496 return Err;
2497 // Add the nested pass manager with the appropriate adaptor.
2498 LPM.addPass(Pass: std::move(NestedLPM));
2499 return Error::success();
2500 }
2501
2502 for (auto &C : LoopPipelineParsingCallbacks)
2503 if (C(Name, LPM, InnerPipeline))
2504 return Error::success();
2505
2506 // Normal passes can't have pipelines.
2507 return make_error<StringError>(
2508 Args: formatv(Fmt: "invalid use of '{}' pass as loop pipeline", Vals&: Name).str(),
2509 Args: inconvertibleErrorCode());
2510 }
2511
2512// Now expand the basic registered passes from the .inc file.
2513#define LOOPNEST_PASS(NAME, CREATE_PASS) \
2514 if (Name == NAME) { \
2515 LPM.addPass(CREATE_PASS); \
2516 return Error::success(); \
2517 }
2518#define LOOP_PASS(NAME, CREATE_PASS) \
2519 if (Name == NAME) { \
2520 LPM.addPass(CREATE_PASS); \
2521 return Error::success(); \
2522 }
2523#define LOOP_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \
2524 if (checkParametrizedPassName(Name, NAME)) { \
2525 auto Params = parsePassParameters(PARSER, Name, NAME); \
2526 if (!Params) \
2527 return Params.takeError(); \
2528 LPM.addPass(CREATE_PASS(Params.get())); \
2529 return Error::success(); \
2530 }
2531#define LOOP_ANALYSIS(NAME, CREATE_PASS) \
2532 if (Name == "require<" NAME ">") { \
2533 LPM.addPass(RequireAnalysisPass< \
2534 std::remove_reference_t<decltype(CREATE_PASS)>, Loop, \
2535 LoopAnalysisManager, LoopStandardAnalysisResults &, \
2536 LPMUpdater &>()); \
2537 return Error::success(); \
2538 } \
2539 if (Name == "invalidate<" NAME ">") { \
2540 LPM.addPass(InvalidateAnalysisPass< \
2541 std::remove_reference_t<decltype(CREATE_PASS)>>()); \
2542 return Error::success(); \
2543 }
2544#include "PassRegistry.def"
2545
2546 for (auto &C : LoopPipelineParsingCallbacks)
2547 if (C(Name, LPM, InnerPipeline))
2548 return Error::success();
2549 return make_error<StringError>(Args: formatv(Fmt: "unknown loop pass '{}'", Vals&: Name).str(),
2550 Args: inconvertibleErrorCode());
2551}
2552
2553Error PassBuilder::parseMachinePass(MachineFunctionPassManager &MFPM,
2554 const PipelineElement &E) {
2555 StringRef Name = E.Name;
2556 // Handle any nested pass managers.
2557 if (!E.InnerPipeline.empty()) {
2558 if (E.Name == "machine-function") {
2559 MachineFunctionPassManager NestedPM;
2560 if (auto Err = parseMachinePassPipeline(MFPM&: NestedPM, Pipeline: E.InnerPipeline))
2561 return Err;
2562 MFPM.addPass(Pass: std::move(NestedPM));
2563 return Error::success();
2564 }
2565 return make_error<StringError>(Args: "invalid pipeline",
2566 Args: inconvertibleErrorCode());
2567 }
2568
2569#define MACHINE_MODULE_PASS(NAME, CREATE_PASS) \
2570 if (Name == NAME) { \
2571 MFPM.addPass(CREATE_PASS); \
2572 return Error::success(); \
2573 }
2574#define MACHINE_FUNCTION_PASS(NAME, CREATE_PASS) \
2575 if (Name == NAME) { \
2576 MFPM.addPass(CREATE_PASS); \
2577 return Error::success(); \
2578 }
2579#define MACHINE_FUNCTION_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, \
2580 PARAMS) \
2581 if (checkParametrizedPassName(Name, NAME)) { \
2582 auto Params = parsePassParameters(PARSER, Name, NAME); \
2583 if (!Params) \
2584 return Params.takeError(); \
2585 MFPM.addPass(CREATE_PASS(Params.get())); \
2586 return Error::success(); \
2587 }
2588#define MACHINE_FUNCTION_ANALYSIS(NAME, CREATE_PASS) \
2589 if (Name == "require<" NAME ">") { \
2590 MFPM.addPass( \
2591 RequireAnalysisPass<std::remove_reference_t<decltype(CREATE_PASS)>, \
2592 MachineFunction>()); \
2593 return Error::success(); \
2594 } \
2595 if (Name == "invalidate<" NAME ">") { \
2596 MFPM.addPass(InvalidateAnalysisPass< \
2597 std::remove_reference_t<decltype(CREATE_PASS)>>()); \
2598 return Error::success(); \
2599 }
2600#include "llvm/Passes/MachinePassRegistry.def"
2601
2602 for (auto &C : MachineFunctionPipelineParsingCallbacks)
2603 if (C(Name, MFPM, E.InnerPipeline))
2604 return Error::success();
2605 return make_error<StringError>(
2606 Args: formatv(Fmt: "unknown machine pass '{}'", Vals&: Name).str(),
2607 Args: inconvertibleErrorCode());
2608}
2609
2610bool PassBuilder::parseAAPassName(AAManager &AA, StringRef Name) {
2611#define MODULE_ALIAS_ANALYSIS(NAME, CREATE_PASS) \
2612 if (Name == NAME) { \
2613 AA.registerModuleAnalysis< \
2614 std::remove_reference_t<decltype(CREATE_PASS)>>(); \
2615 return true; \
2616 }
2617#define FUNCTION_ALIAS_ANALYSIS(NAME, CREATE_PASS) \
2618 if (Name == NAME) { \
2619 AA.registerFunctionAnalysis< \
2620 std::remove_reference_t<decltype(CREATE_PASS)>>(); \
2621 return true; \
2622 }
2623#include "PassRegistry.def"
2624
2625 for (auto &C : AAParsingCallbacks)
2626 if (C(Name, AA))
2627 return true;
2628 return false;
2629}
2630
2631Error PassBuilder::parseMachinePassPipeline(
2632 MachineFunctionPassManager &MFPM, ArrayRef<PipelineElement> Pipeline) {
2633 for (const auto &Element : Pipeline) {
2634 if (auto Err = parseMachinePass(MFPM, E: Element))
2635 return Err;
2636 }
2637 return Error::success();
2638}
2639
2640Error PassBuilder::parseLoopPassPipeline(LoopPassManager &LPM,
2641 ArrayRef<PipelineElement> Pipeline) {
2642 for (const auto &Element : Pipeline) {
2643 if (auto Err = parseLoopPass(LPM, E: Element))
2644 return Err;
2645 }
2646 return Error::success();
2647}
2648
2649Error PassBuilder::parseFunctionPassPipeline(
2650 FunctionPassManager &FPM, ArrayRef<PipelineElement> Pipeline) {
2651 for (const auto &Element : Pipeline) {
2652 if (auto Err = parseFunctionPass(FPM, E: Element))
2653 return Err;
2654 }
2655 return Error::success();
2656}
2657
2658Error PassBuilder::parseCGSCCPassPipeline(CGSCCPassManager &CGPM,
2659 ArrayRef<PipelineElement> Pipeline) {
2660 for (const auto &Element : Pipeline) {
2661 if (auto Err = parseCGSCCPass(CGPM, E: Element))
2662 return Err;
2663 }
2664 return Error::success();
2665}
2666
2667void PassBuilder::crossRegisterProxies(LoopAnalysisManager &LAM,
2668 FunctionAnalysisManager &FAM,
2669 CGSCCAnalysisManager &CGAM,
2670 ModuleAnalysisManager &MAM,
2671 MachineFunctionAnalysisManager *MFAM) {
2672 MAM.registerPass(PassBuilder: [&] { return FunctionAnalysisManagerModuleProxy(FAM); });
2673 MAM.registerPass(PassBuilder: [&] { return CGSCCAnalysisManagerModuleProxy(CGAM); });
2674 CGAM.registerPass(PassBuilder: [&] { return ModuleAnalysisManagerCGSCCProxy(MAM); });
2675 FAM.registerPass(PassBuilder: [&] { return CGSCCAnalysisManagerFunctionProxy(CGAM); });
2676 FAM.registerPass(PassBuilder: [&] { return ModuleAnalysisManagerFunctionProxy(MAM); });
2677 FAM.registerPass(PassBuilder: [&] { return LoopAnalysisManagerFunctionProxy(LAM); });
2678 LAM.registerPass(PassBuilder: [&] { return FunctionAnalysisManagerLoopProxy(FAM); });
2679 if (MFAM) {
2680 MAM.registerPass(
2681 PassBuilder: [&] { return MachineFunctionAnalysisManagerModuleProxy(*MFAM); });
2682 FAM.registerPass(
2683 PassBuilder: [&] { return MachineFunctionAnalysisManagerFunctionProxy(*MFAM); });
2684 MFAM->registerPass(
2685 PassBuilder: [&] { return ModuleAnalysisManagerMachineFunctionProxy(MAM); });
2686 MFAM->registerPass(
2687 PassBuilder: [&] { return FunctionAnalysisManagerMachineFunctionProxy(FAM); });
2688 }
2689}
2690
2691Error PassBuilder::parseModulePassPipeline(ModulePassManager &MPM,
2692 ArrayRef<PipelineElement> Pipeline) {
2693 for (const auto &Element : Pipeline) {
2694 if (auto Err = parseModulePass(MPM, E: Element))
2695 return Err;
2696 }
2697 return Error::success();
2698}
2699
2700// Primary pass pipeline description parsing routine for a \c ModulePassManager
2701// FIXME: Should this routine accept a TargetMachine or require the caller to
2702// pre-populate the analysis managers with target-specific stuff?
2703Error PassBuilder::parsePassPipeline(ModulePassManager &MPM,
2704 StringRef PipelineText) {
2705 auto Pipeline = parsePipelineText(Text: PipelineText);
2706 if (!Pipeline || Pipeline->empty())
2707 return make_error<StringError>(
2708 Args: formatv(Fmt: "invalid pipeline '{}'", Vals&: PipelineText).str(),
2709 Args: inconvertibleErrorCode());
2710
2711 // If the first name isn't at the module layer, wrap the pipeline up
2712 // automatically.
2713 StringRef FirstName = Pipeline->front().Name;
2714
2715 if (!isModulePassName(Name: FirstName, Callbacks&: ModulePipelineParsingCallbacks)) {
2716 bool UseMemorySSA;
2717 if (isCGSCCPassName(Name: FirstName, Callbacks&: CGSCCPipelineParsingCallbacks)) {
2718 Pipeline = {{.Name: "cgscc", .InnerPipeline: std::move(*Pipeline)}};
2719 } else if (isFunctionPassName(Name: FirstName,
2720 Callbacks&: FunctionPipelineParsingCallbacks)) {
2721 Pipeline = {{.Name: "function", .InnerPipeline: std::move(*Pipeline)}};
2722 } else if (isLoopNestPassName(Name: FirstName, Callbacks&: LoopPipelineParsingCallbacks,
2723 UseMemorySSA)) {
2724 Pipeline = {{.Name: "function", .InnerPipeline: {{.Name: UseMemorySSA ? "loop-mssa" : "loop",
2725 .InnerPipeline: std::move(*Pipeline)}}}};
2726 } else if (isLoopPassName(Name: FirstName, Callbacks&: LoopPipelineParsingCallbacks,
2727 UseMemorySSA)) {
2728 Pipeline = {{.Name: "function", .InnerPipeline: {{.Name: UseMemorySSA ? "loop-mssa" : "loop",
2729 .InnerPipeline: std::move(*Pipeline)}}}};
2730 } else if (isMachineFunctionPassName(
2731 Name: FirstName, Callbacks&: MachineFunctionPipelineParsingCallbacks)) {
2732 Pipeline = {{.Name: "function", .InnerPipeline: {{.Name: "machine-function", .InnerPipeline: std::move(*Pipeline)}}}};
2733 } else {
2734 for (auto &C : TopLevelPipelineParsingCallbacks)
2735 if (C(MPM, *Pipeline))
2736 return Error::success();
2737
2738 // Unknown pass or pipeline name!
2739 auto &InnerPipeline = Pipeline->front().InnerPipeline;
2740 return make_error<StringError>(
2741 Args: formatv(Fmt: "unknown {} name '{}'",
2742 Vals: (InnerPipeline.empty() ? "pass" : "pipeline"), Vals&: FirstName)
2743 .str(),
2744 Args: inconvertibleErrorCode());
2745 }
2746 }
2747
2748 if (auto Err = parseModulePassPipeline(MPM, Pipeline: *Pipeline))
2749 return Err;
2750 return Error::success();
2751}
2752
2753// Primary pass pipeline description parsing routine for a \c CGSCCPassManager
2754Error PassBuilder::parsePassPipeline(CGSCCPassManager &CGPM,
2755 StringRef PipelineText) {
2756 auto Pipeline = parsePipelineText(Text: PipelineText);
2757 if (!Pipeline || Pipeline->empty())
2758 return make_error<StringError>(
2759 Args: formatv(Fmt: "invalid pipeline '{}'", Vals&: PipelineText).str(),
2760 Args: inconvertibleErrorCode());
2761
2762 StringRef FirstName = Pipeline->front().Name;
2763 if (!isCGSCCPassName(Name: FirstName, Callbacks&: CGSCCPipelineParsingCallbacks))
2764 return make_error<StringError>(
2765 Args: formatv(Fmt: "unknown cgscc pass '{}' in pipeline '{}'", Vals&: FirstName,
2766 Vals&: PipelineText)
2767 .str(),
2768 Args: inconvertibleErrorCode());
2769
2770 if (auto Err = parseCGSCCPassPipeline(CGPM, Pipeline: *Pipeline))
2771 return Err;
2772 return Error::success();
2773}
2774
2775// Primary pass pipeline description parsing routine for a \c
2776// FunctionPassManager
2777Error PassBuilder::parsePassPipeline(FunctionPassManager &FPM,
2778 StringRef PipelineText) {
2779 auto Pipeline = parsePipelineText(Text: PipelineText);
2780 if (!Pipeline || Pipeline->empty())
2781 return make_error<StringError>(
2782 Args: formatv(Fmt: "invalid pipeline '{}'", Vals&: PipelineText).str(),
2783 Args: inconvertibleErrorCode());
2784
2785 StringRef FirstName = Pipeline->front().Name;
2786 if (!isFunctionPassName(Name: FirstName, Callbacks&: FunctionPipelineParsingCallbacks))
2787 return make_error<StringError>(
2788 Args: formatv(Fmt: "unknown function pass '{}' in pipeline '{}'", Vals&: FirstName,
2789 Vals&: PipelineText)
2790 .str(),
2791 Args: inconvertibleErrorCode());
2792
2793 if (auto Err = parseFunctionPassPipeline(FPM, Pipeline: *Pipeline))
2794 return Err;
2795 return Error::success();
2796}
2797
2798// Primary pass pipeline description parsing routine for a \c LoopPassManager
2799Error PassBuilder::parsePassPipeline(LoopPassManager &CGPM,
2800 StringRef PipelineText) {
2801 auto Pipeline = parsePipelineText(Text: PipelineText);
2802 if (!Pipeline || Pipeline->empty())
2803 return make_error<StringError>(
2804 Args: formatv(Fmt: "invalid pipeline '{}'", Vals&: PipelineText).str(),
2805 Args: inconvertibleErrorCode());
2806
2807 if (auto Err = parseLoopPassPipeline(LPM&: CGPM, Pipeline: *Pipeline))
2808 return Err;
2809
2810 return Error::success();
2811}
2812
2813Error PassBuilder::parsePassPipeline(MachineFunctionPassManager &MFPM,
2814 StringRef PipelineText) {
2815 auto Pipeline = parsePipelineText(Text: PipelineText);
2816 if (!Pipeline || Pipeline->empty())
2817 return make_error<StringError>(
2818 Args: formatv(Fmt: "invalid machine pass pipeline '{}'", Vals&: PipelineText).str(),
2819 Args: inconvertibleErrorCode());
2820
2821 if (auto Err = parseMachinePassPipeline(MFPM, Pipeline: *Pipeline))
2822 return Err;
2823
2824 return Error::success();
2825}
2826
2827Error PassBuilder::parseAAPipeline(AAManager &AA, StringRef PipelineText) {
2828 // If the pipeline just consists of the word 'default' just replace the AA
2829 // manager with our default one.
2830 if (PipelineText == "default") {
2831 AA = buildDefaultAAPipeline();
2832 return Error::success();
2833 }
2834
2835 while (!PipelineText.empty()) {
2836 StringRef Name;
2837 std::tie(args&: Name, args&: PipelineText) = PipelineText.split(Separator: ',');
2838 if (!parseAAPassName(AA, Name))
2839 return make_error<StringError>(
2840 Args: formatv(Fmt: "unknown alias analysis name '{}'", Vals&: Name).str(),
2841 Args: inconvertibleErrorCode());
2842 }
2843
2844 return Error::success();
2845}
2846
2847std::optional<RegAllocFilterFunc>
2848PassBuilder::parseRegAllocFilter(StringRef FilterName) {
2849 if (FilterName == "all")
2850 return nullptr;
2851 for (auto &C : RegClassFilterParsingCallbacks)
2852 if (auto F = C(FilterName))
2853 return F;
2854 return std::nullopt;
2855}
2856
2857LLVM_ATTRIBUTE_NOINLINE static void printPassNameList(StringTable PassNames,
2858 raw_ostream &OS) {
2859 for (StringRef PassName : PassNames)
2860 OS << " " << PassName << '\n';
2861}
2862
2863LLVM_ATTRIBUTE_NOINLINE static void
2864printPassNameListWithParams(StringTable PassNames, raw_ostream &OS) {
2865 auto I = PassNames.begin();
2866 auto End = PassNames.end();
2867 while (I != End) {
2868 StringRef Name = *I;
2869 ++I;
2870 assert(I != End);
2871 StringRef Params = *I;
2872 ++I;
2873 OS << " " << Name << '<' << Params << ">\n";
2874 }
2875}
2876
2877void PassBuilder::printPassNames(raw_ostream &OS) {
2878 // TODO: print pass descriptions when they are available
2879
2880 OS << "Module passes:\n";
2881 static constexpr char ModulePassNames[] = {"\0"
2882#define MODULE_PASS(NAME, CREATE_PASS) NAME "\0"
2883#include "PassRegistry.def"
2884 };
2885 printPassNameList(PassNames: StringTable(ModulePassNames), OS);
2886
2887 OS << "Module passes with params:\n";
2888 static constexpr char ModulePassNamesWithParams[] = {"\0"
2889#define MODULE_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \
2890 NAME "\0" PARAMS "\0"
2891#include "PassRegistry.def"
2892 };
2893 printPassNameListWithParams(PassNames: StringTable(ModulePassNamesWithParams), OS);
2894
2895 OS << "Module analyses:\n";
2896 static constexpr char ModuleAnalysisNames[] = {"\0"
2897#define MODULE_ANALYSIS(NAME, CREATE_PASS) NAME "\0"
2898#include "PassRegistry.def"
2899 };
2900 printPassNameList(PassNames: StringTable(ModuleAnalysisNames), OS);
2901
2902 OS << "Module alias analyses:\n";
2903 static constexpr char ModuleAliasAnalysisNames[] = {"\0"
2904#define MODULE_ALIAS_ANALYSIS(NAME, CREATE_PASS) NAME "\0"
2905#include "PassRegistry.def"
2906 };
2907 printPassNameList(PassNames: StringTable(ModuleAliasAnalysisNames), OS);
2908
2909 OS << "CGSCC passes:\n";
2910 static constexpr char CGSCCPassNames[] = {"\0"
2911#define CGSCC_PASS(NAME, CREATE_PASS) NAME "\0"
2912#include "PassRegistry.def"
2913 };
2914 printPassNameList(PassNames: StringTable(CGSCCPassNames), OS);
2915
2916 OS << "CGSCC passes with params:\n";
2917 static constexpr char CGSCCPassNamesWithParams[] = {"\0"
2918#define CGSCC_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \
2919 NAME "\0" PARAMS "\0"
2920#include "PassRegistry.def"
2921 };
2922 printPassNameListWithParams(PassNames: StringTable(CGSCCPassNamesWithParams), OS);
2923
2924 OS << "CGSCC analyses:\n";
2925 static constexpr char CGSCCAnalysisNames[] = {"\0"
2926#define CGSCC_ANALYSIS(NAME, CREATE_PASS) NAME "\0"
2927#include "PassRegistry.def"
2928 };
2929 printPassNameList(PassNames: StringTable(CGSCCAnalysisNames), OS);
2930
2931 OS << "Function passes:\n";
2932 static constexpr char FunctionPassNames[] = {"\0"
2933#define FUNCTION_PASS(NAME, CREATE_PASS) NAME "\0"
2934#include "PassRegistry.def"
2935 };
2936 printPassNameList(PassNames: StringTable(FunctionPassNames), OS);
2937
2938 OS << "Function passes with params:\n";
2939 static constexpr char FunctionPassNamesWithParams[] = {"\0"
2940#define FUNCTION_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \
2941 NAME "\0" PARAMS "\0"
2942#include "PassRegistry.def"
2943 };
2944 printPassNameListWithParams(PassNames: StringTable(FunctionPassNamesWithParams), OS);
2945
2946 OS << "Function analyses:\n";
2947 static constexpr char FunctionAnalysisNames[] = {"\0"
2948#define FUNCTION_ANALYSIS(NAME, CREATE_PASS) NAME "\0"
2949#include "PassRegistry.def"
2950 };
2951 printPassNameList(PassNames: StringTable(FunctionAnalysisNames), OS);
2952
2953 OS << "Function alias analyses:\n";
2954 static constexpr char FunctionAliasAnalysisNames[] = {"\0"
2955#define FUNCTION_ALIAS_ANALYSIS(NAME, CREATE_PASS) NAME "\0"
2956#include "PassRegistry.def"
2957 };
2958 printPassNameList(PassNames: StringTable(FunctionAliasAnalysisNames), OS);
2959
2960 OS << "LoopNest passes:\n";
2961 static constexpr char LoopNestPassNames[] = {"\0"
2962#define LOOPNEST_PASS(NAME, CREATE_PASS) NAME "\0"
2963#include "PassRegistry.def"
2964 };
2965 printPassNameList(PassNames: StringTable(LoopNestPassNames), OS);
2966
2967 OS << "Loop passes:\n";
2968 static constexpr char LoopPassNames[] = {"\0"
2969#define LOOP_PASS(NAME, CREATE_PASS) NAME "\0"
2970#include "PassRegistry.def"
2971 };
2972 printPassNameList(PassNames: StringTable(LoopPassNames), OS);
2973
2974 OS << "Loop passes with params:\n";
2975 static constexpr char LoopPassNamesWithParams[] = {"\0"
2976#define LOOP_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) \
2977 NAME "\0" PARAMS "\0"
2978#include "PassRegistry.def"
2979 };
2980 printPassNameListWithParams(PassNames: StringTable(LoopPassNamesWithParams), OS);
2981
2982 OS << "Loop analyses:\n";
2983 static constexpr char LoopAnalysisNames[] = {"\0"
2984#define LOOP_ANALYSIS(NAME, CREATE_PASS) NAME "\0"
2985#include "PassRegistry.def"
2986 };
2987 printPassNameList(PassNames: StringTable(LoopAnalysisNames), OS);
2988
2989 OS << "Machine module passes (WIP):\n";
2990 static constexpr char MachineModulePassNames[] = {"\0"
2991#define MACHINE_MODULE_PASS(NAME, CREATE_PASS) NAME "\0"
2992#include "llvm/Passes/MachinePassRegistry.def"
2993 };
2994 printPassNameList(PassNames: StringTable(MachineModulePassNames), OS);
2995
2996 OS << "Machine function passes (WIP):\n";
2997 static constexpr char MachineFunctionPassNames[] = {"\0"
2998#define MACHINE_FUNCTION_PASS(NAME, CREATE_PASS) NAME "\0"
2999#include "llvm/Passes/MachinePassRegistry.def"
3000 };
3001 printPassNameList(PassNames: StringTable(MachineFunctionPassNames), OS);
3002
3003 OS << "Machine function analyses (WIP):\n";
3004 static constexpr char MachineFunctionAnalysisNames[] = {"\0"
3005#define MACHINE_FUNCTION_ANALYSIS(NAME, CREATE_PASS) NAME "\0"
3006#include "llvm/Passes/MachinePassRegistry.def"
3007 };
3008 printPassNameList(PassNames: StringTable(MachineFunctionAnalysisNames), OS);
3009}
3010
3011void PassBuilder::registerParseTopLevelPipelineCallback(
3012 const std::function<bool(ModulePassManager &, ArrayRef<PipelineElement>)>
3013 &C) {
3014 TopLevelPipelineParsingCallbacks.push_back(Elt: C);
3015}
3016