From: Jürg Billeter Date: Wed, 23 Dec 2009 19:55:52 +0000 (+0100) Subject: Use dominance algorithm by Cooper, Harvey, and Kennedy X-Git-Tag: 0.7.10~142 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=2a7b0497aa1a9ea11c9479efaef5efff3d572525;p=thirdparty%2Fvala.git Use dominance algorithm by Cooper, Harvey, and Kennedy Improves performance of flow analysis. --- diff --git a/vala/valabasicblock.vala b/vala/valabasicblock.vala index c69f6c663..7339224d5 100644 --- a/vala/valabasicblock.vala +++ b/vala/valabasicblock.vala @@ -41,6 +41,7 @@ public class Vala.BasicBlock { Set phi_functions = new HashSet (); public bool postorder_visited { get; set; } + public int postorder_number { get; set; } public BasicBlock () { } diff --git a/vala/valaflowanalyzer.vala b/vala/valaflowanalyzer.vala index 5cb8f1fbf..878936d38 100644 --- a/vala/valaflowanalyzer.vala +++ b/vala/valaflowanalyzer.vala @@ -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 block_list, BasicBlock entry_block) { - // set dom(n) = {E,1,2...,N,X} forall n - var dom = new HashMap> (); - foreach (BasicBlock block in block_list) { - var block_set = new HashSet (); - 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 (); - 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 (); + 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 (); - 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 block_list, BasicBlock entry_block) {