fixed fxch emitter
[libfirm] / ir / be / belower.c
index 80d6a7a..ae3db13 100644 (file)
 #include "iredges_t.h"
 #include "irgwalk.h"
 
-#ifdef _WIN32
-#include <malloc.h>
-#else
-#include <alloca.h>
+#ifdef HAVE_MALLOC_H
+ #include <malloc.h>
+#endif
+#ifdef HAVE_ALLOCA_H
+ #include <alloca.h>
 #endif
 
 #undef is_Perm
@@ -42,7 +43,7 @@
 typedef struct _lower_env_t {
        be_chordal_env_t  *chord_env;
        int                do_copy;
-       firm_dbg_module_t *dbg_module;
+       DEBUG_ONLY(firm_dbg_module_t *dbg_module;)
 } lower_env_t;
 
 /* holds a perm register pair */
@@ -247,7 +248,6 @@ static perm_cycle_t *get_perm_cycle(perm_cycle_t *cycle, reg_pair_t *pairs, int
 static void lower_perm_node(ir_node *irn, void *walk_env) {
        const arch_register_class_t *reg_class;
        const arch_env_t            *arch_env;
-       firm_dbg_module_t           *mod;
        lower_env_t     *env = walk_env;
        reg_pair_t      *pairs;
        const ir_edge_t *edge;
@@ -256,10 +256,11 @@ static void lower_perm_node(ir_node *irn, void *walk_env) {
        ir_node         *sched_point, *block, *in[2];
        ir_node         *arg1, *arg2, *res1, *res2;
        ir_node         *cpyxchg = NULL;
+       DEBUG_ONLY(firm_dbg_module_t *mod;)
 
        arch_env = env->chord_env->birg->main_env->arch_env;
        do_copy  = env->do_copy;
-       mod      = env->dbg_module;
+       DEBUG_ONLY(mod = env->dbg_module;)
        block    = get_nodes_block(irn);
 
        /*
@@ -409,16 +410,16 @@ static void lower_perm_node(ir_node *irn, void *walk_env) {
                                        int pidx = get_pairidx_for_regidx(pairs, n, cycle->elems[i]->index, 0);
 
                                        /* create intermediate proj */
-                                       res2 = new_r_Proj(get_irn_irg(irn), block, cpyxchg, get_irn_mode(res1), 0);
+                                       res1 = new_r_Proj(get_irn_irg(irn), block, cpyxchg, get_irn_mode(res1), 0);
 
                                        /* set as in for next Perm */
-                                       pairs[pidx].in_node = res2;
+                                       pairs[pidx].in_node = res1;
                                }
                                else {
-                                       sched_remove(res2);
+                                       sched_remove(res1);
                                }
 
-                               sched_remove(res1);
+                               sched_remove(res2);
 
                                set_Proj_pred(res2, cpyxchg);
                                set_Proj_proj(res2, 0);
@@ -430,6 +431,14 @@ static void lower_perm_node(ir_node *irn, void *walk_env) {
 
                                arch_set_irn_register(arch_env, res2, cycle->elems[i + 1]);
                                arch_set_irn_register(arch_env, res1, cycle->elems[i]);
+
+                               /* insert the copy/exchange node in schedule after the magic schedule node (see above) */
+                               sched_add_after(sched_point, cpyxchg);
+
+                               DBG((mod, LEVEL_1, "replacing %+F with %+F, placed new node after %+F\n", irn, cpyxchg, sched_point));
+
+                               /* set the new scheduling point */
+                               sched_point = res1;
                        }
                        else {
                                DBG((mod, LEVEL_1, "%+F creating copy node (%+F, %s) -> (%+F, %s)\n",
@@ -443,14 +452,13 @@ static void lower_perm_node(ir_node *irn, void *walk_env) {
 
                                /* exchange copy node and proj */
                                exchange(res2, cpyxchg);
-                       }
 
-                       /* insert the copy/exchange node in schedule after the magic schedule node (see above) */
-                       sched_add_after(sched_point, cpyxchg);
-                       /* set the new scheduling point */
-                       sched_point = cpyxchg;
+                               /* insert the copy/exchange node in schedule after the magic schedule node (see above) */
+                               sched_add_after(sched_point, cpyxchg);
 
-                       DBG((mod, LEVEL_1, "replacing %+F with %+F, placed new node after %+F\n", irn, cpyxchg, sched_point));
+                               /* set the new scheduling point */
+                               sched_point = cpyxchg;
+                       }
                }
 
                free((void *) cycle->elems);
@@ -481,9 +489,10 @@ static ir_node *belower_skip_proj(ir_node *irn) {
 }
 
 static void fix_in(ir_node *irn, ir_node *old, ir_node *nw) {
-       int i, n = get_irn_arity(irn);
+       int i, n;
 
        irn = belower_skip_proj(irn);
+       n   = get_irn_arity(irn);
 
        for (i = 0; i < n; i++) {
                if (get_irn_n(irn, i) == old) {
@@ -497,11 +506,11 @@ static void gen_assure_different_pattern(ir_node *irn, be_irg_t *birg, ir_node *
        const arch_env_t          *arch_env = birg->main_env->arch_env;
        ir_node                   *in[2], *keep, *cpy, *temp;
        ir_node                   *block = get_nodes_block(irn);
-       firm_dbg_module_t         *mod   = firm_dbg_register("firm.be.lower");
        const arch_register_class_t *cls = arch_get_irn_reg_class(arch_env, other_different, -1);
+       FIRM_DBG_REGISTER(firm_dbg_module_t *mod, "firm.be.lower");
 
-       if (arch_irn_is_ignore(arch_env, other_different)) {
-               DBG((mod, LEVEL_1, "ignore constraint for %+F because other_irn is ignore\n", irn));
+       if (arch_irn_is(arch_env, other_different, ignore) || ! mode_is_datab(get_irn_mode(other_different))) {
+               DBG((mod, LEVEL_1, "ignore constraint for %+F because other_irn is ignore or not a datab node\n", irn));
                return;
        }
 
@@ -517,22 +526,23 @@ static void gen_assure_different_pattern(ir_node *irn, be_irg_t *birg, ir_node *
        in[0] = irn;
        in[1] = cpy;
 
+       /* Let the irn use the copy instead of the old other_different */
+       fix_in(irn, other_different, cpy);
+
        /* Add the Keep resp. CopyKeep and reroute the users */
        /* of the other_different irn in case of CopyKeep.   */
-       if (get_n_out_edges(other_different) == 1) {
+       if (get_n_out_edges(other_different) == 0) {
                keep = be_new_Keep(cls, birg->irg, block, 2, in);
        }
        else {
-               keep = be_new_CopyKeep(cls, birg->irg, block, cpy, 2, in, get_irn_mode(other_different));
+               keep = be_new_CopyKeep_single(cls, birg->irg, block, cpy, irn, get_irn_mode(other_different));
+               be_node_set_reg_class(keep, 1, cls);
                edges_reroute(other_different, keep, birg->irg);
        }
 
        /* after rerouting: let the copy point to the other_different irn */
        set_irn_n(cpy, 0, other_different);
 
-       /* Let the irn use the copy instead of the old other_different */
-       fix_in(irn, other_different, cpy);
-
        DBG((mod, LEVEL_1, "created %+F for %+F to assure should_be_different\n", keep, irn));
 }
 
@@ -625,7 +635,7 @@ void lower_nodes_after_ra(be_chordal_env_t *chord_env, int do_copy) {
 
        env.chord_env  = chord_env;
        env.do_copy    = do_copy;
-       env.dbg_module = firm_dbg_register("firm.be.lower");
+       FIRM_DBG_REGISTER(env.dbg_module, "firm.be.lower");
 
        irg_walk_blkwise_graph(chord_env->irg, NULL, lower_nodes_after_ra_walker, &env);
 }