X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fir%2Firopt.c;h=b0bb50f6b507d095efc7309e12522b161bc845a2;hb=b84d550997d07bfcc4d828e8fbb5742098e050e4;hp=d9ec66d4eebdefe100a6aa653ab855bc92bd6024;hpb=c3f885132674f7cd7d0c77aa89cef69a537a0171;p=libfirm diff --git a/ir/ir/iropt.c b/ir/ir/iropt.c index d9ec66d4e..b0bb50f6b 100644 --- a/ir/ir/iropt.c +++ b/ir/ir/iropt.c @@ -106,6 +106,51 @@ static tarval *computed_value_Sub(ir_node *n) return tarval_bad; } +/** + * return the value of a Carry + * Special : a op 0, 0 op b + */ +static tarval *computed_value_Carry(ir_node *n) +{ + ir_node *a = get_binop_left(n); + ir_node *b = get_binop_right(n); + ir_mode *m = get_irn_mode(n); + + tarval *ta = value_of(a); + tarval *tb = value_of(b); + + if ((ta != tarval_bad) && (tb != tarval_bad)) { + tarval_add(ta, tb); + return tarval_carry() ? get_mode_one(m) : get_mode_null(m); + } else { + if ( (classify_tarval(ta) == TV_CLASSIFY_NULL) + || (classify_tarval(tb) == TV_CLASSIFY_NULL)) + return get_mode_null(m); + } + return tarval_bad; +} + +/** + * return the value of a Borrow + * Special : a op 0 + */ +static tarval *computed_value_Borrow(ir_node *n) +{ + ir_node *a = get_binop_left(n); + ir_node *b = get_binop_right(n); + ir_mode *m = get_irn_mode(n); + + tarval *ta = value_of(a); + tarval *tb = value_of(b); + + if ((ta != tarval_bad) && (tb != tarval_bad)) { + return tarval_cmp(ta, tb) == pn_Cmp_Lt ? get_mode_one(m) : get_mode_null(m); + } else if (classify_tarval(ta) == TV_CLASSIFY_NULL) { + return get_mode_null(m); + } + return tarval_bad; +} + /** * return the value of an unary Minus */ @@ -573,6 +618,16 @@ static tarval *computed_value_Mux(ir_node *n) return tarval_bad; } +/** + * Calculate the value of a Psi: can be evaluated, if a condition is true + * and all previous conditions are false. If all conditions are false + * we evaluate to the default one. + */ +static tarval *computed_value_Psi(ir_node *n) +{ + return tarval_bad; +} + /** * calculate the value of a Confirm: can be evaluated, * if it has the form Confirm(x, '=', Const). @@ -631,9 +686,12 @@ static ir_op_ops *firm_set_default_computed_value(opcode code, ir_op_ops *ops) CASE(Shr); CASE(Shrs); CASE(Rot); + CASE(Carry); + CASE(Borrow); CASE(Conv); CASE(Proj); CASE(Mux); + CASE(Psi); CASE(Confirm); default: /* leave NULL */; @@ -643,25 +701,6 @@ static ir_op_ops *firm_set_default_computed_value(opcode code, ir_op_ops *ops) #undef CASE } -#if 0 -/* returns 1 if the a and b are pointers to different locations. */ -static bool -different_identity (ir_node *a, ir_node *b) -{ - assert (mode_is_reference(get_irn_mode (a)) - && mode_is_reference(get_irn_mode (b))); - - if (get_irn_op (a) == op_Proj && get_irn_op(b) == op_Proj) { - ir_node *a1 = get_Proj_pred (a); - ir_node *b1 = get_Proj_pred (b); - if (a1 != b1 && get_irn_op (a1) == op_Alloc - && get_irn_op (b1) == op_Alloc) - return 1; - } - return 0; -} -#endif - /** * Returns a equivalent block for another block. * If the block has only one predecessor, this is @@ -734,8 +773,8 @@ static ir_node *equivalent_node_Block(ir_node *n) } } else if (get_opt_unreachable_code() && - (n != current_ir_graph->start_block) && - (n != current_ir_graph->end_block) ) { + (n != get_irg_start_block(current_ir_graph)) && + (n != get_irg_end_block(current_ir_graph)) ) { int i; /* If all inputs are dead, this block is dead too, except if it is @@ -1140,12 +1179,13 @@ static ir_node *equivalent_node_Cast(ir_node *n) { return n; } -/* Several optimizations: +/** + Several optimizations: - no Phi in start block. - remove Id operators that are inputs to Phi - fold Phi-nodes, iff they have only one predecessor except themselves. -*/ + */ static ir_node *equivalent_node_Phi(ir_node *n) { int i, n_preds; @@ -1153,7 +1193,6 @@ static ir_node *equivalent_node_Phi(ir_node *n) ir_node *oldn = n; ir_node *block = NULL; /* to shutup gcc */ ir_node *first_val = NULL; /* to shutup gcc */ - ir_node *scnd_val = NULL; /* to shutup gcc */ if (!get_opt_normalize()) return n; @@ -1163,8 +1202,8 @@ static ir_node *equivalent_node_Phi(ir_node *n) /* @@@ fliegt 'raus, sollte aber doch immer wahr sein!!! assert(get_irn_arity(block) == n_preds && "phi in wrong block!"); */ if ((is_Block_dead(block)) || /* Control dead */ - (block == current_ir_graph->start_block)) /* There should be no Phi nodes */ - return new_Bad(); /* in the Start Block. */ + (block == get_irg_start_block(current_ir_graph))) /* There should be no Phi nodes */ + return new_Bad(); /* in the Start Block. */ if (n_preds == 0) return n; /* Phi of dead Region without predecessors. */ @@ -1190,12 +1229,10 @@ static ir_node *equivalent_node_Phi(ir_node *n) return new_Bad(); } - scnd_val = NULL; - - /* follow_Id () for rest of inputs, determine if any of these + /* search for rest of inputs, determine if any of these are non-self-referencing */ while (++i < n_preds) { - scnd_val = get_Phi_pred(n, i); + ir_node *scnd_val = get_Phi_pred(n, i); if ( (scnd_val != n) && (scnd_val != first_val) #if 1 @@ -1210,10 +1247,57 @@ static ir_node *equivalent_node_Phi(ir_node *n) /* Fold, if no multiple distinct non-self-referencing inputs */ n = first_val; DBG_OPT_PHI(oldn, n); - } else { - /* skip the remaining Ids (done in get_Phi_pred). */ - /* superfluous, since we walk all to propagate Block's Bads. - while (++i < n_preds) get_Phi_pred(n, i); */ + } + return n; +} + +/** + Several optimizations: + - no Sync in start block. + - fold Sync-nodes, iff they have only one predecessor except + themselves. + @fixme: are there loop's in Sync's + */ +static ir_node *equivalent_node_Sync(ir_node *n) +{ + int i, n_preds; + + ir_node *oldn = n; + ir_node *first_val = NULL; /* to shutup gcc */ + + if (!get_opt_normalize()) return n; + + n_preds = get_Sync_n_preds(n); + + /* Find first non-self-referencing input */ + for (i = 0; i < n_preds; ++i) { + first_val = get_Sync_pred(n, i); + if ((first_val != n) /* not self pointer */ && + (! is_Bad(first_val)) + ) { /* value not dead */ + break; /* then found first value. */ + } + } + + if (i >= n_preds) + /* A totally Bad or self-referencing Sync (we didn't break the above loop) */ + return new_Bad(); + + /* search the rest of inputs, determine if any of these + are non-self-referencing */ + while (++i < n_preds) { + ir_node *scnd_val = get_Sync_pred(n, i); + if ((scnd_val != n) && + (scnd_val != first_val) && + (! is_Bad(scnd_val)) + ) + break; + } + + if (i >= n_preds) { + /* Fold, if no multiple distinct non-self-referencing inputs */ + n = first_val; + DBG_OPT_SYNC(oldn, n); } return n; } @@ -1250,7 +1334,7 @@ static ir_node *equivalent_node_Proj(ir_node *n) /* get the load/store address */ ir_node *addr = get_irn_n(a, 1); if (value_not_null(addr)) { - /* this node may float */ + /* this node may float if it did not depend on a Confirm */ set_irn_pinned(a, op_pin_state_floats); DBG_OPT_EXC_REM(n); return new_Bad(); @@ -1349,6 +1433,15 @@ static ir_node *equivalent_node_Mux(ir_node *n) return n; } +/** + * Returns a equivalent node of a Psi: if a condition is true + * and all previous conditions are false we know its value. + * If all conditions are false its value is the default one. + */ +static ir_node *equivalent_node_Psi(ir_node *n) { + return n; +} + /** * Optimize -a CMP -b into b CMP a. * This works only for for modes where unary Minus @@ -1416,7 +1509,7 @@ static ir_node *equivalent_node_CopyB(ir_node *n) turn_into_tuple(n, pn_CopyB_max); set_Tuple_pred(n, pn_CopyB_M, mem); set_Tuple_pred(n, pn_CopyB_X_except, new_Bad()); /* no exception */ - set_Tuple_pred(n, pn_Call_M_except, new_Bad()); + set_Tuple_pred(n, pn_CopyB_M_except, new_Bad()); } return n; } @@ -1521,9 +1614,11 @@ static ir_op_ops *firm_set_default_equivalent_node(opcode code, ir_op_ops *ops) CASE(Conv); CASE(Cast); CASE(Phi); + CASE(Sync); CASE(Proj); CASE(Id); CASE(Mux); + CASE(Psi); CASE(Cmp); CASE(Confirm); CASE(CopyB); @@ -1684,7 +1779,8 @@ static ir_node *transform_node_Add(ir_node *n) mode); DBG_OPT_ALGSIM0(oldn, n, FS_OPT_ADD_A_MINUS_B); } - else if (get_irn_op(a) == op_Mul) { + /* do NOT execute this code if reassociation is enabled, it does the inverse! */ + else if (!get_opt_reassociation() && get_irn_op(a) == op_Mul) { ir_node *ma = get_Mul_left(a); ir_node *mb = get_Mul_right(a); @@ -1715,7 +1811,8 @@ static ir_node *transform_node_Add(ir_node *n) DBG_OPT_ALGSIM0(oldn, n, FS_OPT_ADD_MUL_A_X_A); } } - else if (get_irn_op(b) == op_Mul) { + /* do NOT execute this code if reassociation is enabled, it does the inverse! */ + else if (!get_opt_reassociation() && get_irn_op(b) == op_Mul) { ir_node *ma = get_Mul_left(b); ir_node *mb = get_Mul_right(b); @@ -1775,7 +1872,8 @@ static ir_node *transform_node_Sub(ir_node *n) mode); DBG_OPT_ALGSIM0(oldn, n, FS_OPT_SUB_0_A); } - else if (get_irn_op(a) == op_Mul) { + /* do NOT execute this code if reassociation is enabled, it does the inverse! */ + else if (get_opt_reassociation() && get_irn_op(a) == op_Mul) { ir_node *ma = get_Mul_left(a); ir_node *mb = get_Mul_right(a); @@ -2126,18 +2224,22 @@ static ir_node *transform_node_Proj_Div(ir_node *proj) /* div(x, y) && y != 0 */ proj_nr = get_Proj_proj(proj); - /* this node may float */ + /* this node may float if it did not depend on a Confirm */ set_irn_pinned(n, op_pin_state_floats); if (proj_nr == pn_Div_X_except) { /* we found an exception handler, remove it */ DBG_OPT_EXC_REM(proj); return new_Bad(); - } else if (proj_nr == pn_Div_M) { - /* the memory Proj can be removed */ + } + else if (proj_nr == pn_Div_M) { ir_node *res = get_Div_mem(n); - set_Div_mem(n, get_irg_no_mem(current_ir_graph)); - + /* the memory Proj can only be removed if we divide by a + real constant, but the node never produce a new memory */ + if (value_of(b) != tarval_bad) { + /* this is a Div by a const, we can remove the memory edge */ + set_Div_mem(n, get_irg_no_mem(current_ir_graph)); + } return res; } } @@ -2158,7 +2260,7 @@ static ir_node *transform_node_Proj_Mod(ir_node *proj) /* mod(x, y) && y != 0 */ proj_nr = get_Proj_proj(proj); - /* this node may float */ + /* this node may float if it did not depend on a Confirm */ set_irn_pinned(n, op_pin_state_floats); if (proj_nr == pn_Mod_X_except) { @@ -2166,10 +2268,13 @@ static ir_node *transform_node_Proj_Mod(ir_node *proj) DBG_OPT_EXC_REM(proj); return new_Bad(); } else if (proj_nr == pn_Mod_M) { - /* the memory Proj can be removed */ ir_node *res = get_Mod_mem(n); - set_Mod_mem(n, get_irg_no_mem(current_ir_graph)); - + /* the memory Proj can only be removed if we divide by a + real constant, but the node never produce a new memory */ + if (value_of(b) != tarval_bad) { + /* this is a Mod by a const, we can remove the memory edge */ + set_Mod_mem(n, get_irg_no_mem(current_ir_graph)); + } return res; } else if (proj_nr == pn_Mod_res && get_Mod_left(n) == b) { @@ -2198,7 +2303,7 @@ static ir_node *transform_node_Proj_DivMod(ir_node *proj) /* DivMod(x, y) && y != 0 */ proj_nr = get_Proj_proj(proj); - /* this node may float */ + /* this node may float if it did not depend on a Confirm */ set_irn_pinned(n, op_pin_state_floats); if (proj_nr == pn_DivMod_X_except) { @@ -2207,10 +2312,13 @@ static ir_node *transform_node_Proj_DivMod(ir_node *proj) return new_Bad(); } else if (proj_nr == pn_DivMod_M) { - /* the memory Proj can be removed */ ir_node *res = get_DivMod_mem(n); - set_DivMod_mem(n, get_irg_no_mem(current_ir_graph)); - + /* the memory Proj can only be removed if we divide by a + real constant, but the node never produce a new memory */ + if (value_of(b) != tarval_bad) { + /* this is a DivMod by a const, we can remove the memory edge */ + set_DivMod_mem(n, get_irg_no_mem(current_ir_graph)); + } return res; } else if (proj_nr == pn_DivMod_res_mod && get_DivMod_left(n) == b) { @@ -2290,7 +2398,7 @@ static ir_node *transform_node_Proj_Cmp(ir_node *proj) proj_nr = get_inversed_pnc(proj_nr); changed |= 1; } - else if (left > right) { + else if (get_irn_idx(left) > get_irn_idx(right)) { ir_node *t = left; left = right; @@ -2434,7 +2542,32 @@ static ir_node *transform_node_Proj_Cmp(ir_node *proj) } } } /* mode_is_int */ - } + + /* + * optimization for AND: + * Optimize: + * And(x, C) == C ==> And(x, C) != 0 + * And(x, C) != C ==> And(X, C) == 0 + * + * if C is a single Bit constant. + */ + if ((proj_nr == pn_Cmp_Eq || proj_nr == pn_Cmp_Lg) && + (get_irn_op(left) == op_And)) { + if (is_single_bit_tarval(tv)) { + /* check for Constant's match. We have check hare the tarvals, + because our const might be changed */ + ir_node *la = get_And_left(left); + ir_node *ra = get_And_right(left); + if ((is_Const(la) && get_Const_tarval(la) == tv) || + (is_Const(ra) && get_Const_tarval(ra) == tv)) { + /* fine: do the transformation */ + tv = get_mode_null(get_tarval_mode(tv)); + proj_nr ^= pn_Cmp_Leg; + changed |= 2; + } + } + } + } /* tarval != bad */ } if (changed) { @@ -2932,6 +3065,16 @@ static ir_node *transform_node_Mux(ir_node *n) return arch_transform_node_Mux(n); } +/** + * Optimize a Psi into some simpler cases. + */ +static ir_node *transform_node_Psi(ir_node *n) { + if (is_Mux(n)) + return transform_node_Mux(n); + + return n; +} + /** * Tries several [inplace] [optimizing] transformations and returns an * equivalent node. The difference to equivalent_node() is that these @@ -2981,6 +3124,7 @@ static ir_op_ops *firm_set_default_transform_node(opcode code, ir_op_ops *ops) CASE(Shl); CASE(End); CASE(Mux); + CASE(Psi); default: /* leave NULL */; } @@ -3132,7 +3276,7 @@ static ir_op_ops *firm_set_default_node_cmp_attr(opcode code, ir_op_ops *ops) * Compare function for two nodes in the hash table. Gets two * nodes as parameters. Returns 0 if the nodes are a cse. */ -static int identities_cmp(const void *elt, const void *key) +int identities_cmp(const void *elt, const void *key) { ir_node *a, *b; int i, irn_arity_a; @@ -3238,7 +3382,7 @@ identify (pset *value_table, ir_node *n) ir_node *r = get_binop_right(n); /* for commutative operators perform a OP b == b OP a */ - if (l > r) { + if (get_irn_idx(l) > get_irn_idx(r)) { set_binop_left(n, r); set_binop_right(n, l); } @@ -3273,7 +3417,7 @@ identify_cons (pset *value_table, ir_node *n) { * Looks up the node in a hash table, enters it in the table * if it isn't there yet. */ -static ir_node * +ir_node * identify_remember (pset *value_table, ir_node *n) { ir_node *o = NULL; @@ -3356,8 +3500,15 @@ gigo (ir_node *node) if (is_Bad(pred)) return new_Bad(); +#if 0 + /* Propagating Unknowns here seems to be a bad idea, because + sometimes we need a node as a input and did not want that + it kills it's user. + However, i might be useful to move this into a later phase + (it you thing optimizing such code is useful). */ if (is_Unknown(pred) && mode_is_data(get_irn_mode(node))) return new_Unknown(get_irn_mode(node)); +#endif } } #if 0 @@ -3429,7 +3580,7 @@ optimize_node(ir_node *n) edges_node_deleted(n, current_ir_graph); /* evaluation was successful -- replace the node. */ - obstack_free(current_ir_graph->obst, n); + irg_kill_node(current_ir_graph, n); nw = new_Const(get_tarval_mode (tv), tv); if (old_tp && get_type_mode(old_tp) == get_tarval_mode (tv)) @@ -3464,8 +3615,7 @@ optimize_node(ir_node *n) edges_node_deleted(oldn, current_ir_graph); /* We found an existing, better node, so we can deallocate the old node. */ - obstack_free (current_ir_graph->obst, oldn); - + irg_kill_node(current_ir_graph, oldn); return n; }