Coverage Report

Created: 2026-03-26 07:41

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/cranelift-codegen-0.129.1/src/context.rs
Line
Count
Source
1
//! Cranelift compilation context and main entry point.
2
//!
3
//! When compiling many small functions, it is important to avoid repeatedly allocating and
4
//! deallocating the data structures needed for compilation. The `Context` struct is used to hold
5
//! on to memory allocations between function compilations.
6
//!
7
//! The context does not hold a `TargetIsa` instance which has to be provided as an argument
8
//! instead. This is because an ISA instance is immutable and can be used by multiple compilation
9
//! contexts concurrently. Typically, you would have one context per compilation thread and only a
10
//! single ISA instance.
11
12
use crate::alias_analysis::AliasAnalysis;
13
use crate::dominator_tree::DominatorTree;
14
use crate::egraph::EgraphPass;
15
use crate::flowgraph::ControlFlowGraph;
16
use crate::inline::{Inline, do_inlining};
17
use crate::ir::Function;
18
use crate::isa::TargetIsa;
19
use crate::legalizer::simple_legalize;
20
use crate::loop_analysis::LoopAnalysis;
21
use crate::machinst::{CompiledCode, CompiledCodeStencil};
22
use crate::nan_canonicalization::do_nan_canonicalization;
23
use crate::remove_constant_phis::do_remove_constant_phis;
24
use crate::result::{CodegenResult, CompileResult};
25
use crate::settings::{FlagsOrIsa, OptLevel};
26
use crate::trace;
27
use crate::unreachable_code::eliminate_unreachable_code;
28
use crate::verifier::{VerifierErrors, VerifierResult, verify_context};
29
use crate::{CompileError, timing};
30
#[cfg(feature = "souper-harvest")]
31
use alloc::string::String;
32
use alloc::vec::Vec;
33
use cranelift_control::ControlPlane;
34
use target_lexicon::Architecture;
35
36
#[cfg(feature = "souper-harvest")]
37
use crate::souper_harvest::do_souper_harvest;
38
39
/// Persistent data structures and compilation pipeline.
40
pub struct Context {
41
    /// The function we're compiling.
42
    pub func: Function,
43
44
    /// The control flow graph of `func`.
45
    pub cfg: ControlFlowGraph,
46
47
    /// Dominator tree for `func`.
48
    pub domtree: DominatorTree,
49
50
    /// Loop analysis of `func`.
51
    pub loop_analysis: LoopAnalysis,
52
53
    /// Result of MachBackend compilation, if computed.
54
    pub(crate) compiled_code: Option<CompiledCode>,
55
56
    /// Flag: do we want a disassembly with the CompiledCode?
57
    pub want_disasm: bool,
58
}
59
60
impl Context {
61
    /// Allocate a new compilation context.
62
    ///
63
    /// The returned instance should be reused for compiling multiple functions in order to avoid
64
    /// needless allocator thrashing.
65
198k
    pub fn new() -> Self {
66
198k
        Self::for_function(Function::new())
67
198k
    }
Unexecuted instantiation: <cranelift_codegen::context::Context>::new
<cranelift_codegen::context::Context>::new
Line
Count
Source
65
198k
    pub fn new() -> Self {
66
198k
        Self::for_function(Function::new())
67
198k
    }
68
69
    /// Allocate a new compilation context with an existing Function.
70
    ///
71
    /// The returned instance should be reused for compiling multiple functions in order to avoid
72
    /// needless allocator thrashing.
73
198k
    pub fn for_function(func: Function) -> Self {
74
198k
        Self {
75
198k
            func,
76
198k
            cfg: ControlFlowGraph::new(),
77
198k
            domtree: DominatorTree::new(),
78
198k
            loop_analysis: LoopAnalysis::new(),
79
198k
            compiled_code: None,
80
198k
            want_disasm: false,
81
198k
        }
82
198k
    }
Unexecuted instantiation: <cranelift_codegen::context::Context>::for_function
<cranelift_codegen::context::Context>::for_function
Line
Count
Source
73
198k
    pub fn for_function(func: Function) -> Self {
74
198k
        Self {
75
198k
            func,
76
198k
            cfg: ControlFlowGraph::new(),
77
198k
            domtree: DominatorTree::new(),
78
198k
            loop_analysis: LoopAnalysis::new(),
79
198k
            compiled_code: None,
80
198k
            want_disasm: false,
81
198k
        }
82
198k
    }
83
84
    /// Clear all data structures in this context.
85
0
    pub fn clear(&mut self) {
86
0
        self.func.clear();
87
0
        self.cfg.clear();
88
0
        self.domtree.clear();
89
0
        self.loop_analysis.clear();
90
0
        self.compiled_code = None;
91
0
        self.want_disasm = false;
92
0
    }
Unexecuted instantiation: <cranelift_codegen::context::Context>::clear
Unexecuted instantiation: <cranelift_codegen::context::Context>::clear
93
94
    /// Returns the compilation result for this function, available after any `compile` function
95
    /// has been called.
96
318k
    pub fn compiled_code(&self) -> Option<&CompiledCode> {
97
318k
        self.compiled_code.as_ref()
98
318k
    }
Unexecuted instantiation: <cranelift_codegen::context::Context>::compiled_code
<cranelift_codegen::context::Context>::compiled_code
Line
Count
Source
96
318k
    pub fn compiled_code(&self) -> Option<&CompiledCode> {
97
318k
        self.compiled_code.as_ref()
98
318k
    }
99
100
    /// Returns the compilation result for this function, available after any `compile` function
101
    /// has been called.
102
0
    pub fn take_compiled_code(&mut self) -> Option<CompiledCode> {
103
0
        self.compiled_code.take()
104
0
    }
Unexecuted instantiation: <cranelift_codegen::context::Context>::take_compiled_code
Unexecuted instantiation: <cranelift_codegen::context::Context>::take_compiled_code
105
106
    /// Set the flag to request a disassembly when compiling with a
107
    /// `MachBackend` backend.
108
0
    pub fn set_disasm(&mut self, val: bool) {
109
0
        self.want_disasm = val;
110
0
    }
Unexecuted instantiation: <cranelift_codegen::context::Context>::set_disasm
Unexecuted instantiation: <cranelift_codegen::context::Context>::set_disasm
111
112
    /// Compile the function, and emit machine code into a `Vec<u8>`.
113
    #[deprecated = "use Context::compile"]
114
0
    pub fn compile_and_emit(
115
0
        &mut self,
116
0
        isa: &dyn TargetIsa,
117
0
        mem: &mut Vec<u8>,
118
0
        ctrl_plane: &mut ControlPlane,
119
0
    ) -> CompileResult<'_, &CompiledCode> {
120
0
        let compiled_code = self.compile(isa, ctrl_plane)?;
121
0
        mem.extend_from_slice(compiled_code.code_buffer());
122
0
        Ok(compiled_code)
123
0
    }
