Commit 2345458a by Michael Beck

add a phase to reverse distributive law rules

`[r15583]`
parent cab6b486
 ... ... @@ -129,7 +129,7 @@ static void get_comm_Binop_ops(ir_node *binop, ir_node **a, ir_node **c) } /* get_comm_Binop_ops */ /** * reassociate a Sub: x - c = (-c) + x * reassociate a Sub: x - c = x + (-c) */ static int reassoc_Sub(ir_node **in) { ... ... @@ -145,16 +145,13 @@ static int reassoc_Sub(ir_node **in) block = get_nodes_block(n); /* handles rule R6: * convert x - c => (-c) + x * * As there is NO real Minus in Firm it makes no sense to do this * for non-real constants yet. * convert x - c => x + (-c) */ if (get_const_class(right, block) == REAL_CONSTANT) { ir_node *left = get_Sub_left(n); ir_mode *mode; dbg_info *dbi; ir_node *irn, *c; ir_node *irn; switch (get_const_class(left, block)) { case REAL_CONSTANT: ... ... @@ -175,15 +172,13 @@ static int reassoc_Sub(ir_node **in) dbi = get_irn_dbg_info(n); /* Beware of SubP(P, Is) */ c = new_r_Const(current_ir_graph, block, rmode, get_mode_null(rmode)); irn = new_rd_Sub(dbi, current_ir_graph, block, c, right, rmode); irn = new_rd_Minus(dbi, current_ir_graph, block, right, rmode); irn = new_rd_Add(dbi, current_ir_graph, block, left, irn, get_irn_mode(n)); DBG((dbg, LEVEL_5, "Applied: %n - %n => %n + (-%n)\n", get_Sub_left(n), c, get_Sub_left(n), c)); get_Sub_left(n), right, get_Sub_left(n), right)); if(n == irn) if (n == irn) return 0; exchange(n, irn); ... ... @@ -256,7 +251,7 @@ static int reassoc_commutative(ir_node **node) if ((c_c1 != NO_CONSTANT) /* & (c_c2 != NO_CONSTANT) */) { /* handles rules R7, R8, R9, R10: * convert c1 .OP. (c2 .OP. x) => (c1 .OP. c2) .OP. x * convert c1 .OP. (c2 .OP. x) => x .OP. (c1 .OP. c2) */ ir_node *irn, *in[2]; ir_mode *mode, *mode_c1 = get_irn_mode(c1), *mode_c2 = get_irn_mode(c2); ... ... @@ -284,16 +279,16 @@ static int reassoc_commutative(ir_node **node) in[0] = c1; in[1] = c2; mode = get_mode_from_ops(in[0], in[1]); in[0] = optimize_node(new_ir_node(NULL, current_ir_graph, block, op, mode, 2, in)); in[1] = t2; mode = get_mode_from_ops(in[0], in[1]); in[1] = optimize_node(new_ir_node(NULL, current_ir_graph, block, op, mode, 2, in)); in[0] = t2; 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 .%s. %n) => (%n .%s. %n) .%s. %n\n", c1, get_irn_opname(n), c2, get_irn_opname(n), t2, c1, get_irn_opname(n), c2, get_irn_opname(n), t2)); DBG((dbg, LEVEL_5, "Applied: %n .%s. (%n .%s. %n) => %n .%s. (%n .%s. %n)\n", c1, get_irn_opname(n), c2, get_irn_opname(n), t2, t2, get_irn_opname(n), c1, get_irn_opname(n), c2)); /* * In some rare cases it can really happen that we get the same node back. * This might be happen in dead loops, were the Phi nodes are already gone away. ... ... @@ -315,7 +310,7 @@ static int reassoc_commutative(ir_node **node) #define reassoc_Eor reassoc_commutative /** * reassociate using distributive law for Mul and Add/Sub * Reassociate using commutative law for Mul and distributive law for Mul and Add/Sub: */ static int reassoc_Mul(ir_node **node) { ... ... @@ -449,6 +444,106 @@ static void do_reassociation(walker_t *wenv) } } /* do_reassociation */ /** * Returns the earliest were a,b are available. * Note that we know that we know that a, b both dominate * the block of the previous operation, so one must dominate the other. */ static ir_node *earliest_block(ir_node *a, ir_node *b) { ir_node *blk_a = get_nodes_block(a); ir_node *blk_b = get_nodes_block(b); /* if blk_a != blk_b, one must dominate the other */ if (block_dominates(blk_a, blk_b)) return blk_b; else return blk_a; } /** * Apply distributive Law for Mul and Add/Sub */ static int reverse_rule_distributive(ir_node **node) { ir_node *n = *node; ir_node *left = get_binop_left(n); ir_node *right = get_binop_right(n); ir_node *x, *blk; ir_node *a, *b, *irn; ir_mode *mode; dbg_info *dbg; if (! is_Mul(left) || !is_Mul(right)) return 0; x = get_Mul_left(left); if (x == get_Mul_left(right)) { /* (x * a) +/- (x * b) */ a = get_Mul_right(left); b = get_Mul_right(right); goto transform; } else if (x == get_Mul_right(right)) { /* (x * a) +/- (b * x) */ a = get_Mul_right(left); b = get_Mul_left(right); goto transform; } x = get_Mul_right(left); if (x == get_Mul_right(right)) { /* (a * x) +/- (b * x) */ a = get_Mul_left(left); b = get_Mul_left(right); goto transform; } else if (x == get_Mul_left(right)) { /* (a * x) +/- (x * b) */ a = get_Mul_left(left); b = get_Mul_right(right); goto transform; } return 0; transform: blk = earliest_block(a, b); dbg = get_irn_dbg_info(n); mode = get_irn_mode(n); if (is_Add(n)) irn = new_rd_Add(dbg, current_ir_graph, blk, a, b, mode); else irn = new_rd_Sub(dbg, current_ir_graph, blk, a, b, mode); blk = earliest_block(irn, x); irn = new_rd_Mul(dbg, current_ir_graph, blk, irn, x, mode); exchange(n, irn); *node = irn; return 1; } /* reverse_rule_distributive */ /** * Apply the rules in reverse order, removing code that was not collapsed */ static void reverse_rules(ir_node *node, void *env) { walker_t *wenv = env; ir_mode *mode = get_irn_mode(node); int res; /* for FP these optimizations are only allowed if fp_strict_algebraic is disabled */ if (mode_is_float(mode) && get_irg_fp_model(current_ir_graph) & fp_strict_algebraic) return; do { res = 0; if (is_Add(node) || is_Sub(node)) { wenv->changes |= res = reverse_rule_distributive(&node); } } while (res); } /* * do the reassociation */ ... ... @@ -486,6 +581,9 @@ void optimize_reassociation(ir_graph *irg) irg_walk_graph(irg, NULL, wq_walker, &env); do_reassociation(&env); /* reverse those rules that do not result in collapsed constants */ irg_walk_graph(irg, NULL, reverse_rules, &env); /* Handle graph state */ if (env.changes) { set_irg_outs_inconsistent(irg); ... ...
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!