waffle/src/cfg/mod.rs

129 lines
3.8 KiB
Rust
Raw Normal View History

2021-11-15 01:56:56 -06:00
//! Lightweight CFG analyses.
// Borrowed from regalloc2's cfg.rs, which is also Apache-2.0 with
// LLVM exception.
use crate::declare_entity;
use crate::entity::{EntityRef, EntityVec, PerEntity};
2022-11-29 02:27:38 -06:00
use crate::ir::{Block, FunctionBody, Terminator, Value, ValueDef};
2021-11-15 01:56:56 -06:00
pub mod domtree;
pub mod postorder;
declare_entity!(RPOIndex, "rpo");
2021-11-15 01:56:56 -06:00
#[derive(Clone, Debug)]
pub struct CFGInfo {
2022-11-01 22:43:47 -05:00
/// Entry block.
pub entry: Block,
2021-11-15 01:56:56 -06:00
/// Blocks that end in return.
2022-11-01 22:43:47 -05:00
pub return_blocks: Vec<Block>,
/// Reverse-postorder traversal of blocks.
pub rpo: EntityVec<RPOIndex, Block>,
/// Position of each block in RPO, if reachable.
pub rpo_pos: PerEntity<Block, Option<RPOIndex>>,
2021-11-15 01:56:56 -06:00
/// Domtree parents, indexed by block.
2022-11-01 22:43:47 -05:00
pub domtree: PerEntity<Block, Block>,
2022-11-02 23:26:22 -05:00
/// Domtree children.
pub domtree_children: PerEntity<Block, DomtreeChildren>,
2022-11-29 02:27:38 -06:00
/// Defining block for a given value.
pub def_block: PerEntity<Value, Block>,
2022-11-02 23:26:22 -05:00
}
#[derive(Clone, Debug, Default)]
pub struct DomtreeChildren {
pub child: Block,
pub next: Block,
}
pub struct DomtreeChildIter<'a> {
domtree_children: &'a PerEntity<Block, DomtreeChildren>,
block: Block,
}
impl<'a> Iterator for DomtreeChildIter<'a> {
type Item = Block;
fn next(&mut self) -> Option<Block> {
if self.block.is_invalid() {
None
} else {
let block = self.block;
self.block = self.domtree_children[block].next;
Some(block)
}
}
2021-11-15 01:56:56 -06:00
}
impl CFGInfo {
pub fn new(f: &FunctionBody) -> CFGInfo {
let mut return_blocks = vec![];
2022-11-01 22:43:47 -05:00
for (block_id, block) in f.blocks.entries() {
if let Terminator::Return { .. } = &block.terminator {
return_blocks.push(block_id);
2021-11-15 01:56:56 -06:00
}
}
let postorder = postorder::calculate(f.entry, |block| &f.blocks[block].succs[..]);
2021-11-15 01:56:56 -06:00
let domtree =
domtree::calculate(|block| &f.blocks[block].preds[..], &postorder[..], f.entry);
2022-11-02 23:26:22 -05:00
let mut domtree_children: PerEntity<Block, DomtreeChildren> = PerEntity::default();
for block in f.blocks.iter().rev() {
let idom = domtree[block];
if idom.is_valid() {
let next = domtree_children[idom].child;
domtree_children[block].next = next;
domtree_children[idom].child = block;
}
}
2021-11-15 01:56:56 -06:00
2022-11-29 02:27:38 -06:00
let mut def_block: PerEntity<Value, Block> = PerEntity::default();
for (block, block_def) in f.blocks.entries() {
2022-12-02 13:58:04 -06:00
for &(_, param) in &block_def.params {
def_block[param] = block;
}
2022-11-29 02:27:38 -06:00
for &value in &block_def.insts {
def_block[value] = block;
}
}
for value in f.values.iter() {
let orig_value = f.resolve_alias(value);
let underlying_value = match &f.values[orig_value] {
&ValueDef::PickOutput(value, ..) => value,
_ => orig_value,
};
def_block[value] = def_block[underlying_value];
}
let mut rpo = postorder;
rpo.reverse();
let rpo = EntityVec::from(rpo);
let mut rpo_pos = PerEntity::default();
for (rpo, &block) in rpo.entries() {
rpo_pos[block] = Some(rpo);
}
2021-11-15 01:56:56 -06:00
CFGInfo {
2022-11-01 22:43:47 -05:00
entry: f.entry,
2021-11-15 01:56:56 -06:00
return_blocks,
rpo,
rpo_pos,
2021-11-15 01:56:56 -06:00
domtree,
2022-11-02 23:26:22 -05:00
domtree_children,
2022-11-29 02:27:38 -06:00
def_block,
2021-11-15 01:56:56 -06:00
}
}
2022-11-01 22:43:47 -05:00
pub fn dominates(&self, a: Block, b: Block) -> bool {
domtree::dominates(&self.domtree, a, b)
}
2022-11-02 23:26:22 -05:00
pub fn dom_children<'a>(&'a self, block: Block) -> DomtreeChildIter<'a> {
DomtreeChildIter {
domtree_children: &self.domtree_children,
block: self.domtree_children[block].child,
}
}
2021-11-15 01:56:56 -06:00
}