Do not emit cld in the CopyB prologue. The ABI mandates that DF is cleared, so do...
[libfirm] / ir / be / belower.c
index 872bd37..ea759db 100644 (file)
@@ -38,6 +38,7 @@
 #include "irgmod.h"
 #include "iredges_t.h"
 #include "irgwalk.h"
+#include "array_t.h"
 
 #include "bearch_t.h"
 #include "belower.h"
@@ -224,7 +225,7 @@ static perm_cycle_t *get_perm_cycle(perm_cycle_t *cycle, reg_pair_t *pairs, int
        }
 
        /* assume worst case: all remaining pairs build a cycle or chain */
-       cycle->elems    = xcalloc((n - n_pairs_done) * 2, sizeof(cycle->elems[0]));
+       cycle->elems    = XMALLOCNZ(const arch_register_t*, (n - n_pairs_done) * 2);
        cycle->n_elems  = 2;  /* initial number of elements is 2 */
        cycle->elems[0] = pairs[start].in_reg;
        cycle->elems[1] = pairs[start].out_reg;
@@ -289,7 +290,6 @@ static void lower_perm_node(ir_node *irn, void *walk_env) {
        int             n, i, pn, do_copy, j, n_ops;
        reg_pair_t      *pairs;
        const ir_edge_t *edge;
-       perm_cycle_t    *cycle;
        ir_node         *sched_point, *block, *in[2];
        ir_node         *arg1, *arg2, *res1, *res2;
        ir_node         *cpyxchg = NULL;
@@ -364,15 +364,15 @@ static void lower_perm_node(ir_node *irn, void *walk_env) {
 
        real_size = n - get_n_checked_pairs(pairs, n);
 
-       be_do_stat_perm(reg_class->name, reg_class->n_regs, irn, block, n, real_size);
-
        /* check for cycles and chains */
        while (get_n_checked_pairs(pairs, n) < n) {
+               perm_cycle_t *cycle;
+
                i = n_ops = 0;
 
                /* go to the first not-checked pair */
                while (pairs[i].checked) i++;
-               cycle = xcalloc(1, sizeof(*cycle));
+               cycle = XMALLOCZ(perm_cycle_t);
                cycle = get_perm_cycle(cycle, pairs, n, i);
 
                DB((mod, LEVEL_1, "%+F: following %s created:\n  ", irn, cycle->type == PERM_CHAIN ? "chain" : "cycle"));
@@ -495,8 +495,6 @@ static void lower_perm_node(ir_node *irn, void *walk_env) {
                        }
                }
 
-               be_do_stat_permcycle(reg_class->name, irn, block, cycle->type == PERM_CHAIN, cycle->n_elems, n_ops);
-
                free((void *) cycle->elems);
                free(cycle);
        }
@@ -620,7 +618,8 @@ static void gen_assure_different_pattern(ir_node *irn, ir_node *other_different,
  */
 static void assure_different_constraints(ir_node *irn, constraint_env_t *env) {
        const arch_register_req_t *req;
-       const arch_env_t          *arch_env = be_get_birg_arch_env(env->birg);
+       const arch_env_t          *arch_env    = be_get_birg_arch_env(env->birg);
+       ir_node                   *skipped_irn = belower_skip_proj(irn);
 
        req = arch_get_register_req(arch_env, irn, -1);
 
@@ -639,14 +638,14 @@ static void assure_different_constraints(ir_node *irn, constraint_env_t *env) {
                                 * We can safely ignore a should_be_same x must_be_different y
                                 * IFF both inputs are equal!
                                 */
-                               if (get_irn_n(irn, idx_other) == get_irn_n(irn, idx_same)) {
+                               if (get_irn_n(skipped_irn, idx_other) == get_irn_n(skipped_irn, idx_same)) {
                                        return;
                                }
                        }
                }
                for (i = 0; 1U << i <= other; ++i) {
                        if (other & (1U << i)) {
-                               ir_node *different_from = get_irn_n(belower_skip_proj(irn), i);
+                               ir_node *different_from = get_irn_n(skipped_irn, i);
                                gen_assure_different_pattern(irn, different_from, env);
                        }
                }
@@ -800,8 +799,6 @@ void assure_constraints(be_irg_t *birg) {
        ir_node          **nodes;
        FIRM_DBG_REGISTER(firm_dbg_module_t *mod, "firm.be.lower.constr");
 
-       be_assure_dom_front(birg);
-
        DEBUG_ONLY(cenv.dbg = mod;)
        cenv.birg   = birg;
        cenv.op_set = new_pset(cmp_op_copy_assoc, 16);
@@ -894,35 +891,36 @@ static int push_through_perm(ir_node *perm, void *data)
        bitset_t *moved   = bitset_alloca(arity);
        int n_moved;
        int new_size;
-       ir_node *frontier = sched_first(bl);
+       ir_node *frontier = bl;
        FIRM_DBG_REGISTER(firm_dbg_module_t *mod, "firm.be.lower.permmove");
 
        int i, n;
        const ir_edge_t *edge;
-       ir_node *last_proj = NULL, *irn;
+       ir_node *one_proj = NULL, *irn;
        const arch_register_class_t *cls = NULL;
 
        DBG((mod, LEVEL_1, "perm move %+F irg %+F\n", perm, irg));
 
-       /* get some proj and find out the register class of the proj. */
-       foreach_out_edge (perm, edge) {
-               last_proj  = get_edge_src_irn(edge);
-               cls = arch_get_irn_reg_class(aenv, last_proj, -1);
-               assert(is_Proj(last_proj));
-               break;
-       }
+       /* get some Proj and find out the register class of that Proj. */
+       edge     = get_irn_out_edge_first_kind(perm, EDGE_KIND_NORMAL);
+       one_proj = get_edge_src_irn(edge);
+       assert(is_Proj(one_proj));
+       cls      = arch_get_irn_reg_class(aenv, one_proj, -1);
 
-       /* find the point in the schedule after which the
+       /* Find the point in the schedule after which the
         * potentially movable nodes must be defined.
-        * A perm will only be pushed up to first instruction
-        * which lets an operand of itself die.  */
-
+        * A Perm will only be pushed up to first instruction
+        * which lets an operand of itself die.
+        * If we would allow to move the Perm above this instruction,
+        * the former dead operand would be live now at the point of
+        * the Perm, increasing the register pressure by one.
+        */
        sched_foreach_reverse_from (sched_prev(perm), irn) {
-               for(i = get_irn_arity(irn) - 1; i >= 0; --i) {
+               for (i = get_irn_arity(irn) - 1; i >= 0; --i) {
                        ir_node *op = get_irn_n(irn, i);
-                       if(arch_irn_consider_in_reg_alloc(aenv, cls, op)
-                               && !values_interfere(env->birg, op, last_proj)) {
-                               frontier = sched_next(irn);
+                       if (arch_irn_consider_in_reg_alloc(aenv, cls, op) &&
+                           !values_interfere(env->birg, op, one_proj)) {
+                               frontier = irn;
                                goto found_front;
                        }
                }
@@ -938,11 +936,12 @@ found_front:
                int                        input = -1;
                ir_node                   *proj;
 
+               /* search if node is a INPUT of Perm */
                foreach_out_edge(perm, edge) {
                        ir_node *out = get_edge_src_irn(edge);
                        int      pn  = get_Proj_proj(out);
                        ir_node *in  = get_irn_n(perm, pn);
-                       if(node == in) {
+                       if (node == in) {
                                proj  = out;
                                input = pn;
                                break;