Unexecuted instantiation: <cranelift_codegen::context::Context>::compile_and_emit
Unexecuted instantiation: <cranelift_codegen::context::Context>::compile_and_emit
124
125
    /// Internally compiles the function into a stencil.
126
    ///
127
    /// Public only for testing and fuzzing purposes.
128
198k
    pub fn compile_stencil(
129
198k
        &mut self,
130
198k
        isa: &dyn TargetIsa,
131
198k
        ctrl_plane: &mut ControlPlane,
132
198k
    ) -> CodegenResult<CompiledCodeStencil> {
133
        let result;
134
198k
        trace!("****** START compiling {}", self.func.display_spec());
135
        {
136
198k
            let _tt = timing::compile();
137
138
198k
            self.verify_if(isa)?;
139
198k
            self.optimize(isa, ctrl_plane)?;
140
198k
            result = isa.compile_function(&self.func, &self.domtree, self.want_disasm, ctrl_plane);
141
        }
142
198k
        trace!("****** DONE compiling {}\n", self.func.display_spec());
143
198k
        result
144
198k
    }
Unexecuted instantiation: <cranelift_codegen::context::Context>::compile_stencil
<cranelift_codegen::context::Context>::compile_stencil
Line
Count
Source
128
198k
    pub fn compile_stencil(
129
198k
        &mut self,
130
198k
        isa: &dyn TargetIsa,
131
198k
        ctrl_plane: &mut ControlPlane,
132
198k
    ) -> CodegenResult<CompiledCodeStencil> {
133
        let result;
134
198k
        trace!("****** START compiling {}", self.func.display_spec());
135
        {
136
198k
            let _tt = timing::compile();
137
138
198k
            self.verify_if(isa)?;
139
198k
            self.optimize(isa, ctrl_plane)?;
140
198k
            result = isa.compile_function(&self.func, &self.domtree, self.want_disasm, ctrl_plane);
141
        }
142
198k
        trace!("****** DONE compiling {}\n", self.func.display_spec());
143
198k
        result
144
198k
    }
