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))
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 */
/**
/**
* 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;
/*
* 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 */
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);