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