145
146
    /// Optimize the function, performing all compilation steps up to
147
    /// but not including machine-code lowering and register
148
    /// allocation.
149
    ///
150
    /// Public only for testing purposes.
151
198k
    pub fn optimize(
152
198k
        &mut self,
153
198k
        isa: &dyn TargetIsa,
154
198k
        ctrl_plane: &mut ControlPlane,
155
198k
    ) -> CodegenResult<()> {
156
198k
        log::debug!(
157
            "Number of CLIF instructions to optimize: {}",
158
0
            self.func.dfg.num_insts()
159
        );
160
198k
        log::debug!(
161
            "Number of CLIF blocks to optimize: {}",
162
0
            self.func.dfg.num_blocks()
163
        );
164
165
198k
        let opt_level = isa.flags().opt_level();
166
198k
        crate::trace!(
167
            "Optimizing (opt level {:?}):\n{}",
168
            opt_level,
169
0
            self.func.display()
170
        );
171
172
198k
        if isa.flags().enable_nan_canonicalization() {
173
198k
            self.canonicalize_nans(isa)?;
174
0
        }
175
176
198k
        self.legalize(isa)?;
177
178
198k
        self.compute_cfg();
179
198k
        self.compute_domtree();
180
198k
        self.eliminate_unreachable_code(isa)?;
181
198k
        self.remove_constant_phis(isa)?;
182
183
198k
        self.func.dfg.resolve_all_aliases();
184
185
198k
        if opt_level != OptLevel::None {
186
198k
            self.egraph_pass(isa, ctrl_plane)?;
187
0
        }
188
189
198k
        Ok(())
190
198k
    }
Unexecuted instantiation: <cranelift_codegen::context::Context>::optimize
<cranelift_codegen::context::Context>::optimize
Line
Count
Source
151
198k
    pub fn optimize(
152
198k
        &mut self,
153
198k
        isa: &dyn TargetIsa,
154
198k
        ctrl_plane: &mut ControlPlane,
155
198k
    ) -> CodegenResult<()> {
156
198k
        log::debug!(
157
            "Number of CLIF instructions to optimize: {}",
158
0
            self.func.dfg.num_insts()
159
        );
160
198k
        log::debug!(
161
            "Number of CLIF blocks to optimize: {}",
162
0
            self.func.dfg.num_blocks()
163
        );
164
165
198k
        let opt_level = isa.flags().opt_level();
166
198k
        crate::trace!(
167
            "Optimizing (opt level {:?}):\n{}",
168
            opt_level,
169
0
            self.func.display()
170
        );
171
172
198k
        if isa.flags().enable_nan_canonicalization() {
173
198k
            self.canonicalize_nans(isa)?;
174
0
        }
175
176
198k
        self.legalize(isa)?;
177
178
198k
        self.compute_cfg();
179
198k
        self.compute_domtree();
180
198k
        self.eliminate_unreachable_code(isa)?;
181
198k
        self.remove_constant_phis(isa)?;
182
183
198k
        self.func.dfg.resolve_all_aliases();
184
185
198k
        if opt_level != OptLevel::None {
186
198k
            self.egraph_pass(isa, ctrl_plane)?;
187
0
        }
188
189
198k
        Ok(())
190
198k
    }
