X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fir%2Firopt.c;h=742e6a8e8b0b2c7e93f76bb62b2c91fc68d65ed1;hb=5f8ddee6b08c8040c0a304a347d65045c1141d52;hp=f39b23dcaf40a0ac4b46d8a7ab57b782b1032325;hpb=55fadbd9a8b631825b8abdcb185f53c5f0cdd1a7;p=libfirm diff --git a/ir/ir/iropt.c b/ir/ir/iropt.c index f39b23dca..742e6a8e8 100644 --- a/ir/ir/iropt.c +++ b/ir/ir/iropt.c @@ -6,11 +6,18 @@ ** iropt --- optimizations intertwined with IR construction. */ -# include "iropt.h" +# 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" /* Trivial inlineable routine for copy propagation. Does follow Ids, needed to optimize inlined code. */ @@ -21,7 +28,6 @@ follow_Id (ir_node *n) return n; } - static inline tarval * value_of (ir_node *n) { @@ -31,9 +37,8 @@ value_of (ir_node *n) return NULL; } - /* if n can be computed, return the value, else NULL. Performs - constant Folding. GL: Only if n is arithmetic operator? */ + constant folding. GL: Only if n is arithmetic operator? */ tarval * computed_value (ir_node *n) { @@ -95,7 +100,7 @@ computed_value (ir_node *n) case iro_Abs: if (ta) res = /*tarval_abs (ta);*/ res; - /* allowded or problems with max/min ?? */ + /* allowed or problems with max/min ?? */ break; case iro_And: if (ta && tb) { @@ -120,12 +125,12 @@ 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_not (ta)*/; } break; case iro_Shl: if (ta && tb) { res = tarval_shl (ta, tb); } break; 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_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_Rot: if (ta && tb) { /*res = tarval_rot (ta, tb)*/; } break; + case iro_Conv: if(ta) { res = tarval_convert_to (ta, get_irn_mode (n)); } break; case iro_Proj: { @@ -244,28 +249,26 @@ equivalent_node (ir_node *n) a = get_unop_op(n); } - /* skip unnecessary nodes. */ switch (get_irn_opcode (n)) { case iro_Block: { - /* The Block constructor does not call optimize, therefore - dead blocks are not removed without an extra optimizing - pass through the graph. */ + /* The Block constructor does not call optimize, but mature_block + calls the optimization. */ assert(get_Block_matured(n)); - /* a single entry Region following a single exit Region 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. */ 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) { 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 */ - for (i = 0; i < get_Block_n_cfgpreds(n); i++) { if (!is_Bad(get_Block_cfgpred(n, i))) break; } @@ -275,18 +278,13 @@ equivalent_node (ir_node *n) } break; - case iro_Jmp: /* GL: ??? Why not same for op_Raise?? */ + case iro_Jmp: /* GL: Why not same for op_Raise?? */ /* unreachable code elimination */ if (is_Bad(get_nodes_Block(n))) n = new_Bad(); break; - /* GL: Why isn't there a case that checks whether input ot Cond is - constant true or false? For unreachable code elimination - is this done in Proj? It's not here as it generates a new node, - a Jmp. It is in transform_node. * - case iro_Cond: - break; - */ - /* remove stuff as x+0, x*1 x&true ... constant expression evaluation */ + /* We do not evaluate Cond here as we replace it by a new node, a Jmp. + See cases for iro_Cond and iro_Proj in transform_node. */ + /** remove stuff as x+0, x*1 x&true ... constant expression evaluation **/ case iro_Or: if (a == b) {n = a; break;} case iro_Add: case iro_Eor: @@ -377,6 +375,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 */ @@ -422,14 +422,14 @@ equivalent_node (ir_node *n) /* skip Id's */ set_Phi_pred(n, i, first_val); if ( (first_val != n) /* not self pointer */ - && (get_irn_op(first_val) != op_Bad) /* value not dead */ + && (get_irn_op(first_val) != op_Bad) /* value not dead */ && !(is_Bad (get_Block_cfgpred(block, i))) ) { /* not dead control flow */ break; /* then found first value. */ } } - /* A totally Bad or self-referencing Phi */ - if (i > n_preds) { n = new_Bad(); break; } + /* A totally Bad or self-referencing Phi (we didn't break the above loop) */ + if (i >= n_preds) { n = new_Bad(); break; } scnd_val = NULL; @@ -448,12 +448,13 @@ 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) + while (++i < n_preds) { set_Phi_pred(n, i, follow_Id(get_Phi_pred(n, i))); + } } } break; @@ -507,7 +508,7 @@ equivalent_node (ir_node *n) if ( get_Proj_proj(n) <= get_Tuple_n_preds(a) ) { n = get_Tuple_pred(a, get_Proj_proj(n)); } else { - assert(0); /* This should not happen?! (GL added this assert) */ + assert(0); /* This should not happen! (GL added this assert) */ n = new_Bad(); } } else if (get_irn_mode(n) == mode_X && @@ -529,7 +530,6 @@ equivalent_node (ir_node *n) } /* end equivalent_node() */ -#if 0 /* tries several [inplace] [optimizing] transformations and returns a equivalent node. The difference to equivalent_node is that these transformations _do_ generate new nodes, and thus the old node must @@ -538,16 +538,18 @@ static ir_node * transform_node (ir_node *n) { - ir_node *a, *b; + ir_node *a = NULL, *b; tarval *ta, *tb; switch (get_irn_opcode(n)) { case iro_DivMod: { + int evaluated = 0; - ir_mode *mode = get_irn_mode(a); + ir_mode *mode; a = get_DivMod_left(n); b = get_DivMod_right(n); + mode = get_irn_mode(a); if (!( mode_is_int(get_irn_mode(a)) && mode_is_int(get_irn_mode(b)))) @@ -585,9 +587,10 @@ transform_node (ir_node *n) ir_node *mem = get_DivMod_mem(n); turn_into_tuple(n, 4); set_Tuple_pred(n, 0, mem); - set_Tuple_pred(n, 1, new_Bad()); + set_Tuple_pred(n, 1, new_Bad()); /* no exception */ set_Tuple_pred(n, 2, a); set_Tuple_pred(n, 3, b); + assert(get_nodes_Block(n)); } } break; @@ -596,7 +599,6 @@ transform_node (ir_node *n) /* Replace the Cond by a Jmp if it branches on a constant condition. */ ir_node *jmp; - a = get_Cond_selector(n); ta = value_of(a); @@ -618,14 +620,19 @@ transform_node (ir_node *n) I generate the Jmp here, and remember it in link. Link is used when optimizing Proj. */ set_irn_link(n, new_r_Jmp(current_ir_graph, get_nodes_Block(n))); - } else if ( ((get_irn_op(get_Cond_selector(n)) == op_Eor) - /* || (get_irn_op(get_Cond_selector(a)) == op_Not)*/) + } else if ( (get_irn_op(get_Cond_selector(n)) == op_Eor) && (get_irn_mode(get_Cond_selector(n)) == mode_b) && (tarval_classify(computed_value(get_Eor_right(a))) == 1)) { /* The Eor is a negate. Generate a new Cond without the negate, simulate the negate by exchanging the results. */ set_irn_link(n, new_r_Cond(current_ir_graph, get_nodes_Block(n), get_Eor_left(a))); + } else if ( (get_irn_op(get_Cond_selector(n)) == op_Not) + && (get_irn_mode(get_Cond_selector(n)) == mode_b)) { + /* A Not before the Cond. Generate a new Cond without the Not, + simulate the Not by exchanging the results. */ + set_irn_link(n, new_r_Cond(current_ir_graph, get_nodes_Block(n), + get_Not_op(a))); } } break; @@ -638,8 +645,8 @@ transform_node (ir_node *n) && get_irn_op(get_irn_link(a)) == op_Cond) { /* Use the better Cond if the Proj projs from a Cond which get's its result from an Eor/Not. */ - assert ( ((get_irn_op(get_Cond_selector(a)) == op_Eor) - /* || (get_irn_op(get_Cond_selector(a)) == op_Not)*/) + assert ( ( (get_irn_op(get_Cond_selector(a)) == op_Eor) + || (get_irn_op(get_Cond_selector(a)) == op_Not)) && (get_irn_mode(get_Cond_selector(a)) == mode_b) && (get_irn_op(get_irn_link(a)) == op_Cond) && (get_Cond_selector(get_irn_link(a)) == @@ -666,7 +673,7 @@ transform_node (ir_node *n) } } break; - case iro_Eor: { + case iro_Eor: { /* @@@ not tested as boolean Eor not allowed any more. */ a = get_Eor_left(n); b = get_Eor_right(n); @@ -674,7 +681,7 @@ transform_node (ir_node *n) && (get_irn_op(a) == op_Proj) && (get_irn_mode(a) == mode_b) && (tarval_classify (computed_value (b)) == 1) - && (get_irn_op(get_Proj_pred(a)) == iro_Cmp)) + && (get_irn_op(get_Proj_pred(a)) == op_Cmp)) /* The Eor negates a Cmp. The Cmp has the negated result anyways! */ n = new_r_Proj(current_ir_graph, get_nodes_Block(n), get_Proj_pred(a), mode_b, get_negated_pnc(get_Proj_proj(a))); @@ -691,7 +698,7 @@ transform_node (ir_node *n) if ( (get_irn_mode(n) == mode_b) && (get_irn_op(a) == op_Proj) && (get_irn_mode(a) == mode_b) - && (get_irn_op(get_Proj_pred(a)) == iro_Cmp)) + && (get_irn_op(get_Proj_pred(a)) == op_Cmp)) /* We negate a Cmp. The Cmp has the negated result anyways! */ n = new_r_Proj(current_ir_graph, get_nodes_Block(n), get_Proj_pred(a), mode_b, get_negated_pnc(get_Proj_proj(a))); @@ -699,8 +706,8 @@ transform_node (ir_node *n) break; default: ; } + return n; } -#endif /***************** Common Subexpression Elimination *****************/ @@ -868,11 +875,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; } @@ -886,7 +902,8 @@ optimize (ir_node *n) tarval *tv; ir_node *old_n = n; - if (!get_optimize()) return NULL; + /* Allways optimize Phi nodes: part of the construction. */ + if ((!get_optimize()) && (get_irn_op(n) != op_Phi)) return n; /* if not optimize return n */ if (n == NULL) { @@ -904,10 +921,10 @@ optimize (ir_node *n) /* evaluation was succesful -- replace the node. */ obstack_free (current_ir_graph->obst, n); return new_Const (get_tv_mode (tv), tv); - /* xprintf("* optimize: computed node %I\n", n->op->name); */ } } } + /* remove unnecessary nodes */ if (get_opt_constant_folding() || get_irn_op(n) == op_Phi) n = equivalent_node (n); @@ -917,31 +934,26 @@ optimize (ir_node *n) /* The block input is used to distinguish different subexpressions. Right now all nodes are pinned to blocks, i.e., the cse only finds common subexpressions within a block. */ - if (get_opt_cse()) n = identify (current_ir_graph->value_table, n); - /* identify found a cse, so deallocate the old node. */ if (n != old_n) { obstack_free (current_ir_graph->obst, old_n); /* The AmRoq fiasco returns n here. Martin's version doesn't. */ } -#if 0 - /* Some more constant expression evaluation. */ + /* Some more constant expression evaluation that does not allow to + free the node. */ if (get_opt_constant_folding()) n = transform_node (n); -#endif /* Remove nodes with dead (Bad) input. */ n = gigo (n); /* Now we can verify the node, as it has no dead inputs any more. */ - ir_vrfy(n); + 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. */ n = identify_remember (current_ir_graph->value_table, n); } @@ -965,6 +977,8 @@ 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? */ @@ -979,12 +993,16 @@ 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) n = equivalent_node (n); @@ -993,7 +1011,6 @@ optimize_in_place (ir_node *n) /* The block input is used to distinguish different subexpressions. Right now all nodes are pinned to blocks, i.e., the cse only finds common subexpressions within a block. */ - if (get_opt_cse()) n = identify (current_ir_graph->value_table, n); @@ -1002,16 +1019,14 @@ optimize_in_place (ir_node *n) /* The AmRoq fiasco returns n here. Martin's version doesn't. */ } -#if 0 /* Some more constant expression evaluation. */ if (get_opt_constant_folding()) n = transform_node (n); -#endif /* Remove nodes with dead (Bad) input. */ n = gigo (n); /* Now we can verify the node, as it has no dead inputs any more. */ - ir_vrfy(n); + irn_vrfy(n); /* Now we have a legal, useful node. Enter it in hash table for cse */ if (get_opt_cse()) {