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
74use crate::module::Module;
75use crate::values::{AsValueRef, FunctionValue};
76#[llvm_versions(..=16)]
77use crate::OptimizationLevel;
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 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)]
219impl 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
228pub 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
237impl PassManagerSubType for Module<'_> {
238 type Input = ();
239
240 unsafe fn create<I: Borrow<Self::Input>>(_: I) -> LLVMPassManagerRef {
241 LLVMCreatePassManager()
242 }
243
244 unsafe fn run_in_pass_manager(&self, pass_manager: &PassManager<Self>) -> bool {
245 LLVMRunPassManager(pass_manager.pass_manager, self.module.get()) == 1
246 }
247}
248
249// With GATs https://github.com/rust-lang/rust/issues/44265 this could be
250// type Input<'a> = &'a Module;
251impl<'ctx> PassManagerSubType for FunctionValue<'ctx> {
252 type Input = Module<'ctx>;
253
254 unsafe fn create<I: Borrow<Self::Input>>(input: I) -> LLVMPassManagerRef {
255 LLVMCreateFunctionPassManagerForModule(input.borrow().module.get())
256 }
257
258 unsafe fn run_in_pass_manager(&self, pass_manager: &PassManager<Self>) -> bool {
259 LLVMRunFunctionPassManager(pass_manager.pass_manager, self.as_value_ref()) == 1
260 }
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)]
268pub struct PassManager<T> {
269 pub(crate) pass_manager: LLVMPassManagerRef,
270 sub_type: PhantomData<T>,
271}
272
273impl PassManager<FunctionValue<'_>> {
274 /// Acquires the underlying raw pointer belonging to this `PassManager<T>` type.
275 pub fn as_mut_ptr(&self) -> LLVMPassManagerRef {
276 self.pass_manager
277 }
278
279 // return true means some pass modified the module, not an error occurred
280 pub fn initialize(&self) -> bool {
281 unsafe { LLVMInitializeFunctionPassManager(self.pass_manager) == 1 }
282 }
283
284 pub fn finalize(&self) -> bool {
285 unsafe { LLVMFinalizeFunctionPassManager(self.pass_manager) == 1 }
286 }
287}
288
289impl<T: PassManagerSubType> PassManager<T> {
290 pub unsafe fn new(pass_manager: LLVMPassManagerRef) -> Self {
291 assert!(!pass_manager.is_null());
292
293 PassManager {
294 pass_manager,
295 sub_type: PhantomData,
296 }
297 }
298
299 pub fn create<I: Borrow<T::Input>>(input: I) -> PassManager<T> {
300 let pass_manager = unsafe { T::create(input) };
301
302 unsafe { PassManager::new(pass_manager) }
303 }
304
305 /// This method returns true if any of the passes modified the function or module
306 /// and false otherwise.
307 pub fn run_on(&self, input: &T) -> bool {
308 unsafe { input.run_in_pass_manager(self) }
309 }
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
1091impl<T> Drop for PassManager<T> {
1092 fn drop(&mut self) {
1093 unsafe { LLVMDisposePassManager(self.pass_manager) }
1094 }
1095}
1096
1097#[llvm_versions(..=16)]
1098#[derive(Debug)]
1099pub struct PassRegistry {
1100 pass_registry: LLVMPassRegistryRef,
1101}
1102
1103#[llvm_versions(..=16)]
1104impl 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)]
1183pub struct PassBuilderOptions {
1184 pub(crate) options_ref: LLVMPassBuilderOptionsRef,
1185}
1186
1187#[llvm_versions(13..)]
1188impl PassBuilderOptions {
1189 /// Create a new set of options for a PassBuilder
1190 pub fn create() -> Self {
1191 unsafe {
1192 PassBuilderOptions {
1193 options_ref: LLVMCreatePassBuilderOptions(),
1194 }
1195 }
1196 }
1197
1198 /// Acquires the underlying raw pointer belonging to this `PassBuilderOptions` type.
1199 pub fn as_mut_ptr(&self) -> LLVMPassBuilderOptionsRef {
1200 self.options_ref
1201 }
1202
1203 ///Toggle adding the VerifierPass for the PassBuilder, ensuring all functions inside the module is valid.
1204 pub fn set_verify_each(&self, value: bool) {
1205 unsafe {
1206 LLVMPassBuilderOptionsSetVerifyEach(self.options_ref, value as i32);
1207 }
1208 }
1209
1210 ///Toggle debug logging when running the PassBuilder.
1211 pub fn set_debug_logging(&self, value: bool) {
1212 unsafe {
1213 LLVMPassBuilderOptionsSetDebugLogging(self.options_ref, value as i32);
1214 }
1215 }
1216
1217 pub fn set_loop_interleaving(&self, value: bool) {
1218 unsafe {
1219 LLVMPassBuilderOptionsSetLoopInterleaving(self.options_ref, value as i32);
1220 }
1221 }
1222
1223 pub fn set_loop_vectorization(&self, value: bool) {
1224 unsafe {
1225 LLVMPassBuilderOptionsSetLoopVectorization(self.options_ref, value as i32);
1226 }
1227 }
1228
1229 pub fn set_loop_slp_vectorization(&self, value: bool) {
1230 unsafe {
1231 LLVMPassBuilderOptionsSetSLPVectorization(self.options_ref, value as i32);
1232 }
1233 }
1234
1235 pub fn set_loop_unrolling(&self, value: bool) {
1236 unsafe {
1237 LLVMPassBuilderOptionsSetLoopUnrolling(self.options_ref, value as i32);
1238 }
1239 }
1240
1241 pub fn set_forget_all_scev_in_loop_unroll(&self, value: bool) {
1242 unsafe {
1243 LLVMPassBuilderOptionsSetForgetAllSCEVInLoopUnroll(self.options_ref, value as i32);
1244 }
1245 }
1246
1247 pub fn set_licm_mssa_opt_cap(&self, value: u32) {
1248 unsafe {
1249 LLVMPassBuilderOptionsSetLicmMssaOptCap(self.options_ref, value);
1250 }
1251 }
1252
1253 pub fn set_licm_mssa_no_acc_for_promotion_cap(&self, value: u32) {
1254 unsafe {
1255 LLVMPassBuilderOptionsSetLicmMssaNoAccForPromotionCap(self.options_ref, value);
1256 }
1257 }
1258
1259 pub fn set_call_graph_profile(&self, value: bool) {
1260 unsafe {
1261 LLVMPassBuilderOptionsSetCallGraphProfile(self.options_ref, value as i32);
1262 }
1263 }
1264
1265 pub fn set_merge_functions(&self, value: bool) {
1266 unsafe {
1267 LLVMPassBuilderOptionsSetMergeFunctions(self.options_ref, value as i32);
1268 }
1269 }
1270}
1271
1272#[llvm_versions(13..)]
1273impl Drop for PassBuilderOptions {
1274 fn drop(&mut self) {
1275 unsafe {
1276 LLVMDisposePassBuilderOptions(self.options_ref);
1277 }
1278 }
1279}