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