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