- BugFix: when splitting by input, ensure than Z is split by ALL inputs
[libfirm] / ir / ir / iropt.c
index 631570b..7603a49 100644 (file)
@@ -4546,7 +4546,7 @@ static ir_node *transform_node_Or_bf_store(ir_node *or) {
 static ir_node *transform_node_Or_Rotl(ir_node *or) {
        ir_mode *mode = get_irn_mode(or);
        ir_node *shl, *shr, *block;
-       ir_node *irn, *x, *c1, *c2, *v, *sub, *n;
+       ir_node *irn, *x, *c1, *c2, *v, *sub, *n, *rotval;
        tarval *tv1, *tv2;
 
        if (! mode_is_int(mode))
@@ -4587,64 +4587,45 @@ static ir_node *transform_node_Or_Rotl(ir_node *or) {
                        return or;
 
                /* yet, condition met */
-               block = get_irn_n(or, -1);
+               block = get_nodes_block(or);
 
                n = new_r_Rotl(current_ir_graph, block, x, c1, mode);
 
                DBG_OPT_ALGSIM1(or, shl, shr, n, FS_OPT_OR_SHFT_TO_ROTL);
                return n;
-       } else if (is_Sub(c1)) {
-               v   = c2;
-               sub = c1;
-
-               if (get_Sub_right(sub) != v)
-                       return or;
-
-               c1 = get_Sub_left(sub);
-               if (!is_Const(c1))
-                       return or;
-
-               tv1 = get_Const_tarval(c1);
-               if (! tarval_is_long(tv1))
-                       return or;
-
-               if (get_tarval_long(tv1) != (int) get_mode_size_bits(mode))
-                       return or;
-
-               /* yet, condition met */
-               block = get_nodes_block(or);
-
-               /* a Rot right is not supported, so use a rot left */
-               n =  new_r_Rotl(current_ir_graph, block, x, sub, mode);
+       }
 
-               DBG_OPT_ALGSIM0(or, n, FS_OPT_OR_SHFT_TO_ROTL);
-               return n;
-       } else if (is_Sub(c2)) {
-               v   = c1;
-               sub = c2;
+    if (is_Sub(c1)) {
+           v      = c2;
+               sub    = c1;
+        rotval = sub; /* a Rot right is not supported, so use a rot left */
+    } else if (is_Sub(c2)) {
+               v      = c1;
+       sub    = c2;
+        rotval = v;
+    } else return or;
 
-               c1 = get_Sub_left(sub);
-               if (!is_Const(c1))
-                       return or;
+       if (get_Sub_right(sub) != v)
+               return or;
 
-               tv1 = get_Const_tarval(c1);
-               if (! tarval_is_long(tv1))
-                       return or;
+       c1 = get_Sub_left(sub);
+       if (!is_Const(c1))
+               return or;
 
-               if (get_tarval_long(tv1) != (int) get_mode_size_bits(mode))
-                       return or;
+       tv1 = get_Const_tarval(c1);
+       if (! tarval_is_long(tv1))
+               return or;
 
-               /* yet, condition met */
-               block = get_irn_n(or, -1);
+       if (get_tarval_long(tv1) != (int) get_mode_size_bits(mode))
+               return or;
 
-               /* a Rot Left */
-               n = new_r_Rotl(current_ir_graph, block, x, v, mode);
+       /* yet, condition met */
+       block = get_nodes_block(or);
 
-               DBG_OPT_ALGSIM0(or, n, FS_OPT_OR_SHFT_TO_ROTL);
-               return n;
-       }
+       n = new_r_Rotl(current_ir_graph, block, x, rotval, mode);
 
-       return or;
+       DBG_OPT_ALGSIM0(or, n, FS_OPT_OR_SHFT_TO_ROTL);
+       return n;
 }  /* transform_node_Or_Rotl */
 
 /**
@@ -4857,10 +4838,10 @@ static ir_node *transform_node_bitop_shift(ir_node *n) {
 
 /**
  * normalisation:
- *    (x << c1) >> c2  <=>  x>>(c2-c1) & (-1>>c2)
+ *    (x << c1) >> c2  <=>  x OP (c2-c1) & ((-1 << c1) >> c2)
  *    also:
- *     if c2 > c1:   x << (c2-c1)
- *    (x >>s c2) << c1  <=>  x>>s(c2-c1) & (-1>>c2)
+ *    (x >> c1) << c2  <=>  x OP (c2-c1) & ((-1 >> c1) << c2)
+ *      (also with x >>s c1  when c1>=c2)
  */
 static ir_node *transform_node_shl_shr(ir_node *n) {
        ir_node  *left;
@@ -5727,38 +5708,14 @@ int identities_cmp(const void *elt, const void *key) {
 
 /*
  * Calculate a hash value of a node.
+ *
+ * @param node  The IR-node
  */
 unsigned ir_node_hash(const ir_node *node) {
-       unsigned h;
-       int i, irn_arity;
-
-       if (node->op == op_Const) {
-               /* special value for const, as they only differ in their tarval. */
-               h = HASH_PTR(node->attr.con.tv);
-               h = 9*h + HASH_PTR(get_irn_mode(node));
-       } else if (node->op == op_SymConst) {
-               /* special value for const, as they only differ in their symbol. */
-               h = HASH_PTR(node->attr.symc.sym.type_p);
-               h = 9*h + HASH_PTR(get_irn_mode(node));
-       } else {
-
-               /* hash table value = 9*(9*(9*(9*(9*arity+in[0])+in[1])+ ...)+mode)+code */
-               h = irn_arity = get_irn_intra_arity(node);
-
-               /* consider all in nodes... except the block if not a control flow. */
-               for (i = is_cfop(node) ? -1 : 0;  i < irn_arity;  i++) {
-                       h = 9*h + HASH_PTR(get_irn_intra_n(node, i));
-               }
-
-               /* ...mode,... */
-               h = 9*h + HASH_PTR(get_irn_mode(node));
-               /* ...and code */
-               h = 9*h + HASH_PTR(get_irn_op(node));
-       }
-
-       return h;
+       return node->op->ops.hash(node);
 }  /* ir_node_hash */
 
+
 pset *new_identities(void) {
        return new_pset(identities_cmp, N_IR_NODES);
 }  /* new_identities */
@@ -6206,10 +6163,69 @@ ir_node *optimize_in_place(ir_node *n) {
        return optimize_in_place_2(n);
 }  /* optimize_in_place */
 
+/**
+ * Calculate a hash value of a Const node.
+ */
+static unsigned hash_Const(const ir_node *node) {
+       unsigned h;
+
+       /* special value for const, as they only differ in their tarval. */
+       h = HASH_PTR(node->attr.con.tv);
+       h = 9*h + HASH_PTR(get_irn_mode(node));
+
+       return h;
+}  /* hash_Const */
+
+/**
+ * Calculate a hash value of a SymConst node.
+ */
+static unsigned hash_SymConst(const ir_node *node) {
+       unsigned h;
+
+       /* special value for const, as they only differ in their symbol. */
+       h = HASH_PTR(node->attr.symc.sym.type_p);
+       h = 9*h + HASH_PTR(get_irn_mode(node));
+
+       return h;
+}  /* hash_SymConst */
+
+/**
+ * Set the default hash operation in an ir_op_ops.
+ *
+ * @param code   the opcode for the default operation
+ * @param ops    the operations initialized
+ *
+ * @return
+ *    The operations.
+ */
+static ir_op_ops *firm_set_default_hash(ir_opcode code, ir_op_ops *ops)
+{
+#define CASE(a)                                    \
+       case iro_##a:                                  \
+               ops->hash  = hash_##a; \
+               break
+
+       /* hash function already set */
+       if (ops->hash != NULL)
+               return ops;
+
+       switch (code) {
+       CASE(Const);
+       CASE(SymConst);
+       default:
+               /* use input/mode default hash if no function was given */
+               ops->hash = firm_default_hash;
+       }
+
+       return ops;
+#undef CASE
+}
+
 /*
  * Sets the default operation for an ir_ops.
  */
 ir_op_ops *firm_set_default_operations(ir_opcode code, ir_op_ops *ops) {
+       ops = firm_set_default_hash(code, ops);
        ops = firm_set_default_computed_value(code, ops);
        ops = firm_set_default_equivalent_node(code, ops);
        ops = firm_set_default_transform_node(code, ops);