Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 6c35b53

Browse files
committed
Redo the pass manager
1 parent 8c6ad9a commit 6c35b53

File tree

4 files changed

+508
-65
lines changed

4 files changed

+508
-65
lines changed

‎Sources/LLVM/PassManager.swift

Lines changed: 8 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import cllvm
33
#endif
44

55
/// A subset of supported LLVM IR optimizer passes.
6-
public enum FunctionPass {
6+
public enum Pass {
77
/// This pass uses the SSA based Aggressive DCE algorithm. This algorithm
88
/// assumes instructions are dead until proven otherwise, which makes
99
/// it more successful are removing non-obviously dead instructions.
@@ -106,8 +106,6 @@ public enum FunctionPass {
106106
case scalarReplAggregates
107107
/// Replace aggregates or pieces of aggregates with scalar SSA values.
108108
case scalarReplAggregatesSSA
109-
/// Tries to inline the fast path of library calls such as sqrt.
110-
case simplifyLibCalls
111109
/// This pass eliminates call instructions to the current function which occur
112110
/// immediately before return instructions.
113111
case tailCallElimination
@@ -186,69 +184,10 @@ public enum FunctionPass {
186184
/// A `FunctionPassManager` is an object that collects a sequence of passes
187185
/// which run over a particular IR construct, and runs each of them in sequence
188186
/// over each such construct.
187+
@available(*, deprecated, message: "Use the PassPipeliner instead")
189188
public class FunctionPassManager {
190189
internal let llvm: LLVMPassManagerRef
191190

192-
private static let passMapping: [FunctionPass: (LLVMPassManagerRef) -> Void] = [
193-
.aggressiveDCE: LLVMAddAggressiveDCEPass,
194-
.bitTrackingDCE: LLVMAddBitTrackingDCEPass,
195-
.alignmentFromAssumptions: LLVMAddAlignmentFromAssumptionsPass,
196-
.cfgSimplification: LLVMAddCFGSimplificationPass,
197-
.deadStoreElimination: LLVMAddDeadStoreEliminationPass,
198-
.scalarizer: LLVMAddScalarizerPass,
199-
.mergedLoadStoreMotion: LLVMAddMergedLoadStoreMotionPass,
200-
.gvn: LLVMAddGVNPass,
201-
.indVarSimplify: LLVMAddIndVarSimplifyPass,
202-
.instructionCombining: LLVMAddInstructionCombiningPass,
203-
.jumpThreading: LLVMAddJumpThreadingPass,
204-
.licm: LLVMAddLICMPass,
205-
.loopDeletion: LLVMAddLoopDeletionPass,
206-
.loopIdiom: LLVMAddLoopIdiomPass,
207-
.loopRotate: LLVMAddLoopRotatePass,
208-
.loopReroll: LLVMAddLoopRerollPass,
209-
.loopUnroll: LLVMAddLoopUnrollPass,
210-
.loopUnrollAndJam: LLVMAddLoopUnrollAndJamPass,
211-
.loopUnswitch: LLVMAddLoopUnswitchPass,
212-
.lowerAtomic: LLVMAddLowerAtomicPass,
213-
.memCpyOpt: LLVMAddMemCpyOptPass,
214-
.partiallyInlineLibCalls: LLVMAddPartiallyInlineLibCallsPass,
215-
.lowerSwitch: LLVMAddLowerSwitchPass,
216-
.promoteMemoryToRegister: LLVMAddPromoteMemoryToRegisterPass,
217-
.reassociate: LLVMAddReassociatePass,
218-
.sccp: LLVMAddSCCPPass,
219-
.scalarReplAggregates: LLVMAddScalarReplAggregatesPass,
220-
.scalarReplAggregatesSSA: LLVMAddScalarReplAggregatesPassSSA,
221-
.simplifyLibCalls: LLVMAddSimplifyLibCallsPass,
222-
.tailCallElimination: LLVMAddTailCallEliminationPass,
223-
.constantPropagation: LLVMAddConstantPropagationPass,
224-
.demoteMemoryToRegister: LLVMAddDemoteMemoryToRegisterPass,
225-
.verifier: LLVMAddVerifierPass,
226-
.correlatedValuePropagation: LLVMAddCorrelatedValuePropagationPass,
227-
.earlyCSE: LLVMAddEarlyCSEPass,
228-
.lowerExpectIntrinsic: LLVMAddLowerExpectIntrinsicPass,
229-
.typeBasedAliasAnalysis: LLVMAddTypeBasedAliasAnalysisPass,
230-
.scopedNoAliasAA: LLVMAddScopedNoAliasAAPass,
231-
.basicAliasAnalysis: LLVMAddBasicAliasAnalysisPass,
232-
.unifyFunctionExitNodes: LLVMAddUnifyFunctionExitNodesPass,
233-
.alwaysInliner: LLVMAddAlwaysInlinerPass,
234-
.argumentPromotion: LLVMAddArgumentPromotionPass,
235-
.constantMerge: LLVMAddConstantMergePass,
236-
.deadArgElimination: LLVMAddDeadArgEliminationPass,
237-
.functionAttrs: LLVMAddFunctionAttrsPass,
238-
.functionInlining: LLVMAddFunctionInliningPass,
239-
.globalDCE: LLVMAddGlobalDCEPass,
240-
.globalOptimizer: LLVMAddGlobalOptimizerPass,
241-
.ipConstantPropagation: LLVMAddIPConstantPropagationPass,
242-
.ipscc: LLVMAddIPSCCPPass,
243-
.pruneEH: LLVMAddPruneEHPass,
244-
.stripDeadPrototypes: LLVMAddStripDeadPrototypesPass,
245-
.stripSymbols: LLVMAddStripSymbolsPass,
246-
.loopVectorize: LLVMAddLoopVectorizePass,
247-
.slpVectorize: LLVMAddSLPVectorizePass,
248-
// .internalize: LLVMAddInternalizePass,
249-
// .sroaWithThreshhold: LLVMAddScalarReplAggregatesPassWithThreshold,
250-
]
251-
252191
/// Creates a `FunctionPassManager` bound to the given module's IR.
253192
public init(module: Module) {
254193
llvm = LLVMCreateFunctionPassManagerForModule(module.llvm)!
@@ -259,9 +198,9 @@ public class FunctionPassManager {
259198
///
260199
/// - parameter passes: A list of function passes to add to the pass manager's
261200
/// list of passes to run.
262-
public func add(_ passes: FunctionPass...) {
201+
public func add(_ passes: Pass...) {
263202
for pass in passes {
264-
FunctionPassManager.passMapping[pass]!(llvm)
203+
PassPipeliner.passMapping[pass]!(llvm)
265204
}
266205
}
267206

@@ -272,3 +211,7 @@ public class FunctionPassManager {
272211
LLVMRunFunctionPassManager(llvm, function.asLLVM())
273212
}
274213
}
214+
215+
@available(*, deprecated, renamed: "Pass")
216+
public typealias FunctionPass = Pass
217+

‎Sources/LLVM/PassPipeliner.swift

Lines changed: 284 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,284 @@
1+
#if SWIFT_PACKAGE
2+
import cllvm
3+
#endif
4+
5+
/// Implements a pass manager, pipeliner, and executor for a set of
6+
/// user-provided optimization passes.
7+
///
8+
/// A `PassPipeliner` handles the creation of a related set of optimization
9+
/// passes called a "pipeline". Grouping passes is done for multiple reasons,
10+
/// chief among them is that optimizer passes are extremely sensitive to their
11+
/// ordering relative to other passses. In addition, pass groupings allow for
12+
/// the clean segregation of otherwise unrelated passes. For example, a
13+
/// pipeline might consist of "mandatory" passes such as Jump Threading, LICM,
14+
/// and DCE in one pipeline and "diagnostic" passes in another.
15+
public final class PassPipeliner {
16+
private enum Pipeline {
17+
case builtinPasses([Pass])
18+
case functionPassManager(LLVMPassManagerRef)
19+
case modulePassManager(LLVMPassManagerRef)
20+
}
21+
22+
/// The module for this pass pipeline.
23+
public let module: Module
24+
/// The pipeline stages registered with this pass pipeliner.
25+
public private(set) var stages: [String]
26+
27+
private var stageMapping: [String: Pipeline]
28+
private var frozen: Bool = false
29+
30+
public final class Builder {
31+
fileprivate var passes: [Pass] = []
32+
33+
fileprivate init() {}
34+
35+
/// Appends a pass to the current pipeline.
36+
public func add(_ type: Pass) {
37+
self.passes.append(type)
38+
}
39+
}
40+
41+
/// Initializes a new, empty pipeliner.
42+
///
43+
/// - Parameter module: The module the pipeliner will run over.
44+
public init(module: Module) {
45+
self.module = module
46+
self.stages = []
47+
self.stageMapping = [:]
48+
}
49+
50+
deinit {
51+
for stage in stageMapping.values {
52+
switch stage {
53+
case let .functionPassManager(pm):
54+
LLVMDisposePassManager(pm)
55+
case let .modulePassManager(pm):
56+
LLVMDisposePassManager(pm)
57+
case .builtinPasses(_):
58+
continue
59+
}
60+
}
61+
}
62+
63+
/// Appends a stage to the pipeliner.
64+
///
65+
/// The staging function provides a `Builder` object into which the types
66+
/// of passes for a given pipeline are inserted.
67+
///
68+
/// - Parameters:
69+
/// - name: The name of the pipeline stage.
70+
/// - stager: A builder function.
71+
public func addStage(_ name: String, _ stager: (Builder) -> Void) {
72+
precondition(!self.frozen, "Cannot add new stages to a frozen pipeline!")
73+
74+
self.frozen = true
75+
defer { self.frozen = false }
76+
77+
self.stages.append(name)
78+
let builder = Builder()
79+
stager(builder)
80+
self.stageMapping[name] = .builtinPasses(builder.passes)
81+
}
82+
83+
/// Executes the entirety of the pass pipeline.
84+
///
85+
/// Execution of passes is done in a loop that is divided into two phases.
86+
/// The first phase aggregates all local passes and stops aggregation when
87+
/// it encounters a module-level pass. This group of local passes
88+
/// is then run one at a time on the same scope. The second phase is entered
89+
/// and the module pass is run. The first phase is then re-entered until all
90+
/// local passes have run on all local scopes and all intervening module
91+
/// passes have been run.
92+
///
93+
/// The same pipeline may be repeatedly re-executed, but pipeline execution
94+
/// is not re-entrancy safe.
95+
public func execute() {
96+
precondition(!self.frozen, "Cannot execute a frozen pipeline!")
97+
98+
self.frozen = true
99+
defer { self.frozen = false }
100+
101+
stageLoop: for stage in self.stages {
102+
guard let pipeline = self.stageMapping[stage] else {
103+
fatalError("Unregistered pass stage?")
104+
}
105+
106+
switch pipeline {
107+
case let .builtinPasses(passTypes):
108+
guard !passTypes.isEmpty else {
109+
continue stageLoop
110+
}
111+
self.runPasses(passTypes)
112+
case let .functionPassManager(pm):
113+
self.runFunctionPasses([], pm)
114+
case let .modulePassManager(pm):
115+
LLVMRunPassManager(pm, self.module.llvm)
116+
}
117+
}
118+
}
119+
120+
private func runFunctionPasses(_ passes: [Pass], _ pm: LLVMPassManagerRef) {
121+
LLVMInitializeFunctionPassManager(pm)
122+
123+
for pass in passes {
124+
PassPipeliner.passMapping[pass]!(pm)
125+
}
126+
127+
for function in self.module.functions {
128+
LLVMRunFunctionPassManager(pm, function.asLLVM())
129+
}
130+
}
131+
132+
private func runPasses(_ passes: [Pass]) {
133+
let pm = LLVMCreatePassManager()!
134+
for pass in passes {
135+
PassPipeliner.passMapping[pass]!(pm)
136+
}
137+
LLVMRunPassManager(pm, self.module.llvm)
138+
LLVMDisposePassManager(pm)
139+
}
140+
}
141+
142+
// MARK: Standard Pass Pipelines
143+
144+
extension PassPipeliner {
145+
public func addStandardFunctionPipeline(
146+
_ name: String,
147+
optimization: CodeGenOptLevel = .`default`,
148+
size: CodeGenOptLevel = .none
149+
) {
150+
let passBuilder = self.configurePassBuilder(optimization, size)
151+
let functionPasses =
152+
LLVMCreateFunctionPassManagerForModule(self.module.llvm)!
153+
LLVMPassManagerBuilderPopulateFunctionPassManager(passBuilder,
154+
functionPasses)
155+
LLVMPassManagerBuilderDispose(passBuilder)
156+
self.stages.append(name)
157+
self.stageMapping[name] = .functionPassManager(functionPasses)
158+
}
159+
160+
public func addStandardModulePipeline(
161+
_ name: String,
162+
optimization: CodeGenOptLevel = .`default`,
163+
size: CodeGenOptLevel = .none
164+
) {
165+
let passBuilder = self.configurePassBuilder(optimization, size)
166+
let modulePasses = LLVMCreatePassManager()!
167+
LLVMPassManagerBuilderPopulateModulePassManager(passBuilder, modulePasses)
168+
LLVMPassManagerBuilderDispose(passBuilder)
169+
self.stages.append(name)
170+
self.stageMapping[name] = .modulePassManager(modulePasses)
171+
}
172+
173+
private func configurePassBuilder(
174+
_ opt: CodeGenOptLevel,
175+
_ size: CodeGenOptLevel
176+
) -> LLVMPassManagerBuilderRef {
177+
let passBuilder = LLVMPassManagerBuilderCreate()!
178+
switch opt {
179+
case .none:
180+
LLVMPassManagerBuilderSetOptLevel(passBuilder, 0)
181+
case .less:
182+
LLVMPassManagerBuilderSetOptLevel(passBuilder, 1)
183+
case .default:
184+
LLVMPassManagerBuilderSetOptLevel(passBuilder, 2)
185+
case .aggressive:
186+
LLVMPassManagerBuilderSetOptLevel(passBuilder, 3)
187+
}
188+
189+
switch size {
190+
case .none:
191+
LLVMPassManagerBuilderSetSizeLevel(passBuilder, 0)
192+
case .less:
193+
LLVMPassManagerBuilderSetSizeLevel(passBuilder, 1)
194+
case .default:
195+
LLVMPassManagerBuilderSetSizeLevel(passBuilder, 2)
196+
case .aggressive:
197+
LLVMPassManagerBuilderSetSizeLevel(passBuilder, 3)
198+
}
199+
200+
return passBuilder
201+
}
202+
}
203+
204+
205+
extension PassPipeliner {
206+
static let passMapping: [Pass: (LLVMPassManagerRef) -> Void] = [
207+
.aggressiveDCE: LLVMAddAggressiveDCEPass,
208+
.bitTrackingDCE: LLVMAddBitTrackingDCEPass,
209+
.alignmentFromAssumptions: LLVMAddAlignmentFromAssumptionsPass,
210+
.cfgSimplification: LLVMAddCFGSimplificationPass,
211+
.deadStoreElimination: LLVMAddDeadStoreEliminationPass,
212+
.scalarizer: LLVMAddScalarizerPass,
213+
.mergedLoadStoreMotion: LLVMAddMergedLoadStoreMotionPass,
214+
.gvn: LLVMAddGVNPass,
215+
.indVarSimplify: LLVMAddIndVarSimplifyPass,
216+
.instructionCombining: LLVMAddInstructionCombiningPass,
217+
.jumpThreading: LLVMAddJumpThreadingPass,
218+
.licm: LLVMAddLICMPass,
219+
.loopDeletion: LLVMAddLoopDeletionPass,
220+
.loopIdiom: LLVMAddLoopIdiomPass,
221+
.loopRotate: LLVMAddLoopRotatePass,
222+
.loopReroll: LLVMAddLoopRerollPass,
223+
.loopUnroll: LLVMAddLoopUnrollPass,
224+
.loopUnrollAndJam: LLVMAddLoopUnrollAndJamPass,
225+
.loopUnswitch: LLVMAddLoopUnswitchPass,
226+
.lowerAtomic: LLVMAddLowerAtomicPass,
227+
.memCpyOpt: LLVMAddMemCpyOptPass,
228+
.partiallyInlineLibCalls: LLVMAddPartiallyInlineLibCallsPass,
229+
.lowerSwitch: LLVMAddLowerSwitchPass,
230+
.promoteMemoryToRegister: LLVMAddPromoteMemoryToRegisterPass,
231+
.reassociate: LLVMAddReassociatePass,
232+
.sccp: LLVMAddSCCPPass,
233+
.scalarReplAggregates: LLVMAddScalarReplAggregatesPass,
234+
.scalarReplAggregatesSSA: LLVMAddScalarReplAggregatesPassSSA,
235+
.tailCallElimination: LLVMAddTailCallEliminationPass,
236+
.constantPropagation: LLVMAddConstantPropagationPass,
237+
.demoteMemoryToRegister: LLVMAddDemoteMemoryToRegisterPass,
238+
.verifier: LLVMAddVerifierPass,
239+
.correlatedValuePropagation: LLVMAddCorrelatedValuePropagationPass,
240+
.earlyCSE: LLVMAddEarlyCSEPass,
241+
.lowerExpectIntrinsic: LLVMAddLowerExpectIntrinsicPass,
242+
.typeBasedAliasAnalysis: LLVMAddTypeBasedAliasAnalysisPass,
243+
.scopedNoAliasAA: LLVMAddScopedNoAliasAAPass,
244+
.basicAliasAnalysis: LLVMAddBasicAliasAnalysisPass,
245+
.unifyFunctionExitNodes: LLVMAddUnifyFunctionExitNodesPass,
246+
.alwaysInliner: LLVMAddAlwaysInlinerPass,
247+
.argumentPromotion: LLVMAddArgumentPromotionPass,
248+
.constantMerge: LLVMAddConstantMergePass,
249+
.deadArgElimination: LLVMAddDeadArgEliminationPass,
250+
.functionAttrs: LLVMAddFunctionAttrsPass,
251+
.functionInlining: LLVMAddFunctionInliningPass,
252+
.globalDCE: LLVMAddGlobalDCEPass,
253+
.globalOptimizer: LLVMAddGlobalOptimizerPass,
254+
.ipConstantPropagation: LLVMAddIPConstantPropagationPass,
255+
.ipscc: LLVMAddIPSCCPPass,
256+
.pruneEH: LLVMAddPruneEHPass,
257+
.stripDeadPrototypes: LLVMAddStripDeadPrototypesPass,
258+
.stripSymbols: LLVMAddStripSymbolsPass,
259+
.loopVectorize: LLVMAddLoopVectorizePass,
260+
.slpVectorize: LLVMAddSLPVectorizePass,
261+
// .internalize: LLVMAddInternalizePass,
262+
// .sroaWithThreshhold: LLVMAddScalarReplAggregatesPassWithThreshold,
263+
]
264+
}
265+
266+
extension Pass {
267+
var isModulePass: Bool {
268+
switch self {
269+
case .stripSymbols,
270+
.stripDeadPrototypes,
271+
.constantMerge,
272+
.globalOptimizer,
273+
.globalDCE,
274+
.deadArgElimination,
275+
.ipConstantPropagation,
276+
.ipscc,
277+
.functionAttrs,
278+
.functionInlining:
279+
return true
280+
default:
281+
return false
282+
}
283+
}
284+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /