From 8ac3590c7251b05225fca87854b3915ef0374261 Mon Sep 17 00:00:00 2001 From: Michael Beck Date: Wed, 14 May 2008 10:17:58 +0000 Subject: [PATCH] - modeled vfisttp using a dummy output value, this should fix the non-working copy hack [r19608] --- ir/be/bespillslots.c | 9 ++++-- ir/be/ia32/ia32_spec.pl | 4 +-- ir/be/ia32/ia32_transform.c | 55 ++++++++++++++++++++----------------- ir/be/ia32/ia32_x87.c | 25 ++++++----------- 4 files changed, 48 insertions(+), 45 deletions(-) diff --git a/ir/be/bespillslots.c b/ir/be/bespillslots.c index 018ea1b3f..43149be83 100644 --- a/ir/be/bespillslots.c +++ b/ir/be/bespillslots.c @@ -127,7 +127,12 @@ static spill_t *collect_spill(be_fec_env_t *env, ir_node *node, const ir_mode *mode, int align) { spill_t spill, *res; - int hash = hash_irn(node); + int hash; + + /* beware: although untypical there might be store nodes WITH Proj's, + vfisttp in ia32 for instance */ + node = skip_Proj(node); + hash = hash_irn(node); /* insert into set of spills if not already there */ spill.spill = node; @@ -663,7 +668,7 @@ static void assign_spillslots(be_fec_env_t *env) for(i = 0; i < ARR_LEN(env->reloads); ++i) { ir_node *reload = env->reloads[i]; - ir_node *spillnode = get_memory_edge(reload); + ir_node *spillnode = skip_Proj(get_memory_edge(reload)); spill_t *spill = get_spill(env, spillnode); const spill_slot_t *slot = & spillslots[spill->spillslot]; diff --git a/ir/be/ia32/ia32_spec.pl b/ir/be/ia32/ia32_spec.pl index 26775aa65..3272a6642 100644 --- a/ir/be/ia32/ia32_spec.pl +++ b/ir/be/ia32/ia32_spec.pl @@ -2000,11 +2000,11 @@ vfist => { # SSE3 fisttp instruction vfisttp => { state => "exc_pinned", - reg_req => { in => [ "gp", "gp", "none", "vfp" ] }, + reg_req => { in => [ "gp", "gp", "none", "vfp" ], out => [ "in_r4", "none" ]}, ins => [ "base", "index", "mem", "val" ], + outs => [ "res", "M" ], latency => 4, units => [ "VFP" ], - mode => "mode_M", attr_type => "ia32_x87_attr_t", }, diff --git a/ir/be/ia32/ia32_transform.c b/ir/be/ia32/ia32_transform.c index a381cbc4f..fb6592a4e 100644 --- a/ir/be/ia32/ia32_transform.c +++ b/ir/be/ia32/ia32_transform.c @@ -2447,7 +2447,7 @@ static ir_node *gen_float_const_Store(ir_node *node, ir_node *cns) { * Generate a vfist or vfisttp instruction. */ static ir_node *gen_vfist(dbg_info *dbgi, ir_graph *irg, ir_node *block, ir_node *base, ir_node *index, - ir_node *mem, ir_node *val) + ir_node *mem, ir_node *val, ir_node **fist) { ir_node *new_node; @@ -2455,14 +2455,18 @@ static ir_node *gen_vfist(dbg_info *dbgi, ir_graph *irg, ir_node *block, ir_node /* Note: fisttp ALWAYS pop the tos. We have to ensure here that the value is copied if other users exists */ const arch_register_class_t *reg_class = &ia32_reg_classes[CLASS_ia32_vfp]; - val = be_new_Copy(reg_class, irg, block, val); + ir_node *vfisttp = new_rd_ia32_vfisttp(dbgi, irg, block, base, index, mem, val); + ir_node *value = new_r_Proj(irg, block, vfisttp, mode_E, pn_ia32_vfisttp_res); + be_new_Keep(reg_class, irg, block, 1, &value); - new_node = new_rd_ia32_vfisttp(dbgi, irg, block, base, index, mem, val); + new_node = new_r_Proj(irg, block, vfisttp, mode_M, pn_ia32_vfisttp_M); + *fist = vfisttp; } else { ir_node *trunc_mode = ia32_new_Fpu_truncate(env_cg); /* do a fist */ new_node = new_rd_ia32_vfist(dbgi, irg, block, base, index, mem, val, trunc_mode); + *fist = new_node; } return new_node; } @@ -2482,8 +2486,7 @@ static ir_node *gen_normal_Store(ir_node *node) ir_graph *irg = current_ir_graph; dbg_info *dbgi = get_irn_dbg_info(node); ir_node *noreg = ia32_new_NoReg_gp(env_cg); - ir_node *new_val; - ir_node *new_node; + ir_node *new_val, *new_node, *store; ia32_address_t addr; /* check for destination address mode */ @@ -2531,7 +2534,7 @@ static ir_node *gen_normal_Store(ir_node *node) val = get_Conv_op(val); } new_val = be_transform_node(val); - new_node = gen_vfist(dbgi, irg, new_block, addr.base, addr.index, addr.mem, new_val); + new_node = gen_vfist(dbgi, irg, new_block, addr.base, addr.index, addr.mem, new_val, &store); } else { new_val = create_immediate_or_transform(val, 0); assert(mode != mode_b); @@ -2543,14 +2546,15 @@ static ir_node *gen_normal_Store(ir_node *node) new_node = new_rd_ia32_Store(dbgi, irg, new_block, addr.base, addr.index, addr.mem, new_val); } + store = new_node; } - set_irn_pinned(new_node, get_irn_pinned(node)); - set_ia32_op_type(new_node, ia32_AddrModeD); - set_ia32_ls_mode(new_node, mode); + set_irn_pinned(store, get_irn_pinned(node)); + set_ia32_op_type(store, ia32_AddrModeD); + set_ia32_ls_mode(store, mode); - set_address(new_node, &addr); - SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node)); + set_address(store, &addr); + SET_IA32_ORIG_NODE(store, ia32_get_old_node_name(env_cg, node)); return new_node; } @@ -3021,9 +3025,9 @@ static ir_node *gen_x87_fp_to_gp(ir_node *node) { dbg_info *dbgi = get_irn_dbg_info(node); ir_node *noreg = ia32_new_NoReg_gp(cg); ir_mode *mode = get_irn_mode(node); - ir_node *fist, *load; + ir_node *fist, *load, *mem; - fist = gen_vfist(dbgi, irg, block, get_irg_frame(irg), noreg, new_NoMem(), new_op); + mem = gen_vfist(dbgi, irg, block, get_irg_frame(irg), noreg, new_NoMem(), new_op, &fist); set_irn_pinned(fist, op_pin_state_floats); set_ia32_use_frame(fist); set_ia32_op_type(fist, ia32_AddrModeD); @@ -3039,7 +3043,7 @@ static ir_node *gen_x87_fp_to_gp(ir_node *node) { SET_IA32_ORIG_NODE(fist, ia32_get_old_node_name(cg, node)); /* do a Load */ - load = new_rd_ia32_Load(dbgi, irg, block, get_irg_frame(irg), noreg, fist); + load = new_rd_ia32_Load(dbgi, irg, block, get_irg_frame(irg), noreg, mem); set_irn_pinned(load, op_pin_state_floats); set_ia32_use_frame(load); @@ -4399,21 +4403,21 @@ static ir_node *gen_ia32_l_vfist(ir_node *node) { dbg_info *dbgi = get_irn_dbg_info(node); ir_node *noreg = ia32_new_NoReg_gp(env_cg); ir_mode *mode = get_ia32_ls_mode(node); - ir_node *new_op; + ir_node *memres, *fist; long am_offs; - new_op = gen_vfist(dbgi, irg, block, new_ptr, noreg, new_mem, new_val); + memres = gen_vfist(dbgi, irg, block, new_ptr, noreg, new_mem, new_val, &fist); am_offs = get_ia32_am_offs_int(node); - add_ia32_am_offs_int(new_op, am_offs); + add_ia32_am_offs_int(fist, am_offs); - set_ia32_op_type(new_op, ia32_AddrModeD); - set_ia32_ls_mode(new_op, mode); - set_ia32_frame_ent(new_op, get_ia32_frame_ent(node)); - set_ia32_use_frame(new_op); + set_ia32_op_type(fist, ia32_AddrModeD); + set_ia32_ls_mode(fist, mode); + set_ia32_frame_ent(fist, get_ia32_frame_ent(node)); + set_ia32_use_frame(fist); - SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env_cg, node)); + SET_IA32_ORIG_NODE(fist, ia32_get_old_node_name(env_cg, node)); - return new_op; + return memres; } /** @@ -4582,14 +4586,15 @@ static ir_node *gen_ia32_l_FloattoLL(ir_node *node) { ir_node *nomem = new_NoMem(); ir_node *val = get_irn_n(node, n_ia32_l_FloattoLL_val); ir_node *new_val = be_transform_node(val); + ir_node *fist, *mem; - ir_node *fist = gen_vfist(dbgi, irg, block, frame, noreg, nomem, new_val); + mem = gen_vfist(dbgi, irg, block, frame, noreg, nomem, new_val, &fist); SET_IA32_ORIG_NODE(fist, ia32_get_old_node_name(env_cg, node)); set_ia32_use_frame(fist); set_ia32_op_type(fist, ia32_AddrModeD); set_ia32_ls_mode(fist, mode_Ls); - return fist; + return mem; } /** diff --git a/ir/be/ia32/ia32_x87.c b/ir/be/ia32/ia32_x87.c index 67d72eaf7..1ad35ec07 100644 --- a/ir/be/ia32/ia32_x87.c +++ b/ir/be/ia32/ia32_x87.c @@ -1345,8 +1345,6 @@ static int sim_fisttp(x87_state *state, ir_node *n) { int insn = NO_NODE_ADDED; ia32_x87_attr_t *attr; int op2_reg_idx, op2_idx, depth; - int live_after_node; - ir_mode *mode; op2_reg_idx = arch_register_get_index(op2); if (op2_reg_idx == REG_VFP_UKNWN) { @@ -1354,35 +1352,30 @@ static int sim_fisttp(x87_state *state, ir_node *n) { if (state->depth > 0) { op2_idx = 0; DEBUG_ONLY(op2 = NULL); - live_after_node = 1; } else { /* produce a new value which we will consume immediately */ x87_create_fldz(state, n, op2_reg_idx); - live_after_node = 0; op2_idx = x87_on_stack(state, op2_reg_idx); assert(op2_idx >= 0); } } else { op2_idx = x87_on_stack(state, op2_reg_idx); - live_after_node = is_vfp_live(arch_register_get_index(op2), live); DB((dbg, LEVEL_1, ">>> %+F %s ->\n", n, arch_register_get_name(op2))); assert(op2_idx >= 0); } - mode = get_ia32_ls_mode(n); depth = x87_get_depth(state); - if (live_after_node) { - /* ffistp always pop the stack */ - panic("vfisttp with live input detected, RA failed"); - } else { - /* we can only store the tos to memory */ - if (op2_idx != 0) - x87_create_fxch(state, n, op2_idx); + /* Note: although the value is still live here, it is destroyed because + of the pop. The register allocator is aware of that and introduced a copy + if the value must be alive. */ - x87_pop(state); - x87_patch_insn(n, op_ia32_fisttp); - } + /* we can only store the tos to memory */ + if (op2_idx != 0) + x87_create_fxch(state, n, op2_idx); + + x87_pop(state); + x87_patch_insn(n, op_ia32_fisttp); attr = get_ia32_x87_attr(n); attr->x87[1] = op2 = &ia32_st_regs[0]; -- 2.20.1