fix trailing whitespaces and tabulators in the middle of a line
[libfirm] / ir / opt / reassoc.c
index db0e9a1..c008b15 100644 (file)
@@ -25,6 +25,7 @@
  */
 #include "config.h"
 
+#include "iroptimize.h"
 #include "iropt_t.h"
 #include "irnode_t.h"
 #include "irgraph_t.h"
 #include "irgwalk.h"
 #include "irouts.h"
 #include "reassoc_t.h"
+#include "opt_init.h"
 #include "irhooks.h"
 #include "irloop.h"
 #include "pdeq.h"
 #include "debug.h"
+#include "irpass.h"
 
 //#define NEW_REASSOC
 
 DEBUG_ONLY(static firm_dbg_module_t *dbg;)
 
-typedef struct _walker_t {
+typedef struct walker_t {
        int   changes;        /**< set, if a reassociation take place */
        waitq *wq;            /**< a wait queue */
 } walker_t;
@@ -171,8 +174,8 @@ static int reassoc_Sub(ir_node **in)
                dbi  = get_irn_dbg_info(n);
 
                /* Beware of SubP(P, Is) */
-               irn = new_rd_Minus(dbi, current_ir_graph, block, right, rmode);
-               irn = new_rd_Add(dbi, current_ir_graph, block, left, irn, mode);
+               irn = new_rd_Minus(dbi, block, right, rmode);
+               irn = new_rd_Add(dbi, block, left, irn, mode);
 
                DBG((dbg, LEVEL_5, "Applied: %n - %n => %n + (-%n)\n",
                        get_Sub_left(n), right, get_Sub_left(n), right));
@@ -220,7 +223,7 @@ static ir_mode *get_mode_from_ops(ir_node *op1, ir_node *op2)
 static int reassoc_commutative(ir_node **node)
 {
        ir_node *n     = *node;
-       ir_op *op      = get_irn_op(n);
+       ir_op   *op    = get_irn_op(n);
        ir_node *block = get_nodes_block(n);
        ir_node *t1, *c1;
 
@@ -266,15 +269,15 @@ static int reassoc_commutative(ir_node **node)
                                if (mode_is_int(mode_c1) && mode_is_int(mode_c2)) {
                                        /* get the bigger one */
                                        if (get_mode_size_bits(mode_c1) > get_mode_size_bits(mode_c2))
-                                               c2 = new_r_Conv(current_ir_graph, block, c2, mode_c1);
+                                               c2 = new_r_Conv(block, c2, mode_c1);
                                        else if (get_mode_size_bits(mode_c1) < get_mode_size_bits(mode_c2))
-                                               c1 = new_r_Conv(current_ir_graph, block, c1, mode_c2);
+                                               c1 = new_r_Conv(block, c1, mode_c2);
                                        else {
                                                /* Try to cast the real const */
                                                if (c_c1 == REAL_CONSTANT)
-                                                       c1 = new_r_Conv(current_ir_graph, block, c1, mode_c2);
+                                                       c1 = new_r_Conv(block, c1, mode_c2);
                                                else
-                                                       c2 = new_r_Conv(current_ir_graph, block, c2, mode_c1);
+                                                       c2 = new_r_Conv(block, c2, mode_c1);
                                        }
                                }
                        }
@@ -304,6 +307,55 @@ static int reassoc_commutative(ir_node **node)
                        }
                }
        }
+       if (get_irn_op(c1) == op) {
+               ir_node *t = c1;
+               c1 = t1;
+               t1 = t;
+       }
+       if (get_irn_op(t1) == op) {
+               ir_node *l = get_binop_left(t1);
+               ir_node *r = get_binop_right(t1);
+               const_class_t c_r;
+
+               if (r == c1) {
+                       ir_node *t = r;
+                       r = l;
+                       l = t;
+               }
+               c_r = get_const_class(r, block);
+               if (c_r != NO_CONSTANT) {
+                       /*
+                        * Beware: don't do the following op if a constant was
+                        * placed below, else we will fall into a loop.
+                        */
+                       return 0;
+               }
+
+               if (l == c1) {
+                       /* convert x .OP. (x .OP. y) => y .OP. (x .OP. x) */
+                       ir_mode *mode_res = get_irn_mode(n);
+                       ir_mode *mode_c1  = get_irn_mode(c1);
+                       ir_node *irn, *in[2];
+
+                       in[0] = c1;
+                       in[1] = c1;
+
+                       in[1] = optimize_node(new_ir_node(NULL, current_ir_graph, block, op, mode_c1, 2, in));
+                       in[0] = r;
+
+                       irn   = optimize_node(new_ir_node(NULL, current_ir_graph, block, op, mode_res, 2, in));
+
+                       DBG((dbg, LEVEL_5, "Applied: %n .%s. (%n .%s. %n) => %n .%s. (%n .%s. %n)\n",
+                               c1, get_irn_opname(n), l, get_irn_opname(n), r,
+                               r, get_irn_opname(n), c1, get_irn_opname(n), c1));
+
+                       if (n != irn) {
+                               exchange(n, irn);
+                               *node = irn;
+                               return 1;
+                       }
+               }
+       }
        return 0;
 }  /* reassoc_commutative */
 
