X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fia32%2Fia32_transform.c;h=c32c060f03ccfe89de6bb0eaa83460bea400418a;hb=4bdf858cdb11749577b89e449b9665e6fc6ab5e8;hp=17e7855a0637f93c749d8dfa35b752f9aede2d60;hpb=2f10d96357f98a6d313d35aee8c49ca3caa4752a;p=libfirm diff --git a/ir/be/ia32/ia32_transform.c b/ir/be/ia32/ia32_transform.c index 17e7855a0..c32c060f0 100644 --- a/ir/be/ia32/ia32_transform.c +++ b/ir/be/ia32/ia32_transform.c @@ -99,7 +99,7 @@ static ir_node *get_proj_for_pn(const ir_node *irn, long pn) { } /* Generates an entity for a known FP const (used for FP Neg + Abs) */ -static const char *gen_fp_known_const(ir_mode *mode, ia32_known_const_t kct) { +static ident *gen_fp_known_const(ir_mode *mode, ia32_known_const_t kct) { static const struct { const char *tp_name; const char *ent_name; @@ -145,7 +145,8 @@ static const char *gen_fp_known_const(ir_mode *mode, ia32_known_const_t kct) { /* cache the entry */ ent_cache[kct] = ent; } - return ent_name; + + return get_entity_ident(ent_cache[kct]); } #ifndef NDEBUG @@ -544,7 +545,7 @@ static ir_node *gen_Mulh(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) /* to be on the save side */ set_Proj_proj(proj_EAX, pn_EAX); - if (get_ia32_cnst(mulh)) { + if (is_ia32_ImmConst(mulh) || is_ia32_ImmSymConst(mulh)) { /* Mulh with const cannot have AM */ set_ia32_am_support(mulh, ia32_am_None); } @@ -908,9 +909,16 @@ static ir_node *gen_Quot(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) ir_node *nomem = new_rd_NoMem(env->irg); ir_node *new_op; - new_op = new_rd_ia32_fDiv(env->dbg, env->irg, env->block, noreg, noreg, op1, op2, nomem, mode_T); + if (is_ia32_fConst(op2)) { + new_op = new_rd_ia32_fDiv(env->dbg, env->irg, env->block, noreg, noreg, op1, noreg, nomem, mode_T); + set_ia32_am_support(new_op, ia32_am_None); + set_ia32_Immop_attr(new_op, op2); + } + else { + new_op = new_rd_ia32_fDiv(env->dbg, env->irg, env->block, noreg, noreg, op1, op2, nomem, mode_T); + set_ia32_am_support(new_op, ia32_am_Source); + } set_ia32_res_mode(new_op, get_irn_mode(get_proj_for_pn(env->irn, pn_Quot_res))); - set_ia32_am_support(new_op, ia32_am_Source); SET_IA32_ORIG_NODE(new_op, get_old_node_name(env)); @@ -1046,7 +1054,7 @@ static ir_node *gen_Rot(ia32_transform_env_t *env, ir_node *op1, ir_node *op2) { * @return The created ia32 Minus node */ static ir_node *gen_Minus(ia32_transform_env_t *env, ir_node *op) { - const char *name; + ident *name; ir_node *new_op; ir_node *noreg_gp = ia32_new_NoReg_gp(env->cg); ir_node *noreg_fp = ia32_new_NoReg_fp(env->cg); @@ -1064,6 +1072,7 @@ static ir_node *gen_Minus(ia32_transform_env_t *env, ir_node *op) { SET_IA32_ORIG_NODE(new_op, get_old_node_name(env)); set_ia32_res_mode(new_op, env->mode); + set_ia32_immop_type(new_op, ia32_ImmSymConst); new_op = new_rd_Proj(env->dbg, env->irg, env->block, new_op, env->mode, 0); } @@ -1115,7 +1124,7 @@ static ir_node *gen_Abs(ia32_transform_env_t *env, ir_node *op) { ir_node *noreg_fp = ia32_new_NoReg_fp(env->cg); ir_node *nomem = new_NoMem(); int size; - const char *name; + ident *name; if (mode_is_float(mode)) { res = new_rd_ia32_fAnd(dbg,irg, block, noreg_gp, noreg_gp, op, noreg_fp, nomem, mode_T); @@ -1128,6 +1137,7 @@ static ir_node *gen_Abs(ia32_transform_env_t *env, ir_node *op) { SET_IA32_ORIG_NODE(res, get_old_node_name(env)); set_ia32_res_mode(res, mode); + set_ia32_immop_type(res, ia32_ImmSymConst); res = new_rd_Proj(dbg, irg, block, res, mode, 0); } @@ -1167,21 +1177,36 @@ static ir_node *gen_Abs(ia32_transform_env_t *env, ir_node *op) { * @return the created ia32 Load node */ static ir_node *gen_Load(ia32_transform_env_t *env) { - ir_node *node = env->irn; - ir_node *noreg = ia32_new_NoReg_gp(env->cg); - ir_mode *mode = get_Load_mode(node); + ir_node *node = env->irn; + ir_node *noreg = ia32_new_NoReg_gp(env->cg); + ir_node *ptr = get_Load_ptr(node); + ir_mode *mode = get_Load_mode(node); + const char *offs = NULL; ir_node *new_op; + ia32_am_flavour_t am_flav = ia32_B; + + /* address might be a constant (symconst or absolute address) */ + if (is_ia32_Const(ptr)) { + offs = get_ia32_cnst(ptr); + ptr = noreg; + } if (mode_is_float(mode)) { - new_op = new_rd_ia32_fLoad(env->dbg, env->irg, env->block, get_Load_ptr(node), noreg, get_Load_mem(node), env->mode); + new_op = new_rd_ia32_fLoad(env->dbg, env->irg, env->block, ptr, noreg, get_Load_mem(node), env->mode); } else { - new_op = new_rd_ia32_Load(env->dbg, env->irg, env->block, get_Load_ptr(node), noreg, get_Load_mem(node), env->mode); + new_op = new_rd_ia32_Load(env->dbg, env->irg, env->block, ptr, noreg, get_Load_mem(node), env->mode); + } + + /* base is an constant address */ + if (offs) { + add_ia32_am_offs(new_op, offs); + am_flav = ia32_O; } 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_am_flavour(new_op, am_flav); set_ia32_ls_mode(new_op, mode); SET_IA32_ORIG_NODE(new_op, get_old_node_name(env)); @@ -1201,20 +1226,40 @@ static ir_node *gen_Load(ia32_transform_env_t *env) { * @return the created ia32 Store node */ static ir_node *gen_Store(ia32_transform_env_t *env) { - ir_node *node = env->irn; - ir_node *noreg = ia32_new_NoReg_gp(env->cg); - ir_node *val = get_Store_value(node); - ir_node *ptr = get_Store_ptr(node); - ir_node *mem = get_Store_mem(node); - ir_mode *mode = get_irn_mode(val); - ir_node *sval = val; + ir_node *node = env->irn; + ir_node *noreg = ia32_new_NoReg_gp(env->cg); + ir_node *val = get_Store_value(node); + ir_node *ptr = get_Store_ptr(node); + ir_node *mem = get_Store_mem(node); + ir_mode *mode = get_irn_mode(val); + ir_node *sval = val; + const char *offs = NULL; ir_node *new_op; + ia32_am_flavour_t am_flav = ia32_B; + ia32_immop_type_t immop = ia32_ImmNone; /* in case of storing a const (but not a symconst) -> make it an attribute */ - if (is_ia32_Const(val)) { + if (is_ia32_Cnst(val)) { + switch (get_ia32_op_type(val)) { + case ia32_Const: + immop = ia32_ImmConst; + break; + case ia32_SymConst: + immop = ia32_ImmSymConst; + break; + default: + assert(0 && "unsupported Const type"); + } + sval = noreg; } + /* address might be a constant (symconst or absolute address) */ + if (is_ia32_Const(ptr)) { + offs = get_ia32_cnst(ptr); + ptr = noreg; + } + if (mode_is_float(mode)) { new_op = new_rd_ia32_fStore(env->dbg, env->irg, env->block, ptr, noreg, sval, mem, mode_T); } @@ -1226,14 +1271,21 @@ static ir_node *gen_Store(ia32_transform_env_t *env) { } /* stored const is an attribute (saves a register) */ - if (is_ia32_Const(val)) { + if (is_ia32_Cnst(val)) { set_ia32_Immop_attr(new_op, val); } + /* base is an constant address */ + if (offs) { + add_ia32_am_offs(new_op, offs); + am_flav = ia32_O; + } + 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_am_flavour(new_op, am_flav); set_ia32_ls_mode(new_op, get_irn_mode(val)); + set_ia32_immop_type(new_op, immop); SET_IA32_ORIG_NODE(new_op, get_old_node_name(env)); @@ -1274,20 +1326,22 @@ static ir_node *gen_Cond(ia32_transform_env_t *env) { expr = get_expr_op(cmp_a, cmp_b); if (cnst && expr) { - if (mode_is_int(get_irn_mode(expr))) { + pn_Cmp pnc = get_Proj_proj(sel); + + if ((pnc == pn_Cmp_Eq || pnc == pn_Cmp_Lg) && mode_is_int(get_irn_mode(expr))) { if (classify_tarval(get_ia32_Immop_tarval(cnst)) == TV_CLASSIFY_NULL) { - /* a Cmp A, 0 */ - ir_node *op1 = expr; - ir_node *op2 = expr; - ir_node *and = skip_Proj(expr); - char *cnst = NULL; + /* a Cmp A =/!= 0 */ + ir_node *op1 = expr; + ir_node *op2 = expr; + ir_node *and = skip_Proj(expr); + const char *cnst = NULL; /* check, if expr is an only once used And operation */ if (get_irn_n_edges(expr) == 1 && is_ia32_And(and)) { op1 = get_irn_n(and, 2); op2 = get_irn_n(and, 3); - cnst = get_ia32_cnst(and); + cnst = (is_ia32_ImmConst(and) || is_ia32_ImmSymConst(and)) ? get_ia32_cnst(and) : NULL; } res = new_rd_ia32_TestJmp(dbg, irg, block, op1, op2, mode_T); set_ia32_pncode(res, get_Proj_proj(sel)); @@ -1367,6 +1421,7 @@ static ir_node *gen_CopyB(ia32_transform_env_t *env) { else { res = new_rd_ia32_CopyB_i(dbg, irg, block, dst, src, mem, mode); set_ia32_Immop_tarval(res, new_tarval_from_long(size, mode_Is)); + set_ia32_immop_type(res, ia32_ImmConst); } SET_IA32_ORIG_NODE(res, get_old_node_name(env)); @@ -1563,6 +1618,12 @@ static ir_node *gen_StackParam(ia32_transform_env_t *env) { entity *ent = be_get_frame_entity(node); ir_mode *mode = env->mode; + /* If the StackParam has only one user -> */ + /* put it in the Block where the user resides */ + if (get_irn_n_edges(node) == 1) { + env->block = get_nodes_block(get_edge_src_irn(get_irn_out_edge_first(node))); + } + if (mode_is_float(mode)) { new_op = new_rd_ia32_fLoad(env->dbg, env->irg, env->block, ptr, noreg, mem, mode_T); } @@ -1597,6 +1658,7 @@ static ir_node *gen_FrameAddr(ia32_transform_env_t *env) { set_ia32_frame_ent(new_op, be_get_frame_entity(node)); set_ia32_am_support(new_op, ia32_am_Full); set_ia32_use_frame(new_op); + set_ia32_immop_type(new_op, ia32_ImmConst); SET_IA32_ORIG_NODE(new_op, get_old_node_name(env)); @@ -1842,8 +1904,10 @@ void ia32_transform_lea_to_add(ir_node *irn, ia32_code_gen_t *cg) { arch_set_irn_register(cg->arch_env, res, out_reg); set_ia32_op_type(res, ia32_Normal); - if (imm) + if (imm) { set_ia32_cnst(res, offs); + set_ia32_immop_type(res, ia32_ImmConst); + } SET_IA32_ORIG_NODE(res, get_old_node_name(&tenv));