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