@@ -467,8 +519,8 @@ static int reassoc_Mul(ir_node **node)
 
                /* 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);
+                       in[0] = new_rd_Mul(NULL, block, c, t1, mode);
+                       in[1] = new_rd_Mul(NULL, block, c, t2, mode);
 
                        irn   = optimize_node(new_ir_node(NULL, current_ir_graph, block, op, mode, 2, in));
 
@@ -497,7 +549,8 @@ static int reassoc_Mul(ir_node **node)
 /**
  * Reassociate Shl. We transform Shl(x, const) into Mul's if possible.
  */
-static int reassoc_Shl(ir_node **node) {
+static int reassoc_Shl(ir_node **node)
+{
        ir_node *n = *node;
        ir_node *c = get_Shl_right(n);
        ir_node *x, *blk, *irn;
@@ -517,8 +570,8 @@ static int reassoc_Shl(ir_node **node) {
                return 0;
 
        blk = get_nodes_block(n);
-       c   = new_Const(mode, tv);
-       irn = new_rd_Mul(get_irn_dbg_info(n), current_ir_graph, blk, x, c, mode);
+       c   = new_Const(tv);
+       irn = new_rd_Mul(get_irn_dbg_info(n), blk, x, c, mode);
 
        if (irn != n) {
                exchange(n, irn);
@@ -536,7 +589,7 @@ static void wq_walker(ir_node *n, void *env)
        walker_t *wenv = env;
 
        set_irn_link(n, NULL);
-       if (is_no_Block(n)) {
+       if (!is_Block(n)) {
                ir_node *blk = get_nodes_block(n);
 
                if (is_Block_dead(blk) || get_Block_dom_depth(blk) < 0) {
@@ -615,7 +668,8 @@ static void do_reassociation(walker_t *wenv)
  *
  * If the earliest block is the start block, return curr_blk instead
  */
-static ir_node *earliest_block(ir_node *a, ir_node *b, ir_node *curr_blk) {
+static ir_node *earliest_block(ir_node *a, ir_node *b, ir_node *curr_blk)
+{
        ir_node *blk_a = get_nodes_block(a);
        ir_node *blk_b = get_nodes_block(b);
        ir_node *res;
@@ -639,7 +693,8 @@ static ir_node *earliest_block(ir_node *a, ir_node *b, ir_node *curr_blk) {
  * Handling SymConsts as const might be not a good idea for all
  * architectures ...
  */
-static int is_constant_expr(ir_node *irn) {
+static int is_constant_expr(ir_node *irn)
+{
        ir_op *op;
 
        switch (get_irn_opcode(irn)) {
@@ -662,7 +717,8 @@ static int is_constant_expr(ir_node *irn) {
 /**
  * Apply distributive Law for Mul and Add/Sub
  */
-static int reverse_rule_distributive(ir_node **node) {
+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);
@@ -725,16 +781,16 @@ transform:
        mode = get_irn_mode(n);
 
        if (is_Add(n))
-               irn = new_rd_Add(dbg, current_ir_graph, blk, a, b, mode);
+               irn = new_rd_Add(dbg, blk, a, b, mode);
        else
-               irn = new_rd_Sub(dbg, current_ir_graph, blk, a, b, mode);
+               irn = new_rd_Sub(dbg, blk, a, b, mode);
 
        blk  = earliest_block(irn, x, curr_blk);
 
        if (op == op_Mul)
-               irn = new_rd_Mul(dbg, current_ir_graph, blk, irn, x, mode);
+               irn = new_rd_Mul(dbg, blk, irn, x, mode);
        else
-               irn = new_rd_Shl(dbg, current_ir_graph, blk, irn, x, mode);
+               irn = new_rd_Shl(dbg, blk, irn, x, mode);
 
        exchange(n, irn);
        *node = irn;
@@ -744,7 +800,8 @@ transform:
 /**
  * Move Constants towards the root.
  */
-static int move_consts_up(ir_node **node) {
+static int move_consts_up(ir_node **node)
+{
        ir_node *n = *node;
        ir_op *op;
        ir_node *l, *r, *a, *b, *c, *blk, *irn, *in[2];
@@ -780,7 +837,8 @@ static int move_consts_up(ir_node **node) {
                        dbg = dbg == get_irn_dbg_info(l) ? dbg : NULL;
                        goto transform;
                }
-       } else if (get_irn_op(r) == op) {
+       }
+       if (get_irn_op(r) == op) {
                /* l .op. (a .op. b) */
                a = get_binop_left(r);
                b = get_binop_right(r);
@@ -844,7 +902,8 @@ transform:
 /**
  * Apply the rules in reverse order, removing code that was not collapsed
  */
-static void reverse_rules(ir_node *node, void *env) {
+static void reverse_rules(ir_node *node, void *env)
+{
        walker_t *wenv = env;
        ir_mode *mode = get_irn_mode(node);
        int res;
@@ -932,6 +991,12 @@ int optimize_reassociation(ir_graph *irg)
        return env.changes;
 }  /* optimize_reassociation */
 
+/* create a pass for the reassociation */
+ir_graph_pass_t *optimize_reassociation_pass(const char *name)
+{
+       return def_graph_pass_ret(name ? name : "reassoc", optimize_reassociation);
+}  /* optimize_reassociation_pass */
+
 /* Sets the default reassociation operation for an ir_op_ops. */
 ir_op_ops *firm_set_default_reassoc(ir_opcode code, ir_op_ops *ops)
 {