* (VanDrunen Hosking 2004)
* @author Michael Beck
* @version $Id$
- * @summary
+ * @brief
*/
#include "config.h"
+#include "iroptimize.h"
#include "irflag.h"
#include "irdom.h"
#include "irouts.h"
#include "iredges.h"
#include "iropt_dbg.h"
#include "debug.h"
+#include "irpass.h"
#include "irgraph_t.h"
#include "irnode_t.h"
struct obstack *obst; /**< The obstack to allocate on. */
ir_node *start_block; /**< The start block of the current graph. */
ir_node *end_block; /**< The end block of the current graph */
- block_info *list; /**< Links all block info entires for easier recovery. */
+ block_info *list; /**< Links all block info entries for easier recovery. */
elim_pair *pairs; /**< A list of node pairs that must be eliminated. */
unsigned last_idx; /**< last node index of "old" nodes, all higher indexes are newly created once. */
char changes; /**< Non-zero, if calculation of Antic_in has changed. */
char first_iter; /**< non-zero for first iteration */
} pre_env;
-static pset *value_table;
static ir_nodemap_t value_map;
/** The debug module handle. */
{
if (is_Proj(v)) {
ir_node *pred = get_Proj_pred(v);
- ir_node *v_pred = identify_remember(value_table, pred);
+ ir_node *v_pred = identify_remember(pred);
if (v_pred != pred) {
/* must create a new value here */
- v = new_r_Proj(current_ir_graph, get_nodes_block(v_pred), v_pred, get_irn_mode(v), get_Proj_proj(v));
+ v = new_r_Proj(v_pred, get_irn_mode(v), get_Proj_proj(v));
}
}
- v = identify_remember(value_table, v);
+ v = identify_remember(v);
ir_nodemap_insert(&value_map, e, v);
return v;
} /* add */
{
ir_node *value = ir_nodemap_get(&value_map, e);
if (value != NULL)
- return identify_remember(value_table, value);
+ return identify_remember(value);
return NULL;
} /* lookup */
*
* @param block the block
*/
-static block_info *get_block_info(ir_node *block) {
+static block_info *get_block_info(ir_node *block)
+{
return get_irn_link(block);
} /* get_block_info */
* @param block the block
* @param env the environment
*/
-static void alloc_blk_info(ir_node *block, pre_env *env) {
- block_info *info = obstack_alloc(env->obst, sizeof(*info));
+static void alloc_blk_info(ir_node *block, pre_env *env)
+{
+ block_info *info = OALLOC(env->obst, block_info);
set_irn_link(block, info);
info->exp_gen = ir_valueset_new(16);
*
* @param n the node
*/
-static int is_nice_value(ir_node *n) {
+static int is_nice_value(ir_node *n)
+{
ir_mode *mode;
while (is_Proj(n))
* @param txt a text to describe the set
* @param block the owner block of the set
*/
-static void dump_value_set(ir_valueset_t *set, char *txt, ir_node *block) {
+static void dump_value_set(ir_valueset_t *set, char *txt, ir_node *block)
+{
ir_valueset_iterator_t iter;
ir_node *value, *expr;
int i;
* Topological walker. Allocates block info for every block and place nodes in topological
* order into the nodes set.
*/
-static void topo_walker(ir_node *irn, void *ctx) {
+static void topo_walker(ir_node *irn, void *ctx)
+{
pre_env *env = ctx;
ir_node *block;
block_info *info;
* @param block the block
* @param set a value set, containing the already processed predecessors
*/
-static int is_clean_in_block(ir_node *n, ir_node *block, ir_valueset_t *set) {
+static int is_clean_in_block(ir_node *n, ir_node *block, ir_valueset_t *set)
+{
int i;
if (is_Phi(n))
return node;
}
- arity = get_irn_intra_arity(node);
+ arity = get_irn_arity(node);
/* check if the node has at least one Phi predecessor */
for (i = 0; i < arity; ++i) {
- ir_node *pred = get_irn_intra_n(node, i);
+ ir_node *pred = get_irn_n(node, i);
ir_node *leader = lookup(pred);
ir_node *trans;
nn = new_ir_node(
get_irn_dbg_info(node),
current_ir_graph,
- NULL,
+ get_nodes_block(node),
get_irn_op(node),
get_irn_mode(node),
arity,
get_irn_in(node));
/* We need the attribute copy here, because the Hash value of a
node might depend on that. */
- copy_node_attr(node, nn);
+ copy_node_attr(current_ir_graph, node, nn);
- set_nodes_block(nn, get_nodes_block(node));
for (i = 0; i < arity; ++i) {
- ir_node *pred = get_irn_intra_n(node, i);
+ ir_node *pred = get_irn_n(node, i);
ir_node *leader = lookup(pred);
ir_node *trans;
if (trans == NULL)
trans = leader;
- if (is_Phi(trans) && get_nodes_block(trans) == block) {
- ir_node *trans_pred = get_Phi_pred(trans, pos);
- set_irn_n(nn, i, trans_pred);
- } else
+ if (is_Phi(trans) && get_nodes_block(trans) == block)
+ set_irn_n(nn, i, get_Phi_pred(trans, pos));
+ else
set_irn_n(nn, i, trans);
}
nn = optimize_node(nn);
* @param block the block
* @param ctx the walker environment
*/
-static void compute_antic(ir_node *block, void *ctx) {
+static void compute_antic(ir_node *block, void *ctx)
+{
pre_env *env = ctx;
block_info *succ_info;
block_info *info = get_block_info(block);
n_succ = get_Block_n_cfg_outs(block);
if (n_succ == 1) {
- int i, pos = -1;
+ int pos = -1;
/* find blocks position in succ's block predecessors */
succ = get_Block_cfg_out(block, 0);
- for (i = get_Block_n_cfgpreds(succ) - 1; i >= 0; --i) {
- if (get_Block_cfgpred_block(succ, i) == block) {
- pos = i;
- break;
- }
- }
+ pos = get_Block_cfgpred_pos(succ, block);
assert(pos >= 0);
succ_info = get_block_info(succ);
pre_env *env = ctx;
ir_node *value, *expr, *idom, *first_s, *worklist;
block_info *curr_info, *idom_info;
- int pos, arity = get_irn_intra_arity(block);
+ int pos, arity = get_irn_arity(block);
int all_same, by_some, updated;
ir_valueset_iterator_t iter;
/* ignore bad blocks. */
if (is_Bad(pred_blk)) {
- in[pos] = new_Bad();
+ ir_graph *irg = get_irn_irg(pred_blk);
+ in[pos] = new_r_Bad(irg);
continue;
}
mode,
get_irn_arity(pred),
get_irn_in(pred) + 1);
- copy_node_attr(pred, nn);
+ copy_node_attr(current_ir_graph, pred, nn);
DB((dbg, LEVEL_1, "New node %+F in block %+F created\n", nn, pred_blk));
proj_pred = nn;
mode,
get_irn_arity(e_prime),
get_irn_in(e_prime) + 1);
- copy_node_attr(e_prime, nn);
+ copy_node_attr(current_ir_graph, e_prime, nn);
if (proj_pred != NULL) {
set_Proj_pred(nn, proj_pred);
}
}
in[pos] = pred_info->avail;
} /* for */
- phi = new_r_Phi(current_ir_graph, block, arity, in, mode);
+ phi = new_r_Phi(block, arity, in, mode);
l = lookup(expr);
if (l == NULL) {
l = add(expr, value);
* @param irn the node
* @param ctx the walker environment
*/
-static void eliminate(ir_node *irn, void *ctx) {
+static void eliminate(ir_node *irn, void *ctx)
+{
pre_env *env = ctx;
- if (is_no_Block(irn)) {
+ if (!is_Block(irn)) {
ir_node *block = get_nodes_block(irn);
block_info *bl = get_block_info(block);
ir_node *value = lookup(irn);
ir_node *expr = ir_valueset_lookup(bl->avail_out, value);
if (expr != NULL && expr != irn) {
- elim_pair *p = obstack_alloc(env->obst, sizeof(*p));
+ elim_pair *p = OALLOC(env->obst, elim_pair);
p->old_node = irn;
p->new_node = expr;
*
* @param pairs list of elimination pairs
*/
-static void eliminate_nodes(elim_pair *pairs) {
+static void eliminate_nodes(elim_pair *pairs)
+{
elim_pair *p;
for (p = pairs; p != NULL; p = p->next) {
int i;
ir_node *res = NULL;
- for (i = get_irn_intra_arity(p->new_node) - 1; i >= 0; --i) {
+ for (i = get_irn_arity(p->new_node) - 1; i >= 0; --i) {
ir_node *pred = get_irn_n(p->new_node, i);
if (pred != p->old_node) {
* references the origin. These nodes are translated again and again...
*
* The current fix is to use post-dominance. This simple ignores
- * endless loops, ie we cannot optimize them.
+ * endless loops, i.e. we cannot optimize them.
*/
void do_gvn_pre(ir_graph *irg)
{
/* register a debug mask */
FIRM_DBG_REGISTER(dbg, "firm.opt.gvn_pre");
- firm_dbg_set_mask(dbg, 3);
/* edges will crash if enabled due to our allocate on other obstack trick */
edges_deactivate(irg);
- value_table = new_identities();
+ new_identities(irg);
ir_nodemap_init(&value_map);
obstack_init(&obst);
a_env.end_block = get_irg_end_block(irg);
a_env.pairs = NULL;
- /* Move Proj's into the same block as their args,
- else we would assign the result to wrong blocks */
- normalize_proj_nodes(irg);
-
/* critical edges MUST be removed */
remove_critical_cf_edges(irg);
if (bl_info->new_set)
ir_valueset_del(bl_info->new_set);
}
- del_identities(value_table);
ir_nodemap_destroy(&value_map);
obstack_free(&obst, NULL);
- value_table = NULL;
/* pin the graph again: This is needed due to the use of set_opt_global_cse(1) */
set_irg_pinned(irg, op_pin_state_pinned);
set_irg_loopinfo_inconsistent(irg);
}
} /* do_gvn_pre */
+
+/* Creates an ir_graph pass for do_gvn_pre. */
+ir_graph_pass_t *do_gvn_pre_pass(const char *name)
+{
+ return def_graph_pass(name ? name : "gvn_pre", do_gvn_pre);
+} /* do_gvn_pre_pass */