#include "bitset.h"
#include "debug.h"
#include "bechordal.h"
+#include "belive.h"
#include "bera_t.h"
#include "bephicongr_t.h"
#include "bephicoal_t.h"
-static firm_dbg_module_t *dbgphi = NULL;
+#define DEBUG_LVL 1
-void be_phi_coal_init(void) {
- dbgphi = firm_dbg_register("Phi coalescing");
- firm_dbg_set_mask(dbgphi, 1);
-}
+#define MAX_PHI_CLS_SIZE (1<<(sizeof(unsigned char)*8)) /* possible colors added should fit into unsigned char */
+#define MAX_COLORS 16
-static INLINE ir_node **pset_to_array(pset *theset) {
- ir_node **res, *p;
- int i, count;
+static firm_dbg_module_t *dbgphi = NULL;
- count = pset_count(theset);
- res = (ir_node **) malloc(count * sizeof(ir_node*));
- for (i = 0, p = (ir_node *)pset_first(theset); p; p = (ir_node *)pset_next(theset))
- res[i++] = p;
- assert(i == count);
- return res;
-}
+typedef enum _live_status_t {
+ livein = 1,
+ liveout = 2
+} live_status_t;
+
+
+typedef struct _phi_unit_t {
+ unsigned char count;
+ unsigned char phi_count;
+ ir_node **members; /* [0..phi_count-1] are phi nodes. [phi_count..count-1] the rest/arguments of the phis */
+ bitset_t **used_cols;
+ int *tgt_colors; /* [i] is the color to set for members[i]. [i] == -1 means dont change anything for members[i]*/
+ live_status_t *live_info; /* [i] says how/where members[i] is live */
+} phi_unit_t;
-static INLINE pset *clone(pset *theset) {
- void *p;
- pset *res;
+static pset *done;
- res = pset_new_ptr(8);
- for (p = pset_first(theset); p; p = pset_next(theset))
- pset_insert_ptr(res, p);
- return res;
+static INLINE void set_color(ir_node *irn, int col) {
+ if (!pset_find_ptr(done, irn)) {
+ set_irn_color(irn, col);
+ pset_insert_ptr(done, irn);
+ }
}
-static void coalesce_locals(pset *phi_class, dominfo_t *dominfo) {
- int i, count, phi_count, arity, intf_det, phi_col, allfree;
- pset *pc, *intffree;
- ir_node *phi = NULL, *n, *m;
-// ir_node **members;
+static void coalesce(phi_unit_t *pu) {
+ int i;
+ if (pu->phi_count != 1) {
+ DBG((dbgphi, 1, "Dropped: phicount\n"));
+ return;
+ }
+#if 0
- count = pset_count(phi_class);
- pc = clone(phi_class);
-// members = pset_to_array(phi_class);
+ done = pset_new_ptr(64);
- /* how many phi nodes are in this class? */
- DBG((dbgphi, 1, "Checking phi count\n"));
- phi_count = 0;
- for (n = (ir_node *)pset_first(pc); n; n = (ir_node *)pset_next(pc)) {
- if (is_Phi(n)) {
- phi = n;
- phi_count++;
+ for (i = 0; i < pu->count; ++i)
+ if (pu->live_info[i] & livein) {
+ DBG((dbgphi, 1, "Dropped: live-in\n"));
+ return;
+ }
+
+ for (i = 0; i < pu->count; ++i) {
+ block_list_t *bl;
+
+ if (pu->tgt_colors[i] == -1)
+ continue;
+
+ /* TODO: if we move ahead to swapping (not just allocating new colors) this is wrong */
+ set_color(pu->members[i], pu->tgt_colors[i]);
+ if (pu->live_info[i] & liveout) {
+ bl = get_dominated_dfs(get_nodes_block(pu->members[i]));
}
}
- if (phi_count > 1) {
- DBG((dbgphi, 1, "Dropped: Too many phis\n"));
- goto exit;
+ del_pset(done);
+
+#endif
+}
+
+
+static void ana_1_phi(phi_unit_t *pu) {
+ ir_node *phi, *phi_blk;
+ int i, o, n, col, best_color, size, best_size;
+ ir_node **cand, **max_set, **best_max_set;
+
+ cand = malloc(pu->count * sizeof(ir_node*));
+ max_set = malloc(pu->count * sizeof(ir_node*));
+ best_max_set = malloc(pu->count * sizeof(ir_node*));
+
+ phi = pu->members[0];
+ phi_blk = get_nodes_block(phi);
+
+
+ /* fill live_info */
+ DBG((dbgphi, 1, "\tLiveness info\n"));
+ /* first the phi */
+ if (is_live_out(phi_blk, phi)) {
+ pu->live_info[0] = liveout;
+ DBG((dbgphi, 1, "\t\t%n lives out\n", phi));
}
- assert(phi_count == 1 && phi);
+ /* then all args */
+ for (i = 0, n = get_irn_arity(phi); i < n; ++i) {
+ int midx;
+ ir_node *arg, *block_ith_pred;
+
+ arg = get_irn_n(phi, i);
+ block_ith_pred = get_nodes_block(get_irn_n(phi_blk, i));
- /* where is the definition of the arguments? */
- DBG((dbgphi, 1, "Checking arg def\n"));
- arity = get_irn_arity(phi);
- for (i = 0; i < arity; ++i) {
- ir_node *block_of_arg, *block_ith_pred;
- ir_node *arg = get_irn_n(phi, i);
+ /* find the arg in the members array */
+ midx = -1;
+ for (o = 0; o < pu->count; ++o)
+ if (pu->members[o] == arg) {
+ midx = o;
+ break;
+ }
+ assert(midx != -1 && "All args have to be in the members!\n");
- block_of_arg = get_nodes_block(arg);
- block_ith_pred = get_nodes_block(get_irn_n(get_nodes_block(phi), i));
+ if (is_live_in(block_ith_pred, arg)) {
+ pu->live_info[midx] |= livein;
+ DBG((dbgphi, 1, "\t\t%n lives in\n", arg));
+ }
- if (block_of_arg != block_ith_pred) {
- DBG((dbgphi, 1, "Dropped: Arg-def not in pred-block\n"));
- goto exit;
+ if (is_live_out(block_ith_pred, arg)) {
+ pu->live_info[midx] |= liveout;
+ DBG((dbgphi, 1, "\t\t%n lives out\n", arg));
}
}
+ /* find best color */
+ best_size = -1;
+ for (col = 0; col < MAX_COLORS; ++col) { /* TODO: try phi color first */
+ DBG((dbgphi, 1, "\tTesting colors %d\n", col));
+
+ memset(cand, 0, pu->count * sizeof(ir_node*));
+ memset(max_set, 0, pu->count * sizeof(ir_node*));
+
+ /* BETTER: Alle die mit dem phi interferieren koennen eigentlich
+ * schon frueher raus, da unabhaengig von Farbe. */
+ /* for this color get all potential candidates for a max indep. set */
+ cand[0] = phi;
+ size = 1;
+ for (i = 1; i < pu->count; ++i)
+ if ((!bitset_is_set(pu->used_cols[i], col) || get_irn_color(pu->members[i]) == col)
+ && !phi_ops_interfere(phi, pu->members[i])) {
+ /* color is free or already used by the node
+ * and argument is not interfering with phi */
+ cand[i] = pu->members[i];
+ DBG((dbgphi, 1, "\t\tAdding candidate %n\n", cand[i]));
+ size++;
+ }
+ if (size <= best_size) {
+ /* If the candidate set is smaller the max indep. set wont be larger :) */
+ continue;
+ }
- /* determine a greedy set of non-interfering members
- * crucial: starting with the phi node
- */
- DBG((dbgphi, 1, "Building greedy non-interfering set\n"));
- intffree = pset_new_ptr(4);
-
- pset_remove_ptr(pc, phi);
- pset_insert_ptr(intffree, phi);
-
- while (m = (ir_node *)pset_first(pc), m) {
- DBG((dbgphi, 1, "Checking %n\n", m));
- pset_break(pc);
- pset_remove_ptr(pc, m);
-
- intf_det = 0;
- for (n = (ir_node *)pset_first(intffree); n; n = (ir_node *)pset_next(intffree)) {
- DBG((dbgphi, 1, "\t%n", n));
- if (phi_ops_interfere(m, n)) {
- DBG((dbgphi, 1, "\tinterf\n"));
- intf_det = 1;
- } else {
- DBG((dbgphi, 1, "\tclean\n"));
+ /* determine the max indep. set */
+ /* TODO: make this 'un-greedy' */
+ size = 0;
+ for (i = 0; i < pu->count; ++i) {
+ int intf_det = 0;
+ if (!cand[i])
+ continue;
+
+ for (o = 0; o < pu->count; ++o) {
+ if (!max_set[o])
+ continue;
+ if (phi_ops_interfere(cand[i], max_set[o])) {
+ DBG((dbgphi, 1, "\t\t\n"));
+ intf_det = 1;
+ break;
+ }
+ }
+
+ if (!intf_det) {
+ DBG((dbgphi, 1, "\t\tAdding to set %n\n", cand[i]));
+ max_set[i] = cand[i];
+ size++;
}
}
- if (!intf_det) {
- DBG((dbgphi, 1, "Added to set\n"));
- pset_insert_ptr(intffree, m);
+
+ DBG((dbgphi, 1, "\t\tColor %d resulted in a set size of %d\n", col, size));
+
+ /* Did we find a better max set? */
+ if (size > best_size) {
+ void *tmp;
+
+ best_color = col;
+ best_size = size;
+
+ tmp = best_max_set;
+ best_max_set = max_set;
+ max_set = tmp;
}
+
+ /* Is this a best possible set? */
+ /* BETTER: Find a better lower bound than pu->count, considering interferences */
+ if (best_size == pu->count)
+ break;
}
+ DBG((dbgphi, 1, "Best color was %d. %d of %d copies needed.\n", best_color, pu->count-best_size, pu->count-1));
- /*
- * color the non interfering set
- */
- DBG((dbgphi, 1, "Coloring...\n"));
- phi_col = get_irn_color(phi);
- DBG((dbgphi, 1, "phi-color: %d\n", phi_col));
- /* check if phi color is free in blocks of all members */
- allfree = 1;
- for (n = (ir_node *)pset_first(intffree); n; n = (ir_node *)pset_next(intffree)) {
- ir_node *block;
- bitset_t *used_colors;
+ /* now we have the best_max_set with its best_size
+ * so set the tgt_colors */
+ for (i = 0; i < pu->count; ++i)
+ if (best_max_set[i] && get_irn_color(best_max_set[i]) != best_color)
+ pu->tgt_colors[i] = best_color;
+ else
+ pu->tgt_colors[i] = -1;
- if (n == phi)
- continue;
+ free(cand);
+ free(max_set);
+ free(best_max_set);
+}
- block = get_nodes_block(n);
- used_colors = get_ra_block_info(block)->used_colors;
+static phi_unit_t *new_phi_unit(pset *pc) {
+ phi_unit_t *pu;
+ int i, o;
+ ir_node *n;
- if (bitset_is_set(used_colors, phi_col)) {
- allfree = 0;
- break;
- }
+ assert(pset_count(pc) <= MAX_PHI_CLS_SIZE && "Phi class too large!");
+
+ pu = malloc(sizeof(phi_unit_t));
+ pu->count = pset_count(pc);
+ pu->members = malloc(pu->count * sizeof(*pu->members));
+ pu->used_cols = malloc(pu->count * sizeof(bitset_t*));
+ pu->tgt_colors = malloc(pu->count * sizeof(int));
+ pu->live_info = calloc(pu->count, sizeof(ir_node*));
+
+
+ /* fill the members array */
+ DBG((dbgphi, 1, "Phi class:\n"));
+ i = 0;
+ o = pu->count-1;
+ for (n = (ir_node *)pset_first(pc); n; n = (ir_node *)pset_next(pc)) {
+ DBG((dbgphi, 1, "\t%n\n", n));
+ if (is_Phi(n))
+ pu->members[i++] = n;
+ else
+ pu->members[o--] = n;
}
+ pu->phi_count = i;
+ DBG((dbgphi, 1, "\n"));
+
+
+ /* fill used colors array */
+ for (i = 0; i < pu->count; ++i)
+ pu->used_cols[i] = get_ra_block_info(get_nodes_block(pu->members[i]))->used_colors;
- if (allfree) {
- for (n = (ir_node *)pset_first(intffree); n; n = (ir_node *)pset_next(intffree))
- set_irn_color(n, phi_col);
- printf("KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK\n");
- } else {
+ if (pu->phi_count == 1) {
+ ana_1_phi(pu);
+ } else {
+ /* TODO */
+ // ana_n_phi(pu);
}
-exit:
- del_pset(pc);
-// free(members);
+ return pu;
+}
+
+
+static void free_phi_unit(phi_unit_t *pu) {
+ DBG((dbgphi, 1, "\n"));
+ free(pu->members);
+ free(pu->used_cols);
+ free(pu->tgt_colors);
+ free(pu->live_info);
+ free(pu);
}
-void be_phi_coalesce(pset *all_phi_classes, dominfo_t *dominfo) {
- pset *phi_class;
+void be_phi_coalesce(pset *all_phi_classes) {
+ pset *pc;
+ phi_unit_t *pu;
+
+ for (pc = (pset *)pset_first(all_phi_classes); pc; pc = (pset *)pset_next(all_phi_classes)) {
+ pu = new_phi_unit(pc);
+ coalesce(pu);
+ free_phi_unit(pu);
+ }
+}
- for (phi_class = (pset *)pset_first(all_phi_classes); phi_class; phi_class = (pset *)pset_next(all_phi_classes))
- coalesce_locals(phi_class, dominfo);
+
+void be_phi_coal_init(void) {
+ dbgphi = firm_dbg_register("Phi coalescing");
+ firm_dbg_set_mask(dbgphi, DEBUG_LVL);
}
* @date 04.01.2005
*/
+#include <stdlib.h>
#include <stdio.h>
#include "pset.h"
#include "irgraph.h"
#include "irnode.h"
#include "irgwalk.h"
+#include "irdom.h"
-#include "domtree.h"
#include "bephiopt.h"
#include "bephicongr_t.h"
#include "bephicoal_t.h"
#include "phistat.h"
-#define CUMULATIVE_FILE "~/all.phistat"
+#define DO_PHI_STATISTICS
+#undef DUMP_IRG_PHI_STAT
+#define DUMP_ALL_PHI_STAT
+
+#define DEBUG_LVL 1
+
+#define CUMULATIVE_FILE "all.phistat"
+#define ENV_PHI_STAT "PHI_STAT"
static firm_dbg_module_t *dbgphi = NULL;
void be_phi_opt(ir_graph* irg) {
- dominfo_t *dominfo;
pset *all_phi_nodes, *all_phi_classes;
- char buf[1024];
+ DBG((dbgphi, 1, "\n\n=======================> IRG: %s\n\n", get_entity_name(get_irg_entity(irg))));
/* get all phi nodes */
- printf("-----------------------> Collecting phi nodes <-----------------------\n");
+ DBG((dbgphi, 1, "-----------------------> Collecting phi nodes <-----------------------\n\n"));
all_phi_nodes = pset_new_ptr(64);
irg_walk_graph(irg, phi_node_walker, NULL, all_phi_nodes);
+
/* get all phi congruence classes */
- printf("-----------------------> Collecting phi classes <-----------------------\n");
+ DBG((dbgphi, 1, "-----------------------> Collecting phi classes <---------------------\n\n"));
all_phi_classes = be_phi_congr_classes(all_phi_nodes);
+
/* do some statistics */
- printf("-----------------------> Collecting phi stats <-----------------------\n");
+#ifdef DO_PHI_STATISTICS
+ DBG((dbgphi, 1, "-----------------------> Collecting phi stats <-----------------------\n\n"));
phi_stat_reset();
phi_stat_collect(irg, all_phi_nodes, all_phi_classes);
- snprintf(buf, sizeof(buf), "%s.phistat", get_entity_name(get_irg_entity(irg)));
- //phi_stat_dump_pretty(buf);
- phi_stat_dump(buf, CUMULATIVE_FILE);
+#ifdef DUMP_IRG_PHI_STAT
+ {
+ char buf[1024];
+ snprintf(buf, sizeof(buf), "%s.phistat", get_entity_name(get_irg_entity(irg)));
+ //phi_stat_dump(buf);
+ phi_stat_dump_pretty(buf);
+ }
+#endif
+#ifdef DUMP_ALL_PHI_STAT
+ phi_stat_update(CUMULATIVE_FILE);
+#endif
+ phi_stat_update(getenv(ENV_PHI_STAT));
+#endif
+
/* try to coalesce the colors of each phi class */
- printf("-----------------------> Building domtree <-----------------------\n");
- dominfo = domtree_create(irg);
- printf("-----------------------> Coalescing <-----------------------\n");
- /* be_phi_coalesce_locals(all_phi_classes, dominfo); */
- printf("-----------------------> Destroying domtree <-----------------------\n");
- domtree_free(dominfo);
+ DBG((dbgphi, 1, "-----------------------> Coalescing <---------------------------------\n\n"));
+ compute_doms(irg);
+ be_phi_coalesce(all_phi_classes);
+ free_dom_and_peace(irg);
}
void be_phi_opt_init(void) {
dbgphi = firm_dbg_register("Phi optimizer");
- firm_dbg_set_mask(dbgphi, 1);
+ firm_dbg_set_mask(dbgphi, DEBUG_LVL);
be_phi_congr_class_init();
be_phi_coal_init();
#include <stdlib.h>
+#include "debug.h"
+#include "hashptr.h"
+#include "set.h"
+#include "irprintf_t.h"
#include "irgwalk.h"
+
#include "irdom.h"
#include "domtree.h"
-
struct _domtree_t {
ir_node *block;
struct _domtree_t *up, *right, *down;
struct _dominfo_t {
domtree_t *root;
- pmap *b2dom;
+ set *b2dom;
};
+static firm_dbg_module_t *dbg = NULL;
+
+
+int set_cmp_domtree(const void *x, const void *y, size_t size) {
+ return ((domtree_t *)x)->block != ((domtree_t *)y)->block;
+}
+
+
domtree_t *domtree_find(dominfo_t *dom, ir_node *block) {
+ domtree_t d;
+ DBG((dbg, 1, "%n\n", block));
assert(is_Block(block));
- return (domtree_t *)pmap_find(dom->b2dom, block);
+ d.block = block;
+ return set_find(dom->b2dom, &d, sizeof(d), HASH_PTR(block));
}
static void domtree_insert(dominfo_t *dom, ir_node *idom, ir_node *dominated) {
domtree_t *parent, *child;
+ DBG((dbg, 1, "%n %n\n", idom, dominated));
parent = domtree_find(dom, idom);
if (!parent) {
- parent = malloc(sizeof(domtree_t));
- parent->block = idom;
- parent->up = parent->right = parent->down = NULL;
- pmap_insert(dom->b2dom, idom, parent);
+ domtree_t d;
+ d.block = idom;
+ d.up = d.right = d.down = NULL;
+ set_insert(dom->b2dom, &d, sizeof(d), HASH_PTR(idom));
}
child = domtree_find(dom, dominated);
if (!child) {
- child = malloc(sizeof(domtree_t));
- child->block = dominated;
- child->up = child->right = child->down = NULL;
- pmap_insert(dom->b2dom, dominated, child);
+ domtree_t d;
+ d.block = dominated;
+ d.up = d.right = d.down = NULL;
+ set_insert(dom->b2dom, &d, sizeof(d), HASH_PTR(dominated));
}
+ /* get them (perhaps) again, cause they were _copied_ */
+ parent = domtree_find(dom, idom);
+ child = domtree_find(dom, dominated);
+
child->right = parent->down;
child->up = parent;
parent->down = child;
return;
idom = get_Block_idom(node);
- domtree_insert((dominfo_t *)env, idom, node);
+
+ if (idom)
+ domtree_insert((dominfo_t *)env, idom, node);
}
dominfo_t *res;
domtree_t *dom;
+ dbg = firm_dbg_register("Domtree");
+ firm_dbg_set_mask(dbg, 1);
+
+ DBG((dbg, 1, "\n"));
res = malloc(sizeof(dominfo_t));
- res->b2dom = pmap_create();
+ res->b2dom = new_set(set_cmp_domtree, 64);
/* construct domtree */
compute_doms(irg);
free_dom_and_peace(irg);
/* determine root of dom tree and store in dominfo. */
- dom = pmap_first(res->b2dom)->value;
+ dom = set_first(res->b2dom);
+ set_break(res->b2dom);
while (dom->up)
dom = dom->up;
res->root = dom;
void domtree_free(dominfo_t *dom) {
- pmap_entry *e;
-
- for (e = pmap_first(dom->b2dom); e; e = pmap_next(dom->b2dom))
- free(e->value);
-
- pmap_destroy(dom->b2dom);
+ DBG((dbg, 1, "\n"));
+ del_set(dom->b2dom);
free(dom);
}