Make the out edge verifier happy, when removing unnecessary ia32_Test, by not creatin...
[libfirm] / ir / be / ia32 / ia32_x87.c
index a0fd212..2d59801 100644 (file)
@@ -24,9 +24,7 @@
  * @author      Michael Beck
  * @version     $Id$
  */
-#ifdef HAVE_CONFIG_H
 #include "config.h"
-#endif
 
 #include <assert.h>
 
@@ -139,7 +137,6 @@ typedef unsigned char vfp_liveness;
 struct _x87_simulator {
        struct obstack obst;        /**< An obstack for fast allocating. */
        pmap *blk_states;           /**< Map blocks to states. */
-       const arch_env_t *arch_env; /**< The architecture environment. */
        be_lv_t *lv;                /**< intrablock liveness. */
        vfp_liveness *live;         /**< Liveness information. */
        unsigned n_idx;             /**< The cached get_irg_last_idx() result. */
@@ -445,7 +442,7 @@ static ir_node *get_irn_Proj_for_mode(ir_node *n, ir_mode *m)
 /**
  * Wrap the arch_* function here so we can check for errors.
  */
-static INLINE const arch_register_t *x87_get_irn_register(const ir_node *irn)
+static inline const arch_register_t *x87_get_irn_register(const ir_node *irn)
 {
        const arch_register_t *res = arch_get_irn_register(irn);
 
@@ -453,6 +450,15 @@ static INLINE const arch_register_t *x87_get_irn_register(const ir_node *irn)
        return res;
 }  /* x87_get_irn_register */
 
+static inline const arch_register_t *x87_irn_get_register(const ir_node *irn,
+                                                          int pos)
+{
+       const arch_register_t *res = arch_irn_get_register(irn, pos);
+
+       assert(res->reg_class->regs == ia32_vfp_regs);
+       return res;
+}
+
 /* -------------- x87 perm --------------- */
 
 /**
@@ -472,7 +478,7 @@ static ir_node *x87_fxch_shuffle(x87_state *state, int pos, ir_node *block)
        ir_node         *fxch;
        ia32_x87_attr_t *attr;
 
-       fxch = new_rd_ia32_fxch(NULL, get_irn_irg(block), block);
+       fxch = new_bd_ia32_fxch(NULL, block);
        attr = get_ia32_x87_attr(fxch);
        attr->x87[0] = &ia32_st_regs[pos];
        attr->x87[2] = &ia32_st_regs[0];
@@ -637,12 +643,11 @@ static ir_node *x87_create_fxch(x87_state *state, ir_node *n, int pos)
 {
        ir_node         *fxch;
        ia32_x87_attr_t *attr;
-       ir_graph        *irg = get_irn_irg(n);
        ir_node         *block = get_nodes_block(n);
 
        x87_fxch(state, pos);
 
-       fxch = new_rd_ia32_fxch(NULL, irg, block);
+       fxch = new_bd_ia32_fxch(NULL, block);
        attr = get_ia32_x87_attr(fxch);
        attr->x87[0] = &ia32_st_regs[pos];
        attr->x87[2] = &ia32_st_regs[0];
@@ -670,7 +675,7 @@ static void x87_create_fpush(x87_state *state, ir_node *n, int pos, int op_idx)
 
        x87_push_dbl(state, arch_register_get_index(out), pred);
 
-       fpush = new_rd_ia32_fpush(NULL, get_irn_irg(n), get_nodes_block(n));
+       fpush = new_bd_ia32_fpush(NULL, get_nodes_block(n));
        attr  = get_ia32_x87_attr(fpush);
        attr->x87[0] = &ia32_st_regs[pos];
        attr->x87[2] = &ia32_st_regs[0];
@@ -699,9 +704,9 @@ static ir_node *x87_create_fpop(x87_state *state, ir_node *n, int num)
        while (num > 0) {
                x87_pop(state);
                if (ia32_cg_config.use_ffreep)
-                       fpop = new_rd_ia32_ffreep(NULL, get_irn_irg(n), get_nodes_block(n));
+                       fpop = new_bd_ia32_ffreep(NULL, get_nodes_block(n));
                else
-                       fpop = new_rd_ia32_fpop(NULL, get_irn_irg(n), get_nodes_block(n));
+                       fpop = new_bd_ia32_fpop(NULL, get_nodes_block(n));
                attr = get_ia32_x87_attr(fpop);
                attr->x87[0] = &ia32_st_regs[0];
                attr->x87[1] = &ia32_st_regs[0];
@@ -726,11 +731,10 @@ static ir_node *x87_create_fpop(x87_state *state, ir_node *n, int num)
  */
 static ir_node *x87_create_fldz(x87_state *state, ir_node *n, int regidx)
 {
-       ir_graph *irg = get_irn_irg(n);
        ir_node *block = get_nodes_block(n);
        ir_node *fldz;
 
-       fldz = new_rd_ia32_fldz(NULL, irg, block, mode_E);
+       fldz = new_bd_ia32_fldz(NULL, block, mode_E);
 
        sched_add_before(n, fldz);
        DB((dbg, LEVEL_1, "<<< %s\n", get_irn_opname(fldz)));
@@ -748,18 +752,16 @@ static ir_node *x87_create_fldz(x87_state *state, ir_node *n, int regidx)
  * Updates a live set over a single step from a given node to its predecessor.
  * Everything defined at the node is removed from the set, the uses of the node get inserted.
  *
- * @param sim      The simulator handle.
  * @param irn      The node at which liveness should be computed.
  * @param live     The bitset of registers live before @p irn. This set gets modified by updating it to
  *                 the registers live after irn.
  *
  * @return The live bitset.
  */
-static vfp_liveness vfp_liveness_transfer(x87_simulator *sim, ir_node *irn, vfp_liveness live)
+static vfp_liveness vfp_liveness_transfer(ir_node *irn, vfp_liveness live)
 {
        int i, n;
        const arch_register_class_t *cls = &ia32_reg_classes[CLASS_ia32_vfp];
-       const arch_env_t *arch_env = sim->arch_env;
 
        if (get_irn_mode(irn) == mode_T) {
                const ir_edge_t *edge;
@@ -767,14 +769,14 @@ static vfp_liveness vfp_liveness_transfer(x87_simulator *sim, ir_node *irn, vfp_
                foreach_out_edge(irn, edge) {
                        ir_node *proj = get_edge_src_irn(edge);
 
-                       if (arch_irn_consider_in_reg_alloc(arch_env, cls, proj)) {
+                       if (arch_irn_consider_in_reg_alloc(cls, proj)) {
                                const arch_register_t *reg = x87_get_irn_register(proj);
                                live &= ~(1 << arch_register_get_index(reg));
                        }
                }
        }
 
-       if (arch_irn_consider_in_reg_alloc(arch_env, cls, irn)) {
+       if (arch_irn_consider_in_reg_alloc(cls, irn)) {
                const arch_register_t *reg = x87_get_irn_register(irn);
                live &= ~(1 << arch_register_get_index(reg));
        }
@@ -782,7 +784,8 @@ static vfp_liveness vfp_liveness_transfer(x87_simulator *sim, ir_node *irn, vfp_
        for (i = 0, n = get_irn_arity(irn); i < n; ++i) {
                ir_node *op = get_irn_n(irn, i);
 
-               if (mode_is_float(get_irn_mode(op)) && arch_irn_consider_in_reg_alloc(arch_env, cls, op)) {
+               if (mode_is_float(get_irn_mode(op)) &&
+                               arch_irn_consider_in_reg_alloc(cls, op)) {
                        const arch_register_t *reg = x87_get_irn_register(op);
                        live |= 1 << arch_register_get_index(reg);
                }
@@ -804,13 +807,12 @@ static vfp_liveness vfp_liveness_end_of_block(x87_simulator *sim, const ir_node
        int i;
        vfp_liveness live = 0;
        const arch_register_class_t *cls = &ia32_reg_classes[CLASS_ia32_vfp];
-       const arch_env_t *arch_env = sim->arch_env;
        const be_lv_t *lv = sim->lv;
 
        be_lv_foreach(lv, block, be_lv_state_end, i) {
                const arch_register_t *reg;
                const ir_node *node = be_lv_get_irn(lv, block, i);
-               if (!arch_irn_consider_in_reg_alloc(arch_env, cls, node))
+               if (!arch_irn_consider_in_reg_alloc(cls, node))
                        continue;
 
                reg = x87_get_irn_register(node);
@@ -862,7 +864,7 @@ static void update_liveness(x87_simulator *sim, ir_node *block)
                idx = get_irn_idx(irn);
                sim->live[idx] = live;
 
-               live = vfp_liveness_transfer(sim, irn, live);
+               live = vfp_liveness_transfer(irn, live);
        }
        idx = get_irn_idx(block);
        sim->live[idx] = live;
@@ -931,7 +933,7 @@ static int sim_binop(x87_state *state, ir_node *n, const exchange_tmpl *tmpl)
        ir_node               *op2     = get_irn_n(n, n_ia32_binary_right);
        const arch_register_t *op1_reg = x87_get_irn_register(op1);
        const arch_register_t *op2_reg = x87_get_irn_register(op2);
-       const arch_register_t *out     = x87_get_irn_register(n);
+       const arch_register_t *out     = x87_irn_get_register(n, pn_ia32_res);
        int reg_index_1                = arch_register_get_index(op1_reg);
        int reg_index_2                = arch_register_get_index(op2_reg);
        vfp_liveness           live    = vfp_live_args_after(sim, n, REGMASK(out));
@@ -1149,14 +1151,14 @@ static int sim_unop(x87_state *state, ir_node *n, ir_op *op)
  *
  * @return NO_NODE_ADDED
  */
-static int sim_load(x87_state *state, ir_node *n, ir_op *op)
+static int sim_load(x87_state *state, ir_node *n, ir_op *op, int res_pos)
 {
-       const arch_register_t *out = x87_get_irn_register(n);
+       const arch_register_t *out = x87_irn_get_register(n, res_pos);
        ia32_x87_attr_t *attr;
 
        DB((dbg, LEVEL_1, ">>> %+F -> %s\n", n, arch_register_get_name(out)));
        x87_push(state, arch_register_get_index(out), x87_patch_insn(n, op));
-       assert(out == x87_get_irn_register(n));
+       assert(out == x87_irn_get_register(n, res_pos));
        attr = get_ia32_x87_attr(n);
        attr->x87[2] = out = &ia32_st_regs[0];
        DB((dbg, LEVEL_1, "<<< %s -> %s\n", get_irn_opname(n), arch_register_get_name(out)));
@@ -1259,8 +1261,7 @@ static int sim_store(x87_state *state, ir_node *n, ir_op *op, ir_op *op_p)
                                x87_patch_insn(n, op_p);
 
                                block = get_nodes_block(n);
-                               irg   = get_irn_irg(n);
-                               vfld  = new_rd_ia32_vfld(NULL, irg, block, get_irn_n(n, 0), get_irn_n(n, 1), new_rd_NoMem(irg), get_ia32_ls_mode(n));
+                               vfld  = new_bd_ia32_vfld(NULL, block, get_irn_n(n, 0), get_irn_n(n, 1), new_NoMem(), get_ia32_ls_mode(n));
 
                                /* copy all attributes */
                                set_ia32_frame_ent(vfld, get_ia32_frame_ent(n));
@@ -1271,6 +1272,7 @@ static int sim_store(x87_state *state, ir_node *n, ir_op *op, ir_op *op_p)
                                set_ia32_am_sc(vfld, get_ia32_am_sc(n));
                                set_ia32_ls_mode(vfld, get_ia32_ls_mode(n));
 
+                               irg   = get_irn_irg(n);
                                rproj = new_r_Proj(irg, block, vfld, get_ia32_ls_mode(vfld), pn_ia32_vfld_res);
                                mproj = new_r_Proj(irg, block, vfld, mode_M, pn_ia32_vfld_M);
                                mem   = get_irn_Proj_for_mode(n, mode_M);
@@ -1325,13 +1327,11 @@ static int sim_##op(x87_state *state, ir_node *n) { \
 #define GEN_BINOP(op)   _GEN_BINOP(op, op)
 #define GEN_BINOPR(op) _GEN_BINOP(op, op##r)
 
-#define GEN_LOAD2(op, nop) \
-static int sim_##op(x87_state *state, ir_node *n) { \
-       return sim_load(state, n, op_ia32_##nop); \
+#define GEN_LOAD(op)                                              \
+static int sim_##op(x87_state *state, ir_node *n) {               \
+       return sim_load(state, n, op_ia32_##op, pn_ia32_v##op##_res); \
 }
 
-#define GEN_LOAD(op)   GEN_LOAD2(op, op)
-
 #define GEN_UNOP(op) \
 static int sim_##op(x87_state *state, ir_node *n) { \
        return sim_unop(state, n, op_ia32_##op); \
@@ -1720,15 +1720,12 @@ static int sim_Keep(x87_state *state, ir_node *node)
 
 static void keep_float_node_alive(ir_node *node)
 {
-       ir_graph                    *irg;
-       ir_node                     *block;
+       ir_graph                    *irg    = get_irn_irg(node);
+       ir_node                     *block  = get_nodes_block(node);
+       const arch_register_class_t *cls    = arch_get_irn_reg_class_out(node);
        ir_node                     *in[1];
        ir_node                     *keep;
-       const arch_register_class_t *cls;
 
-       irg    = get_irn_irg(node);
-       block  = get_nodes_block(node);
-       cls    = arch_get_irn_reg_class(node, -1);
        in[0]  = node;
        keep   = be_new_Keep(cls, irg, block, 1, in);
 
@@ -1746,12 +1743,11 @@ static void keep_float_node_alive(ir_node *node)
  */
 static ir_node *create_Copy(x87_state *state, ir_node *n)
 {
-       ir_graph *irg = get_irn_irg(n);
        dbg_info *n_dbg = get_irn_dbg_info(n);
        ir_mode *mode = get_irn_mode(n);
        ir_node *block = get_nodes_block(n);
        ir_node *pred = get_irn_n(n, 0);
-       ir_node *(*cnstr)(dbg_info *, ir_graph *, ir_node *, ir_mode *) = NULL;
+       ir_node *(*cnstr)(dbg_info *, ir_node *, ir_mode *) = NULL;
        ir_node *res;
        const arch_register_t *out;
        const arch_register_t *op1;
@@ -1761,25 +1757,25 @@ static ir_node *create_Copy(x87_state *state, ir_node *n)
        switch (get_ia32_irn_opcode(pred)) {
        case iro_ia32_Unknown_VFP:
        case iro_ia32_fldz:
-               cnstr = new_rd_ia32_fldz;
+               cnstr = new_bd_ia32_fldz;
                break;
        case iro_ia32_fld1:
-               cnstr = new_rd_ia32_fld1;
+               cnstr = new_bd_ia32_fld1;
                break;
        case iro_ia32_fldpi:
-               cnstr = new_rd_ia32_fldpi;
+               cnstr = new_bd_ia32_fldpi;
                break;
        case iro_ia32_fldl2e:
-               cnstr = new_rd_ia32_fldl2e;
+               cnstr = new_bd_ia32_fldl2e;
                break;
        case iro_ia32_fldl2t:
-               cnstr = new_rd_ia32_fldl2t;
+               cnstr = new_bd_ia32_fldl2t;
                break;
        case iro_ia32_fldlg2:
-               cnstr = new_rd_ia32_fldlg2;
+               cnstr = new_bd_ia32_fldlg2;
                break;
        case iro_ia32_fldln2:
-               cnstr = new_rd_ia32_fldln2;
+               cnstr = new_bd_ia32_fldln2;
                break;
        default:
                break;
@@ -1790,7 +1786,7 @@ static ir_node *create_Copy(x87_state *state, ir_node *n)
 
        if (cnstr != NULL) {
                /* copy a constant */
-               res = (*cnstr)(n_dbg, irg, block, mode);
+               res = (*cnstr)(n_dbg, block, mode);
 
                x87_push(state, arch_register_get_index(out), res);
 
@@ -1799,7 +1795,7 @@ static ir_node *create_Copy(x87_state *state, ir_node *n)
        } else {
                int op1_idx = x87_on_stack(state, arch_register_get_index(op1));
 
-               res = new_rd_ia32_fpushCopy(n_dbg, irg, block, pred, mode);
+               res = new_bd_ia32_fpushCopy(n_dbg, block, pred, mode);
 
                x87_push(state, arch_register_get_index(out), res);
 
@@ -1831,7 +1827,7 @@ static int sim_Copy(x87_state *state, ir_node *n)
        int                         op1_idx, out_idx;
        unsigned                    live;
 
-       cls = arch_get_irn_reg_class(n, -1);
+       cls = arch_get_irn_reg_class_out(n);
        if (cls->regs != ia32_vfp_regs)
                return 0;
 
@@ -2009,7 +2005,7 @@ end_call:
  */
 static int sim_Spill(x87_state *state, ir_node *n)
 {
-       assert(0 && "Spill not lowered");
+       panic("Spill not lowered");
        return sim_fst(state, n);
 }  /* sim_Spill */
 
@@ -2023,7 +2019,7 @@ static int sim_Spill(x87_state *state, ir_node *n)
  */
 static int sim_Reload(x87_state *state, ir_node *n)
 {
-       assert(0 && "Reload not lowered");
+       panic("Reload not lowered");
        return sim_fld(state, n);
 }  /* sim_Reload */
 
@@ -2114,7 +2110,6 @@ static int sim_Perm(x87_state *state, ir_node *irn)
 
 static int sim_Barrier(x87_state *state, ir_node *node)
 {
-       //const arch_env_t *arch_env = state->sim->arch_env;
        int i, arity;
 
        /* materialize unknown if needed */
@@ -2134,7 +2129,7 @@ static int sim_Barrier(x87_state *state, ir_node *node)
 
                /* create a zero */
                block = get_nodes_block(node);
-               zero  = new_rd_ia32_fldz(NULL, current_ir_graph, block, mode_E);
+               zero  = new_bd_ia32_fldz(NULL, block, mode_E);
                x87_push(state, arch_register_get_index(reg), zero);
 
                attr = get_ia32_x87_attr(zero);
@@ -2189,10 +2184,10 @@ static x87_state *x87_kill_deads(x87_simulator *sim, ir_node *block, x87_state *
                        if (ia32_cg_config.use_femms || ia32_cg_config.use_emms) {
                                if (ia32_cg_config.use_femms) {
                                        /* use FEMMS on AMD processors to clear all */
-                                       keep = new_rd_ia32_femms(NULL, get_irn_irg(block), block);
+                                       keep = new_bd_ia32_femms(NULL, block);
                                } else {
                                        /* use EMMS to clear all */
-                                       keep = new_rd_ia32_emms(NULL, get_irn_irg(block), block);
+                                       keep = new_bd_ia32_emms(NULL, block);
                                }
                                sched_add_before(first_insn, keep);
                                keep_alive(keep);
@@ -2260,7 +2255,7 @@ static void fix_unknown_phis(x87_state *state, ir_node *block,
                reg = arch_get_irn_register(node);
 
                /* create a zero at end of pred block */
-               zero = new_rd_ia32_fldz(NULL, current_ir_graph, pred_block, mode_E);
+               zero = new_bd_ia32_fldz(NULL, pred_block, mode_E);
                x87_push(state, arch_register_get_index(reg), zero);
 
                attr = get_ia32_x87_attr(zero);
@@ -2373,14 +2368,11 @@ static void register_sim(ir_op *op, sim_func func)
  *
  * @param sim       a simulator handle, will be initialized
  * @param irg       the current graph
- * @param arch_env  the architecture environment
  */
-static void x87_init_simulator(x87_simulator *sim, ir_graph *irg,
-                               const arch_env_t *arch_env)
+static void x87_init_simulator(x87_simulator *sim, ir_graph *irg)
 {
        obstack_init(&sim->obst);
        sim->blk_states = pmap_create();
-       sim->arch_env   = arch_env;
        sim->n_idx      = get_irg_last_idx(irg);
        sim->live       = obstack_alloc(&sim->obst, sizeof(*sim->live) * sim->n_idx);
 
@@ -2439,23 +2431,17 @@ static void update_liveness_walker(ir_node *block, void *data)
        update_liveness(sim, block);
 }  /* update_liveness_walker */
 
-/**
- * Run a simulation and fix all virtual instructions for a graph.
- *
- * @param env       the architecture environment
- * @param irg       the current graph
- *
- * Needs a block-schedule.
- */
-void x87_simulate_graph(const arch_env_t *arch_env, be_irg_t *birg)
+void x87_simulate_graph(be_irg_t *birg)
 {
+       /* TODO improve code quality (less executed fxch) by using execfreqs */
+
        ir_node       *block, *start_block;
        blk_state     *bl_state;
        x87_simulator sim;
        ir_graph      *irg = be_get_birg_irg(birg);
 
        /* create the simulator */
-       x87_init_simulator(&sim, irg, arch_env);
+       x87_init_simulator(&sim, irg);
 
        start_block = get_irg_start_block(irg);
        bl_state    = x87_get_bl_state(&sim, start_block);