191
192
    /// Perform function call inlining.
193
    ///
194
    /// Returns `true` if any function call was inlined, `false` otherwise.
195
0
    pub fn inline(&mut self, inliner: impl Inline) -> CodegenResult<bool> {
196
0
        do_inlining(&mut self.func, inliner)
197
0
    }
Unexecuted instantiation: <cranelift_codegen::context::Context>::inline::<_>
Unexecuted instantiation: <cranelift_codegen::context::Context>::inline::<_>
198
199
    /// Compile the function,
200
    ///
201
    /// Run the function through all the passes necessary to generate
202
    /// code for the target ISA represented by `isa`. The generated
203
    /// machine code is not relocated. Instead, any relocations can be
204
    /// obtained from `compiled_code.buffer.relocs()`.
205
    ///
206
    /// Performs any optimizations that are enabled, unless
207
    /// `optimize()` was already invoked.
208
    ///
209
    /// Returns the generated machine code as well as information about
210
    /// the function's code and read-only data.
211
198k
    pub fn compile(
212
198k
        &mut self,
213
198k
        isa: &dyn TargetIsa,
214
198k
        ctrl_plane: &mut ControlPlane,
215
198k
    ) -> CompileResult<'_, &CompiledCode> {
216
198k
        let stencil = self
217
198k
            .compile_stencil(isa, ctrl_plane)
218
198k
            .map_err(|error| CompileError {
219
0
                inner: error,
220
0
                func: &self.func,
221
0
            })?;
Unexecuted instantiation: <cranelift_codegen::context::Context>::compile::{closure#0}
Unexecuted instantiation: <cranelift_codegen::context::Context>::compile::{closure#0}
222
198k
        Ok(self
223
198k
            .compiled_code
224
198k
            .insert(stencil.apply_params(&self.func.params)))
225
198k
    }
Unexecuted instantiation: <cranelift_codegen::context::Context>::compile
<cranelift_codegen::context::Context>::compile
Line
Count
Source
211
198k
    pub fn compile(
212
198k
        &mut self,
213
198k
        isa: &dyn TargetIsa,
214
198k
        ctrl_plane: &mut ControlPlane,
215
198k
    ) -> CompileResult<'_, &CompiledCode> {
216
198k
        let stencil = self
217
198k
            .compile_stencil(isa, ctrl_plane)
218
198k
            .map_err(|error| CompileError {
219
                inner: error,
220
                func: &self.func,
221
0
            })?;
222
198k
        Ok(self
223
198k
            .compiled_code
224
198k
            .insert(stencil.apply_params(&self.func.params)))
225
198k
    }
226
227
    /// If available, return information about the code layout in the
228
    /// final machine code: the offsets (in bytes) of each basic-block
229
    /// start, and all basic-block edges.
230
    #[deprecated = "use CompiledCode::get_code_bb_layout"]
231
0
    pub fn get_code_bb_layout(&self) -> Option<(Vec<usize>, Vec<(usize, usize)>)> {
232
0
        self.compiled_code().map(CompiledCode::get_code_bb_layout)
233
0
    }
Unexecuted instantiation: <cranelift_codegen::context::Context>::get_code_bb_layout
Unexecuted instantiation: <cranelift_codegen::context::Context>::get_code_bb_layout
234
235
    /// Creates unwind information for the function.
236
    ///
237
    /// Returns `None` if the function has no unwind information.
