bepeephole: reachability check in can_move_before
authorMatthias Braun <matze@braunis.de>
Wed, 9 Nov 2011 18:22:09 +0000 (19:22 +0100)
committerMatthias Braun <matze@braunis.de>
Wed, 9 Nov 2011 18:30:02 +0000 (19:30 +0100)
before we only tested, if we produce an output that is used as as input
of any schedule node in between. This missed the case where you have
unscheduled utility nodes like Sync in between.

ir/be/bepeephole.c
ir/be/bepeephole.h
ir/be/sparc/sparc_emitter.c
ir/be/sparc/sparc_finish.c

index a3fa31d..03e47fc 100644 (file)
@@ -33,6 +33,7 @@
 #include "irprintf.h"
 #include "ircons.h"
 #include "irgmod.h"
+#include "heights.h"
 #include "error.h"
 
 #include "beirg.h"
@@ -248,22 +249,19 @@ bool be_has_only_one_user(ir_node *node)
        return n_users == 1;
 }
 
-bool be_can_move_before(const ir_node *node, const ir_node *before)
+bool be_can_move_before(ir_heights_t *heights, const ir_node *node,
+                        const ir_node *before)
 {
        int      node_arity = get_irn_arity(node);
        ir_node *schedpoint = sched_next(node);
 
        while (schedpoint != before) {
                int      i;
-               int      arity  = get_irn_arity(schedpoint);
                unsigned n_outs = arch_get_irn_n_outs(schedpoint);
 
                /* the node must not use our computed values */
-               for (i = 0; i < arity; ++i) {
-                       ir_node *in = get_irn_n(schedpoint, i);
-                       if (skip_Proj(in) == node)
-                               return false;
-               }
+               if (heights_reachable_in_block(heights, schedpoint, node))
+                       return false;
 
                /* the node must not overwrite registers of our inputs */
                for (i = 0; i < node_arity; ++i) {
index 3731be4..c31d66c 100644 (file)
@@ -81,7 +81,8 @@ bool be_has_only_one_user(ir_node *node);
  * Note: It is allowed to use this function without being in a peephole
  * optimization phase.
  */
-bool be_can_move_before(const ir_node *node, const ir_node *before);
+bool be_can_move_before(ir_heights_t *heights, const ir_node *node,
+                        const ir_node *before);
 
 /**
  * Do peephole optimisations. It traverses the schedule of all blocks in
index c8fe24d..a44892b 100644 (file)
@@ -401,7 +401,7 @@ static bool writes_reg(const ir_node *node, const arch_register_t *reg)
 
 static bool can_move_into_delayslot(const ir_node *node, const ir_node *to)
 {
-       if (!be_can_move_before(node, to))
+       if (!be_can_move_before(heights, node, to))
                return false;
 
        if (is_sparc_Call(to)) {
index 03c7aa5..cfde1ff 100644 (file)
@@ -47,6 +47,7 @@
 #include "irgmod.h"
 #include "ircons.h"
 #include "irgwalk.h"
+#include "heights.h"
 
 #include "bepeephole.h"
 #include "benode.h"
@@ -55,6 +56,8 @@
 #include "bestack.h"
 #include "beirgmod.h"
 
+static ir_heights_t *heights;
+
 static void kill_unused_stacknodes(ir_node *node)
 {
        if (get_irn_n_edges(node) > 0)
@@ -505,13 +508,13 @@ static void peephole_sparc_RestoreZero(ir_node *node)
                if (!is_restorezeroopt_reg(reg))
                        continue;
 
-               if (be_is_Copy(schedpoint) && be_can_move_before(schedpoint, node)) {
+               if (be_is_Copy(schedpoint) && be_can_move_before(heights, schedpoint, node)) {
                        ir_node *op = get_irn_n(schedpoint, n_be_Copy_op);
                        replace_with_restore_imm(node, schedpoint, op, NULL, 0);
                } else if (is_sparc_Or(schedpoint) &&
                           arch_get_irn_flags(schedpoint) & ((arch_irn_flags_t)sparc_arch_irn_flag_immediate_form) &&
                           arch_get_irn_register_in(schedpoint, 0) == &sparc_registers[REG_G0] &&
-                          be_can_move_before(schedpoint, node)) {
+                          be_can_move_before(heights, schedpoint, node)) {
                        /* it's a constant */
                        const sparc_attr_t *attr      = get_sparc_attr_const(schedpoint);
                        ir_entity          *entity    = attr->immediate_value_entity;
@@ -519,7 +522,7 @@ static void peephole_sparc_RestoreZero(ir_node *node)
                        ir_node            *g0        = get_irn_n(schedpoint, 0);
                        replace_with_restore_imm(node, schedpoint, g0, entity, immediate);
                } else if (is_sparc_Add(schedpoint) &&
-                          be_can_move_before(schedpoint, node)) {
+                          be_can_move_before(heights, schedpoint, node)) {
                        if (arch_get_irn_flags(schedpoint) & ((arch_irn_flags_t)sparc_arch_irn_flag_immediate_form)) {
                                ir_node            *op     = get_irn_n(schedpoint, 0);
                                const sparc_attr_t *attr   = get_sparc_attr_const(schedpoint);
@@ -534,7 +537,7 @@ static void peephole_sparc_RestoreZero(ir_node *node)
                } else if (is_sparc_Sub(schedpoint) &&
                           arch_get_irn_flags(schedpoint) & ((arch_irn_flags_t)sparc_arch_irn_flag_immediate_form) &&
                           arch_get_irn_register_in(schedpoint, 0) == &sparc_registers[REG_G0] &&
-                          be_can_move_before(schedpoint, node)) {
+                          be_can_move_before(heights, schedpoint, node)) {
                        /* it's a constant */
                        const sparc_attr_t *attr   = get_sparc_attr_const(schedpoint);
                        ir_entity          *entity = attr->immediate_value_entity;
@@ -642,6 +645,8 @@ void sparc_finish(ir_graph *irg)
        be_abi_fix_stack_nodes(irg);
        sparc_fix_stack_bias(irg);
 
+       heights = heights_new(irg);
+
        /* perform peephole optimizations */
        clear_irp_opcodes_generic_func();
        register_peephole_optimisation(op_be_IncSP,        peephole_be_IncSP);
@@ -662,5 +667,7 @@ void sparc_finish(ir_graph *irg)
        register_peephole_optimisation(op_sparc_Stf,       finish_sparc_Stf);
        be_peephole_opt(irg);
 
+       heights_free(heights);
+
        be_remove_dead_nodes_from_schedule(irg);
 }