From ad8a59efb0be499f0ccddfd591f3ae57599ebaf5 Mon Sep 17 00:00:00 2001 From: Matthias Braun Date: Mon, 18 Dec 2006 12:43:44 +0000 Subject: [PATCH] - Use a default node compare attribute function for all nodes, except the ones where CSE is explicitely forbidden. This fixes some bugs where a cmp function was missing. - Don't make all the nodes mode_T by default. They keep their normal mode node and only get set to mode_T is we actually use am_Dest - get rid of src_mode and tgt_mode node attribute, you can get the modes by looking at the conv output mode and the arguments mode. This fixes some bugs where the src_mode and tgt_mode attributes were wrong - cleaned up and fixed some bugs in addressmode optimisation --- ir/be/ia32/bearch_ia32.c | 121 ++++----- ir/be/ia32/ia32_emitter.c | 35 +-- ir/be/ia32/ia32_finish.c | 75 +++--- ir/be/ia32/ia32_intrinsics.c | 16 +- ir/be/ia32/ia32_new_nodes.c | 97 +++---- ir/be/ia32/ia32_new_nodes.h | 41 +-- ir/be/ia32/ia32_nodes_attr.h | 2 - ir/be/ia32/ia32_optimize.c | 458 ++++++++++++++++---------------- ir/be/ia32/ia32_spec.pl | 206 ++++----------- ir/be/ia32/ia32_transform.c | 497 +++++++++++++++++------------------ ir/be/ia32/ia32_x87.c | 3 +- 11 files changed, 690 insertions(+), 861 deletions(-) diff --git a/ir/be/ia32/bearch_ia32.c b/ir/be/ia32/bearch_ia32.c index a9e04cb48..ac33f22b1 100644 --- a/ir/be/ia32/bearch_ia32.c +++ b/ir/be/ia32/bearch_ia32.c @@ -117,7 +117,7 @@ static const arch_register_req_t *ia32_get_irn_reg_req(const void *self, arch_re ir_mode *mode = is_Block(irn) ? NULL : get_irn_mode(irn); FIRM_DBG_REGISTER(firm_dbg_module_t *mod, DEBUG_MODULE); - if (is_Block(irn) || mode == mode_M || mode == mode_X) { + if (is_Block(irn) || mode == mode_X) { DBG((mod, LEVEL_1, "ignoring Block, mode_M, mode_X node %+F\n", irn)); return NULL; } @@ -130,6 +130,9 @@ static const arch_register_req_t *ia32_get_irn_reg_req(const void *self, arch_re DBG((mod, LEVEL_1, "get requirements at pos %d for %+F ... ", pos, irn)); if (is_Proj(irn)) { + if(mode == mode_M) + return NULL; + if(pos >= 0) { DBG((mod, LEVEL_1, "ignoring request IN requirements for node %+F\n", irn)); return NULL; @@ -305,12 +308,9 @@ static void ia32_set_frame_entity(const void *self, ir_node *irn, ir_entity *ent } static void ia32_set_frame_offset(const void *self, ir_node *irn, int bias) { - char buf[64]; const ia32_irn_ops_t *ops = self; if (get_ia32_frame_ent(irn)) { - ia32_am_flavour_t am_flav = get_ia32_am_flavour(irn); - if(is_ia32_Pop(irn)) { int omit_fp = be_abi_omit_fp(ops->cg->birg->abi); if (omit_fp) { @@ -323,14 +323,17 @@ static void ia32_set_frame_offset(const void *self, ir_node *irn, int bias) { DBG((ops->cg->mod, LEVEL_1, "stack biased %+F with %d\n", irn, bias)); - snprintf(buf, sizeof(buf), "%d", bias); - if (get_ia32_op_type(irn) == ia32_Normal) { + // Matze: When does this case happen? + char buf[64]; + snprintf(buf, sizeof(buf), "%d", bias); set_ia32_cnst(irn, buf); } else { - add_ia32_am_offs(irn, buf); + ia32_am_flavour_t am_flav = get_ia32_am_flavour(irn); am_flav |= ia32_O; set_ia32_am_flavour(irn, am_flav); + + add_ia32_am_offs_int(irn, bias); } } } @@ -340,9 +343,9 @@ static int ia32_get_sp_bias(const void *self, const ir_node *irn) { long proj = get_Proj_proj(irn); ir_node *pred = get_Proj_pred(irn); - if (proj == pn_ia32_Push_stack && is_ia32_Push(pred)) + if (is_ia32_Push(pred) && proj == pn_ia32_Push_stack) return 4; - if (proj == pn_ia32_Pop_stack && is_ia32_Pop(pred)) + if (is_ia32_Pop(pred) && proj == pn_ia32_Pop_stack) return -4; } @@ -599,8 +602,9 @@ static int ia32_get_op_estimated_cost(const void *self, const ir_node *irn) static arch_inverse_t *ia32_get_inverse(const void *self, const ir_node *irn, int i, arch_inverse_t *inverse, struct obstack *obst) { ir_graph *irg; ir_mode *mode; + ir_mode *irn_mode; ir_node *block, *noreg, *nomem; - int pnc; + dbg_info *dbg; /* we cannot invert non-ia32 irns */ if (! is_ia32_irn(irn)) @@ -614,24 +618,25 @@ static arch_inverse_t *ia32_get_inverse(const void *self, const ir_node *irn, in if (get_ia32_op_type(irn) != ia32_Normal) return NULL; - irg = get_irn_irg(irn); - block = get_nodes_block(irn); - mode = get_ia32_res_mode(irn); - noreg = get_irn_n(irn, 0); - nomem = new_r_NoMem(irg); + irg = get_irn_irg(irn); + block = get_nodes_block(irn); + mode = get_ia32_res_mode(irn); + irn_mode = get_irn_mode(irn); + noreg = get_irn_n(irn, 0); + nomem = new_r_NoMem(irg); + dbg = get_irn_dbg_info(irn); /* initialize structure */ inverse->nodes = obstack_alloc(obst, 2 * sizeof(inverse->nodes[0])); inverse->costs = 0; - inverse->n = 2; + inverse->n = 1; switch (get_ia32_irn_opcode(irn)) { case iro_ia32_Add: if (get_ia32_immop_type(irn) == ia32_ImmConst) { /* we have an add with a const here */ /* invers == add with negated const */ - inverse->nodes[0] = new_rd_ia32_Add(NULL, irg, block, noreg, noreg, get_irn_n(irn, i), noreg, nomem); - pnc = pn_ia32_Add_res; + inverse->nodes[0] = new_rd_ia32_Add(dbg, irg, block, noreg, noreg, get_irn_n(irn, i), noreg, nomem, irn_mode); inverse->costs += 1; copy_ia32_Immop_attr(inverse->nodes[0], (ir_node *)irn); set_ia32_Immop_tarval(inverse->nodes[0], tarval_neg(get_ia32_Immop_tarval(irn))); @@ -640,8 +645,7 @@ static arch_inverse_t *ia32_get_inverse(const void *self, const ir_node *irn, in else if (get_ia32_immop_type(irn) == ia32_ImmSymConst) { /* we have an add with a symconst here */ /* invers == sub with const */ - inverse->nodes[0] = new_rd_ia32_Sub(NULL, irg, block, noreg, noreg, get_irn_n(irn, i), noreg, nomem); - pnc = pn_ia32_Sub_res; + inverse->nodes[0] = new_rd_ia32_Sub(dbg, irg, block, noreg, noreg, get_irn_n(irn, i), noreg, nomem, irn_mode); inverse->costs += 2; copy_ia32_Immop_attr(inverse->nodes[0], (ir_node *)irn); } @@ -650,8 +654,7 @@ static arch_inverse_t *ia32_get_inverse(const void *self, const ir_node *irn, in ir_node *proj = ia32_get_res_proj(irn); assert(proj); - inverse->nodes[0] = new_rd_ia32_Sub(NULL, irg, block, noreg, noreg, proj, get_irn_n(irn, i ^ 1), nomem); - pnc = pn_ia32_Sub_res; + inverse->nodes[0] = new_rd_ia32_Sub(dbg, irg, block, noreg, noreg, proj, get_irn_n(irn, i ^ 1), nomem, irn_mode); inverse->costs += 2; } break; @@ -659,8 +662,7 @@ static arch_inverse_t *ia32_get_inverse(const void *self, const ir_node *irn, in if (get_ia32_immop_type(irn) != ia32_ImmNone) { /* we have a sub with a const/symconst here */ /* invers == add with this const */ - inverse->nodes[0] = new_rd_ia32_Add(NULL, irg, block, noreg, noreg, get_irn_n(irn, i), noreg, nomem); - pnc = pn_ia32_Add_res; + inverse->nodes[0] = new_rd_ia32_Add(dbg, irg, block, noreg, noreg, get_irn_n(irn, i), noreg, nomem, irn_mode); inverse->costs += (get_ia32_immop_type(irn) == ia32_ImmSymConst) ? 5 : 1; copy_ia32_Immop_attr(inverse->nodes[0], (ir_node *)irn); } @@ -670,27 +672,24 @@ static arch_inverse_t *ia32_get_inverse(const void *self, const ir_node *irn, in assert(proj); if (i == 2) { - inverse->nodes[0] = new_rd_ia32_Add(NULL, irg, block, noreg, noreg, proj, get_irn_n(irn, 3), nomem); + inverse->nodes[0] = new_rd_ia32_Add(dbg, irg, block, noreg, noreg, proj, get_irn_n(irn, 3), nomem, irn_mode); } else { - inverse->nodes[0] = new_rd_ia32_Sub(NULL, irg, block, noreg, noreg, get_irn_n(irn, 2), proj, nomem); + inverse->nodes[0] = new_rd_ia32_Sub(dbg, irg, block, noreg, noreg, get_irn_n(irn, 2), proj, nomem, irn_mode); } - pnc = pn_ia32_Sub_res; inverse->costs += 1; } break; case iro_ia32_Eor: if (get_ia32_immop_type(irn) != ia32_ImmNone) { /* xor with const: inverse = xor */ - inverse->nodes[0] = new_rd_ia32_Eor(NULL, irg, block, noreg, noreg, get_irn_n(irn, i), noreg, nomem); - pnc = pn_ia32_Eor_res; + inverse->nodes[0] = new_rd_ia32_Eor(dbg, irg, block, noreg, noreg, get_irn_n(irn, i), noreg, nomem, irn_mode); inverse->costs += (get_ia32_immop_type(irn) == ia32_ImmSymConst) ? 5 : 1; copy_ia32_Immop_attr(inverse->nodes[0], (ir_node *)irn); } else { /* normal xor */ - inverse->nodes[0] = new_rd_ia32_Eor(NULL, irg, block, noreg, noreg, (ir_node *)irn, get_irn_n(irn, i), nomem); - pnc = pn_ia32_Eor_res; + inverse->nodes[0] = new_rd_ia32_Eor(dbg, irg, block, noreg, noreg, (ir_node *)irn, get_irn_n(irn, i), nomem, irn_mode); inverse->costs += 1; } break; @@ -698,8 +697,7 @@ static arch_inverse_t *ia32_get_inverse(const void *self, const ir_node *irn, in ir_node *proj = ia32_get_res_proj(irn); assert(proj); - inverse->nodes[0] = new_rd_ia32_Not(NULL, irg, block, noreg, noreg, proj, nomem); - pnc = pn_ia32_Not_res; + inverse->nodes[0] = new_rd_ia32_Not(dbg, irg, block, noreg, noreg, proj, nomem, irn_mode); inverse->costs += 1; break; } @@ -707,8 +705,7 @@ static arch_inverse_t *ia32_get_inverse(const void *self, const ir_node *irn, in ir_node *proj = ia32_get_res_proj(irn); assert(proj); - inverse->nodes[0] = new_rd_ia32_Minus(NULL, irg, block, noreg, noreg, proj, nomem); - pnc = pn_ia32_Minus_res; + inverse->nodes[0] = new_rd_ia32_Minus(dbg, irg, block, noreg, noreg, proj, nomem, irn_mode); inverse->costs += 1; break; } @@ -718,7 +715,6 @@ static arch_inverse_t *ia32_get_inverse(const void *self, const ir_node *irn, in } set_ia32_res_mode(inverse->nodes[0], mode); - inverse->nodes[1] = new_r_Proj(irg, block, inverse->nodes[0], mode, pnc); return inverse; } @@ -807,14 +803,8 @@ static void ia32_perform_memory_operand(const void *self, ir_node *irn, ir_node set_ia32_got_reload(irn); set_irn_n(irn, 0, get_irg_frame(get_irn_irg(irn))); - set_irn_n(irn, 4, spill); - - /* - Input at position one is index register, which is NoReg. - We would need cg object to get a real noreg, but we cannot - access it from here. - */ set_irn_n(irn, 3, ia32_get_admissible_noreg(cg, irn, 3)); + set_irn_n(irn, 4, spill); //FIXME DBG_OPT_AM_S(reload, irn); } @@ -867,9 +857,8 @@ ia32_irn_ops_t ia32_irn_ops = { static void ia32_kill_convs(ia32_code_gen_t *cg) { ir_node *irn; - /* BEWARE: the Projs are inserted in the set */ foreach_nodeset(cg->kill_conv, irn) { - ir_node *in = get_irn_n(get_Proj_pred(irn), 2); + ir_node *in = get_irn_n(irn, 2); edges_reroute(irn, in, cg->birg->irg); } } @@ -1029,7 +1018,8 @@ static void ia32_before_ra(void *self) { static void transform_to_Load(ia32_transform_env_t *env) { ir_node *irn = env->irn; ir_entity *ent = be_get_frame_entity(irn); - ir_mode *mode = get_spill_mode(env->cg, irn); + ir_mode *mode = get_irn_mode(irn); + ir_mode *spillmode = get_spill_mode(env->cg, irn); ir_node *noreg = ia32_new_NoReg_gp(env->cg); ir_node *sched_point = NULL; ir_node *ptr = get_irg_frame(env->irg); @@ -1041,7 +1031,7 @@ static void transform_to_Load(ia32_transform_env_t *env) { sched_point = sched_prev(irn); } - if (mode_is_float(mode)) { + if (mode_is_float(spillmode)) { if (USE_SSE2(env->cg)) new_op = new_rd_ia32_xLoad(env->dbg, env->irg, env->block, ptr, noreg, mem); else @@ -1053,7 +1043,7 @@ static void transform_to_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, mode); + set_ia32_ls_mode(new_op, spillmode); set_ia32_frame_ent(new_op, ent); set_ia32_use_frame(new_op); @@ -1089,7 +1079,7 @@ static void transform_to_Store(ia32_transform_env_t *env) { ir_node *nomem = new_rd_NoMem(env->irg); ir_node *ptr = get_irg_frame(env->irg); ir_node *val = get_irn_n(irn, be_pos_Spill_val); - ir_node *new_op, *proj; + ir_node *store; ir_node *sched_point = NULL; if (sched_is_scheduled(irn)) { @@ -1098,36 +1088,33 @@ static void transform_to_Store(ia32_transform_env_t *env) { if (mode_is_float(mode)) { if (USE_SSE2(env->cg)) - new_op = new_rd_ia32_xStore(env->dbg, env->irg, env->block, ptr, noreg, val, nomem); + store = new_rd_ia32_xStore(env->dbg, env->irg, env->block, ptr, noreg, val, nomem); else - new_op = new_rd_ia32_vfst(env->dbg, env->irg, env->block, ptr, noreg, val, nomem); + store = new_rd_ia32_vfst(env->dbg, env->irg, env->block, ptr, noreg, val, nomem); } else if (get_mode_size_bits(mode) == 8) { - new_op = new_rd_ia32_Store8Bit(env->dbg, env->irg, env->block, ptr, noreg, val, nomem); + store = new_rd_ia32_Store8Bit(env->dbg, env->irg, env->block, ptr, noreg, val, nomem); } else { - new_op = new_rd_ia32_Store(env->dbg, env->irg, env->block, ptr, noreg, val, nomem); + store = new_rd_ia32_Store(env->dbg, env->irg, env->block, ptr, noreg, val, nomem); } - 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, mode); - set_ia32_frame_ent(new_op, ent); - set_ia32_use_frame(new_op); - - DBG_OPT_SPILL2ST(irn, new_op); + set_ia32_am_support(store, ia32_am_Dest); + set_ia32_op_type(store, ia32_AddrModeD); + set_ia32_am_flavour(store, ia32_B); + set_ia32_ls_mode(store, mode); + set_ia32_frame_ent(store, ent); + set_ia32_use_frame(store); - proj = new_rd_Proj(env->dbg, env->irg, env->block, new_op, mode_M, pn_ia32_Store_M); + DBG_OPT_SPILL2ST(irn, store); + SET_IA32_ORIG_NODE(store, ia32_get_old_node_name(env->cg, irn)); if (sched_point) { - sched_add_after(sched_point, new_op); + sched_add_after(sched_point, store); sched_remove(irn); } - SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, irn)); - - exchange(irn, proj); + exchange(irn, store); } static ir_node *create_push(ia32_transform_env_t *env, ir_node *schedpoint, ir_node *sp, ir_node *mem, ir_entity *ent) { @@ -1155,7 +1142,7 @@ static ir_node *create_pop(ia32_transform_env_t *env, ir_node *schedpoint, ir_no set_ia32_frame_ent(pop, ent); set_ia32_use_frame(pop); set_ia32_op_type(pop, ia32_AddrModeD); - set_ia32_am_flavour(pop, ia32_B); + set_ia32_am_flavour(pop, ia32_am_OB); set_ia32_ls_mode(pop, mode_Is); sched_add_before(schedpoint, pop); diff --git a/ir/be/ia32/ia32_emitter.c b/ir/be/ia32/ia32_emitter.c index 9d850a8e0..cc0e8df38 100644 --- a/ir/be/ia32/ia32_emitter.c +++ b/ir/be/ia32/ia32_emitter.c @@ -1558,8 +1558,8 @@ static void emit_ia32_CopyB_i(const ir_node *irn, ia32_emit_env_t *emit_env) { static void emit_ia32_Conv_with_FP(const ir_node *irn, ia32_emit_env_t *emit_env) { FILE *F = emit_env->out; const lc_arg_env_t *env = ia32_get_arg_env(); - ir_mode *src_mode = get_ia32_src_mode(irn); - ir_mode *tgt_mode = get_ia32_tgt_mode(irn); + ir_mode *src_mode = get_ia32_Conv_src_mode(irn); + ir_mode *tgt_mode = get_ia32_Conv_tgt_mode(irn); char *from, *to, buf[64]; char cmd_buf[SNPRINTF_BUF_LEN], cmnt_buf[SNPRINTF_BUF_LEN]; @@ -1602,21 +1602,20 @@ static void emit_ia32_Conv_I2I(const ir_node *irn, ia32_emit_env_t *emit_env) { const lc_arg_env_t *env = ia32_get_arg_env(); char *move_cmd = "movzx"; char *conv_cmd = NULL; - ir_mode *src_mode = get_ia32_src_mode(irn); - ir_mode *tgt_mode = get_ia32_tgt_mode(irn); + ir_mode *src_mode = get_ia32_Conv_src_mode(irn); + ir_mode *tgt_mode = get_ia32_Conv_tgt_mode(irn); int signed_mode; - int n, m; + int src_bits = get_mode_size_bits(src_mode); + int tgt_bits = get_mode_size_bits(tgt_mode); char cmd_buf[SNPRINTF_BUF_LEN], cmnt_buf[SNPRINTF_BUF_LEN]; const arch_register_t *in_reg, *out_reg; - n = get_mode_size_bits(src_mode); - m = get_mode_size_bits(tgt_mode); + assert(mode_is_int(src_mode) && mode_is_int(tgt_mode)); + assert(src_bits == 8 || src_bits == 16 || src_bits == 32); + assert(tgt_bits == 8 || tgt_bits == 16 || tgt_bits == 32); + assert(src_bits != tgt_bits); - assert(n == 8 || n == 16 || n == 32); - assert(m == 8 || m == 16 || m == 32); - assert(n != m); - - signed_mode = mode_is_signed(n < m ? src_mode : tgt_mode); + signed_mode = mode_is_signed(src_bits < tgt_bits ? src_mode : tgt_mode); if(signed_mode) { move_cmd = "movsx"; } @@ -1630,9 +1629,9 @@ static void emit_ia32_Conv_I2I(const ir_node *irn, ia32_emit_env_t *emit_env) { REGS_ARE_EQUAL(out_reg, in_reg) && signed_mode) { - if (n == 8 || m == 8) + if (src_bits == 8 || tgt_bits == 8) conv_cmd = "cbw"; - else if (n == 16 || m == 16) + else if (src_bits == 16 || tgt_bits == 16) conv_cmd = "cwde"; /* argument and result are both in EAX and */ @@ -1643,13 +1642,15 @@ static void emit_ia32_Conv_I2I(const ir_node *irn, ia32_emit_env_t *emit_env) { { /* argument and result are in the same register */ /* and signedness is ok: -> use and with mask */ - int mask = (1 << (n < m ? n : m)) - 1; + int mask = (1 << (src_bits < tgt_bits ? src_bits : tgt_bits)) - 1; lc_esnprintf(env, cmd_buf, SNPRINTF_BUF_LEN, "and %1D, 0x%x", irn, mask); } else { /* use move w/o sign extension */ + ir_mode *smaller_mode = src_bits < tgt_bits ? src_mode : tgt_mode; lc_esnprintf(env, cmd_buf, SNPRINTF_BUF_LEN, "%s %1D, %%%s", - move_cmd, irn, ia32_get_reg_name_for_mode(emit_env, n < m ? src_mode : tgt_mode, in_reg)); + move_cmd, irn, + ia32_get_reg_name_for_mode(emit_env, smaller_mode, in_reg)); } break; @@ -1662,7 +1663,7 @@ static void emit_ia32_Conv_I2I(const ir_node *irn, ia32_emit_env_t *emit_env) { } lc_esnprintf(env, cmnt_buf, SNPRINTF_BUF_LEN, "/* %+F(%d Bit mode_%F -> %d Bit mode_%F) */", - irn, n, src_mode, m, tgt_mode); + irn, src_bits, src_mode, tgt_bits, tgt_mode); IA32_DO_EMIT(irn); } diff --git a/ir/be/ia32/ia32_finish.c b/ir/be/ia32/ia32_finish.c index 45f616b2c..0588ce65f 100644 --- a/ir/be/ia32/ia32_finish.c +++ b/ir/be/ia32/ia32_finish.c @@ -12,6 +12,7 @@ #include "ircons.h" #include "irgmod.h" #include "irgwalk.h" +#include "iredges.h" #include "pdeq.h" #include "../bearch.h" @@ -35,6 +36,7 @@ static void ia32_transform_sub_to_neg_add(ir_node *irn, ia32_code_gen_t *cg) { ia32_transform_env_t tenv; ir_node *in1, *in2, *noreg, *nomem, *res; const arch_register_t *in1_reg, *in2_reg, *out_reg, **slots; + int i, arity; /* Return if AM node or not a Sub or xSub */ if (!(is_ia32_Sub(irn) || is_ia32_xSub(irn)) || get_ia32_op_type(irn) != ia32_Normal) @@ -57,43 +59,47 @@ static void ia32_transform_sub_to_neg_add(ir_node *irn, ia32_code_gen_t *cg) { DEBUG_ONLY(tenv.mod = cg->mod;) /* in case of sub and OUT == SRC2 we can transform the sequence into neg src2 -- add */ - if (REGS_ARE_EQUAL(out_reg, in2_reg)) { - /* generate the neg src2 */ - res = gen_Minus_ex(&tenv, in2); - arch_set_irn_register(cg->arch_env, res, in2_reg); - - /* add to schedule */ - sched_add_before(irn, get_Proj_pred(res)); - sched_add_before(irn, res); - - /* generate the add */ - if (mode_is_float(tenv.mode)) { - res = new_rd_ia32_xAdd(tenv.dbg, tenv.irg, tenv.block, noreg, noreg, res, in1, nomem); - set_ia32_am_support(res, ia32_am_Source); - } - else { - res = new_rd_ia32_Add(tenv.dbg, tenv.irg, tenv.block, noreg, noreg, res, in1, nomem); - set_ia32_am_support(res, ia32_am_Full); - set_ia32_commutative(res); - } - set_ia32_res_mode(res, tenv.mode); + if (!REGS_ARE_EQUAL(out_reg, in2_reg)) + return; + + /* generate the neg src2 */ + res = gen_Minus_ex(&tenv, in2); + arch_set_irn_register(cg->arch_env, res, in2_reg); - SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(tenv.cg, irn)); - /* copy register */ - slots = get_ia32_slots(res); - slots[0] = in2_reg; + /* add to schedule */ + sched_add_before(irn, res); - /* add to schedule */ - sched_add_before(irn, res); + /* generate the add */ + if (mode_is_float(tenv.mode)) { + res = new_rd_ia32_xAdd(tenv.dbg, tenv.irg, tenv.block, noreg, noreg, res, in1, nomem, tenv.mode); + set_ia32_am_support(res, ia32_am_Source); + } + else { + res = new_rd_ia32_Add(tenv.dbg, tenv.irg, tenv.block, noreg, noreg, res, in1, nomem, tenv.mode); + set_ia32_am_support(res, ia32_am_Full); + set_ia32_commutative(res); + } + set_ia32_res_mode(res, tenv.mode); - /* remove the old sub */ - sched_remove(irn); + SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(tenv.cg, irn)); + /* copy register */ + slots = get_ia32_slots(res); + slots[0] = in2_reg; - DBG_OPT_SUB2NEGADD(irn, res); + /* exchange the add and the sub */ + edges_reroute(irn, res, tenv.irg); - /* exchange the add and the sub */ - exchange(irn, res); + /* add to schedule */ + sched_add_before(irn, res); + + /* remove the old sub */ + sched_remove(irn); + arity = get_irn_arity(irn); + for(i = 0; i < arity; ++i) { + set_irn_n(irn, i, new_Bad()); } + + DBG_OPT_SUB2NEGADD(irn, res); } /** @@ -199,7 +205,7 @@ static void ia32_transform_lea_to_add(ir_node *irn, ia32_code_gen_t *cg) { break; } - res = new_rd_ia32_Add(tenv.dbg, tenv.irg, tenv.block, noreg, noreg, op1, op2, nomem); + res = new_rd_ia32_Add(tenv.dbg, tenv.irg, tenv.block, noreg, noreg, op1, op2, nomem, tenv.mode); arch_set_irn_register(cg->arch_env, res, out_reg); set_ia32_op_type(res, ia32_Normal); set_ia32_commutative(res); @@ -217,11 +223,6 @@ static void ia32_transform_lea_to_add(ir_node *irn, ia32_code_gen_t *cg) { DBG_OPT_LEA2ADD(irn, res); - res = new_rd_Proj(tenv.dbg, tenv.irg, tenv.block, res, tenv.mode, pn_ia32_Add_res); - - /* add result Proj to schedule */ - sched_add_before(irn, res); - /* remove the old LEA */ sched_remove(irn); diff --git a/ir/be/ia32/ia32_intrinsics.c b/ir/be/ia32/ia32_intrinsics.c index 21cd94a20..e0641b17a 100644 --- a/ir/be/ia32/ia32_intrinsics.c +++ b/ir/be/ia32/ia32_intrinsics.c @@ -361,14 +361,14 @@ static int DivMod_mapper(ir_node *call, void *ctx, ia32_intrinsic_divmod_t dmtp) set_ia32_frame_ent(store_l, ent_a); set_ia32_use_frame(store_l); set_ia32_ls_mode(store_l, get_irn_mode(a_l)); - op_mem[0] = new_r_Proj(irg, block, store_l, mode_M, pn_ia32_l_Store_M); + op_mem[0] = store_l; 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_a); add_ia32_am_offs_int(store_h, mode_bytes); set_ia32_use_frame(store_h); set_ia32_ls_mode(store_h, get_irn_mode(a_h)); - op_mem[1] = new_r_Proj(irg, block, store_h, mode_M, pn_ia32_l_Store_M); + op_mem[1] = store_h; mem = new_r_Sync(irg, block, 2, op_mem); @@ -385,14 +385,14 @@ static int DivMod_mapper(ir_node *call, void *ctx, ia32_intrinsic_divmod_t dmtp) set_ia32_frame_ent(store_l, ent_b); set_ia32_use_frame(store_l); set_ia32_ls_mode(store_l, get_irn_mode(b_l)); - op_mem[0] = new_r_Proj(irg, block, store_l, mode_M, pn_ia32_l_Store_M); + op_mem[0] = store_l; store_h = new_rd_ia32_l_Store(dbg, irg, block, frame, b_h, get_irg_no_mem(irg)); set_ia32_frame_ent(store_h, ent_b); add_ia32_am_offs_int(store_h, mode_bytes); set_ia32_use_frame(store_h); set_ia32_ls_mode(store_h, get_irn_mode(b_h)); - op_mem[1] = new_r_Proj(irg, block, store_h, mode_M, pn_ia32_l_Store_M); + op_mem[1] = store_h; mem = new_r_Sync(irg, block, 2, op_mem); @@ -426,7 +426,7 @@ static int DivMod_mapper(ir_node *call, void *ctx, ia32_intrinsic_divmod_t dmtp) set_ia32_frame_ent(fres, ent_a); set_ia32_use_frame(fres); set_ia32_ls_mode(fres, mode_D); - mem = new_r_Proj(irg, block, fres, mode_M, pn_ia32_l_vfist_M); + mem = fres; /* load low part of the result */ l_res = new_rd_ia32_l_Load(dbg, irg, block, frame, mem); @@ -508,7 +508,7 @@ static int map_Conv(ir_node *call, void *ctx) { set_ia32_frame_ent(a_f, ent); set_ia32_use_frame(a_f); set_ia32_ls_mode(a_f, mode_D); - mem = new_r_Proj(irg, block, a_f, mode_M, pn_ia32_l_vfist_M); + mem = a_f; /* load low part of the result */ l_res = new_rd_ia32_l_Load(dbg, irg, block, frame, mem); @@ -553,7 +553,7 @@ static int map_Conv(ir_node *call, void *ctx) { 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] = new_r_Proj(irg, block, store_l, mode_M, pn_ia32_l_Store_M); + 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)); @@ -561,7 +561,7 @@ static int map_Conv(ir_node *call, void *ctx) { 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] = new_r_Proj(irg, block, store_h, mode_M, pn_ia32_l_Store_M); + op_mem[1] = store_h; mem = new_r_Sync(irg, block, 2, op_mem); diff --git a/ir/be/ia32/ia32_new_nodes.c b/ir/be/ia32/ia32_new_nodes.c index e95456fde..2f70ad270 100644 --- a/ir/be/ia32/ia32_new_nodes.c +++ b/ir/be/ia32/ia32_new_nodes.c @@ -29,6 +29,7 @@ #include "firm_common_t.h" #include "irvrfy_t.h" #include "irprintf.h" +#include "iredges.h" #include "../bearch.h" @@ -423,24 +424,6 @@ static int ia32_dump_node(ir_node *n, FILE *F, dump_reason_t reason) { } fprintf(F, "\n"); - fprintf(F, "src_mode = "); - if (get_ia32_src_mode(n)) { - ir_fprintf(F, "%+F", get_ia32_src_mode(n)); - } - else { - fprintf(F, "n/a"); - } - fprintf(F, "\n"); - - fprintf(F, "tgt_mode = "); - if (get_ia32_tgt_mode(n)) { - ir_fprintf(F, "%+F", get_ia32_tgt_mode(n)); - } - else { - fprintf(F, "n/a"); - } - fprintf(F, "\n"); - #ifndef NDEBUG /* dump original ir node name */ fprintf(F, "orig node = "); @@ -570,13 +553,21 @@ char *get_ia32_am_offs(const ir_node *node) { } /** - * Gets the addressmode offset as long. + * Gets the addressmode offset as int. */ int get_ia32_am_offs_int(const ir_node *node) { ia32_attr_t *attr = get_ia32_attr(node); return attr->am_offs; } +/** + * Sets the addressmode offset from an int. + */ +void set_ia32_am_offs_int(ir_node *node, int offset) { + ia32_attr_t *attr = get_ia32_attr(node); + attr->am_offs = offset; +} + /** * Add an offset for addrmode. */ @@ -879,38 +870,6 @@ void set_ia32_res_mode(ir_node *node, ir_mode *mode) { attr->res_mode = mode; } -/** - * Gets the source mode of conversion. - */ -ir_mode *get_ia32_src_mode(const ir_node *node) { - ia32_attr_t *attr = get_ia32_attr(node); - return attr->src_mode; -} - -/** - * Sets the source mode of conversion. - */ -void set_ia32_src_mode(ir_node *node, ir_mode *mode) { - ia32_attr_t *attr = get_ia32_attr(node); - attr->src_mode = mode; -} - -/** - * Gets the target mode of conversion. - */ -ir_mode *get_ia32_tgt_mode(const ir_node *node) { - ia32_attr_t *attr = get_ia32_attr(node); - return attr->tgt_mode; -} - -/** - * Sets the target mode of conversion. - */ -void set_ia32_tgt_mode(ir_node *node, ir_mode *mode) { - ia32_attr_t *attr = get_ia32_attr(node); - attr->tgt_mode = mode; -} - /** * Gets the frame entity assigned to this node. */ @@ -1372,6 +1331,33 @@ void init_ia32_attributes(ir_node *node, arch_irn_flags_t flags, const ia32_regi memset((void *)attr->slots, 0, n_res * sizeof(attr->slots[0])); } +ir_node *get_ia32_result_proj(const ir_node *node) +{ + const ir_edge_t *edge; + + foreach_out_edge(node, edge) { + ir_node *proj = get_edge_src_irn(edge); + if(get_Proj_proj(proj) == 0) { + return proj; + } + } + return NULL; +} + +ir_mode *get_ia32_Conv_src_mode(const ir_node *node) +{ + if(get_ia32_op_type(node) == ia32_AddrModeS) { + return get_ia32_ls_mode(node); + } + + return get_irn_mode(get_irn_n(node, 2)); +} + +ir_mode *get_ia32_Conv_tgt_mode(const ir_node *node) +{ + return get_irn_mode(node); +} + /*************************************************************************************** * _ _ _ * | | | | | | @@ -1412,15 +1398,6 @@ int ia32_compare_immop_attr(ia32_attr_t *a, ia32_attr_t *b) { return !equ; } -/* compare converts */ -int ia32_compare_conv_attr(ia32_attr_t *a, ia32_attr_t *b) { - int equ = ! ia32_compare_immop_attr(a, b); - - equ = equ ? (a->src_mode == b->src_mode) && (a->tgt_mode == b->tgt_mode) : equ; - - return !equ; -} - /* copies the ia32 attributes */ static void ia32_copy_attr(const ir_node *old_node, ir_node *new_node) { ia32_attr_t *attr_old = get_ia32_attr(old_node); diff --git a/ir/be/ia32/ia32_new_nodes.h b/ir/be/ia32/ia32_new_nodes.h index 77456632f..59fb86acb 100644 --- a/ir/be/ia32/ia32_new_nodes.h +++ b/ir/be/ia32/ia32_new_nodes.h @@ -81,6 +81,11 @@ char *get_ia32_am_offs(const ir_node *node); */ int get_ia32_am_offs_int(const ir_node *node); +/** + * Sets the addressmode offset + */ +void set_ia32_am_offs_int(ir_node *node, int offset); + /** * Adds an offset for addrmode. */ @@ -253,26 +258,6 @@ ir_mode *get_ia32_res_mode(const ir_node *node); */ void set_ia32_res_mode(ir_node *node, ir_mode *mode); -/** - * Gets the source mode of conversion. - */ -ir_mode *get_ia32_src_mode(const ir_node *node); - -/** - * Sets the source mode of conversion. - */ -void set_ia32_src_mode(ir_node *node, ir_mode *mode); - -/** - * Gets the target mode of conversion. - */ -ir_mode *get_ia32_tgt_mode(const ir_node *node); - -/** - * Sets the target mode of conversion. - */ -void set_ia32_tgt_mode(ir_node *node, ir_mode *mode); - /** * Gets the frame entity assigned to this node; */ @@ -454,6 +439,22 @@ void set_ia32_Immop_attr(ir_node *node, ir_node *cnst); */ void copy_ia32_Immop_attr(ir_node *node, ir_node *src); +/** + * Returns the proj of the result value for nodes that have the usual + * (res, Mem) result tuple + */ +ir_node *get_ia32_result_proj(const ir_node *node); + +/** + * Returns the source mode for ia32 conv nodes + */ +ir_mode *get_ia32_Conv_src_mode(const ir_node *node); + +/** + * Returns the target mode for ia32 conv nodes + */ +ir_mode *get_ia32_Conv_tgt_mode(const ir_node *node); + /** * Copy the attributes from a Const to an ia32_Const */ diff --git a/ir/be/ia32/ia32_nodes_attr.h b/ir/be/ia32/ia32_nodes_attr.h index 6a9e0460b..4e748291a 100644 --- a/ir/be/ia32/ia32_nodes_attr.h +++ b/ir/be/ia32/ia32_nodes_attr.h @@ -116,8 +116,6 @@ typedef struct _ia32_attr_t { ir_mode *ls_mode; /**< the mode of the stored/loaded value */ ir_mode *res_mode; /**< the mode of the result */ - ir_mode *src_mode; /**< source mode for conversion */ - ir_mode *tgt_mode; /**< target mode for conversion */ ir_entity *frame_ent; /**< the frame entity attached to this node */ diff --git a/ir/be/ia32/ia32_optimize.c b/ir/be/ia32/ia32_optimize.c index 1c6d72011..8781ed9ed 100644 --- a/ir/be/ia32/ia32_optimize.c +++ b/ir/be/ia32/ia32_optimize.c @@ -38,10 +38,10 @@ #define AGGRESSIVE_AM typedef enum { - IA32_AM_CAND_NONE = 0, - IA32_AM_CAND_LEFT = 1, - IA32_AM_CAND_RIGHT = 2, - IA32_AM_CAND_BOTH = 3 + IA32_AM_CAND_NONE = 0, /**< no addressmode possible with irn inputs */ + IA32_AM_CAND_LEFT = 1, /**< addressmode possible with left input */ + IA32_AM_CAND_RIGHT = 2, /**< addressmode possible with right input */ + IA32_AM_CAND_BOTH = 3 /**< addressmode possible with both inputs */ } ia32_am_cand_t; typedef int is_op_func_t(const ir_node *n); @@ -566,7 +566,6 @@ static void ia32_create_Pushs(ir_node *irn, ia32_code_gen_t *cg) { } for( ; i >= 0; --i) { - const ir_edge_t *edge, *next; const arch_register_t *spreg; ir_node *push; ir_node *val, *mem; @@ -592,13 +591,8 @@ static void ia32_create_Pushs(ir_node *irn, ia32_code_gen_t *cg) { arch_set_irn_register(cg->arch_env, curr_sp, spreg); sched_add_before(irn, curr_sp); - // rewire memprojs of the store - foreach_out_edge_safe(store, edge, next) { - ir_node *succ = get_edge_src_irn(edge); - - assert(is_Proj(succ) && get_Proj_proj(succ) == pn_ia32_Store_M); - set_irn_n(succ, 0, push); - } + // rewire users + edges_reroute(store, push, irg); // we can remove the store now set_irn_n(store, 0, new_Bad()); @@ -717,11 +711,7 @@ static int ia32_get_irn_n_edges(const ir_node *irn) { * @return 1 if conditions are fulfilled, 0 otherwise */ static int pred_is_specific_node(const ir_node *pred, is_op_func_t *is_op_func) { - if (is_Proj(pred) && is_op_func(get_Proj_pred(pred))) { - return 1; - } - - return 0; + return is_op_func(pred); } /** @@ -810,7 +800,14 @@ static ia32_am_cand_t is_am_candidate(ia32_code_gen_t *cg, heights_t *h, const i return 0; left = get_irn_n(irn, 2); - right = get_irn_n(irn, 3); + if(get_irn_arity(irn) == 5) { + /* binary op */ + right = get_irn_n(irn, 3); + } else { + /* unary op */ + assert(get_irn_arity(irn) == 4); + right = left; + } in = left; @@ -875,13 +872,16 @@ static ia32_am_cand_t is_am_candidate(ia32_code_gen_t *cg, heights_t *h, const i /* check some special cases */ if (USE_SSE2(cg) && is_ia32_Conv_I2FP(irn)) { + const ir_mode *tgt_mode = get_ia32_Conv_tgt_mode(irn); /* SSE Conv I -> FP cvtsi2s(s|d) can only load 32 bit values */ - if (get_mode_size_bits(get_ia32_tgt_mode(irn)) != 32) + if (get_mode_size_bits(tgt_mode) != 32) cand = IA32_AM_CAND_NONE; } else if (is_ia32_Conv_I2I(irn)) { + const ir_mode *src_mode = get_ia32_Conv_src_mode(irn); + const ir_mode *tgt_mode = get_ia32_Conv_tgt_mode(irn); /* we cannot load an N bit value and implicitly convert it into an M bit value if N > M */ - if (get_mode_size_bits(get_ia32_src_mode(irn)) > get_mode_size_bits(get_ia32_tgt_mode(irn))) + if (get_mode_size_bits(src_mode) > get_mode_size_bits(tgt_mode)) cand = IA32_AM_CAND_NONE; } @@ -1189,7 +1189,6 @@ static ir_node *fold_addr(ia32_code_gen_t *cg, ir_node *irn, ir_node *noreg) { /* check for SHL 1,2,3 */ if (pred_is_specific_node(temp, is_ia32_Shl)) { - temp = get_Proj_pred(temp); shift = temp; if (get_ia32_Immop_tarval(temp)) { @@ -1370,7 +1369,6 @@ static ir_node *fold_addr(ia32_code_gen_t *cg, ir_node *irn, ir_node *noreg) { /* get the result Proj of the Add/Sub */ try_add_to_sched(irn, res); try_remove_from_sched(irn); - irn = ia32_get_res_proj(irn); assert(irn && "Couldn't find result proj"); @@ -1516,17 +1514,25 @@ static void optimize_lea(ir_node *irn, void *env) { static void optimize_am(ir_node *irn, void *env) { ia32_am_opt_env_t *am_opt_env = env; ia32_code_gen_t *cg = am_opt_env->cg; + ir_graph *irg = get_irn_irg(irn); heights_t *h = am_opt_env->h; ir_node *block, *left, *right; ir_node *store, *load, *mem_proj; - ir_node *succ, *addr_b, *addr_i; - int check_am_src = 0; + ir_node *addr_b, *addr_i; int need_exchange_on_fail = 0; + ia32_am_type_t am_support; + ia32_am_cand_t cand; + ia32_am_cand_t orig_cand; + int dest_possible; + int source_possible; DEBUG_ONLY(firm_dbg_module_t *mod = cg->mod;) - if (! is_ia32_irn(irn) || is_ia32_Ld(irn) || is_ia32_St(irn) || is_ia32_Store8Bit(irn)) + if (!is_ia32_irn(irn) || is_ia32_Ld(irn) || is_ia32_St(irn) || is_ia32_Store8Bit(irn)) + return; + if (is_ia32_Lea(irn)) return; + am_support = get_ia32_am_support(irn); block = get_nodes_block(irn); DBG((mod, LEVEL_1, "checking for AM\n")); @@ -1544,242 +1550,234 @@ static void optimize_am(ir_node *irn, void *env) { /* - the Load is only used by this op AND */ /* - the Load and Store are in the same block AND */ /* - nobody else uses the result of the op */ + if (get_ia32_am_support(irn) == ia32_am_None) + return; - if ((get_ia32_am_support(irn) != ia32_am_None) && ! is_ia32_Lea(irn)) { - ia32_am_cand_t cand = is_am_candidate(cg, h, block, irn); - ia32_am_cand_t orig_cand = cand; - - /* cand == 1: load is left; cand == 2: load is right; */ - - if (cand == IA32_AM_CAND_NONE) - return; + cand = is_am_candidate(cg, h, block, irn); + if (cand == IA32_AM_CAND_NONE) + return; - DBG((mod, LEVEL_1, "\tfound address mode candidate %+F ... ", irn)); + orig_cand = cand; + DBG((mod, LEVEL_1, "\tfound address mode candidate %+F ... ", irn)); - left = get_irn_n(irn, 2); - if (get_irn_arity(irn) == 4) { - /* it's an "unary" operation */ - right = left; - cand = IA32_AM_CAND_BOTH; - } - else { - right = get_irn_n(irn, 3); - } + left = get_irn_n(irn, 2); + if (get_irn_arity(irn) == 4) { + /* it's an "unary" operation */ + right = left; + assert(cand == IA32_AM_CAND_BOTH); + } else { + right = get_irn_n(irn, 3); + } - /* normalize commutative ops */ - if (node_is_ia32_comm(irn) && (cand == IA32_AM_CAND_RIGHT)) { + dest_possible = am_support & ia32_am_Dest ? 1 : 0; + source_possible = am_support & ia32_am_Source ? 1 : 0; - /* Assure that left operand is always a Load if there is one */ - /* because non-commutative ops can only use Dest AM if the left */ - /* operand is a load, so we only need to check left operand. */ + if (dest_possible) { + addr_b = NULL; + addr_i = NULL; + store = NULL; - exchange_left_right(irn, &left, &right, 3, 2); - need_exchange_on_fail = 1; + /* we should only have 1 user which is a store */ + if (ia32_get_irn_n_edges(irn) == 1) { + ir_node *succ = get_edge_src_irn(get_irn_out_edge_first(irn)); - /* now: load is right */ - cand = IA32_AM_CAND_LEFT; + if (is_ia32_xStore(succ) || is_ia32_Store(succ)) { + store = succ; + addr_b = get_irn_n(store, 0); + addr_i = get_irn_n(store, 1); + } } - /* check for Store -> op -> Load */ + if (store == NULL) { + dest_possible = 0; + } + } - /* Store -> op -> Load optimization is only possible if supported by op */ - /* and if right operand is a Load */ - if ((get_ia32_am_support(irn) & ia32_am_Dest) && (cand & IA32_AM_CAND_LEFT)) - { - /* An address mode capable op always has a result Proj. */ - /* If this Proj is used by more than one other node, we don't need to */ - /* check further, otherwise we check for Store and remember the address, */ - /* the Store points to. */ - - succ = ia32_get_res_proj(irn); - assert(succ && "Couldn't find result proj"); - - addr_b = NULL; - addr_i = NULL; - store = NULL; - - /* now check for users and Store */ - if (ia32_get_irn_n_edges(succ) == 1) { - succ = get_edge_src_irn(get_irn_out_edge_first(succ)); - - if (is_ia32_xStore(succ) || is_ia32_Store(succ)) { - store = succ; - addr_b = get_irn_n(store, 0); - addr_i = get_irn_n(store, 1); - } + if (dest_possible) { + /* normalize nodes, we need the interesting load on the left side */ + if (cand & IA32_AM_CAND_RIGHT) { + load = get_Proj_pred(right); + if (load_store_addr_is_equal(load, store, addr_b, addr_i)) { + exchange_left_right(irn, &left, &right, 3, 2); + need_exchange_on_fail ^= 1; + if (cand == IA32_AM_CAND_RIGHT) + cand = IA32_AM_CAND_LEFT; } + } + } - if (store) { - /* we found a Store as single user: Now check for Load */ - - /* skip the Proj for easier access */ - load = is_Proj(right) ? (is_ia32_Load(get_Proj_pred(right)) ? get_Proj_pred(right) : NULL) : NULL; - - /* Extra check for commutative ops with two Loads */ - /* -> put the interesting Load left */ - if (load && node_is_ia32_comm(irn) && (cand == IA32_AM_CAND_BOTH)) { - if (load_store_addr_is_equal(load, store, addr_b, addr_i)) { - /* We exchange left and right, so it's easier to kill */ - /* the correct Load later and to handle unary operations. */ - exchange_left_right(irn, &left, &right, 3, 2); - need_exchange_on_fail ^= 1; - } - } + if (dest_possible) { + if(cand & IA32_AM_CAND_LEFT && is_Proj(left)) { + load = get_Proj_pred(left); - /* we have to be the only user of the load */ - if(get_irn_n_edges(left) > 1) { - store = NULL; - } - } - if (store) { - /* skip the Proj for easier access */ - load = get_Proj_pred(left); - - /* Compare Load and Store address */ - if (load_store_addr_is_equal(load, store, addr_b, addr_i)) { - /* Left Load is from same address, so we can */ - /* disconnect the Load and Store here */ - - /* set new base, index and attributes */ - set_irn_n(irn, 0, addr_b); - set_irn_n(irn, 1, addr_i); - add_ia32_am_offs(irn, get_ia32_am_offs(load)); - set_ia32_am_scale(irn, get_ia32_am_scale(load)); - set_ia32_am_flavour(irn, get_ia32_am_flavour(load)); - set_ia32_op_type(irn, ia32_AddrModeD); - set_ia32_frame_ent(irn, get_ia32_frame_ent(load)); - set_ia32_ls_mode(irn, get_ia32_ls_mode(load)); - - set_ia32_am_sc(irn, get_ia32_am_sc(load)); - if (is_ia32_am_sc_sign(load)) - set_ia32_am_sc_sign(irn); - - if (is_ia32_use_frame(load)) - set_ia32_use_frame(irn); - - /* connect to Load memory and disconnect Load */ - if (get_irn_arity(irn) == 5) { - /* binary AMop */ - set_irn_n(irn, 4, get_irn_n(load, 2)); - set_irn_n(irn, 2, ia32_get_admissible_noreg(cg, irn, 2)); - } - else { - /* unary AMop */ - set_irn_n(irn, 3, get_irn_n(load, 2)); - set_irn_n(irn, 2, ia32_get_admissible_noreg(cg, irn, 2)); - } - - /* connect the memory Proj of the Store to the op */ - mem_proj = ia32_get_proj_for_mode(store, mode_M); - set_Proj_pred(mem_proj, irn); - set_Proj_proj(mem_proj, 1); - - /* clear remat flag */ - set_ia32_flags(irn, get_ia32_flags(irn) & ~arch_irn_flags_rematerializable); - - try_remove_from_sched(load); - try_remove_from_sched(store); - DBG_OPT_AM_D(load, store, irn); - - DB((mod, LEVEL_1, "merged with %+F and %+F into dest AM\n", load, store)); - - need_exchange_on_fail = 0; - } - } /* if (store) */ - else if (get_ia32_am_support(irn) & ia32_am_Source) { - /* There was no store, check if we still can optimize for source address mode */ - check_am_src = 1; +#ifndef AGGRESSIVE_AM + /* we have to be the only user of the load */ + if (get_irn_n_edges(left) > 1) { + dest_possible = 0; } - } /* if (support AM Dest) */ - else if (get_ia32_am_support(irn) & ia32_am_Source) { - /* op doesn't support am AM Dest -> check for AM Source */ - check_am_src = 1; +#endif + } else { + dest_possible = 0; } + } - /* was exchanged but optimize failed: exchange back */ - if (need_exchange_on_fail) { - exchange_left_right(irn, &left, &right, 3, 2); - cand = orig_cand; + if (dest_possible) { + /* the store has to use the loads memory or the same memory + * as the load */ + ir_node *loadmem = get_irn_n(load, 2); + ir_node *storemem = get_irn_n(store, 3); + assert(get_irn_mode(loadmem) == mode_M); + assert(get_irn_mode(storemem) == mode_M); + if(storemem != loadmem || !is_Proj(storemem) + || get_Proj_pred(storemem) != load) { + dest_possible = 0; } + } - need_exchange_on_fail = 0; + if (dest_possible) { + /* Compare Load and Store address */ + if (!load_store_addr_is_equal(load, store, addr_b, addr_i)) + dest_possible = 0; + } - /* normalize commutative ops */ - if (check_am_src && node_is_ia32_comm(irn) && (cand == IA32_AM_CAND_LEFT)) { + if (dest_possible) { + /* all conditions fullfilled, do the transformation */ + assert(cand & IA32_AM_CAND_LEFT); + + /* set new base, index and attributes */ + set_irn_n(irn, 0, addr_b); + set_irn_n(irn, 1, addr_i); + add_ia32_am_offs(irn, get_ia32_am_offs(load)); + set_ia32_am_scale(irn, get_ia32_am_scale(load)); + set_ia32_am_flavour(irn, get_ia32_am_flavour(load)); + set_ia32_op_type(irn, ia32_AddrModeD); + set_ia32_frame_ent(irn, get_ia32_frame_ent(load)); + set_ia32_ls_mode(irn, get_ia32_ls_mode(load)); + + set_ia32_am_sc(irn, get_ia32_am_sc(load)); + if (is_ia32_am_sc_sign(load)) + set_ia32_am_sc_sign(irn); + + if (is_ia32_use_frame(load)) + set_ia32_use_frame(irn); + + /* connect to Load memory and disconnect Load */ + if (get_irn_arity(irn) == 5) { + /* binary AMop */ + set_irn_n(irn, 4, get_irn_n(load, 2)); + set_irn_n(irn, 2, ia32_get_admissible_noreg(cg, irn, 2)); + } else { + /* unary AMop */ + set_irn_n(irn, 3, get_irn_n(load, 2)); + set_irn_n(irn, 2, ia32_get_admissible_noreg(cg, irn, 2)); + } - /* Assure that right operand is always a Load if there is one */ - /* because non-commutative ops can only use Source AM if the */ - /* right operand is a Load, so we only need to check the right */ - /* operand afterwards. */ + set_irn_mode(irn, mode_M); - exchange_left_right(irn, &left, &right, 3, 2); - need_exchange_on_fail = 1; + /* connect the memory Proj of the Store to the op */ + mem_proj = ia32_get_proj_for_mode(store, mode_M); + edges_reroute(mem_proj, irn, irg); - /* now: load is left */ - cand = IA32_AM_CAND_RIGHT; - } + /* clear remat flag */ + set_ia32_flags(irn, get_ia32_flags(irn) & ~arch_irn_flags_rematerializable); - /* optimize op -> Load iff Load is only used by this op */ - /* and right operand is a Load which only used by this irn */ - if (check_am_src && - (cand & IA32_AM_CAND_RIGHT) && - (ia32_get_irn_n_edges(right) == 1)) - { - ir_node *load = get_Proj_pred(right); - - addr_b = get_irn_n(load, 0); - addr_i = get_irn_n(load, 1); - - /* set new base, index and attributes */ - set_irn_n(irn, 0, addr_b); - set_irn_n(irn, 1, addr_i); - add_ia32_am_offs(irn, get_ia32_am_offs(load)); - set_ia32_am_scale(irn, get_ia32_am_scale(load)); - set_ia32_am_flavour(irn, get_ia32_am_flavour(load)); - set_ia32_op_type(irn, ia32_AddrModeS); - set_ia32_frame_ent(irn, get_ia32_frame_ent(load)); - set_ia32_ls_mode(irn, get_ia32_ls_mode(load)); - - set_ia32_am_sc(irn, get_ia32_am_sc(load)); - if (is_ia32_am_sc_sign(load)) - set_ia32_am_sc_sign(irn); - - /* clear remat flag */ - set_ia32_flags(irn, get_ia32_flags(irn) & ~arch_irn_flags_rematerializable); - - if (is_ia32_use_frame(load)) - set_ia32_use_frame(irn); - - /* connect to Load memory and disconnect Load */ - if (get_irn_arity(irn) == 5) { - /* binary AMop */ - set_irn_n(irn, 4, get_irn_n(load, 2)); - set_irn_n(irn, 3, ia32_get_admissible_noreg(cg, irn, 3)); + try_remove_from_sched(load); + try_remove_from_sched(store); + DBG_OPT_AM_D(load, store, irn); + + DB((mod, LEVEL_1, "merged with %+F and %+F into dest AM\n", load, store)); + need_exchange_on_fail = 0; + source_possible = 0; + } + + if (source_possible) { + /* normalize ops, we need the load on the right */ + if(cand == IA32_AM_CAND_LEFT) { + if(node_is_ia32_comm(irn)) { + exchange_left_right(irn, &left, &right, 3, 2); + need_exchange_on_fail ^= 1; + cand = IA32_AM_CAND_RIGHT; } else { - assert(get_irn_arity(irn) == 4); - /* unary AMop */ - set_irn_n(irn, 3, get_irn_n(load, 2)); - set_irn_n(irn, 2, ia32_get_admissible_noreg(cg, irn, 2)); + source_possible = 0; } + } + } - DBG_OPT_AM_S(load, irn); + if (source_possible) { + /* all conditions fullfilled, do transform */ + assert(cand & IA32_AM_CAND_RIGHT); + load = get_Proj_pred(right); - /* If Load has a memory Proj, connect it to the op */ - mem_proj = ia32_get_proj_for_mode(load, mode_M); - if (mem_proj) { - set_Proj_pred(mem_proj, irn); - set_Proj_proj(mem_proj, 1); - } + if(get_irn_n_edges(load) > 1) { + source_possible = 0; + } + } - try_remove_from_sched(load); + if (source_possible) { + addr_b = get_irn_n(load, 0); + addr_i = get_irn_n(load, 1); + + /* set new base, index and attributes */ + set_irn_n(irn, 0, addr_b); + set_irn_n(irn, 1, addr_i); + add_ia32_am_offs(irn, get_ia32_am_offs(load)); + set_ia32_am_scale(irn, get_ia32_am_scale(load)); + set_ia32_am_flavour(irn, get_ia32_am_flavour(load)); + set_ia32_op_type(irn, ia32_AddrModeS); + set_ia32_frame_ent(irn, get_ia32_frame_ent(load)); + set_ia32_ls_mode(irn, get_ia32_ls_mode(load)); + + set_ia32_am_sc(irn, get_ia32_am_sc(load)); + if (is_ia32_am_sc_sign(load)) + set_ia32_am_sc_sign(irn); + + /* clear remat flag */ + set_ia32_flags(irn, get_ia32_flags(irn) & ~arch_irn_flags_rematerializable); + + if (is_ia32_use_frame(load)) + set_ia32_use_frame(irn); + + /* connect to Load memory and disconnect Load */ + if (get_irn_arity(irn) == 5) { + /* binary AMop */ + set_irn_n(irn, 3, ia32_get_admissible_noreg(cg, irn, 3)); + set_irn_n(irn, 4, get_irn_n(load, 2)); + } else { + assert(get_irn_arity(irn) == 4); + /* unary AMop */ + set_irn_n(irn, 2, ia32_get_admissible_noreg(cg, irn, 2)); + set_irn_n(irn, 3, get_irn_n(load, 2)); + } + + DBG_OPT_AM_S(load, irn); + + /* If Load has a memory Proj, connect it to the op */ + mem_proj = ia32_get_proj_for_mode(load, mode_M); + if (mem_proj != NULL) { + ir_node *res_proj; + ir_mode *mode = get_irn_mode(irn); + + res_proj = new_rd_Proj(get_irn_dbg_info(irn), irg, + get_nodes_block(irn), new_Unknown(mode_T), mode, 0); + set_irn_mode(irn, mode_T); + edges_reroute(irn, res_proj, irg); + set_Proj_pred(res_proj, irn); - DB((mod, LEVEL_1, "merged with %+F into source AM\n", load)); + set_Proj_pred(mem_proj, irn); + set_Proj_proj(mem_proj, 1); } - else { - /* was exchanged but optimize failed: exchange back */ - if (need_exchange_on_fail) - exchange_left_right(irn, &left, &right, 3, 2); + + if(get_irn_n_edges(load) == 0) { + try_remove_from_sched(load); } + need_exchange_on_fail = 0; + + DB((mod, LEVEL_1, "merged with %+F into source AM\n", load)); + } + + /* was exchanged but optimize failed: exchange back */ + if (need_exchange_on_fail) { + exchange_left_right(irn, &left, &right, 3, 2); } } diff --git a/ir/be/ia32/ia32_spec.pl b/ir/be/ia32/ia32_spec.pl index 7b3c2fa7c..dd3542d64 100644 --- a/ir/be/ia32/ia32_spec.pl +++ b/ir/be/ia32/ia32_spec.pl @@ -208,6 +208,8 @@ $comment_string = "/*"; # |_| # #--------------------------------------------------# +$default_cmp_attr = "return ia32_compare_immop_attr(attr_a, attr_b);"; + %operands = ( ); @@ -237,19 +239,15 @@ $comment_string = "/*"; "Add" => { "irn_flags" => "R", "comment" => "construct Add: Add(a, b) = Add(b, a) = a + b", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "in_r3" ] }, "emit" => '. add %ia32_emit_binop /* Add(%A3, %A4) -> %D1 */', - "outs" => [ "res", "M" ], "units" => [ "ALU", "MEM" ], }, "AddC" => { "comment" => "construct Add with Carry: AddC(a, b) = Add(b, a) = a + b + carry", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "in_r3" ] }, "emit" => '. adc %ia32_emit_binop /* AddC(%A3, %A4) -> %D1 */', - "outs" => [ "res", "M" ], "units" => [ "ALU", "MEM" ], }, @@ -271,14 +269,14 @@ $comment_string = "/*"; "l_Add" => { "op_flags" => "C", "irn_flags" => "R", - "cmp_attr" => " return 1;\n", + "cmp_attr" => "return 1;", "comment" => "construct lowered Add: Add(a, b) = Add(b, a) = a + b", "arity" => 2, }, "l_AddC" => { "op_flags" => "C", - "cmp_attr" => " return 1;\n", + "cmp_attr" => "return 1;", "comment" => "construct lowered Add with Carry: AddC(a, b) = Add(b, a) = a + b + carry", "arity" => 2, }, @@ -287,7 +285,6 @@ $comment_string = "/*"; # we should not rematrialize this node. It produces 2 results and has # very strict constrains "comment" => "construct MulS: MulS(a, b) = MulS(b, a) = a * b", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "eax", "gp", "none" ], "out" => [ "eax", "edx" ] }, "emit" => '. mul %ia32_emit_unop /* Mul(%A1, %A2) -> %D1 */', "outs" => [ "EAX", "EDX", "M" ], @@ -299,7 +296,7 @@ $comment_string = "/*"; # we should not rematrialize this node. It produces 2 results and has # very strict constrains "op_flags" => "C", - "cmp_attr" => " return 1;\n", + "cmp_attr" => "return 1;", "comment" => "construct lowered MulS: MulS(a, b) = MulS(b, a) = a * b", "outs" => [ "EAX", "EDX", "M" ], "arity" => 2 @@ -308,17 +305,15 @@ $comment_string = "/*"; "Mul" => { "irn_flags" => "R", "comment" => "construct Mul: Mul(a, b) = Mul(b, a) = a * b", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "in_r3" ] }, "emit" => '. imul %ia32_emit_binop /* Mul(%A1, %A2) -> %D1 */', - "outs" => [ "res", "M" ], "latency" => 5, "units" => [ "MUL" ], }, "l_Mul" => { "op_flags" => "C", - "cmp_attr" => " return 1;\n", + "cmp_attr" => "return 1;", "comment" => "construct lowered Mul: Mul(a, b) = Mul(b, a) = a * b", "arity" => 2 }, @@ -328,7 +323,6 @@ $comment_string = "/*"; # we should not rematrialize this node. It produces 2 results and has # very strict constrains "comment" => "construct Mul: Mul(a, b) = Mul(b, a) = a * b", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "eax", "gp", "none" ], "out" => [ "eax", "edx" ] }, "emit" => '. imul %ia32_emit_unop /* Mulh(%A1, %A2) -> %D1 */', "outs" => [ "EAX", "EDX", "M" ], @@ -339,36 +333,30 @@ $comment_string = "/*"; "And" => { "irn_flags" => "R", "comment" => "construct And: And(a, b) = And(b, a) = a AND b", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "in_r3" ] }, "emit" => '. and %ia32_emit_binop /* And(%A1, %A2) -> %D1 */', - "outs" => [ "res", "M" ], "units" => [ "ALU" ], }, "Or" => { "irn_flags" => "R", "comment" => "construct Or: Or(a, b) = Or(b, a) = a OR b", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "in_r3" ] }, "emit" => '. or %ia32_emit_binop /* Or(%A1, %A2) -> %D1 */', - "outs" => [ "res", "M" ], "units" => [ "ALU" ], }, "Eor" => { "irn_flags" => "R", "comment" => "construct Eor: Eor(a, b) = Eor(b, a) = a EOR b", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "in_r3" ] }, "emit" => '. xor %ia32_emit_binop /* Xor(%A1, %A2) -> %D1 */', - "outs" => [ "res", "M" ], "units" => [ "ALU" ], }, "l_Eor" => { "op_flags" => "C", - "cmp_attr" => " return 1;\n", + "cmp_attr" => "return 1;", "comment" => "construct lowered Eor: Eor(a, b) = Eor(b, a) = a EOR b", "arity" => 2 }, @@ -412,19 +400,15 @@ $comment_string = "/*"; "Sub" => { "irn_flags" => "R", "comment" => "construct Sub: Sub(a, b) = a - b", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "in_r3" ] }, "emit" => '. sub %ia32_emit_binop /* Sub(%A3, %A4) -> %D1 */', - "outs" => [ "res", "M" ], "units" => [ "ALU" ], }, "SubC" => { "comment" => "construct Sub with Carry: SubC(a, b) = a - b - carry", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "in_r3 !in_r4" ] }, "emit" => '. sbb %ia32_emit_binop /* SubC(%A3, %A4) -> %D1 */', - "outs" => [ "res", "M" ], "units" => [ "ALU" ], }, @@ -445,13 +429,13 @@ $comment_string = "/*"; "l_Sub" => { "irn_flags" => "R", - "cmp_attr" => " return 1;\n", + "cmp_attr" => "return 1;", "comment" => "construct lowered Sub: Sub(a, b) = a - b", "arity" => 2, }, "l_SubC" => { - "cmp_attr" => " return 1;\n", + "cmp_attr" => "return 1;", "comment" => "construct lowered Sub with Carry: SubC(a, b) = a - b - carry", "arity" => 2, }, @@ -479,15 +463,13 @@ $comment_string = "/*"; "Shl" => { "irn_flags" => "R", "comment" => "construct Shl: Shl(a, b) = a << b", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "gp", "ecx", "none" ], "out" => [ "in_r3 !in_r4" ] }, "emit" => '. shl %ia32_emit_binop /* Shl(%A1, %A2) -> %D1 */', - "outs" => [ "res", "M" ], "units" => [ "ALU1", "SSE1" ], }, "l_Shl" => { - "cmp_attr" => " return 1;\n", + "cmp_attr" => "return 1;", "comment" => "construct lowered Shl: Shl(a, b) = a << b", "arity" => 2 }, @@ -495,7 +477,6 @@ $comment_string = "/*"; "ShlD" => { "irn_flags" => "R", "comment" => "construct ShlD: ShlD(a, b, c) = a, b << count (shift left count bits from b into a)", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", # Out requirements is: different from all in # This is because, out must be different from LowPart and ShiftCount. # We could say "!ecx !in_r4" but it can occur, that all values live through @@ -524,13 +505,12 @@ else { } } ', - "outs" => [ "res", "M" ], "latency" => 6, "units" => [ "ALU1", "SSE1" ], }, "l_ShlD" => { - "cmp_attr" => " return 1;\n", + "cmp_attr" => "return 1;", "comment" => "construct lowered ShlD: ShlD(a, b, c) = a, b << count (shift left count bits from b into a)", "arity" => 3 }, @@ -538,15 +518,13 @@ else { "Shr" => { "irn_flags" => "R", "comment" => "construct Shr: Shr(a, b) = a >> b", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "gp", "ecx", "none" ], "out" => [ "in_r3 !in_r4" ] }, "emit" => '. shr %ia32_emit_binop /* Shr(%A1, %A2) -> %D1 */', - "outs" => [ "res", "M" ], "units" => [ "ALU1", "SSE1" ], }, "l_Shr" => { - "cmp_attr" => " return 1;\n", + "cmp_attr" => "return 1;", "comment" => "construct lowered Shr: Shr(a, b) = a << b", "arity" => 2 }, @@ -554,7 +532,6 @@ else { "ShrD" => { "irn_flags" => "R", "comment" => "construct ShrD: ShrD(a, b, c) = a, b >> count (shift rigth count bits from a into b)", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", # Out requirements is: different from all in # This is because, out must be different from LowPart and ShiftCount. # We could say "!ecx !in_r4" but it can occur, that all values live through @@ -583,13 +560,12 @@ else { } } ', - "outs" => [ "res", "M" ], "latency" => 6, "units" => [ "ALU1", "SSE1" ], }, "l_ShrD" => { - "cmp_attr" => " return 1;\n", + "cmp_attr" => "return 1;", "comment" => "construct lowered ShrD: ShrD(a, b, c) = a, b >> count (shift rigth count bits from a into b)", "arity" => 3 }, @@ -597,15 +573,13 @@ else { "Shrs" => { "irn_flags" => "R", "comment" => "construct Shrs: Shrs(a, b) = a >> b", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "gp", "ecx", "none" ], "out" => [ "in_r3 !in_r4" ] }, "emit" => '. sar %ia32_emit_binop /* Shrs(%A1, %A2) -> %D1 */', - "outs" => [ "res", "M" ], "units" => [ "ALU1", "SSE1" ], }, "l_Shrs" => { - "cmp_attr" => " return 1;\n", + "cmp_attr" => "return 1;", "comment" => "construct lowered Shrs: Shrs(a, b) = a << b", "arity" => 2 }, @@ -613,20 +587,16 @@ else { "RotR" => { "irn_flags" => "R", "comment" => "construct RotR: RotR(a, b) = a ROTR b", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "gp", "ecx", "none" ], "out" => [ "in_r3 !in_r4" ] }, "emit" => '. ror %ia32_emit_binop /* RotR(%A1, %A2) -> %D1 */', - "outs" => [ "res", "M" ], "units" => [ "ALU1", "SSE1" ], }, "RotL" => { "irn_flags" => "R", "comment" => "construct RotL: RotL(a, b) = a ROTL b", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "gp", "ecx", "none" ], "out" => [ "in_r3 !in_r4" ] }, "emit" => '. rol %ia32_emit_binop /* RotL(%A1, %A2) -> %D1 */', - "outs" => [ "res", "M" ], "units" => [ "ALU1", "SSE1" ], }, @@ -635,10 +605,8 @@ else { "Minus" => { "irn_flags" => "R", "comment" => "construct Minus: Minus(a) = -a", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "gp", "none" ], "out" => [ "in_r3" ] }, "emit" => '. neg %ia32_emit_unop /* Neg(%A1) -> %D1, (%A1) */', - "outs" => [ "res", "M" ], "units" => [ "ALU" ], }, @@ -659,7 +627,7 @@ else { "l_Minus" => { - "cmp_attr" => " return 1;\n", + "cmp_attr" => "return 1;", "comment" => "construct lowered Minus: Minus(a) = -a", "arity" => 1, }, @@ -667,30 +635,24 @@ else { "Inc" => { "irn_flags" => "R", "comment" => "construct Increment: Inc(a) = a++", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "gp", "none" ], "out" => [ "in_r3" ] }, "emit" => '. inc %ia32_emit_unop /* Inc(%S1) -> %D1, (%A1) */', - "outs" => [ "res", "M" ], "units" => [ "ALU" ], }, "Dec" => { "irn_flags" => "R", "comment" => "construct Decrement: Dec(a) = a--", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "gp", "none" ], "out" => [ "in_r3" ] }, "emit" => '. dec %ia32_emit_unop /* Dec(%S1) -> %D1, (%A1) */', - "outs" => [ "res", "M" ], "units" => [ "ALU" ], }, "Not" => { "irn_flags" => "R", "comment" => "construct Not: Not(a) = !a", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "gp", "none" ], "out" => [ "in_r3" ] }, "emit" => '. not %ia32_emit_unop /* Not(%S1) -> %D1, (%A1) */', - "outs" => [ "res", "M" ], "units" => [ "ALU" ], }, @@ -699,7 +661,6 @@ else { "CondJmp" => { "op_flags" => "L|X|Y", "comment" => "construct conditional jump: CMP A, B && JMPxx LABEL", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "gp", "gp", "none" ] }, "outs" => [ "false", "true" ], "latency" => 3, @@ -710,7 +671,6 @@ else { "op_flags" => "L|X|Y", "comment" => "construct conditional jump: TEST A, B && JMPxx LABEL", "reg_req" => { "in" => [ "gp", "gp" ] }, - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "outs" => [ "false", "true" ], "latency" => 3, "units" => [ "BRANCH" ], @@ -719,7 +679,6 @@ else { "CJmpAM" => { "op_flags" => "L|X|Y", "comment" => "construct conditional jump without CMP (replaces CondJmp): JMPxx LABEL", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "none", "none" ] }, "outs" => [ "false", "true" ], "units" => [ "BRANCH" ], @@ -728,7 +687,6 @@ else { "CJmp" => { "op_flags" => "L|X|Y", "comment" => "construct conditional jump without CMP (replaces TestJmp): JMPxx LABEL", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp" ] }, "units" => [ "BRANCH" ], }, @@ -736,7 +694,6 @@ else { "SwitchJmp" => { "op_flags" => "L|X|Y", "comment" => "construct switch", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp" ], "out" => [ "none" ] }, "latency" => 3, "units" => [ "BRANCH" ], @@ -746,7 +703,6 @@ else { "op_flags" => "c", "irn_flags" => "R", "comment" => "represents an integer constant", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "out" => [ "gp" ] }, "units" => [ "ALU" ], }, @@ -767,7 +723,6 @@ else { "op_flags" => "L|F", "state" => "exc_pinned", "comment" => "construct Load: Load(ptr, mem) = LD ptr -> reg", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "none" ], "out" => [ "gp" ] }, "latency" => 3, "emit" => @@ -784,7 +739,7 @@ else { "l_Load" => { "op_flags" => "L|F", - "cmp_attr" => " return 1;\n", + "cmp_attr" => "return 1;", "comment" => "construct lowered Load: Load(ptr, mem) = LD ptr -> reg", "outs" => [ "res", "M" ], "arity" => 2, @@ -792,41 +747,38 @@ else { "l_Store" => { "op_flags" => "L|F", - "cmp_attr" => " return 1;\n", + "cmp_attr" => "return 1;", "state" => "exc_pinned", "comment" => "construct lowered Store: Store(ptr, val, mem) = ST ptr,val", "arity" => 3, - "outs" => [ "M" ], + "mode" => "mode_M", }, "Store" => { "op_flags" => "L|F", "state" => "exc_pinned", "comment" => "construct Store: Store(ptr, val, mem) = ST ptr,val", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "gp", "none" ] }, "emit" => '. mov %ia32_emit_binop /* Store(%A3) -> (%A1) */', - "outs" => [ "M" ], "latency" => 3, "units" => [ "MEM" ], + "mode" => "mode_M", }, "Store8Bit" => { "op_flags" => "L|F", "state" => "exc_pinned", "comment" => "construct 8Bit Store: Store(ptr, val, mem) = ST ptr,val", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "eax ebx ecx edx", "none" ] }, "emit" => '. mov %ia32_emit_binop /* Store(%A3) -> (%A1) */', - "outs" => [ "M" ], "latency" => 3, "units" => [ "MEM" ], + "mode" => "mode_M", }, "Lea" => { "irn_flags" => "R", "comment" => "construct Lea: Lea(a,b) = lea [a+b*const+offs] | res = a + b * const + offs with const = 0,1,2,4,8", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp" ], "out" => [ "in_r1" ] }, "emit" => '. lea %D1, %ia32_emit_am /* LEA(%A1, %A2) */', "latency" => 2, @@ -909,10 +861,8 @@ else { "xAdd" => { "irn_flags" => "R", "comment" => "construct SSE Add: Add(a, b) = Add(b, a) = a + b", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "xmm", "xmm", "none" ], "out" => [ "in_r3" ] }, "emit" => '. adds%M %ia32_emit_binop /* SSE Add(%A3, %A4) -> %D1 */', - "outs" => [ "res", "M" ], "latency" => 4, "units" => [ "SSE" ], }, @@ -920,10 +870,8 @@ else { "xMul" => { "irn_flags" => "R", "comment" => "construct SSE Mul: Mul(a, b) = Mul(b, a) = a * b", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "xmm", "xmm", "none" ], "out" => [ "in_r3" ] }, "emit" => '. muls%M %ia32_emit_binop /* SSE Mul(%A3, %A4) -> %D1 */', - "outs" => [ "res", "M" ], "latency" => 4, "units" => [ "SSE" ], }, @@ -931,10 +879,8 @@ else { "xMax" => { "irn_flags" => "R", "comment" => "construct SSE Max: Max(a, b) = Max(b, a) = a > b ? a : b", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "xmm", "xmm", "none" ], "out" => [ "in_r3" ] }, "emit" => '. maxs%M %ia32_emit_binop /* SSE Max(%A3, %A4) -> %D1 */', - "outs" => [ "res", "M" ], "latency" => 2, "units" => [ "SSE" ], }, @@ -942,10 +888,8 @@ else { "xMin" => { "irn_flags" => "R", "comment" => "construct SSE Min: Min(a, b) = Min(b, a) = a < b ? a : b", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "xmm", "xmm", "none" ], "out" => [ "in_r3" ] }, "emit" => '. mins%M %ia32_emit_binop /* SSE Min(%A3, %A4) -> %D1 */', - "outs" => [ "res", "M" ], "latency" => 2, "units" => [ "SSE" ], }, @@ -953,10 +897,8 @@ else { "xAnd" => { "irn_flags" => "R", "comment" => "construct SSE And: And(a, b) = a AND b", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "xmm", "xmm", "none" ], "out" => [ "in_r3" ] }, "emit" => '. andp%M %ia32_emit_binop /* SSE And(%A3, %A4) -> %D1 */', - "outs" => [ "res", "M" ], "latency" => 3, "units" => [ "SSE" ], }, @@ -964,20 +906,16 @@ else { "xOr" => { "irn_flags" => "R", "comment" => "construct SSE Or: Or(a, b) = a OR b", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "xmm", "xmm", "none" ], "out" => [ "in_r3" ] }, "emit" => '. orp%M %ia32_emit_binop /* SSE Or(%A3, %A4) -> %D1 */', - "outs" => [ "res", "M" ], "units" => [ "SSE" ], }, "xEor" => { "irn_flags" => "R", "comment" => "construct SSE Eor: Eor(a, b) = a XOR b", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "xmm", "xmm", "none" ], "out" => [ "in_r3" ] }, "emit" => '. xorp%M %ia32_emit_binop /* SSE Xor(%A3, %A4) -> %D1 */', - "outs" => [ "res", "M" ], "latency" => 3, "units" => [ "SSE" ], }, @@ -987,10 +925,8 @@ else { "xAndNot" => { "irn_flags" => "R", "comment" => "construct SSE AndNot: AndNot(a, b) = a AND NOT b", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "xmm", "xmm", "none" ], "out" => [ "in_r3 !in_r4" ] }, "emit" => '. andnp%M %ia32_emit_binop /* SSE AndNot(%A3, %A4) -> %D1 */', - "outs" => [ "res", "M" ], "latency" => 3, "units" => [ "SSE" ], }, @@ -998,10 +934,8 @@ else { "xSub" => { "irn_flags" => "R", "comment" => "construct SSE Sub: Sub(a, b) = a - b", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "xmm", "xmm", "none" ], "out" => [ "in_r3" ] }, "emit" => '. subs%M %ia32_emit_binop /* SSE Sub(%A1, %A2) -> %D1 */', - "outs" => [ "res", "M" ], "latency" => 4, "units" => [ "SSE" ], }, @@ -1009,10 +943,9 @@ else { "xDiv" => { "irn_flags" => "R", "comment" => "construct SSE Div: Div(a, b) = a / b", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "xmm", "xmm", "none" ], "out" => [ "in_r3 !in_r4" ] }, - "emit" => '. divs%M %ia32_emit_binop /* SSE Div(%A1, %A2) -> %D1 */', "outs" => [ "res", "M" ], + "emit" => '. divs%M %ia32_emit_binop /* SSE Div(%A1, %A2) -> %D1 */', "latency" => 16, "units" => [ "SSE" ], }, @@ -1023,7 +956,6 @@ else { "irn_flags" => "R", "comment" => "construct SSE Compare: Cmp(a, b) == a = a cmp b", "reg_req" => { "in" => [ "gp", "gp", "xmm", "xmm", "none" ], "out" => [ "in_r3 !in_r4" ] }, - "outs" => [ "res", "M" ], "latency" => 3, "units" => [ "SSE" ], }, @@ -1031,7 +963,6 @@ else { "xCondJmp" => { "op_flags" => "L|X|Y", "comment" => "construct conditional jump: UCOMIS A, B && JMPxx LABEL", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "xmm", "xmm", "none" ], "out" => [ "none", "none" ] }, "outs" => [ "false", "true" ], "latency" => 5, @@ -1042,7 +973,6 @@ else { "op_flags" => "c", "irn_flags" => "R", "comment" => "represents a SSE constant", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "out" => [ "xmm" ] }, "emit" => '. movs%M %D1, %C /* Load fConst into register */', "latency" => 2, @@ -1055,7 +985,6 @@ else { "op_flags" => "L|F", "state" => "exc_pinned", "comment" => "construct SSE Load: Load(ptr, mem) = LD ptr", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "none" ], "out" => [ "xmm" ] }, "emit" => '. movs%M %D1, %ia32_emit_am /* Load((%A1)) -> %D1 */', "outs" => [ "res", "M" ], @@ -1067,37 +996,35 @@ else { "op_flags" => "L|F", "state" => "exc_pinned", "comment" => "construct Store: Store(ptr, val, mem) = ST ptr,val", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "xmm", "none" ] }, "emit" => '. movs%M %ia32_emit_binop /* Store(%S3) -> (%A1) */', - "outs" => [ "M" ], - "latency" => 2, - "units" => [ "MEM" ], + "latency" => 2, + "units" => [ "MEM" ], + "mode" => "mode_M", }, "xStoreSimple" => { "op_flags" => "L|F", "state" => "exc_pinned", "comment" => "construct Store without index: Store(ptr, val, mem) = ST ptr,val", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "xmm", "none" ] }, "emit" => '. movs%M %ia32_emit_am, %S2 /* store XMM0 onto stack */', - "outs" => [ "M" ], - "latency" => 2, - "units" => [ "MEM" ], + "latency" => 2, + "units" => [ "MEM" ], + "mode" => "mode_M", }, "l_X87toSSE" => { "op_flags" => "L|F", "comment" => "construct: transfer a value from x87 FPU into a SSE register", - "cmp_attr" => " return 1;\n", + "cmp_attr" => "return 1;", "arity" => 3, }, "l_SSEtoX87" => { "op_flags" => "L|F", "comment" => "construct: transfer a value from SSE register to x87 FPU", - "cmp_attr" => " return 1;\n", + "cmp_attr" => "return 1;", "arity" => 3, }, @@ -1106,12 +1033,11 @@ else { "irn_flags" => "I", "state" => "exc_pinned", "comment" => "store ST0 onto stack", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", - "reg_req" => { "in" => [ "gp", "none" ] }, + "reg_req" => { "in" => [ "gp", "gp", "none" ] }, "emit" => '. fstp %ia32_emit_am /* store ST0 onto stack */', - "outs" => [ "M" ], "latency" => 4, - "units" => [ "MEM" ], + "units" => [ "MEM" ], + "mode" => "mode_M", }, "SetST0" => { @@ -1119,7 +1045,6 @@ else { "irn_flags" => "I", "state" => "exc_pinned", "comment" => "load ST0 from stack", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "none" ], "out" => [ "vf0", "none" ] }, "emit" => '. fld %ia32_emit_am /* load ST0 from stack */', "outs" => [ "res", "M" ], @@ -1142,7 +1067,6 @@ else { "op_flags" => "F|H", "state" => "pinned", "comment" => "implements a memcopy: CopyB(dst, src, mem) == memcpy(dst, src, attr(size))", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "edi", "esi", "none" ], "out" => [ "edi", "esi", "none" ] }, "outs" => [ "DST", "SRC", "M" ], "units" => [ "MEM" ], @@ -1152,43 +1076,33 @@ else { "Conv_I2I" => { "reg_req" => { "in" => [ "gp", "gp", "gp", "none" ], "out" => [ "in_r3", "none" ] }, - "cmp_attr" => " return ia32_compare_conv_attr(attr_a, attr_b);\n", "comment" => "construct Conv Int -> Int", - "outs" => [ "res", "M" ], "units" => [ "ALU" ], }, "Conv_I2I8Bit" => { "reg_req" => { "in" => [ "gp", "gp", "eax ebx ecx edx", "none" ], "out" => [ "in_r3", "none" ] }, - "cmp_attr" => " return ia32_compare_conv_attr(attr_a, attr_b);\n", "comment" => "construct Conv Int -> Int", - "outs" => [ "res", "M" ], "units" => [ "ALU" ], }, "Conv_I2FP" => { "reg_req" => { "in" => [ "gp", "gp", "gp", "none" ], "out" => [ "xmm", "none" ] }, - "cmp_attr" => " return ia32_compare_conv_attr(attr_a, attr_b);\n", "comment" => "construct Conv Int -> Floating Point", - "outs" => [ "res", "M" ], "latency" => 10, "units" => [ "SSE" ], }, "Conv_FP2I" => { "reg_req" => { "in" => [ "gp", "gp", "xmm", "none" ], "out" => [ "gp", "none" ] }, - "cmp_attr" => " return ia32_compare_conv_attr(attr_a, attr_b);\n", "comment" => "construct Conv Floating Point -> Int", - "outs" => [ "res", "M" ], "latency" => 10, "units" => [ "SSE" ], }, "Conv_FP2FP" => { "reg_req" => { "in" => [ "gp", "gp", "xmm", "none" ], "out" => [ "xmm", "none" ] }, - "cmp_attr" => " return ia32_compare_conv_attr(attr_a, attr_b);\n", "comment" => "construct Conv Floating Point -> Floating Point", - "outs" => [ "res", "M" ], "latency" => 8, "units" => [ "SSE" ], }, @@ -1229,8 +1143,6 @@ else { "irn_flags" => "R", "comment" => "construct Set: Set(sel) == sel ? 1 : 0", "reg_req" => { "in" => [ "gp", "gp", "gp", "gp", "none" ], "out" => [ "eax ebx ecx edx", "none" ] }, - "outs" => [ "res", "M" ], - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "latency" => 2, "units" => [ "ALU" ], }, @@ -1247,7 +1159,6 @@ else { "irn_flags" => "R", "comment" => "construct Set: SSE Compare + int Set", "reg_req" => { "in" => [ "gp", "gp", "xmm", "xmm", "none" ], "out" => [ "eax ebx ecx edx", "none" ] }, - "outs" => [ "res", "M" ], "latency" => 5, "units" => [ "SSE" ], }, @@ -1256,7 +1167,6 @@ else { "irn_flags" => "R", "comment" => "construct Set: x87 Compare + int Set", "reg_req" => { "in" => [ "gp", "gp", "vfp", "vfp", "none" ], "out" => [ "eax ebx ecx edx", "none" ] }, - "outs" => [ "res", "M" ], "latency" => 10, "units" => [ "FPU" ], }, @@ -1286,9 +1196,7 @@ else { "vfadd" => { "irn_flags" => "R", "comment" => "virtual fp Add: Add(a, b) = Add(b, a) = a + b", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "vfp", "vfp", "none" ], "out" => [ "vfp" ] }, - "outs" => [ "res", "M" ], "latency" => 4, "units" => [ "FPU" ], }, @@ -1296,16 +1204,14 @@ else { "vfmul" => { "irn_flags" => "R", "comment" => "virtual fp Mul: Mul(a, b) = Mul(b, a) = a * b", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "vfp", "vfp", "none" ], "out" => [ "vfp" ] }, - "outs" => [ "res", "M" ], "latency" => 4, "units" => [ "FPU" ], }, "l_vfmul" => { "op_flags" => "C", - "cmp_attr" => " return 1;\n", + "cmp_attr" => "return 1;", "comment" => "lowered virtual fp Mul: Mul(a, b) = Mul(b, a) = a * b", "arity" => 2, }, @@ -1313,22 +1219,19 @@ else { "vfsub" => { "irn_flags" => "R", "comment" => "virtual fp Sub: Sub(a, b) = a - b", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "vfp", "vfp", "none" ], "out" => [ "vfp" ] }, - "outs" => [ "res", "M" ], "latency" => 4, "units" => [ "FPU" ], }, "l_vfsub" => { - "cmp_attr" => " return 1;\n", + "cmp_attr" => "return 1;", "comment" => "lowered virtual fp Sub: Sub(a, b) = a - b", "arity" => 2, }, "vfdiv" => { "comment" => "virtual fp Div: Div(a, b) = a / b", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "vfp", "vfp", "none" ], "out" => [ "vfp" ] }, "outs" => [ "res", "M" ], "latency" => 20, @@ -1336,22 +1239,20 @@ else { }, "l_vfdiv" => { - "cmp_attr" => " return 1;\n", + "cmp_attr" => "return 1;", "comment" => "lowered virtual fp Div: Div(a, b) = a / b", "arity" => 2, }, "vfprem" => { "comment" => "virtual fp Rem: Rem(a, b) = a - Q * b (Q is integer)", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "vfp", "vfp", "none" ], "out" => [ "vfp" ] }, - "outs" => [ "res", "M" ], "latency" => 20, "units" => [ "FPU" ], }, "l_vfprem" => { - "cmp_attr" => " return 1;\n", + "cmp_attr" => "return 1;", "comment" => "lowered virtual fp Rem: Rem(a, b) = a - Q * b (Q is integer)", "arity" => 2, }, @@ -1402,7 +1303,6 @@ else { "op_flags" => "L|F", "state" => "exc_pinned", "comment" => "virtual fp Load: Load(ptr, mem) = LD ptr -> reg", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "none" ], "out" => [ "vfp", "none" ] }, "outs" => [ "res", "M" ], "latency" => 2, @@ -1413,18 +1313,16 @@ else { "op_flags" => "L|F", "state" => "exc_pinned", "comment" => "virtual fp Store: Store(ptr, val, mem) = ST ptr,val", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "vfp", "none" ] }, - "outs" => [ "M" ], "latency" => 2, "units" => [ "FPU" ], + "mode" => "mode_M", }, # Conversions "vfild" => { "comment" => "virtual fp integer Load: Load(ptr, mem) = iLD ptr -> reg", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "none" ], "out" => [ "vfp", "none" ] }, "outs" => [ "res", "M" ], "latency" => 4, @@ -1432,7 +1330,7 @@ else { }, "l_vfild" => { - "cmp_attr" => " return 1;\n", + "cmp_attr" => "return 1;", "comment" => "lowered virtual fp integer Load: Load(ptr, mem) = iLD ptr -> reg", "outs" => [ "res", "M" ], "arity" => 2, @@ -1440,18 +1338,17 @@ else { "vfist" => { "comment" => "virtual fp integer Store: Store(ptr, val, mem) = iST ptr,val", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "vfp", "none" ] }, - "outs" => [ "M" ], "latency" => 4, "units" => [ "FPU" ], + "mode" => "mode_M", }, "l_vfist" => { - "cmp_attr" => " return 1;\n", + "cmp_attr" => "return 1;", "comment" => "lowered virtual fp integer Store: Store(ptr, val, mem) = iST ptr,val", - "outs" => [ "M" ], "arity" => 3, + "mode" => "mode_M", }, @@ -1518,7 +1415,6 @@ else { "irn_flags" => "R", "init_attr" => " set_ia32_ls_mode(res, mode);", "comment" => "represents a virtual floating point constant", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "out" => [ "vfp" ] }, "latency" => 3, "units" => [ "FPU" ], @@ -1529,7 +1425,6 @@ else { "vfCondJmp" => { "op_flags" => "L|X|Y", "comment" => "represents a virtual floating point compare", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "in" => [ "gp", "gp", "vfp", "vfp", "none" ], "out" => [ "none", "none", "eax" ] }, "outs" => [ "false", "true", "temp_reg_eax" ], "latency" => 10, @@ -1718,6 +1613,7 @@ else { "comment" => "x87 fp Store: Store(ptr, val, mem) = ST ptr,val", "reg_req" => { }, "emit" => '. fst %ia32_emit_am /* Store(%A3) -> (%A1) */', + "mode" => "mode_M", }, "fstp" => { @@ -1727,6 +1623,7 @@ else { "comment" => "x87 fp Store: Store(ptr, val, mem) = ST ptr,val", "reg_req" => { }, "emit" => '. fstp %ia32_emit_am /* Store(%A3) -> (%A1) and pop */', + "mode" => "mode_M", }, # Conversions @@ -1745,6 +1642,7 @@ else { "comment" => "x87 fp integer Store: Store(ptr, val, mem) = iST ptr,val", "reg_req" => { }, "emit" => '. fist %ia32_emit_am /* integer Store(%A3) -> (%A1) */', + "mode" => "mode_M", }, "fistp" => { @@ -1753,6 +1651,7 @@ else { "comment" => "x87 fp integer Store: Store(ptr, val, mem) = iST ptr,val", "reg_req" => { }, "emit" => '. fistp %ia32_emit_am /* integer Store(%A3) -> (%A1) and pop */', + "mode" => "mode_M", }, # constants @@ -1818,7 +1717,6 @@ else { "irn_flags" => "R", "rd_constructor" => "NONE", "comment" => "represents a x87 constant", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { "out" => [ "vfp" ] }, "emit" => '. fld %ia32_emit_adr /* Load fConst into register -> %D1 */', }, @@ -1831,7 +1729,7 @@ else { "op_flags" => "R|K", "comment" => "x87 stack exchange", "reg_req" => { }, - "cmp_attr" => " return 1;\n", + "cmp_attr" => "return 1;", "emit" => '. fxch %X1 /* x87 swap %X1, %X3 */', }, @@ -1839,7 +1737,7 @@ else { "op_flags" => "R|K", "comment" => "x87 stack push", "reg_req" => {}, - "cmp_attr" => " return 1;\n", + "cmp_attr" => "return 1;", "emit" => '. fld %X1 /* x87 push %X1 */', }, @@ -1847,7 +1745,7 @@ else { "op_flags" => "R", "comment" => "x87 stack push", "reg_req" => { "in" => [ "vfp"], "out" => [ "vfp" ] }, - "cmp_attr" => " return 1;\n", + "cmp_attr" => "return 1;", "emit" => '. fld %X1 /* x87 push %X1 */', }, @@ -1855,7 +1753,7 @@ else { "op_flags" => "R|K", "comment" => "x87 stack pop", "reg_req" => { }, - "cmp_attr" => " return 1;\n", + "cmp_attr" => "return 1;", "emit" => '. fstp %X1 /* x87 pop %X1 */', }, @@ -1864,42 +1762,36 @@ else { "fcomJmp" => { "op_flags" => "L|X|Y", "comment" => "floating point compare", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { }, }, "fcompJmp" => { "op_flags" => "L|X|Y", "comment" => "floating point compare and pop", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { }, }, "fcomppJmp" => { "op_flags" => "L|X|Y", "comment" => "floating point compare and pop twice", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { }, }, "fcomrJmp" => { "op_flags" => "L|X|Y", "comment" => "floating point compare reverse", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { }, }, "fcomrpJmp" => { "op_flags" => "L|X|Y", "comment" => "floating point compare reverse and pop", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { }, }, "fcomrppJmp" => { "op_flags" => "L|X|Y", "comment" => "floating point compare reverse and pop twice", - "cmp_attr" => " return ia32_compare_immop_attr(attr_a, attr_b);\n", "reg_req" => { }, }, diff --git a/ir/be/ia32/ia32_transform.c b/ir/be/ia32/ia32_transform.c index 56cd4d840..b2f7c95f9 100644 --- a/ir/be/ia32/ia32_transform.c +++ b/ir/be/ia32/ia32_transform.c @@ -28,6 +28,7 @@ #include "type.h" #include "entity.h" #include "archop.h" /* we need this for Min and Max nodes */ +#include "error.h" #include "../benode_t.h" #include "../besched.h" @@ -62,10 +63,10 @@ extern ir_op *get_op_Mulh(void); typedef ir_node *construct_binop_func(dbg_info *db, ir_graph *irg, ir_node *block, ir_node *base, ir_node *index, \ - ir_node *op1, ir_node *op2, ir_node *mem); + ir_node *op1, ir_node *op2, ir_node *mem, ir_mode *mode); typedef ir_node *construct_unop_func(dbg_info *db, ir_graph *irg, ir_node *block, ir_node *base, ir_node *index, \ - ir_node *op, ir_node *mem); + ir_node *op, ir_node *mem, ir_mode *mode); typedef enum { ia32_SSIGN, ia32_DSIGN, ia32_SABS, ia32_DABS, ia32_known_const_max @@ -169,13 +170,11 @@ static ir_node *gen_sse_conv_int2float(ia32_code_gen_t *cg, dbg_info *dbg, ir_gr ir_node *noreg = ia32_new_NoReg_gp(cg); ir_node *nomem = new_rd_NoMem(irg); - ir_node *conv = new_rd_ia32_Conv_I2FP(dbg, irg, block, noreg, noreg, in, nomem); - set_ia32_src_mode(conv, get_irn_mode(in)); - set_ia32_tgt_mode(conv, tgt_mode); + ir_node *conv = new_rd_ia32_Conv_I2FP(dbg, irg, block, noreg, noreg, in, nomem, tgt_mode); set_ia32_am_support(conv, ia32_am_Source); SET_IA32_ORIG_NODE(conv, ia32_get_old_node_name(cg, old_node)); - return new_rd_Proj(dbg, irg, block, conv, tgt_mode, pn_ia32_Conv_I2FP_res); + return conv; } /** @@ -187,13 +186,11 @@ static ir_node *gen_sse_conv_f2d(ia32_code_gen_t *cg, dbg_info *dbg, ir_graph *i ir_node *noreg = ia32_new_NoReg_gp(cg); ir_node *nomem = new_rd_NoMem(irg); - ir_node *conv = new_rd_ia32_Conv_FP2FP(dbg, irg, block, noreg, noreg, in, nomem); - set_ia32_src_mode(conv, mode_F); - set_ia32_tgt_mode(conv, mode_D); + ir_node *conv = new_rd_ia32_Conv_FP2FP(dbg, irg, block, noreg, noreg, in, nomem, mode_D); set_ia32_am_support(conv, ia32_am_Source); SET_IA32_ORIG_NODE(conv, ia32_get_old_node_name(cg, old_node)); - return new_rd_Proj(dbg, irg, block, conv, mode_D, pn_ia32_Conv_FP2FP_res); + return conv; } /* Generates an entity for a known FP const (used for FP Neg + Abs) */ @@ -274,6 +271,32 @@ static ir_node *get_expr_op(ir_node *op1, ir_node *op2) { return !is_ia32_Cnst(op1) ? op1 : (!is_ia32_Cnst(op2) ? op2 : NULL); } +static void fold_immediate(ia32_transform_env_t *env, ir_node *node, int in1, int in2) { + ir_node *left; + ir_node *right; + + if(! (env->cg->opt & IA32_OPT_IMMOPS)) + return; + + left = get_irn_n(node, in1); + right = get_irn_n(node, in2); + if(!is_ia32_Cnst(right) && is_ia32_Cnst(left)) { + /* we can only set right operand to immediate */ + if(!is_ia32_commutative(node)) + return; + /* exchange left/right */ + set_irn_n(node, in1, right); + set_irn_n(node, in2, ia32_get_admissible_noreg(env->cg, node, in2)); + set_ia32_Immop_attr(node, left); + } else if(is_ia32_Cnst(right)) { + set_irn_n(node, in2, ia32_get_admissible_noreg(env->cg, node, in2)); + set_ia32_Immop_attr(node, right); + } else { + return; + } + + set_ia32_am_support(node, get_ia32_am_support(node) & ~ia32_am_Source); +} /** * Construct a standard binary operation, set AM and immediate if required. @@ -291,91 +314,30 @@ static ir_node *gen_binop(ia32_transform_env_t *env, ir_node *op1, ir_node *op2, ir_graph *irg = env->irg; ir_node *block = env->block; ir_node *noreg_gp = ia32_new_NoReg_gp(env->cg); - ir_node *noreg_fp = ia32_new_NoReg_fp(env->cg); ir_node *nomem = new_NoMem(); - int is_mul = 0; - ir_node *expr_op, *imm_op; - DEBUG_ONLY(firm_dbg_module_t *mod = env->mod;) - - /* Check if immediate optimization is on and */ - /* if it's an operation with immediate. */ - /* Mul/MulS/Mulh don't support immediates */ - if (! (env->cg->opt & IA32_OPT_IMMOPS) || - func == new_rd_ia32_Mul || - func == new_rd_ia32_Mulh || - func == new_rd_ia32_MulS) - { - expr_op = op1; - imm_op = NULL; - /* immediate operations are requested, but we are here: it a mul */ - if (env->cg->opt & IA32_OPT_IMMOPS) - is_mul = 1; - } - else if (is_op_commutative(get_irn_op(env->irn))) { - imm_op = get_immediate_op(op1, op2); - expr_op = get_expr_op(op1, op2); - } - else { - imm_op = get_immediate_op(NULL, op2); - expr_op = get_expr_op(op1, op2); - } - assert((expr_op || imm_op) && "invalid operands"); - - if (!expr_op) { - /* We have two consts here: not yet supported */ - imm_op = NULL; - } - - if (mode_is_float(mode)) { - /* floating point operations */ - if (imm_op) { - DB((mod, LEVEL_1, "FP with immediate ...")); - new_op = func(dbg, irg, block, noreg_gp, noreg_gp, expr_op, noreg_fp, nomem); - set_ia32_Immop_attr(new_op, imm_op); - set_ia32_am_support(new_op, ia32_am_None); - } - else { - DB((mod, LEVEL_1, "FP binop ...")); - new_op = func(dbg, irg, block, noreg_gp, noreg_gp, op1, op2, nomem); + if(mode_is_float(mode)) { + new_op = func(dbg, irg, block, noreg_gp, noreg_gp, op1, op2, nomem, mode); + set_ia32_am_support(new_op, ia32_am_Source); + } else { + new_op = func(dbg, irg, block, noreg_gp, noreg_gp, op1, op2, nomem, mode); + if(func == new_rd_ia32_Mul) { set_ia32_am_support(new_op, ia32_am_Source); - } - set_ia32_ls_mode(new_op, mode); - } - else { - /* integer operations */ - if (imm_op) { - /* This is expr + const */ - DB((mod, LEVEL_1, "INT with immediate ...")); - new_op = func(dbg, irg, block, noreg_gp, noreg_gp, expr_op, noreg_gp, nomem); - set_ia32_Immop_attr(new_op, imm_op); - - /* set AM support */ - set_ia32_am_support(new_op, ia32_am_Dest); - } - else { - DB((mod, LEVEL_1, "INT binop ...")); - /* This is a normal operation */ - new_op = func(dbg, irg, block, noreg_gp, noreg_gp, op1, op2, nomem); - - /* set AM support */ + } else { set_ia32_am_support(new_op, ia32_am_Full); } - - /* Muls can only have AM source */ - if (is_mul) - set_ia32_am_support(new_op, ia32_am_Source); } SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn)); - set_ia32_res_mode(new_op, mode); - if (is_op_commutative(get_irn_op(env->irn))) { set_ia32_commutative(new_op); } + if(func != new_rd_ia32_vfmul) { + fold_immediate(env, new_op, 2, 3); + } - return new_rd_Proj(dbg, irg, block, new_op, mode, 0); + return new_op; } @@ -433,13 +395,13 @@ static ir_node *gen_shift_binop(ia32_transform_env_t *env, ir_node *op1, ir_node /* This is shift/rot with const */ DB((mod, LEVEL_1, "Shift/Rot with immediate ...")); - new_op = func(dbg, irg, block, noreg, noreg, expr_op, noreg, nomem); + new_op = func(dbg, irg, block, noreg, noreg, expr_op, noreg, nomem, mode); set_ia32_Immop_attr(new_op, imm_op); } else { /* This is a normal shift/rot */ DB((mod, LEVEL_1, "Shift/Rot binop ...")); - new_op = func(dbg, irg, block, noreg, noreg, op1, op2, nomem); + new_op = func(dbg, irg, block, noreg, noreg, op1, op2, nomem, mode); } /* set AM support */ @@ -450,7 +412,7 @@ static ir_node *gen_shift_binop(ia32_transform_env_t *env, ir_node *op1, ir_node set_ia32_res_mode(new_op, mode); set_ia32_emit_cl(new_op); - return new_rd_Proj(dbg, irg, block, new_op, mode, 0); + return new_op; } @@ -472,7 +434,7 @@ static ir_node *gen_unop(ia32_transform_env_t *env, ir_node *op, construct_unop_ ir_node *nomem = new_NoMem(); DEBUG_ONLY(firm_dbg_module_t *mod = env->mod;) - new_op = func(dbg, irg, block, noreg, noreg, op, nomem); + new_op = func(dbg, irg, block, noreg, noreg, op, nomem, mode); if (mode_is_float(mode)) { DB((mod, LEVEL_1, "FP unop ...")); @@ -488,7 +450,7 @@ static ir_node *gen_unop(ia32_transform_env_t *env, ir_node *op, construct_unop_ set_ia32_res_mode(new_op, mode); - return new_rd_Proj(dbg, irg, block, new_op, mode, 0); + return new_op; } @@ -509,6 +471,7 @@ static ir_node *gen_imm_Add(ia32_transform_env_t *env, ir_node *expr_op, ir_node ir_node *block = env->block; ir_node *noreg = ia32_new_NoReg_gp(env->cg); ir_node *nomem = new_NoMem(); + ir_mode *mode = env->mode; int normal_add = 1; tarval_classification_t class_tv, class_negtv; DEBUG_ONLY(firm_dbg_module_t *mod = env->mod;) @@ -521,18 +484,18 @@ static ir_node *gen_imm_Add(ia32_transform_env_t *env, ir_node *expr_op, ir_node if (class_tv == TV_CLASSIFY_ONE) { /* + 1 == INC */ DB((env->mod, LEVEL_2, "Add(1) to Inc ... ")); - new_op = new_rd_ia32_Inc(dbg, irg, block, noreg, noreg, expr_op, nomem); + new_op = new_rd_ia32_Inc(dbg, irg, block, noreg, noreg, expr_op, nomem, mode); normal_add = 0; } else if (class_tv == TV_CLASSIFY_ALL_ONE || class_negtv == TV_CLASSIFY_ONE) { /* + (-1) == DEC */ DB((mod, LEVEL_2, "Add(-1) to Dec ... ")); - new_op = new_rd_ia32_Dec(dbg, irg, block, noreg, noreg, expr_op, nomem); + new_op = new_rd_ia32_Dec(dbg, irg, block, noreg, noreg, expr_op, nomem, mode); normal_add = 0; } } if (normal_add) { - new_op = new_rd_ia32_Add(dbg, irg, block, noreg, noreg, expr_op, noreg, nomem); + new_op = new_rd_ia32_Add(dbg, irg, block, noreg, noreg, expr_op, noreg, nomem, mode); set_ia32_Immop_attr(new_op, const_op); set_ia32_commutative(new_op); } @@ -624,7 +587,7 @@ static ir_node *gen_Add(ia32_transform_env_t *env) { } else { /* This is a normal add */ - new_op = new_rd_ia32_Add(dbg, irg, block, noreg, noreg, op1, op2, nomem); + new_op = new_rd_ia32_Add(dbg, irg, block, noreg, noreg, op1, op2, nomem, mode); /* set AM support */ set_ia32_am_support(new_op, ia32_am_Full); @@ -636,7 +599,7 @@ static ir_node *gen_Add(ia32_transform_env_t *env) { set_ia32_res_mode(new_op, mode); - return new_rd_Proj(dbg, irg, block, new_op, mode, pn_ia32_Add_res); + return new_op; } @@ -679,29 +642,22 @@ static ir_node *gen_Mul(ia32_transform_env_t *env) { static ir_node *gen_Mulh(ia32_transform_env_t *env) { ir_node *op1 = get_irn_n(env->irn, 0); ir_node *op2 = get_irn_n(env->irn, 1); + ir_node *noreg = ia32_new_NoReg_gp(env->cg); ir_node *proj_EAX, *proj_EDX, *mulh; ir_node *in[1]; assert(!mode_is_float(env->mode) && "Mulh with float not supported"); - proj_EAX = gen_binop(env, op1, op2, new_rd_ia32_Mulh); - mulh = get_Proj_pred(proj_EAX); - proj_EDX = new_rd_Proj(env->dbg, env->irg, env->block, mulh, env->mode, pn_EDX); - - /* to be on the save side */ - set_Proj_proj(proj_EAX, pn_EAX); - - if (is_ia32_ImmConst(mulh) || is_ia32_ImmSymConst(mulh)) { - /* Mulh with const cannot have AM */ - set_ia32_am_support(mulh, ia32_am_None); - } - else { - /* Mulh cannot have AM for destination */ - set_ia32_am_support(mulh, ia32_am_Source); - } + mulh = new_rd_ia32_Mulh(env->dbg, env->irg, env->block, noreg, noreg, op1, op2, new_NoMem()); + set_ia32_commutative(mulh); + set_ia32_res_mode(mulh, env->mode); + set_ia32_am_support(mulh, ia32_am_Source); + /* imediates are not supported, so no fold_immediate */ - in[0] = proj_EAX; + proj_EAX = new_rd_Proj(env->dbg, env->irg, env->block, mulh, mode_Is, pn_EAX); + proj_EDX = new_rd_Proj(env->dbg, env->irg, env->block, mulh, mode_Is, pn_EDX); /* keep EAX */ + in[0] = proj_EAX; be_new_Keep(&ia32_reg_classes[CLASS_ia32_gp], env->irg, env->block, 1, in); return proj_EDX; @@ -833,6 +789,7 @@ static ir_node *gen_imm_Sub(ia32_transform_env_t *env, ir_node *expr_op, ir_node ir_node *block = env->block; ir_node *noreg = ia32_new_NoReg_gp(env->cg); ir_node *nomem = new_NoMem(); + ir_mode *mode = env->mode; int normal_sub = 1; tarval_classification_t class_tv, class_negtv; DEBUG_ONLY(firm_dbg_module_t *mod = env->mod;) @@ -845,18 +802,18 @@ static ir_node *gen_imm_Sub(ia32_transform_env_t *env, ir_node *expr_op, ir_node if (class_tv == TV_CLASSIFY_ONE) { /* - 1 == DEC */ DB((mod, LEVEL_2, "Sub(1) to Dec ... ")); - new_op = new_rd_ia32_Dec(dbg, irg, block, noreg, noreg, expr_op, nomem); + new_op = new_rd_ia32_Dec(dbg, irg, block, noreg, noreg, expr_op, nomem, mode); normal_sub = 0; } else if (class_negtv == TV_CLASSIFY_ONE) { /* - (-1) == Sub */ DB((mod, LEVEL_2, "Sub(-1) to Inc ... ")); - new_op = new_rd_ia32_Inc(dbg, irg, block, noreg, noreg, expr_op, nomem); + new_op = new_rd_ia32_Inc(dbg, irg, block, noreg, noreg, expr_op, nomem, mode); normal_sub = 0; } } if (normal_sub) { - new_op = new_rd_ia32_Sub(dbg, irg, block, noreg, noreg, expr_op, noreg, nomem); + new_op = new_rd_ia32_Sub(dbg, irg, block, noreg, noreg, expr_op, noreg, nomem, mode); set_ia32_Immop_attr(new_op, const_op); } @@ -949,7 +906,7 @@ static ir_node *gen_Sub(ia32_transform_env_t *env) { } else { /* This is a normal sub */ - new_op = new_rd_ia32_Sub(dbg, irg, block, noreg, noreg, op1, op2, nomem); + new_op = new_rd_ia32_Sub(dbg, irg, block, noreg, noreg, op1, op2, nomem, mode); /* set AM support */ set_ia32_am_support(new_op, ia32_am_Full); @@ -960,7 +917,7 @@ static ir_node *gen_Sub(ia32_transform_env_t *env) { set_ia32_res_mode(new_op, mode); - return new_rd_Proj(dbg, irg, block, new_op, mode, pn_ia32_Sub_res); + return new_op; } @@ -1280,32 +1237,31 @@ static ir_node *gen_Rot(ia32_transform_env_t *env) { ir_node *gen_Minus_ex(ia32_transform_env_t *env, ir_node *op) { ident *name; ir_node *new_op; + ir_mode *mode = env->mode; int size; - if (mode_is_float(env->mode)) { + if (mode_is_float(mode)) { FP_USED(env->cg); if (USE_SSE2(env->cg)) { ir_node *noreg_gp = ia32_new_NoReg_gp(env->cg); ir_node *noreg_fp = ia32_new_NoReg_fp(env->cg); ir_node *nomem = new_rd_NoMem(env->irg); - new_op = new_rd_ia32_xEor(env->dbg, env->irg, env->block, noreg_gp, noreg_gp, op, noreg_fp, nomem); + new_op = new_rd_ia32_xEor(env->dbg, env->irg, env->block, noreg_gp, noreg_gp, op, noreg_fp, nomem, mode); - size = get_mode_size_bits(env->mode); + size = get_mode_size_bits(mode); name = gen_fp_known_const(size == 32 ? ia32_SSIGN : ia32_DSIGN); set_ia32_am_sc(new_op, name); SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn)); - set_ia32_res_mode(new_op, env->mode); + set_ia32_res_mode(new_op, mode); set_ia32_op_type(new_op, ia32_AddrModeS); - set_ia32_ls_mode(new_op, env->mode); - - new_op = new_rd_Proj(env->dbg, env->irg, env->block, new_op, env->mode, pn_ia32_xEor_res); + set_ia32_ls_mode(new_op, mode); } else { - new_op = new_rd_ia32_vfchs(env->dbg, env->irg, env->block, op, env->mode); + new_op = new_rd_ia32_vfchs(env->dbg, env->irg, env->block, op, mode); SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn)); } } @@ -1362,7 +1318,7 @@ static ir_node *gen_Abs(ia32_transform_env_t *env) { if (mode_is_float(mode)) { FP_USED(env->cg); if (USE_SSE2(env->cg)) { - res = new_rd_ia32_xAnd(dbg,irg, block, noreg_gp, noreg_gp, op, noreg_fp, nomem); + res = new_rd_ia32_xAnd(dbg,irg, block, noreg_gp, noreg_gp, op, noreg_fp, nomem, mode); size = get_mode_size_bits(mode); name = gen_fp_known_const(size == 32 ? ia32_SABS : ia32_DABS); @@ -1374,8 +1330,6 @@ static ir_node *gen_Abs(ia32_transform_env_t *env) { set_ia32_res_mode(res, mode); set_ia32_op_type(res, ia32_AddrModeS); set_ia32_ls_mode(res, env->mode); - - res = new_rd_Proj(dbg, irg, block, res, mode, pn_ia32_xAnd_res); } else { res = new_rd_ia32_vfabs(dbg, irg, block, op, mode); @@ -1383,24 +1337,24 @@ static ir_node *gen_Abs(ia32_transform_env_t *env) { } } else { + // Matze: does this work with other modes? I'm not sure... + // someone should check and remove this assert then + assert(get_mode_size_bits(mode) == 32); + res = new_rd_ia32_Cdq(dbg, irg, block, op); SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(env->cg, env->irn)); set_ia32_res_mode(res, mode); - p_eax = new_rd_Proj(dbg, irg, block, res, mode, pn_ia32_Cdq_EAX); - p_edx = new_rd_Proj(dbg, irg, block, res, mode, pn_ia32_Cdq_EDX); + p_eax = new_rd_Proj(dbg, irg, block, res, mode, pn_EAX); + p_edx = new_rd_Proj(dbg, irg, block, res, mode, pn_EDX); - res = new_rd_ia32_Eor(dbg, irg, block, noreg_gp, noreg_gp, p_eax, p_edx, nomem); + res = new_rd_ia32_Eor(dbg, irg, block, noreg_gp, noreg_gp, p_eax, p_edx, nomem, mode); SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(env->cg, env->irn)); set_ia32_res_mode(res, mode); - res = new_rd_Proj(dbg, irg, block, res, mode, pn_ia32_Eor_res); - - res = new_rd_ia32_Sub(dbg, irg, block, noreg_gp, noreg_gp, res, p_edx, nomem); + res = new_rd_ia32_Sub(dbg, irg, block, noreg_gp, noreg_gp, res, p_edx, nomem, mode); SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(env->cg, env->irn)); set_ia32_res_mode(res, mode); - - res = new_rd_Proj(dbg, irg, block, res, mode, pn_ia32_Sub_res); } return res; @@ -1497,6 +1451,7 @@ static ir_node *gen_Load(ia32_transform_env_t *env) { */ static ir_node *gen_Store(ia32_transform_env_t *env) { ir_node *node = env->irn; + ir_graph *irg = env->irg; ir_node *noreg = ia32_new_NoReg_gp(env->cg); ir_node *val = get_Store_value(node); ir_node *ptr = get_Store_ptr(node); @@ -1508,9 +1463,6 @@ static ir_node *gen_Store(ia32_transform_env_t *env) { ir_node *new_op; ia32_am_flavour_t am_flav = ia32_am_B; ia32_immop_type_t immop = ia32_ImmNone; - ir_node *projs[pn_Store_max]; - - ia32_collect_Projs(env->irn, projs, pn_Store_max); if (! mode_is_float(mode)) { /* in case of storing a const (but not a symconst) -> make it an attribute */ @@ -1538,21 +1490,17 @@ static ir_node *gen_Store(ia32_transform_env_t *env) { if (mode_is_float(mode)) { FP_USED(env->cg); if (USE_SSE2(env->cg)) { - new_op = new_rd_ia32_xStore(env->dbg, env->irg, env->block, sptr, noreg, sval, mem); - ia32_renumber_Proj(projs, pn_Store_M, pn_ia32_xStore_M); + new_op = new_rd_ia32_xStore(env->dbg, irg, env->block, sptr, noreg, sval, mem); } else { - new_op = new_rd_ia32_vfst(env->dbg, env->irg, env->block, sptr, noreg, sval, mem); - ia32_renumber_Proj(projs, pn_Store_M, pn_ia32_vfst_M); + new_op = new_rd_ia32_vfst(env->dbg, irg, env->block, sptr, noreg, sval, mem); } } else if (get_mode_size_bits(mode) == 8) { - new_op = new_rd_ia32_Store8Bit(env->dbg, env->irg, env->block, sptr, noreg, sval, mem); - ia32_renumber_Proj(projs, pn_Store_M, pn_ia32_Store8Bit_M); + new_op = new_rd_ia32_Store8Bit(env->dbg, irg, env->block, sptr, noreg, sval, mem); } else { - new_op = new_rd_ia32_Store(env->dbg, env->irg, env->block, sptr, noreg, sval, mem); - ia32_renumber_Proj(projs, pn_Store_M, pn_ia32_Store_M); + new_op = new_rd_ia32_Store(env->dbg, irg, env->block, sptr, noreg, sval, mem); } /* stored const is an attribute (saves a register) */ @@ -1858,33 +1806,29 @@ static ir_node *gen_Psi(ia32_transform_env_t *env) { pnc |= 8; /* transform integer compare to fp compare */ } - new_op = new_rd_ia32_xCmp(dbg, irg, block, noreg, noreg, cmp_a, cmp_b, nomem); + new_op = new_rd_ia32_xCmp(dbg, irg, block, noreg, noreg, cmp_a, cmp_b, nomem, mode); set_ia32_pncode(new_op, pnc); set_ia32_am_support(new_op, ia32_am_Source); set_ia32_res_mode(new_op, mode); SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(cg, node)); - new_op = new_rd_Proj(dbg, irg, block, new_op, mode, pn_ia32_xCmp_res); - and1 = new_rd_ia32_xAnd(dbg, irg, block, noreg, noreg, psi_true, new_op, nomem); + and1 = new_rd_ia32_xAnd(dbg, irg, block, noreg, noreg, psi_true, new_op, nomem, mode); set_ia32_am_support(and1, ia32_am_None); set_ia32_res_mode(and1, mode); set_ia32_commutative(and1); SET_IA32_ORIG_NODE(and1, ia32_get_old_node_name(cg, node)); - and1 = new_rd_Proj(dbg, irg, block, and1, mode, pn_ia32_xAnd_res); - and2 = new_rd_ia32_xAndNot(dbg, irg, block, noreg, noreg, new_op, psi_default, nomem); + and2 = new_rd_ia32_xAndNot(dbg, irg, block, noreg, noreg, new_op, psi_default, nomem, mode); set_ia32_am_support(and2, ia32_am_None); set_ia32_res_mode(and2, mode); set_ia32_commutative(and2); SET_IA32_ORIG_NODE(and2, ia32_get_old_node_name(cg, node)); - and2 = new_rd_Proj(dbg, irg, block, and2, mode, pn_ia32_xAndNot_res); - new_op = new_rd_ia32_xOr(dbg, irg, block, noreg, noreg, and1, and2, nomem); + new_op = new_rd_ia32_xOr(dbg, irg, block, noreg, noreg, and1, and2, nomem, mode); set_ia32_am_support(new_op, ia32_am_None); set_ia32_res_mode(new_op, mode); set_ia32_commutative(new_op); SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(cg, node)); - new_op = new_rd_Proj(dbg, irg, block, new_op, mode, pn_ia32_xOr_res); } else { /* x87 FPU */ @@ -1949,15 +1893,15 @@ static ir_node *gen_Psi(ia32_transform_env_t *env) { if (is_ia32_Const_1(psi_true) && is_ia32_Const_0(psi_default)) { /* first case for SETcc: default is 0, set to 1 iff condition is true */ new_op = gen_binop(env, cmp_a, cmp_b, set_func); - set_ia32_pncode(get_Proj_pred(new_op), pnc); - set_ia32_am_support(get_Proj_pred(new_op), ia32_am_Source); + set_ia32_pncode(new_op, pnc); + set_ia32_am_support(new_op, ia32_am_Source); } else if (is_ia32_Const_0(psi_true) && is_ia32_Const_1(psi_default)) { /* second case for SETcc: default is 1, set to 0 iff condition is true: */ /* we invert condition and set default to 0 */ new_op = gen_binop(env, cmp_a, cmp_b, set_func); - set_ia32_pncode(get_Proj_pred(new_op), get_inversed_pnc(pnc)); - set_ia32_am_support(get_Proj_pred(new_op), ia32_am_Source); + set_ia32_pncode(new_op, get_inversed_pnc(pnc)); + set_ia32_am_support(new_op, ia32_am_Source); } else { /* otherwise: use CMOVcc */ @@ -2009,16 +1953,22 @@ static ir_node *gen_x87_fp_to_gp(ia32_transform_env_t *env, ir_mode *tgt_mode) { ia32_code_gen_t *cg = env->cg; ir_entity *ent = cg->fp_to_gp; ir_graph *irg = env->irg; + ir_node *irn = env->irn; ir_node *block = env->block; ir_node *noreg = ia32_new_NoReg_gp(env->cg); ir_node *op = get_Conv_op(env->irn); ir_node *fist, *mem, *load; +#if 0 if (! ent) { int size = get_mode_size_bytes(ia32_reg_classes[CLASS_ia32_vfp].mode); ent = cg->fp_to_gp = frame_alloc_area(get_irg_frame_type(env->irg), size, 16, 0); + if(ent == NULL) { + panic("Couldn't allocate space on stack for fp conversion"); + } } +#endif /* do a fist */ fist = new_rd_ia32_vfist(env->dbg, irg, block, get_irg_frame(irg), noreg, op, get_irg_no_mem(irg)); @@ -2029,8 +1979,9 @@ static ir_node *gen_x87_fp_to_gp(ia32_transform_env_t *env, ir_mode *tgt_mode) { set_ia32_op_type(fist, ia32_AddrModeD); set_ia32_am_flavour(fist, ia32_B); set_ia32_ls_mode(fist, mode_F); + SET_IA32_ORIG_NODE(fist, ia32_get_old_node_name(cg, irn)); - mem = new_r_Proj(irg, block, fist, mode_M, pn_ia32_vfist_M); + mem = fist; /* do a Load */ load = new_rd_ia32_Load(env->dbg, irg, block, get_irg_frame(irg), noreg, mem); @@ -2041,39 +1992,46 @@ static ir_node *gen_x87_fp_to_gp(ia32_transform_env_t *env, ir_mode *tgt_mode) { set_ia32_op_type(load, ia32_AddrModeS); set_ia32_am_flavour(load, ia32_B); set_ia32_ls_mode(load, tgt_mode); + SET_IA32_ORIG_NODE(load, ia32_get_old_node_name(cg, irn)); return new_r_Proj(irg, block, load, tgt_mode, pn_ia32_Load_res); } /** - * Create a conversion from x87 state register to general purpose. + * Create a conversion from general purpose to x87 register */ static ir_node *gen_x87_gp_to_fp(ia32_transform_env_t *env, ir_mode *src_mode) { ia32_code_gen_t *cg = env->cg; ir_entity *ent = cg->gp_to_fp; + ir_node *irn = env->irn; ir_graph *irg = env->irg; ir_node *block = env->block; ir_node *noreg = ia32_new_NoReg_gp(env->cg); ir_node *nomem = get_irg_no_mem(irg); ir_node *op = get_Conv_op(env->irn); - ir_node *fild, *store, *mem; + ir_node *fild, *store; int src_bits; - if (! ent) { + if (ent == NULL) { int size = get_mode_size_bytes(ia32_reg_classes[CLASS_ia32_gp].mode); ent = cg->gp_to_fp = frame_alloc_area(get_irg_frame_type(env->irg), size, size, 0); + if(ent == NULL) { + panic("Couldn't allocate space on stack for fp conversion"); + } } /* first convert to 32 bit */ src_bits = get_mode_size_bits(src_mode); if (src_bits == 8) { - op = new_rd_ia32_Conv_I2I8Bit(env->dbg, irg, block, noreg, noreg, op, nomem); - op = new_r_Proj(irg, block, op, mode_Is, 0); + op = new_rd_ia32_Conv_I2I8Bit(env->dbg, irg, block, noreg, noreg, op, nomem, mode_Is); + set_ia32_am_support(op, ia32_am_Source); + SET_IA32_ORIG_NODE(op, ia32_get_old_node_name(cg, irn)); } else if (src_bits < 32) { - op = new_rd_ia32_Conv_I2I(env->dbg, irg, block, noreg, noreg, op, nomem); - op = new_r_Proj(irg, block, op, mode_Is, 0); + op = new_rd_ia32_Conv_I2I(env->dbg, irg, block, noreg, noreg, op, nomem, mode_Is); + set_ia32_am_support(op, ia32_am_Source); + SET_IA32_ORIG_NODE(op, ia32_get_old_node_name(cg, irn)); } /* do a store */ @@ -2081,23 +2039,20 @@ static ir_node *gen_x87_gp_to_fp(ia32_transform_env_t *env, ir_mode *src_mode) { set_ia32_frame_ent(store, ent); set_ia32_use_frame(store); - set_ia32_am_support(store, ia32_am_Dest); set_ia32_op_type(store, ia32_AddrModeD); - set_ia32_am_flavour(store, ia32_B); + set_ia32_am_flavour(store, ia32_am_OB); set_ia32_ls_mode(store, mode_Is); - mem = new_r_Proj(irg, block, store, mode_M, pn_ia32_Store_M); - /* do a fild */ - fild = new_rd_ia32_vfild(env->dbg, irg, block, get_irg_frame(irg), noreg, mem); + fild = new_rd_ia32_vfild(env->dbg, irg, block, get_irg_frame(irg), noreg, store); set_ia32_frame_ent(fild, ent); set_ia32_use_frame(fild); set_ia32_am_support(fild, ia32_am_Source); set_ia32_op_type(fild, ia32_AddrModeS); - set_ia32_am_flavour(fild, ia32_B); - set_ia32_ls_mode(fild, mode_F); + set_ia32_am_flavour(fild, ia32_am_OB); + set_ia32_ls_mode(fild, mode_Is); return new_r_Proj(irg, block, fild, mode_F, pn_ia32_vfild_res); } @@ -2116,19 +2071,17 @@ static ir_node *gen_Conv(ia32_transform_env_t *env) { ir_mode *tgt_mode = env->mode; int src_bits = get_mode_size_bits(src_mode); int tgt_bits = get_mode_size_bits(tgt_mode); - int pn = -1; int kill = 0; ir_node *block = env->block; ir_node *new_op = NULL; ir_node *noreg = ia32_new_NoReg_gp(env->cg); ir_node *nomem = new_rd_NoMem(irg); - ir_node *proj; DEBUG_ONLY(firm_dbg_module_t *mod = env->mod;) if (src_mode == tgt_mode) { /* this can happen when changing mode_P to mode_Is */ DB((mod, LEVEL_1, "killed Conv(mode, mode) ...")); - edges_reroute(env->irn, op, irg); + exchange(env->irn, op); } else if (mode_is_float(src_mode)) { /* we convert from float ... */ @@ -2136,8 +2089,7 @@ static ir_node *gen_Conv(ia32_transform_env_t *env) { /* ... to float */ if (USE_SSE2(env->cg)) { DB((mod, LEVEL_1, "create Conv(float, float) ...")); - new_op = new_rd_ia32_Conv_FP2FP(dbg, irg, block, noreg, noreg, op, nomem); - pn = pn_ia32_Conv_FP2FP_res; + new_op = new_rd_ia32_Conv_FP2FP(dbg, irg, block, noreg, noreg, op, nomem, tgt_mode); } else { DB((mod, LEVEL_1, "killed Conv(float, float) ...")); @@ -2145,8 +2097,7 @@ static ir_node *gen_Conv(ia32_transform_env_t *env) { remark: we create a intermediate conv here, so modes will be spread correctly these convs will be killed later */ - new_op = new_rd_ia32_Conv_FP2FP(dbg, irg, block, noreg, noreg, op, nomem); - pn = pn_ia32_Conv_FP2FP_res; + new_op = new_rd_ia32_Conv_FP2FP(dbg, irg, block, noreg, noreg, op, nomem, tgt_mode); kill = 1; } } @@ -2154,28 +2105,20 @@ static ir_node *gen_Conv(ia32_transform_env_t *env) { /* ... to int */ DB((mod, LEVEL_1, "create Conv(float, int) ...")); if (USE_SSE2(env->cg)) { - new_op = new_rd_ia32_Conv_FP2I(dbg, irg, block, noreg, noreg, op, nomem); - pn = pn_ia32_Conv_FP2I_res; + new_op = new_rd_ia32_Conv_FP2I(dbg, irg, block, noreg, noreg, op, nomem, mode_Is); } else - return gen_x87_fp_to_gp(env, tgt_mode); + return gen_x87_fp_to_gp(env, mode_Is); /* if target mode is not int: add an additional downscale convert */ - if (tgt_bits < 32) { + if (tgt_mode != mode_Is) { SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn)); - set_ia32_am_support(new_op, ia32_am_Source); - set_ia32_tgt_mode(new_op, mode_Is); - set_ia32_src_mode(new_op, src_mode); - - proj = new_rd_Proj(dbg, irg, block, new_op, mode_Is, pn_ia32_Conv_FP2I_res); if (tgt_bits == 8 || src_bits == 8) { - new_op = new_rd_ia32_Conv_I2I8Bit(dbg, irg, block, noreg, noreg, proj, nomem); - pn = pn_ia32_Conv_I2I8Bit_res; + new_op = new_rd_ia32_Conv_I2I8Bit(dbg, irg, block, noreg, noreg, new_op, nomem, tgt_mode); } else { - new_op = new_rd_ia32_Conv_I2I(dbg, irg, block, noreg, noreg, proj, nomem); - pn = pn_ia32_Conv_I2I_res; + new_op = new_rd_ia32_Conv_I2I(dbg, irg, block, noreg, noreg, new_op, nomem, tgt_mode); } src_mode = mode_Is; } @@ -2188,8 +2131,7 @@ static ir_node *gen_Conv(ia32_transform_env_t *env) { /* ... to float */ DB((mod, LEVEL_1, "create Conv(int, float) ...")); if (USE_SSE2(env->cg)) { - new_op = new_rd_ia32_Conv_I2FP(dbg, irg, block, noreg, noreg, op, nomem); - pn = pn_ia32_Conv_I2FP_res; + new_op = new_rd_ia32_Conv_I2FP(dbg, irg, block, noreg, noreg, op, nomem, tgt_mode); } else return gen_x87_gp_to_fp(env, src_mode); @@ -2202,19 +2144,16 @@ static ir_node *gen_Conv(ia32_transform_env_t *env) { remark: we create a intermediate conv here, so modes will be spread correctly these convs will be killed later */ - new_op = new_rd_ia32_Conv_I2I(dbg, irg, block, noreg, noreg, op, nomem); - pn = pn_ia32_Conv_I2I_res; + new_op = new_rd_ia32_Conv_I2I(dbg, irg, block, noreg, noreg, op, nomem, tgt_mode); kill = 1; } else { DB((mod, LEVEL_1, "create Conv(int, int) ...", src_mode, tgt_mode)); if (tgt_bits == 8 || src_bits == 8) { - new_op = new_rd_ia32_Conv_I2I8Bit(dbg, irg, block, noreg, noreg, op, nomem); - pn = pn_ia32_Conv_I2I8Bit_res; + new_op = new_rd_ia32_Conv_I2I8Bit(dbg, irg, block, noreg, noreg, op, nomem, tgt_mode); } else { - new_op = new_rd_ia32_Conv_I2I(dbg, irg, block, noreg, noreg, op, nomem); - pn = pn_ia32_Conv_I2I_res; + new_op = new_rd_ia32_Conv_I2I(dbg, irg, block, noreg, noreg, op, nomem, tgt_mode); } } } @@ -2222,14 +2161,10 @@ static ir_node *gen_Conv(ia32_transform_env_t *env) { if (new_op) { SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn)); - set_ia32_tgt_mode(new_op, tgt_mode); - set_ia32_src_mode(new_op, src_mode); if(tgt_bits >= src_bits) set_ia32_am_support(new_op, ia32_am_Source); - new_op = new_rd_Proj(dbg, irg, block, new_op, tgt_mode, pn); - if (kill) nodeset_insert(env->cg->kill_conv, new_op); } @@ -2298,8 +2233,9 @@ static ir_node *gen_be_FrameAddr(ia32_transform_env_t *env) { ir_node *op = get_irn_n(node, 0); ir_node *noreg = ia32_new_NoReg_gp(env->cg); ir_node *nomem = new_rd_NoMem(env->irg); + ir_mode *mode = env->mode; - new_op = new_rd_ia32_Add(env->dbg, env->irg, env->block, noreg, noreg, op, noreg, nomem); + new_op = new_rd_ia32_Add(env->dbg, env->irg, env->block, noreg, noreg, op, noreg, nomem, mode); set_ia32_frame_ent(new_op, arch_get_frame_entity(env->cg->arch_env, node)); set_ia32_am_support(new_op, ia32_am_Full); set_ia32_use_frame(new_op); @@ -2308,7 +2244,7 @@ static ir_node *gen_be_FrameAddr(ia32_transform_env_t *env) { SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, env->irn)); - return new_rd_Proj(env->dbg, env->irg, env->block, new_op, env->mode, pn_ia32_Add_res); + return new_op; } /** @@ -2365,6 +2301,7 @@ static ir_node *gen_be_FrameLoad(ia32_transform_env_t *env) { static ir_node *gen_be_FrameStore(ia32_transform_env_t *env) { ir_node *new_op = NULL; ir_node *node = env->irn; + ir_graph *irg = env->irg; ir_node *noreg = ia32_new_NoReg_gp(env->cg); ir_node *mem = get_irn_n(node, 0); ir_node *ptr = get_irn_n(node, 1); @@ -2378,21 +2315,17 @@ static ir_node *gen_be_FrameStore(ia32_transform_env_t *env) { if (mode_is_float(mode)) { FP_USED(env->cg); if (USE_SSE2(env->cg)) { - new_op = new_rd_ia32_xStore(env->dbg, env->irg, env->block, ptr, noreg, val, mem); - ia32_renumber_Proj(projs, pn_Store_M, pn_ia32_xStore_M); + new_op = new_rd_ia32_xStore(env->dbg, irg, env->block, ptr, noreg, val, mem); } else { - new_op = new_rd_ia32_vfst(env->dbg, env->irg, env->block, ptr, noreg, val, mem); - ia32_renumber_Proj(projs, pn_Store_M, pn_ia32_vfst_M); + new_op = new_rd_ia32_vfst(env->dbg, irg, env->block, ptr, noreg, val, mem); } } else if (get_mode_size_bits(mode) == 8) { - new_op = new_rd_ia32_Store8Bit(env->dbg, env->irg, env->block, ptr, noreg, val, mem); - ia32_renumber_Proj(projs, pn_Store_M, pn_ia32_Store8Bit_M); + new_op = new_rd_ia32_Store8Bit(env->dbg, irg, env->block, ptr, noreg, val, mem); } else { - new_op = new_rd_ia32_Store(env->dbg, env->irg, env->block, ptr, noreg, val, mem); - ia32_renumber_Proj(projs, pn_Store_M, pn_ia32_Store_M); + new_op = new_rd_ia32_Store(env->dbg, irg, env->block, ptr, noreg, val, mem); } set_ia32_frame_ent(new_op, ent); @@ -2415,6 +2348,8 @@ static ir_node *gen_be_Call(ia32_transform_env_t *env) { ir_node *call_res = get_proj_for_pn(env->irn, pn_be_Call_first_res); ir_node *call_mem = get_proj_for_pn(env->irn, pn_be_Call_M_regular); ir_mode *mode; + ir_node *nomem = new_NoMem(); + ir_node *noreg = ia32_new_NoReg_gp(env->cg); if (! call_res || ! USE_SSE2(env->cg)) return NULL; @@ -2428,10 +2363,10 @@ static ir_node *gen_be_Call(ia32_transform_env_t *env) { if (mode_is_float(mode)) { /* store st(0) onto stack */ ir_node *frame = get_irg_frame(env->irg); - ir_node *fstp = new_rd_ia32_GetST0(env->dbg, env->irg, env->block, frame, get_irg_no_mem(env->irg)); - ir_node *mproj = new_r_Proj(env->irg, env->block, fstp, mode_M, pn_ia32_GetST0_M); + ir_node *fstp = new_rd_ia32_GetST0(env->dbg, env->irg, env->block, frame, noreg, nomem); ir_entity *ent = frame_alloc_area(get_irg_frame_type(env->irg), get_mode_size_bytes(mode), 16, 0); ir_node *sse_load, *p, *bad, *keep; + ir_node *mproj; ir_node **in_keep; int keep_arity, i; @@ -2443,7 +2378,7 @@ static ir_node *gen_be_Call(ia32_transform_env_t *env) { set_ia32_am_support(fstp, ia32_am_Dest); /* load into SSE register */ - sse_load = new_rd_ia32_xLoad(env->dbg, env->irg, env->block, frame, ia32_new_NoReg_gp(env->cg), mproj); + sse_load = new_rd_ia32_xLoad(env->dbg, env->irg, env->block, frame, ia32_new_NoReg_gp(env->cg), fstp); set_ia32_ls_mode(sse_load, mode); set_ia32_op_type(sse_load, ia32_AddrModeS); set_ia32_use_frame(sse_load); @@ -2543,7 +2478,6 @@ static ir_node *gen_be_Return(ia32_transform_env_t *env) { set_ia32_frame_ent(sse_store, ent); set_ia32_am_flavour(sse_store, ia32_B); set_ia32_am_support(sse_store, ia32_am_Dest); - sse_store = new_r_Proj(env->irg, env->block, sse_store, mode_M, pn_ia32_xStore_M); /* load into st0 */ fld = new_rd_ia32_SetST0(env->dbg, env->irg, env->block, frame, sse_store); @@ -2688,6 +2622,29 @@ static ir_node *gen_Unknown(ia32_transform_env_t *env) { return NULL; } +static ir_node *gen_Proj(ia32_transform_env_t *env) { + ir_node *pred = get_Proj_pred(env->irn); + int proj = get_Proj_proj(env->irn); + + if(is_Store(pred)) { + if(proj == pn_Store_M) { + env->irn = pred; + return gen_Store(env); + } else { + return new_Bad(); + } + } else if(be_is_FrameStore(pred)) { + if(proj == pn_Store_M) { + env->irn = pred; + return gen_be_FrameStore(env); + } else { + return new_Bad(); + } + } + + return NULL; +} + /********************************************************************** * _ _ _ * | | | | | | @@ -2711,11 +2668,8 @@ typedef ir_node *construct_store_func(dbg_info *db, ir_graph *irg, ir_node *bloc */ static ir_node *gen_lowered_Load(ia32_transform_env_t *env, construct_load_func func, char fp_unit) { ir_node *node = env->irn; - ir_node *noreg = ia32_new_NoReg_gp(env->cg); ir_mode *mode = get_ia32_ls_mode(node); ir_node *new_op; - char *am_offs; - ia32_am_flavour_t am_flav = ia32_B; /* Could be that we have SSE2 unit, but due to 64Bit Div/Conv @@ -2727,20 +2681,21 @@ static ir_node *gen_lowered_Load(ia32_transform_env_t *env, construct_load_func FORCE_x87(env->cg); } - new_op = func(env->dbg, env->irg, env->block, get_irn_n(node, 0), noreg, get_irn_n(node, 1)); - am_offs = get_ia32_am_offs(node); - - if (am_offs) { - am_flav |= ia32_O; - add_ia32_am_offs(new_op, am_offs); - } + new_op = func(env->dbg, env->irg, env->block, get_irn_n(node, 0), get_irn_n(node, 1), get_irn_n(node, 2)); set_ia32_am_support(new_op, ia32_am_Source); set_ia32_op_type(new_op, ia32_AddrModeS); - set_ia32_am_flavour(new_op, am_flav); - 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_am_flavour(new_op, get_ia32_am_flavour(node)); + set_ia32_am_offs_int(new_op, get_ia32_am_offs_int(node)); + set_ia32_am_sc(new_op, get_ia32_am_sc(node)); + if(is_ia32_am_sc_sign(node)) + set_ia32_am_sc_sign(new_op); + set_ia32_am_scale(new_op, get_ia32_am_scale(node)); + set_ia32_ls_mode(new_op, get_ia32_ls_mode(node)); + if(is_ia32_use_frame(node)) { + set_ia32_frame_ent(new_op, get_ia32_frame_ent(node)); + set_ia32_use_frame(new_op); + } SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, node)); @@ -2806,7 +2761,6 @@ static ir_node *gen_lowered_Store(ia32_transform_env_t *env, construct_store_fun ir_node *new_op; \ FORCE_x87(env->cg); \ new_op = gen_binop(env, get_binop_left(env->irn), get_binop_right(env->irn), new_rd_ia32_##op); \ - set_ia32_am_support(get_Proj_pred(new_op), ia32_am_None); \ return new_op; \ } @@ -2836,7 +2790,6 @@ GEN_LOWERED_OP(SubC) GEN_LOWERED_OP(Sub) GEN_LOWERED_OP(Mul) GEN_LOWERED_OP(Eor) -GEN_LOWERED_x87_OP(vfdiv) GEN_LOWERED_x87_OP(vfprem) GEN_LOWERED_x87_OP(vfmul) GEN_LOWERED_x87_OP(vfsub) @@ -2848,6 +2801,30 @@ GEN_LOWERED_LOAD(Load, fp_none) GEN_LOWERED_STORE(vfist, fp_x87) GEN_LOWERED_STORE(Store, fp_none) +static ir_node *gen_ia32_l_vfdiv(ia32_transform_env_t *env) { + ir_node *noreg = ia32_new_NoReg_gp(env->cg); + ir_node *node = env->irn; + ir_node *left = get_binop_left(node); + ir_node *right = get_binop_right(node); + ir_mode *mode = env->mode; + ir_node *vfdiv; + ir_node *projs[pn_DivMod_max]; + + vfdiv = new_rd_ia32_vfdiv(env->dbg, env->irg, env->block, noreg, noreg, left, right, new_NoMem()); + clear_ia32_commutative(vfdiv); + set_ia32_am_support(vfdiv, ia32_am_Source); + set_ia32_res_mode(vfdiv, mode); + fold_immediate(env, vfdiv, 2, 3); + + ia32_collect_Projs(node, projs, pn_DivMod_max); + ia32_renumber_Proj(projs, pn_Div_M, pn_ia32_vfdiv_M); + ia32_renumber_Proj(projs, pn_Div_res, pn_ia32_vfdiv_res); + + FORCE_x87(env->cg); + + return vfdiv; +} + /** * Transforms a l_MulS into a "real" MulS node. * @@ -2855,29 +2832,25 @@ GEN_LOWERED_STORE(Store, fp_none) * @return the created ia32 MulS node */ static ir_node *gen_ia32_l_MulS(ia32_transform_env_t *env) { + ir_node *noreg = ia32_new_NoReg_gp(env->cg); + ir_node *left = get_binop_left(env->irn); + ir_node *right = get_binop_right(env->irn); + ir_mode *mode = env->mode; + ir_node *in[2]; /* l_MulS is already a mode_T node, so we create the MulS in the normal way */ /* and then skip the result Proj, because all needed Projs are already there. */ - ir_node *new_op = gen_binop(env, get_binop_left(env->irn), get_binop_right(env->irn), new_rd_ia32_MulS); - ir_node *muls = get_Proj_pred(new_op); - ir_node *proj; - - /* MulS cannot have AM for destination */ - if (get_ia32_am_support(muls) != ia32_am_None) - set_ia32_am_support(muls, ia32_am_Source); + ir_node *muls = new_rd_ia32_MulS(env->dbg, env->irg, env->block, noreg, noreg, left, right, new_NoMem()); + clear_ia32_commutative(muls); + set_ia32_am_support(muls, ia32_am_Source); + set_ia32_res_mode(muls, mode); + fold_immediate(env, muls, 2, 3); /* check if EAX and EDX proj exist, add missing one */ - proj = get_proj_for_pn(env->irn, pn_ia32_MulS_EAX); - if (! proj) { - proj = new_r_Proj(env->irg, env->block, muls, get_ia32_res_mode(env->irn), pn_ia32_MulS_EAX); - be_new_Keep(&ia32_reg_classes[CLASS_ia32_gp], env->irg, env->block, 1, &proj); - } - proj = get_proj_for_pn(env->irn, pn_ia32_MulS_EDX); - if (! proj) { - proj = new_r_Proj(env->irg, env->block, muls, get_ia32_res_mode(env->irn), pn_ia32_MulS_EDX); - be_new_Keep(&ia32_reg_classes[CLASS_ia32_gp], env->irg, env->block, 1, &proj); - } + in[0] = new_rd_Proj(env->dbg, env->irg, env->block, muls, mode, pn_EAX); + in[1] = new_rd_Proj(env->dbg, env->irg, env->block, muls, mode, pn_EDX); + be_new_Keep(&ia32_reg_classes[CLASS_ia32_gp], env->irg, env->block, 2, in); return muls; } @@ -2930,18 +2903,18 @@ static ir_node *gen_lowered_64bit_shifts(ia32_transform_env_t *env, ir_node *op1 DB((mod, LEVEL_1, "ShiftD with immediate ...")); if (is_ia32_l_ShlD(env->irn)) - new_op = new_rd_ia32_ShlD(dbg, irg, block, noreg, noreg, op1, op2, noreg, nomem); + new_op = new_rd_ia32_ShlD(dbg, irg, block, noreg, noreg, op1, op2, noreg, nomem, mode); else - new_op = new_rd_ia32_ShrD(dbg, irg, block, noreg, noreg, op1, op2, noreg, nomem); + new_op = new_rd_ia32_ShrD(dbg, irg, block, noreg, noreg, op1, op2, noreg, nomem, mode); set_ia32_Immop_attr(new_op, imm_op); } else { /* This is a normal ShiftD */ DB((mod, LEVEL_1, "ShiftD binop ...")); if (is_ia32_l_ShlD(env->irn)) - new_op = new_rd_ia32_ShlD(dbg, irg, block, noreg, noreg, op1, op2, count, nomem); + new_op = new_rd_ia32_ShlD(dbg, irg, block, noreg, noreg, op1, op2, count, nomem, mode); else - new_op = new_rd_ia32_ShrD(dbg, irg, block, noreg, noreg, op1, op2, count, nomem); + new_op = new_rd_ia32_ShrD(dbg, irg, block, noreg, noreg, op1, op2, count, nomem, mode); } /* set AM support */ @@ -2952,7 +2925,7 @@ static ir_node *gen_lowered_64bit_shifts(ia32_transform_env_t *env, ir_node *op1 set_ia32_res_mode(new_op, mode); set_ia32_emit_cl(new_op); - return new_rd_Proj(dbg, irg, block, new_op, mode, 0); + return new_op; } static ir_node *gen_ia32_l_ShlD(ia32_transform_env_t *env) { @@ -2984,7 +2957,6 @@ static ir_node *gen_ia32_l_X87toSSE(ia32_transform_env_t *env) { set_ia32_am_support(res, ia32_am_Dest); set_ia32_am_flavour(res, ia32_B); set_ia32_op_type(res, ia32_AddrModeD); - res = new_rd_Proj(env->dbg, env->irg, env->block, res, mode_M, pn_ia32_vfst_M); /* Load MEM -> SSE */ res = new_rd_ia32_xLoad(env->dbg, env->irg, env->block, ptr, noreg, res); @@ -3041,7 +3013,7 @@ static ir_node *gen_ia32_l_SSEtoX87(ia32_transform_env_t *env) { set_ia32_am_support(res, ia32_am_Dest); set_ia32_am_flavour(res, ia32_B); set_ia32_op_type(res, ia32_AddrModeD); - mem = new_rd_Proj(env->dbg, env->irg, env->block, res, mode_M, pn_ia32_xStore_M); + mem = res; } /* Load MEM -> x87 */ @@ -3123,12 +3095,13 @@ void ia32_register_transformers(void) { GEN(Not); GEN(Load); - GEN(Store); + //GEN(Store); GEN(Cond); GEN(CopyB); GEN(Mux); GEN(Psi); + GEN(Proj); /* transform ops from intrinsic lowering */ GEN(ia32_l_Add); @@ -3158,7 +3131,7 @@ void ia32_register_transformers(void) { IGN(Call); IGN(Alloc); - IGN(Proj); + //IGN(Proj); IGN(Block); IGN(Start); IGN(End); @@ -3193,7 +3166,7 @@ void ia32_register_transformers(void) { GEN(be_Call); GEN(be_Return); GEN(be_FrameLoad); - GEN(be_FrameStore); + //GEN(be_FrameStore); GEN(be_StackParam); GEN(be_AddSP); GEN(be_SubSP); @@ -3313,7 +3286,7 @@ static void transform_psi_cond(ir_node *cond, ir_mode *mode, ia32_code_gen_t *cg cmp_b = gen_sse_conv_f2d(cg, dbg, irg, block, cmp_b, cmp_b); } - new_op = new_rd_ia32_xCmp(dbg, irg, block, noreg, noreg, cmp_a, cmp_b, nomem); + new_op = new_rd_ia32_xCmp(dbg, irg, block, noreg, noreg, cmp_a, cmp_b, nomem, mode); set_ia32_pncode(new_op, pnc); SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(cg, cmp)); } @@ -3356,8 +3329,8 @@ static void transform_psi_cond(ir_node *cond, ir_mode *mode, ia32_code_gen_t *cg DEBUG_ONLY(tenv.mod = cg->mod;) new_op = gen_binop(&tenv, cmp_a, cmp_b, set_func); - set_ia32_pncode(get_Proj_pred(new_op), pnc); - set_ia32_am_support(get_Proj_pred(new_op), ia32_am_Source); + set_ia32_pncode(new_op, pnc); + set_ia32_am_support(new_op, ia32_am_Source); } /* the the new compare as in */ diff --git a/ir/be/ia32/ia32_x87.c b/ir/be/ia32/ia32_x87.c index e5a34d011..c5d5d89ae 100644 --- a/ir/be/ia32/ia32_x87.c +++ b/ir/be/ia32/ia32_x87.c @@ -977,8 +977,9 @@ static int sim_binop(x87_state *state, ir_node *n, const exchange_tmpl *tmpl) { } x87_set_st(state, arch_register_get_index(out), x87_patch_insn(n, dst), out_idx); - if (do_pop) + if (do_pop) { x87_pop(state); + } /* patch the operation */ attr = get_ia32_attr(n); -- 2.20.1