/rust/registry/src/index.crates.io-1949cf8c6b5b557f/inkwell-0.8.0/src/passes.rs
Line | Count | Source |
1 | | #[llvm_versions(..=16)] |
2 | | use llvm_sys::core::LLVMGetGlobalPassRegistry; |
3 | | use llvm_sys::core::{ |
4 | | LLVMCreateFunctionPassManagerForModule, LLVMCreatePassManager, LLVMDisposePassManager, |
5 | | LLVMFinalizeFunctionPassManager, LLVMInitializeFunctionPassManager, LLVMRunFunctionPassManager, LLVMRunPassManager, |
6 | | }; |
7 | | #[llvm_versions(..=16)] |
8 | | use llvm_sys::initialization::{ |
9 | | LLVMInitializeAnalysis, LLVMInitializeCodeGen, LLVMInitializeCore, LLVMInitializeIPA, LLVMInitializeIPO, |
10 | | LLVMInitializeInstCombine, LLVMInitializeScalarOpts, LLVMInitializeTarget, LLVMInitializeTransformUtils, |
11 | | LLVMInitializeVectorization, |
12 | | }; |
13 | | #[llvm_versions(..=15)] |
14 | | use llvm_sys::initialization::{LLVMInitializeInstrumentation, LLVMInitializeObjCARCOpts}; |
15 | | use llvm_sys::prelude::LLVMPassManagerRef; |
16 | | #[llvm_versions(..=16)] |
17 | | use llvm_sys::prelude::LLVMPassRegistryRef; |
18 | | #[llvm_versions(..=15)] |
19 | | use llvm_sys::transforms::aggressive_instcombine::LLVMAddAggressiveInstCombinerPass; |
20 | | #[llvm_versions(..=16)] |
21 | | use llvm_sys::transforms::ipo::LLVMAddMergeFunctionsPass; |
22 | | #[llvm_versions(..=15)] |
23 | | use llvm_sys::transforms::ipo::LLVMAddPruneEHPass; |
24 | | #[llvm_versions(..=16)] |
25 | | use llvm_sys::transforms::ipo::{ |
26 | | LLVMAddAlwaysInlinerPass, LLVMAddConstantMergePass, LLVMAddDeadArgEliminationPass, LLVMAddFunctionAttrsPass, |
27 | | LLVMAddFunctionInliningPass, LLVMAddGlobalDCEPass, LLVMAddGlobalOptimizerPass, LLVMAddIPSCCPPass, |
28 | | LLVMAddInternalizePass, LLVMAddStripDeadPrototypesPass, LLVMAddStripSymbolsPass, |
29 | | }; |
30 | | #[llvm_versions(..=16)] |
31 | | use llvm_sys::transforms::pass_manager_builder::{ |
32 | | LLVMPassManagerBuilderCreate, LLVMPassManagerBuilderDispose, LLVMPassManagerBuilderPopulateFunctionPassManager, |
33 | | LLVMPassManagerBuilderPopulateModulePassManager, LLVMPassManagerBuilderRef, |
34 | | LLVMPassManagerBuilderSetDisableSimplifyLibCalls, LLVMPassManagerBuilderSetDisableUnitAtATime, |
35 | | LLVMPassManagerBuilderSetDisableUnrollLoops, LLVMPassManagerBuilderSetOptLevel, LLVMPassManagerBuilderSetSizeLevel, |
36 | | LLVMPassManagerBuilderUseInlinerWithThreshold, |
37 | | }; |
38 | | #[llvm_versions(..=16)] |
39 | | use llvm_sys::transforms::scalar::{ |
40 | | LLVMAddAggressiveDCEPass, LLVMAddAlignmentFromAssumptionsPass, LLVMAddBasicAliasAnalysisPass, |
41 | | LLVMAddBitTrackingDCEPass, LLVMAddCFGSimplificationPass, LLVMAddCorrelatedValuePropagationPass, |
42 | | LLVMAddDeadStoreEliminationPass, LLVMAddDemoteMemoryToRegisterPass, LLVMAddEarlyCSEPass, LLVMAddGVNPass, |
43 | | LLVMAddIndVarSimplifyPass, LLVMAddInstructionCombiningPass, LLVMAddJumpThreadingPass, LLVMAddLICMPass, |
44 | | LLVMAddLoopDeletionPass, LLVMAddLoopIdiomPass, LLVMAddLoopRerollPass, LLVMAddLoopRotatePass, LLVMAddLoopUnrollPass, |
45 | | LLVMAddLowerExpectIntrinsicPass, LLVMAddMemCpyOptPass, LLVMAddMergedLoadStoreMotionPass, |
46 | | LLVMAddPartiallyInlineLibCallsPass, LLVMAddReassociatePass, LLVMAddSCCPPass, LLVMAddScalarReplAggregatesPass, |
47 | | LLVMAddScalarReplAggregatesPassSSA, LLVMAddScalarReplAggregatesPassWithThreshold, LLVMAddScalarizerPass, |
48 | | LLVMAddScopedNoAliasAAPass, LLVMAddSimplifyLibCallsPass, LLVMAddTailCallEliminationPass, |
49 | | LLVMAddTypeBasedAliasAnalysisPass, LLVMAddVerifierPass, |
50 | | }; |
51 | | #[llvm_versions(..=16)] |
52 | | use llvm_sys::transforms::vectorize::{LLVMAddLoopVectorizePass, LLVMAddSLPVectorizePass}; |
53 | | |
54 | | // LLVM12 removes the ConstantPropagation pass |
55 | | // Users should use the InstSimplify pass instead. |
56 | | #[cfg(feature = "llvm11-0")] |
57 | | use llvm_sys::transforms::ipo::LLVMAddIPConstantPropagationPass; |
58 | | #[cfg(feature = "llvm11-0")] |
59 | | use llvm_sys::transforms::scalar::LLVMAddConstantPropagationPass; |
60 | | |
61 | | #[llvm_versions(13..)] |
62 | | use llvm_sys::transforms::pass_builder::{ |
63 | | LLVMCreatePassBuilderOptions, LLVMDisposePassBuilderOptions, LLVMPassBuilderOptionsRef, |
64 | | LLVMPassBuilderOptionsSetCallGraphProfile, LLVMPassBuilderOptionsSetDebugLogging, |
65 | | LLVMPassBuilderOptionsSetForgetAllSCEVInLoopUnroll, LLVMPassBuilderOptionsSetLicmMssaNoAccForPromotionCap, |
66 | | LLVMPassBuilderOptionsSetLicmMssaOptCap, LLVMPassBuilderOptionsSetLoopInterleaving, |
67 | | LLVMPassBuilderOptionsSetLoopUnrolling, LLVMPassBuilderOptionsSetLoopVectorization, |
68 | | LLVMPassBuilderOptionsSetMergeFunctions, LLVMPassBuilderOptionsSetSLPVectorization, |
69 | | LLVMPassBuilderOptionsSetVerifyEach, |
70 | | }; |
71 | | #[llvm_versions(12..=16)] |
72 | | use llvm_sys::transforms::scalar::LLVMAddInstructionSimplifyPass; |
73 | | |
74 | | use crate::module::Module; |
75 | | use crate::values::{AsValueRef, FunctionValue}; |
76 | | #[llvm_versions(..=16)] |
77 | | use crate::OptimizationLevel; |
78 | | |
79 | | use std::borrow::Borrow; |
80 | | use std::marker::PhantomData; |
81 | | |
82 | | // REVIEW: Opt Level might be identical to targets::Option<CodeGenOptLevel> |
83 | | #[llvm_versions(..=16)] |
84 | | #[derive(Debug)] |
85 | | pub struct PassManagerBuilder { |
86 | | pass_manager_builder: LLVMPassManagerBuilderRef, |
87 | | } |
88 | | |
89 | | #[llvm_versions(..=16)] |
90 | | impl PassManagerBuilder { |
91 | | pub unsafe fn new(pass_manager_builder: LLVMPassManagerBuilderRef) -> Self { |
92 | | assert!(!pass_manager_builder.is_null()); |
93 | | |
94 | | PassManagerBuilder { pass_manager_builder } |
95 | | } |
96 | | |
97 | | /// Acquires the underlying raw pointer belonging to this `PassManagerBuilder` type. |
98 | | pub fn as_mut_ptr(&self) -> LLVMPassManagerBuilderRef { |
99 | | self.pass_manager_builder |
100 | | } |
101 | | |
102 | | pub fn create() -> Self { |
103 | | let pass_manager_builder = unsafe { LLVMPassManagerBuilderCreate() }; |
104 | | |
105 | | unsafe { PassManagerBuilder::new(pass_manager_builder) } |
106 | | } |
107 | | |
108 | | pub fn set_optimization_level(&self, opt_level: OptimizationLevel) { |
109 | | unsafe { LLVMPassManagerBuilderSetOptLevel(self.pass_manager_builder, opt_level as u32) } |
110 | | } |
111 | | |
112 | | // REVIEW: Valid input 0-2 according to llvmlite. Maybe better as an enum? |
113 | | pub fn set_size_level(&self, size_level: u32) { |
114 | | unsafe { LLVMPassManagerBuilderSetSizeLevel(self.pass_manager_builder, size_level) } |
115 | | } |
116 | | |
117 | | pub fn set_disable_unit_at_a_time(&self, disable: bool) { |
118 | | unsafe { LLVMPassManagerBuilderSetDisableUnitAtATime(self.pass_manager_builder, disable as i32) } |
119 | | } |
120 | | |
121 | | pub fn set_disable_unroll_loops(&self, disable: bool) { |
122 | | unsafe { LLVMPassManagerBuilderSetDisableUnrollLoops(self.pass_manager_builder, disable as i32) } |
123 | | } |
124 | | |
125 | | pub fn set_disable_simplify_lib_calls(&self, disable: bool) { |
126 | | unsafe { LLVMPassManagerBuilderSetDisableSimplifyLibCalls(self.pass_manager_builder, disable as i32) } |
127 | | } |
128 | | |
129 | | pub fn set_inliner_with_threshold(&self, threshold: u32) { |
130 | | unsafe { LLVMPassManagerBuilderUseInlinerWithThreshold(self.pass_manager_builder, threshold) } |
131 | | } |
132 | | |
133 | | /// Populates a PassManager<FunctionValue> with the expectation of function |
134 | | /// transformations. |
135 | | /// |
136 | | /// # Example |
137 | | /// |
138 | | /// ```no_run |
139 | | /// use inkwell::context::Context; |
140 | | /// use inkwell::OptimizationLevel::Aggressive; |
141 | | /// use inkwell::passes::{PassManager, PassManagerBuilder}; |
142 | | /// |
143 | | /// let context = Context::create(); |
144 | | /// let module = context.create_module("mod"); |
145 | | /// let pass_manager_builder = PassManagerBuilder::create(); |
146 | | /// |
147 | | /// pass_manager_builder.set_optimization_level(Aggressive); |
148 | | /// |
149 | | /// let fpm = PassManager::create(&module); |
150 | | /// |
151 | | /// pass_manager_builder.populate_function_pass_manager(&fpm); |
152 | | /// ``` |
153 | | pub fn populate_function_pass_manager(&self, pass_manager: &PassManager<FunctionValue>) { |
154 | | unsafe { |
155 | | LLVMPassManagerBuilderPopulateFunctionPassManager(self.pass_manager_builder, pass_manager.pass_manager) |
156 | | } |
157 | | } |
158 | | |
159 | | /// Populates a PassManager<Module> with the expectation of whole module |
160 | | /// transformations. |
161 | | /// |
162 | | /// # Example |
163 | | /// |
164 | | /// ```no_run |
165 | | /// use inkwell::OptimizationLevel::Aggressive; |
166 | | /// use inkwell::passes::{PassManager, PassManagerBuilder}; |
167 | | /// use inkwell::targets::{InitializationConfig, Target}; |
168 | | /// |
169 | | /// let config = InitializationConfig::default(); |
170 | | /// Target::initialize_native(&config).unwrap(); |
171 | | /// let pass_manager_builder = PassManagerBuilder::create(); |
172 | | /// |
173 | | /// pass_manager_builder.set_optimization_level(Aggressive); |
174 | | /// |
175 | | /// let fpm = PassManager::create(()); |
176 | | /// |
177 | | /// pass_manager_builder.populate_module_pass_manager(&fpm); |
178 | | /// ``` |
179 | | pub fn populate_module_pass_manager(&self, pass_manager: &PassManager<Module>) { |
180 | | unsafe { LLVMPassManagerBuilderPopulateModulePassManager(self.pass_manager_builder, pass_manager.pass_manager) } |
181 | | } |
182 | | |
183 | | /// Populates a PassManager<Module> with the expectation of link time |
184 | | /// optimization transformations. |
185 | | /// |
186 | | /// # Example |
187 | | /// |
188 | | /// ```no_run |
189 | | /// use inkwell::OptimizationLevel::Aggressive; |
190 | | /// use inkwell::passes::{PassManager, PassManagerBuilder}; |
191 | | /// use inkwell::targets::{InitializationConfig, Target}; |
192 | | /// |
193 | | /// let config = InitializationConfig::default(); |
194 | | /// Target::initialize_native(&config).unwrap(); |
195 | | /// let pass_manager_builder = PassManagerBuilder::create(); |
196 | | /// |
197 | | /// pass_manager_builder.set_optimization_level(Aggressive); |
198 | | /// |
199 | | /// let lpm = PassManager::create(()); |
200 | | /// |
201 | | /// pass_manager_builder.populate_lto_pass_manager(&lpm, false, false); |
202 | | /// ``` |
203 | | #[llvm_versions(..=14)] |
204 | | pub fn populate_lto_pass_manager(&self, pass_manager: &PassManager<Module>, internalize: bool, run_inliner: bool) { |
205 | | use llvm_sys::transforms::pass_manager_builder::LLVMPassManagerBuilderPopulateLTOPassManager; |
206 | | |
207 | | unsafe { |
208 | | LLVMPassManagerBuilderPopulateLTOPassManager( |
209 | | self.pass_manager_builder, |
210 | | pass_manager.pass_manager, |
211 | | internalize as i32, |
212 | | run_inliner as i32, |
213 | | ) |
214 | | } |
215 | | } |
216 | | } |
217 | | |
218 | | #[llvm_versions(..=16)] |
219 | | impl Drop for PassManagerBuilder { |
220 | | fn drop(&mut self) { |
221 | | unsafe { LLVMPassManagerBuilderDispose(self.pass_manager_builder) } |
222 | | } |
223 | | } |
224 | | |
225 | | // This is an ugly privacy hack so that PassManagerSubType can stay private |
226 | | // to this module and so that super traits using this trait will be not be |
227 | | // implementable outside this library |
228 | | pub trait PassManagerSubType { |
229 | | type Input; |
230 | | |
231 | | unsafe fn create<I: Borrow<Self::Input>>(input: I) -> LLVMPassManagerRef; |
232 | | unsafe fn run_in_pass_manager(&self, pass_manager: &PassManager<Self>) -> bool |
233 | | where |
234 | | Self: Sized; |
235 | | } |
236 | | |
237 | | impl PassManagerSubType for Module<'_> { |
238 | | type Input = (); |
239 | | |
240 | 0 | unsafe fn create<I: Borrow<Self::Input>>(_: I) -> LLVMPassManagerRef { |
241 | 0 | LLVMCreatePassManager() |
242 | 0 | } |
243 | | |
244 | 0 | unsafe fn run_in_pass_manager(&self, pass_manager: &PassManager<Self>) -> bool { |
245 | 0 | LLVMRunPassManager(pass_manager.pass_manager, self.module.get()) == 1 |
246 | 0 | } |
247 | | } |
248 | | |
249 | | // With GATs https://github.com/rust-lang/rust/issues/44265 this could be |
250 | | // type Input<'a> = &'a Module; |
251 | | impl<'ctx> PassManagerSubType for FunctionValue<'ctx> { |
252 | | type Input = Module<'ctx>; |
253 | | |
254 | 0 | unsafe fn create<I: Borrow<Self::Input>>(input: I) -> LLVMPassManagerRef { |
255 | 0 | LLVMCreateFunctionPassManagerForModule(input.borrow().module.get()) |
256 | 0 | } |
257 | | |
258 | 0 | unsafe fn run_in_pass_manager(&self, pass_manager: &PassManager<Self>) -> bool { |
259 | 0 | LLVMRunFunctionPassManager(pass_manager.pass_manager, self.as_value_ref()) == 1 |
260 | 0 | } |
261 | | } |
262 | | |
263 | | // SubTypes: PassManager<Module>, PassManager<FunctionValue> |
264 | | /// A manager for running optimization and simplification passes. Much of the |
265 | | /// documentation for specific passes is directly from the [LLVM |
266 | | /// documentation](https://llvm.org/docs/Passes.html). |
267 | | #[derive(Debug)] |
268 | | pub struct PassManager<T> { |
269 | | pub(crate) pass_manager: LLVMPassManagerRef, |
270 | | sub_type: PhantomData<T>, |
271 | | } |
272 | | |
273 | | impl PassManager<FunctionValue<'_>> { |
274 | | /// Acquires the underlying raw pointer belonging to this `PassManager<T>` type. |
275 | 0 | pub fn as_mut_ptr(&self) -> LLVMPassManagerRef { |
276 | 0 | self.pass_manager |
277 | 0 | } |
278 | | |
279 | | // return true means some pass modified the module, not an error occurred |
280 | 0 | pub fn initialize(&self) -> bool { |
281 | 0 | unsafe { LLVMInitializeFunctionPassManager(self.pass_manager) == 1 } |
282 | 0 | } |
283 | | |
284 | 0 | pub fn finalize(&self) -> bool { |
285 | 0 | unsafe { LLVMFinalizeFunctionPassManager(self.pass_manager) == 1 } |
286 | 0 | } |
287 | | } |
288 | | |
289 | | impl<T: PassManagerSubType> PassManager<T> { |
290 | 0 | pub unsafe fn new(pass_manager: LLVMPassManagerRef) -> Self { |
291 | 0 | assert!(!pass_manager.is_null()); |
292 | | |
293 | 0 | PassManager { |
294 | 0 | pass_manager, |
295 | 0 | sub_type: PhantomData, |
296 | 0 | } |
297 | 0 | } |
298 | | |
299 | 0 | pub fn create<I: Borrow<T::Input>>(input: I) -> PassManager<T> { |
300 | 0 | let pass_manager = unsafe { T::create(input) }; |
301 | | |
302 | 0 | unsafe { PassManager::new(pass_manager) } |
303 | 0 | } |
304 | | |
305 | | /// This method returns true if any of the passes modified the function or module |
306 | | /// and false otherwise. |
307 | 0 | pub fn run_on(&self, input: &T) -> bool { |
308 | 0 | unsafe { input.run_in_pass_manager(self) } |
309 | 0 | } |
310 | | |
311 | | /// This pass promotes "by reference" arguments to be "by value" arguments. |
312 | | /// In practice, this means looking for internal functions that have pointer |
313 | | /// arguments. If it can prove, through the use of alias analysis, that an |
314 | | /// argument is only loaded, then it can pass the value into the function |
315 | | /// instead of the address of the value. This can cause recursive simplification |
316 | | /// of code and lead to the elimination of allocas (especially in C++ template |
317 | | /// code like the STL). |
318 | | /// |
319 | | /// This pass also handles aggregate arguments that are passed into a function, |
320 | | /// scalarizing them if the elements of the aggregate are only loaded. Note that |
321 | | /// it refuses to scalarize aggregates which would require passing in more than |
322 | | /// three operands to the function, because passing thousands of operands for a |
323 | | /// large array or structure is unprofitable! |
324 | | /// |
325 | | /// Note that this transformation could also be done for arguments that are |
326 | | /// only stored to (returning the value instead), but does not currently. |
327 | | /// This case would be best handled when and if LLVM starts supporting multiple |
328 | | /// return values from functions. |
329 | | #[llvm_versions(..=14)] |
330 | | pub fn add_argument_promotion_pass(&self) { |
331 | | use llvm_sys::transforms::ipo::LLVMAddArgumentPromotionPass; |
332 | | |
333 | | unsafe { LLVMAddArgumentPromotionPass(self.pass_manager) } |
334 | | } |
335 | | |
336 | | /// Merges duplicate global constants together into a single constant that is |
337 | | /// shared. This is useful because some passes (i.e., TraceValues) insert a lot |
338 | | /// of string constants into the program, regardless of whether or not an existing |
339 | | /// string is available. |
340 | | #[llvm_versions(..=16)] |
341 | | pub fn add_constant_merge_pass(&self) { |
342 | | unsafe { LLVMAddConstantMergePass(self.pass_manager) } |
343 | | } |
344 | | |
345 | | /// Discovers identical functions and collapses them. |
346 | | #[llvm_versions(..=16)] |
347 | | pub fn add_merge_functions_pass(&self) { |
348 | | unsafe { LLVMAddMergeFunctionsPass(self.pass_manager) } |
349 | | } |
350 | | |
351 | | /// This pass deletes dead arguments from internal functions. Dead argument |
352 | | /// elimination removes arguments which are directly dead, as well as arguments |
353 | | /// only passed into function calls as dead arguments of other functions. This |
354 | | /// pass also deletes dead arguments in a similar way. |
355 | | /// |
356 | | /// This pass is often useful as a cleanup pass to run after aggressive |
357 | | /// interprocedural passes, which add possibly-dead arguments. |
358 | | #[llvm_versions(..=16)] |
359 | | pub fn add_dead_arg_elimination_pass(&self) { |
360 | | unsafe { LLVMAddDeadArgEliminationPass(self.pass_manager) } |
361 | | } |
362 | | |
363 | | /// A simple interprocedural pass which walks the call-graph, looking for |
364 | | /// functions which do not access or only read non-local memory, and marking |
365 | | /// them readnone/readonly. In addition, it marks function arguments (of |
366 | | /// pointer type) “nocapture” if a call to the function does not create |
367 | | /// any copies of the pointer value that outlive the call. This more or |
368 | | /// less means that the pointer is only dereferenced, and not returned |
369 | | /// from the function or stored in a global. This pass is implemented |
370 | | /// as a bottom-up traversal of the call-graph. |
371 | | #[llvm_versions(..=16)] |
372 | | pub fn add_function_attrs_pass(&self) { |
373 | | unsafe { LLVMAddFunctionAttrsPass(self.pass_manager) } |
374 | | } |
375 | | |
376 | | /// Bottom-up inlining of functions into callees. |
377 | | #[llvm_versions(..=16)] |
378 | | pub fn add_function_inlining_pass(&self) { |
379 | | unsafe { LLVMAddFunctionInliningPass(self.pass_manager) } |
380 | | } |
381 | | |
382 | | /// A custom inliner that handles only functions that are marked as “always inline”. |
383 | | #[llvm_versions(..=16)] |
384 | | pub fn add_always_inliner_pass(&self) { |
385 | | unsafe { LLVMAddAlwaysInlinerPass(self.pass_manager) } |
386 | | } |
387 | | |
388 | | /// This transform is designed to eliminate unreachable internal |
389 | | /// globals from the program. It uses an aggressive algorithm, |
390 | | /// searching out globals that are known to be alive. After it |
391 | | /// finds all of the globals which are needed, it deletes |
392 | | /// whatever is left over. This allows it to delete recursive |
393 | | /// chunks of the program which are unreachable. |
394 | | #[llvm_versions(..=16)] |
395 | | pub fn add_global_dce_pass(&self) { |
396 | | unsafe { LLVMAddGlobalDCEPass(self.pass_manager) } |
397 | | } |
398 | | |
399 | | /// This pass transforms simple global variables that never have |
400 | | /// their address taken. If obviously true, it marks read/write |
401 | | /// globals as constant, deletes variables only stored to, etc. |
402 | | #[llvm_versions(..=16)] |
403 | | pub fn add_global_optimizer_pass(&self) { |
404 | | unsafe { LLVMAddGlobalOptimizerPass(self.pass_manager) } |
405 | | } |
406 | | |
407 | | /// This pass implements an extremely simple interprocedural |
408 | | /// constant propagation pass. It could certainly be improved |
409 | | /// in many different ways, like using a worklist. This pass |
410 | | /// makes arguments dead, but does not remove them. The existing |
411 | | /// dead argument elimination pass should be run after this to |
412 | | /// clean up the mess. |
413 | | /// |
414 | | /// In LLVM 12 and later, this instruction is replaced by the |
415 | | /// [`add_instruction_simplify_pass`]. |
416 | | #[cfg(feature = "llvm11-0")] |
417 | | pub fn add_ip_constant_propagation_pass(&self) { |
418 | | unsafe { LLVMAddIPConstantPropagationPass(self.pass_manager) } |
419 | | } |
420 | | |
421 | | /// This file implements a simple interprocedural pass which |
422 | | /// walks the call-graph, turning invoke instructions into |
423 | | /// call instructions if and only if the callee cannot throw |
424 | | /// an exception. It implements this as a bottom-up traversal |
425 | | /// of the call-graph. |
426 | | #[llvm_versions(..=15)] |
427 | | pub fn add_prune_eh_pass(&self) { |
428 | | unsafe { LLVMAddPruneEHPass(self.pass_manager) } |
429 | | } |
430 | | |
431 | | /// An interprocedural variant of [Sparse Conditional Constant |
432 | | /// Propagation](https://llvm.org/docs/Passes.html#passes-sccp). |
433 | | #[llvm_versions(..=16)] |
434 | | pub fn add_ipsccp_pass(&self) { |
435 | | unsafe { LLVMAddIPSCCPPass(self.pass_manager) } |
436 | | } |
437 | | |
438 | | /// This pass loops over all of the functions in the input module, |
439 | | /// looking for a main function. If a main function is found, all |
440 | | /// other functions and all global variables with initializers are |
441 | | /// marked as internal. |
442 | | #[llvm_versions(..=16)] |
443 | | pub fn add_internalize_pass(&self, all_but_main: bool) { |
444 | | unsafe { LLVMAddInternalizePass(self.pass_manager, all_but_main as u32) } |
445 | | } |
446 | | |
447 | | /// This pass loops over all of the functions in the input module, |
448 | | /// looking for dead declarations and removes them. Dead declarations |
449 | | /// are declarations of functions for which no implementation is available |
450 | | /// (i.e., declarations for unused library functions). |
451 | | #[llvm_versions(..=16)] |
452 | | pub fn add_strip_dead_prototypes_pass(&self) { |
453 | | unsafe { LLVMAddStripDeadPrototypesPass(self.pass_manager) } |
454 | | } |
455 | | |
456 | | /// Performs code stripping. This transformation can delete: |
457 | | /// |
458 | | /// * Names for virtual registers |
459 | | /// * Symbols for internal globals and functions |
460 | | /// * Debug information |
461 | | /// |
462 | | /// Note that this transformation makes code much less readable, |
463 | | /// so it should only be used in situations where the strip utility |
464 | | /// would be used, such as reducing code size or making it harder |
465 | | /// to reverse engineer code. |
466 | | #[llvm_versions(..=16)] |
467 | | pub fn add_strip_symbol_pass(&self) { |
468 | | unsafe { LLVMAddStripSymbolsPass(self.pass_manager) } |
469 | | } |
470 | | |
471 | | /// No LLVM documentation is available at this time. |
472 | | #[llvm_versions(..=16)] |
473 | | pub fn add_loop_vectorize_pass(&self) { |
474 | | unsafe { LLVMAddLoopVectorizePass(self.pass_manager) } |
475 | | } |
476 | | |
477 | | /// No LLVM documentation is available at this time. |
478 | | #[llvm_versions(..=16)] |
479 | | pub fn add_slp_vectorize_pass(&self) { |
480 | | unsafe { LLVMAddSLPVectorizePass(self.pass_manager) } |
481 | | } |
482 | | |
483 | | /// ADCE aggressively tries to eliminate code. This pass is similar |
484 | | /// to [DCE](https://llvm.org/docs/Passes.html#passes-dce) but it |
485 | | /// assumes that values are dead until proven otherwise. This is |
486 | | /// similar to [SCCP](https://llvm.org/docs/Passes.html#passes-sccp), |
487 | | /// except applied to the liveness of values. |
488 | | #[llvm_versions(..=16)] |
489 | | pub fn add_aggressive_dce_pass(&self) { |
490 | | unsafe { LLVMAddAggressiveDCEPass(self.pass_manager) } |
491 | | } |
492 | | |
493 | | /// No LLVM documentation is available at this time. |
494 | | #[llvm_versions(..=16)] |
495 | | pub fn add_bit_tracking_dce_pass(&self) { |
496 | | unsafe { LLVMAddBitTrackingDCEPass(self.pass_manager) } |
497 | | } |
498 | | |
499 | | /// No LLVM documentation is available at this time. |
500 | | #[llvm_versions(..=16)] |
501 | | pub fn add_alignment_from_assumptions_pass(&self) { |
502 | | unsafe { LLVMAddAlignmentFromAssumptionsPass(self.pass_manager) } |
503 | | } |
504 | | |
505 | | /// Performs dead code elimination and basic block merging. Specifically: |
506 | | /// |
507 | | /// * Removes basic blocks with no predecessors. |
508 | | /// * Merges a basic block into its predecessor if there is only one and the predecessor only has one successor. |
509 | | /// * Eliminates PHI nodes for basic blocks with a single predecessor. |
510 | | /// * Eliminates a basic block that only contains an unconditional branch. |
511 | | #[llvm_versions(..=16)] |
512 | | pub fn add_cfg_simplification_pass(&self) { |
513 | | unsafe { LLVMAddCFGSimplificationPass(self.pass_manager) } |
514 | | } |
515 | | |
516 | | /// A trivial dead store elimination that only considers basic-block local redundant stores. |
517 | | #[llvm_versions(..=16)] |
518 | | pub fn add_dead_store_elimination_pass(&self) { |
519 | | unsafe { LLVMAddDeadStoreEliminationPass(self.pass_manager) } |
520 | | } |
521 | | |
522 | | /// No LLVM documentation is available at this time. |
523 | | #[llvm_versions(..=16)] |
524 | | pub fn add_scalarizer_pass(&self) { |
525 | | unsafe { LLVMAddScalarizerPass(self.pass_manager) } |
526 | | } |
527 | | |
528 | | /// No LLVM documentation is available at this time. |
529 | | #[llvm_versions(..=16)] |
530 | | pub fn add_merged_load_store_motion_pass(&self) { |
531 | | unsafe { LLVMAddMergedLoadStoreMotionPass(self.pass_manager) } |
532 | | } |
533 | | |
534 | | /// This pass performs global value numbering to eliminate |
535 | | /// fully and partially redundant instructions. It also |
536 | | /// performs redundant load elimination. |
537 | | #[llvm_versions(..=16)] |
538 | | pub fn add_gvn_pass(&self) { |
539 | | unsafe { LLVMAddGVNPass(self.pass_manager) } |
540 | | } |
541 | | |
542 | | /// This pass performs global value numbering to eliminate |
543 | | /// fully and partially redundant instructions. It also |
544 | | /// performs redundant load elimination. |
545 | | // REVIEW: Is `LLVMAddGVNPass` deprecated? Should we just seamlessly replace |
546 | | // the old one with this one in 4.0+? |
547 | | #[llvm_versions(..=16)] |
548 | | pub fn add_new_gvn_pass(&self) { |
549 | | use llvm_sys::transforms::scalar::LLVMAddNewGVNPass; |
550 | | |
551 | | unsafe { LLVMAddNewGVNPass(self.pass_manager) } |
552 | | } |
553 | | |
554 | | /// This transformation analyzes and transforms the induction variables (and |
555 | | /// computations derived from them) into simpler forms suitable for subsequent |
556 | | /// analysis and transformation. |
557 | | /// |
558 | | /// This transformation makes the following changes to each loop with an |
559 | | /// identifiable induction variable: |
560 | | /// |
561 | | /// * All loops are transformed to have a single canonical induction variable |
562 | | /// which starts at zero and steps by one. |
563 | | /// |
564 | | /// * The canonical induction variable is guaranteed to be the first PHI node |
565 | | /// in the loop header block. |
566 | | /// |
567 | | /// * Any pointer arithmetic recurrences are raised to use array subscripts. |
568 | | /// |
569 | | /// If the trip count of a loop is computable, this pass also makes the |
570 | | /// following changes: |
571 | | /// |
572 | | /// * The exit condition for the loop is canonicalized to compare the induction |
573 | | /// value against the exit value. This turns loops like: |
574 | | /// |
575 | | /// ```c |
576 | | /// for (i = 7; i*i < 1000; ++i) |
577 | | /// ``` |
578 | | /// into |
579 | | /// ```c |
580 | | /// for (i = 0; i != 25; ++i) |
581 | | /// ``` |
582 | | /// |
583 | | /// * Any use outside of the loop of an expression derived from the indvar is |
584 | | /// changed to compute the derived value outside of the loop, eliminating the |
585 | | /// dependence on the exit value of the induction variable. If the only purpose |
586 | | /// of the loop is to compute the exit value of some derived expression, this |
587 | | /// transformation will make the loop dead. |
588 | | /// |
589 | | /// This transformation should be followed by strength reduction after all of |
590 | | /// the desired loop transformations have been performed. Additionally, on |
591 | | /// targets where it is profitable, the loop could be transformed to count |
592 | | /// down to zero (the "do loop" optimization). |
593 | | #[llvm_versions(..=16)] |
594 | | pub fn add_ind_var_simplify_pass(&self) { |
595 | | unsafe { LLVMAddIndVarSimplifyPass(self.pass_manager) } |
596 | | } |
597 | | |
598 | | /// Combine instructions to form fewer, simple instructions. This pass |
599 | | /// does not modify the CFG. This pass is where algebraic simplification happens. |
600 | | /// |
601 | | /// This pass combines things like: |
602 | | /// |
603 | | /// ```c |
604 | | /// %Y = add i32 %X, 1 |
605 | | /// %Z = add i32 %Y, 1 |
606 | | /// ``` |
607 | | /// into: |
608 | | /// ```c |
609 | | /// %Z = add i32 %X, 2 |
610 | | /// ``` |
611 | | /// |
612 | | /// This is a simple worklist driven algorithm. |
613 | | /// |
614 | | /// This pass guarantees that the following canonicalization are performed |
615 | | /// on the program: |
616 | | /// |
617 | | /// 1. If a binary operator has a constant operand, it is moved to the |
618 | | /// right-hand side. |
619 | | /// |
620 | | /// 2. Bitwise operators with constant operands are always grouped so that |
621 | | /// shifts are performed first, then ORs, then ANDs, then XORs. |
622 | | /// |
623 | | /// 3. Compare instructions are converted from <, >, ≤, or ≥ to = or ≠ if possible. |
624 | | /// |
625 | | /// 4. All cmp instructions on boolean values are replaced with logical operations. |
626 | | /// |
627 | | /// 5. add X, X is represented as mul X, 2 ⇒ shl X, 1 |
628 | | /// |
629 | | /// 6. Multiplies with a constant power-of-two argument are transformed into shifts. |
630 | | /// |
631 | | /// 7. ... etc. |
632 | | /// |
633 | | /// This pass can also simplify calls to specific well-known function calls |
634 | | /// (e.g. runtime library functions). For example, a call exit(3) that occurs within |
635 | | /// the main() function can be transformed into simply return 3. Whether or not library |
636 | | /// calls are simplified is controlled by the [-functionattrs](https://llvm.org/docs/Passes.html#passes-functionattrs) |
637 | | /// pass and LLVM’s knowledge of library calls on different targets. |
638 | | #[llvm_versions(..=16)] |
639 | | pub fn add_instruction_combining_pass(&self) { |
640 | | unsafe { LLVMAddInstructionCombiningPass(self.pass_manager) } |
641 | | } |
642 | | |
643 | | /// Jump threading tries to find distinct threads of control flow |
644 | | /// running through a basic block. This pass looks at blocks that |
645 | | /// have multiple predecessors and multiple successors. If one or |
646 | | /// more of the predecessors of the block can be proven to always |
647 | | /// cause a jump to one of the successors, we forward the edge from |
648 | | /// the predecessor to the successor by duplicating the contents of |
649 | | /// this block. |
650 | | /// |
651 | | /// An example of when this can occur is code like this: |
652 | | /// |
653 | | /// ```c |
654 | | /// if () { ... |
655 | | /// X = 4; |
656 | | /// } |
657 | | /// if (X < 3) { |
658 | | /// ``` |
659 | | /// |
660 | | /// In this case, the unconditional branch at the end of the first |
661 | | /// if can be revectored to the false side of the second if. |
662 | | #[llvm_versions(..=16)] |
663 | | pub fn add_jump_threading_pass(&self) { |
664 | | unsafe { LLVMAddJumpThreadingPass(self.pass_manager) } |
665 | | } |
666 | | |
667 | | /// This pass performs loop invariant code motion, |
668 | | /// attempting to remove as much code from the body of |
669 | | /// a loop as possible. It does this by either hoisting |
670 | | /// code into the preheader block, or by sinking code to |
671 | | /// the exit blocks if it is safe. This pass also promotes |
672 | | /// must-aliased memory locations in the loop to live in |
673 | | /// registers, thus hoisting and sinking “invariant” loads |
674 | | /// and stores. |
675 | | /// |
676 | | /// This pass uses alias analysis for two purposes: |
677 | | /// |
678 | | /// 1. Moving loop invariant loads and calls out of loops. |
679 | | /// If we can determine that a load or call inside of a |
680 | | /// loop never aliases anything stored to, we can hoist |
681 | | /// it or sink it like any other instruction. |
682 | | /// |
683 | | /// 2. Scalar Promotion of Memory. If there is a store |
684 | | /// instruction inside of the loop, we try to move the |
685 | | /// store to happen AFTER the loop instead of inside of |
686 | | /// the loop. This can only happen if a few conditions |
687 | | /// are true: |
688 | | /// |
689 | | /// 1. The pointer stored through is loop invariant. |
690 | | /// |
691 | | /// 2. There are no stores or loads in the loop |
692 | | /// which may alias the pointer. There are no calls in |
693 | | /// the loop which mod/ref the pointer. |
694 | | /// |
695 | | /// If these conditions are true, we can promote the loads |
696 | | /// and stores in the loop of the pointer to use a temporary |
697 | | /// alloca'd variable. We then use the mem2reg functionality |
698 | | /// to construct the appropriate SSA form for the variable. |
699 | | #[llvm_versions(..=16)] |
700 | | pub fn add_licm_pass(&self) { |
701 | | unsafe { LLVMAddLICMPass(self.pass_manager) } |
702 | | } |
703 | | |
704 | | /// This file implements the Dead Loop Deletion Pass. |
705 | | /// This pass is responsible for eliminating loops with |
706 | | /// non-infinite computable trip counts that have no side |
707 | | /// effects or volatile instructions, and do not contribute |
708 | | /// to the computation of the function’s return value. |
709 | | #[llvm_versions(..=16)] |
710 | | pub fn add_loop_deletion_pass(&self) { |
711 | | unsafe { LLVMAddLoopDeletionPass(self.pass_manager) } |
712 | | } |
713 | | |
714 | | /// No LLVM documentation is available at this time. |
715 | | #[llvm_versions(..=16)] |
716 | | pub fn add_loop_idiom_pass(&self) { |
717 | | unsafe { LLVMAddLoopIdiomPass(self.pass_manager) } |
718 | | } |
719 | | |
720 | | /// A simple loop rotation transformation. |
721 | | #[llvm_versions(..=16)] |
722 | | pub fn add_loop_rotate_pass(&self) { |
723 | | unsafe { LLVMAddLoopRotatePass(self.pass_manager) } |
724 | | } |
725 | | |
726 | | /// No LLVM documentation is available at this time. |
727 | | #[llvm_versions(..=16)] |
728 | | pub fn add_loop_reroll_pass(&self) { |
729 | | unsafe { LLVMAddLoopRerollPass(self.pass_manager) } |
730 | | } |
731 | | |
732 | | /// This pass implements a simple loop unroller. |
733 | | /// It works best when loops have been canonicalized |
734 | | /// by the [indvars](https://llvm.org/docs/Passes.html#passes-indvars) |
735 | | /// pass, allowing it to determine the trip counts |
736 | | /// of loops easily. |
737 | | #[llvm_versions(..=16)] |
738 | | pub fn add_loop_unroll_pass(&self) { |
739 | | unsafe { LLVMAddLoopUnrollPass(self.pass_manager) } |
740 | | } |
741 | | |
742 | | /// This pass transforms loops that contain branches on |
743 | | /// loop-invariant conditions to have multiple loops. |
744 | | /// For example, it turns the left into the right code: |
745 | | /// |
746 | | /// ```c |
747 | | /// for (...) if (lic) |
748 | | /// A for (...) |
749 | | /// if (lic) A; B; C |
750 | | /// B else |
751 | | /// C for (...) |
752 | | /// A; C |
753 | | /// ``` |
754 | | /// |
755 | | /// This can increase the size of the code exponentially |
756 | | /// (doubling it every time a loop is unswitched) so we |
757 | | /// only unswitch if the resultant code will be smaller |
758 | | /// than a threshold. |
759 | | /// |
760 | | /// This pass expects [LICM](https://llvm.org/docs/Passes.html#passes-licm) |
761 | | /// to be run before it to hoist invariant conditions |
762 | | /// out of the loop, to make the unswitching opportunity |
763 | | /// obvious. |
764 | | #[llvm_versions(..=14)] |
765 | | pub fn add_loop_unswitch_pass(&self) { |
766 | | use llvm_sys::transforms::scalar::LLVMAddLoopUnswitchPass; |
767 | | |
768 | | unsafe { LLVMAddLoopUnswitchPass(self.pass_manager) } |
769 | | } |
770 | | |
771 | | /// This pass performs various transformations related |
772 | | /// to eliminating memcpy calls, or transforming sets |
773 | | /// of stores into memsets. |
774 | | #[llvm_versions(..=16)] |
775 | | pub fn add_memcpy_optimize_pass(&self) { |
776 | | unsafe { LLVMAddMemCpyOptPass(self.pass_manager) } |
777 | | } |
778 | | |
779 | | /// This pass performs partial inlining, typically by inlining |
780 | | /// an if statement that surrounds the body of the function. |
781 | | #[llvm_versions(..=16)] |
782 | | pub fn add_partially_inline_lib_calls_pass(&self) { |
783 | | unsafe { LLVMAddPartiallyInlineLibCallsPass(self.pass_manager) } |
784 | | } |
785 | | |
786 | | /// Rewrites switch instructions with a sequence of branches, |
787 | | /// which allows targets to get away with not implementing the |
788 | | /// switch instruction until it is convenient. |
789 | | #[llvm_versions(..=16)] |
790 | | pub fn add_lower_switch_pass(&self) { |
791 | | use llvm_sys::transforms::util::LLVMAddLowerSwitchPass; |
792 | | |
793 | | unsafe { LLVMAddLowerSwitchPass(self.pass_manager) } |
794 | | } |
795 | | |
796 | | /// This file promotes memory references to be register references. |
797 | | /// It promotes alloca instructions which only have loads and stores |
798 | | /// as uses. An alloca is transformed by using dominator frontiers |
799 | | /// to place phi nodes, then traversing the function in depth-first |
800 | | /// order to rewrite loads and stores as appropriate. This is just |
801 | | /// the standard SSA construction algorithm to construct "pruned" SSA form. |
802 | | #[llvm_versions(..=16)] |
803 | | pub fn add_promote_memory_to_register_pass(&self) { |
804 | | use llvm_sys::transforms::util::LLVMAddPromoteMemoryToRegisterPass; |
805 | | |
806 | | unsafe { LLVMAddPromoteMemoryToRegisterPass(self.pass_manager) } |
807 | | } |
808 | | |
809 | | /// This pass reassociates commutative expressions in an order that is designed |
810 | | /// to promote better constant propagation, GCSE, LICM, PRE, etc. |
811 | | /// |
812 | | /// For example: 4 + (x + 5) ⇒ x + (4 + 5) |
813 | | /// |
814 | | /// In the implementation of this algorithm, constants are assigned rank = 0, |
815 | | /// function arguments are rank = 1, and other values are assigned ranks |
816 | | /// corresponding to the reverse post order traversal of current function |
817 | | /// (starting at 2), which effectively gives values in deep loops higher |
818 | | /// rank than values not in loops. |
819 | | #[llvm_versions(..=16)] |
820 | | pub fn add_reassociate_pass(&self) { |
821 | | unsafe { LLVMAddReassociatePass(self.pass_manager) } |
822 | | } |
823 | | |
824 | | /// Sparse conditional constant propagation and merging, which can |
825 | | /// be summarized as: |
826 | | /// |
827 | | /// * Assumes values are constant unless proven otherwise |
828 | | /// * Assumes BasicBlocks are dead unless proven otherwise |
829 | | /// * Proves values to be constant, and replaces them with constants |
830 | | /// * Proves conditional branches to be unconditional |
831 | | /// |
832 | | /// Note that this pass has a habit of making definitions be dead. |
833 | | /// It is a good idea to run a DCE pass sometime after running this pass. |
834 | | #[llvm_versions(..=16)] |
835 | | pub fn add_sccp_pass(&self) { |
836 | | unsafe { LLVMAddSCCPPass(self.pass_manager) } |
837 | | } |
838 | | |
839 | | /// No LLVM documentation is available at this time. |
840 | | #[llvm_versions(..=16)] |
841 | | pub fn add_scalar_repl_aggregates_pass(&self) { |
842 | | unsafe { LLVMAddScalarReplAggregatesPass(self.pass_manager) } |
843 | | } |
844 | | |
845 | | /// The well-known scalar replacement of aggregates transformation. |
846 | | /// This transform breaks up alloca instructions of aggregate type |
847 | | /// (structure or array) into individual alloca instructions for each |
848 | | /// member if possible. Then, if possible, it transforms the individual |
849 | | /// alloca instructions into nice clean scalar SSA form. |
850 | | #[llvm_versions(..=16)] |
851 | | pub fn add_scalar_repl_aggregates_pass_ssa(&self) { |
852 | | unsafe { LLVMAddScalarReplAggregatesPassSSA(self.pass_manager) } |
853 | | } |
854 | | |
855 | | /// No LLVM documentation is available at this time. |
856 | | #[llvm_versions(..=16)] |
857 | | pub fn add_scalar_repl_aggregates_pass_with_threshold(&self, threshold: i32) { |
858 | | unsafe { LLVMAddScalarReplAggregatesPassWithThreshold(self.pass_manager, threshold) } |
859 | | } |
860 | | |
861 | | /// No LLVM documentation is available at this time. |
862 | | #[llvm_versions(..=16)] |
863 | | pub fn add_simplify_lib_calls_pass(&self) { |
864 | | unsafe { LLVMAddSimplifyLibCallsPass(self.pass_manager) } |
865 | | } |
866 | | |
867 | | /// This file transforms calls of the current function (self recursion) followed |
868 | | /// by a return instruction with a branch to the entry of the function, creating |
869 | | /// a loop. This pass also implements the following extensions to the basic algorithm: |
870 | | /// |
871 | | /// 1. Trivial instructions between the call and return do not prevent the |
872 | | /// transformation from taking place, though currently the analysis cannot support |
873 | | /// moving any really useful instructions (only dead ones). |
874 | | /// |
875 | | /// 2. This pass transforms functions that are prevented from being tail |
876 | | /// recursive by an associative expression to use an accumulator variable, thus |
877 | | /// compiling the typical naive factorial or fib implementation into efficient code. |
878 | | /// |
879 | | /// 3. TRE is performed if the function returns void, if the return returns |
880 | | /// the result returned by the call, or if the function returns a run-time constant |
881 | | /// on all exits from the function. It is possible, though unlikely, that the return |
882 | | /// returns something else (like constant 0), and can still be TRE’d. It can be |
883 | | /// TRE'd if all other return instructions in the function return the exact same value. |
884 | | /// |
885 | | /// 4. If it can prove that callees do not access their caller stack frame, |
886 | | /// they are marked as eligible for tail call elimination (by the code generator). |
887 | | #[llvm_versions(..=16)] |
888 | | pub fn add_tail_call_elimination_pass(&self) { |
889 | | unsafe { LLVMAddTailCallEliminationPass(self.pass_manager) } |
890 | | } |
891 | | |
892 | | /// This pass implements constant propagation and merging. It looks for instructions |
893 | | /// involving only constant operands and replaces them with a constant value instead |
894 | | /// of an instruction. For example: |
895 | | /// |
896 | | /// ```ir |
897 | | /// add i32 1, 2 |
898 | | /// ``` |
899 | | /// |
900 | | /// becomes |
901 | | /// |
902 | | /// ```ir |
903 | | /// i32 3 |
904 | | /// ``` |
905 | | /// |
906 | | /// NOTE: this pass has a habit of making definitions be dead. It is a good idea to |
907 | | /// run a Dead Instruction Elimination pass sometime after running this pass. |
908 | | /// |
909 | | /// In LLVM 12 and later, this instruction is replaced by the |
910 | | /// [`add_instruction_simplify_pass`]. |
911 | | #[cfg(feature = "llvm11-0")] |
912 | | pub fn add_constant_propagation_pass(&self) { |
913 | | unsafe { LLVMAddConstantPropagationPass(self.pass_manager) } |
914 | | } |
915 | | |
916 | | /// This pass implements constant propagation and merging. It looks for instructions |
917 | | /// involving only constant operands and replaces them with a constant value instead |
918 | | /// of an instruction. For example: |
919 | | /// |
920 | | /// ```ir |
921 | | /// add i32 1, 2 |
922 | | /// ``` |
923 | | /// |
924 | | /// becomes |
925 | | /// |
926 | | /// ```ir |
927 | | /// i32 3 |
928 | | /// ``` |
929 | | /// |
930 | | /// NOTE: this pass has a habit of making definitions be dead. It is a good idea to |
931 | | /// run a Dead Instruction Elimination pass sometime after running this pass. |
932 | | #[llvm_versions(12..=16)] |
933 | | pub fn add_instruction_simplify_pass(&self) { |
934 | | unsafe { LLVMAddInstructionSimplifyPass(self.pass_manager) } |
935 | | } |
936 | | |
937 | | /// This file promotes memory references to be register references. |
938 | | /// It promotes alloca instructions which only have loads and stores |
939 | | /// as uses. An alloca is transformed by using dominator frontiers to |
940 | | /// place phi nodes, then traversing the function in depth-first order to |
941 | | /// rewrite loads and stores as appropriate. This is just the standard SSA |
942 | | /// construction algorithm to construct “pruned” SSA form. |
943 | | #[llvm_versions(..=16)] |
944 | | pub fn add_demote_memory_to_register_pass(&self) { |
945 | | unsafe { LLVMAddDemoteMemoryToRegisterPass(self.pass_manager) } |
946 | | } |
947 | | |
948 | | /// Verifies an LLVM IR code. This is useful to run after an optimization |
949 | | /// which is undergoing testing. Note that llvm-as verifies its input before |
950 | | /// emitting bitcode, and also that malformed bitcode is likely to make |
951 | | /// LLVM crash. All language front-ends are therefore encouraged to verify |
952 | | /// their output before performing optimizing transformations. |
953 | | /// |
954 | | /// 1. Both of a binary operator’s parameters are of the same type. |
955 | | /// |
956 | | /// 2. Verify that the indices of mem access instructions match other operands. |
957 | | /// |
958 | | /// 3. Verify that arithmetic and other things are only performed on |
959 | | /// first-class types. Verify that shifts and logicals only happen on |
960 | | /// integrals f.e. |
961 | | /// |
962 | | /// 4. All of the constants in a switch statement are of the correct type. |
963 | | /// |
964 | | /// 5. The code is in valid SSA form. |
965 | | /// |
966 | | /// 6. It is illegal to put a label into any other type (like a structure) |
967 | | /// or to return one. |
968 | | /// |
969 | | /// 7. Only phi nodes can be self referential: %x = add i32 %x, %x is invalid. |
970 | | /// |
971 | | /// 8. PHI nodes must have an entry for each predecessor, with no extras. |
972 | | /// |
973 | | /// 9. PHI nodes must be the first thing in a basic block, all grouped together. |
974 | | /// |
975 | | /// 10. PHI nodes must have at least one entry. |
976 | | /// |
977 | | /// 11. All basic blocks should only end with terminator insts, not contain them. |
978 | | /// |
979 | | /// 12. The entry node to a function must not have predecessors. |
980 | | /// |
981 | | /// 13. All Instructions must be embedded into a basic block. |
982 | | /// |
983 | | /// 14. Functions cannot take a void-typed parameter. |
984 | | /// |
985 | | /// 15. Verify that a function’s argument list agrees with its declared type. |
986 | | /// |
987 | | /// 16. It is illegal to specify a name for a void value. |
988 | | /// |
989 | | /// 17. It is illegal to have an internal global value with no initializer. |
990 | | /// |
991 | | /// 18. It is illegal to have a ret instruction that returns a value that does |
992 | | /// not agree with the function return value type. |
993 | | /// |
994 | | /// 19. Function call argument types match the function prototype. |
995 | | /// |
996 | | /// 20. All other things that are tested by asserts spread about the code. |
997 | | /// |
998 | | /// Note that this does not provide full security verification (like Java), but instead just tries to ensure that code is well-formed. |
999 | | #[llvm_versions(..=16)] |
1000 | | pub fn add_verifier_pass(&self) { |
1001 | | unsafe { LLVMAddVerifierPass(self.pass_manager) } |
1002 | | } |
1003 | | |
1004 | | /// No LLVM documentation is available at this time. |
1005 | | #[llvm_versions(..=16)] |
1006 | | pub fn add_correlated_value_propagation_pass(&self) { |
1007 | | unsafe { LLVMAddCorrelatedValuePropagationPass(self.pass_manager) } |
1008 | | } |
1009 | | |
1010 | | /// No LLVM documentation is available at this time. |
1011 | | #[llvm_versions(..=16)] |
1012 | | pub fn add_early_cse_pass(&self) { |
1013 | | unsafe { LLVMAddEarlyCSEPass(self.pass_manager) } |
1014 | | } |
1015 | | |
1016 | | #[llvm_versions(..=16)] |
1017 | | /// No LLVM documentation is available at this time. |
1018 | | pub fn add_early_cse_mem_ssa_pass(&self) { |
1019 | | use llvm_sys::transforms::scalar::LLVMAddEarlyCSEMemSSAPass; |
1020 | | |
1021 | | unsafe { LLVMAddEarlyCSEMemSSAPass(self.pass_manager) } |
1022 | | } |
1023 | | |
1024 | | /// No LLVM documentation is available at this time. |
1025 | | #[llvm_versions(..=16)] |
1026 | | pub fn add_lower_expect_intrinsic_pass(&self) { |
1027 | | unsafe { LLVMAddLowerExpectIntrinsicPass(self.pass_manager) } |
1028 | | } |
1029 | | |
1030 | | /// No LLVM documentation is available at this time. |
1031 | | #[llvm_versions(..=16)] |
1032 | | pub fn add_type_based_alias_analysis_pass(&self) { |
1033 | | unsafe { LLVMAddTypeBasedAliasAnalysisPass(self.pass_manager) } |
1034 | | } |
1035 | | |
1036 | | /// No LLVM documentation is available at this time. |
1037 | | #[llvm_versions(..=16)] |
1038 | | pub fn add_scoped_no_alias_aa_pass(&self) { |
1039 | | unsafe { LLVMAddScopedNoAliasAAPass(self.pass_manager) } |
1040 | | } |
1041 | | |
1042 | | /// A basic alias analysis pass that implements identities |
1043 | | /// (two different globals cannot alias, etc), but does no |
1044 | | /// stateful analysis. |
1045 | | #[llvm_versions(..=16)] |
1046 | | pub fn add_basic_alias_analysis_pass(&self) { |
1047 | | unsafe { LLVMAddBasicAliasAnalysisPass(self.pass_manager) } |
1048 | | } |
1049 | | |
1050 | | #[llvm_versions(..=15)] |
1051 | | pub fn add_aggressive_inst_combiner_pass(&self) { |
1052 | | unsafe { LLVMAddAggressiveInstCombinerPass(self.pass_manager) } |
1053 | | } |
1054 | | |
1055 | | #[llvm_versions(..=16)] |
1056 | | pub fn add_loop_unroll_and_jam_pass(&self) { |
1057 | | use llvm_sys::transforms::scalar::LLVMAddLoopUnrollAndJamPass; |
1058 | | |
1059 | | unsafe { LLVMAddLoopUnrollAndJamPass(self.pass_manager) } |
1060 | | } |
1061 | | |
1062 | | #[llvm_versions(..15)] |
1063 | | pub fn add_coroutine_early_pass(&self) { |
1064 | | use llvm_sys::transforms::coroutines::LLVMAddCoroEarlyPass; |
1065 | | |
1066 | | unsafe { LLVMAddCoroEarlyPass(self.pass_manager) } |
1067 | | } |
1068 | | |
1069 | | #[llvm_versions(..15)] |
1070 | | pub fn add_coroutine_split_pass(&self) { |
1071 | | use llvm_sys::transforms::coroutines::LLVMAddCoroSplitPass; |
1072 | | |
1073 | | unsafe { LLVMAddCoroSplitPass(self.pass_manager) } |
1074 | | } |
1075 | | |
1076 | | #[llvm_versions(..15)] |
1077 | | pub fn add_coroutine_elide_pass(&self) { |
1078 | | use llvm_sys::transforms::coroutines::LLVMAddCoroElidePass; |
1079 | | |
1080 | | unsafe { LLVMAddCoroElidePass(self.pass_manager) } |
1081 | | } |
1082 | | |
1083 | | #[llvm_versions(..15)] |
1084 | | pub fn add_coroutine_cleanup_pass(&self) { |
1085 | | use llvm_sys::transforms::coroutines::LLVMAddCoroCleanupPass; |
1086 | | |
1087 | | unsafe { LLVMAddCoroCleanupPass(self.pass_manager) } |
1088 | | } |
1089 | | } |
1090 | | |
1091 | | impl<T> Drop for PassManager<T> { |
1092 | 0 | fn drop(&mut self) { |
1093 | 0 | unsafe { LLVMDisposePassManager(self.pass_manager) } |
1094 | 0 | } |
1095 | | } |
1096 | | |
1097 | | #[llvm_versions(..=16)] |
1098 | | #[derive(Debug)] |
1099 | | pub struct PassRegistry { |
1100 | | pass_registry: LLVMPassRegistryRef, |
1101 | | } |
1102 | | |
1103 | | #[llvm_versions(..=16)] |
1104 | | impl PassRegistry { |
1105 | | pub unsafe fn new(pass_registry: LLVMPassRegistryRef) -> PassRegistry { |
1106 | | assert!(!pass_registry.is_null()); |
1107 | | |
1108 | | PassRegistry { pass_registry } |
1109 | | } |
1110 | | |
1111 | | /// Acquires the underlying raw pointer belonging to this `PassRegistry` type. |
1112 | | pub fn as_mut_ptr(&self) -> LLVMPassRegistryRef { |
1113 | | self.pass_registry |
1114 | | } |
1115 | | |
1116 | | pub fn get_global() -> PassRegistry { |
1117 | | let pass_registry = unsafe { LLVMGetGlobalPassRegistry() }; |
1118 | | |
1119 | | unsafe { PassRegistry::new(pass_registry) } |
1120 | | } |
1121 | | |
1122 | | pub fn initialize_core(&self) { |
1123 | | unsafe { LLVMInitializeCore(self.pass_registry) } |
1124 | | } |
1125 | | |
1126 | | pub fn initialize_transform_utils(&self) { |
1127 | | unsafe { LLVMInitializeTransformUtils(self.pass_registry) } |
1128 | | } |
1129 | | |
1130 | | pub fn initialize_scalar_opts(&self) { |
1131 | | unsafe { LLVMInitializeScalarOpts(self.pass_registry) } |
1132 | | } |
1133 | | |
1134 | | #[llvm_versions(..=15)] |
1135 | | pub fn initialize_obj_carc_opts(&self) { |
1136 | | unsafe { LLVMInitializeObjCARCOpts(self.pass_registry) } |
1137 | | } |
1138 | | |
1139 | | pub fn initialize_vectorization(&self) { |
1140 | | unsafe { LLVMInitializeVectorization(self.pass_registry) } |
1141 | | } |
1142 | | |
1143 | | pub fn initialize_inst_combine(&self) { |
1144 | | unsafe { LLVMInitializeInstCombine(self.pass_registry) } |
1145 | | } |
1146 | | |
1147 | | // Let us begin our initial public offering |
1148 | | pub fn initialize_ipo(&self) { |
1149 | | unsafe { LLVMInitializeIPO(self.pass_registry) } |
1150 | | } |
1151 | | |
1152 | | #[llvm_versions(..=15)] |
1153 | | pub fn initialize_instrumentation(&self) { |
1154 | | unsafe { LLVMInitializeInstrumentation(self.pass_registry) } |
1155 | | } |
1156 | | |
1157 | | pub fn initialize_analysis(&self) { |
1158 | | unsafe { LLVMInitializeAnalysis(self.pass_registry) } |
1159 | | } |
1160 | | |
1161 | | pub fn initialize_ipa(&self) { |
1162 | | unsafe { LLVMInitializeIPA(self.pass_registry) } |
1163 | | } |
1164 | | |
1165 | | pub fn initialize_codegen(&self) { |
1166 | | unsafe { LLVMInitializeCodeGen(self.pass_registry) } |
1167 | | } |
1168 | | |
1169 | | pub fn initialize_target(&self) { |
1170 | | unsafe { LLVMInitializeTarget(self.pass_registry) } |
1171 | | } |
1172 | | |
1173 | | #[llvm_versions(..=15)] |
1174 | | pub fn initialize_aggressive_inst_combiner(&self) { |
1175 | | use llvm_sys::initialization::LLVMInitializeAggressiveInstCombiner; |
1176 | | |
1177 | | unsafe { LLVMInitializeAggressiveInstCombiner(self.pass_registry) } |
1178 | | } |
1179 | | } |
1180 | | |
1181 | | #[llvm_versions(13..)] |
1182 | | #[derive(Debug)] |
1183 | | pub struct PassBuilderOptions { |
1184 | | pub(crate) options_ref: LLVMPassBuilderOptionsRef, |
1185 | | } |
1186 | | |
1187 | | #[llvm_versions(13..)] |
1188 | | impl PassBuilderOptions { |
1189 | | /// Create a new set of options for a PassBuilder |
1190 | 129k | pub fn create() -> Self { |
1191 | | unsafe { |
1192 | 129k | PassBuilderOptions { |
1193 | 129k | options_ref: LLVMCreatePassBuilderOptions(), |
1194 | 129k | } |
1195 | | } |
1196 | 129k | } |
1197 | | |
1198 | | /// Acquires the underlying raw pointer belonging to this `PassBuilderOptions` type. |
1199 | 0 | pub fn as_mut_ptr(&self) -> LLVMPassBuilderOptionsRef { |
1200 | 0 | self.options_ref |
1201 | 0 | } |
1202 | | |
1203 | | ///Toggle adding the VerifierPass for the PassBuilder, ensuring all functions inside the module is valid. |
1204 | 0 | pub fn set_verify_each(&self, value: bool) { |
1205 | 0 | unsafe { |
1206 | 0 | LLVMPassBuilderOptionsSetVerifyEach(self.options_ref, value as i32); |
1207 | 0 | } |
1208 | 0 | } |
1209 | | |
1210 | | ///Toggle debug logging when running the PassBuilder. |
1211 | 0 | pub fn set_debug_logging(&self, value: bool) { |
1212 | 0 | unsafe { |
1213 | 0 | LLVMPassBuilderOptionsSetDebugLogging(self.options_ref, value as i32); |
1214 | 0 | } |
1215 | 0 | } |
1216 | | |
1217 | 0 | pub fn set_loop_interleaving(&self, value: bool) { |
1218 | 0 | unsafe { |
1219 | 0 | LLVMPassBuilderOptionsSetLoopInterleaving(self.options_ref, value as i32); |
1220 | 0 | } |
1221 | 0 | } |
1222 | | |
1223 | 0 | pub fn set_loop_vectorization(&self, value: bool) { |
1224 | 0 | unsafe { |
1225 | 0 | LLVMPassBuilderOptionsSetLoopVectorization(self.options_ref, value as i32); |
1226 | 0 | } |
1227 | 0 | } |
1228 | | |
1229 | 0 | pub fn set_loop_slp_vectorization(&self, value: bool) { |
1230 | 0 | unsafe { |
1231 | 0 | LLVMPassBuilderOptionsSetSLPVectorization(self.options_ref, value as i32); |
1232 | 0 | } |
1233 | 0 | } |
1234 | | |
1235 | 0 | pub fn set_loop_unrolling(&self, value: bool) { |
1236 | 0 | unsafe { |
1237 | 0 | LLVMPassBuilderOptionsSetLoopUnrolling(self.options_ref, value as i32); |
1238 | 0 | } |
1239 | 0 | } |
1240 | | |
1241 | 0 | pub fn set_forget_all_scev_in_loop_unroll(&self, value: bool) { |
1242 | 0 | unsafe { |
1243 | 0 | LLVMPassBuilderOptionsSetForgetAllSCEVInLoopUnroll(self.options_ref, value as i32); |
1244 | 0 | } |
1245 | 0 | } |
1246 | | |
1247 | 0 | pub fn set_licm_mssa_opt_cap(&self, value: u32) { |
1248 | 0 | unsafe { |
1249 | 0 | LLVMPassBuilderOptionsSetLicmMssaOptCap(self.options_ref, value); |
1250 | 0 | } |
1251 | 0 | } |
1252 | | |
1253 | 0 | pub fn set_licm_mssa_no_acc_for_promotion_cap(&self, value: u32) { |
1254 | 0 | unsafe { |
1255 | 0 | LLVMPassBuilderOptionsSetLicmMssaNoAccForPromotionCap(self.options_ref, value); |
1256 | 0 | } |
1257 | 0 | } |
1258 | | |
1259 | 0 | pub fn set_call_graph_profile(&self, value: bool) { |
1260 | 0 | unsafe { |
1261 | 0 | LLVMPassBuilderOptionsSetCallGraphProfile(self.options_ref, value as i32); |
1262 | 0 | } |
1263 | 0 | } |
1264 | | |
1265 | 0 | pub fn set_merge_functions(&self, value: bool) { |
1266 | 0 | unsafe { |
1267 | 0 | LLVMPassBuilderOptionsSetMergeFunctions(self.options_ref, value as i32); |
1268 | 0 | } |
1269 | 0 | } |
1270 | | } |
1271 | | |
1272 | | #[llvm_versions(13..)] |
1273 | | impl Drop for PassBuilderOptions { |
1274 | 129k | fn drop(&mut self) { |
1275 | 129k | unsafe { |
1276 | 129k | LLVMDisposePassBuilderOptions(self.options_ref); |
1277 | 129k | } |
1278 | 129k | } |
1279 | | } |