X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fia32%2Fia32_finish.c;h=45f616b2c7e1c9f8525227da29363741bf8f45fa;hb=afa44cc5648401a50c08458622b50de4256498c2;hp=9965d332768ffefe44b123c2bb555f3bad8f879a;hpb=b417fff717bf133a1b46d57bf5dec9c1c0f74951;p=libfirm diff --git a/ir/be/ia32/ia32_finish.c b/ir/be/ia32/ia32_finish.c index 9965d3327..45f616b2c 100644 --- a/ir/be/ia32/ia32_finish.c +++ b/ir/be/ia32/ia32_finish.c @@ -4,6 +4,10 @@ * $Id$ */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include "irnode.h" #include "ircons.h" #include "irgmod.h" @@ -33,7 +37,7 @@ static void ia32_transform_sub_to_neg_add(ir_node *irn, ia32_code_gen_t *cg) { const arch_register_t *in1_reg, *in2_reg, *out_reg, **slots; /* Return if AM node or not a Sub or xSub */ - if (get_ia32_op_type(irn) != ia32_Normal || !(is_ia32_Sub(irn) || is_ia32_xSub(irn))) + if (!(is_ia32_Sub(irn) || is_ia32_xSub(irn)) || get_ia32_op_type(irn) != ia32_Normal) return; noreg = ia32_new_NoReg_gp(cg); @@ -59,6 +63,7 @@ static void ia32_transform_sub_to_neg_add(ir_node *irn, ia32_code_gen_t *cg) { 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 */ @@ -100,9 +105,10 @@ static void ia32_transform_lea_to_add(ir_node *irn, ia32_code_gen_t *cg) { int imm = 0; ir_node *res = NULL; ir_node *nomem, *noreg, *base, *index, *op1, *op2; - char *offs; + const char *offs = NULL; ia32_transform_env_t tenv; const arch_register_t *out_reg, *base_reg, *index_reg; + int imm_tp = ia32_ImmConst; /* must be a LEA */ if (! is_ia32_Lea(irn)) @@ -124,11 +130,20 @@ static void ia32_transform_lea_to_add(ir_node *irn, ia32_code_gen_t *cg) { base = get_irn_n(irn, 0); index = get_irn_n(irn,1); - offs = get_ia32_am_offs(irn); + if (am_flav & ia32_O) { + offs = get_ia32_am_offs(irn); - /* offset has a explicit sign -> we need to skip + */ - if (offs && offs[0] == '+') - offs++; + if (! offs) { + ident *id = get_ia32_am_sc(irn); + + assert(id != NULL); + offs = get_id_str(id); + imm_tp = ia32_ImmSymConst; + } + /* offset has a explicit sign -> we need to skip + */ + else if (offs[0] == '+') + offs++; + } out_reg = arch_get_irn_register(cg->arch_env, irn); base_reg = arch_get_irn_register(cg->arch_env, base); @@ -192,7 +207,7 @@ static void ia32_transform_lea_to_add(ir_node *irn, ia32_code_gen_t *cg) { if (imm) { set_ia32_cnst(res, offs); - set_ia32_immop_type(res, ia32_ImmConst); + set_ia32_immop_type(res, imm_tp); } SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(cg, irn)); @@ -220,6 +235,7 @@ static INLINE int need_constraint_copy(ir_node *irn) { ! is_ia32_Conv_I2I(irn) && \ ! is_ia32_Conv_I2I8Bit(irn) && \ ! is_ia32_CmpCMov(irn) && \ + ! is_ia32_PsiCondCMov(irn) && \ ! is_ia32_CmpSet(irn); } @@ -298,10 +314,37 @@ insert_copy: } } - /* If we have a CondJmp/CmpSet/xCmpSet with immediate, we need to */ - /* check if it's the right operand, otherwise we have */ - /* to change it, as CMP doesn't support immediate as */ - /* left operands. */ + /* check xCmp: try to avoid unordered cmp */ + if ((is_ia32_xCmp(irn) || is_ia32_xCmpCMov(irn) || is_ia32_xCmpSet(irn)) && + op_tp == ia32_Normal && + ! is_ia32_ImmConst(irn) && ! is_ia32_ImmSymConst(irn)) + { + long pnc = get_ia32_pncode(irn); + + if (pnc & pn_Cmp_Uo) { + ir_node *tmp; + int idx1 = 2, idx2 = 3; + + if (is_ia32_xCmpCMov(irn)) { + idx1 = 0; + idx2 = 1; + } + + tmp = get_irn_n(irn, idx1); + set_irn_n(irn, idx1, get_irn_n(irn, idx2)); + set_irn_n(irn, idx2, tmp); + + set_ia32_pncode(irn, get_negated_pnc(pnc, mode_D)); + } + } + + /* + If we have a CondJmp/CmpSet/xCmpSet with immediate, + we need to check if it's the right operand, otherwise + we have to change it, as CMP doesn't support immediate + as left operands. + */ +#if 0 if ((is_ia32_CondJmp(irn) || is_ia32_CmpSet(irn) || is_ia32_xCmpSet(irn)) && (is_ia32_ImmConst(irn) || is_ia32_ImmSymConst(irn)) && op_tp == ia32_AddrModeS) @@ -309,17 +352,9 @@ insert_copy: set_ia32_op_type(irn, ia32_AddrModeD); set_ia32_pncode(irn, get_inversed_pnc(get_ia32_pncode(irn))); } - - /* check if there is a sub which need to be transformed */ - ia32_transform_sub_to_neg_add(irn, cg); - - /* transform a LEA into an Add if possible */ - ia32_transform_lea_to_add(irn, cg); +#endif } -end: - - /* check for peephole optimization */ - ia32_peephole_optimization(irn, cg); +end: ; } /** @@ -332,7 +367,7 @@ end: */ static void fix_am_source(ir_node *irn, void *env) { ia32_code_gen_t *cg = env; - ir_node *base, *index; + ir_node *base, *index, *noreg; const arch_register_t *reg_base, *reg_index; const ia32_register_req_t **reqs; int n_res, i; @@ -340,6 +375,9 @@ static void fix_am_source(ir_node *irn, void *env) { /* check only ia32 nodes with source address mode */ if (! is_ia32_irn(irn) || get_ia32_op_type(irn) != ia32_AddrModeS) return; + /* no need to fix unary operations */ + if (get_irn_arity(irn) == 4) + return; base = get_irn_n(irn, 0); index = get_irn_n(irn, 1); @@ -348,6 +386,8 @@ static void fix_am_source(ir_node *irn, void *env) { reg_index = arch_get_irn_register(cg->arch_env, index); reqs = get_ia32_out_req_all(irn); + noreg = ia32_new_NoReg_gp(cg); + n_res = get_ia32_n_res(irn); for (i = 0; i < n_res; i++) { @@ -410,6 +450,8 @@ static void fix_am_source(ir_node *irn, void *env) { set_irn_n(irn, 3, load); /* this is a normal node now */ + set_irn_n(irn, 0, noreg); + set_irn_n(irn, 1, noreg); set_ia32_op_type(irn, ia32_Normal); break; @@ -427,6 +469,18 @@ static void ia32_finish_irg_walker(ir_node *block, void *env) { fix_am_source(irn, env); } + for (irn = sched_first(block); ! sched_is_end(irn); irn = next) { + ia32_code_gen_t *cg = env; + + next = sched_next(irn); + + /* check if there is a sub which need to be transformed */ + ia32_transform_sub_to_neg_add(irn, cg); + + /* transform a LEA into an Add if possible */ + ia32_transform_lea_to_add(irn, cg); + } + /* second: insert copies and finish irg */ for (irn = sched_first(block); ! sched_is_end(irn); irn = next) { next = sched_next(irn);