From: Matthias Braun Date: Mon, 17 Dec 2007 18:27:46 +0000 (+0000) Subject: reimplement the long long -> double, conversion. Removed broken double -> long long... X-Git-Url: http://nsz.repo.hu/git/?a=commitdiff_plain;h=9f4312e19dc28d120e93bd2ee60eea21ddb675c3;p=libfirm reimplement the long long -> double, conversion. Removed broken double -> long long conv for now [r17007] --- diff --git a/ir/be/ia32/ia32_intrinsics.c b/ir/be/ia32/ia32_intrinsics.c index 7abb56d05..fa07a9fc0 100644 --- a/ir/be/ia32/ia32_intrinsics.c +++ b/ir/be/ia32/ia32_intrinsics.c @@ -682,6 +682,8 @@ static int map_Conv(ir_node *call, void *ctx) { ir_node *op_mem[2], *mem; if (n == 1) { + ir_node *float_to_ll; + /* We have a Conv float -> long long here */ ir_node *a_f = params[0]; ir_mode *l_res_mode = get_type_mode(get_method_res_type(method, 0)); @@ -689,60 +691,18 @@ static int map_Conv(ir_node *call, void *ctx) { assert(mode_is_float(get_irn_mode(a_f)) && "unexpected Conv call"); - /* allocate memory on frame to store args */ - ent = env->irg == irg ? env->d_ll_conv : NULL; - if (! ent) { - ent = env->d_ll_conv = frame_alloc_area(get_irg_frame_type(irg), 2 * gp_bytes, 16, 0); - env->irg = irg; - } + float_to_ll = new_rd_ia32_l_FloattoLL(dbg, irg, block, a_f); - /* Store arg */ - frame = get_irg_frame(irg); - - /* - Now we create a node to move the value from a XMM register into - x87 FPU because it is unknown here, which FPU is used. - This node is killed in transformation phase when not needed. - Otherwise it is split up into a movsd + fld - */ - a_f = new_rd_ia32_l_SSEtoX87(dbg, irg, block, frame, a_f, get_irg_no_mem(irg), mode_D); - set_ia32_frame_ent(a_f, ent); - set_ia32_use_frame(a_f); - set_ia32_ls_mode(a_f, mode_D); - - if (mode_is_signed(h_res_mode)) { - /* a float to signed conv, the simple case */ - - /* store from FPU as Int */ - a_f = new_rd_ia32_l_vfist(dbg, irg, block, frame, a_f, get_irg_no_mem(irg)); - set_ia32_frame_ent(a_f, ent); - set_ia32_use_frame(a_f); - set_ia32_ls_mode(a_f, mode_Ls); - mem = a_f; - - /* load low part of the result */ - l_res = new_rd_ia32_l_Load(dbg, irg, block, frame, mem); - set_ia32_frame_ent(l_res, ent); - set_ia32_use_frame(l_res); - set_ia32_ls_mode(l_res, l_res_mode); - l_res = new_r_Proj(irg, block, l_res, l_res_mode, pn_ia32_l_Load_res); - - /* load hight part of the result */ - h_res = new_rd_ia32_l_Load(dbg, irg, block, frame, mem); - set_ia32_frame_ent(h_res, ent); - add_ia32_am_offs_int(h_res, gp_bytes); - set_ia32_use_frame(h_res); - set_ia32_ls_mode(h_res, h_res_mode); - h_res = new_r_Proj(irg, block, h_res, h_res_mode, pn_ia32_l_Load_res); - } else { - /* a float to unsigned conv, more complicated */ - panic("Float->unsigned64 NYI\n"); - } + l_res = new_r_Proj(irg, block, float_to_ll, l_res_mode, + pn_ia32_l_FloattoLL_res_low); + h_res = new_r_Proj(irg, block, float_to_ll, h_res_mode, + pn_ia32_l_FloattoLL_res_high); /* lower the call */ resolve_call(call, l_res, h_res, irg, block); - } - else if (n == 2) { + } else if (n == 2) { + ir_node *ll_to_float; + /* We have a Conv long long -> float here */ ir_node *a_l = params[BINOP_Left_Low]; ir_node *a_h = params[BINOP_Left_High]; @@ -751,57 +711,13 @@ static int map_Conv(ir_node *call, void *ctx) { assert(! mode_is_float(get_irn_mode(a_l)) && ! mode_is_float(get_irn_mode(a_h))); - /* allocate memory on frame to store args */ - ent = env->irg == irg ? env->ll_d_conv : NULL; - if (! ent) { - ent = env->ll_d_conv = frame_alloc_area(get_irg_frame_type(irg), 2 * gp_bytes, 16, 0); - env->irg = irg; - } - - /* Store arg */ - frame = get_irg_frame(irg); - - /* store first arg (low part) */ - store_l = new_rd_ia32_l_Store(dbg, irg, block, frame, a_l, get_irg_no_mem(irg)); - set_ia32_frame_ent(store_l, ent); - set_ia32_use_frame(store_l); - set_ia32_ls_mode(store_l, get_irn_mode(a_l)); - op_mem[0] = store_l; - - /* store second arg (high part) */ - store_h = new_rd_ia32_l_Store(dbg, irg, block, frame, a_h, get_irg_no_mem(irg)); - set_ia32_frame_ent(store_h, ent); - add_ia32_am_offs_int(store_h, gp_bytes); - set_ia32_use_frame(store_h); - set_ia32_ls_mode(store_h, get_irn_mode(a_h)); - op_mem[1] = store_h; - - mem = new_r_Sync(irg, block, 2, op_mem); - - /* Load arg into x87 FPU (implicit convert) */ - fres = new_rd_ia32_l_vfild(dbg, irg, block, frame, mem); - set_ia32_frame_ent(fres, ent); - set_ia32_use_frame(fres); - set_ia32_ls_mode(fres, mode_D); - mem = new_r_Proj(irg, block, fres, mode_M, pn_ia32_l_vfild_M); - fres = new_r_Proj(irg, block, fres, fres_mode, pn_ia32_l_vfild_res); - - /* - Now we create a node to move the loaded value into a XMM - register because it is unknown here, which FPU is used. - This node is killed in transformation phase when not needed. - Otherwise it is split up into a fst + movsd - */ - fres = new_rd_ia32_l_X87toSSE(dbg, irg, block, frame, fres, mem, fres_mode); - set_ia32_frame_ent(fres, ent); - set_ia32_use_frame(fres); - set_ia32_ls_mode(fres, fres_mode); + ll_to_float = new_rd_ia32_l_LLtoFloat(dbg, irg, block, a_h, a_l, + fres_mode); /* lower the call */ - resolve_call(call, fres, NULL, irg, block); - } - else { - assert(0 && "unexpected Conv call"); + resolve_call(call, ll_to_float, NULL, irg, block); + } else { + panic("unexpected Conv call %+F", call); } return 1; diff --git a/ir/be/ia32/ia32_spec.pl b/ir/be/ia32/ia32_spec.pl index 05aeef47e..9ee0999b9 100644 --- a/ir/be/ia32/ia32_spec.pl +++ b/ir/be/ia32/ia32_spec.pl @@ -1637,16 +1637,17 @@ CvtSI2SD => { }, -l_X87toSSE => { +l_LLtoFloat => { op_flags => "L|F", cmp_attr => "return 1;", - arity => 3, + ins => [ "val_high", "val_low" ], }, -l_SSEtoX87 => { +l_FloattoLL => { op_flags => "L|F", cmp_attr => "return 1;", - arity => 3, + ins => [ "val" ], + outs => [ "res_high", "res_low" ], }, # CopyB diff --git a/ir/be/ia32/ia32_transform.c b/ir/be/ia32/ia32_transform.c index a70c52e8f..ead958c39 100644 --- a/ir/be/ia32/ia32_transform.c +++ b/ir/be/ia32/ia32_transform.c @@ -4169,104 +4169,63 @@ static ir_node *gen_ia32_l_ShrD(ir_node *node) return gen_lowered_64bit_shifts(node, high, low, count); } -/** - * In case SSE Unit is used, the node is transformed into a vfst + xLoad. - */ -static ir_node *gen_ia32_l_X87toSSE(ir_node *node) { - ir_node *block = be_transform_node(get_nodes_block(node)); - ir_node *val = get_irn_n(node, 1); - ir_node *new_val = be_transform_node(val); - ir_node *res = NULL; - ir_graph *irg = current_ir_graph; - dbg_info *dbgi; - ir_node *noreg, *new_ptr, *new_mem; - ir_node *ptr, *mem; +static ir_node *gen_ia32_l_LLtoFloat(ir_node *node) { + ir_node *src_block = get_nodes_block(node); + ir_node *block = be_transform_node(src_block); + ir_graph *irg = current_ir_graph; + dbg_info *dbgi = get_irn_dbg_info(node); + ir_node *frame = get_irg_frame(irg); + ir_node *noreg = ia32_new_NoReg_gp(env_cg); + ir_node *nomem = new_NoMem(); + ir_node *val_low = get_irn_n(node, n_ia32_l_LLtoFloat_val_low); + ir_node *val_high = get_irn_n(node, n_ia32_l_LLtoFloat_val_high); + ir_node *new_val_low = be_transform_node(val_low); + ir_node *new_val_high = be_transform_node(val_high); + ir_node *in[2]; + ir_node *sync; + ir_node *fild; + ir_node *store_low; + ir_node *store_high; - if (ia32_cg_config.use_sse2) { - return new_val; + if(!mode_is_signed(get_irn_mode(val_high))) { + panic("unsigned long long -> float not supported yet (%+F)", node); } - mem = get_irn_n(node, 2); - new_mem = be_transform_node(mem); - ptr = get_irn_n(node, 0); - new_ptr = be_transform_node(ptr); - noreg = ia32_new_NoReg_gp(env_cg); - dbgi = get_irn_dbg_info(node); - - /* Store x87 -> MEM */ - res = new_rd_ia32_vfst(dbgi, irg, block, new_ptr, noreg, new_mem, new_val, - get_ia32_ls_mode(node)); - set_ia32_frame_ent(res, get_ia32_frame_ent(node)); - set_ia32_use_frame(res); - set_ia32_ls_mode(res, get_ia32_ls_mode(node)); - set_ia32_op_type(res, ia32_AddrModeD); - - /* Load MEM -> SSE */ - res = new_rd_ia32_xLoad(dbgi, irg, block, new_ptr, noreg, res, - get_ia32_ls_mode(node)); - set_ia32_frame_ent(res, get_ia32_frame_ent(node)); - set_ia32_use_frame(res); - set_ia32_op_type(res, ia32_AddrModeS); - res = new_rd_Proj(dbgi, irg, block, res, mode_xmm, pn_ia32_xLoad_res); + /* do a store */ + store_low = new_rd_ia32_Store(dbgi, irg, block, frame, noreg, nomem, + new_val_low); + store_high = new_rd_ia32_Store(dbgi, irg, block, frame, noreg, nomem, + new_val_high); + SET_IA32_ORIG_NODE(store_low, ia32_get_old_node_name(env_cg, node)); + SET_IA32_ORIG_NODE(store_high, ia32_get_old_node_name(env_cg, node)); + + set_ia32_use_frame(store_low); + set_ia32_use_frame(store_high); + set_ia32_op_type(store_low, ia32_AddrModeD); + set_ia32_op_type(store_high, ia32_AddrModeD); + set_ia32_ls_mode(store_low, mode_Iu); + set_ia32_ls_mode(store_high, mode_Is); + add_ia32_am_offs_int(store_high, 4); + + in[0] = store_low; + in[1] = store_high; + sync = new_rd_Sync(dbgi, irg, block, 2, in); - return res; -} + /* do a fild */ + fild = new_rd_ia32_vfild(dbgi, irg, block, frame, noreg, sync); -/** - * In case SSE Unit is used, the node is transformed into a xStore + vfld. - */ -static ir_node *gen_ia32_l_SSEtoX87(ir_node *node) { - ir_node *block = be_transform_node(get_nodes_block(node)); - ir_node *val = get_irn_n(node, 1); - ir_node *new_val = be_transform_node(val); - ir_graph *irg = current_ir_graph; - ir_node *res = NULL; - ir_entity *fent = get_ia32_frame_ent(node); - ir_mode *lsmode = get_ia32_ls_mode(node); - int offs = 0; - ir_node *noreg, *new_ptr, *new_mem; - ir_node *ptr, *mem; - dbg_info *dbgi; - - if (! ia32_cg_config.use_sse2) { - /* SSE unit is not used -> skip this node. */ - return new_val; - } + set_ia32_use_frame(fild); + set_ia32_op_type(fild, ia32_AddrModeS); + set_ia32_ls_mode(fild, mode_Ls); - ptr = get_irn_n(node, 0); - new_ptr = be_transform_node(ptr); - mem = get_irn_n(node, 2); - new_mem = be_transform_node(mem); - noreg = ia32_new_NoReg_gp(env_cg); - dbgi = get_irn_dbg_info(node); - - /* Store SSE -> MEM */ - if (is_ia32_xLoad(skip_Proj(new_val))) { - ir_node *ld = skip_Proj(new_val); - - /* we can vfld the value directly into the fpu */ - fent = get_ia32_frame_ent(ld); - ptr = get_irn_n(ld, 0); - offs = get_ia32_am_offs_int(ld); - } else { - res = new_rd_ia32_xStore(dbgi, irg, block, new_ptr, noreg, new_mem, - new_val); - set_ia32_frame_ent(res, fent); - set_ia32_use_frame(res); - set_ia32_ls_mode(res, lsmode); - set_ia32_op_type(res, ia32_AddrModeD); - mem = res; - } + SET_IA32_ORIG_NODE(fild, ia32_get_old_node_name(env_cg, node)); - /* Load MEM -> x87 */ - res = new_rd_ia32_vfld(dbgi, irg, block, new_ptr, noreg, new_mem, lsmode); - set_ia32_frame_ent(res, fent); - set_ia32_use_frame(res); - add_ia32_am_offs_int(res, offs); - set_ia32_op_type(res, ia32_AddrModeS); - res = new_rd_Proj(dbgi, irg, block, res, mode_vfp, pn_ia32_vfld_res); + return new_r_Proj(irg, block, fild, mode_vfp, pn_ia32_vfild_res); +} - return res; +static ir_node *gen_ia32_l_FloattoLL(ir_node *node) { + (void) node; + panic("LLtoFloat NIY"); } /** @@ -4779,8 +4738,8 @@ static void register_transformers(void) GEN(ia32_l_Load); GEN(ia32_l_vfist); GEN(ia32_l_Store); - GEN(ia32_l_X87toSSE); - GEN(ia32_l_SSEtoX87); + GEN(ia32_l_LLtoFloat); + GEN(ia32_l_FloattoLL); GEN(Const); GEN(SymConst);