Commit 2a7b0497 authored by Jürg Billeter's avatar Jürg Billeter

Use dominance algorithm by Cooper, Harvey, and Kennedy

Improves performance of flow analysis.
parent ae18e9b4
......@@ -41,6 +41,7 @@ public class Vala.BasicBlock {
Set<PhiFunction> phi_functions = new HashSet<PhiFunction> ();
public bool postorder_visited { get; set; }
public int postorder_number { get; set; }
public BasicBlock () {
}
......
......@@ -196,66 +196,40 @@ public class Vala.FlowAnalyzer : CodeVisitor {
foreach (BasicBlock succ in current.get_successors ()) {
depth_first_traverse (succ, list);
}
current.postorder_number = list.size;
list.insert (0, current);
}
void build_dominator_tree (List<BasicBlock> block_list, BasicBlock entry_block) {
// set dom(n) = {E,1,2...,N,X} forall n
var dom = new HashMap<BasicBlock, Set<BasicBlock>> ();
foreach (BasicBlock block in block_list) {
var block_set = new HashSet<BasicBlock> ();
foreach (BasicBlock b in block_list) {
block_set.add (b);
}
dom.set (block, block_set);
}
// immediate dominators
var idoms = new BasicBlock[block_list.size];
idoms[entry_block.postorder_number] = entry_block;
// set dom(E) = {E}
var entry_dom_set = new HashSet<BasicBlock> ();
entry_dom_set.add (entry_block);
dom.set (entry_block, entry_dom_set);
bool changes = true;
while (changes) {
changes = false;
bool changed = true;
while (changed) {
changed = false;
foreach (BasicBlock block in block_list) {
// intersect dom(pred) forall pred: pred = predecessor(s)
var dom_set = new HashSet<BasicBlock> ();
if (block == entry_block) {
continue;
}
// new immediate dominator
BasicBlock new_idom = null;
bool first = true;
foreach (BasicBlock pred in block.get_predecessors ()) {
var pred_dom_set = dom.get (pred);
if (first) {
foreach (BasicBlock dom_block in pred_dom_set) {
dom_set.add (dom_block);
}
first = false;
} else {
var remove_queue = new ArrayList<BasicBlock> ();
foreach (BasicBlock dom_block in dom_set) {
if (!(dom_block in pred_dom_set)) {
remove_queue.add (dom_block);
}
}
foreach (BasicBlock dom_block in remove_queue) {
dom_set.remove (dom_block);
if (idoms[pred.postorder_number] != null) {
if (first) {
new_idom = pred;
first = false;
} else {
new_idom = intersect (idoms, pred, new_idom);
}
}
}
// unite with s
dom_set.add (block);
// check for changes
if (dom.get (block).size != dom_set.size) {
changes = true;
} else {
foreach (BasicBlock dom_block in dom.get (block)) {
if (!(dom_block in dom_set)) {
changes = true;
}
}
if (idoms[block.postorder_number] != new_idom) {
idoms[block.postorder_number] = new_idom;
changed = true;
}
// update set in map
dom.set (block, dom_set);
}
}
......@@ -265,25 +239,20 @@ public class Vala.FlowAnalyzer : CodeVisitor {
continue;
}
BasicBlock immediate_dominator = null;
foreach (BasicBlock dominator in dom.get (block)) {
if (dominator == block) {
continue;
}
idoms[block.postorder_number].add_child (block);
}
}
if (immediate_dominator == null) {
immediate_dominator = dominator;
} else {
// if immediate_dominator dominates dominator,
// update immediate_dominator
if (immediate_dominator in dom.get (dominator)) {
immediate_dominator = dominator;
}
}
BasicBlock intersect (BasicBlock[] idoms, BasicBlock b1, BasicBlock b2) {
while (b1 != b2) {
while (b1.postorder_number < b2.postorder_number) {
b1 = idoms[b2.postorder_number];
}
while (b2.postorder_number < b1.postorder_number) {
b2 = idoms[b2.postorder_number];
}
immediate_dominator.add_child (block);
}
return b1;
}
void build_dominator_frontier (List<BasicBlock> block_list, BasicBlock entry_block) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment