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