Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Common sub-expression elimination pass #6413

Merged
merged 24 commits into from
Sep 23, 2024
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
3d317ed
value numbering analysis
vaivaswatha Jul 26, 2024
f5a48de
initialize PHIs too
vaivaswatha Jul 29, 2024
4a1cf03
Add CSE optimization and update unit tests
vaivaswatha Aug 14, 2024
bc8d055
Merge branch 'master' into vaivaswatha/cse
vaivaswatha Aug 14, 2024
504783c
do not replace consts
vaivaswatha Aug 15, 2024
10561bf
spell fix
vaivaswatha Aug 15, 2024
03963c5
Should not combine 2 PHIs, they may be in different loops
vaivaswatha Aug 16, 2024
1452888
clippy fix
vaivaswatha Aug 16, 2024
8462fdf
update tests
vaivaswatha Aug 16, 2024
d1e035c
remove dbg prints
vaivaswatha Aug 19, 2024
e4a11bb
Merge branch 'master' into vaivaswatha/cse
vaivaswatha Aug 19, 2024
1b30fd2
Merge branch 'master' into vaivaswatha/cse
vaivaswatha Aug 19, 2024
dabff28
Merge branch 'master' into vaivaswatha/cse
IGI-111 Aug 22, 2024
b1aec9f
Merge branch 'master' into vaivaswatha/cse
vaivaswatha Aug 25, 2024
99a32da
Merge branch 'vaivaswatha/cse' of github.com:FuelLabs/sway into vaiva…
vaivaswatha Aug 25, 2024
0e06fb8
Merge branch 'master' into vaivaswatha/cse
IGI-111 Aug 26, 2024
4988927
Merge branch 'master' into vaivaswatha/cse
vaivaswatha Aug 28, 2024
531e43f
Merge branch 'master' into vaivaswatha/cse
sdankel Aug 29, 2024
9f26596
Merge branch 'master' into vaivaswatha/cse
vaivaswatha Sep 2, 2024
89704bb
Merge branch 'master' into vaivaswatha/cse
IGI-111 Sep 2, 2024
87d1df3
Merge branch 'master' into vaivaswatha/cse
vaivaswatha Sep 9, 2024
a90df95
Fix tests and run cargo fmt
vaivaswatha Sep 9, 2024
8e3f2ca
Merge branch 'master' into vaivaswatha/cse
vaivaswatha Sep 20, 2024
6246528
Merge branch 'master' into vaivaswatha/cse
IGI-111 Sep 23, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 36 additions & 15 deletions sway-ir/src/analysis/dominator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ impl DomTreeNode {
}

// The dominator tree is represented by mapping each Block to its DomTreeNode.
pub type DomTree = FxIndexMap<Block, DomTreeNode>;
#[derive(Default)]
pub struct DomTree(FxIndexMap<Block, DomTreeNode>);
impl AnalysisResultT for DomTree {}

