Skip to main content

inkwell/
passes.rs

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