#include "iredges_t.h"
#include "irgmod.h"
#include "ircons.h"
+#include "irgwalk.h"
#include "obst.h"
#include "pmap.h"
#include "pdeq.h"
* 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. */
};
/**
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) {
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))
GEN_LOAD(fild)
GEN_LOAD(fldz)
GEN_LOAD(fld1)
-GEN_LOAD2(fConst, fldConst)
GEN_STORE(fst)
GEN_STORE(fist)
/* 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;
attr->x87[0] = op1 = &ia32_st_regs[op1_idx];
attr->x87[2] = out = &ia32_st_regs[0];
}
- arch_set_irn_register(sim->env, res, out);
+ arch_set_irn_register(sim->arch_env, res, out);
- DB((dbg, LEVEL_1, ">>> %+F -> %s\n", res, arch_register_get_name(out)));
return res;
}
/* handle the infamous unknown value */
if (arch_register_get_index(op1) == REG_VFP_UKNWN) {
- /* Matze: copies of unknowns should not happen (anymore) */
- assert(0);
+ /* 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 -> %s\n", node, op1->name,
+ arch_get_irn_register(sim->arch_env, node)->name));
+ return 0;
}
op1_idx = x87_on_stack(state, arch_register_get_index(op1));
sched_remove(n);
exchange(n, node);
sched_add_before(next, node);
- DB((dbg, LEVEL_1, ">>> %+F %s -> %s\n", node, op1->name, out->name));
+ 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_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));
+ 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)));
+ DB((dbg, LEVEL_1, "<<< KILLED %s\n", get_irn_opname(n)));
exchange(n, get_unop_op(n));
}
}
/**
* 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 {