X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fia32%2Fia32_intrinsics.c;h=026cd384bcc202592f5477d0f4729a7730977082;hb=049531b478ae922e01b9c23d7ad9ed9d4df9a37d;hp=774a195be3a795f5d2a5d7a6a9b0188c88987bea;hpb=d7ab1511e6f462d9c4556673e1320f6b127afe6b;p=libfirm diff --git a/ir/be/ia32/ia32_intrinsics.c b/ir/be/ia32/ia32_intrinsics.c index 774a195be..026cd384b 100644 --- a/ir/be/ia32/ia32_intrinsics.c +++ b/ir/be/ia32/ia32_intrinsics.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1995-2007 University of Karlsruhe. All right reserved. + * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved. * * This file is part of libFirm. * @@ -24,9 +24,7 @@ * @author Michael Beck * @version $Id$ */ -#ifdef HAVE_CONFIG_H #include "config.h" -#endif #include "irgmod.h" #include "irop.h" @@ -35,6 +33,7 @@ #include "irprog_t.h" #include "lowering.h" #include "array.h" +#include "error.h" #include "ia32_new_nodes.h" #include "bearch_ia32_t.h" @@ -43,8 +42,8 @@ /** The array of all intrinsics that must be mapped. */ static i_record *intrinsics; -/** An array to cache all entities */ -static ir_entity *i_ents[iro_MaxOpcode]; +/** An array to cache all entities. */ +static ir_entity *i_ents[iro_Last + 1]; /* * Maps all intrinsic calls that the backend support @@ -66,9 +65,10 @@ void ia32_handle_intrinsics(void) { * Replace a call be a tuple of l_res, h_res. */ static void resolve_call(ir_node *call, ir_node *l_res, ir_node *h_res, ir_graph *irg, ir_node *block) { - ir_node *res, *in[2]; + ir_node *jmp, *res, *in[2]; ir_node *bad = get_irg_bad(irg); ir_node *nomem = get_irg_no_mem(irg); + int old_cse; in[0] = l_res; in[1] = h_res; @@ -76,11 +76,19 @@ static void resolve_call(ir_node *call, ir_node *l_res, ir_node *h_res, ir_graph turn_into_tuple(call, pn_Call_max); set_Tuple_pred(call, pn_Call_M_regular, nomem); - /* Matze: the new_r_Jmp here sometimes CSEs and then bad things happen - * (in movgen.c from 186.crafty for example) I don't know why it is here - * and if this fix is correct... */ - /*set_Tuple_pred(call, pn_Call_X_regular, new_r_Jmp(irg, block));*/ - set_Tuple_pred(call, pn_Call_X_regular, bad); + /* + * Beware: + * We do not check here if this call really has exception and regular Proj's. + * new_r_Jmp might than be CSEd with the real exit jmp and then bad things happen + * (in movgen.c from 186.crafty for example). + * So be sure the newly created Jmp cannot CSE. + */ + old_cse = get_opt_cse(); + set_opt_cse(0); + jmp = new_r_Jmp(irg, block); + set_opt_cse(old_cse); + + set_Tuple_pred(call, pn_Call_X_regular, jmp); set_Tuple_pred(call, pn_Call_X_except, bad); set_Tuple_pred(call, pn_Call_T_result, res); set_Tuple_pred(call, pn_Call_M_except, nomem); @@ -227,13 +235,13 @@ static int map_Shl(ir_node *call, void *ctx) { in[0] = l1; in[1] = l2; l_res = new_r_Phi(irg, block, 2, in, l_mode); - set_irn_link(block, l_res); + set_Block_phis(block, l_res); in[0] = h1; in[1] = h2; h_res = new_r_Phi(irg, block, 2, in, h_mode); - set_irn_link(l_res, h_res); - set_irn_link(h_res, NULL); + set_Phi_next(l_res, h_res); + set_Phi_next(h_res, NULL); /* move it down */ set_nodes_block(call, block); @@ -305,7 +313,7 @@ static int map_Shr(ir_node *call, void *ctx) { /* the block for cnt >= 32 */ n_block = new_rd_Block(dbg, irg, 1, &in[1]); l2 = new_rd_Conv(dbg, irg, n_block, h1, l_mode); - h2 = new_r_Const(irg, n_block, l_mode, get_mode_null(h_mode)); + h2 = new_r_Const(irg, n_block, h_mode, get_mode_null(h_mode)); in[1] = new_r_Jmp(irg, n_block); set_irn_in(block, 2, in); @@ -313,13 +321,13 @@ static int map_Shr(ir_node *call, void *ctx) { in[0] = l1; in[1] = l2; l_res = new_r_Phi(irg, block, 2, in, l_mode); - set_irn_link(block, l_res); + set_Block_phis(block, l_res); in[0] = h1; in[1] = h2; h_res = new_r_Phi(irg, block, 2, in, h_mode); - set_irn_link(l_res, h_res); - set_irn_link(h_res, NULL); + set_Phi_next(l_res, h_res); + set_Phi_next(h_res, NULL); /* move it down */ set_nodes_block(call, block); @@ -401,13 +409,13 @@ static int map_Shrs(ir_node *call, void *ctx) { in[0] = l1; in[1] = l2; l_res = new_r_Phi(irg, block, 2, in, l_mode); - set_irn_link(block, l_res); + set_Block_phis(block, l_res); in[0] = h1; in[1] = h2; h_res = new_r_Phi(irg, block, 2, in, h_mode); - set_irn_link(l_res, h_res); - set_irn_link(h_res, NULL); + set_Phi_next(l_res, h_res); + set_Phi_next(h_res, NULL); /* move it down */ set_nodes_block(call, block); @@ -624,7 +632,7 @@ static int map_Div(ir_node *call, void *ctx) { static int map_Mod(ir_node *call, void *ctx) { ia32_intrinsic_env_t *env = ctx; ir_type *method = get_Call_type(call); - ir_mode *h_mode = get_type_mode(get_method_res_type(method, 0)); + ir_mode *h_mode = get_type_mode(get_method_res_type(method, 1)); ir_node *ptr; ir_entity *ent; symconst_symbol sym; @@ -658,20 +666,18 @@ static int map_Mod(ir_node *call, void *ctx) { * Maps a Conv. */ static int map_Conv(ir_node *call, void *ctx) { - ia32_intrinsic_env_t *env = ctx; - ir_graph *irg = current_ir_graph; - dbg_info *dbg = get_irn_dbg_info(call); - ir_node *block = get_nodes_block(call); - ir_node **params = get_Call_param_arr(call); - ir_type *method = get_Call_type(call); - int n = get_Call_n_params(call); - int gp_bytes = get_mode_size_bytes(ia32_reg_classes[CLASS_ia32_gp].mode); - ir_entity *ent; - ir_node *l_res, *h_res, *frame, *fres; - ir_node *store_l, *store_h; - ir_node *op_mem[2], *mem; + ir_graph *irg = current_ir_graph; + dbg_info *dbg = get_irn_dbg_info(call); + ir_node *block = get_nodes_block(call); + ir_node **params = get_Call_param_arr(call); + ir_type *method = get_Call_type(call); + int n = get_Call_n_params(call); + ir_node *l_res, *h_res; + (void) ctx; 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)); @@ -679,113 +685,33 @@ 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); - - /* 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); + 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]; - ir_mode *mode_a_l = get_irn_mode(a_l); - ir_mode *mode_a_h = get_irn_mode(a_h); ir_mode *fres_mode = get_type_mode(get_method_res_type(method, 0)); - assert(! mode_is_float(mode_a_l) && ! mode_is_float(mode_a_h) && "unexpected Conv call"); - - /* 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; - } + assert(! mode_is_float(get_irn_mode(a_l)) + && ! mode_is_float(get_irn_mode(a_h))); - /* 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;