# include "irloop.h"
# include "debug.h"
-static firm_dbg_module_t *dbg;
+DEBUG_ONLY(static firm_dbg_module_t *dbg;)
typedef struct _walker_t {
int changes; /* set, if a reassociation take place */
return REAL_CONSTANT;
if (op == op_SymConst)
return CONST_EXPR;
+
/*
* Beware: Bad nodes are always loop-invariant, but
- * cannot handles in later code, so filter them here
+ * cannot handled in later code, so filter them here
*/
if (! is_Bad(n) && is_loop_invariant(n, block))
return CONST_EXPR;
t1 = get_binop_left(add_sub);
t2 = get_binop_right(add_sub);
- in[0] = new_rd_Mul(NULL, current_ir_graph, block, c, t1, mode);
- in[1] = new_rd_Mul(NULL, current_ir_graph, block, c, t2, mode);
+ /* we can only multiplication rules on integer arithmetic */
+ if (mode_is_int(get_irn_mode(t1)) && mode_is_int(get_irn_mode(t2))) {
+ in[0] = new_rd_Mul(NULL, current_ir_graph, block, c, t1, mode);
+ in[1] = new_rd_Mul(NULL, current_ir_graph, block, c, t2, mode);
- mode = get_mode_from_ops(in[0], in[1]);
- irn = optimize_node(new_ir_node(NULL, current_ir_graph, block, op, mode, 2, in));
+ mode = get_mode_from_ops(in[0], in[1]);
+ irn = optimize_node(new_ir_node(NULL, current_ir_graph, block, op, mode, 2, in));
- DBG((dbg, LEVEL_5, "Applied: (%n .%s. %n) %n %n => (%n %n %n) .%s. (%n %n %n)\n",
- t1, get_op_name(op), t2, n, c, t1, n, c, get_op_name(op), t2, n, c));
- exchange(n, irn);
- *node = irn;
+ /* In some cases it might happen that the new irn is equal the old one, for
+ * instance in:
+ * (x - 1) * y == x * y - y
+ * will be transformed back by simpler optimization
+ * We could switch simple optimizations off, but this only happens iff y
+ * is a loop-invariant expreassion and that it is not clear if the new form
+ * is better.
+ * So, we let the old one.
+ */
+ if (irn != n) {
+ DBG((dbg, LEVEL_5, "Applied: (%n .%s. %n) %n %n => (%n %n %n) .%s. (%n %n %n)\n",
+ t1, get_op_name(op), t2, n, c, t1, n, c, get_op_name(op), t2, n, c));
+ exchange(n, irn);
+ *node = irn;
- return 1;
+ return 1;
+ }
+ }
}
return 0;
}
hook_reassociate(1);
- /* Reassociation must run until a fixpoint is reached. */
+ /* reassociation must run until a fixpoint is reached. */
do {
ir_op *op = get_irn_op(n);
ir_mode *mode = get_irn_mode(n);
res = 0;
/* reassociation works only for integer or reference modes */
- if (op->reassociate && (mode_is_int(mode) || mode_is_reference(mode))) {
- res = op->reassociate(&n);
+ if (op->ops.reassociate && (mode_is_int(mode) || mode_is_reference(mode))) {
+ res = op->ops.reassociate(&n);
wenv->changes |= res;
}
irg_loopinfo_state state;
assert(get_irg_phase_state(irg) != phase_building);
+ assert(get_irg_pinned(irg) != op_pin_state_floats &&
+ "Reassociation needs pinned graph to work properly");
/* reassociation needs constant folding */
if (!get_opt_reassociation() || !get_opt_constant_folding())
}
}
+/* Sets the default reassociation operation for an ir_op_ops. */
+ir_op_ops *firm_set_default_reassoc(opcode code, ir_op_ops *ops)
+{
+#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);
+ default:
+ /* leave NULL */;
+ }
+
+ return ops;
+#undef CASE
+}
+
/* initialize the reassociation by adding operations to some opcodes */
void firm_init_reassociation(void)
{
-#define INIT(a) op_##a->reassociate = reassoc_##a;
- INIT(Mul);
- INIT(Add);
- INIT(Sub);
- INIT(And);
- INIT(Or);
- INIT(Eor);
-#undef INIT
-
- dbg = firm_dbg_register("firm.opt.reassoc");
+ FIRM_DBG_REGISTER(dbg, "firm.opt.reassoc");
}