238
    #[cfg(feature = "unwind")]
239
    #[deprecated = "use CompiledCode::create_unwind_info"]
240
0
    pub fn create_unwind_info(
241
0
        &self,
242
0
        isa: &dyn TargetIsa,
243
0
    ) -> CodegenResult<Option<crate::isa::unwind::UnwindInfo>> {
244
0
        self.compiled_code().unwrap().create_unwind_info(isa)
245
0
    }
Unexecuted instantiation: <cranelift_codegen::context::Context>::create_unwind_info
Unexecuted instantiation: <cranelift_codegen::context::Context>::create_unwind_info
246
247
    /// Run the verifier on the function.
248
    ///
249
    /// Also check that the dominator tree and control flow graph are consistent with the function.
250
    ///
251
    /// TODO: rename to "CLIF validate" or similar.
252
1.19M
    pub fn verify<'a, FOI: Into<FlagsOrIsa<'a>>>(&self, fisa: FOI) -> VerifierResult<()> {
253
1.19M
        let mut errors = VerifierErrors::default();
254
1.19M
        let _ = verify_context(&self.func, &self.cfg, &self.domtree, fisa, &mut errors);
255
256
1.19M
        if errors.is_empty() {
257
1.19M
            Ok(())
258
        } else {
259
0
            Err(errors)
260
        }
261
1.19M
    }
Unexecuted instantiation: <cranelift_codegen::context::Context>::verify::<cranelift_codegen::settings::FlagsOrIsa>
<cranelift_codegen::context::Context>::verify::<cranelift_codegen::settings::FlagsOrIsa>
Line
Count
Source
252
1.19M
    pub fn verify<'a, FOI: Into<FlagsOrIsa<'a>>>(&self, fisa: FOI) -> VerifierResult<()> {
253
1.19M
        let mut errors = VerifierErrors::default();
254
1.19M
        let _ = verify_context(&self.func, &self.cfg, &self.domtree, fisa, &mut errors);
255
256
1.19M
        if errors.is_empty() {
257
1.19M
            Ok(())
258
        } else {
259
0
            Err(errors)
260
        }
261
1.19M
    }
262
263
    /// Run the verifier only if the `enable_verifier` setting is true.
264
1.19M
    pub fn verify_if<'a, FOI: Into<FlagsOrIsa<'a>>>(&self, fisa: FOI) -> CodegenResult<()> {
265
1.19M
        let fisa = fisa.into();
266
1.19M
        if fisa.flags.enable_verifier() {
267
1.19M
            self.verify(fisa)?;
268
0
        }
269
1.19M
        Ok(())
270
1.19M
    }
Unexecuted instantiation: <cranelift_codegen::context::Context>::verify_if::<cranelift_codegen::settings::FlagsOrIsa>
Unexecuted instantiation: <cranelift_codegen::context::Context>::verify_if::<&dyn cranelift_codegen::isa::TargetIsa>
<cranelift_codegen::context::Context>::verify_if::<cranelift_codegen::settings::FlagsOrIsa>
Line
Count
Source
264
198k
    pub fn verify_if<'a, FOI: Into<FlagsOrIsa<'a>>>(&self, fisa: FOI) -> CodegenResult<()> {
265
198k
        let fisa = fisa.into();
266
198k
        if fisa.flags.enable_verifier() {
267
198k
            self.verify(fisa)?;
268
0
        }
269
198k
        Ok(())
270
198k
    }
<cranelift_codegen::context::Context>::verify_if::<&dyn cranelift_codegen::isa::TargetIsa>
Line
Count
Source
264
992k
    pub fn verify_if<'a, FOI: Into<FlagsOrIsa<'a>>>(&self, fisa: FOI) -> CodegenResult<()> {
265
992k
        let fisa = fisa.into();
266
992k
        if fisa.flags.enable_verifier() {
267
992k
            self.verify(fisa)?;
268
0
        }
269
992k
        Ok(())
270
992k
    }
