be: factor out can_move_to function from sparc_emitter
authorMatthias Braun <matze@braunis.de>
Mon, 17 Oct 2011 13:39:28 +0000 (15:39 +0200)
committerMatthias Braun <matze@braunis.de>
Mon, 17 Oct 2011 16:30:05 +0000 (18:30 +0200)
ir/be/bepeephole.c
ir/be/bepeephole.h
ir/be/sparc/sparc_emitter.c

index 6f971df..a3fa31d 100644 (file)
@@ -248,6 +248,55 @@ 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)
+{
+       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;
+               }
+
+               /* the node must not overwrite registers of our inputs */
+               for (i = 0; i < node_arity; ++i) {
+                       ir_node                   *in  = get_irn_n(node, i);
+                       const arch_register_t     *reg = arch_get_irn_register(in);
+                       const arch_register_req_t *in_req
+                               = arch_get_irn_register_req_in(node, i);
+                       unsigned                   o;
+                       if (reg == NULL)
+                               continue;
+                       for (o = 0; o < n_outs; ++o) {
+                               const arch_register_t *outreg
+                                       = arch_get_irn_register_out(schedpoint, o);
+                               const arch_register_req_t *outreq
+                                       = arch_get_irn_register_req_out(schedpoint, o);
+                               if (outreg == NULL)
+                                       continue;
+                               if (outreg->global_index >= reg->global_index
+                                       && outreg->global_index
+                                          < (unsigned)reg->global_index + in_req->width)
+                                       return false;
+                               if (reg->global_index >= outreg->global_index
+                                       && reg->global_index
+                                          < (unsigned)outreg->global_index + outreq->width)
+                                       return false;
+                       }
+               }
+
+               schedpoint = sched_next(schedpoint);
+       }
+       return true;
+}
+
 /*
  * Tries to optimize a beIncSP node with its previous IncSP node.
  * Must be run from a be_peephole_opt() context.
index fca32e9..3731be4 100644 (file)
@@ -73,6 +73,16 @@ ir_node *be_peephole_IncSP_IncSP(ir_node *node);
 
 bool be_has_only_one_user(ir_node *node);
 
+/**
+ * In a scheduled program with registers assigned,
+ * checks wether @p node can be moved before @p before without changing program
+ * semantics.
+ *
+ * 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);
+
 /**
  * Do peephole optimisations. It traverses the schedule of all blocks in
  * backward direction. The register_values variable indicates which (live)
index c9116ae..cb37079 100644 (file)
@@ -50,6 +50,7 @@
 #include "be_dbgout.h"
 #include "benode.h"
 #include "bestack.h"
+#include "bepeephole.h"
 
 #include "sparc_emitter.h"
 #include "gen_sparc_emitter.h"
@@ -392,85 +393,41 @@ 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)
 {
-       int      node_arity = get_irn_arity(node);
-       ir_node *schedpoint = sched_next(node);
-
-       while (true) {
-               if (schedpoint != to) {
-                       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;
-                       }
-
-                       /* the node must not overwrite registers of our inputs */
-                       for (i = 0; i < node_arity; ++i) {
-                               ir_node                   *in  = get_irn_n(node, i);
-                               const arch_register_t     *reg = arch_get_irn_register(in);
-                               const arch_register_req_t *in_req
-                                       = arch_get_irn_register_req_in(node, i);
-                               unsigned                   o;
-                               if (reg == NULL)
-                                       continue;
-                               for (o = 0; o < n_outs; ++o) {
-                                       const arch_register_t *outreg
-                                               = arch_get_irn_register_out(schedpoint, o);
-                                       const arch_register_req_t *outreq
-                                               = arch_get_irn_register_req_out(schedpoint, o);
-                                       if (outreg == NULL)
-                                               continue;
-                                       if (outreg->global_index >= reg->global_index
-                                               && outreg->global_index
-                                              < (unsigned)reg->global_index + in_req->width)
-                                               return false;
-                                       if (reg->global_index >= outreg->global_index
-                                               && reg->global_index
-                                              < (unsigned)outreg->global_index + outreq->width)
-                                               return false;
-                               }
-                       }
-               } else {
-                       if (is_sparc_Call(to)) {
-                               ir_node *check;
-                               /** all deps are used after the delay slot so, we're fine */
-                               if (!is_sparc_reg_call(to))
-                                       return true;
-
-                               check = get_irn_n(to, get_sparc_Call_dest_addr_pos(to));
-                               if (skip_Proj(check) == node)
-                                       return false;
-
-                               /* the Call also destroys the value of %o7, but since this is
-                                * currently marked as ignore register in the backend, it
-                                * should never be used by the instruction in the delay slot. */
-                               if (uses_reg(node, &sparc_registers[REG_O7]))
-                                       return false;
-                               return true;
-                       } else if (is_sparc_Return(to)) {
-                               /* return uses the value of %o7, all other values are not
-                                * immediately used */
-                               if (writes_reg(node, &sparc_registers[REG_O7]))
-                                       return false;
-                               return true;
-                       } else {
-                               /* the node must not use our computed values */
-                               int arity = get_irn_arity(to);
-                               int i;
-                               for (i = 0; i < arity; ++i) {
-                                       ir_node *in = get_irn_n(to, i);
-                                       if (skip_Proj(in) == node)
-                                               return false;
-                               }
-                               return true;
-                       }
-               }
+       if (!be_can_move_before(node, to))
+               return false;
 
-               schedpoint = sched_next(schedpoint);
+       if (is_sparc_Call(to)) {
+               ir_node *check;
+               /** all deps are used after the delay slot so, we're fine */
+               if (!is_sparc_reg_call(to))
+                       return true;
+
+               check = get_irn_n(to, get_sparc_Call_dest_addr_pos(to));
+               if (skip_Proj(check) == node)
+                       return false;
+
+               /* the Call also destroys the value of %o7, but since this is
+                * currently marked as ignore register in the backend, it
+                * should never be used by the instruction in the delay slot. */
+               if (uses_reg(node, &sparc_registers[REG_O7]))
+                       return false;
+               return true;
+       } else if (is_sparc_Return(to)) {
+               /* return uses the value of %o7, all other values are not
+                * immediately used */
+               if (writes_reg(node, &sparc_registers[REG_O7]))
+                       return false;
+               return true;
+       } else {
+               /* the node must not use our computed values */
+               int arity = get_irn_arity(to);
+               int i;
+               for (i = 0; i < arity; ++i) {
+                       ir_node *in = get_irn_n(to, i);
+                       if (skip_Proj(in) == node)
+                               return false;
+               }
+               return true;
        }
 }