X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fir%2Firopt.c;h=1dd151fb4ab946db6e57c856aaef108129c87bb1;hb=62526938a78e229e700fef9bd825e87d14ba549f;hp=54494a64bb98105ee2b0edb9759c9ea06d0645cf;hpb=b629f9f2c86fa8a50576bb4933b2ecdeb9f41008;p=libfirm diff --git a/ir/ir/iropt.c b/ir/ir/iropt.c index 54494a64b..1dd151fb4 100644 --- a/ir/ir/iropt.c +++ b/ir/ir/iropt.c @@ -6,11 +6,19 @@ ** iropt --- optimizations intertwined with IR construction. */ -# include "iropt.h" +#ifdef HAVE_CONFIG_H +# include +#endif + +# include "irnode_t.h" +# include "irgraph_t.h" +# include "iropt_t.h" # include "ircons.h" # include "irgmod.h" # include "irvrfy.h" # include "tv.h" +# include "tune.h" +# include "debinfo.h" /* Make types visible to allow most efficient access */ # include "entity_t.h" @@ -78,14 +86,15 @@ computed_value (ir_node *n) break; case iro_Minus: if (ta && mode_is_float(get_irn_mode(a))) - res = /*tarval_minus (ta);*/ res; + res = tarval_neg (ta); break; case iro_Mul: if (ta && tb) /* tarval_mul tests for equivalent modes itself */ { res = tarval_mul (ta, tb); } else { - /* calls computed_value recursive and returns the 0 with proper - mode. Why is this an extra case? */ + /* a*0 = 0 or 0*b = 0: + calls computed_value recursive and returns the 0 with proper + mode. */ tarval *v; if ( (tarval_classify ((v = computed_value (a))) == 0) || (tarval_classify ((v = computed_value (b))) == 0)) { @@ -93,10 +102,31 @@ computed_value (ir_node *n) } } break; + case iro_Quot: + /* This was missing in original implementation. Why? */ + if (ta && tb && (get_irn_mode(a) == get_irn_mode(b))) { + if (tarval_classify(tb) == 0) {res = NULL; break;} + res = tarval_quo(ta, tb); + } + break; + case iro_Div: + /* This was missing in original implementation. Why? */ + if (ta && tb && (get_irn_mode(a) == get_irn_mode(b))) { + if (tarval_classify(tb) == 0) {res = NULL; break;} + res = tarval_div(ta, tb); + } + break; + case iro_Mod: + /* This was missing in original implementation. Why? */ + if (ta && tb && (get_irn_mode(a) == get_irn_mode(b))) { + if (tarval_classify(tb) == 0) {res = NULL; break;} + res = tarval_mod(ta, tb); + } + break; + /* for iro_DivMod see iro_Proj */ case iro_Abs: if (ta) - res = /*tarval_abs (ta);*/ res; - /* allowed or problems with max/min ?? */ + res = tarval_abs (ta); break; case iro_And: if (ta && tb) { @@ -121,14 +151,15 @@ computed_value (ir_node *n) } break; case iro_Eor: if (ta && tb) { res = tarval_eor (ta, tb); } break; - case iro_Not: if (ta) { /*res = tarval_not (ta)*/; } break; + case iro_Not: if (ta) { res = tarval_neg (ta); } break; case iro_Shl: if (ta && tb) { res = tarval_shl (ta, tb); } break; + /* tarval_shr is faulty !! */ case iro_Shr: if (ta && tb) { res = tarval_shr (ta, tb); } break; - case iro_Shrs: if(ta && tb) { /*res = tarval_shrs (ta, tb)*/; } break; + case iro_Shrs:if (ta && tb) { /*res = tarval_shrs (ta, tb)*/; } break; case iro_Rot: if (ta && tb) { /*res = tarval_rot (ta, tb)*/; } break; - case iro_Conv: if(ta) { res = tarval_convert_to (ta, get_irn_mode (n)); } + case iro_Conv:if (ta) { res = tarval_convert_to (ta, get_irn_mode (n)); } break; - case iro_Proj: + case iro_Proj: /* iro_Cmp */ { ir_node *aa, *ab; @@ -191,6 +222,16 @@ computed_value (ir_node *n) res = tarval_from_long (mode_b, get_Proj_proj(n) & irpn_Ne); } } + } else if (get_irn_op(a) == op_DivMod) { + ta = value_of(get_DivMod_left(a)); + tb = value_of(get_DivMod_right(a)); + if (ta && tb && (get_irn_mode(a) == get_irn_mode(b))) { + if (tarval_classify(tb) == 0) {res = NULL; break;} + if (get_Proj_proj(n)== 0) /* Div */ + res = tarval_div(ta, tb); + else /* Mod */ + res = tarval_mod(ta, tb); + } } else { /* printf(" # comp_val: Proj node, not optimized\n"); */ } @@ -253,17 +294,21 @@ equivalent_node (ir_node *n) calls the optimization. */ assert(get_Block_matured(n)); - /* a single entry Block following a single exit Block can be merged */ + /* A single entry Block following a single exit Block can be merged, + if it is not the Start block. */ /* !!! Beware, all Phi-nodes of n must have been optimized away. - This is true, as the block is matured before optimize is called. */ + This should be true, as the block is matured before optimize is called. + But what about Phi-cycles with the Phi0/Id that could not be resolved? */ if (get_Block_n_cfgpreds(n) == 1 && get_irn_op(get_Block_cfgpred(n, 0)) == op_Jmp) { n = get_nodes_Block(get_Block_cfgpred(n, 0)); - } else if (n != current_ir_graph->start_block) { + } else if ((n != current_ir_graph->start_block) && + (n != current_ir_graph->end_block) ) { int i; /* If all inputs are dead, this block is dead too, except if it is - the start block. This is a step of unreachable code elimination */ + the start or end block. This is a step of unreachable code + elimination */ for (i = 0; i < get_Block_n_cfgpreds(n); i++) { if (!is_Bad(get_Block_cfgpred(n, i))) break; } @@ -370,6 +415,8 @@ equivalent_node (ir_node *n) themselves. */ int i, n_preds; + + ir_node *block = NULL; /* to shutup gcc */ ir_node *first_val = NULL; /* to shutup gcc */ ir_node *scnd_val = NULL; /* to shutup gcc */ @@ -408,6 +455,7 @@ equivalent_node (ir_node *n) } } #endif + /* Find first non-self-referencing input */ for (i = 0; i < n_preds; ++i) { first_val = follow_Id(get_Phi_pred(n, i)); @@ -421,7 +469,7 @@ equivalent_node (ir_node *n) } /* A totally Bad or self-referencing Phi (we didn't break the above loop) */ - if (i > n_preds) { n = new_Bad(); break; } + if (i >= n_preds) { n = new_Bad(); break; } scnd_val = NULL; @@ -440,8 +488,8 @@ equivalent_node (ir_node *n) } /* Fold, if no multiple distinct non-self-referencing inputs */ - if (i > n_preds) { - n = a; + if (i >= n_preds) { + n = first_val; } else { /* skip the remaining Ids. */ while (++i < n_preds) { @@ -606,7 +654,7 @@ transform_node (ir_node *n) set_Tuple_pred(n, 0, jmp); set_Tuple_pred(n, 1, new_Bad()); } - } else if (ta && (get_irn_mode(a) == mode_I)) { + } else if (ta && (get_irn_mode(a) == mode_I) && (get_Cond_kind(n) == dense)) { /* I don't want to allow Tuples smaller than the biggest Proj. Also this tuple might get really big... I generate the Jmp here, and remember it in link. Link is used @@ -650,7 +698,8 @@ transform_node (ir_node *n) set_Proj_proj(n, 0); } else if ( (get_irn_op(a) == op_Cond) && (get_irn_mode(get_Cond_selector(a)) == mode_I) - && value_of(a)) { + && value_of(a) + && (get_Cond_kind(a) == dense)) { /* The Cond is a Switch on a Constant */ if (get_Proj_proj(n) == tv_val_CHIL(value_of(a))) { /* The always taken branch, reuse the existing Jmp. */ @@ -701,7 +750,7 @@ transform_node (ir_node *n) return n; } -/***************** Common Subexpression Elimination *****************/ +/* **************** Common Subexpression Elimination **************** */ /* Compare function for two nodes in the hash table. Gets two */ /* nodes as parameters. */ @@ -753,8 +802,7 @@ vt_cmp (const void *elt, const void *key) return (get_irn_symconst_attr(a).num != get_irn_symconst_attr(b).num) || (get_irn_symconst_attr(a).tori.typ != get_irn_symconst_attr(b).tori.typ); case iro_Call: - return (get_irn_call_attr(a)->kind != get_irn_call_attr(b)->kind) - || (get_irn_call_attr(a)->arity != get_irn_call_attr(b)->arity); + return (get_irn_call_attr(a) != get_irn_call_attr(b)); case iro_Sel: return (get_irn_sel_attr(a).ent->kind != get_irn_sel_attr(b).ent->kind) || (get_irn_sel_attr(a).ent->name != get_irn_sel_attr(b).ent->name) @@ -867,11 +915,20 @@ gigo (ir_node *node) if ( op != op_Block && op != op_Phi && op != op_Tuple) { for (i = -1; i < get_irn_arity(node); i++) { if (is_Bad(get_irn_n(node, i))) { - node = new_Bad(); - break; + return new_Bad(); } } } +#if 0 + /* If Block has only Bads as predecessors it's garbage. */ + /* If Phi has only Bads as predecessors it's garbage. */ + if (op == op_Block || op == op_Phi) { + for (i = 0; i < get_irn_arity(node); i++) { + if (!is_Bad(get_irn_n(node, i))) break; + } + if (i = get_irn_arity(node)) node = new_Bad(); + } +#endif return node; } @@ -956,10 +1013,11 @@ optimize (ir_node *n) ir_node * optimize_in_place (ir_node *n) { - tarval *tv; ir_node *old_n = n; + if (!get_optimize()) return n; + /* if not optimize return n */ if (n == NULL) { /* Here this is possible. Why? */ @@ -974,15 +1032,17 @@ optimize_in_place (ir_node *n) tv = computed_value (n); if (tv != NULL) { /* evaluation was succesful -- replace the node. */ - return new_Const (get_tv_mode (tv), tv); + n = new_Const (get_tv_mode (tv), tv); + deb_info_copy(n, old_n, id_from_str("const_eval", 10)); + return n; /* xprintf("* optimize: computed node %I\n", n->op->name);*/ } } } /* remove unnecessary nodes */ - if (get_opt_constant_folding()) - // if (get_opt_constant_folding() || get_irn_op(n) == op_Phi) + /*if (get_opt_constant_folding()) */ + if (get_opt_constant_folding() || get_irn_op(n) == op_Phi) n = equivalent_node (n); /** common subexpression elimination **/ @@ -1007,12 +1067,11 @@ optimize_in_place (ir_node *n) /* Now we can verify the node, as it has no dead inputs any more. */ irn_vrfy(n); - /* Now we have a legal, useful node. Enter it in hash table for cse */ - if (get_opt_cse()) { - /* aborts ??! set/pset can not handle several hash tables??! - No, suddenly it works. */ + /* Now we have a legal, useful node. Enter it in hash table for cse. + Blocks should be unique anyways. (Except the successor of start: + is cse with the start block!) */ + if (get_opt_cse() && (get_irn_opcode(n) != iro_Block)) n = identify_remember (current_ir_graph->value_table, n); - } return n; }