X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fia32%2Fia32_transform.c;h=f0a7543a25412e96f061a4391e59c4ad8392e7ea;hb=662c639f2c7b825e6ddf954142119bcc7d43e348;hp=517d12d9e8082af08dfb0ba1e9ac211c0635c352;hpb=09386bbf9b717b6669b11390ab2cbb13230a368b;p=libfirm diff --git a/ir/be/ia32/ia32_transform.c b/ir/be/ia32/ia32_transform.c index 517d12d9e..f0a7543a2 100644 --- a/ir/be/ia32/ia32_transform.c +++ b/ir/be/ia32/ia32_transform.c @@ -5,12 +5,14 @@ #include "irnode_t.h" #include "irgraph_t.h" #include "irmode_t.h" +#include "iropt_t.h" +#include "irop_t.h" +#include "irprog_t.h" #include "irgmod.h" #include "iredges.h" #include "irvrfy.h" #include "ircons.h" #include "dbginfo.h" -#include "iropt_t.h" #include "debug.h" #include "../benode_t.h" @@ -20,7 +22,6 @@ #include "../arch/archop.h" /* we need this for Min and Max nodes */ #include "ia32_transform.h" #include "ia32_new_nodes.h" -#include "ia32_map_regs.h" #include "gen_ia32_regalloc_if.h" @@ -146,19 +147,17 @@ static char *gen_fp_known_const(ir_mode *mode, ia32_known_const_t kct) { } -#undef is_cnst -#define is_cnst(op) (is_ia32_Const(op) || is_ia32_fConst(op)) /* determine if one operator is an Imm */ static ir_node *get_immediate_op(ir_node *op1, ir_node *op2) { if (op1) - return is_cnst(op1) ? op1 : (is_cnst(op2) ? op2 : NULL); - else return is_cnst(op2) ? op2 : NULL; + return is_ia32_Cnst(op1) ? op1 : (is_ia32_Cnst(op2) ? op2 : NULL); + else return is_ia32_Cnst(op2) ? op2 : NULL; } /* determine if one operator is not an Imm */ static ir_node *get_expr_op(ir_node *op1, ir_node *op2) { - return !is_cnst(op1) ? op1 : (!is_cnst(op2) ? op2 : NULL); + return !is_ia32_Cnst(op1) ? op1 : (!is_ia32_Cnst(op2) ? op2 : NULL); } @@ -232,6 +231,10 @@ static ir_node *gen_binop(ia32_transform_env_t *env, ir_node *op1, ir_node *op2, } } + if (is_op_commutative(get_irn_op(env->irn))) { + set_ia32_commutative(new_op); + } + return new_rd_Proj(dbg, irg, block, new_op, mode, 0); } @@ -458,7 +461,7 @@ static ir_node *gen_Add(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) { * @param mode node mode * @return the created ia32 Mul node */ -ir_node *gen_Mul(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) { +static ir_node *gen_Mul(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) { ir_node *new_op; if (mode_is_float(env->mode)) { @@ -1107,6 +1110,10 @@ static ir_node *gen_Load(ia32_transform_env_t *env) { } set_ia32_am_support(new_op, ia32_am_Source); + set_ia32_op_type(new_op, ia32_AddrModeS); + set_ia32_am_flavour(new_op, ia32_B); + set_ia32_ls_mode(new_op, get_Load_mode(node)); + return new_op; } @@ -1121,19 +1128,36 @@ static ir_node *gen_Load(ia32_transform_env_t *env) { * @param mode node mode * @return the created ia32 Store node */ -ir_node *gen_Store(ia32_transform_env_t *env) { +static ir_node *gen_Store(ia32_transform_env_t *env) { ir_node *node = env->irn; ir_node *noreg = ia32_new_NoReg_gp(env->cg); + ir_node *val = get_Store_value(node); + ir_node *ptr = get_Store_ptr(node); + ir_node *mem = get_Store_mem(node); + ir_node *sval = val; ir_node *new_op; + /* in case of storing a const -> make it an attribute */ + if (is_ia32_Cnst(val)) { + sval = noreg; + } + if (mode_is_float(env->mode)) { - new_op = new_rd_ia32_fStore(env->dbg, env->irg, env->block, get_Store_ptr(node), noreg, get_Store_value(node), get_Store_mem(node), env->mode); + new_op = new_rd_ia32_fStore(env->dbg, env->irg, env->block, ptr, noreg, sval, mem, env->mode); } else { - new_op = new_rd_ia32_Store(env->dbg, env->irg, env->block, get_Store_ptr(node), noreg, get_Store_value(node), get_Store_mem(node), env->mode); + new_op = new_rd_ia32_Store(env->dbg, env->irg, env->block, ptr, noreg, sval, mem, env->mode); + } + + /* stored const is an attribute (saves a register) */ + if (is_ia32_Cnst(val)) { + set_ia32_Immop_attr(new_op, val); } set_ia32_am_support(new_op, ia32_am_Dest); + set_ia32_op_type(new_op, ia32_AddrModeD); + set_ia32_am_flavour(new_op, ia32_B); + set_ia32_ls_mode(new_op, get_irn_mode(val)); return new_op; } @@ -1142,128 +1166,10 @@ ir_node *gen_Store(ia32_transform_env_t *env) { /** * Transforms a Call and its arguments corresponding to the calling convention. * - * @param mod the debug module - * @param block the block the new node should belong to - * @param node the ir Call node - * @param dummy mode doesn't matter - * @return the created ia32 Call node + * @param env The transformation environment + * @return The created ia32 Call node */ static ir_node *gen_Call(ia32_transform_env_t *env) { -#if 0 - const ia32_register_req_t **in_req; - ir_node **in; - ir_node *new_call, *sync; - int i, j, n_new_call_in, ignore = 0; - ia32_attr_t *attr; - dbg_info *dbg = env->dbg; - ir_graph *irg = env->irg; - ir_node *block = env->block; - ir_node *call = env->irn; - ir_node **stack_param = NULL; - ir_node **param = get_Call_param_arr(call); - ir_node *call_Mem = get_Call_mem(call); - unsigned cc = get_method_calling_convention(get_Call_type(call)); - int n = get_Call_n_params(call); - int stack_idx = 0; - int biggest_n = -1; - int n_res = get_method_n_ress(get_Call_type(call)); - - assert(n_res <= 2 && "method with more than two results not supported"); - - if (cc & cc_reg_param) - biggest_n = ia32_get_n_regparam_class(n, param, &ignore, &ignore); - - /* remember: biggest_n = x means we can pass (x + 1) parameters in register */ - - /* do we need to pass arguments on stack? */ - if (biggest_n + 1 < n) - stack_param = xcalloc(n - biggest_n - 1, sizeof(ir_node *)); - - /* we need at least one in, either for the stack params or the call_Mem */ - n_new_call_in = biggest_n + 2; - - /* the call has one IN for all stack parameter and one IN for each reg param */ - in = xcalloc(n_new_call_in, sizeof(ir_node *)); - in_req = xcalloc(n_new_call_in, sizeof(arch_register_req_t *)); - - /* loop over all parameters and set the register requirements */ - for (i = 0; i <= biggest_n && (cc & cc_reg_param); i++) { - in_req[i] = ia32_get_RegParam_req(n, param, i, cc); - } - stack_idx = i; - - /* create remaining stack parameters */ - if (cc & cc_last_on_top) { - for (i = stack_idx; i < n; i++) { - /* pass it on stack */ - if (mode_is_float(get_irn_mode(param[i]))) { - stack_param[i - stack_idx] = new_rd_ia32_fStackArg(get_irn_dbg_info(param[i]), irg, - block, call_Mem, param[i], mode_M); - } - else { - stack_param[i - stack_idx] = new_rd_ia32_StackArg(get_irn_dbg_info(param[i]), irg, - block, call_Mem, param[i], mode_M); - } - /* set the argument number for later lowering */ - set_ia32_pncode(stack_param[i - stack_idx], i - stack_idx); - } - } - else { - for (i = n - 1, j = 0; i >= stack_idx; i--, j++) { - /* pass it on stack */ - if (mode_is_float(get_irn_mode(param[i]))) { - stack_param[j] = new_rd_ia32_fStackArg(get_irn_dbg_info(param[i]), irg, - block, call_Mem, param[i], mode_M); - } - else { - stack_param[j] = new_rd_ia32_StackArg(get_irn_dbg_info(param[i]), irg, - block, call_Mem, param[i], mode_M); - } - /* set the argument number for later lowering */ - set_ia32_pncode(stack_param[j], j); - } - } - - if (stack_param) { - sync = new_r_Sync(irg, block, n - biggest_n - 1, stack_param); - in[n_new_call_in - 1] = sync; - } - else { - in[n_new_call_in - 1] = call_Mem; - } - - /* create the new node */ - new_call = new_rd_ia32_Call(dbg, irg, block, n_new_call_in, in); - set_ia32_Immop_attr(new_call, get_Call_ptr(call)); - - /* set register requirements for in and out */ - attr = get_ia32_attr(new_call); - attr->in_req = in_req; - - set_ia32_n_res(new_call, n_res); - - if (n_res > 0) { - attr->out_req = xcalloc(n_res, sizeof(ia32_register_req_t *)); - attr->slots = xcalloc(n_res, sizeof(arch_register_t *)); - } - - /* two results only appear when a 64bit int result is broken up into two 32bit results */ - if (n_res == 1) { - if (mode_is_float(get_type_mode(get_method_res_type(get_Call_type(call), 0)))) - attr->out_req[0] = &ia32_default_req_ia32_fp_xmm0; - else - attr->out_req[0] = &ia32_default_req_ia32_gp_eax; - } - else if (n_res == 2) { - attr->out_req[0] = &ia32_default_req_ia32_gp_eax; - attr->out_req[1] = &ia32_default_req_ia32_gp_edx; - } - - /* stack parameter has no OUT register */ - attr->in_req[n_new_call_in - 1] = &ia32_default_req_none; - - return new_call; -#endif } @@ -1319,131 +1225,89 @@ static ir_node *gen_Cond(ia32_transform_env_t *env) { /** - * Transform the argument projs from a start node corresponding to the - * calling convention. - * It transforms "Proj Arg x -> ProjT -> Start <- ProjM" into - * "RegParam x -> ProjT -> Start" OR - * "StackParam x -> ProjM -> Start" - * whether parameter is passed in register or on stack. + * Transforms a CopyB node. * - * @param mod the debug module - * @param block the block the nodes should belong to - * @param proj the ProjT node which points to Start - * @param start the Start node - * @return Should be always NULL + * @param env The transformation environment + * @return The transformed node. */ -static ir_node *gen_Proj_Start(ia32_transform_env_t *env, ir_node *proj, ir_node *start) { -#if 0 - const ia32_register_req_t *temp_req; - const ir_edge_t *edge; - ir_node *succ, *irn; - ir_node **projargs; - ir_mode *mode; - int n, i; - unsigned cc; - ir_node *proj_M = get_irg_initial_mem(current_ir_graph); - entity *irg_ent = get_irg_entity(current_ir_graph); - ir_type *tp = get_entity_type(irg_ent); - int cur_pn = 0; - ir_graph *irg = env->irg; - ir_node *block = env->block; - - assert(is_Method_type(tp) && "irg type is not a method"); - - switch(get_Proj_proj(proj)) { - case pn_Start_T_args: - /* We cannot use get_method_n_params here as the function might - be variadic or one argument is not used. */ - n = get_irn_n_edges(proj); - - /* Allocate memory for all non variadic parameters in advance to be on the save side */ - env->cg->reg_param_req = xcalloc(get_method_n_params(tp), sizeof(ia32_register_req_t *)); - - /* we are done here when there are no parameters */ - if (n < 1) - break; - - /* temporary remember all proj arg x */ - projargs = xcalloc(n, sizeof(ir_node *)); - - i = 0; - foreach_out_edge((const ir_node *)proj, edge) { - succ = get_edge_src_irn(edge); - assert(is_Proj(succ) && "non-Proj from a Proj_T (pn_Start_T_args)."); - projargs[i++] = succ; - } - - cc = get_method_calling_convention(tp); - - /* loop over all parameters and check whether its a int or float */ - for (i = 0; i < n; i++) { - mode = get_irn_mode(projargs[i]); - cur_pn = get_Proj_proj(projargs[i]); - - if (cc & cc_reg_param) { - temp_req = ia32_get_RegParam_req(n, projargs, cur_pn, cc); - } - else { - temp_req = NULL; - } - - if (temp_req) { - /* passed in register */ - env->cg->reg_param_req[cur_pn] = temp_req; - } - else { - /* passed on stack */ - if (mode_is_float(mode)) - irn = new_rd_ia32_fStackParam(get_irn_dbg_info(projargs[i]), irg, block, proj_M, mode); - else - irn = new_rd_ia32_StackParam(get_irn_dbg_info(projargs[i]), irg, block, proj_M, mode); - - set_ia32_pncode(irn, cur_pn); - - /* kill the old "Proj Arg" and replace with the new stack param */ - exchange(projargs[i], irn); - } - } - - free(projargs); - - break; - case pn_Start_P_frame_base: - case pn_Start_X_initial_exec: - case pn_Start_M: - case pn_Start_P_globals: - case pn_Start_P_value_arg_base: - break; - default: - assert(0 && "unsupported Proj(Start)"); +static ir_node *gen_CopyB(ia32_transform_env_t *env) { + ir_node *res = NULL; + dbg_info *dbg = env->dbg; + ir_graph *irg = env->irg; + ir_mode *mode = env->mode; + ir_node *block = env->block; + ir_node *node = env->irn; + ir_node *src = get_CopyB_src(node); + ir_node *dst = get_CopyB_dst(node); + ir_node *mem = get_CopyB_mem(node); + ir_node *noreg = ia32_new_NoReg_gp(env->cg); + int size = get_type_size_bytes(get_CopyB_type(node)); + int rem; + + /* If we have to copy more than 16 bytes, we use REP MOVSx and */ + /* then we need the size explicitly in ECX. */ + if (size >= 16) { + rem = size & 0x3; /* size % 4 */ + size >>= 2; + + res = new_rd_ia32_Const(dbg, irg, block, mode_Is); + set_ia32_op_type(res, ia32_Const); + set_ia32_Immop_tarval(res, new_tarval_from_long(size, mode_Is)); + + res = new_rd_ia32_CopyB(dbg, irg, block, dst, src, res, mem, mode); + set_ia32_Immop_tarval(res, new_tarval_from_long(rem, mode_Is)); + } + else { + res = new_rd_ia32_CopyB_i(dbg, irg, block, dst, src, mem, mode); + set_ia32_Immop_tarval(res, new_tarval_from_long(size, mode_Is)); } - return NULL; -#endif + return res; } + + /** - * Transform some Proj's (Proj_Proj, Proj_Start, Proj_Cmp, Proj_Cond, Proj_Call). - * All others are ignored. + * Transforms a Mux node into CMov. * - * @param mod the debug module - * @param block the block the new node should belong to - * @param node the ir Proj node - * @param mode mode of the Proj + * @param env The transformation environment * @return The transformed node. */ -static ir_node *gen_Proj(ia32_transform_env_t *env) { - ir_node *new_node = NULL; - ir_node *pred = get_Proj_pred(env->irn); +static ir_node *gen_Mux(ia32_transform_env_t *env) { + ir_node *node = env->irn; - if (env->mode == mode_M) - return NULL; + return new_rd_ia32_CMov(env->dbg, env->irg, env->block, + get_Mux_sel(node), get_Mux_false(node), get_Mux_true(node), env->mode); +} - if (get_irn_op(pred) == op_Start) { - new_node = gen_Proj_Start(env, env->irn, pred); - } - return new_node; + +/******************************************** + * _ _ + * | | | | + * | |__ ___ _ __ ___ __| | ___ ___ + * | '_ \ / _ \ '_ \ / _ \ / _` |/ _ \/ __| + * | |_) | __/ | | | (_) | (_| | __/\__ \ + * |_.__/ \___|_| |_|\___/ \__,_|\___||___/ + * + ********************************************/ + +static ir_node *gen_FrameAddr(ia32_transform_env_t *tenv) { + ir_node *new_op = NULL; + + return new_op; +} + +static ir_node *gen_FrameLoad(ia32_transform_env_t *tenv) { + ir_node *new_op = NULL; + + return new_op; +} + +static ir_node *gen_FrameStore(ia32_transform_env_t *tenv) { + ir_node *new_op = NULL; + + return new_op; } @@ -1458,8 +1322,6 @@ static ir_node *gen_Proj(ia32_transform_env_t *env) { * *********************************************************/ - - /** * Transforms the given firm node (and maybe some other related nodes) * into one or more assembler nodes. @@ -1476,7 +1338,6 @@ void ia32_transform_node(ir_node *node, void *env) { if (is_Block(node)) return; - tenv.arch_env = cgenv->arch_env; tenv.block = get_nodes_block(node); tenv.dbg = get_irn_dbg_info(node); tenv.irg = current_ir_graph; @@ -1490,6 +1351,16 @@ void ia32_transform_node(ir_node *node, void *env) { #define GEN(a) case iro_##a: asm_node = gen_##a(&tenv); break #define IGN(a) case iro_##a: break #define BAD(a) case iro_##a: goto bad +#define OTHER_BIN(a) \ + if (get_irn_op(node) == get_op_##a()) { \ + asm_node = gen_##a(&tenv, get_irn_n(node, 0), get_irn_n(node, 1)); \ + break; \ + } +#define BE_GEN(a) \ + if (be_is_##a(node)) { \ + asm_node = gen_##a(&tenv); \ + break; \ + } DBG((tenv.mod, LEVEL_1, "check %+F ... ", node)); @@ -1520,10 +1391,13 @@ void ia32_transform_node(ir_node *node, void *env) { GEN(Store); GEN(Cond); - IGN(Proj); + GEN(CopyB); + GEN(Mux); + IGN(Call); IGN(Alloc); + IGN(Proj); IGN(Block); IGN(Start); IGN(End); @@ -1533,16 +1407,17 @@ void ia32_transform_node(ir_node *node, void *env) { IGN(Break); IGN(Cmp); IGN(Unknown); + /* constant transformation happens earlier */ IGN(Const); IGN(SymConst); + IGN(Sync); BAD(Raise); BAD(Sel); BAD(InstOf); BAD(Cast); BAD(Free); - BAD(Sync); BAD(Tuple); BAD(Id); BAD(Bad); @@ -1551,25 +1426,22 @@ void ia32_transform_node(ir_node *node, void *env) { BAD(CallBegin); BAD(EndReg); BAD(EndExcept); - BAD(Mux); - BAD(CopyB); default: - if (get_irn_op(node) == get_op_Max()) { - asm_node = gen_Max(&tenv, get_irn_n(node, 0), get_irn_n(node, 1)); - } - else if (get_irn_op(node) == get_op_Min()) { - asm_node = gen_Min(&tenv, get_irn_n(node, 0), get_irn_n(node, 1)); - } - else if (get_irn_op(node) == get_op_Mulh()) { - asm_node = gen_Mulh(&tenv, get_irn_n(node, 0), get_irn_n(node, 1)); - } + OTHER_BIN(Max); + OTHER_BIN(Min); + OTHER_BIN(Mulh); + + BE_GEN(FrameAddr); + BE_GEN(FrameLoad); + BE_GEN(FrameStore); break; bad: fprintf(stderr, "Not implemented: %s\n", get_irn_opname(node)); assert(0); } + /* exchange nodes if a new one was generated */ if (asm_node) { exchange(node, asm_node); DB((tenv.mod, LEVEL_1, "created node %+F[%p]\n", asm_node, asm_node)); @@ -1577,4 +1449,12 @@ bad: else { DB((tenv.mod, LEVEL_1, "ignored\n")); } + +#undef UNOP +#undef BINOP +#undef GEN +#undef IGN +#undef BAD +#undef OTHER_BIN +#undef BE_GEN }