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