more changes. Works for the examples ...
[libfirm] / ir / opt / reassoc.c
index 8f12a13..5e5a163 100644 (file)
@@ -56,7 +56,12 @@ static const_class_t get_const_class(ir_node *n, ir_node *block)
     return REAL_CONSTANT;
   if (op == op_SymConst)
     return CONST_EXPR;
-  if (is_loop_invariant(n, block))
+
+  /*
+   * Beware: Bad nodes are always loop-invariant, but
+   * cannot handled in later code, so filter them here
+   */
+  if (! is_Bad(n) && is_loop_invariant(n, block))
     return CONST_EXPR;
 
   return NO_CONSTANT;
@@ -298,18 +303,21 @@ static int reassoc_Mul(ir_node **node)
     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;
+      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;
 }
@@ -324,7 +332,7 @@ static void do_reassociation(ir_node *n, void *env)
 
   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);
@@ -332,8 +340,8 @@ static void do_reassociation(ir_node *n, void *env)
     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;
     }
@@ -351,6 +359,8 @@ void optimize_reassociation(ir_graph *irg)
   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())
@@ -380,17 +390,28 @@ void optimize_reassociation(ir_graph *irg)
   }
 }
 
+/* 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");
 }