X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fia32%2Fia32_x87.c;h=9694819008adb525db473583b5d8157251c7106c;hb=fef8dc3eff6468d7d65485af8e1ac9884c504e1a;hp=82bc54d841f4552f06d92fe9353dbf0407376cd8;hpb=e70058492edabd5455304b060163440ae0afec21;p=libfirm diff --git a/ir/be/ia32/ia32_x87.c b/ir/be/ia32/ia32_x87.c index 82bc54d84..969481900 100644 --- a/ir/be/ia32/ia32_x87.c +++ b/ir/be/ia32/ia32_x87.c @@ -52,6 +52,8 @@ #include "ia32_x87.h" #include "ia32_architecture.h" +#define N_FLOAT_REGS (N_ia32_fp_REGS-1) // exclude NOREG + /** the debug handle */ DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;) @@ -70,9 +72,9 @@ typedef struct st_entry { * The x87 state. */ typedef struct x87_state { - st_entry st[N_ia32_st_REGS]; /**< the register stack */ - int depth; /**< the current stack depth */ - x87_simulator *sim; /**< The simulator. */ + st_entry st[N_FLOAT_REGS]; /**< the register stack */ + int depth; /**< the current stack depth */ + x87_simulator *sim; /**< The simulator. */ } x87_state; /** An empty state, used for blocks without fp instructions. */ @@ -107,8 +109,8 @@ typedef struct blk_state { x87_state *end; /**< state at the end or NULL if not assigned */ } blk_state; -/** liveness bitset for vfp registers. */ -typedef unsigned char vfp_liveness; +/** liveness bitset for fp registers. */ +typedef unsigned char fp_liveness; /** * The x87 simulator. @@ -117,7 +119,7 @@ struct x87_simulator { struct obstack obst; /**< An obstack for fast allocating. */ pmap *blk_states; /**< Map blocks to states. */ be_lv_t *lv; /**< intrablock liveness. */ - vfp_liveness *live; /**< Liveness information. */ + fp_liveness *live; /**< Liveness information. */ unsigned n_idx; /**< The cached get_irg_last_idx() result. */ waitq *worklist; /**< Worklist of blocks that must be processed. */ }; @@ -137,7 +139,7 @@ static int x87_get_depth(const x87_state *state) static st_entry *x87_get_entry(x87_state *const state, int const pos) { assert(0 <= pos && pos < state->depth); - return &state->st[N_ia32_st_REGS - state->depth + pos]; + return &state->st[N_FLOAT_REGS - state->depth + pos]; } /** @@ -146,7 +148,7 @@ static st_entry *x87_get_entry(x87_state *const state, int const pos) * @param state the x87 state * @param pos a stack position * - * @return the vfp register index that produced the value at st(pos) + * @return the fp register index that produced the value at st(pos) */ static int x87_get_st_reg(const x87_state *state, int pos) { @@ -173,8 +175,8 @@ static void x87_dump_stack(const x87_state *state) * Set a virtual register to st(pos). * * @param state the x87 state - * @param reg_idx the vfp register index that should be set - * @param node the IR node that produces the value of the vfp register + * @param reg_idx the fp register index that should be set + * @param node the IR node that produces the value of the fp register * @param pos the stack position where the new value should be entered */ static void x87_set_st(x87_state *state, int reg_idx, ir_node *node, int pos) @@ -209,7 +211,7 @@ static void x87_fxch(x87_state *state, int pos) * Convert a virtual register to the stack index. * * @param state the x87 state - * @param reg_idx the register vfp index + * @param reg_idx the register fp index * * @return the stack position where the register is stacked * or -1 if the virtual register was not found @@ -227,13 +229,13 @@ static int x87_on_stack(const x87_state *state, int reg_idx) * Push a virtual Register onto the stack, double pushes are NOT allowed. * * @param state the x87 state - * @param reg_idx the register vfp index - * @param node the node that produces the value of the vfp register + * @param reg_idx the register fp index + * @param node the node that produces the value of the fp register */ static void x87_push(x87_state *state, int reg_idx, ir_node *node) { assert(x87_on_stack(state, reg_idx) == -1 && "double push"); - assert(state->depth < N_ia32_st_REGS && "stack overrun"); + assert(state->depth < N_FLOAT_REGS && "stack overrun"); ++state->depth; st_entry *const entry = x87_get_entry(state, 0); @@ -305,37 +307,6 @@ static x87_state *x87_clone_state(x87_simulator *sim, const x87_state *src) return res; } -/** - * Patch a virtual instruction into a x87 one and return - * the node representing the result value. - * - * @param n the IR node to patch - * @param op the x87 opcode to patch in - */ -static ir_node *x87_patch_insn(ir_node *n, ir_op *op) -{ - ir_mode *mode = get_irn_mode(n); - ir_node *res = n; - - set_irn_op(n, op); - - if (mode == mode_T) { - /* patch all Proj's */ - foreach_out_edge(n, edge) { - ir_node *proj = get_edge_src_irn(edge); - if (is_Proj(proj)) { - mode = get_irn_mode(proj); - if (mode_is_float(mode)) { - res = proj; - set_irn_mode(proj, ia32_reg_classes[CLASS_ia32_st].mode); - } - } - } - } else if (mode_is_float(mode)) - set_irn_mode(n, ia32_reg_classes[CLASS_ia32_st].mode); - return res; -} - /** * Returns the first Proj of a mode_T node having a given mode. * @@ -363,7 +334,7 @@ static inline const arch_register_t *x87_get_irn_register(const ir_node *irn) { const arch_register_t *res = arch_get_irn_register(irn); - assert(res->reg_class == &ia32_reg_classes[CLASS_ia32_vfp]); + assert(res->reg_class == &ia32_reg_classes[CLASS_ia32_fp]); return res; } @@ -372,7 +343,7 @@ static inline const arch_register_t *x87_irn_get_register(const ir_node *irn, { const arch_register_t *res = arch_get_irn_register_out(irn, pos); - assert(res->reg_class == &ia32_reg_classes[CLASS_ia32_vfp]); + assert(res->reg_class == &ia32_reg_classes[CLASS_ia32_fp]); return res; } @@ -591,34 +562,18 @@ static ir_node *x87_create_fpop(x87_state *const state, ir_node *const n, int co * * @return The live bitset. */ -static vfp_liveness vfp_liveness_transfer(ir_node *irn, vfp_liveness live) +static fp_liveness fp_liveness_transfer(ir_node *irn, fp_liveness live) { - int i, n; - const arch_register_class_t *cls = &ia32_reg_classes[CLASS_ia32_vfp]; - - if (get_irn_mode(irn) == mode_T) { - foreach_out_edge(irn, edge) { - ir_node *proj = get_edge_src_irn(edge); + const arch_register_class_t *cls = &ia32_reg_classes[CLASS_ia32_fp]; - if (arch_irn_consider_in_reg_alloc(cls, proj)) { - const arch_register_t *reg = x87_get_irn_register(proj); - live &= ~(1 << reg->index); - } - } - } else if (arch_irn_consider_in_reg_alloc(cls, irn)) { - const arch_register_t *reg = x87_get_irn_register(irn); + be_foreach_definition(irn, cls, def, req, + const arch_register_t *reg = x87_get_irn_register(def); live &= ~(1 << reg->index); - } - - 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(cls, op)) { - const arch_register_t *reg = x87_get_irn_register(op); - live |= 1 << reg->index; - } - } + ); + be_foreach_use(irn, cls, in_req_, op, op_req_, + const arch_register_t *reg = x87_get_irn_register(op); + live |= 1 << reg->index; + ); return live; } @@ -630,18 +585,14 @@ static vfp_liveness vfp_liveness_transfer(ir_node *irn, vfp_liveness live) * * @return The live bitset at the end of this block */ -static vfp_liveness vfp_liveness_end_of_block(x87_simulator *sim, const ir_node *block) +static fp_liveness fp_liveness_end_of_block(x87_simulator *sim, const ir_node *block) { - vfp_liveness live = 0; - const arch_register_class_t *cls = &ia32_reg_classes[CLASS_ia32_vfp]; + fp_liveness live = 0; + const arch_register_class_t *cls = &ia32_reg_classes[CLASS_ia32_fp]; const be_lv_t *lv = sim->lv; - be_lv_foreach(lv, block, be_lv_state_end, node) { - const arch_register_t *reg; - if (!arch_irn_consider_in_reg_alloc(cls, node)) - continue; - - reg = x87_get_irn_register(node); + be_lv_foreach_cls(lv, block, be_lv_state_end, cls, node) { + const arch_register_t *reg = x87_get_irn_register(node); live |= 1 << reg->index; } @@ -660,7 +611,7 @@ static vfp_liveness vfp_liveness_end_of_block(x87_simulator *sim, const ir_node * * @return The live bitset. */ -static unsigned vfp_live_args_after(x87_simulator *sim, const ir_node *pos, unsigned kill) +static unsigned fp_live_args_after(x87_simulator *sim, const ir_node *pos, unsigned kill) { unsigned idx = get_irn_idx(pos); @@ -676,7 +627,7 @@ static unsigned vfp_live_args_after(x87_simulator *sim, const ir_node *pos, unsi */ static void update_liveness(x87_simulator *sim, ir_node *block) { - vfp_liveness live = vfp_liveness_end_of_block(sim, block); + fp_liveness live = fp_liveness_end_of_block(sim, block); unsigned idx; /* now iterate through the block backward and cache the results */ @@ -688,7 +639,7 @@ static void update_liveness(x87_simulator *sim, ir_node *block) idx = get_irn_idx(irn); sim->live[idx] = live; - live = vfp_liveness_transfer(irn, live); + live = fp_liveness_transfer(irn, live); } idx = get_irn_idx(block); sim->live[idx] = live; @@ -697,10 +648,10 @@ static void update_liveness(x87_simulator *sim, ir_node *block) /** * Returns true if a register is live in a set. * - * @param reg_idx the vfp register index + * @param reg_idx the fp register index * @param live a live bitset */ -#define is_vfp_live(reg_idx, live) ((live) & (1 << (reg_idx))) +#define is_fp_live(reg_idx, live) ((live) & (1 << (reg_idx))) #ifdef DEBUG_libfirm /** @@ -708,7 +659,7 @@ static void update_liveness(x87_simulator *sim, ir_node *block) * * @param live the live bitset */ -static void vfp_dump_live(vfp_liveness live) +static void fp_dump_live(fp_liveness live) { int i; @@ -732,9 +683,8 @@ static void vfp_dump_live(vfp_liveness live) * * @return NO_NODE_ADDED */ -static int sim_binop(x87_state *const state, ir_node *const n, ir_op *const op) +static int sim_binop(x87_state *const state, ir_node *const n) { - ir_node *patched_insn; x87_simulator *sim = state->sim; ir_node *op1 = get_irn_n(n, n_ia32_binary_left); ir_node *op2 = get_irn_n(n, n_ia32_binary_right); @@ -743,29 +693,29 @@ static int sim_binop(x87_state *const state, ir_node *const n, ir_op *const op) const arch_register_t *out = x87_irn_get_register(n, pn_ia32_res); int reg_index_1 = op1_reg->index; int reg_index_2 = op2_reg->index; - vfp_liveness live = vfp_live_args_after(sim, n, REGMASK(out)); + fp_liveness live = fp_live_args_after(sim, n, REGMASK(out)); int op1_live_after; int op2_live_after; DB((dbg, LEVEL_1, ">>> %+F %s, %s -> %s\n", n, op1_reg->name, op2_reg->name, out->name)); - DEBUG_ONLY(vfp_dump_live(live);) + DEBUG_ONLY(fp_dump_live(live);) DB((dbg, LEVEL_1, "Stack before: ")); DEBUG_ONLY(x87_dump_stack(state);) int op1_idx = x87_on_stack(state, reg_index_1); assert(op1_idx >= 0); - op1_live_after = is_vfp_live(reg_index_1, live); + op1_live_after = is_fp_live(reg_index_1, live); int op2_idx; int out_idx; bool pop = false; int const out_reg_idx = out->index; ia32_x87_attr_t *const attr = get_ia32_x87_attr(n); - if (reg_index_2 != REG_VFP_VFP_NOREG) { - /* second operand is a vfp register */ + if (reg_index_2 != REG_FP_FP_NOREG) { + /* second operand is a fp register */ op2_idx = x87_on_stack(state, reg_index_2); assert(op2_idx >= 0); - op2_live_after = is_vfp_live(reg_index_2, live); + op2_live_after = is_fp_live(reg_index_2, live); if (op2_live_after) { /* Second operand is live. */ @@ -799,15 +749,30 @@ static int sim_binop(x87_state *const state, ir_node *const n, ir_op *const op) out_idx = op2_idx; } else { /* Both operands are dead. */ - if (op1_idx != 0 && op2_idx != 0) { - /* Bring one operand to tos. */ - x87_create_fxch(state, n, op1_idx); - if (op2_idx == op1_idx) op2_idx = 0; - op1_idx = 0; + if (op1_idx == op2_idx) { + /* Operands are identical: no pop. */ + if (op1_idx != 0) { + x87_create_fxch(state, n, op1_idx); + op1_idx = 0; + op2_idx = 0; + } + } else { + if (op1_idx != 0 && op2_idx != 0) { + /* Bring one operand to tos. Heuristically swap the operand not at + * st(1) to tos. This way, if any operand was at st(1), the result + * will end up in the new st(0) after the implicit pop. If the next + * operation uses the result, then no fxch will be necessary. */ + if (op1_idx != 1) { + x87_create_fxch(state, n, op1_idx); + op1_idx = 0; + } else { + x87_create_fxch(state, n, op2_idx); + op2_idx = 0; + } + } + pop = true; } out_idx = op1_idx != 0 ? op1_idx : op2_idx; - /* Only pop if the operands are differnt. */ - pop = op1_idx != op2_idx; } } } else { @@ -828,8 +793,7 @@ static int sim_binop(x87_state *const state, ir_node *const n, ir_op *const op) assert(op1_idx == 0 || op2_idx == 0); assert(out_idx == op1_idx || out_idx == op2_idx); - patched_insn = x87_patch_insn(n, op); - x87_set_st(state, out_reg_idx, patched_insn, out_idx); + x87_set_st(state, out_reg_idx, n, out_idx); if (pop) x87_pop(state); @@ -845,7 +809,7 @@ static int sim_binop(x87_state *const state, ir_node *const n, ir_op *const op) char const *const r = op2_idx >= 0 ? get_st_reg(op2_idx)->name : "[AM]"; char const *const o = get_st_reg(out_idx)->name; DB((dbg, LEVEL_1, "<<< %s %s, %s -> %s\n", get_irn_opname(n), l, r, o)); - ); + ) return NO_NODE_ADDED; } @@ -855,23 +819,22 @@ static int sim_binop(x87_state *const state, ir_node *const n, ir_op *const op) * * @param state the x87 state * @param n the node that should be simulated (and patched) - * @param op the x87 opcode that will replace n's opcode * * @return NO_NODE_ADDED */ -static int sim_unop(x87_state *state, ir_node *n, ir_op *op) +static int sim_unop(x87_state *state, ir_node *n) { arch_register_t const *const out = x87_get_irn_register(n); - unsigned const live = vfp_live_args_after(state->sim, n, REGMASK(out)); + unsigned const live = fp_live_args_after(state->sim, n, REGMASK(out)); DB((dbg, LEVEL_1, ">>> %+F -> %s\n", n, out->name)); - DEBUG_ONLY(vfp_dump_live(live);) + DEBUG_ONLY(fp_dump_live(live);) ir_node *const op1 = get_irn_n(n, 0); arch_register_t const *const op1_reg = x87_get_irn_register(op1); int const op1_reg_idx = op1_reg->index; int const op1_idx = x87_on_stack(state, op1_reg_idx); int const out_reg_idx = out->index; - if (is_vfp_live(op1_reg_idx, live)) { + if (is_fp_live(op1_reg_idx, live)) { /* push the operand here */ x87_create_fpush(state, n, op1_idx, out_reg_idx, op1); } else { @@ -881,7 +844,7 @@ static int sim_unop(x87_state *state, ir_node *n, ir_op *op) } } - x87_set_st(state, out_reg_idx, x87_patch_insn(n, op), 0); + x87_set_st(state, out_reg_idx, n, 0); DB((dbg, LEVEL_1, "<<< %s -> %s\n", get_irn_opname(n), get_st_reg(0)->name)); return NO_NODE_ADDED; @@ -892,17 +855,19 @@ static int sim_unop(x87_state *state, ir_node *n, ir_op *op) * * @param state the x87 state * @param n the node that should be simulated (and patched) - * @param op the x87 opcode that will replace n's opcode * * @return NO_NODE_ADDED */ -static int sim_load(x87_state *state, ir_node *n, ir_op *op, int res_pos) +static int sim_load(x87_state *state, ir_node *n) { - const arch_register_t *out = x87_irn_get_register(n, res_pos); + assert((int)pn_ia32_fld_res == (int)pn_ia32_fild_res + && (int)pn_ia32_fld_res == (int)pn_ia32_fld1_res + && (int)pn_ia32_fld_res == (int)pn_ia32_fldz_res); + const arch_register_t *out = x87_irn_get_register(n, pn_ia32_fld_res); DB((dbg, LEVEL_1, ">>> %+F -> %s\n", n, out->name)); - x87_push(state, out->index, x87_patch_insn(n, op)); - assert(out == x87_irn_get_register(n, res_pos)); + x87_push(state, out->index, n); + assert(out == x87_irn_get_register(n, pn_ia32_fld_res)); DB((dbg, LEVEL_1, "<<< %s -> %s\n", get_irn_opname(n), get_st_reg(0)->name)); return NO_NODE_ADDED; @@ -931,11 +896,10 @@ static void collect_and_rewire_users(ir_node *store, ir_node *old_val, ir_node * * * @param state the x87 state * @param n the node that should be simulated (and patched) - * @param op the x87 store opcode */ -static int sim_store(x87_state *state, ir_node *n, ir_op *op) +static int sim_store(x87_state *state, ir_node *n) { - ir_node *const val = get_irn_n(n, n_ia32_vfst_val); + ir_node *const val = get_irn_n(n, n_ia32_fst_val); arch_register_t const *const op2 = x87_get_irn_register(val); DB((dbg, LEVEL_1, ">>> %+F %s ->\n", n, op2->name)); @@ -943,8 +907,8 @@ static int sim_store(x87_state *state, ir_node *n, ir_op *op) int insn = NO_NODE_ADDED; int const op2_reg_idx = op2->index; int const op2_idx = x87_on_stack(state, op2_reg_idx); - unsigned const live = vfp_live_args_after(state->sim, n, 0); - int const live_after_node = is_vfp_live(op2_reg_idx, live); + unsigned const live = fp_live_args_after(state->sim, n, 0); + int const live_after_node = is_fp_live(op2_reg_idx, live); assert(op2_idx >= 0); if (live_after_node) { /* Problem: fst doesn't support 80bit modes (spills), only fstp does @@ -954,20 +918,18 @@ static int sim_store(x87_state *state, ir_node *n, ir_op *op) * - stack full: fstp value and load again * Note that we cannot test on mode_E, because floats might be 80bit ... */ ir_mode *const mode = get_ia32_ls_mode(n); - if (get_mode_size_bits(mode) > (mode_is_int(mode) ? 32 : 64)) { - if (x87_get_depth(state) < N_ia32_st_REGS) { + if (get_mode_size_bits(mode) > (mode_is_int(mode) ? 32U : 64U)) { + if (x87_get_depth(state) < N_FLOAT_REGS) { /* ok, we have a free register: push + fstp */ - x87_create_fpush(state, n, op2_idx, REG_VFP_VFP_NOREG, val); - x87_patch_insn(n, op); + x87_create_fpush(state, n, op2_idx, REG_FP_FP_NOREG, val); do_pop = true; } else { /* stack full here: need fstp + load */ - x87_patch_insn(n, op); do_pop = true; ir_node *const block = get_nodes_block(n); ir_node *const mem = get_irn_Proj_for_mode(n, mode_M); - ir_node *const vfld = new_bd_ia32_vfld(NULL, block, get_irn_n(n, 0), get_irn_n(n, 1), mem, mode); + ir_node *const vfld = new_bd_ia32_fld(NULL, block, get_irn_n(n, 0), get_irn_n(n, 1), mem, mode); /* copy all attributes */ set_ia32_frame_ent(vfld, get_ia32_frame_ent(n)); @@ -978,8 +940,8 @@ static int sim_store(x87_state *state, ir_node *n, ir_op *op) set_ia32_am_sc(vfld, get_ia32_am_sc(n)); set_ia32_ls_mode(vfld, mode); - ir_node *const rproj = new_r_Proj(vfld, mode, pn_ia32_vfld_res); - ir_node *const mproj = new_r_Proj(vfld, mode_M, pn_ia32_vfld_M); + ir_node *const rproj = new_r_Proj(vfld, mode, pn_ia32_fld_res); + ir_node *const mproj = new_r_Proj(vfld, mode_M, pn_ia32_fld_M); arch_set_irn_register(rproj, op2); @@ -997,16 +959,12 @@ static int sim_store(x87_state *state, ir_node *n, ir_op *op) /* we can only store the tos to memory */ if (op2_idx != 0) x87_create_fxch(state, n, op2_idx); - - /* mode size 64 or smaller -> use normal fst */ - x87_patch_insn(n, op); } } else { /* we can only store the tos to memory */ if (op2_idx != 0) x87_create_fxch(state, n, op2_idx); - x87_patch_insn(n, op); do_pop = true; } @@ -1020,49 +978,11 @@ static int sim_store(x87_state *state, ir_node *n, ir_op *op) return insn; } -#define GEN_BINOP(op) \ -static int sim_##op(x87_state *state, ir_node *n) { \ - return sim_binop(state, n, op_ia32_##op); \ -} - -#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_UNOP(op) \ -static int sim_##op(x87_state *state, ir_node *n) { \ - return sim_unop(state, n, op_ia32_##op); \ -} - -#define GEN_STORE(op) \ -static int sim_##op(x87_state *state, ir_node *n) { \ - return sim_store(state, n, op_ia32_##op); \ -} - -/* all stubs */ -GEN_BINOP(fadd) -GEN_BINOP(fsub) -GEN_BINOP(fmul) -GEN_BINOP(fdiv) - -GEN_UNOP(fabs) -GEN_UNOP(fchs) - -GEN_LOAD(fld) -GEN_LOAD(fild) -GEN_LOAD(fldz) -GEN_LOAD(fld1) - -GEN_STORE(fst) -GEN_STORE(fist) - static int sim_fprem(x87_state *const state, ir_node *const n) { (void)state; (void)n; panic("TODO implement"); - return NO_NODE_ADDED; } /** @@ -1075,7 +995,7 @@ static int sim_fprem(x87_state *const state, ir_node *const n) */ static int sim_fisttp(x87_state *state, ir_node *n) { - ir_node *val = get_irn_n(n, n_ia32_vfst_val); + ir_node *val = get_irn_n(n, n_ia32_fst_val); const arch_register_t *op2 = x87_get_irn_register(val); int const op2_idx = x87_on_stack(state, op2->index); @@ -1091,7 +1011,6 @@ static int sim_fisttp(x87_state *state, ir_node *n) x87_create_fxch(state, n, op2_idx); x87_pop(state); - x87_patch_insn(n, op_ia32_fisttp); DB((dbg, LEVEL_1, "<<< %s %s ->\n", get_irn_opname(n), get_st_reg(0)->name)); @@ -1109,14 +1028,14 @@ static int sim_fisttp(x87_state *state, ir_node *n) static int sim_FtstFnstsw(x87_state *state, ir_node *n) { x87_simulator *sim = state->sim; - ir_node *op1_node = get_irn_n(n, n_ia32_vFtstFnstsw_left); + ir_node *op1_node = get_irn_n(n, n_ia32_FtstFnstsw_left); const arch_register_t *reg1 = x87_get_irn_register(op1_node); int reg_index_1 = reg1->index; int op1_idx = x87_on_stack(state, reg_index_1); - unsigned live = vfp_live_args_after(sim, n, 0); + unsigned live = fp_live_args_after(sim, n, 0); DB((dbg, LEVEL_1, ">>> %+F %s\n", n, reg1->name)); - DEBUG_ONLY(vfp_dump_live(live);) + DEBUG_ONLY(fp_dump_live(live);) DB((dbg, LEVEL_1, "Stack before: ")); DEBUG_ONLY(x87_dump_stack(state);) assert(op1_idx >= 0); @@ -1126,10 +1045,7 @@ static int sim_FtstFnstsw(x87_state *state, ir_node *n) x87_create_fxch(state, n, op1_idx); } - /* patch the operation */ - x87_patch_insn(n, op_ia32_FtstFnstsw); - - if (!is_vfp_live(reg_index_1, live)) + if (!is_fp_live(reg_index_1, live)) x87_create_fpop(state, sched_next(n), 0); return NO_NODE_ADDED; @@ -1145,19 +1061,18 @@ static int sim_FtstFnstsw(x87_state *state, ir_node *n) */ static int sim_Fucom(x87_state *state, ir_node *n) { - ia32_x87_attr_t *attr = get_ia32_x87_attr(n); - ir_op *dst; - x87_simulator *sim = state->sim; - ir_node *op1_node = get_irn_n(n, n_ia32_vFucomFnstsw_left); - ir_node *op2_node = get_irn_n(n, n_ia32_vFucomFnstsw_right); - const arch_register_t *op1 = x87_get_irn_register(op1_node); - const arch_register_t *op2 = x87_get_irn_register(op2_node); + ia32_x87_attr_t *attr = get_ia32_x87_attr(n); + x87_simulator *sim = state->sim; + ir_node *op1_node = get_irn_n(n, n_ia32_FucomFnstsw_left); + ir_node *op2_node = get_irn_n(n, n_ia32_FucomFnstsw_right); + const arch_register_t *op1 = x87_get_irn_register(op1_node); + const arch_register_t *op2 = x87_get_irn_register(op2_node); int reg_index_1 = op1->index; int reg_index_2 = op2->index; - unsigned live = vfp_live_args_after(sim, n, 0); + unsigned live = fp_live_args_after(sim, n, 0); DB((dbg, LEVEL_1, ">>> %+F %s, %s\n", n, op1->name, op2->name)); - DEBUG_ONLY(vfp_dump_live(live);) + DEBUG_ONLY(fp_dump_live(live);) DB((dbg, LEVEL_1, "Stack before: ")); DEBUG_ONLY(x87_dump_stack(state);) @@ -1167,15 +1082,15 @@ static int sim_Fucom(x87_state *state, ir_node *n) int op2_idx; int pops = 0; /* BEWARE: check for comp a,a cases, they might happen */ - if (reg_index_2 != REG_VFP_VFP_NOREG) { - /* second operand is a vfp register */ + if (reg_index_2 != REG_FP_FP_NOREG) { + /* second operand is a fp register */ op2_idx = x87_on_stack(state, reg_index_2); assert(op2_idx >= 0); - if (is_vfp_live(reg_index_2, live)) { + if (is_fp_live(reg_index_2, live)) { /* second operand is live */ - if (is_vfp_live(reg_index_1, live)) { + if (is_fp_live(reg_index_1, live)) { /* both operands are live */ if (op1_idx != 0 && op2_idx != 0) { /* bring the first one to tos */ @@ -1200,7 +1115,7 @@ static int sim_Fucom(x87_state *state, ir_node *n) } } else { /* second operand is dead */ - if (is_vfp_live(reg_index_1, live)) { + if (is_fp_live(reg_index_1, live)) { /* first operand is live: bring second to tos. This means further, op1_idx != op2_idx. */ assert(op1_idx != op2_idx); @@ -1244,7 +1159,7 @@ static int sim_Fucom(x87_state *state, ir_node *n) if (op1_idx != 0) x87_create_fxch(state, n, op1_idx); /* Pop first operand, if it is dead. */ - if (!is_vfp_live(reg_index_1, live)) + if (!is_fp_live(reg_index_1, live)) pops = 1; op1_idx = attr->attr.data.ins_permuted ? -1 : 0; @@ -1253,30 +1168,20 @@ static int sim_Fucom(x87_state *state, ir_node *n) assert(op1_idx == 0 || op2_idx == 0); /* patch the operation */ - if (is_ia32_vFucomFnstsw(n)) { - if (pops == 2 && (op1_idx == 1 || op2_idx == 1)) { - dst = op_ia32_FucomppFnstsw; - x87_pop(state); - x87_pop(state); - } else { - dst = op_ia32_FucomFnstsw; - goto pop; - } - } else if (is_ia32_vFucomi(n)) { - dst = op_ia32_Fucomi; -pop: + if (is_ia32_FucomFnstsw(n) && pops == 2 + && (op1_idx == 1 || op2_idx == 1)) { + set_irn_op(n, op_ia32_FucomppFnstsw); + x87_pop(state); + x87_pop(state); + } else { if (pops != 0) x87_pop(state); if (pops == 2) { int const idx = (op1_idx != 0 ? op1_idx : op2_idx) - 1 /* Due to prior pop. */; x87_create_fpop(state, sched_next(n), idx); } - } else { - panic("invalid operation %+F", n); } - x87_patch_insn(n, dst); - int const reg_idx = op1_idx != 0 ? op1_idx : op2_idx; attr->reg = reg_idx >= 0 ? get_st_reg(reg_idx) : NULL; attr->attr.data.ins_permuted = op1_idx != 0; @@ -1286,7 +1191,7 @@ pop: char const *const l = op1_idx >= 0 ? get_st_reg(op1_idx)->name : "[AM]"; char const *const r = op2_idx >= 0 ? get_st_reg(op2_idx)->name : "[AM]"; DB((dbg, LEVEL_1, "<<< %s %s, %s\n", get_irn_opname(n), l, r)); - ); + ) return NO_NODE_ADDED; } @@ -1314,14 +1219,14 @@ static int sim_Keep(x87_state *state, ir_node *node) for (i = 0; i < arity; ++i) { op = get_irn_n(node, i); op_reg = arch_get_irn_register(op); - if (op_reg->reg_class != &ia32_reg_classes[CLASS_ia32_vfp]) + if (op_reg->reg_class != &ia32_reg_classes[CLASS_ia32_fp]) continue; reg_id = op_reg->index; - live = vfp_live_args_after(state->sim, node, 0); + live = fp_live_args_after(state->sim, node, 0); op_stack_idx = x87_on_stack(state, reg_id); - if (op_stack_idx >= 0 && !is_vfp_live(reg_id, live)) + if (op_stack_idx >= 0 && !is_fp_live(reg_id, live)) x87_create_fpop(state, sched_next(node), 0); } @@ -1357,7 +1262,7 @@ static ir_node *create_Copy(x87_state *state, ir_node *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_node *, ir_mode *) = NULL; + ir_node *(*cnstr)(dbg_info *, ir_node *) = NULL; ir_node *res; const arch_register_t *out; const arch_register_t *op1; @@ -1394,7 +1299,7 @@ static ir_node *create_Copy(x87_state *state, ir_node *n) if (cnstr != NULL) { /* copy a constant */ - res = (*cnstr)(n_dbg, block, mode); + res = (*cnstr)(n_dbg, block); x87_push(state, out->index, res); } else { @@ -1423,18 +1328,18 @@ static ir_node *create_Copy(x87_state *state, ir_node *n) static int sim_Copy(x87_state *state, ir_node *n) { arch_register_class_t const *const cls = arch_get_irn_reg_class(n); - if (cls != &ia32_reg_classes[CLASS_ia32_vfp]) + if (cls != &ia32_reg_classes[CLASS_ia32_fp]) return NO_NODE_ADDED; ir_node *const pred = be_get_Copy_op(n); arch_register_t const *const op1 = x87_get_irn_register(pred); arch_register_t const *const out = x87_get_irn_register(n); - unsigned const live = vfp_live_args_after(state->sim, n, REGMASK(out)); + unsigned const live = fp_live_args_after(state->sim, n, REGMASK(out)); DB((dbg, LEVEL_1, ">>> %+F %s -> %s\n", n, op1->name, out->name)); - DEBUG_ONLY(vfp_dump_live(live);) + DEBUG_ONLY(fp_dump_live(live);) - if (is_vfp_live(op1->index, live)) { + if (is_fp_live(op1->index, 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 */ ir_node *const node = create_Copy(state, n); @@ -1445,10 +1350,8 @@ static int sim_Copy(x87_state *state, ir_node *n) * instruction, but we would have to rerun all the simulation to get * this correct... */ - ir_node *const next = sched_next(n); - sched_remove(n); + sched_replace(n, node); exchange(n, node); - sched_add_before(next, node); if (get_irn_n_edges(pred) == 0) { keep_float_node_alive(pred); @@ -1475,7 +1378,7 @@ static ir_node *get_call_result_proj(ir_node *call) ir_node *proj = get_edge_src_irn(edge); long pn = get_Proj_proj(proj); - if (pn == pn_ia32_Call_vf0) + if (pn == pn_ia32_Call_st0) return proj; } @@ -1486,15 +1389,13 @@ static int sim_Asm(x87_state *const state, ir_node *const n) { (void)state; - for (size_t i = get_irn_arity(n); i-- != 0;) { - arch_register_req_t const *const req = arch_get_irn_register_req_in(n, i); - if (req->cls == &ia32_reg_classes[CLASS_ia32_vfp]) - panic("cannot handle %+F with x87 constraints", n); - } + be_foreach_use(n, &ia32_reg_classes[CLASS_ia32_fp], in_req, value, value_req, + panic("cannot handle %+F with x87 constraints", n); + ); - for (size_t i = arch_get_irn_n_outs(n); i-- != 0;) { + be_foreach_out(n, i) { arch_register_req_t const *const req = arch_get_irn_register_req_out(n, i); - if (req->cls == &ia32_reg_classes[CLASS_ia32_vfp]) + if (req->cls == &ia32_reg_classes[CLASS_ia32_fp]) panic("cannot handle %+F with x87 constraints", n); } @@ -1623,7 +1524,7 @@ static void x87_kill_deads(x87_simulator *const sim, ir_node *const block, x87_s { ir_node *first_insn = sched_first(block); ir_node *keep = NULL; - unsigned live = vfp_live_args_after(sim, block, 0); + unsigned live = fp_live_args_after(sim, block, 0); unsigned kill_mask; int i, depth; @@ -1632,13 +1533,13 @@ static void x87_kill_deads(x87_simulator *const sim, ir_node *const block, x87_s for (i = depth - 1; i >= 0; --i) { int reg = x87_get_st_reg(state, i); - if (! is_vfp_live(reg, live)) + if (! is_fp_live(reg, live)) kill_mask |= (1 << i); } if (kill_mask) { DB((dbg, LEVEL_1, "Killing deads:\n")); - DEBUG_ONLY(vfp_dump_live(live);) + DEBUG_ONLY(fp_dump_live(live);) DEBUG_ONLY(x87_dump_stack(state);) if (kill_mask != 0 && live == 0) { @@ -1795,7 +1696,7 @@ static void x87_init_simulator(x87_simulator *sim, ir_graph *irg) obstack_init(&sim->obst); sim->blk_states = pmap_create(); sim->n_idx = get_irg_last_idx(irg); - sim->live = OALLOCN(&sim->obst, vfp_liveness, sim->n_idx); + sim->live = OALLOCN(&sim->obst, fp_liveness, sim->n_idx); DB((dbg, LEVEL_1, "--------------------------------\n" "x87 Simulator started for %+F\n", irg)); @@ -1805,23 +1706,23 @@ static void x87_init_simulator(x87_simulator *sim, ir_graph *irg) register_sim(op_ia32_Asm, sim_Asm); register_sim(op_ia32_Call, sim_Call); - register_sim(op_ia32_vfld, sim_fld); - register_sim(op_ia32_vfild, sim_fild); - register_sim(op_ia32_vfld1, sim_fld1); - register_sim(op_ia32_vfldz, sim_fldz); - register_sim(op_ia32_vfadd, sim_fadd); - register_sim(op_ia32_vfsub, sim_fsub); - register_sim(op_ia32_vfmul, sim_fmul); - register_sim(op_ia32_vfdiv, sim_fdiv); - register_sim(op_ia32_vfprem, sim_fprem); - register_sim(op_ia32_vfabs, sim_fabs); - register_sim(op_ia32_vfchs, sim_fchs); - register_sim(op_ia32_vfist, sim_fist); - register_sim(op_ia32_vfisttp, sim_fisttp); - register_sim(op_ia32_vfst, sim_fst); - register_sim(op_ia32_vFtstFnstsw, sim_FtstFnstsw); - register_sim(op_ia32_vFucomFnstsw, sim_Fucom); - register_sim(op_ia32_vFucomi, sim_Fucom); + register_sim(op_ia32_fld, sim_load); + register_sim(op_ia32_fild, sim_load); + register_sim(op_ia32_fld1, sim_load); + register_sim(op_ia32_fldz, sim_load); + register_sim(op_ia32_fadd, sim_binop); + register_sim(op_ia32_fsub, sim_binop); + register_sim(op_ia32_fmul, sim_binop); + register_sim(op_ia32_fdiv, sim_binop); + register_sim(op_ia32_fprem, sim_fprem); + register_sim(op_ia32_fabs, sim_unop); + register_sim(op_ia32_fchs, sim_unop); + register_sim(op_ia32_fist, sim_store); + register_sim(op_ia32_fisttp, sim_fisttp); + register_sim(op_ia32_fst, sim_store); + register_sim(op_ia32_FtstFnstsw, sim_FtstFnstsw); + register_sim(op_ia32_FucomFnstsw, sim_Fucom); + register_sim(op_ia32_Fucomi, sim_Fucom); register_sim(op_be_Copy, sim_Copy); register_sim(op_be_Return, sim_Return); register_sim(op_be_Perm, sim_Perm);