1747ad3c4Slazypassion //! Cranelift compilation context and main entry point.
2747ad3c4Slazypassion //!
3747ad3c4Slazypassion //! When compiling many small functions, it is important to avoid repeatedly allocating and
4747ad3c4Slazypassion //! deallocating the data structures needed for compilation. The `Context` struct is used to hold
5747ad3c4Slazypassion //! on to memory allocations between function compilations.
6747ad3c4Slazypassion //!
7747ad3c4Slazypassion //! The context does not hold a `TargetIsa` instance which has to be provided as an argument
8747ad3c4Slazypassion //! instead. This is because an ISA instance is immutable and can be used by multiple compilation
9747ad3c4Slazypassion //! contexts concurrently. Typically, you would have one context per compilation thread and only a
10747ad3c4Slazypassion //! single ISA instance.
11747ad3c4Slazypassion 
120824abbaSChris Fallin use crate::alias_analysis::AliasAnalysis;
13747ad3c4Slazypassion use crate::dominator_tree::DominatorTree;
14f980defeSChris Fallin use crate::egraph::EgraphPass;
15747ad3c4Slazypassion use crate::flowgraph::ControlFlowGraph;
16968952abSNick Fitzgerald use crate::inline::{Inline, do_inlining};
17747ad3c4Slazypassion use crate::ir::Function;
18747ad3c4Slazypassion use crate::isa::TargetIsa;
1960990aeaSChris Fallin use crate::legalizer::simple_legalize;
20747ad3c4Slazypassion use crate::loop_analysis::LoopAnalysis;
218a9b1a90SBenjamin Bouvier use crate::machinst::{CompiledCode, CompiledCodeStencil};
22747ad3c4Slazypassion use crate::nan_canonicalization::do_nan_canonicalization;
230bc0503fSJulian Seward use crate::remove_constant_phis::do_remove_constant_phis;
24ff37c9d8SBenjamin Bouvier use crate::result::{CodegenResult, CompileResult};
25747ad3c4Slazypassion use crate::settings::{FlagsOrIsa, OptLevel};
26f980defeSChris Fallin use crate::trace;
27747ad3c4Slazypassion use crate::unreachable_code::eliminate_unreachable_code;
2890ac295eSAlex Crichton use crate::verifier::{VerifierErrors, VerifierResult, verify_context};
2990ac295eSAlex Crichton use crate::{CompileError, timing};
303a6dd832SNick Fitzgerald #[cfg(feature = "souper-harvest")]
313a6dd832SNick Fitzgerald use alloc::string::String;
3210e226f9Sbjorn3 use alloc::vec::Vec;
337eb89140SRemo Senekowitsch use cranelift_control::ControlPlane;
3472a3b8b9SAdam Bratschi-Kaye use target_lexicon::Architecture;
35747ad3c4Slazypassion 
363a6dd832SNick Fitzgerald #[cfg(feature = "souper-harvest")]
373a6dd832SNick Fitzgerald use crate::souper_harvest::do_souper_harvest;
383a6dd832SNick Fitzgerald 
39747ad3c4Slazypassion /// Persistent data structures and compilation pipeline.
40747ad3c4Slazypassion pub struct Context {
41747ad3c4Slazypassion     /// The function we're compiling.
42747ad3c4Slazypassion     pub func: Function,
43747ad3c4Slazypassion 
44747ad3c4Slazypassion     /// The control flow graph of `func`.
45747ad3c4Slazypassion     pub cfg: ControlFlowGraph,
46747ad3c4Slazypassion 
47747ad3c4Slazypassion     /// Dominator tree for `func`.
48747ad3c4Slazypassion     pub domtree: DominatorTree,
49747ad3c4Slazypassion 
50747ad3c4Slazypassion     /// Loop analysis of `func`.
51747ad3c4Slazypassion     pub loop_analysis: LoopAnalysis,
52b8fb5244Sjulian-seward1 
5360990aeaSChris Fallin     /// Result of MachBackend compilation, if computed.
548a9b1a90SBenjamin Bouvier     pub(crate) compiled_code: Option<CompiledCode>,
5560990aeaSChris Fallin 
56ff37c9d8SBenjamin Bouvier     /// Flag: do we want a disassembly with the CompiledCode?
5760990aeaSChris Fallin     pub want_disasm: bool,
58747ad3c4Slazypassion }
59747ad3c4Slazypassion 
60747ad3c4Slazypassion impl Context {
61747ad3c4Slazypassion     /// Allocate a new compilation context.
62747ad3c4Slazypassion     ///
63747ad3c4Slazypassion     /// The returned instance should be reused for compiling multiple functions in order to avoid
64747ad3c4Slazypassion     /// needless allocator thrashing.
new() -> Self65747ad3c4Slazypassion     pub fn new() -> Self {
66747ad3c4Slazypassion         Self::for_function(Function::new())
67747ad3c4Slazypassion     }
68747ad3c4Slazypassion 
69747ad3c4Slazypassion     /// Allocate a new compilation context with an existing Function.
70747ad3c4Slazypassion     ///
71747ad3c4Slazypassion     /// The returned instance should be reused for compiling multiple functions in order to avoid
72747ad3c4Slazypassion     /// needless allocator thrashing.
for_function(func: Function) -> Self73747ad3c4Slazypassion     pub fn for_function(func: Function) -> Self {
74747ad3c4Slazypassion         Self {
75747ad3c4Slazypassion             func,
76747ad3c4Slazypassion             cfg: ControlFlowGraph::new(),
77747ad3c4Slazypassion             domtree: DominatorTree::new(),
78747ad3c4Slazypassion             loop_analysis: LoopAnalysis::new(),
79ff37c9d8SBenjamin Bouvier             compiled_code: None,
8060990aeaSChris Fallin             want_disasm: false,
81747ad3c4Slazypassion         }
82747ad3c4Slazypassion     }
83747ad3c4Slazypassion 
84747ad3c4Slazypassion     /// Clear all data structures in this context.
clear(&mut self)85747ad3c4Slazypassion     pub fn clear(&mut self) {
86747ad3c4Slazypassion         self.func.clear();
87747ad3c4Slazypassion         self.cfg.clear();
88747ad3c4Slazypassion         self.domtree.clear();
89747ad3c4Slazypassion         self.loop_analysis.clear();
90ff37c9d8SBenjamin Bouvier         self.compiled_code = None;
9160990aeaSChris Fallin         self.want_disasm = false;
9260990aeaSChris Fallin     }
9360990aeaSChris Fallin 
94ff37c9d8SBenjamin Bouvier     /// Returns the compilation result for this function, available after any `compile` function
95ff37c9d8SBenjamin Bouvier     /// has been called.
compiled_code(&self) -> Option<&CompiledCode>96ff37c9d8SBenjamin Bouvier     pub fn compiled_code(&self) -> Option<&CompiledCode> {
97ff37c9d8SBenjamin Bouvier         self.compiled_code.as_ref()
98ff37c9d8SBenjamin Bouvier     }
99ff37c9d8SBenjamin Bouvier 
100b3636ff6SNick Fitzgerald     /// Returns the compilation result for this function, available after any `compile` function
101b3636ff6SNick Fitzgerald     /// has been called.
take_compiled_code(&mut self) -> Option<CompiledCode>102b3636ff6SNick Fitzgerald     pub fn take_compiled_code(&mut self) -> Option<CompiledCode> {
103b3636ff6SNick Fitzgerald         self.compiled_code.take()
104b3636ff6SNick Fitzgerald     }
105b3636ff6SNick Fitzgerald 
10660990aeaSChris Fallin     /// Set the flag to request a disassembly when compiling with a
10760990aeaSChris Fallin     /// `MachBackend` backend.
set_disasm(&mut self, val: bool)10860990aeaSChris Fallin     pub fn set_disasm(&mut self, val: bool) {
10960990aeaSChris Fallin         self.want_disasm = val;
110747ad3c4Slazypassion     }
111747ad3c4Slazypassion 
112747ad3c4Slazypassion     /// Compile the function, and emit machine code into a `Vec<u8>`.
113f96aac79Sbjorn3     #[deprecated = "use Context::compile"]
compile_and_emit( &mut self, isa: &dyn TargetIsa, mem: &mut Vec<u8>, ctrl_plane: &mut ControlPlane, ) -> CompileResult<'_, &CompiledCode>114747ad3c4Slazypassion     pub fn compile_and_emit(
115747ad3c4Slazypassion         &mut self,
116d7d48d5cSBenjamin Bouvier         isa: &dyn TargetIsa,
117747ad3c4Slazypassion         mem: &mut Vec<u8>,
1187eb89140SRemo Senekowitsch         ctrl_plane: &mut ControlPlane,
1198a42768fSAlex Crichton     ) -> CompileResult<'_, &CompiledCode> {
1207eb89140SRemo Senekowitsch         let compiled_code = self.compile(isa, ctrl_plane)?;
12104b30acaSJamey Sharp         mem.extend_from_slice(compiled_code.code_buffer());
122ff37c9d8SBenjamin Bouvier         Ok(compiled_code)
123747ad3c4Slazypassion     }
124747ad3c4Slazypassion 
1258a9b1a90SBenjamin Bouvier     /// Internally compiles the function into a stencil.
126747ad3c4Slazypassion     ///
1278a9b1a90SBenjamin Bouvier     /// Public only for testing and fuzzing purposes.
compile_stencil( &mut self, isa: &dyn TargetIsa, ctrl_plane: &mut ControlPlane, ) -> CodegenResult<CompiledCodeStencil>1287eb89140SRemo Senekowitsch     pub fn compile_stencil(
1297eb89140SRemo Senekowitsch         &mut self,
1307eb89140SRemo Senekowitsch         isa: &dyn TargetIsa,
1317eb89140SRemo Senekowitsch         ctrl_plane: &mut ControlPlane,
1327eb89140SRemo Senekowitsch     ) -> CodegenResult<CompiledCodeStencil> {
1333da7fc8eSSingleAccretion         let result;
1343da7fc8eSSingleAccretion         trace!("****** START compiling {}", self.func.display_spec());
1353da7fc8eSSingleAccretion         {
136747ad3c4Slazypassion             let _tt = timing::compile();
137ff37c9d8SBenjamin Bouvier 
138747ad3c4Slazypassion             self.verify_if(isa)?;
139caa555f8SJamey Sharp             self.optimize(isa, ctrl_plane)?;
1403da7fc8eSSingleAccretion             result = isa.compile_function(&self.func, &self.domtree, self.want_disasm, ctrl_plane);
1413da7fc8eSSingleAccretion         }
1423da7fc8eSSingleAccretion         trace!("****** DONE compiling {}\n", self.func.display_spec());
1433da7fc8eSSingleAccretion         result
1442be12a51SChris Fallin     }
1452be12a51SChris Fallin 
1462be12a51SChris Fallin     /// Optimize the function, performing all compilation steps up to
1472be12a51SChris Fallin     /// but not including machine-code lowering and register
1482be12a51SChris Fallin     /// allocation.
1492be12a51SChris Fallin     ///
1502be12a51SChris Fallin     /// Public only for testing purposes.
optimize( &mut self, isa: &dyn TargetIsa, ctrl_plane: &mut ControlPlane, ) -> CodegenResult<()>151caa555f8SJamey Sharp     pub fn optimize(
152caa555f8SJamey Sharp         &mut self,
153caa555f8SJamey Sharp         isa: &dyn TargetIsa,
154caa555f8SJamey Sharp         ctrl_plane: &mut ControlPlane,
155caa555f8SJamey Sharp     ) -> CodegenResult<()> {
15658a5089eSNick Fitzgerald         log::debug!(
15758a5089eSNick Fitzgerald             "Number of CLIF instructions to optimize: {}",
15858a5089eSNick Fitzgerald             self.func.dfg.num_insts()
15958a5089eSNick Fitzgerald         );
16058a5089eSNick Fitzgerald         log::debug!(
16158a5089eSNick Fitzgerald             "Number of CLIF blocks to optimize: {}",
16258a5089eSNick Fitzgerald             self.func.dfg.num_blocks()
16358a5089eSNick Fitzgerald         );
16458a5089eSNick Fitzgerald 
1659e088e41Sjulian-seward1         let opt_level = isa.flags().opt_level();
16658a5089eSNick Fitzgerald         crate::trace!(
1672be12a51SChris Fallin             "Optimizing (opt level {:?}):\n{}",
16860990aeaSChris Fallin             opt_level,
16943a86f14SBenjamin Bouvier             self.func.display()
17060990aeaSChris Fallin         );
1719e088e41Sjulian-seward1 
172747ad3c4Slazypassion         if isa.flags().enable_nan_canonicalization() {
173747ad3c4Slazypassion             self.canonicalize_nans(isa)?;
174747ad3c4Slazypassion         }
17560990aeaSChris Fallin 
176747ad3c4Slazypassion         self.legalize(isa)?;
1772be12a51SChris Fallin 
178a80dd80dSNick Fitzgerald         self.compute_cfg();
179747ad3c4Slazypassion         self.compute_domtree();
180747ad3c4Slazypassion         self.eliminate_unreachable_code(isa)?;
1810bc0503fSJulian Seward         self.remove_constant_phis(isa)?;
1820bc0503fSJulian Seward 
183c477424fSJamey Sharp         self.func.dfg.resolve_all_aliases();
184c477424fSJamey Sharp 
1851faff8c2SChris Fallin         if opt_level != OptLevel::None {
186caa555f8SJamey Sharp             self.egraph_pass(isa, ctrl_plane)?;
1871faff8c2SChris Fallin         }
1880824abbaSChris Fallin 
1892be12a51SChris Fallin         Ok(())
1908a9b1a90SBenjamin Bouvier     }
191747ad3c4Slazypassion 
192968952abSNick Fitzgerald     /// Perform function call inlining.
193968952abSNick Fitzgerald     ///
194968952abSNick Fitzgerald     /// Returns `true` if any function call was inlined, `false` otherwise.
inline(&mut self, inliner: impl Inline) -> CodegenResult<bool>195968952abSNick Fitzgerald     pub fn inline(&mut self, inliner: impl Inline) -> CodegenResult<bool> {
196968952abSNick Fitzgerald         do_inlining(&mut self.func, inliner)
197968952abSNick Fitzgerald     }
198968952abSNick Fitzgerald 
199f96aac79Sbjorn3     /// Compile the function,
2008a9b1a90SBenjamin Bouvier     ///
201f96aac79Sbjorn3     /// Run the function through all the passes necessary to generate
202f96aac79Sbjorn3     /// code for the target ISA represented by `isa`. The generated
203f96aac79Sbjorn3     /// machine code is not relocated. Instead, any relocations can be
204f96aac79Sbjorn3     /// obtained from `compiled_code.buffer.relocs()`.
2058a9b1a90SBenjamin Bouvier     ///
206f96aac79Sbjorn3     /// Performs any optimizations that are enabled, unless
207f96aac79Sbjorn3     /// `optimize()` was already invoked.
208f96aac79Sbjorn3     ///
209f96aac79Sbjorn3     /// Returns the generated machine code as well as information about
210f96aac79Sbjorn3     /// the function's code and read-only data.
compile( &mut self, isa: &dyn TargetIsa, ctrl_plane: &mut ControlPlane, ) -> CompileResult<'_, &CompiledCode>2117eb89140SRemo Senekowitsch     pub fn compile(
2127eb89140SRemo Senekowitsch         &mut self,
2137eb89140SRemo Senekowitsch         isa: &dyn TargetIsa,
2147eb89140SRemo Senekowitsch         ctrl_plane: &mut ControlPlane,
2158a42768fSAlex Crichton     ) -> CompileResult<'_, &CompiledCode> {
2167eb89140SRemo Senekowitsch         let stencil = self
2177eb89140SRemo Senekowitsch             .compile_stencil(isa, ctrl_plane)
2187eb89140SRemo Senekowitsch             .map_err(|error| CompileError {
219ff37c9d8SBenjamin Bouvier                 inner: error,
220ff37c9d8SBenjamin Bouvier                 func: &self.func,
2218a9b1a90SBenjamin Bouvier             })?;
2228a9b1a90SBenjamin Bouvier         Ok(self
2238a9b1a90SBenjamin Bouvier             .compiled_code
2248a9b1a90SBenjamin Bouvier             .insert(stencil.apply_params(&self.func.params)))
22501b60e81SChris Fallin     }
226747ad3c4Slazypassion 
22711a2ef01SChris Fallin     /// If available, return information about the code layout in the
22811a2ef01SChris Fallin     /// final machine code: the offsets (in bytes) of each basic-block
22911a2ef01SChris Fallin     /// start, and all basic-block edges.
23004b30acaSJamey Sharp     #[deprecated = "use CompiledCode::get_code_bb_layout"]
get_code_bb_layout(&self) -> Option<(Vec<usize>, Vec<(usize, usize)>)>23111a2ef01SChris Fallin     pub fn get_code_bb_layout(&self) -> Option<(Vec<usize>, Vec<(usize, usize)>)> {
23204b30acaSJamey Sharp         self.compiled_code().map(CompiledCode::get_code_bb_layout)
23311a2ef01SChris Fallin     }
23411a2ef01SChris Fallin 
235f7e9f86bSPeter Huene     /// Creates unwind information for the function.
2368923bac7SPeter Huene     ///
237f7e9f86bSPeter Huene     /// Returns `None` if the function has no unwind information.
238f7e9f86bSPeter Huene     #[cfg(feature = "unwind")]
23904b30acaSJamey Sharp     #[deprecated = "use CompiledCode::create_unwind_info"]
create_unwind_info( &self, isa: &dyn TargetIsa, ) -> CodegenResult<Option<crate::isa::unwind::UnwindInfo>>240f7e9f86bSPeter Huene     pub fn create_unwind_info(
241bd881554SYury Delendik         &self,
242bd881554SYury Delendik         isa: &dyn TargetIsa,
243f7e9f86bSPeter Huene     ) -> CodegenResult<Option<crate::isa::unwind::UnwindInfo>> {
24404b30acaSJamey Sharp         self.compiled_code().unwrap().create_unwind_info(isa)
2458923bac7SPeter Huene     }
2468923bac7SPeter Huene 
247747ad3c4Slazypassion     /// Run the verifier on the function.
248747ad3c4Slazypassion     ///
249747ad3c4Slazypassion     /// Also check that the dominator tree and control flow graph are consistent with the function.
250f466aa26SChris Fallin     ///
251f466aa26SChris Fallin     /// TODO: rename to "CLIF validate" or similar.
verify<'a, FOI: Into<FlagsOrIsa<'a>>>(&self, fisa: FOI) -> VerifierResult<()>252747ad3c4Slazypassion     pub fn verify<'a, FOI: Into<FlagsOrIsa<'a>>>(&self, fisa: FOI) -> VerifierResult<()> {
253747ad3c4Slazypassion         let mut errors = VerifierErrors::default();
254747ad3c4Slazypassion         let _ = verify_context(&self.func, &self.cfg, &self.domtree, fisa, &mut errors);
255747ad3c4Slazypassion 
256747ad3c4Slazypassion         if errors.is_empty() {
257747ad3c4Slazypassion             Ok(())
258747ad3c4Slazypassion         } else {
259747ad3c4Slazypassion             Err(errors)
260747ad3c4Slazypassion         }
261747ad3c4Slazypassion     }
262747ad3c4Slazypassion 
263747ad3c4Slazypassion     /// Run the verifier only if the `enable_verifier` setting is true.
verify_if<'a, FOI: Into<FlagsOrIsa<'a>>>(&self, fisa: FOI) -> CodegenResult<()>264747ad3c4Slazypassion     pub fn verify_if<'a, FOI: Into<FlagsOrIsa<'a>>>(&self, fisa: FOI) -> CodegenResult<()> {
265747ad3c4Slazypassion         let fisa = fisa.into();
266747ad3c4Slazypassion         if fisa.flags.enable_verifier() {
267747ad3c4Slazypassion             self.verify(fisa)?;
268747ad3c4Slazypassion         }
269747ad3c4Slazypassion         Ok(())
270747ad3c4Slazypassion     }
271747ad3c4Slazypassion 
2720bc0503fSJulian Seward     /// Perform constant-phi removal on the function.
remove_constant_phis<'a, FOI: Into<FlagsOrIsa<'a>>>( &mut self, fisa: FOI, ) -> CodegenResult<()>2730bc0503fSJulian Seward     pub fn remove_constant_phis<'a, FOI: Into<FlagsOrIsa<'a>>>(
2740bc0503fSJulian Seward         &mut self,
2750bc0503fSJulian Seward         fisa: FOI,
2760bc0503fSJulian Seward     ) -> CodegenResult<()> {
2770bc0503fSJulian Seward         do_remove_constant_phis(&mut self.func, &mut self.domtree);
2780bc0503fSJulian Seward         self.verify_if(fisa)?;
2790bc0503fSJulian Seward         Ok(())
2800bc0503fSJulian Seward     }
2810bc0503fSJulian Seward 
282747ad3c4Slazypassion     /// Perform NaN canonicalizing rewrites on the function.
canonicalize_nans(&mut self, isa: &dyn TargetIsa) -> CodegenResult<()>283d7d48d5cSBenjamin Bouvier     pub fn canonicalize_nans(&mut self, isa: &dyn TargetIsa) -> CodegenResult<()> {
28472a3b8b9SAdam Bratschi-Kaye         // Currently only RiscV64 is the only arch that may not have vector support.
28572a3b8b9SAdam Bratschi-Kaye         let has_vector_support = match isa.triple().architecture {
28672a3b8b9SAdam Bratschi-Kaye             Architecture::Riscv64(_) => match isa.isa_flags().iter().find(|f| f.name == "has_v") {
28772a3b8b9SAdam Bratschi-Kaye                 Some(value) => value.as_bool().unwrap_or(false),
28872a3b8b9SAdam Bratschi-Kaye                 None => false,
28972a3b8b9SAdam Bratschi-Kaye             },
29072a3b8b9SAdam Bratschi-Kaye             _ => true,
29172a3b8b9SAdam Bratschi-Kaye         };
29272a3b8b9SAdam Bratschi-Kaye         do_nan_canonicalization(&mut self.func, has_vector_support);
293747ad3c4Slazypassion         self.verify_if(isa)
294747ad3c4Slazypassion     }
295747ad3c4Slazypassion 
296747ad3c4Slazypassion     /// Run the legalizer for `isa` on the function.
legalize(&mut self, isa: &dyn TargetIsa) -> CodegenResult<()>297d7d48d5cSBenjamin Bouvier     pub fn legalize(&mut self, isa: &dyn TargetIsa) -> CodegenResult<()> {
298747ad3c4Slazypassion         // Legalization invalidates the domtree and loop_analysis by mutating the CFG.
299747ad3c4Slazypassion         // TODO: Avoid doing this when legalization doesn't actually mutate the CFG.
300747ad3c4Slazypassion         self.domtree.clear();
301747ad3c4Slazypassion         self.loop_analysis.clear();
302a80dd80dSNick Fitzgerald         self.cfg.clear();
303bae4ec64SBenjamin Bouvier 
30448cf2c2fSChris Fallin         // Run some specific legalizations only.
305eb0428ebSamartosch         simple_legalize(&mut self.func, isa);
30648cf2c2fSChris Fallin         self.verify_if(isa)
307747ad3c4Slazypassion     }
308747ad3c4Slazypassion 
309747ad3c4Slazypassion     /// Compute the control flow graph.
compute_cfg(&mut self)310747ad3c4Slazypassion     pub fn compute_cfg(&mut self) {
311747ad3c4Slazypassion         self.cfg.compute(&self.func)
312747ad3c4Slazypassion     }
313747ad3c4Slazypassion 
314747ad3c4Slazypassion     /// Compute dominator tree.
compute_domtree(&mut self)315747ad3c4Slazypassion     pub fn compute_domtree(&mut self) {
316e33e0f21SKaran Lokchandani         self.domtree.compute(&self.func, &self.cfg);
317747ad3c4Slazypassion     }
318747ad3c4Slazypassion 
319747ad3c4Slazypassion     /// Compute the loop analysis.
compute_loop_analysis(&mut self)320747ad3c4Slazypassion     pub fn compute_loop_analysis(&mut self) {
321747ad3c4Slazypassion         self.loop_analysis
322747ad3c4Slazypassion             .compute(&self.func, &self.cfg, &self.domtree)
323747ad3c4Slazypassion     }
324747ad3c4Slazypassion 
325747ad3c4Slazypassion     /// Compute the control flow graph and dominator tree.
flowgraph(&mut self)326747ad3c4Slazypassion     pub fn flowgraph(&mut self) {
327747ad3c4Slazypassion         self.compute_cfg();
328747ad3c4Slazypassion         self.compute_domtree()
329747ad3c4Slazypassion     }
330747ad3c4Slazypassion 
331747ad3c4Slazypassion     /// Perform unreachable code elimination.
eliminate_unreachable_code<'a, FOI>(&mut self, fisa: FOI) -> CodegenResult<()> where FOI: Into<FlagsOrIsa<'a>>,332747ad3c4Slazypassion     pub fn eliminate_unreachable_code<'a, FOI>(&mut self, fisa: FOI) -> CodegenResult<()>
333747ad3c4Slazypassion     where
334747ad3c4Slazypassion         FOI: Into<FlagsOrIsa<'a>>,
335747ad3c4Slazypassion     {
336747ad3c4Slazypassion         eliminate_unreachable_code(&mut self.func, &mut self.cfg, &self.domtree);
337747ad3c4Slazypassion         self.verify_if(fisa)
338747ad3c4Slazypassion     }
339747ad3c4Slazypassion 
3400824abbaSChris Fallin     /// Replace all redundant loads with the known values in
3410824abbaSChris Fallin     /// memory. These are loads whose values were already loaded by
3420824abbaSChris Fallin     /// other loads earlier, as well as loads whose values were stored
3430824abbaSChris Fallin     /// by a store instruction to the same instruction (so-called
3440824abbaSChris Fallin     /// "store-to-load forwarding").
replace_redundant_loads(&mut self) -> CodegenResult<()>3450824abbaSChris Fallin     pub fn replace_redundant_loads(&mut self) -> CodegenResult<()> {
346*3a14fa39SPaul Nodet         let mut analysis = AliasAnalysis::new(&self.func, &self.domtree);
347feaa7ca7SChris Fallin         analysis.compute_and_update_aliases(&mut self.func);
3480824abbaSChris Fallin         Ok(())
3490824abbaSChris Fallin     }
3500824abbaSChris Fallin 
3513a6dd832SNick Fitzgerald     /// Harvest candidate left-hand sides for superoptimization with Souper.
3523a6dd832SNick Fitzgerald     #[cfg(feature = "souper-harvest")]
souper_harvest( &mut self, out: &mut std::sync::mpsc::Sender<String>, ) -> CodegenResult<()>3533a6dd832SNick Fitzgerald     pub fn souper_harvest(
3543a6dd832SNick Fitzgerald         &mut self,
3553a6dd832SNick Fitzgerald         out: &mut std::sync::mpsc::Sender<String>,
3563a6dd832SNick Fitzgerald     ) -> CodegenResult<()> {
3573a6dd832SNick Fitzgerald         do_souper_harvest(&self.func, out);
3583a6dd832SNick Fitzgerald         Ok(())
3593a6dd832SNick Fitzgerald     }
360f980defeSChris Fallin 
361f980defeSChris Fallin     /// Run optimizations via the egraph infrastructure.
egraph_pass<'a, FOI>( &mut self, fisa: FOI, ctrl_plane: &mut ControlPlane, ) -> CodegenResult<()> where FOI: Into<FlagsOrIsa<'a>>,362caa555f8SJamey Sharp     pub fn egraph_pass<'a, FOI>(
363caa555f8SJamey Sharp         &mut self,
364caa555f8SJamey Sharp         fisa: FOI,
365caa555f8SJamey Sharp         ctrl_plane: &mut ControlPlane,
366caa555f8SJamey Sharp     ) -> CodegenResult<()>
367b9134e21SGurinder Singh     where
368b9134e21SGurinder Singh         FOI: Into<FlagsOrIsa<'a>>,
369b9134e21SGurinder Singh     {
370108f7917Sbjorn3         let _tt = timing::egraph();
371108f7917Sbjorn3 
372f980defeSChris Fallin         trace!(
373f980defeSChris Fallin             "About to optimize with egraph phase:\n{}",
374f980defeSChris Fallin             self.func.display()
375f980defeSChris Fallin         );
376d7c96a9eSChris Fallin         let fisa = fisa.into();
377f980defeSChris Fallin         self.compute_loop_analysis();
378*3a14fa39SPaul Nodet         let mut alias_analysis = AliasAnalysis::new(&self.func, &self.domtree);
379f980defeSChris Fallin         let mut pass = EgraphPass::new(
380f980defeSChris Fallin             &mut self.func,
381f980defeSChris Fallin             &self.domtree,
382f980defeSChris Fallin             &self.loop_analysis,
383f980defeSChris Fallin             &mut alias_analysis,
384caa555f8SJamey Sharp             ctrl_plane,
385f980defeSChris Fallin         );
386f980defeSChris Fallin         pass.run();
38794f2ff09SYoni L         log::debug!("egraph stats: {:?}", pass.stats);
388f980defeSChris Fallin         trace!("After egraph optimization:\n{}", self.func.display());
389b9134e21SGurinder Singh 
390b9134e21SGurinder Singh         self.verify_if(fisa)
391f980defeSChris Fallin     }
392747ad3c4Slazypassion }
393