pub struct Cfg { /* private fields */ }Expand description
Who goes where in a function, and in what order to walk it.
Built with Cfg::new and read only. Nothing here holds a borrow of the function, so a
pass can compute the graph, then edit the code, and the compiler will not stop it. What
stops it is the pass manager, which throws this away when a pass says it changed the shape.
Implementations§
Source§impl Cfg
impl Cfg
Sourcepub fn new(func: &Func) -> Self
pub fn new(func: &Func) -> Self
Reads the graph out of the function.
Linear in the blocks and the edges between them. A function with no blocks gives an empty graph rather than an error, because a declaration is a perfectly ordinary thing for a pipeline to be handed and refusing it here would put the check in every caller.
Sourcepub fn entry(&self) -> Option<Block>
pub fn entry(&self) -> Option<Block>
Where control arrives, which is None for a function that is only declared.
Sourcepub fn successors(&self, block: Block) -> &[Block] ⓘ
pub fn successors(&self, block: Block) -> &[Block] ⓘ
The blocks this one branches to, each named once however many edges go to it.
Sourcepub fn predecessors(&self, block: Block) -> &[Block] ⓘ
pub fn predecessors(&self, block: Block) -> &[Block] ⓘ
The blocks that branch to this one, each named once however many edges come from it.
Sourcepub fn postorder(&self) -> &[Block] ⓘ
pub fn postorder(&self) -> &[Block] ⓘ
Every block the entry reaches, children before parents.
This is the order to run a backwards analysis in, and reversing it is the order to run a forwards one in. It is computed here rather than in each pass that wants it, which is how a compiler avoids acquiring six traversals that differ in ways nobody wrote down.
Sourcepub fn reverse_postorder(
&self,
) -> impl DoubleEndedIterator<Item = Block> + use<'_>
pub fn reverse_postorder( &self, ) -> impl DoubleEndedIterator<Item = Block> + use<'_>
Every block the entry reaches, parents before children.
A block appears after at least one of its predecessors, and after all of them when the graph has no back edges. That is what makes it the order a forwards fixed point settles in fastest.
Sourcepub fn rank(&self, block: Block) -> Option<u32>
pub fn rank(&self, block: Block) -> Option<u32>
Where a block sits in reverse postorder, and None for one the entry does not reach.
Sourcepub fn reaches(&self, block: Block) -> bool
pub fn reaches(&self, block: Block) -> bool
Whether control can arrive at this block at all.
An unreachable block is not an error and the front end makes them constantly: the block
after a return, the arm of an if on a constant, the code after
__builtin_unreachable. Section 6.5 of the design states the rule for the whole
optimizer, which is that such a block is invisible to every analysis and every
transformation, and is deleted by CFG simplification rather than by whoever noticed it.
A pass that deletes blocks as a side effect of doing something else is a pass whose fuel
accounting is wrong and whose dumps cannot be read.