Commit c6710d5f authored by Matthias Braun's avatar Matthias Braun
Browse files

localopt: simple associativity optimisation

Add op(op(x, c0), c1) => op(x, op(c0, c1)) as localopt rule. This is an
very usual and often encountered case so it makes sense to have this
working without explicitely invoking the associativity optimisation phase.
parent c386867b
......@@ -70,7 +70,7 @@ void firm_collect_block_phis(ir_node *node, void *env);
/**
* Creates an exact copy of a node with same inputs and attributes in the
* same block.
* same block. The copied node will not be optimized (so no CSE is performed).
*
* @param node the node to copy
*/
......
......@@ -2461,6 +2461,55 @@ static bool complement_values(const ir_node *a, const ir_node *b)
return false;
}
typedef ir_tarval *(tv_fold_binop_func)(ir_tarval *a, ir_tarval *b);
/**
* for associative operations fold:
* op(op(x, c0), c1) to op(x, op(c0, c1)) with constants folded.
* This is a "light" version of the reassociation phase
*/
static ir_node *fold_constant_associativity(ir_node *node,
tv_fold_binop_func fold)
{
ir_graph *irg;
ir_op *op;
ir_node *left;
ir_node *right = get_binop_right(node);
ir_node *left_right;
ir_node *left_left;
ir_tarval *c0;
ir_tarval *c1;
ir_tarval *new_c;
ir_node *new_const;
ir_node *new_node;
if (!is_Const(right))
return node;
op = get_irn_op(node);
left = get_binop_left(node);
if (get_irn_op(left) != op)
return node;
left_right = get_binop_right(left);
if (!is_Const(left_right))
return node;
left_left = get_binop_left(left);
c0 = get_Const_tarval(left_right);
c1 = get_Const_tarval(right);
irg = get_irn_irg(node);
if (get_tarval_mode(c0) != get_tarval_mode(c1))
return node;
new_c = fold(c0, c1);
if (new_c == tarval_bad)
return node;
new_const = new_r_Const(irg, new_c);
new_node = exact_copy(node);
set_binop_left(new_node, left_left);
set_binop_right(new_node, new_const);
return new_node;
}
/**
* Transform an Or.
*/
......@@ -2472,6 +2521,10 @@ static ir_node *transform_node_Or_(ir_node *n)
ir_node *c;
ir_mode *mode;
n = fold_constant_associativity(n, tarval_or);
if (n != oldn)
return n;
if (is_Not(a) && is_Not(b)) {
/* ~a | ~b = ~(a&b) */
ir_node *block = get_nodes_block(n);
......@@ -2576,6 +2629,10 @@ static ir_node *transform_node_Eor_(ir_node *n)
ir_mode *mode = get_irn_mode(n);
ir_node *c;
n = fold_constant_associativity(n, tarval_eor);
if (n != oldn)
return n;
/* we can combine the relations of two compares with the same operands */
if (is_Cmp(a) && is_Cmp(b)) {
ir_node *a_left = get_Cmp_left(a);
......@@ -2643,8 +2700,6 @@ static ir_node *transform_node_Eor(ir_node *n)
return transform_node_Eor_(n);
}
/**
* Do the AddSub optimization, then Transform
* Constant folding on Phi
......@@ -2662,6 +2717,10 @@ static ir_node *transform_node_Add(ir_node *n)
ir_node *c;
ir_node *oldn = n;
n = fold_constant_associativity(n, tarval_add);
if (n != oldn)
return n;
n = transform_node_AddSub(n);
if (n != oldn)
return n;
......@@ -3149,7 +3208,8 @@ static ir_node *transform_node_Mul(ir_node *n)
ir_node *a = get_Mul_left(n);
ir_node *b = get_Mul_right(n);
if (is_Bad(a) || is_Bad(b))
n = fold_constant_associativity(n, tarval_mul);
if (n != oldn)
return n;
if (mode != get_irn_mode(a))
......@@ -3646,6 +3706,10 @@ static ir_node *transform_node_And(ir_node *n)
ir_node *b = get_And_right(n);
ir_mode *mode;
n = fold_constant_associativity(n, tarval_and);
if (n != oldn)
return n;
if (is_Cmp(a) && is_Cmp(b)) {
ir_node *a_left = get_Cmp_left(a);
ir_node *a_right = get_Cmp_right(a);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment