pub struct Analyses { /* private fields */ }Expand description
The analyses of one function, computed when asked for and kept until something breaks them.
Empty to start with. Nothing here is computed by existing, which matters because most functions are walked by a pass that wants none of it.
Implementations§
Source§impl Analyses
impl Analyses
Sourcepub fn cfg(&mut self, func: &Func) -> &Cfg
pub fn cfg(&mut self, func: &Func) -> &Cfg
The control flow graph, computed if it is not already here.
Sourcepub fn dominators(&mut self, func: &Func) -> &Dominators
pub fn dominators(&mut self, func: &Func) -> &Dominators
The dominator tree, computed if it is not already here.
The graph comes out of the cache as well, so a caller that wants both pays for it once.
Each of these is written against the field rather than through the method above it,
because two fields of one structure can be borrowed at the same time and two calls that
each take all of self cannot.
Sourcepub fn post_dominators(&mut self, func: &Func) -> &PostDominators
pub fn post_dominators(&mut self, func: &Func) -> &PostDominators
The post-dominator tree, computed if it is not already here.
§Panics
Panics through PostDominators::new, on a function with a block that control reaches
and that has no path to any exit even after the fake edges have been added.
Sourcepub fn loops(&mut self, func: &Func) -> &Loops
pub fn loops(&mut self, func: &Func) -> &Loops
The loop forest, computed if it is not already here.
Sourcepub fn frontiers(&mut self, func: &Func) -> &Frontiers
pub fn frontiers(&mut self, func: &Func) -> &Frontiers
The dominance frontier of every block, computed if it is not already here.
Sourcepub fn control_dependence(&mut self, func: &Func) -> &ControlDependence
pub fn control_dependence(&mut self, func: &Func) -> &ControlDependence
Which branches decide whether each block runs, computed if it is not already here.
§Panics
Panics through PostDominators::new, for the reason above it.
Sourcepub fn frequencies(&mut self, func: &Func) -> &Frequencies
pub fn frequencies(&mut self, func: &Func) -> &Frequencies
How often each block runs and which way each branch goes, computed if it is not here.
Predicted rather than measured, and every number out of it says so. A function pass is
given one function and not the module around it, so nothing is known here about what any
callee does. Section 11.2’s two predictors that would like to know, which are the ones
about a call that never returns and a call to something cold, still fire on what the IR
says: the front end puts an unreachable after a call that does not come back. A module
pass that wants the rest of the answer builds its own with Callees::of_module.
Sourcepub fn holds(&self, analysis: Analysis) -> bool
pub fn holds(&self, analysis: Analysis) -> bool
Whether this one is here without computing it.
For the debug check below and for tests. A pass has no business asking, because a pass that behaves differently depending on what somebody else happened to leave in the cache is a pass whose output depends on the pipeline around it.
Sourcepub fn settle(
&mut self,
func: &Func,
keeps: Preserved,
check: bool,
) -> Vec<Analysis>
pub fn settle( &mut self, func: &Func, keeps: Preserved, check: bool, ) -> Vec<Analysis>
Takes the pass at its word, and in a checked build sees whether it was telling the truth.
Call it after every pass over the function, with what the pass said it preserved. What
comes back is the analyses the pass claimed to preserve and did not, which is empty when
check is off and is empty on an honest pass. Everything the pass did not preserve is
gone from the cache afterwards, and so is everything that was built on top of it.
The check recomputes, which is why it is behind a flag and why the flag is the one that already turns the IR verifier on. Both are the same kind of thing: a cost paid in a build somebody is developing in, to catch the kind of mistake that produces a wrong program rather than a slow one.