Coverage Report

Created: 2026-03-26 07:41

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