271
272
    /// Perform constant-phi removal on the function.
273
198k
    pub fn remove_constant_phis<'a, FOI: Into<FlagsOrIsa<'a>>>(
274
198k
        &mut self,
275
198k
        fisa: FOI,
276
198k
    ) -> CodegenResult<()> {
277
198k
        do_remove_constant_phis(&mut self.func, &mut self.domtree);
278
198k
        self.verify_if(fisa)?;
279
198k
        Ok(())
280
198k
    }
Unexecuted instantiation: <cranelift_codegen::context::Context>::remove_constant_phis::<&dyn cranelift_codegen::isa::TargetIsa>
<cranelift_codegen::context::Context>::remove_constant_phis::<&dyn cranelift_codegen::isa::TargetIsa>
Line
Count
Source
273
198k
    pub fn remove_constant_phis<'a, FOI: Into<FlagsOrIsa<'a>>>(
274
198k
        &mut self,
275
198k
        fisa: FOI,
276
198k
    ) -> CodegenResult<()> {
277
198k
        do_remove_constant_phis(&mut self.func, &mut self.domtree);
278
198k
        self.verify_if(fisa)?;
279
198k
        Ok(())
280
198k
    }
281
282
    /// Perform NaN canonicalizing rewrites on the function.
283
198k
    pub fn canonicalize_nans(&mut self, isa: &dyn TargetIsa) -> CodegenResult<()> {
284
        // Currently only RiscV64 is the only arch that may not have vector support.
285
198k
        let has_vector_support = match isa.triple().architecture {
286
0
            Architecture::Riscv64(_) => match isa.isa_flags().iter().find(|f| f.name == "has_v") {
Unexecuted instantiation: <cranelift_codegen::context::Context>::canonicalize_nans::{closure#0}
Unexecuted instantiation: <cranelift_codegen::context::Context>::canonicalize_nans::{closure#0}
287
0
                Some(value) => value.as_bool().unwrap_or(false),
288
0
                None => false,
289
            },
290
198k
            _ => true,
291
        };
292
198k
        do_nan_canonicalization(&mut self.func, has_vector_support);
293
198k
        self.verify_if(isa)
294
198k
    }
Unexecuted instantiation: <cranelift_codegen::context::Context>::canonicalize_nans
<cranelift_codegen::context::Context>::canonicalize_nans
Line
Count
Source
283
198k
    pub fn canonicalize_nans(&mut self, isa: &dyn TargetIsa) -> CodegenResult<()> {
284
        // Currently only RiscV64 is the only arch that may not have vector support.
285
198k
        let has_vector_support = match isa.triple().architecture {
286
0
            Architecture::Riscv64(_) => match isa.isa_flags().iter().find(|f| f.name == "has_v") {
287
0
                Some(value) => value.as_bool().unwrap_or(false),
288
0
                None => false,
289
            },
290
198k
            _ => true,
291
        };
292
198k
        do_nan_canonicalization(&mut self.func, has_vector_support);
293
198k
        self.verify_if(isa)
294
198k
    }
295
296
    /// Run the legalizer for `isa` on the function.
297
198k
    pub fn legalize(&mut self, isa: &dyn TargetIsa) -> CodegenResult<()> {
298
        // Legalization invalidates the domtree and loop_analysis by mutating the CFG.
299
        // TODO: Avoid doing this when legalization doesn't actually mutate the CFG.
300
198k
        self.domtree.clear();
301
198k
        self.loop_analysis.clear();
302
198k
        self.cfg.clear();
303
304
        // Run some specific legalizations only.
305
198k
        simple_legalize(&mut self.func, isa);
306
198k
        self.verify_if(isa)
307
198k
    }
Unexecuted instantiation: <cranelift_codegen::context::Context>::legalize
<cranelift_codegen::context::Context>::legalize
Line
Count
Source
297
198k
    pub fn legalize(&mut self, isa: &dyn TargetIsa) -> CodegenResult<()> {
298
        // Legalization invalidates the domtree and loop_analysis by mutating the CFG.
299
        // TODO: Avoid doing this when legalization doesn't actually mutate the CFG.
300
198k
        self.domtree.clear();
301
198k
        self.loop_analysis.clear();
302
198k
        self.cfg.clear();
303
304
        // Run some specific legalizations only.
305
198k
        simple_legalize(&mut self.func, isa);
306
198k
        self.verify_if(isa)
307
198k
    }
308
309
    /// Compute the control flow graph.
310
198k
    pub fn compute_cfg(&mut self) {
311
198k
        self.cfg.compute(&self.func)
312
198k
    }
Unexecuted instantiation: <cranelift_codegen::context::Context>::compute_cfg
<cranelift_codegen::context::Context>::compute_cfg
Line
Count
Source
310
198k
    pub fn compute_cfg(&mut self) {
311
198k
        self.cfg.compute(&self.func)
312
198k
    }
313
314
    /// Compute dominator tree.
315
198k
    pub fn compute_domtree(&mut self) {
316
198k
        self.domtree.compute(&self.func, &self.cfg);
317
198k
    }
Unexecuted instantiation: <cranelift_codegen::context::Context>::compute_domtree
<cranelift_codegen::context::Context>::compute_domtree
Line
Count
Source
315
198k
    pub fn compute_domtree(&mut self) {
316
198k
        self.domtree.compute(&self.func, &self.cfg);
317
198k
    }
318
319
    /// Compute the loop analysis.
320
198k
    pub fn compute_loop_analysis(&mut self) {
321
198k
        self.loop_analysis
322
198k
            .compute(&self.func, &self.cfg, &self.domtree)
323
198k
    }
Unexecuted instantiation: <cranelift_codegen::context::Context>::compute_loop_analysis
<cranelift_codegen::context::Context>::compute_loop_analysis
Line
Count
Source
320
198k
    pub fn compute_loop_analysis(&mut self) {
321
198k
        self.loop_analysis
322
198k
            .compute(&self.func, &self.cfg, &self.domtree)
323
198k
    }
324
325
    /// Compute the control flow graph and dominator tree.
326
0
    pub fn flowgraph(&mut self) {
327
0
        self.compute_cfg();
328
0
        self.compute_domtree()
329
0
    }
Unexecuted instantiation: <cranelift_codegen::context::Context>::flowgraph
Unexecuted instantiation: <cranelift_codegen::context::Context>::flowgraph
330
331
    /// Perform unreachable code elimination.
332
198k
    pub fn eliminate_unreachable_code<'a, FOI>(&mut self, fisa: FOI) -> CodegenResult<()>
333
198k
    where
334
198k
        FOI: Into<FlagsOrIsa<'a>>,
335
    {
336
198k
        eliminate_unreachable_code(&mut self.func, &mut self.cfg, &self.domtree);
337
198k
        self.verify_if(fisa)
338
198k
    }
Unexecuted instantiation: <cranelift_codegen::context::Context>::eliminate_unreachable_code::<&dyn cranelift_codegen::isa::TargetIsa>
<cranelift_codegen::context::Context>::eliminate_unreachable_code::<&dyn cranelift_codegen::isa::TargetIsa>
Line
Count
Source
332
198k
    pub fn eliminate_unreachable_code<'a, FOI>(&mut self, fisa: FOI) -> CodegenResult<()>
333
198k
    where
334
198k
        FOI: Into<FlagsOrIsa<'a>>,
335
    {
336
198k
        eliminate_unreachable_code(&mut self.func, &mut self.cfg, &self.domtree);
337
198k
        self.verify_if(fisa)
338
198k
    }
339
340
    /// Replace all redundant loads with the known values in
341
    /// memory. These are loads whose values were already loaded by
342
    /// other loads earlier, as well as loads whose values were stored
343
    /// by a store instruction to the same instruction (so-called
344
    /// "store-to-load forwarding").
345
0
    pub fn replace_redundant_loads(&mut self) -> CodegenResult<()> {
346
0
        let mut analysis = AliasAnalysis::new(&self.func, &self.domtree);
347
0
        analysis.compute_and_update_aliases(&mut self.func);
348
0
        Ok(())
349
0
    }
Unexecuted instantiation: <cranelift_codegen::context::Context>::replace_redundant_loads
Unexecuted instantiation: <cranelift_codegen::context::Context>::replace_redundant_loads
350
351
    /// Harvest candidate left-hand sides for superoptimization with Souper.
352
    #[cfg(feature = "souper-harvest")]
353
    pub fn souper_harvest(
354
        &mut self,
355
        out: &mut std::sync::mpsc::Sender<String>,
356
    ) -> CodegenResult<()> {
357
        do_souper_harvest(&self.func, out);
358
        Ok(())
359
    }
360
361
    /// Run optimizations via the egraph infrastructure.
362
198k
    pub fn egraph_pass<'a, FOI>(
363
198k
        &mut self,
364
198k
        fisa: FOI,
365
198k
        ctrl_plane: &mut ControlPlane,
366
198k
    ) -> CodegenResult<()>
367
198k
    where
368
198k
        FOI: Into<FlagsOrIsa<'a>>,
369
    {
370
198k
        let _tt = timing::egraph();
371
372
198k
        trace!(
373
            "About to optimize with egraph phase:\n{}",
374
0
            self.func.display()
375
        );
376
198k
        let fisa = fisa.into();
377
198k
        self.compute_loop_analysis();
378
198k
        let mut alias_analysis = AliasAnalysis::new(&self.func, &self.domtree);
379
198k
        let mut pass = EgraphPass::new(
380
198k
            &mut self.func,
381
198k
            &self.domtree,
382
198k
            &self.loop_analysis,
383
198k
            &mut alias_analysis,
384
198k
            &fisa.flags,
385
198k
            ctrl_plane,
386
        );
387
198k
        pass.run();
388
198k
        log::debug!("egraph stats: {:?}", pass.stats);
389
198k
        trace!("After egraph optimization:\n{}", self.func.display());
390
391
198k
        self.verify_if(fisa)
392
198k
    }
Unexecuted instantiation: <cranelift_codegen::context::Context>::egraph_pass::<&dyn cranelift_codegen::isa::TargetIsa>
<cranelift_codegen::context::Context>::egraph_pass::<&dyn cranelift_codegen::isa::TargetIsa>
Line
Count
Source
362
198k
    pub fn egraph_pass<'a, FOI>(
363
198k
        &mut self,
364
198k
        fisa: FOI,
365
198k
        ctrl_plane: &mut ControlPlane,
366
198k
    ) -> CodegenResult<()>
367
198k
    where
368
198k
        FOI: Into<FlagsOrIsa<'a>>,
369
    {
370
198k
        let _tt = timing::egraph();
371
372
198k
        trace!(
373
            "About to optimize with egraph phase:\n{}",
374
0
            self.func.display()
375
        );
376
198k
        let fisa = fisa.into();
377
198k
        self.compute_loop_analysis();
378
198k
        let mut alias_analysis = AliasAnalysis::new(&self.func, &self.domtree);
379
198k
        let mut pass = EgraphPass::new(
380
198k
            &mut self.func,
381
198k
            &self.domtree,
382
198k
            &self.loop_analysis,
383
198k
            &mut alias_analysis,
384
198k
            &fisa.flags,
385
198k
            ctrl_plane,
386
        );
387
198k
        pass.run();
388
198k
        log::debug!("egraph stats: {:?}", pass.stats);
389
198k
        trace!("After egraph optimization:\n{}", self.func.display());
390
391
198k
        self.verify_if(fisa)
392
198k
    }
393
}