DEBUG_ONLY(static firm_dbg_module_t *dbg;)
-typedef struct walker_t {
- int changes; /**< set, if a reassociation take place */
- ir_graph *irg;
- waitq *wq; /**< a wait queue */
-} walker_t;
-
typedef enum {
NO_CONSTANT = 0, /**< node is not constant */
REAL_CONSTANT = 1, /**< node is a Const that is suitable for constant folding */
*/
static void wq_walker(ir_node *n, void *env)
{
- walker_t *wenv = (walker_t*)env;
+ waitq *const wq = (waitq*)env;
set_irn_link(n, NULL);
if (!is_Block(n)) {
- waitq_put(wenv->wq, n);
- set_irn_link(n, wenv->wq);
+ waitq_put(wq, n);
+ set_irn_link(n, wq);
}
} /* wq_walker */
/**
* The walker for the reassociation.
*/
-static void do_reassociation(walker_t *wenv)
+static void do_reassociation(waitq *const wq)
{
int i, res, changed;
ir_node *n;
- while (! waitq_empty(wenv->wq)) {
- n = (ir_node*)waitq_get(wenv->wq);
+ while (! waitq_empty(wq)) {
+ n = (ir_node*)waitq_get(wq);
set_irn_link(n, NULL);
hook_reassociate(1);
res = 0;
/* for FP these optimizations are only allowed if fp_strict_algebraic is disabled */
- if (mode_is_float(mode) && get_irg_fp_model(wenv->irg) & fp_strict_algebraic)
+ if (mode_is_float(mode) && get_irg_fp_model(get_irn_irg(n)) & fp_strict_algebraic)
break;
if (op->ops.reassociate) {
} while (res == 1);
hook_reassociate(0);
- wenv->changes |= changed;
-
if (changed) {
for (i = get_irn_arity(n) - 1; i >= 0; --i) {
ir_node *pred = get_irn_n(n, i);
- if (get_irn_link(pred) != wenv->wq) {
- waitq_put(wenv->wq, pred);
- set_irn_link(pred, wenv->wq);
+ if (get_irn_link(pred) != wq) {
+ waitq_put(wq, pred);
+ set_irn_link(pred, wq);
}
}
}
*/
static void reverse_rules(ir_node *node, void *env)
{
- walker_t *wenv = (walker_t*)env;
+ (void)env;
+
ir_graph *irg = get_irn_irg(node);
ir_mode *mode = get_irn_mode(node);
int res;
res = 0;
if (is_op_commutative(op)) {
- wenv->changes |= res = move_consts_up(&node);
+ res = move_consts_up(&node);
}
/* beware: move_consts_up might have changed the opcode, check again */
if (is_Add(node) || is_Sub(node)) {
- wenv->changes |= res = reverse_rule_distributive(&node);
+ res = reverse_rule_distributive(&node);
}
} while (res);
}
*/
void optimize_reassociation(ir_graph *irg)
{
- walker_t env;
-
assert(get_irg_phase_state(irg) != phase_building);
assert(get_irg_pinned(irg) != op_pin_state_floats &&
"Reassociation needs pinned graph to work properly");
obstack_init(&commutative_args);
#endif
- env.changes = 0;
- env.irg = irg;
- env.wq = new_waitq();
+ waitq *const wq = new_waitq();
/* disable some optimizations while reassoc is running to prevent endless loops */
set_reassoc_running(1);
{
/* now we have collected enough information, optimize */
- irg_walk_graph(irg, NULL, wq_walker, &env);
- do_reassociation(&env);
+ irg_walk_graph(irg, NULL, wq_walker, wq);
+ do_reassociation(wq);
/* reverse those rules that do not result in collapsed constants */
- irg_walk_graph(irg, NULL, reverse_rules, &env);
+ irg_walk_graph(irg, NULL, reverse_rules, NULL);
}
set_reassoc_running(0);
obstack_free(&commutative_args, NULL);
#endif
- del_waitq(env.wq);
+ del_waitq(wq);
confirm_irg_properties(irg, IR_GRAPH_PROPERTIES_CONTROL_FLOW);
} /* optimize_reassociation */
return def_graph_pass(name ? name : "reassoc", optimize_reassociation);
} /* optimize_reassociation_pass */
-/* Sets the default reassociation operation for an ir_op_ops. */
-ir_op_ops *firm_set_default_reassoc(unsigned code, ir_op_ops *ops)
+static void register_node_reassoc_func(ir_op *op, reassociate_func func)
{
-#define CASE(a) case iro_##a: ops->reassociate = reassoc_##a; break
-
- switch (code) {
- CASE(Mul);
- CASE(Add);
- CASE(Sub);
- CASE(And);
- CASE(Or);
- CASE(Eor);
- CASE(Shl);
- default:
- break;
- }
+ op->ops.reassociate = func;
+}
- return ops;
-#undef CASE
-} /* firm_set_default_reassoc */
+void ir_register_reassoc_node_ops(void)
+{
+ register_node_reassoc_func(op_Mul, reassoc_Mul);
+ register_node_reassoc_func(op_Add, reassoc_Add);
+ register_node_reassoc_func(op_Sub, reassoc_Sub);
+ register_node_reassoc_func(op_And, reassoc_And);
+ register_node_reassoc_func(op_Or, reassoc_Or);
+ register_node_reassoc_func(op_Eor, reassoc_Eor);
+ register_node_reassoc_func(op_Shl, reassoc_Shl);
+}
/* initialize the reassociation by adding operations to some opcodes */
void firm_init_reassociation(void)