From: Matthias Braun Date: Tue, 17 Jul 2007 14:27:41 +0000 (+0000) Subject: fix Cltd register pressure, fix some SSE (ABI with x87) call things... X-Git-Url: http://nsz.repo.hu/git/?a=commitdiff_plain;h=e9cda1c478adb98eed8c098cd313d2646bcf51c3;p=libfirm fix Cltd register pressure, fix some SSE (ABI with x87) call things... [r15189] --- diff --git a/ir/be/ia32/bearch_ia32.c b/ir/be/ia32/bearch_ia32.c index b83bffe74..d7d312bc6 100644 --- a/ir/be/ia32/bearch_ia32.c +++ b/ir/be/ia32/bearch_ia32.c @@ -1269,17 +1269,12 @@ static void ia32_collect_frame_entity_nodes(ir_node *node, void *data) const ir_mode *mode = ia32_reg_classes[CLASS_ia32_fp_cw].mode; int align = 4; be_node_needs_frame_entity(env, node, mode, align); - } else if (is_ia32_SetST0(node)) { - const ir_mode *mode = get_ia32_ls_mode(node); - int align = 4; - be_node_needs_frame_entity(env, node, mode, align); } else { #ifndef NDEBUG assert(is_ia32_St(node) || is_ia32_xStoreSimple(node) || is_ia32_vfst(node) || is_ia32_vfist(node) || - is_ia32_GetST0(node) || is_ia32_FnstCW(node)); #endif } diff --git a/ir/be/ia32/ia32_spec.pl b/ir/be/ia32/ia32_spec.pl index e97d78b1d..6f7caacb6 100644 --- a/ir/be/ia32/ia32_spec.pl +++ b/ir/be/ia32/ia32_spec.pl @@ -336,6 +336,7 @@ Immediate => { reg_req => { out => [ "gp_NOREG" ] }, attr => "ir_entity *symconst, int symconst_sign, long offset", attr_type => "ia32_immediate_attr_t", + latency => 0, mode => $mode_gp, }, @@ -344,6 +345,17 @@ Asm => { arity => "variable", out_arity => "variable", attr_type => "ia32_asm_attr_t", + latency => 100, +}, + +ProduceVal => { + op_flags => "c", + irn_flags => "R", + reg_req => { out => [ "gp" ] }, + emit => "", + units => [ ], + latency => 0, + mode => $mode_gp, }, #-----------------------------------------------------------------# @@ -908,8 +920,8 @@ FnstCW => { Cltd => { # we should not rematrialize this node. It produces 2 results and has # very strict constrains - reg_req => { in => [ "eax" ], out => [ "edx" ] }, - ins => [ "val" ], + reg_req => { in => [ "eax", "edx" ], out => [ "edx" ] }, + ins => [ "val", "globbered" ], emit => '. cltd', mode => $mode_gp, units => [ "GP" ], @@ -1248,29 +1260,6 @@ l_SSEtoX87 => { arity => 3, }, -GetST0 => { - op_flags => "L|F", - irn_flags => "I", - state => "pinned", - reg_req => { in => [ "gp", "gp", "none" ] }, - emit => '. fstp%XM %AM', - latency => 4, - units => [ "SSE" ], - mode => "mode_M", -}, - -SetST0 => { - op_flags => "L|F", - irn_flags => "I", - state => "pinned", - reg_req => { in => [ "gp", "gp", "none" ], out => [ "vf0", "none" ] }, - ins => [ "base", "index", "mem" ], - emit => '. fld%XM %AM', - outs => [ "res", "M" ], - latency => 2, - units => [ "SSE" ], -}, - # CopyB CopyB => { diff --git a/ir/be/ia32/ia32_transform.c b/ir/be/ia32/ia32_transform.c index af57736f1..4a4a2ee50 100644 --- a/ir/be/ia32/ia32_transform.c +++ b/ir/be/ia32/ia32_transform.c @@ -1078,7 +1078,9 @@ static ir_node *generate_DivMod(ir_node *node, ir_node *dividend, if (mode_is_signed(mode)) { /* in signed mode, we need to sign extend the dividend */ - sign_extension = new_rd_ia32_Cltd(dbgi, irg, block, new_dividend); + ir_node *produceval = new_rd_ia32_ProduceVal(dbgi, irg, block); + sign_extension = new_rd_ia32_Cltd(dbgi, irg, block, new_dividend, + produceval); } else { sign_extension = new_rd_ia32_Const(dbgi, irg, block); set_ia32_Immop_tarval(sign_extension, get_tarval_null(mode_Iu)); @@ -1216,8 +1218,9 @@ static ir_node *gen_Shrs(ir_node *node) { ir_node *block = be_transform_node(get_nodes_block(node)); ir_node *op = left; ir_node *new_op = be_transform_node(op); + ir_node *pval = new_rd_ia32_ProduceVal(dbgi, irg, block); - return new_rd_ia32_Cltd(dbgi, irg, block, new_op); + return new_rd_ia32_Cltd(dbgi, irg, block, new_op, pval); } } @@ -1422,7 +1425,9 @@ static ir_node *gen_Abs(ir_node *node) { } } else { ir_node *xor; - ir_node *sign_extension = new_rd_ia32_Cltd(dbgi, irg, block, new_op); + ir_node *pval = new_rd_ia32_ProduceVal(dbgi, irg, block); + ir_node *sign_extension = new_rd_ia32_Cltd(dbgi, irg, block, new_op, + pval); SET_IA32_ORIG_NODE(sign_extension, ia32_get_old_node_name(env_cg, node)); @@ -2971,22 +2976,21 @@ static ir_node *gen_be_Return(ir_node *node) { noreg = ia32_new_NoReg_gp(env_cg); /* store xmm0 onto stack */ - sse_store = new_rd_ia32_xStoreSimple(dbgi, irg, block, frame, noreg, new_ret_val, new_ret_mem); + sse_store = new_rd_ia32_xStoreSimple(dbgi, irg, block, frame, noreg, + new_ret_val, new_ret_mem); set_ia32_ls_mode(sse_store, mode); set_ia32_op_type(sse_store, ia32_AddrModeD); set_ia32_use_frame(sse_store); set_ia32_am_flavour(sse_store, ia32_am_B); - /* load into st0 */ - fld = new_rd_ia32_SetST0(dbgi, irg, block, frame, noreg, sse_store); - set_ia32_ls_mode(fld, mode); + /* load into x87 register */ + fld = new_rd_ia32_vfld(dbgi, irg, block, frame, noreg, sse_store, mode); set_ia32_op_type(fld, ia32_AddrModeS); set_ia32_use_frame(fld); set_ia32_am_flavour(fld, ia32_am_B); - mproj = new_r_Proj(irg, block, fld, mode_M, pn_ia32_SetST0_M); - fld = new_r_Proj(irg, block, fld, mode_vfp, pn_ia32_SetST0_res); - arch_set_irn_register(env_cg->arch_env, fld, &ia32_vfp_regs[REG_VF0]); + mproj = new_r_Proj(irg, block, fld, mode_M, pn_ia32_vfld_M); + fld = new_r_Proj(irg, block, fld, mode_vfp, pn_ia32_vfld_res); /* create a new barrier */ arity = get_irn_arity(barrier); @@ -3819,26 +3823,32 @@ static ir_node *gen_Proj_be_Call(ir_node *node) { } if (call_res_pred == NULL || be_is_Call(call_res_pred)) { - return new_rd_Proj(dbgi, irg, block, new_call, mode_M, pn_be_Call_M_regular); + return new_rd_Proj(dbgi, irg, block, new_call, mode_M, + pn_be_Call_M_regular); } else { assert(is_ia32_xLoad(call_res_pred)); - return new_rd_Proj(dbgi, irg, block, call_res_pred, mode_M, pn_ia32_xLoad_M); + return new_rd_Proj(dbgi, irg, block, call_res_pred, mode_M, + pn_ia32_xLoad_M); } } if (proj == pn_be_Call_first_res && mode_is_float(mode) && USE_SSE2(env_cg)) { ir_node *fstp; ir_node *frame = get_irg_frame(irg); ir_node *noreg = ia32_new_NoReg_gp(env_cg); - ir_node *p; + //ir_node *p; ir_node *call_mem = be_get_Proj_for_pn(call, pn_be_Call_M_regular); + ir_node *call_res; - /* in case there is no memory output: create one to serialize the copy FPU -> SSE */ - call_mem = new_rd_Proj(dbgi, irg, block, new_call, mode_M, pn_be_Call_M_regular); + /* in case there is no memory output: create one to serialize the copy + FPU -> SSE */ + call_mem = new_rd_Proj(dbgi, irg, block, new_call, mode_M, + pn_be_Call_M_regular); + call_res = new_rd_Proj(dbgi, irg, block, new_call, mode, + pn_be_Call_first_res); /* store st(0) onto stack */ - fstp = new_rd_ia32_GetST0(dbgi, irg, block, frame, noreg, call_mem); - - set_ia32_ls_mode(fstp, mode); + fstp = new_rd_ia32_vfst(dbgi, irg, block, frame, noreg, call_mem, + call_res, mode); set_ia32_op_type(fstp, ia32_AddrModeD); set_ia32_use_frame(fstp); set_ia32_am_flavour(fstp, ia32_am_B); @@ -3850,8 +3860,10 @@ static ir_node *gen_Proj_be_Call(ir_node *node) { set_ia32_use_frame(sse_load); set_ia32_am_flavour(sse_load, ia32_am_B); - sse_load = new_rd_Proj(dbgi, irg, block, sse_load, mode_xmm, pn_ia32_xLoad_res); + sse_load = new_rd_Proj(dbgi, irg, block, sse_load, mode_xmm, + pn_ia32_xLoad_res); +#if 0 /* now: create new Keep whith all former ins and one additional in - the result Proj */ /* get a Proj representing a caller save register */ @@ -3861,6 +3873,7 @@ static ir_node *gen_Proj_be_Call(ir_node *node) { /* user of the the proj is the Keep */ p = get_edge_src_irn(get_irn_out_edge_first(p)); assert(be_is_Keep(p) && "Keep expected."); +#endif return sse_load; } diff --git a/ir/be/ia32/ia32_x87.c b/ir/be/ia32/ia32_x87.c index c291176de..eaef610bd 100644 --- a/ir/be/ia32/ia32_x87.c +++ b/ir/be/ia32/ia32_x87.c @@ -1659,24 +1659,23 @@ static ir_node *create_Copy(x87_state *state, ir_node *n) { * @return NO_NODE_ADDED */ static int sim_Copy(x87_state *state, ir_node *n) { - x87_simulator *sim; - ir_node *pred; - const arch_register_t *out; - const arch_register_t *op1; - ir_node *node, *next; - ia32_x87_attr_t *attr; - int op1_idx, out_idx; - unsigned live; - - ir_mode *mode = get_irn_mode(n); - - if (!mode_is_float(mode)) + x87_simulator *sim = state->sim; + ir_node *pred; + const arch_register_t *out; + const arch_register_t *op1; + const arch_register_class_t *class; + ir_node *node, *next; + ia32_x87_attr_t *attr; + int op1_idx, out_idx; + unsigned live; + + class = arch_get_irn_reg_class(sim->arch_env, n, -1); + if (class->regs != ia32_vfp_regs) return 0; - sim = state->sim; pred = get_irn_n(n, 0); - out = x87_get_irn_register(sim, n); - op1 = x87_get_irn_register(sim, pred); + out = x87_get_irn_register(sim, n); + op1 = x87_get_irn_register(sim, pred); live = vfp_live_args_after(sim, n, REGMASK(out)); DB((dbg, LEVEL_1, ">>> %+F %s -> %s\n", n, @@ -1772,11 +1771,10 @@ static int sim_Copy(x87_state *state, ir_node *n) { } /* sim_Copy */ /** - * Returns the result proj of the call, or NULL if the result is not used + * Returns the result proj of the call */ static ir_node *get_call_result_proj(ir_node *call) { const ir_edge_t *edge; - ir_node *resproj = NULL; /* search the result proj */ foreach_out_edge(call, edge) { @@ -1784,23 +1782,10 @@ static ir_node *get_call_result_proj(ir_node *call) { long pn = get_Proj_proj(proj); if (pn == pn_be_Call_first_res) { - resproj = proj; - break; - } - } - if (resproj == NULL) { - return NULL; - } - - /* the result proj is connected to a Keep and maybe other nodes */ - foreach_out_edge(resproj, edge) { - ir_node *pred = get_edge_src_irn(edge); - if (!be_is_Keep(pred)) { - return resproj; + return proj; } } - /* only be_Keep found, so result is not used */ return NULL; } /* get_call_result_proj */ @@ -1822,11 +1807,13 @@ static int sim_Call(x87_state *state, ir_node *n, const arch_env_t *arch_env) const arch_register_t *reg; (void) arch_env; + DB((dbg, LEVEL_1, ">>> %+F\n", n)); + /* at the begin of a call the x87 state should be empty */ assert(state->depth == 0 && "stack not empty before call"); if (get_method_n_ress(call_tp) <= 0) - return NO_NODE_ADDED; + goto end_call; /* * If the called function returns a float, it is returned in st(0). @@ -1837,15 +1824,18 @@ static int sim_Call(x87_state *state, ir_node *n, const arch_env_t *arch_env) mode = get_type_mode(res_type); if (mode == NULL || !mode_is_float(mode)) - return NO_NODE_ADDED; + goto end_call; resproj = get_call_result_proj(n); - if (resproj == NULL) - return NO_NODE_ADDED; + assert(resproj != NULL); reg = x87_get_irn_register(state->sim, resproj); x87_push(state, arch_register_get_index(reg), resproj); +end_call: + DB((dbg, LEVEL_1, "Stack after: ")); + DEBUG_ONLY(x87_dump_stack(state)); + return NO_NODE_ADDED; } /* sim_Call */