fix trailing whitespaces and tabulators in the middle of a line
[libfirm] / ir / opt / reassoc.c
index 5c13a7b..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 "irtools.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;
@@ -221,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;
 
@@ -305,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 */
 
@@ -498,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;
@@ -537,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) {
@@ -616,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;
@@ -640,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)) {
@@ -663,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);
@@ -745,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];
@@ -781,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);
@@ -845,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;
@@ -934,7 +992,8 @@ int optimize_reassociation(ir_graph *irg)
 }  /* optimize_reassociation */
 
 /* create a pass for the reassociation */
-ir_graph_pass_t *optimize_reassociation_pass(const char *name) {
+ir_graph_pass_t *optimize_reassociation_pass(const char *name)
+{
        return def_graph_pass_ret(name ? name : "reassoc", optimize_reassociation);
 }  /* optimize_reassociation_pass */