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