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