* @brief Spillslot coalescer.
* @author Matthias Braun
* @date 26.07.2006
- * @version $Id$
*/
#include "config.h"
#include "bespill.h"
#include "bespillslots.h"
#include "bechordal_t.h"
-#include "bestatevent.h"
+#include "statev_t.h"
#include "bemodule.h"
#include "beintlive_t.h"
#include "beirg.h"
#include "bearch.h"
+#include "bespillutil.h"
-#define DBG_COALESCING 1
-#define DBG_INTERFERENCES 2
+#define DBG_COALESCING 1
+#define DBG_INTERFERENCES 2
DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
ir_node *spill;
const ir_mode *mode; /**< mode of the spilled value */
int alignment; /**< alignment for the spilled value */
- int spillslot; /**< index into spillslot_unionfind structure */
+ int spillslot;
} spill_t;
typedef struct affinity_edge_t {
struct be_fec_env_t {
struct obstack obst;
ir_graph *irg;
- set *spills;
+ spill_t **spills;
+ unsigned *spills_set;
ir_node **reloads;
affinity_edge_t **affinity_edges;
set *memperms;
set_frame_entity_func set_frame_entity;
+ bool at_begin; /**< frame entities should be allocate at
+ the beginning of the stackframe */
};
/** Compare 2 affinity edges (used in quicksort) */
static int cmp_affinity(const void *d1, const void *d2)
{
- const affinity_edge_t * const *e1 = d1;
- const affinity_edge_t * const *e2 = d2;
+ const affinity_edge_t * const *e1 = (const affinity_edge_t**)d1;
+ const affinity_edge_t * const *e2 = (const affinity_edge_t**)d2;
+ double aff1 = (*e1)->affinity;
+ double aff2 = (*e2)->affinity;
/* sort in descending order */
- return (*e1)->affinity < (*e2)->affinity ? 1 : -1;
-}
-
-static int cmp_spill(const void* d1, const void* d2, size_t size)
-{
- const spill_t* s1 = d1;
- const spill_t* s2 = d2;
- (void) size;
-
- return s1->spill != s2->spill;
+ if (aff1 < aff2) {
+ return 1;
+ } else if (aff1 > aff2) {
+ return -1;
+ } else {
+ int slot11 = (*e1)->slot1;
+ int slot21 = (*e2)->slot1;
+ if (slot11 < slot21) {
+ return 1;
+ } else if (slot11 > slot21) {
+ return -1;
+ } else {
+ int slot12 = (*e1)->slot2;
+ int slot22 = (*e2)->slot2;
+ return (slot12<slot22) - (slot12<slot22);
+ }
+ }
}
static spill_t *get_spill(be_fec_env_t *env, ir_node *node)
{
- spill_t spill, *res;
- int hash = hash_irn(node);
-
- spill.spill = node;
- res = set_find(env->spills, &spill, sizeof(spill), hash);
-
- return res;
+ assert(rbitset_is_set(env->spills_set, get_irn_idx(node)));
+ return (spill_t*)get_irn_link(node);
}
-
static inline ir_node *get_memory_edge(const ir_node *node)
{
int i, arity;
static spill_t *collect_spill(be_fec_env_t *env, ir_node *node,
const ir_mode *mode, int align)
{
- spill_t spill, *res;
- int hash = hash_irn(node);
-
- /* insert into set of spills if not already there */
- spill.spill = node;
- res = set_find(env->spills, &spill, sizeof(spill), hash);
-
- if (res == NULL) {
- spill.spillslot = set_count(env->spills);
- spill.mode = mode;
- spill.alignment = align;
- res = set_insert(env->spills, &spill, sizeof(spill), hash);
- DB((dbg, DBG_COALESCING, "Slot %d: %+F\n", spill.spillslot, node));
- } else {
- assert(res->mode == mode);
- assert(res->alignment == align);
- }
-
- return res;
-}
+ spill_t *spill;
-static spill_t *collect_memphi(be_fec_env_t *env, ir_node *node,
- const ir_mode *mode, int align)
-{
- int i, arity;
- spill_t spill, *res;
- int hash = hash_irn(node);
- const ir_exec_freq *exec_freq = be_get_irg_exec_freq(env->irg);
-
- assert(is_Phi(node));
-
- spill.spill = node;
- res = set_find(env->spills, &spill, sizeof(spill), hash);
- if (res != NULL) {
- assert(res->mode == mode);
- assert(res->alignment == align);
- return res;
+ /* already in spill set? */
+ unsigned idx = get_irn_idx(node);
+ if (rbitset_is_set(env->spills_set, idx)) {
+ spill_t *spill = get_spill(env, node);
+ assert(spill->mode == mode);
+ assert(spill->alignment == align);
+ return spill;
}
+ rbitset_set(env->spills_set, idx);
- spill.spillslot = set_count(env->spills);
- spill.mode = mode;
- spill.alignment = align;
- DB((dbg, DBG_COALESCING, "Slot %d: %+F\n", spill.spillslot, node));
- res = set_insert(env->spills, &spill, sizeof(spill), hash);
-
- /* collect attached spills and mem-phis */
- arity = get_irn_arity(node);
- for (i = 0; i < arity; ++i) {
- affinity_edge_t *affinty_edge;
- ir_node *arg = get_irn_n(node, i);
- spill_t *arg_spill;
-
- if (is_Phi(arg)) {
- arg_spill = collect_memphi(env, arg, mode, align);
- } else {
- arg_spill = collect_spill(env, arg, mode, align);
+ spill = OALLOC(&env->obst, spill_t);
+ /* insert into set of spills if not already there */
+ spill->spill = node;
+ spill->mode = mode;
+ spill->alignment = align;
+ spill->spillslot = (int)ARR_LEN(env->spills);
+ ARR_APP1(spill_t*, env->spills, spill);
+ set_irn_link(node, spill);
+ DB((dbg, DBG_COALESCING, "Slot %d: %+F\n", spill->spillslot, node));
+
+ if (is_Phi(node)) {
+ int arity = get_irn_arity(node);
+ int i;
+ for (i = 0; i < arity; ++i) {
+ affinity_edge_t *affinty_edge;
+ ir_node *arg = get_irn_n(node, i);
+ spill_t *arg_spill = collect_spill(env, arg, mode, align);
+ ir_node *block = get_nodes_block(arg);
+
+ /* add an affinity edge */
+ affinty_edge = OALLOC(&env->obst, affinity_edge_t);
+ affinty_edge->affinity = get_block_execfreq(block);
+ affinty_edge->slot1 = spill->spillslot;
+ affinty_edge->slot2 = arg_spill->spillslot;
+ ARR_APP1(affinity_edge_t*, env->affinity_edges, affinty_edge);
}
-
- /* add an affinity edge */
- affinty_edge = OALLOC(&env->obst, affinity_edge_t);
- 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);
}
- return res;
+ return spill;
}
void be_node_needs_frame_entity(be_fec_env_t *env, ir_node *node,
const ir_mode *mode, int align)
{
ir_node *spillnode = get_memory_edge(node);
- spill_t *spill;
-
assert(spillnode != NULL);
/* walk upwards and collect all phis and spills on this way */
- if (is_Phi(spillnode)) {
- spill = collect_memphi(env, spillnode, mode, align);
- } else {
- spill = collect_spill(env, spillnode, mode, align);
- }
+ collect_spill(env, spillnode, mode, align);
ARR_APP1(ir_node *, env->reloads, node);
}
-
-
static int merge_interferences(be_fec_env_t *env, bitset_t** interferences,
int* spillslot_unionfind, int s1, int s2)
{
int res;
- int i;
- int spillcount;
+ size_t spillcount;
+ size_t i;
/* merge spillslots and interferences */
res = uf_union(spillslot_unionfind, s1, s2);
bitset_or(interferences[s1], interferences[s2]);
/* update other interferences */
- spillcount = set_count(env->spills);
+ spillcount = ARR_LEN(env->spills);
for (i = 0; i < spillcount; ++i) {
bitset_t *intfs = interferences[i];
if (bitset_is_set(intfs, s2))
return res;
}
-static int my_values_interfere2(ir_graph *irg, const ir_node *a,
- const ir_node *b)
+static bool my_values_interfere2(ir_graph *const irg, ir_node const *a, ir_node const *b)
{
- be_lv_t *lv = be_get_irg_liveness(irg);
-
- int a2b = _value_dominates(a, b);
- int b2a = _value_dominates(b, a);
-
- /* If there is no dominance relation, they do not interfere. */
- if ((a2b | b2a) > 0) {
- const ir_edge_t *edge;
- ir_node *bb;
-
- /*
- * Adjust a and b so, that a dominates b if
- * a dominates b or vice versa.
- */
- if (b2a) {
- const ir_node *t = a;
- a = b;
- b = t;
- }
-
- bb = get_nodes_block(b);
-
- /*
- * If a is live end in b's block it is
- * live at b's definition (a dominates b)
- */
- if (be_is_live_end(lv, bb, a))
- return 1;
-
- /*
- * Look at all usages of a.
- * If there's one usage of a in the block of b, then
- * we check, if this use is dominated by b, if that's true
- * a and b interfere. Note that b must strictly dominate the user,
- * since if b is the last user of in the block, b and a do not
- * interfere.
- * Uses of a not in b's block can be disobeyed, because the
- * check for a being live at the end of b's block is already
- * performed.
- */
- foreach_out_edge(a, edge) {
- const ir_node *user = get_edge_src_irn(edge);
- if (is_Sync(user)) {
- const ir_edge_t *edge2;
- foreach_out_edge(user, edge2) {
- const ir_node *user2 = get_edge_src_irn(edge2);
- assert(!is_Sync(user2));
- if (get_nodes_block(user2) == bb && !is_Phi(user2) &&
- _value_strictly_dominates(b, user2))
- return 1;
- }
- } else {
- if (get_nodes_block(user) == bb && !is_Phi(user) &&
- _value_strictly_dominates(b, user))
- return 1;
+ if (value_dominates(b, a)) {
+ /* Adjust a and b so, that a dominates b if
+ * a dominates b or vice versa. */
+ ir_node const *const t = a;
+ a = b;
+ b = t;
+ } else if (!value_dominates(a, b)) {
+ /* If there is no dominance relation, they do not interfere. */
+ return 0;
+ }
+
+ ir_node *const bb = get_nodes_block(b);
+
+ /* If a is live end in b's block it is
+ * live at b's definition (a dominates b) */
+ be_lv_t *const lv = be_get_irg_liveness(irg);
+ if (be_is_live_end(lv, bb, a))
+ return true;
+
+ /* Look at all usages of a.
+ * If there's one usage of a in the block of b, then
+ * we check, if this use is dominated by b, if that's true
+ * a and b interfere. Note that b must strictly dominate the user,
+ * since if b is the last user of in the block, b and a do not
+ * interfere.
+ * Uses of a not in b's block can be disobeyed, because the
+ * check for a being live at the end of b's block is already
+ * performed. */
+ foreach_out_edge(a, edge) {
+ ir_node const *const user = get_edge_src_irn(edge);
+ if (is_Sync(user)) {
+ foreach_out_edge(user, edge2) {
+ ir_node const *const user2 = get_edge_src_irn(edge2);
+ assert(!is_Sync(user2));
+ if (get_nodes_block(user2) == bb && !is_Phi(user2) &&
+ _value_strictly_dominates_intrablock(b, user2))
+ return true;
}
- }
- }
+ } else {
+ if (get_nodes_block(user) == bb && !is_Phi(user) &&
+ _value_strictly_dominates_intrablock(b, user))
+ return true;
+ }
+ }
- return 0;
+ return false;
}
/**
*/
static void do_greedy_coalescing(be_fec_env_t *env)
{
- int spillcount;
- spill_t **spilllist;
- spill_t *spill;
- int i, i2;
- int affinity_edge_count;
+ spill_t **spills = env->spills;
+ size_t spillcount = ARR_LEN(spills);
+ size_t i;
+ size_t affinity_edge_count;
bitset_t **interferences;
int* spillslot_unionfind;
struct obstack data;
- spillcount = set_count(env->spills);
if (spillcount == 0)
return;
interferences = OALLOCN(&data, bitset_t*, spillcount);
spillslot_unionfind = OALLOCN(&data, int, spillcount);
- spilllist = OALLOCN(&data, spill_t*, spillcount);
uf_init(spillslot_unionfind, spillcount);
- DEBUG_ONLY(
- memset(spilllist, 0, spillcount * sizeof(spilllist[0]));
- );
-
- for (spill = set_first(env->spills), i = 0; spill != NULL;
- spill = set_next(env->spills), ++i) {
- assert(spill->spillslot < spillcount);
- spilllist[spill->spillslot] = spill;
- }
-
for (i = 0; i < spillcount; ++i) {
interferences[i] = bitset_obstack_alloc(&data, spillcount);
}
/* construct interferences */
for (i = 0; i < spillcount; ++i) {
- ir_node *spill1 = spilllist[i]->spill;
-
+ size_t i2;
+ ir_node *spill1 = spills[i]->spill;
if (is_NoMem(spill1))
continue;
for (i2 = i+1; i2 < spillcount; ++i2) {
- ir_node *spill2 = spilllist[i2]->spill;
-
+ ir_node *spill2 = spills[i2]->spill;
if (is_NoMem(spill2))
continue;
qsort(env->affinity_edges, affinity_edge_count,
sizeof(env->affinity_edges[0]), cmp_affinity);
- /*dump_interference_graph(env, interferences, "before"); */
-
/* try to merge affine nodes */
for (i = 0; i < affinity_edge_count; ++i) {
const affinity_edge_t *edge = env->affinity_edges[i];
}
DB((dbg, DBG_COALESCING,
- "Merging %d and %d because of affinity edge\n", s1, s2));
+ "Merging %d and %d because of affinity edge\n", s1, s2));
merge_interferences(env, interferences, spillslot_unionfind, s1, s2);
}
/* try to merge as much remaining spillslots as possible */
for (i = 0; i < spillcount; ++i) {
- int s1 = uf_find(spillslot_unionfind, i);
- if (s1 != i)
+ size_t i2;
+ int s1 = uf_find(spillslot_unionfind, i);
+ if (s1 != (int)i)
continue;
for (i2 = i+1; i2 < spillcount; ++i2) {
int s2 = uf_find(spillslot_unionfind, i2);
- if (s2 != i2)
+ if (s2 != (int)i2)
continue;
/* test if values interfere
/* assign spillslots to spills */
for (i = 0; i < spillcount; ++i) {
- spill_t *spill = spilllist[i];
-
- spill->spillslot = uf_find(spillslot_unionfind, i);
+ spills[i]->spillslot = uf_find(spillslot_unionfind, i);
}
- /*dump_interference_graph(env, interferences, "after");*/
obstack_free(&data, 0);
}
-
-
-typedef struct _spill_slot_t {
+typedef struct spill_slot_t {
int size;
int align;
ir_entity *entity;
} spill_slot_t;
-typedef struct _memperm_entry_t {
+typedef struct memperm_entry_t {
ir_node* node;
int pos;
ir_entity *in;
ir_entity *out;
- struct _memperm_entry_t *next;
+ struct memperm_entry_t *next;
} memperm_entry_t;
-typedef struct _memperm_t {
+typedef struct memperm_t {
ir_node *block;
int entrycount;
memperm_entry_t *entries;
static int cmp_memperm(const void* d1, const void* d2, size_t size)
{
- const memperm_t* e1 = d1;
- const memperm_t* e2 = d2;
+ const memperm_t* e1 = (const memperm_t*)d1;
+ const memperm_t* e2 = (const memperm_t*)d2;
(void) size;
return e1->block != e2->block;
entry.block = block;
hash = hash_irn(block);
- res = set_find(env->memperms, &entry, sizeof(entry), hash);
+ res = set_find(memperm_t, env->memperms, &entry, sizeof(entry), hash);
if (res == NULL) {
entry.entrycount = 0;
entry.entries = NULL;
- res = set_insert(env->memperms, &entry, sizeof(entry), hash);
+ res = set_insert(memperm_t, env->memperms, &entry, sizeof(entry), hash);
}
return res;
static ir_entity* create_stack_entity(be_fec_env_t *env, spill_slot_t *slot)
{
- ir_graph *irg = env->irg;
- ir_type *frame = get_irg_frame_type(irg);
- /* TODO: backend should be able to specify wether we want spill slots
- * at begin or end of frame */
- int at_start = 1;
- ir_entity *res = frame_alloc_area(frame, slot->size, slot->align, at_start);
-
- /* adjust size of the entity type... */
- ir_type *enttype = get_entity_type(res);
- set_type_size_bytes(enttype, slot->size);
-
+ ir_graph *irg = env->irg;
+ ir_type *frame = get_irg_frame_type(irg);
+ ir_entity *res = frame_alloc_area(frame, slot->size, slot->align,
+ env->at_begin);
slot->entity = res;
return res;
*/
static void assign_spillslots(be_fec_env_t *env)
{
- int spillcount = set_count(env->spills);
- spill_slot_t *spillslots = ALLOCANZ(spill_slot_t, spillcount);
- spill_t *spill;
- int i;
+ spill_t **spills = env->spills;
+ size_t spillcount = ARR_LEN(spills);
+ spill_slot_t *spillslots = ALLOCANZ(spill_slot_t, spillcount);
+ size_t s;
/* construct spillslots */
- for (spill = set_first(env->spills); spill != NULL;
- spill = set_next(env->spills)) {
-
- int slotid = spill->spillslot;
- const ir_mode *mode = spill->mode;
- spill_slot_t *slot = & (spillslots[slotid]);
- int size = get_mode_size_bytes(mode);
- int align = spill->alignment;
+ for (s = 0; s < spillcount; ++s) {
+ const spill_t *spill = spills[s];
+ int slotid = spill->spillslot;
+ const ir_mode *mode = spill->mode;
+ spill_slot_t *slot = & (spillslots[slotid]);
+ int size = get_mode_size_bytes(mode);
+ int align = spill->alignment;
if (slot->align == 0 && slot->size == 0) {
slot->align = align;
}
}
- for (spill = set_first(env->spills); spill != NULL;
- spill = set_next(env->spills)) {
-
- ir_node *node = spill->spill;
- int slotid = spill->spillslot;
- spill_slot_t *slot;
+ for (s = 0; s < spillcount; ++s) {
+ const spill_t *spill = spills[s];
+ ir_node *node = spill->spill;
+ int slotid = spill->spillslot;
+ spill_slot_t *slot = &spillslots[slotid];
- slot = &spillslots[slotid];
if (slot->entity == NULL) {
create_stack_entity(env, slot);
}
if (is_Phi(node)) {
- int i, arity;
+ int arity = get_irn_arity(node);
+ int i;
ir_node *block = get_nodes_block(node);
/* should be a PhiM */
- assert(is_Phi(node));
+ assert(get_irn_mode(node) == mode_M);
- for (i = 0, arity = get_irn_arity(node); i < arity; ++i) {
- ir_node *arg = get_irn_n(node, i);
+ for (i = 0; i < arity; ++i) {
+ ir_node *arg = get_irn_n(node, i);
ir_node *predblock = get_Block_cfgpred_block(block, i);
- spill_t *argspill;
- int argslotid;
+ spill_t *argspill = get_spill(env, arg);
+ int argslotid = argspill->spillslot;
- argspill = get_spill(env, arg);
- assert(argspill != NULL);
-
- argslotid = argspill->spillslot;
if (slotid != argslotid) {
- memperm_t *memperm;
+ memperm_t *memperm;
memperm_entry_t *entry;
- spill_slot_t *argslot = &spillslots[argslotid];
+ spill_slot_t *argslot = &spillslots[argslotid];
if (argslot->entity == NULL) {
create_stack_entity(env, argslot);
}
}
}
- for (i = 0; i < ARR_LEN(env->reloads); ++i) {
- ir_node *reload = env->reloads[i];
+ for (s = 0; s < ARR_LEN(env->reloads); ++s) {
+ ir_node *reload = env->reloads[s];
ir_node *spillnode = get_memory_edge(reload);
- spill_t *spill = get_spill(env, spillnode);
- const spill_slot_t *slot = & spillslots[spill->spillslot];
+ const spill_t *spill = get_spill(env, spillnode);
+ const spill_slot_t *slot = &spillslots[spill->spillslot];
assert(slot->entity != NULL);
}
}
-/**
- * Returns the last node in a block which is no control flow changing node
- */
-static ir_node *get_end_of_block_insertion_point(ir_node* block)
-{
- ir_node* ins = sched_last(block);
- while (is_Proj(ins) && get_irn_mode(ins) == mode_X) {
- ins = sched_prev(ins);
- assert(ins != NULL);
- }
-
- if (is_cfop(ins)) {
- for (;;) {
- ir_node *prev = sched_prev(ins);
- if (!is_cfop(prev))
- break;
- ins = prev;
- }
- }
-
- return ins;
-}
-
static void create_memperms(be_fec_env_t *env)
{
- ir_graph *irg = env->irg;
- memperm_t *memperm;
-
- for (memperm = set_first(env->memperms); memperm != NULL; memperm = set_next(env->memperms)) {
+ foreach_set(env->memperms, memperm_t, memperm) {
ir_node **nodes = ALLOCAN(ir_node*, memperm->entrycount);
memperm_entry_t *entry;
- ir_node *blockend;
ir_node *mempermnode;
int i;
nodes);
/* insert node into schedule */
- blockend = get_end_of_block_insertion_point(memperm->block);
+ ir_node *const blockend = be_get_end_of_block_insertion_point(memperm->block);
sched_add_before(blockend, mempermnode);
stat_ev_dbl("mem_perm", memperm->entrycount);
be_set_MemPerm_in_entity(mempermnode, i, entry->in);
be_set_MemPerm_out_entity(mempermnode, i, entry->out);
- set_irg_current_block(irg, memperm->block);
- proj = new_Proj(mempermnode, get_irn_mode(arg), i);
+ proj = new_r_Proj(mempermnode, get_irn_mode(arg), i);
set_irn_n(entry->node, entry->pos, proj);
}
}
}
-static int count_spillslots(const be_fec_env_t *env)
+static unsigned count_spillslots(const be_fec_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);
+ size_t spillcount = ARR_LEN(env->spills);
+ unsigned slotcount = 0;
+ size_t s;
+
+ unsigned *const counted = rbitset_alloca(spillcount);
+ for (s = 0; s < spillcount; ++s) {
+ spill_t *spill = env->spills[s];
+ int spillslot = spill->spillslot;
+ if (!rbitset_is_set(counted, spillslot)) {
+ ++slotcount;
+ rbitset_set(counted, spillslot);
}
}
{
be_fec_env_t *env = XMALLOCZ(be_fec_env_t);
- be_liveness_assure_chk(be_assure_liveness(irg));
+ be_assure_live_chk(irg);
obstack_init(&env->obst);
env->irg = irg;
- env->spills = new_set(cmp_spill, 10);
+ env->spills = NEW_ARR_F(spill_t*, 0);
+ env->spills_set = rbitset_malloc(get_irg_last_idx(irg));
env->reloads = NEW_ARR_F(ir_node*, 0);
env->affinity_edges = NEW_ARR_F(affinity_edge_t*, 0);
env->memperms = new_set(cmp_memperm, 10);
+ ir_reserve_resources(irg, IR_RESOURCE_IRN_LINK);
+
return env;
}
void be_free_frame_entity_coalescer(be_fec_env_t *env)
{
+ ir_free_resources(env->irg, IR_RESOURCE_IRN_LINK);
+
del_set(env->memperms);
DEL_ARR_F(env->reloads);
DEL_ARR_F(env->affinity_edges);
- del_set(env->spills);
+ DEL_ARR_F(env->spills);
+ xfree(env->spills_set);
obstack_free(&env->obst, NULL);
free(env);
}
void be_assign_entities(be_fec_env_t *env,
- set_frame_entity_func set_frame_entity)
+ set_frame_entity_func set_frame_entity,
+ bool alloc_entities_at_begin)
{
env->set_frame_entity = set_frame_entity;
+ env->at_begin = alloc_entities_at_begin;
- stat_ev_dbl("spillslots", set_count(env->spills));
+ if (stat_ev_enabled) {
+ stat_ev_dbl("spillslots", ARR_LEN(env->spills));
+ }
if (be_coalesce_spill_slots) {
do_greedy_coalescing(env);
}
- stat_ev_dbl("spillslots_after_coalescing", count_spillslots(env));
+ if (stat_ev_enabled) {
+ stat_ev_dbl("spillslots_after_coalescing", count_spillslots(env));
+ }
assign_spillslots(env);
create_memperms(env);
}
-/**
- * This walker function searches for reloads and collects all the spills
- * and memphis attached to them.
- */
-static void collect_spills_walker(ir_node *node, void *data)
-{
- be_fec_env_t *env = data;
- const ir_mode *mode;
- const arch_register_class_t *cls;
- int align;
- ir_graph *irg;
- const arch_env_t *arch_env;
-
- if (! (arch_irn_classify(node) & arch_irn_class_reload))
- return;
-
- mode = get_irn_mode(node);
- cls = arch_get_irn_reg_class_out(node);
- irg = get_irn_irg(node);
- arch_env = be_get_irg_arch_env(irg);
- align = arch_env_get_reg_class_alignment(arch_env, cls);
-
- be_node_needs_frame_entity(env, node, mode, align);
-}
-
-void be_coalesce_spillslots(ir_graph *irg)
-{
- be_fec_env_t *env = be_new_frame_entity_coalescer(irg);
-
- /* collect reloads */
- irg_walk_graph(irg, NULL, collect_spills_walker, env);
-
- be_assign_entities(env, be_node_set_frame_entity);
-
- be_free_frame_entity_coalescer(env);
-}
-
-BE_REGISTER_MODULE_CONSTRUCTOR(be_init_spillslots);
+BE_REGISTER_MODULE_CONSTRUCTOR(be_init_spillslots)
void be_init_spillslots(void)
{
FIRM_DBG_REGISTER(dbg, "firm.be.spillslots");