summaryrefslogtreecommitdiffhomepage
path: root/ir/ir
diff options
context:
space:
mode:
authorManuel Mohr <manuel.mohr@kit.edu>2016-12-02 15:40:45 +0100
committerSebastian Buchwald <Sebastian.Buchwald@kit.edu>2016-12-02 22:55:05 +0100
commitf8c28f594d49b97ea97576bef91bfa3c67162943 (patch)
tree92bcc850c656b4f24004aaf0cef4c2b24719e973 /ir/ir
parentc8cc6ed640b8cb353d6b0047d1f0648f40ee7196 (diff)
Add walker to visit nodes in topological order.
Diffstat (limited to 'ir/ir')
-rw-r--r--ir/ir/irgwalk.c32
1 files changed, 32 insertions, 0 deletions
diff --git a/ir/ir/irgwalk.c b/ir/ir/irgwalk.c
index 38c9ec7..bdc8306 100644
--- a/ir/ir/irgwalk.c
+++ b/ir/ir/irgwalk.c
@@ -245,6 +245,38 @@ void irg_walk_in_or_dep_graph(ir_graph *irg, irg_walk_func *pre,
irg_walk_in_or_dep(get_irg_end(irg), pre, post, env);
}
+static void walk_topo_helper(ir_node *irn, irg_walk_func *walker, void *env)
+{
+ if (irn_visited(irn))
+ return;
+
+ /* only break loops at phi/block nodes */
+ const bool is_loop_breaker = is_Phi(irn) || is_Block(irn);
+ if (is_loop_breaker)
+ mark_irn_visited(irn);
+
+ if (!is_Block(irn)) {
+ ir_node *const block = get_nodes_block(irn);
+ walk_topo_helper(block, walker, env);
+ }
+
+ for (int i = 0; i < get_irn_arity(irn); ++i) {
+ ir_node *const pred = get_irn_n(irn, i);
+ walk_topo_helper(pred, walker, env);
+ }
+
+ if (is_loop_breaker || !irn_visited(irn))
+ walker(irn, env);
+
+ mark_irn_visited(irn);
+}
+
+void irg_walk_topological(ir_graph *irg, irg_walk_func *walker, void *env)
+{
+ inc_irg_visited(irg);
+ walk_topo_helper(get_irg_end(irg), walker, env);
+}
+
/** Walks back from n until it finds a real cf op. */
static ir_node *get_cf_op(ir_node *n)
{