11#if SWIFT_PACKAGE
22import cllvm
3+ import llvmshims
34#endif
45
56/// Implements a pass manager, pipeliner, and executor for a set of
@@ -125,10 +126,11 @@ public final class PassPipeliner {
125126 }
126127
127128 private func runFunctionPasses( _ passes: [ Pass ] , _ pm: LLVMPassManagerRef ) {
129+ var keepalive = [ Any] ( )
128130 LLVMInitializeFunctionPassManager ( pm)
129131
130132 for pass in passes {
131- PassPipeliner . passMapping [ pass ] ! ( pm )
133+ PassPipeliner . configurePass ( pass , passManager : pm , keepalive : & keepalive )
132134 }
133135
134136 for function in self . module. functions {
@@ -137,9 +139,10 @@ public final class PassPipeliner {
137139 }
138140
139141 private func runPasses( _ passes: [ Pass ] ) {
142+ var keepalive = [ Any] ( )
140143 let pm = LLVMCreatePassManager ( ) !
141144 for pass in passes {
142- PassPipeliner . passMapping [ pass ] ! ( pm )
145+ PassPipeliner . configurePass ( pass , passManager : pm , keepalive : & keepalive )
143146 }
144147 LLVMRunPassManager ( pm, self . module. llvm)
145148 LLVMDisposePassManager ( pm)
@@ -149,6 +152,15 @@ public final class PassPipeliner {
149152// MARK: Standard Pass Pipelines
150153
151154extension PassPipeliner {
155+ /// Adds a pipeline stage populated with function passes that LLVM considers
156+ /// standard for languages like C and C++. Additional parameters are
157+ /// available to tune the overall behavior of the optimization pipeline at a
158+ /// macro level.
159+ ///
160+ /// - Parameters:
161+ /// - name: The name of the pipeline stage.
162+ /// - optimization: The level of optimization.
163+ /// - size: The level of size optimization.
152164 public func addStandardFunctionPipeline(
153165 _ name: String ,
154166 optimization: CodeGenOptLevel = . `default`,
@@ -164,6 +176,15 @@ extension PassPipeliner {
164176 self . stageMapping [ name] = . functionPassManager( functionPasses)
165177 }
166178
179+ /// Adds a pipeline stage populated with module passes that LLVM considers
180+ /// standard for languages like C and C++. Additional parameters are
181+ /// available to tune the overall behavior of the optimization pipeline at a
182+ /// macro level.
183+ ///
184+ /// - Parameters:
185+ /// - name: The name of the pipeline stage.
186+ /// - optimization: The level of optimization.
187+ /// - size: The level of size optimization.
167188 public func addStandardModulePipeline(
168189 _ name: String ,
169190 optimization: CodeGenOptLevel = . `default`,
@@ -210,62 +231,173 @@ extension PassPipeliner {
210231
211232
212233extension PassPipeliner {
213- static let passMapping : [ Pass : ( LLVMPassManagerRef ) -> Void ] = [
214- . aggressiveDCE: LLVMAddAggressiveDCEPass,
215- . bitTrackingDCE: LLVMAddBitTrackingDCEPass,
216- . alignmentFromAssumptions: LLVMAddAlignmentFromAssumptionsPass,
217- . cfgSimplification: LLVMAddCFGSimplificationPass,
218- . deadStoreElimination: LLVMAddDeadStoreEliminationPass,
219- . scalarizer: LLVMAddScalarizerPass,
220- . mergedLoadStoreMotion: LLVMAddMergedLoadStoreMotionPass,
221- . gvn: LLVMAddGVNPass,
222- . indVarSimplify: LLVMAddIndVarSimplifyPass,
223- . instructionCombining: LLVMAddInstructionCombiningPass,
224- . jumpThreading: LLVMAddJumpThreadingPass,
225- . licm: LLVMAddLICMPass,
226- . loopDeletion: LLVMAddLoopDeletionPass,
227- . loopIdiom: LLVMAddLoopIdiomPass,
228- . loopRotate: LLVMAddLoopRotatePass,
229- . loopReroll: LLVMAddLoopRerollPass,
230- . loopUnroll: LLVMAddLoopUnrollPass,
231- . loopUnrollAndJam: LLVMAddLoopUnrollAndJamPass,
232- . loopUnswitch: LLVMAddLoopUnswitchPass,
233- . lowerAtomic: LLVMAddLowerAtomicPass,
234- . memCpyOpt: LLVMAddMemCpyOptPass,
235- . partiallyInlineLibCalls: LLVMAddPartiallyInlineLibCallsPass,
236- . lowerSwitch: LLVMAddLowerSwitchPass,
237- . promoteMemoryToRegister: LLVMAddPromoteMemoryToRegisterPass,
238- . reassociate: LLVMAddReassociatePass,
239- . sccp: LLVMAddSCCPPass,
240- . scalarReplAggregates: LLVMAddScalarReplAggregatesPass,
241- . scalarReplAggregatesSSA: LLVMAddScalarReplAggregatesPassSSA,
242- . tailCallElimination: LLVMAddTailCallEliminationPass,
243- . constantPropagation: LLVMAddConstantPropagationPass,
244- . demoteMemoryToRegister: LLVMAddDemoteMemoryToRegisterPass,
245- . verifier: LLVMAddVerifierPass,
246- . correlatedValuePropagation: LLVMAddCorrelatedValuePropagationPass,
247- . earlyCSE: LLVMAddEarlyCSEPass,
248- . lowerExpectIntrinsic: LLVMAddLowerExpectIntrinsicPass,
249- . typeBasedAliasAnalysis: LLVMAddTypeBasedAliasAnalysisPass,
250- . scopedNoAliasAA: LLVMAddScopedNoAliasAAPass,
251- . basicAliasAnalysis: LLVMAddBasicAliasAnalysisPass,
252- . unifyFunctionExitNodes: LLVMAddUnifyFunctionExitNodesPass,
253- . alwaysInliner: LLVMAddAlwaysInlinerPass,
254- . argumentPromotion: LLVMAddArgumentPromotionPass,
255- . constantMerge: LLVMAddConstantMergePass,
256- . deadArgElimination: LLVMAddDeadArgEliminationPass,
257- . functionAttrs: LLVMAddFunctionAttrsPass,
258- . functionInlining: LLVMAddFunctionInliningPass,
259- . globalDCE: LLVMAddGlobalDCEPass,
260- . globalOptimizer: LLVMAddGlobalOptimizerPass,
261- . ipConstantPropagation: LLVMAddIPConstantPropagationPass,
262- . ipscc: LLVMAddIPSCCPPass,
263- . pruneEH: LLVMAddPruneEHPass,
264- . stripDeadPrototypes: LLVMAddStripDeadPrototypesPass,
265- . stripSymbols: LLVMAddStripSymbolsPass,
266- . loopVectorize: LLVMAddLoopVectorizePass,
267- . slpVectorize: LLVMAddSLPVectorizePass,
268- // .internalize: LLVMAddInternalizePass,
269- // .sroaWithThreshhold: LLVMAddScalarReplAggregatesPassWithThreshold,
270- ]
234+ /// Configures and adds a pass to the given pass manager.
235+ ///
236+ /// - Parameters:
237+ /// - pass: The pass to add to the pass manager.
238+ /// - passManager: The pass manager to which to add a pass.
239+ /// - keepalive: An array that must stay alive for as long as this pass
240+ /// manager stays alive. This array will keep Swift objects
241+ /// that may be passed into closures that will use them at
242+ /// any point in the pass execution line.
243+ static func configurePass(
244+ _ pass: Pass ,
245+ passManager: LLVMPassManagerRef ,
246+ keepalive: inout [ Any ] ) {
247+ switch pass {
248+ case . invalid( let reason) :
249+ fatalError ( " Cannot configure pass: \( reason) " )
250+ case . aggressiveDCE:
251+ LLVMAddAggressiveDCEPass ( passManager)
252+ case . bitTrackingDCE:
253+ LLVMAddBitTrackingDCEPass ( passManager)
254+ case . alignmentFromAssumptions:
255+ LLVMAddAlignmentFromAssumptionsPass ( passManager)
256+ case . cfgSimplification:
257+ LLVMAddCFGSimplificationPass ( passManager)
258+ case . deadStoreElimination:
259+ LLVMAddDeadStoreEliminationPass ( passManager)
260+ case . scalarizer:
261+ LLVMAddScalarizerPass ( passManager)
262+ case . mergedLoadStoreMotion:
263+ LLVMAddMergedLoadStoreMotionPass ( passManager)
264+ case . gvn:
265+ LLVMAddGVNPass ( passManager)
266+ case . indVarSimplify:
267+ LLVMAddIndVarSimplifyPass ( passManager)
268+ case . instructionCombining:
269+ LLVMAddInstructionCombiningPass ( passManager)
270+ case . jumpThreading:
271+ LLVMAddJumpThreadingPass ( passManager)
272+ case . licm:
273+ LLVMAddLICMPass ( passManager)
274+ case . loopDeletion:
275+ LLVMAddLoopDeletionPass ( passManager)
276+ case . loopIdiom:
277+ LLVMAddLoopIdiomPass ( passManager)
278+ case . loopRotate:
279+ LLVMAddLoopRotatePass ( passManager)
280+ case . loopReroll:
281+ LLVMAddLoopRerollPass ( passManager)
282+ case . loopUnroll:
283+ LLVMAddLoopUnrollPass ( passManager)
284+ case . loopUnrollAndJam:
285+ LLVMAddLoopUnrollAndJamPass ( passManager)
286+ case . loopUnswitch:
287+ LLVMAddLoopUnswitchPass ( passManager)
288+ case . lowerAtomic:
289+ LLVMAddLowerAtomicPass ( passManager)
290+ case . memCpyOpt:
291+ LLVMAddMemCpyOptPass ( passManager)
292+ case . partiallyInlineLibCalls:
293+ LLVMAddPartiallyInlineLibCallsPass ( passManager)
294+ case . lowerSwitch:
295+ LLVMAddLowerSwitchPass ( passManager)
296+ case . promoteMemoryToRegister:
297+ LLVMAddPromoteMemoryToRegisterPass ( passManager)
298+ case . addDiscriminators:
299+ LLVMAddAddDiscriminatorsPass ( passManager)
300+ case . reassociate:
301+ LLVMAddReassociatePass ( passManager)
302+ case . sccp:
303+ LLVMAddSCCPPass ( passManager)
304+ case . tailCallElimination:
305+ LLVMAddTailCallEliminationPass ( passManager)
306+ case . constantPropagation:
307+ LLVMAddConstantPropagationPass ( passManager)
308+ case . demoteMemoryToRegister:
309+ LLVMAddDemoteMemoryToRegisterPass ( passManager)
310+ case . verifier:
311+ LLVMAddVerifierPass ( passManager)
312+ case . correlatedValuePropagation:
313+ LLVMAddCorrelatedValuePropagationPass ( passManager)
314+ case . earlyCSE:
315+ LLVMAddEarlyCSEPass ( passManager)
316+ case . lowerExpectIntrinsic:
317+ LLVMAddLowerExpectIntrinsicPass ( passManager)
318+ case . typeBasedAliasAnalysis:
319+ LLVMAddTypeBasedAliasAnalysisPass ( passManager)
320+ case . scopedNoAliasAA:
321+ LLVMAddScopedNoAliasAAPass ( passManager)
322+ case . basicAliasAnalysis:
323+ LLVMAddBasicAliasAnalysisPass ( passManager)
324+ case . unifyFunctionExitNodes:
325+ LLVMAddUnifyFunctionExitNodesPass ( passManager)
326+ case . alwaysInliner:
327+ LLVMAddAlwaysInlinerPass ( passManager)
328+ case . argumentPromotion:
329+ LLVMAddArgumentPromotionPass ( passManager)
330+ case . constantMerge:
331+ LLVMAddConstantMergePass ( passManager)
332+ case . deadArgElimination:
333+ LLVMAddDeadArgEliminationPass ( passManager)
334+ case . functionAttrs:
335+ LLVMAddFunctionAttrsPass ( passManager)
336+ case . functionInlining:
337+ LLVMAddFunctionInliningPass ( passManager)
338+ case . globalDCE:
339+ LLVMAddGlobalDCEPass ( passManager)
340+ case . globalOptimizer:
341+ LLVMAddGlobalOptimizerPass ( passManager)
342+ case . ipConstantPropagation:
343+ LLVMAddIPConstantPropagationPass ( passManager)
344+ case . ipscc:
345+ LLVMAddIPSCCPPass ( passManager)
346+ case . pruneEH:
347+ LLVMAddPruneEHPass ( passManager)
348+ case . stripDeadPrototypes:
349+ LLVMAddStripDeadPrototypesPass ( passManager)
350+ case . stripSymbols:
351+ LLVMAddStripSymbolsPass ( passManager)
352+ case . loopVectorize:
353+ LLVMAddLoopVectorizePass ( passManager)
354+ case . slpVectorize:
355+ LLVMAddSLPVectorizePass ( passManager)
356+ case . internalizeAll( let preserveMain) :
357+ LLVMAddInternalizePass ( passManager, preserveMain == false ? 0 : 1 )
358+ case . internalize( let pred) :
359+ // The lifetime of this callback is must be manually managed to ensure
360+ // it remains alive across the execution of the given pass manager.
361+
362+ // Create a callback context at +1
363+ let callbackContext = InternalizeCallbackContext ( pred)
364+ // Stick it in the keepalive array, now at +2
365+ keepalive. append ( callbackContext)
366+ // Pass it unmanaged at +2
367+ let contextPtr = Unmanaged < InternalizeCallbackContext > . passUnretained ( callbackContext) . toOpaque ( )
368+ LLVMAddInternalizePassWithMustPreservePredicate ( passManager, contextPtr) { globalValue, callbackCtx in
369+ guard let globalValue = globalValue, let callbackCtx = callbackCtx else {
370+ fatalError ( " Global value and context must be non-nil " )
371+ }
372+
373+ let callback = Unmanaged < InternalizeCallbackContext > . fromOpaque ( callbackCtx) . takeUnretainedValue ( )
374+ return callback. block ( realizeGlobalValue ( globalValue) ) . llvm
375+ }
376+ // Context dropped, now at +1
377+ // When the keepalive array is dropped by the caller, it will drop to +0.
378+ case . scalarReplacementOfAggregates:
379+ LLVMAddScalarReplAggregatesPassWithThreshold ( passManager, /*ignored*/ 0 )
380+ }
381+ }
382+ }
383+
384+ private func realizeGlobalValue( _ llvm: LLVMValueRef ) -> IRGlobal {
385+ precondition ( llvm. isAGlobalValue, " must be a global value " )
386+ if llvm. isAFunction {
387+ return Function ( llvm: llvm)
388+ } else if llvm. isAGlobalAlias {
389+ return Alias ( llvm: llvm)
390+ } else if llvm. isAGlobalVariable {
391+ return Global ( llvm: llvm)
392+ } else {
393+ fatalError ( " unrecognized global value " )
394+ }
395+ }
396+
397+ private class InternalizeCallbackContext {
398+ fileprivate let block : ( IRGlobal ) -> Bool
399+
400+ fileprivate init ( _ block: @escaping ( IRGlobal ) -> Bool ) {
401+ self . block = block
402+ }
271403}
0 commit comments