removed assertion (spill value can have another class than reload)
[libfirm] / ir / be / bespillslots.c
index ea0eee4..486a88b 100644 (file)
@@ -25,7 +25,9 @@
 #include "bespillslots.h"
 #include "bechordal_t.h"
 #include "bejavacoal.h"
-
+#include "benodesets.h"
+#include "bestatevent.h"
+#include "bespilloptions.h"
 
 #define DBG_COALESCING         1
 #define DBG_INTERFERENCES      2
@@ -59,10 +61,11 @@ typedef struct _ss_env_t {
 
 /** Compare 2 affinity edges (used in quicksort) */
 static int cmp_affinity(const void *d1, const void *d2) {
-       const affinity_edge_t *e1 = d1;
-       const affinity_edge_t *e2 = d2;
+       const affinity_edge_t * const *e1 = d1;
+       const affinity_edge_t * const *e2 = d2;
 
-       return e1->affinity < e2->affinity ? -1 : 1;
+       // sort in descending order
+       return (*e1)->affinity < (*e2)->affinity ? 1 : -1;
 }
 
 static int cmp_spill(const void* d1, const void* d2, size_t size) {
@@ -73,7 +76,7 @@ static int cmp_spill(const void* d1, const void* d2, size_t size) {
 
 static spill_t *get_spill(ss_env_t *env, ir_node *node) {
        spill_t spill, *res;
-       int hash = HASH_PTR(node);
+       int hash = nodeset_hash(node);
 
        spill.spill = node;
        res = set_find(env->spills, &spill, sizeof(spill), hash);
@@ -107,7 +110,7 @@ static spill_t *collect_spill(ss_env_t *env, ir_node *node) {
        const arch_env_t *arch_env = env->arch_env;
        const arch_register_class_t *cls;
        spill_t spill, *res;
-       int hash = HASH_PTR(node);
+       int hash = nodeset_hash(node);
 
        assert(arch_irn_class_is(arch_env, node, spill));
 
@@ -133,7 +136,8 @@ static spill_t *collect_spill(ss_env_t *env, ir_node *node) {
 static spill_t *collect_memphi(ss_env_t *env, ir_node *node) {
        int i, arity;
        spill_t spill, *res;
-       int hash = HASH_PTR(node);
+       int hash = nodeset_hash(node);
+       ir_exec_freq *exec_freq = env->chordal_env->birg->exec_freq;
 
        assert(is_Phi(node));
 
@@ -169,7 +173,7 @@ static spill_t *collect_memphi(ss_env_t *env, ir_node *node) {
 
                // add an affinity edge
                affinty_edge = obstack_alloc(&env->obst, sizeof(affinty_edge[0]));
-               affinty_edge->affinity = get_block_execfreq(env->chordal_env->exec_freq, get_nodes_block(arg));
+               affinty_edge->affinity = get_block_execfreq(exec_freq, get_nodes_block(arg));
                affinty_edge->slot1 = res->spillslot;
                affinty_edge->slot2 = arg_spill->spillslot;
                ARR_APP1(affinity_edge_t*, env->affinity_edges, affinty_edge);
@@ -183,28 +187,27 @@ static spill_t *collect_memphi(ss_env_t *env, ir_node *node) {
  * and memphis attached to them.
  */
 static void collect_spills_walker(ir_node *node, void *data) {
-       ss_env_t *env = data;
+       ss_env_t         *env      = data;
        const arch_env_t *arch_env = env->arch_env;
 
-       // @@@ ia32 classify returns classification of the irn the proj is attached
-       // too, why oh why?...
-       if(is_Proj(node))
+       /* classify returns classification of the irn the proj is attached to */
+       if (is_Proj(node))
                return;
 
-       if(arch_irn_class_is(arch_env, node, reload)) {
+       if (arch_irn_class_is(arch_env, node, reload)) {
                ir_node *spillnode = get_memory_edge(node);
                spill_t *spill;
 
                assert(spillnode != NULL);
 
-               if(is_Phi(spillnode)) {
+               if (is_Phi(spillnode)) {
                        spill = collect_memphi(env, spillnode);
-               } else {
+               }
+               else {
                        spill = collect_spill(env, spillnode);
                }
 
-               assert(!be_is_Reload(node) || spill->cls == arch_get_irn_reg_class(arch_env, node, -1));
-               ARR_APP1(ir_node*, env->reloads, node);
+               ARR_APP1(ir_node *, env->reloads, node);
        }
 }
 
@@ -328,6 +331,7 @@ static void do_greedy_coalescing(ss_env_t *env)
        int affinity_edge_count;
        bitset_t **interferences;
        int* spillslot_unionfind;
+       be_lv_t *lv = env->chordal_env->birg->lv;
 
        spillcount = set_count(env->spills);
        if(spillcount == 0)
@@ -357,7 +361,7 @@ static void do_greedy_coalescing(ss_env_t *env)
        // construct interferences
        for(i = 0; i < spillcount; ++i) {
                for(i2 = i+1; i2 < spillcount; ++i2) {
-                       if(values_interfere(env->chordal_env->lv, spilllist[i]->spill, spilllist[i2]->spill)) {
+                       if(values_interfere(lv, spilllist[i]->spill, spilllist[i2]->spill)) {
                                DBG((dbg, DBG_INTERFERENCES, "Slot %d and %d interfere\n", i, i2));
                                bitset_set(interferences[i], i2);
                                bitset_set(interferences[i2], i);
@@ -525,7 +529,7 @@ static memperm_t *get_memperm(ss_env_t *env, ir_node *block) {
        int hash;
 
        entry.block = block;
-       hash = HASH_PTR(block);
+       hash = nodeset_hash(block);
 
        res = set_find(env->memperms, &entry, sizeof(entry), hash);
 
@@ -723,6 +727,7 @@ static void create_memperms(ss_env_t *env) {
                // insert node into schedule
                blockend = get_end_of_block_insertion_point(memperm->block);
                sched_add_before(blockend, mempermnode);
+               be_stat_ev("mem_perm", memperm->entrycount);
 
                for(entry = memperm->entries, i = 0; entry != NULL; entry = entry->next, ++i) {
                        ir_node *proj;
@@ -739,6 +744,25 @@ static void create_memperms(ss_env_t *env) {
        }
 }
 
+static int count_spillslots(const ss_env_t *env) {
+       const spill_t *spill;
+       int spillcount = set_count(env->spills);
+       bitset_t *counted = bitset_alloca(spillcount);
+       int slotcount;
+
+       slotcount = 0;
+       for(spill = set_first(env->spills); spill != NULL;
+           spill = set_next(env->spills)) {
+               int spillslot = spill->spillslot;
+               if(!bitset_is_set(counted, spillslot)) {
+                       slotcount++;
+                       bitset_set(counted, spillslot);
+               }
+       }
+
+       return slotcount;
+}
+
 void be_coalesce_spillslots(const be_chordal_env_t *chordal_env) {
        ss_env_t env;
 
@@ -755,7 +779,14 @@ void be_coalesce_spillslots(const be_chordal_env_t *chordal_env) {
        /* Get initial spill slots */
        irg_walk_graph(chordal_env->irg, NULL, collect_spills_walker, &env);
 
-       do_greedy_coalescing(&env);
+       be_stat_ev("spillslots", set_count(env.spills));
+
+       if(be_coalesce_spill_slots) {
+               do_greedy_coalescing(&env);
+               if(be_stat_ev_is_active()) {
+                       be_stat_ev("spillslots_after_coalescing", count_spillslots(&env));
+               }
+       }
 
        assign_spillslots(&env);