X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fia32%2Fia32_optimize.c;h=631f6e6c7b98f04481ab90be5120c08e321d11ae;hb=8694468860fe14808c20e9e246fe1368c097b322;hp=10dee2f13c0da96bba7d3f7a688469eabab07a3b;hpb=cfca4797175eb9f25889a6db5a37d2def39ff3fc;p=libfirm diff --git a/ir/be/ia32/ia32_optimize.c b/ir/be/ia32/ia32_optimize.c index 10dee2f13..631f6e6c7 100644 --- a/ir/be/ia32/ia32_optimize.c +++ b/ir/be/ia32/ia32_optimize.c @@ -33,6 +33,13 @@ #include "ia32_transform.h" #include "ia32_dbg_stat.h" +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_t; + #undef is_NoMem #define is_NoMem(irn) (get_irn_op(irn) == op_NoMem) @@ -145,7 +152,7 @@ static entity *get_entity_for_tv(ia32_code_gen_t *cg, ir_node *cnst) if (tp == firm_unknown_type) tp = get_prim_type(cg->isa->types, mode); - res = new_entity(get_glob_type(), unique_id("ia32FloatCnst_%u"), tp); + res = new_entity(get_glob_type(), unique_id(".LC%u"), tp); set_entity_ld_ident(res, get_entity_ident(res)); set_entity_visibility(res, visibility_local); @@ -736,11 +743,11 @@ static int is_addr_candidate(const ir_node *block, const ir_node *irn) { * @param h The height information of the irg * @param block The block the Loads must/mustnot be in * @param irn The irn to check - * return 1 if irn is a candidate, 0 otherwise + * return 0 if irn is no candidate, 1 if left load can be used, 2 if right one, 3 for both */ -static int is_am_candidate(heights_t *h, const ir_node *block, ir_node *irn) { +static ia32_am_cand_t is_am_candidate(heights_t *h, const ir_node *block, ir_node *irn) { ir_node *in, *load, *other, *left, *right; - int n, is_cand = 0; + int n, is_cand = 0, cand; if (is_ia32_Ld(irn) || is_ia32_St(irn) || is_ia32_Store8Bit(irn)) return 0; @@ -758,11 +765,15 @@ static int is_am_candidate(heights_t *h, const ir_node *block, ir_node *irn) { other = right; /* If there is a data dependency of other irn from load: cannot use AM */ - if (get_nodes_block(other) == block) - is_cand = heights_reachable_in_block(h, load, other) ? 0 : is_cand; + if (get_nodes_block(other) == block) { + other = skip_Proj(other); + is_cand = heights_reachable_in_block(h, other, load) ? 0 : is_cand; + } } - in = right; + cand = is_cand ? IA32_AM_CAND_LEFT : IA32_AM_CAND_NONE; + in = right; + is_cand = 0; if (pred_is_specific_nodeblock(block, in, is_ia32_Ld)) { n = ia32_get_irn_n_edges(in); @@ -772,13 +783,16 @@ static int is_am_candidate(heights_t *h, const ir_node *block, ir_node *irn) { other = left; /* If there is a data dependency of other irn from load: cannot use load */ - if (get_nodes_block(other) == block) - is_cand = heights_reachable_in_block(h, load, other) ? 0 : is_cand; + if (get_nodes_block(other) == block) { + other = skip_Proj(other); + is_cand = heights_reachable_in_block(h, other, load) ? 0 : is_cand; + } } - is_cand = get_ia32_frame_ent(irn) ? 0 : is_cand; + cand = is_cand ? (cand | IA32_AM_CAND_RIGHT) : cand; - return is_cand; + /* if the irn has a frame entity: we do not use address mode */ + return get_ia32_frame_ent(irn) ? IA32_AM_CAND_NONE : cand; } /** @@ -1325,9 +1339,6 @@ static void optimize_lea(ir_node *irn, void *env) { const ir_edge_t *edge, *ne; ir_node *src; - if (get_irn_node_nr(irn) == 2324) - __asm int 3 - /* merge all Loads/Stores connected to this LEA with the LEA */ foreach_out_edge_safe(left, edge, ne) { src = get_edge_src_irn(edge); @@ -1354,7 +1365,7 @@ static void optimize_am(ir_node *irn, void *env) { ia32_code_gen_t *cg = am_opt_env->cg; heights_t *h = am_opt_env->h; ir_node *block, *noreg_gp, *noreg_fp; - ir_node *left, *right, *temp; + ir_node *left, *right; ir_node *store, *load, *mem_proj; ir_node *succ, *addr_b, *addr_i; int check_am_src = 0; @@ -1384,7 +1395,15 @@ static void optimize_am(ir_node *irn, void *env) { /* - 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) && ! is_ia32_Lea(irn) && is_am_candidate(h, block, irn)) { + if ((get_ia32_am_support(irn) != ia32_am_None) && ! is_ia32_Lea(irn)) { + ia32_am_cand_t cand = is_am_candidate(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; + DBG((mod, LEVEL_1, "\tfound address mode candidate %+F ... ", irn)); left = get_irn_n(irn, 2); @@ -1397,25 +1416,25 @@ static void optimize_am(ir_node *irn, void *env) { } /* normalize commutative ops */ - if (node_is_ia32_comm(irn)) { + if (node_is_ia32_comm(irn) && (cand == IA32_AM_CAND_LEFT)) { + /* Assure that right operand is always a Load if there is one */ /* because non-commutative ops can only use Dest AM if the right */ /* operand is a load, so we only need to check right operand. */ - if (pred_is_specific_nodeblock(block, left, is_ia32_Ld)) - { - exchange_left_right(irn, &left, &right, 3, 2); - need_exchange_on_fail = 1; - } + + exchange_left_right(irn, &left, &right, 3, 2); + need_exchange_on_fail = 1; + + /* now: load is right */ + cand = IA32_AM_CAND_RIGHT; } /* check for Store -> op -> Load */ /* 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) && - pred_is_specific_nodeblock(block, right, is_ia32_Ld)) + if ((get_ia32_am_support(irn) & ia32_am_Dest) && (cand & IA32_AM_CAND_RIGHT)) { - /* 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, */ @@ -1444,24 +1463,14 @@ static void optimize_am(ir_node *irn, void *env) { /* Extra check for commutative ops with two Loads */ /* -> put the interesting Load right */ - if (node_is_ia32_comm(irn) && - pred_is_specific_nodeblock(block, left, is_ia32_Ld)) - { + if (node_is_ia32_comm(irn) && (cand == IA32_AM_CAND_BOTH)) { if ((addr_b == get_irn_n(get_Proj_pred(left), 0)) && (addr_i == get_irn_n(get_Proj_pred(left), 1))) { /* We exchange left and right, so it's easier to kill */ /* the correct Load later and to handle unary operations. */ - set_irn_n(irn, 2, right); - set_irn_n(irn, 3, left); - - temp = left; - left = right; - right = temp; - - /* this is only needed for Compares, but currently ALL nodes - * have this attribute :-) */ - set_ia32_pncode(irn, get_inversed_pnc(get_ia32_pncode(irn))); + exchange_left_right(irn, &left, &right, 3, 2); + need_exchange_on_fail ^= 1; } } @@ -1513,6 +1522,8 @@ static void optimize_am(ir_node *irn, void *env) { 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) { @@ -1526,27 +1537,32 @@ static void optimize_am(ir_node *irn, void *env) { } /* was exchanged but optimize failed: exchange back */ - if (check_am_src && need_exchange_on_fail) + if (need_exchange_on_fail) { exchange_left_right(irn, &left, &right, 3, 2); + cand = orig_cand; + } need_exchange_on_fail = 0; /* normalize commutative ops */ - if (check_am_src && node_is_ia32_comm(irn)) { + if (check_am_src && node_is_ia32_comm(irn) && (cand == IA32_AM_CAND_RIGHT)) { + /* Assure that left operand is always a Load if there is one */ /* because non-commutative ops can only use Source AM if the */ /* left operand is a Load, so we only need to check the left */ /* operand afterwards. */ - if (pred_is_specific_nodeblock(block, right, is_ia32_Ld)) { - exchange_left_right(irn, &left, &right, 3, 2); - need_exchange_on_fail = 1; - } + + exchange_left_right(irn, &left, &right, 3, 2); + need_exchange_on_fail = 1; + + /* now: load is left */ + cand = IA32_AM_CAND_LEFT; } /* optimize op -> Load iff Load is only used by this op */ /* and left operand is a Load which only used by this irn */ - if (check_am_src && - pred_is_specific_nodeblock(block, left, is_ia32_Ld) && + if (check_am_src && + (cand & IA32_AM_CAND_LEFT) && (ia32_get_irn_n_edges(left) == 1)) { left = get_Proj_pred(left);