*
* $Id$
*/
-
#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif /* HAVE_CONFIG_H */
+#include <config.h>
+#endif
#include <assert.h>
#include "iredges_t.h"
#include "irgmod.h"
#include "ircons.h"
+#include "irgwalk.h"
#include "obst.h"
#include "pmap.h"
#include "pdeq.h"
#define N_x87_REGS 8
/* first and second binop index */
-#define BINOP_IDX_1 2
+#define BINOP_IDX_1 2
#define BINOP_IDX_2 3
/* the unop index */
-#define UNOP_IDX 0
+#define UNOP_IDX 0
/* the store val index */
#define STORE_VAL_IDX 2
* The x87 simulator.
*/
struct _x87_simulator {
- struct obstack obst; /**< An obstack for fast allocating. */
- pmap *blk_states; /**< Map blocks to states. */
- const arch_env_t *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. */
- waitq *worklist; /**< list of blocks to process. */
+ 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. */
+ waitq *worklist; /**< list of blocks to process. */
};
/**
return state->depth;
}
+#if 0
/**
* Check if the state is empty.
*
static int x87_state_is_empty(const x87_state *state) {
return state->depth == 0;
}
+#endif
/**
* Return the virtual register index at st(pos).
int i;
for (i = state->depth - 1; i >= 0; --i) {
- DB((dbg, LEVEL_2, "vf%d ", x87_get_st_reg(state, i)));
+ DB((dbg, LEVEL_2, "vf%d(%+F) ", x87_get_st_reg(state, i),
+ x87_get_st_node(state, i)));
}
DB((dbg, LEVEL_2, "<-- TOS\n"));
} /* x87_dump_stack */
static INLINE const arch_register_t *x87_get_irn_register(x87_simulator *sim, const ir_node *irn) {
const arch_register_t *res;
- res = arch_get_irn_register(sim->env, irn);
+ res = arch_get_irn_register(sim->arch_env, irn);
assert(res->reg_class->regs == ia32_vfp_regs);
return res;
}
attr->x87[1] = &ia32_st_regs[0];
attr->x87[2] = &ia32_st_regs[0];
+ keep_alive(fpop);
sched_add_before(n, fpop);
DB((dbg, LEVEL_1, "<<< %s %s\n", get_irn_opname(fpop), attr->x87[0]->name));
{
int i, n;
const arch_register_class_t *cls = &ia32_reg_classes[CLASS_ia32_vfp];
- const arch_env_t *arch_env = sim->env;
+ const arch_env_t *arch_env = sim->arch_env;
if (arch_irn_consider_in_reg_alloc(arch_env, cls, irn)) {
const arch_register_t *reg = x87_get_irn_register(sim, irn);
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->env;
+ 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) {
int op2_idx, op1_idx;
int out_idx, do_pop = 0;
ia32_attr_t *attr;
+ ir_node *patched_insn;
ir_op *dst;
x87_simulator *sim = state->sim;
const arch_register_t *op1 = x87_get_irn_register(sim, get_irn_n(n, BINOP_IDX_1));
out_idx = 0;
dst = tmpl->normal_op;
}
- }
- else {
+ } else {
/* Second operand is dead. */
if (is_vfp_live(arch_register_get_index(op1), live)) {
/* First operand is live: bring second to tos. */
/* now do fxxxr (tos = op X tos) */
out_idx = 0;
dst = tmpl->reverse_op;
- }
- else {
+ } else {
/* Both operands are dead here, pop them from the stack. */
if (op2_idx == 0) {
if (op1_idx == 0) {
/* here fxxx (tos = tos X tos) */
dst = tmpl->normal_op;
out_idx = 0;
- }
- else {
+ } else {
/* now do fxxxp (op = op X tos, pop) */
dst = tmpl->normal_pop_op;
do_pop = 1;
out_idx = op1_idx;
}
- }
- else if (op1_idx == 0) {
+ } else if (op1_idx == 0) {
assert(op1_idx != op2_idx);
/* now do fxxxrp (op = tos X op, pop) */
dst = tmpl->reverse_pop_op;
do_pop = 1;
out_idx = op2_idx;
- }
- else {
+ } else {
/* Bring the second on top. */
x87_create_fxch(state, n, op2_idx, BINOP_IDX_2);
if (op1_idx == op2_idx) {
/* use fxxx (tos = tos X tos) */
dst = tmpl->normal_op;
out_idx = 0;
- }
- else {
+ } else {
/* op2 is on tos now */
op2_idx = 0;
/* use fxxxp (op = op X tos, pop) */
}
}
}
- }
- else {
+ } else {
/* second operand is an address mode */
if (is_vfp_live(arch_register_get_index(op1), live)) {
/* first operand is live: push it here */
/* use fxxx (tos = tos X mem) */
dst = tmpl->normal_op;
out_idx = 0;
- }
- else {
+ } else {
/* first operand is dead: bring it to tos */
if (op1_idx != 0) {
x87_create_fxch(state, n, op1_idx, BINOP_IDX_1);
}
}
- x87_set_st(state, arch_register_get_index(out), x87_patch_insn(n, dst), out_idx);
+ patched_insn = x87_patch_insn(n, dst);
+ x87_set_st(state, arch_register_get_index(out), patched_insn, out_idx);
if (do_pop) {
x87_pop(state);
}
assert(mem && "Store memory not found");
- arch_set_irn_register(sim->env, rproj, op2);
+ arch_set_irn_register(sim->arch_env, rproj, op2);
/* reroute all former users of the store memory to the load memory */
edges_reroute(mem, mproj, irg);
* Simulate a virtual Phi.
* Just for cosmetic reasons change the mode of Phi nodes to mode_E.
*
- * @param state the x87 state
- * @param n the node that should be simulated (and patched)
- * @param env the architecture environment
+ * @param state the x87 state
+ * @param n the node that should be simulated (and patched)
+ * @param arch_env the architecture environment
*/
-static int sim_Phi(x87_state *state, ir_node *n, const arch_env_t *env) {
+static int sim_Phi(x87_state *state, ir_node *n, const arch_env_t *arch_env) {
ir_mode *mode = get_irn_mode(n);
if (mode_is_float(mode))
return 0;
} /* sim_Phi */
-
#define _GEN_BINOP(op, rev) \
static int sim_##op(x87_state *state, ir_node *n) { \
exchange_tmpl tmpl = { op_ia32_##op, op_ia32_##rev, op_ia32_##op##p, op_ia32_##rev##p }; \
GEN_LOAD(fild)
GEN_LOAD(fldz)
GEN_LOAD(fld1)
-GEN_LOAD2(fConst, fldConst)
GEN_STORE(fst)
GEN_STORE(fist)
/* both operands are live */
if (op1_idx == 0) {
+ /* res = tos X op */
dst = op_ia32_fcomJmp;
} else if (op2_idx == 0) {
+ /* res = op X tos */
dst = op_ia32_fcomrJmp;
} else {
/* bring the first one to tos */
if (op2_idx == 0)
op2_idx = op1_idx;
op1_idx = 0;
+ /* res = tos X op */
dst = op_ia32_fcomJmp;
}
- }
- else {
+ } else {
/* second live, first operand is dead here, bring it to tos.
This means further, op1_idx != op2_idx. */
assert(op1_idx != op2_idx);
op2_idx = op1_idx;
op1_idx = 0;
}
+ /* res = tos X op, pop */
dst = op_ia32_fcompJmp;
pop_cnt = 1;
}
- }
- else {
+ } else {
/* second operand is dead */
if (is_vfp_live(arch_register_get_index(op1), live)) {
/* first operand is live: bring second to tos.
op1_idx = op2_idx;
op2_idx = 0;
}
+ /* res = op X tos, pop */
dst = op_ia32_fcomrpJmp;
pop_cnt = 1;
- }
- else {
+ } else {
/* both operands are dead here, check first for identity. */
if (op1_idx == op2_idx) {
/* identically, one pop needed */
op1_idx = 0;
op2_idx = 0;
}
+ /* res = tos X op, pop */
dst = op_ia32_fcompJmp;
pop_cnt = 1;
}
if (op1_idx != 0) {
/* bring the first on top */
x87_create_fxch(state, n, op1_idx, BINOP_IDX_1);
+ assert(op2_idx != 0);
op1_idx = 0;
}
+ /* res = tos X op, pop, pop */
dst = op_ia32_fcomppJmp;
pop_cnt = 2;
- }
- else if (op1_idx == 1) {
+ } else if (op1_idx == 1) {
/* good, first operand is already in the right place, move the second */
if (op2_idx != 0) {
/* bring the first on top */
x87_create_fxch(state, n, op2_idx, BINOP_IDX_2);
+ assert(op1_idx != 0);
op2_idx = 0;
}
dst = op_ia32_fcomrppJmp;
pop_cnt = 2;
- }
- else {
+ } else {
/* if one is already the TOS, we need two fxch */
if (op1_idx == 0) {
/* first one is TOS, move to st(1) */
x87_create_fxch(state, n, 1, BINOP_IDX_1);
+ assert(op2_idx != 1);
op1_idx = 1;
x87_create_fxch(state, n, op2_idx, BINOP_IDX_2);
op2_idx = 0;
+ /* res = op X tos, pop, pop */
dst = op_ia32_fcomrppJmp;
pop_cnt = 2;
- }
- else if (op2_idx == 0) {
+ } else if (op2_idx == 0) {
/* second one is TOS, move to st(1) */
x87_create_fxch(state, n, 1, BINOP_IDX_2);
+ assert(op1_idx != 1);
op2_idx = 1;
x87_create_fxch(state, n, op1_idx, BINOP_IDX_1);
op1_idx = 0;
- dst = op_ia32_fcomrppJmp;
+ /* res = tos X op, pop, pop */
+ dst = op_ia32_fcomppJmp;
pop_cnt = 2;
- }
- else {
+ } else {
/* none of them is either TOS or st(1), 3 fxch needed */
x87_create_fxch(state, n, op2_idx, BINOP_IDX_2);
+ assert(op1_idx != 0);
x87_create_fxch(state, n, 1, BINOP_IDX_2);
op2_idx = 1;
x87_create_fxch(state, n, op1_idx, BINOP_IDX_1);
op1_idx = 0;
+ /* res = tos X op, pop, pop */
dst = op_ia32_fcomppJmp;
pop_cnt = 2;
}
}
}
}
- }
- else {
+ } else {
/* second operand is an address mode */
if (is_vfp_live(arch_register_get_index(op1), live)) {
/* first operand is live: bring it to TOS */
op1_idx = 0;
}
dst = op_ia32_fcomJmp;
- }
- else {
+ } else {
/* first operand is dead: bring it to tos */
if (op1_idx != 0) {
x87_create_fxch(state, n, op1_idx, BINOP_IDX_1);
return 0;
} /* sim_fCondJmp */
+static ir_node *create_Copy(x87_state *state, ir_node *n) {
+ x87_simulator *sim = state->sim;
+ 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 *res;
+ const arch_register_t *out;
+ const arch_register_t *op1;
+ ia32_attr_t *attr;
+
+ /* Do not copy constants, recreate them. */
+ switch (get_ia32_irn_opcode(pred)) {
+ case iro_ia32_Unknown_VFP:
+ case iro_ia32_fldz:
+ cnstr = new_rd_ia32_fldz;
+ break;
+ case iro_ia32_fld1:
+ cnstr = new_rd_ia32_fld1;
+ break;
+ case iro_ia32_fldpi:
+ cnstr = new_rd_ia32_fldpi;
+ break;
+ case iro_ia32_fldl2e:
+ cnstr = new_rd_ia32_fldl2e;
+ break;
+ case iro_ia32_fldl2t:
+ cnstr = new_rd_ia32_fldl2t;
+ break;
+ case iro_ia32_fldlg2:
+ cnstr = new_rd_ia32_fldlg2;
+ break;
+ case iro_ia32_fldln2:
+ cnstr = new_rd_ia32_fldln2;
+ break;
+ }
+
+ out = x87_get_irn_register(sim, n);
+ op1 = x87_get_irn_register(sim, pred);
+
+ if(cnstr != NULL) {
+ /* copy a constant */
+ res = (*cnstr)(n_dbg, irg, block, mode);
+
+ x87_push(state, arch_register_get_index(out), res);
+
+ attr = get_ia32_attr(res);
+ attr->x87[2] = out = &ia32_st_regs[0];
+ } else {
+ int op1_idx = x87_on_stack(state, arch_register_get_index(op1));
+
+ res = new_rd_ia32_fpushCopy(n_dbg, irg, block, pred, mode);
+
+ x87_push(state, arch_register_get_index(out), res);
+
+ attr = get_ia32_attr(res);
+ attr->x87[0] = op1 = &ia32_st_regs[op1_idx];
+ attr->x87[2] = out = &ia32_st_regs[0];
+ }
+ arch_set_irn_register(sim->arch_env, res, out);
+
+ return res;
+}
+
/**
* Simulate a be_Copy.
*
* @param n the node that should be simulated (and patched)
*/
static int sim_Copy(x87_state *state, ir_node *n) {
- ir_mode *mode = get_irn_mode(n);
+ x87_simulator *sim;
+ ir_node *pred;
+ const arch_register_t *out;
+ const arch_register_t *op1;
+ ir_node *node, *next;
+ ia32_attr_t *attr;
+ int op1_idx, out_idx;
+ unsigned live;
- if (mode_is_float(mode)) {
- x87_simulator *sim = state->sim;
- ir_node *pred = get_irn_n(n, 0);
- const arch_register_t *out = x87_get_irn_register(sim, n);
- const arch_register_t *op1 = x87_get_irn_register(sim, pred);
- ir_node *node, *next;
- ia32_attr_t *attr;
- int op1_idx, out_idx;
- unsigned live = vfp_live_args_after(sim, n, REGMASK(out));
- ir_node *(*cnstr)(dbg_info *, ir_graph *, ir_node *, ir_mode *);
-
- DB((dbg, LEVEL_1, ">>> %+F %s -> %s\n", n,
- arch_register_get_name(op1), arch_register_get_name(out)));
- DEBUG_ONLY(vfp_dump_live(live));
+ ir_mode *mode = get_irn_mode(n);
- /* Do not copy constants, recreate them. */
- switch (get_ia32_irn_opcode(pred)) {
- case iro_ia32_fldz:
- cnstr = new_rd_ia32_fldz;
- break;
- case iro_ia32_fld1:
- cnstr = new_rd_ia32_fld1;
- break;
- case iro_ia32_fldpi:
- cnstr = new_rd_ia32_fldpi;
- break;
- case iro_ia32_fldl2e:
- cnstr = new_rd_ia32_fldl2e;
- break;
- case iro_ia32_fldl2t:
- cnstr = new_rd_ia32_fldl2t;
- break;
- case iro_ia32_fldlg2:
- cnstr = new_rd_ia32_fldlg2;
- break;
- case iro_ia32_fldln2:
- cnstr = new_rd_ia32_fldln2;
- break;
- default:
- goto no_constant;
- }
+ if (!mode_is_float(mode))
+ return 0;
- /* copy a constant */
- node = (*cnstr)(get_irn_dbg_info(n), get_irn_irg(n), get_nodes_block(n), mode);
- arch_set_irn_register(sim->env, node, out);
+ sim = state->sim;
+ pred = get_irn_n(n, 0);
+ out = x87_get_irn_register(sim, n);
+ op1 = x87_get_irn_register(sim, pred);
+ live = vfp_live_args_after(sim, n, REGMASK(out));
- x87_push(state, arch_register_get_index(out), node);
+ DB((dbg, LEVEL_1, ">>> %+F %s -> %s\n", n,
+ arch_register_get_name(op1), arch_register_get_name(out)));
+ DEBUG_ONLY(vfp_dump_live(live));
- attr = get_ia32_attr(node);
- attr->x87[2] = out = &ia32_st_regs[0];
+ /* handle the infamous unknown value */
+ if (arch_register_get_index(op1) == REG_VFP_UKNWN) {
+ /* Operand is still live, a real copy. We need here an fpush that can
+ hold a a register, so use the fpushCopy or recreate constants */
+ node = create_Copy(state, n);
+ assert(is_ia32_fldz(node));
next = sched_next(n);
sched_remove(n);
exchange(n, node);
sched_add_before(next, node);
- DB((dbg, LEVEL_1, ">>> %+F -> %s\n", node, arch_register_get_name(out)));
+
+ DB((dbg, LEVEL_1, "<<< %+F %s -> %s\n", node, op1->name,
+ arch_get_irn_register(sim->arch_env, node)->name));
return 0;
+ }
-no_constant:
- /* handle the infamous unknown value */
- if (arch_register_get_index(op1) == REG_VFP_UKNWN) {
- /* This happens before Phi nodes */
- if (x87_state_is_empty(state)) {
- /* create some value */
- x87_patch_insn(n, op_ia32_fldz);
- attr = get_ia32_attr(n);
- attr->x87[2] = out = &ia32_st_regs[0];
- DB((dbg, LEVEL_1, "<<< %+F -> %s\n", n,
- arch_register_get_name(out)));
- } else {
- /* Just copy one. We need here an fpush that can hold a
- a register, so use the fpushCopy. */
- node = new_rd_ia32_fpushCopy(get_irn_dbg_info(n), get_irn_irg(n), get_nodes_block(n), get_irn_n(n, 0), mode);
- arch_set_irn_register(sim->env, node, out);
-
- x87_push(state, arch_register_get_index(out), node);
-
- attr = get_ia32_attr(node);
- attr->x87[0] = op1 =
- attr->x87[2] = out = &ia32_st_regs[0];
-
- next = sched_next(n);
- sched_remove(n);
- exchange(n, node);
- sched_add_before(next, node);
- DB((dbg, LEVEL_1, "<<< %+F %s -> %s\n", node,
- arch_register_get_name(op1),
- arch_register_get_name(out)));
- }
- return 0;
- }
+ op1_idx = x87_on_stack(state, arch_register_get_index(op1));
- op1_idx = x87_on_stack(state, arch_register_get_index(op1));
+ if (is_vfp_live(arch_register_get_index(op1), live)) {
+ /* Operand is still live, a real copy. We need here an fpush that can
+ hold a a register, so use the fpushCopy or recreate constants */
+ node = create_Copy(state, n);
- if (is_vfp_live(arch_register_get_index(op1), live)) {
- /* Operand is still live,a real copy. We need here an fpush that can hold a
- a register, so use the fpushCopy. */
- node = new_rd_ia32_fpushCopy(get_irn_dbg_info(n), get_irn_irg(n), get_nodes_block(n), get_irn_n(n, 0), mode);
- arch_set_irn_register(sim->env, node, out);
+ next = sched_next(n);
+ sched_remove(n);
+ exchange(n, node);
+ sched_add_before(next, node);
+ DB((dbg, LEVEL_1, "<<< %+F %s -> %s\n", node, op1->name,
+ arch_get_irn_register(sim->arch_env, node)->name));
+ } else {
+ out_idx = x87_on_stack(state, arch_register_get_index(out));
- x87_push(state, arch_register_get_index(out), node);
+ if (out_idx >= 0 && out_idx != op1_idx) {
+ /* Matze: out already on stack? how can this happen? */
+ assert(0);
- attr = get_ia32_attr(node);
- attr->x87[0] = op1 = &ia32_st_regs[op1_idx];
- attr->x87[2] = out = &ia32_st_regs[0];
+ /* op1 must be killed and placed where out is */
+ if (out_idx == 0) {
+ /* best case, simple remove and rename */
+ x87_patch_insn(n, op_ia32_Pop);
+ attr = get_ia32_attr(n);
+ attr->x87[0] = op1 = &ia32_st_regs[0];
- next = sched_next(n);
- sched_remove(n);
- exchange(n, node);
- sched_add_before(next, node);
- DB((dbg, LEVEL_1, ">>> %+F %s -> %s\n", node, op1->name, out->name));
- }
- else {
- out_idx = x87_on_stack(state, arch_register_get_index(out));
-
- if (out_idx >= 0 && out_idx != op1_idx) {
- /* op1 must be killed and placed where out is */
- if (out_idx == 0) {
- /* best case, simple remove and rename */
- x87_patch_insn(n, op_ia32_Pop);
- attr = get_ia32_attr(n);
- attr->x87[0] = op1 = &ia32_st_regs[0];
-
- x87_pop(state);
- x87_set_st(state, arch_register_get_index(out), n, op1_idx - 1);
+ x87_pop(state);
+ x87_set_st(state, arch_register_get_index(out), n, op1_idx - 1);
+ } else {
+ /* move op1 to tos, store and pop it */
+ if (op1_idx != 0) {
+ x87_create_fxch(state, n, op1_idx, 0);
+ op1_idx = 0;
}
- else {
- /* move op1 to tos, store and pop it */
- if (op1_idx != 0) {
- x87_create_fxch(state, n, op1_idx, 0);
- op1_idx = 0;
- }
- x87_patch_insn(n, op_ia32_Pop);
- attr = get_ia32_attr(n);
- attr->x87[0] = op1 = &ia32_st_regs[out_idx];
+ x87_patch_insn(n, op_ia32_Pop);
+ attr = get_ia32_attr(n);
+ attr->x87[0] = op1 = &ia32_st_regs[out_idx];
- x87_pop(state);
- x87_set_st(state, arch_register_get_index(out), n, out_idx - 1);
- }
- DB((dbg, LEVEL_1, ">>> %+F %s\n", n, op1->name));
- }
- else {
- /* just a virtual copy */
- x87_set_st(state, arch_register_get_index(out), get_unop_op(n), op1_idx);
- sched_remove(n);
- DB((dbg, LEVEL_1, ">>> KILLED %s\n", get_irn_opname(n)));
- exchange(n, get_unop_op(n));
+ x87_pop(state);
+ x87_set_st(state, arch_register_get_index(out), n, out_idx - 1);
}
+ DB((dbg, LEVEL_1, "<<< %+F %s\n", n, op1->name));
+ } else {
+ /* just a virtual copy */
+ x87_set_st(state, arch_register_get_index(out), get_unop_op(n), op1_idx);
+ sched_remove(n);
+ DB((dbg, LEVEL_1, "<<< KILLED %s\n", get_irn_opname(n)));
+ exchange(n, get_unop_op(n));
}
}
+
return 0;
} /* sim_Copy */
/**
* Simulate a be_Call.
*
- * @param state the x87 state
- * @param n the node that should be simulated
- * @param env the architecture environment
+ * @param state the x87 state
+ * @param n the node that should be simulated
+ * @param arch_env the architecture environment
*/
-static int sim_Call(x87_state *state, ir_node *n, const arch_env_t *env) {
+static int sim_Call(x87_state *state, ir_node *n, const arch_env_t *arch_env) {
ir_type *call_tp = be_Call_get_type(n);
/* at the begin of a call the x87 state should be empty */
*
* @param state the x87 state
* @param n the node that should be simulated (and patched)
- * @param env the architecture environment
*
* Should not happen, spills are lowered before x87 simulator see them.
*/
*
* @param state the x87 state
* @param n the node that should be simulated (and patched)
- * @param env the architecture environment
*
* Should not happen, reloads are lowered before x87 simulator see them.
*/
*
* @param state the x87 state
* @param n the node that should be simulated (and patched)
- * @param env the architecture environment
*/
static int sim_Return(x87_state *state, ir_node *n) {
int n_res = be_Return_get_n_rets(n);
if(bl_state->end != NULL)
return;
- update_liveness(sim, block);
+ //update_liveness(sim, block);
DB((dbg, LEVEL_1, "Simulate %+F\n", block));
DB((dbg, LEVEL_2, "State at Block begin:\n "));
/* at block begin, kill all dead registers */
state = x87_kill_deads(sim, block, state);
- /* beware, n might changed */
+ /* beware, n might change */
for (n = sched_first(block); !sched_is_end(n); n = next) {
int node_inserted;
sim_func func;
/**
* Create a new x87 simulator.
*
- * @param sim a simulator handle, will be initialized
- * @param irg the current graph
- * @param env the architecture environment
+ * @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 *env)
+static void x87_init_simulator(x87_simulator *sim, ir_graph *irg,
+ const arch_env_t *arch_env)
{
obstack_init(&sim->obst);
sim->blk_states = pmap_create();
- sim->env = env;
+ 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);
#define ASSOC(op) (op_ ## op)->ops.generic = (op_func)(sim_##op)
#define ASSOC_IA32(op) (op_ia32_v ## op)->ops.generic = (op_func)(sim_##op)
#define ASSOC_BE(op) (op_be_ ## op)->ops.generic = (op_func)(sim_##op)
- ASSOC_IA32(fConst);
ASSOC_IA32(fld);
ASSOC_IA32(fild);
ASSOC_IA32(fld1);
DB((dbg, LEVEL_1, "x87 Simulator stopped\n\n"));
} /* x87_destroy_simulator */
+static void update_liveness_walker(ir_node *block, void *data)
+{
+ x87_simulator *sim = data;
+ update_liveness(sim, block);
+}
+
/**
* Run a simulation and fix all virtual instructions for a graph.
*
*
* Needs a block-schedule.
*/
-void x87_simulate_graph(const arch_env_t *env, be_irg_t *birg) {
+void x87_simulate_graph(const arch_env_t *arch_env, be_irg_t *birg) {
ir_node *block, *start_block;
blk_state *bl_state;
x87_simulator sim;
ir_graph *irg = birg->irg;
/* create the simulator */
- x87_init_simulator(&sim, irg, env);
+ x87_init_simulator(&sim, irg, arch_env);
start_block = get_irg_start_block(irg);
bl_state = x87_get_bl_state(&sim, start_block);
be_assure_liveness(birg);
sim.lv = birg->lv;
-#if 0
- /* Create the worklist for the schedule and calculate the liveness
- for all nodes. We must precalculate this info, because the
- simulator adds new nodes (and possible before Phi nodes) which
- let fail the old lazy calculation.
- On the other hand we reduce the computation amount due to
- precaching from O(n^2) to O(n) at the expense of O(n) cache memory.
+ /* Calculate the liveness for all nodes. We must precalculate this info,
+ * because the simulator adds new nodes (possible before Phi nodes) which
+ * would let a lazy calculation fail.
+ * On the other hand we reduce the computation amount due to
+ * precaching from O(n^2) to O(n) at the expense of O(n) cache memory.
*/
- for (i = 0, n = ARR_LEN(blk_list); i < n; ++i) {
- update_liveness(&sim, lv, blk_list[i]);
- waitq_put(worklist, blk_list[i]);
- }
-#endif
+ irg_block_walk_graph(irg, update_liveness_walker, NULL, &sim);
/* iterate */
do {