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