#include "irpass.h"
#include "valueset.h"
#include "irloop.h"
+#include "firmstat_t.h"
#include "irgraph_t.h"
#include "irnode_t.h"
TODO Broken for yet unknown reasons. */
#define OPTIMIZE_NODES 0
-#define OLD_DIVMODS 0
-
/** Additional info we need for every block. */
typedef struct block_info {
/** environment for the GVN-PRE algorithm */
typedef struct pre_env {
ir_graph *graph; /* current graph */
- struct obstack *obst; /* obstack to allocate on */
+ struct obstack obst; /* obstack to allocate on */
ir_node *start_block; /* start block of the current graph */
ir_node *end_block; /* end block of the current graph */
ir_node *end_node; /* end node of the current graph */
int infinite_loops;
} gvnpre_statistics;
-gvnpre_statistics *gvnpre_stats = NULL;
+static gvnpre_statistics *gvnpre_stats = NULL;
-static void init_stats()
+static void init_stats(void)
{
gvnpre_stats = XMALLOCZ(gvnpre_statistics);
}
-static void free_stats()
+static void free_stats(void)
{
free(gvnpre_stats);
gvnpre_stats = NULL;
}
-static void print_stats()
+static void print_stats(void)
{
gvnpre_statistics *stats = gvnpre_stats;
DB((dbg, LEVEL_1, "replaced : %d\n", stats->replaced));
++i;
}
DB((dbg, LEVEL_2, "\n}\n"));
-} /* dump_value_set */
+}
/**
* Dump all exp_gen value sets.
*/
static void alloc_block_info(ir_node *block, pre_env *env)
{
- block_info *info = OALLOC(env->obst, block_info);
+ block_info *info = OALLOC(&env->obst, block_info);
set_irn_link(block, info);
info->exp_gen = ir_valueset_new(16);
info->next = env->list;
env->list = info;
-} /* alloc_block_info */
+}
static void free_block_info(block_info *block_info)
{
if (is_Phi(n))
return 1;
-#if LOADS || OLD_DIVMODS || DIVMODS
+#if LOADS || DIVMODS
if (is_Proj(n) && mode != mode_X && mode != mode_T)
return 1;
#else
ir_nodehashmap_insert(map, node, trans);
}
-#if OLD_DIVMODS
-/* Helper function to compare the values of pred and avail_pred. */
-static unsigned match_pred(ir_node *pred, ir_node *avail_pred, ir_node *block, int pos)
-{
- ir_node *avail_value = identify(avail_pred);
- ir_node *pred_block = get_Block_cfgpred_block(block, pos);
- ir_node *trans_pred = get_translated(pred_block, pred);
- ir_node *value;
-
- if (trans_pred == NULL)
- trans_pred = pred;
- value = identify(trans_pred);
-
- DB((dbg, LEVEL_3, "manual compare %+F %+F\n", pred, avail_pred));
-
- return (value == avail_value);
-}
-
-/**
- * Does phi translation for redundant Div/Mod nodes only.
- * Returns NULL for non-redundant node, which needs to be phi translated.
- */
-static ir_node *phi_translate_divmod(ir_node *divmod, ir_node *block, int pos)
-{
- ir_node *mem = get_memop_mem(divmod);
- ir_node *trans = get_translated_pred(block, pos, mem);
-
- if (trans == NULL)
- trans = mem;
-
- /* no partial redundancy if this is a mode_M phi */
- if (is_Proj(trans)) {
- /* The last memory operation in predecessor block */
- ir_node *avail_op = get_Proj_pred(trans);
-
- if (get_irn_op(divmod) == get_irn_op(avail_op)) {
- unsigned left, right;
-
- if (is_Div(avail_op)) {
- if (get_Div_resmode(divmod) == get_Div_resmode(avail_op) &&
- get_Div_no_remainder(divmod) == get_Div_no_remainder(avail_op)) {
-
- left = match_pred(get_Div_left(divmod), get_Div_left(avail_op), block, pos);
- right = match_pred(get_Div_right(divmod), get_Div_right(avail_op), block, pos);
-
- if (left && right)
- return avail_op;
- }
- } else if (is_Mod(avail_op)) {
- if (get_Mod_resmode(divmod) == get_Mod_resmode(avail_op)) {
-
- left = match_pred(get_Mod_left(divmod), get_Mod_left(avail_op), block, pos);
- right = match_pred(get_Mod_right(divmod), get_Mod_right(avail_op), block, pos);
-
- if (left && right)
- return avail_op;
- }
- }
- }
- }
- return NULL;
-}
-#endif
-
/**
* Translates an expression above a Phi.
*
}
arity = get_irn_arity(node);
-#if OLD_DIVMODS
- if (is_Div(node) || is_Mod(node)) {
- ir_node *avail_op = phi_translate_divmod(node, block, pos);
- if (avail_op)
- return avail_op;
- }
-#endif
-
needed = 0;
in = ALLOCANZ(ir_node *, arity);
if (updated)
dump_value_set(curr_info->avail_out, "Updated [Avail_out]", block);
#endif
-} /* update_new_set */
+}
/**
* Checks if hoisting irn is greedy.
if (mode == NULL)
continue;
-#if LOADS || OLD_DIVMODS || DIVMODS
+#if LOADS || DIVMODS
/* save old mode_M phis to remove keepalive edges later */
if (is_memop(expr)) {
ir_node *mem = get_memop_mem(expr);
DB((dbg, LEVEL_3, "Elim %+F(%+F) avail %+F\n", irn, value, expr));
if (expr != NULL && expr != irn) {
- elim_pair *p = OALLOC(env->obst, elim_pair);
+ elim_pair *p = OALLOC(&env->obst, elim_pair);
p->old_node = irn;
p->new_node = expr;
}
}
}
-} /* eliminate */
+}
/**
* Do all the recorded changes and optimize
foreach_ir_nodeset(keeps, m_phi, iter) {
remove_End_keepalive(end, m_phi);
}
-} /* eliminate_nodes */
+}
/* --------------------------------------------------------
*/
void do_gvn_pre(ir_graph *irg)
{
- struct obstack obst;
pre_env env;
ir_nodeset_t keeps;
optimization_state_t state;
DEBUG_ONLY(init_stats();)
/* setup environment */
- obstack_init(&obst);
env.graph = irg;
- env.obst = &obst;
env.list = NULL;
env.start_block = get_irg_start_block(irg);
env.end_block = get_irg_end_block(irg);
env.pairs = NULL;
env.keeps = &keeps;
env.last_idx = get_irg_last_idx(irg);
+ obstack_init(&env.obst);
/* Detect and set links of infinite loops to non-zero. */
analyse_loops(irg);
DEBUG_ONLY(free_stats();)
ir_nodehashmap_destroy(&value_map);
- obstack_free(&obst, NULL);
+ obstack_free(&env.obst, NULL);
ir_free_resources(irg, IR_RESOURCE_IRN_LINK | IR_RESOURCE_LOOP_LINK);
/* Pin the graph again.