// Dominance frontier sets.
Expand Down Expand Up @@ -120,11 +121,11 @@ fn compute_dom_tree(
let entry = function.get_entry_block(context);

// This is to make the algorithm happy. It'll be changed to None later.
dom_tree.insert(entry, DomTreeNode::new(Some(entry)));
dom_tree.0.insert(entry, DomTreeNode::new(Some(entry)));
// initialize the dominators tree. This allows us to do dom_tree[b] fearlessly.
// Note that we just previously initialized "entry", so we skip that here.
for b in po.po_to_block.iter().take(po.po_to_block.len() - 1) {
dom_tree.insert(*b, DomTreeNode::new(None));
dom_tree.0.insert(*b, DomTreeNode::new(None));
}
let mut changed = true;

Expand All @@ -149,12 +150,12 @@ fn compute_dom_tree(
.pred_iter(context)
.filter(|p| **p != picked_pred && po.block_to_po.contains_key(p))
{
if dom_tree[p].parent.is_some() {
if dom_tree.0[p].parent.is_some() {
// if doms[p] already calculated
new_idom = intersect(po, &dom_tree, *p, new_idom);
}
}
let b_node = dom_tree.get_mut(b).unwrap();
let b_node = dom_tree.0.get_mut(b).unwrap();
match b_node.parent {
Some(idom) if idom == new_idom => {}
_ => {
Expand All @@ -175,29 +176,49 @@ fn compute_dom_tree(
) -> Block {
while finger1 != finger2 {
while po.block_to_po[&finger1] < po.block_to_po[&finger2] {
finger1 = dom_tree[&finger1].parent.unwrap();
finger1 = dom_tree.0[&finger1].parent.unwrap();
}
while po.block_to_po[&finger2] < po.block_to_po[&finger1] {
finger2 = dom_tree[&finger2].parent.unwrap();
finger2 = dom_tree.0[&finger2].parent.unwrap();
}
}
finger1
}

// Fix the root.
dom_tree.get_mut(&entry).unwrap().parent = None;
dom_tree.0.get_mut(&entry).unwrap().parent = None;
// Build the children.
let child_parent: Vec<_> = dom_tree
.0
.iter()
.filter_map(|(n, n_node)| n_node.parent.map(|n_parent| (*n, n_parent)))
.collect();
for (child, parent) in child_parent {
dom_tree.get_mut(&parent).unwrap().children.push(child);
dom_tree.0.get_mut(&parent).unwrap().children.push(child);
}

Ok(Box::new(dom_tree))
}

impl DomTree {
/// Does `dominator` dominate `dominatee`?
pub fn dominates(&self, dominator: Block, dominatee: Block) -> bool {
let mut node_opt = Some(dominatee);
while let Some(node) = node_opt {
if node == dominator {
return true;
}
node_opt = self.0[&node].parent;
}
false
}

/// Get an iterator over the childre nodes
pub fn children(&self, node: Block) -> impl Iterator<Item = Block> + '_ {
self.0[&node].children.iter().cloned()
}
}

pub const DOM_FRONTS_NAME: &str = "dominance-frontiers";

pub fn create_dom_fronts_pass() -> Pass {
Expand All @@ -217,23 +238,23 @@ fn compute_dom_fronts(
) -> Result<AnalysisResult, IrError> {
let dom_tree: &DomTree = analyses.get_analysis_result(function);
let mut res = DomFronts::default();
for (b, _) in dom_tree.iter() {
for (b, _) in dom_tree.0.iter() {
res.insert(*b, IndexSet::default());
}

// for all nodes, b
for (b, _) in dom_tree.iter() {
for (b, _) in dom_tree.0.iter() {
// if the number of predecessors of b >= 2
if b.num_predecessors(context) > 1 {
// unwrap() is safe as b is not "entry", and hence must have idom.
let b_idom = dom_tree[b].parent.unwrap();
let b_idom = dom_tree.0[b].parent.unwrap();
// for all (reachable) predecessors, p, of b
for p in b.pred_iter(context).filter(|&p| dom_tree.contains_key(p)) {
for p in b.pred_iter(context).filter(|&p| dom_tree.0.contains_key(p)) {
let mut runner = *p;
while runner != b_idom {
// add b to runner’s dominance frontier set
res.get_mut(&runner).unwrap().insert(*b);
runner = dom_tree[&runner].parent.unwrap();
runner = dom_tree.0[&runner].parent.unwrap();
}
}
}
Expand All @@ -244,7 +265,7 @@ fn compute_dom_fronts(
/// Print dominator tree in the graphviz dot format.
pub fn print_dot(context: &Context, func_name: &str, dom_tree: &DomTree) -> String {
let mut res = format!("digraph {func_name} {{\n");
for (b, idom) in dom_tree.iter() {
for (b, idom) in dom_tree.0.iter() {
if let Some(idom) = idom.parent {
let _ = writeln!(
res,
Expand Down
6 changes: 3 additions & 3 deletions sway-ir/src/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,19 +205,19 @@ pub enum FuelVmInstruction {
}

/// Comparison operations.
#[derive(Debug, Clone, Copy, Hash)]
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
pub enum Predicate {
Equal,
LessThan,
GreaterThan,
}

#[derive(Debug, Clone, Copy, Hash)]
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
pub enum UnaryOpKind {
Not,
}

#[derive(Debug, Clone, Copy, Hash)]
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
pub enum BinaryOpKind {
Add,
Sub,
Expand Down
2 changes: 2 additions & 0 deletions sway-ir/src/optimize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ pub mod const_demotion;
pub use const_demotion::*;
pub mod constants;
pub use constants::*;
pub mod cse;
pub use cse::*;
pub mod dce;
pub use dce::*;
pub mod inline;
Expand Down
Loading
Loading