Commit 8b005796 authored by Matthias Braun's avatar Matthias Braun
Browse files

commit my experimental new reassoc before it gets lost (but keep it disabled)

[r20898]
parent 814d67e5
......@@ -36,12 +36,15 @@
#include "iropt_dbg.h"
#include "irflag_t.h"
#include "irgwalk.h"
#include "irouts.h"
#include "reassoc_t.h"
#include "irhooks.h"
#include "irloop.h"
#include "pdeq.h"
#include "debug.h"
//#define NEW_REASSOC
DEBUG_ONLY(static firm_dbg_module_t *dbg;)
typedef struct _walker_t {
......@@ -63,16 +66,13 @@ typedef enum {
* @param n the node to be checked for constant
* @param block a block that might be in a loop
*/
static const_class_t get_const_class(ir_node *n, ir_node *block)
static const_class_t get_const_class(const ir_node *n, const ir_node *block)
{
ir_op *op = get_irn_op(n);
if (op == op_Const)
if (is_Const(n))
return REAL_CONSTANT;
/* although SymConst's are of course real constant, we cannot
fold them, so handle them like region constants */
if (op == op_SymConst)
/* constant nodes which can't be folded are region constants */
if (is_irn_constlike(n))
return REGION_CONST;
/*
......@@ -210,6 +210,8 @@ static ir_mode *get_mode_from_ops(ir_node *op1, ir_node *op2)
return m1;
} /* get_mode_from_ops */
#ifndef NEW_REASSOC
/**
* reassociate a commutative Binop
*
......@@ -242,7 +244,8 @@ static int reassoc_commutative(ir_node **node)
if ( ((c_c1 > NO_CONSTANT) & (c_t2 > NO_CONSTANT)) &&
((((c_c1 ^ c_c2 ^ c_t2) & REGION_CONST) == 0) || ((c_c1 & c_c2 & c_t2) == REGION_CONST)) ) {
/* All three are constant and either all are constant expressions or two of them are:
/* All three are constant and either all are constant expressions
* or two of them are:
* then applying this rule would lead into a cycle
*
* Note that if t2 is a constant so is c2 hence we save one test.
......@@ -257,7 +260,8 @@ static int reassoc_commutative(ir_node **node)
ir_node *irn, *in[2];
ir_mode *mode, *mode_c1 = get_irn_mode(c1), *mode_c2 = get_irn_mode(c2);
/* It might happen, that c1 and c2 have different modes, for instance Is and Iu.
/* It might happen, that c1 and c2 have different modes, for
* instance Is and Iu.
* Handle this here.
*/
if (mode_c1 != mode_c2) {
......@@ -291,9 +295,9 @@ static int reassoc_commutative(ir_node **node)
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.
* So check this.
* 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. So check this.
*/
if (n != irn) {
exchange(n, irn);
......@@ -305,6 +309,135 @@ static int reassoc_commutative(ir_node **node)
return 0;
} /* reassoc_commutative */
#else
static ir_op *commutative_op;
static ir_node *commutative_block;
static struct obstack commutative_args;
static void collect_args(ir_node *node)
{
ir_node *left = get_binop_left(node);
ir_node *right = get_binop_right(node);
if (get_irn_op(left) == commutative_op
&& (!get_irn_outs_computed(left) || get_irn_n_outs(left) == 1)) {
collect_args(left);
} else {
obstack_ptr_grow(&commutative_args, left);
}
if (get_irn_op(right) == commutative_op
&& (!get_irn_outs_computed(right) || get_irn_n_outs(right) == 1)) {
collect_args(right);
} else {
obstack_ptr_grow(&commutative_args, right);
}
#ifndef NDEBUG
{
ir_mode *mode = get_irn_mode(node);
if (is_Add(node) && mode_is_reference(mode)) {
assert(get_irn_mode(left) == mode || get_irn_mode(right) == mode);
} else {
assert(get_irn_mode(left) == mode);
assert(get_irn_mode(right) == mode);
}
}
#endif
}
static int compare_nodes(const ir_node *node1, const ir_node *node2)
{
const_class_t class1 = get_const_class(node1, commutative_block);
const_class_t class2 = get_const_class(node2, commutative_block);
if (class1 == class2)
return 0;
// return get_irn_idx(node1) - get_irn_idx(node2);
if (class1 < class2)
return -1;
assert(class1 > class2);
return 1;
}
static int compare_node_ptr(const void *e1, const void *e2)
{
const ir_node *node1 = *((const ir_node *const*) e1);
const ir_node *node2 = *((const ir_node *const*) e2);
return compare_nodes(node1, node2);
}
static int reassoc_commutative(ir_node **n)
{
int i;
int n_args;
ir_node *last;
ir_node **args;
ir_mode *mode;
ir_node *node = *n;
commutative_op = get_irn_op(node);
commutative_block = get_nodes_block(node);
/* collect all nodes with same op type */
collect_args(node);
n_args = obstack_object_size(&commutative_args) / sizeof(ir_node*);
args = obstack_finish(&commutative_args);
/* shortcut: in most cases there's nothing to do */
if (n_args == 2 && compare_nodes(args[0], args[1]) <= 0) {
obstack_free(&commutative_args, args);
return 0;
}
/* sort the arguments */
qsort(args, n_args, sizeof(ir_node*), compare_node_ptr);
/* build new tree */
last = args[n_args-1];
mode = get_irn_mode(last);
for (i = n_args-2; i >= 0; --i) {
ir_mode *mode_right;
ir_node *new_node;
ir_node *in[2];
in[0] = last;
in[1] = args[i];
/* AddP violates the assumption that all modes in args are equal...
* we need some hacks to cope with this */
mode_right = get_irn_mode(in[1]);
if (mode_is_reference(mode_right)) {
assert(is_Add(node) && mode_is_reference(get_irn_mode(node)));
mode = get_irn_mode(in[1]);
}
if (mode_right != mode) {
assert(is_Add(node) && mode_is_reference(get_irn_mode(node)));
in[1] = new_r_Conv(current_ir_graph, commutative_block,in[1], mode);
}
/* TODO: produce useful debug info! */
new_node = new_ir_node(NULL, current_ir_graph, commutative_block,
commutative_op, mode, 2, in);
new_node = optimize_node(new_node);
last = new_node;
}
/* CSE often returns the old node again, only exchange if needed */
if (last != node) {
exchange(node, last);
*n = last;
return 1;
}
return 0;
}
#endif
#define reassoc_Add reassoc_commutative
#define reassoc_And reassoc_commutative
#define reassoc_Or reassoc_commutative
......@@ -427,7 +560,6 @@ static void do_reassociation(walker_t *wenv)
int i, res, changed;
ir_node *n, *blk;
while (! waitq_empty(wenv->wq)) {
n = waitq_get(wenv->wq);
set_irn_link(n, NULL);
......@@ -756,6 +888,11 @@ void optimize_reassociation(ir_graph *irg)
/* we use dominance to detect dead blocks */
assure_doms(irg);
#ifdef NEW_REASSOC
assure_irg_outs(irg);
obstack_init(&commutative_args);
#endif
/*
* Calculate loop info, so we could identify loop-invariant
* code and threat it like a constant.
......@@ -788,6 +925,10 @@ void optimize_reassociation(ir_graph *irg)
set_irg_loopinfo_inconsistent(irg);
}
#ifdef NEW_REASSOC
obstack_free(&commutative_args, NULL);
#endif
del_waitq(env.wq);
current_ir_graph = rem;
} /* optimize_reassociation */
......
Markdown is supported
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