Commit 9f70e2b2 authored by Matthias Braun's avatar Matthias Braun
Browse files

- Spillslot coalescing now collects all nodes that have class spill/reload

- Stackparams get rematerialized now
- several warning fixes
parent 1d241087
......@@ -1992,7 +1992,7 @@ static entity *abi_get_frame_entity(const void *_self, const ir_node *irn)
return NULL;
}
static void abi_set_frame_entity(const void *_self, const ir_node *irn, entity *ent)
static void abi_set_frame_entity(const void *_self, ir_node *irn, entity *ent)
{
}
......
......@@ -286,7 +286,7 @@ struct _arch_irn_ops_if_t {
* @param irn The node in question.
* @param ent The entity to set
*/
void (*set_frame_entity)(const void *self, const ir_node *irn, entity *ent);
void (*set_frame_entity)(const void *self, ir_node *irn, entity *ent);
/**
* Set the offset of a node carrying an entity on the stack frame.
......
......@@ -490,9 +490,8 @@ static be_ra_timer_t *be_ra_chordal_main(const be_irg_t *bi)
dump(BE_CH_DUMP_SPILL, irg, chordal_env.cls, "-spill", dump_ir_block_graph_sched);
// commented out for now, since spillslot coalescer currently doesn't
// detect memory as reloads
//check_for_memory_operands(&chordal_env);
check_for_memory_operands(&chordal_env);
be_abi_fix_stack_nodes(bi->abi, chordal_env.lv);
BE_TIMER_PUSH(ra_timer.t_verify);
......@@ -598,10 +597,10 @@ static be_ra_timer_t *be_ra_chordal_main(const be_irg_t *bi)
/* verify spillslots */
if (options.vrfy_option == BE_CH_VRFY_WARN) {
be_verify_spillslots(irg);
be_verify_spillslots(main_env->arch_env, irg);
}
else if (options.vrfy_option == BE_CH_VRFY_ASSERT) {
assert(be_verify_spillslots(irg) && "Spillslot verification failed");
assert(be_verify_spillslots(main_env->arch_env, irg) && "Spillslot verification failed");
}
BE_TIMER_POP(ra_timer.t_verify);
......
......@@ -100,8 +100,6 @@ static ir_node *trivial_select(void *block_env, nodeset *ready_set)
/* assure that branches and constants are executed last */
for (irn = nodeset_first(ready_set); irn; irn = nodeset_next(ready_set)) {
arch_irn_class_t irn_class = arch_irn_classify(arch_env, irn);
if (! arch_irn_class_is(arch_env, irn, branch) && (const_last ? (! arch_irn_class_is(arch_env, irn, const)) : 1)) {
nodeset_break(ready_set);
return irn;
......@@ -566,16 +564,16 @@ static INLINE int make_ready(block_sched_env_t *env, ir_node *pred, ir_node *irn
nodeset_insert(env->cands, irn);
/* calculate the etime of this node */
etime = env->curr_time;
if (pred) {
etime_p = get_irn_etime(env, pred);
etime += latency(env->sched_env, pred, 1, irn, 0);
/* calculate the etime of this node */
etime = env->curr_time;
if (pred) {
etime_p = get_irn_etime(env, pred);
etime += latency(env->sched_env, pred, 1, irn, 0);
etime = etime_p > etime ? etime_p : etime;
}
etime = etime_p > etime ? etime_p : etime;
}
set_irn_etime(env, irn, etime);
set_irn_etime(env, irn, etime);
DB((env->dbg, LEVEL_2, "\tmaking ready: %+F etime %u\n", irn, etime));
......
......@@ -753,7 +753,7 @@ int be_has_frame_entity(const ir_node *irn)
}
}
entity *be_get_frame_entity(const ir_node *irn)
entity* be_get_frame_entity(const ir_node *irn)
{
if(be_has_frame_entity(irn)) {
be_frame_attr_t *a = get_irn_attr(irn);
......@@ -762,16 +762,6 @@ entity *be_get_frame_entity(const ir_node *irn)
return NULL;
}
void be_set_frame_entity(const ir_node *irn, entity* ent)
{
be_frame_attr_t *a;
assert(be_has_frame_entity(irn));
a = get_irn_attr(irn);
a->ent = ent;
}
void be_set_MemPerm_in_entity(const ir_node *irn, int n, entity *ent)
{
be_memperm_attr_t *attr = get_irn_attr(irn);
......@@ -1065,7 +1055,7 @@ static arch_irn_class_t be_node_classify(const void *_self, const ir_node *irn)
XXX(StackParam, stackparam);
#undef XXX
default:
return 0;
return arch_irn_class_normal;
}
return 0;
......@@ -1082,9 +1072,14 @@ static entity *be_node_get_frame_entity(const void *self, const ir_node *irn)
return be_get_frame_entity(irn);
}
static void be_node_set_frame_entity(const void *self, const ir_node *irn, entity *ent)
static void be_node_set_frame_entity(const void *self, ir_node *irn, entity *ent)
{
be_set_frame_entity(irn, ent);
be_frame_attr_t *a;
assert(be_has_frame_entity(irn));
a = get_irn_attr(irn);
a->ent = ent;
}
static void be_node_set_frame_offset(const void *self, ir_node *irn, int offset)
......@@ -1236,7 +1231,7 @@ static entity *phi_get_frame_entity(const void *_self, const ir_node *irn)
return NULL;
}
static void phi_set_frame_entity(const void *_self, const ir_node *irn, entity *ent)
static void phi_set_frame_entity(const void *_self, ir_node *irn, entity *ent)
{
}
......
......@@ -341,15 +341,11 @@ int be_is_FrameStore(const ir_node *irn);
int be_is_Barrier(const ir_node *irn);
/**
* Get the entity on the stack frame the given node uses.
* @param irn The node.
* @return The entity on the stack frame used by the node or NULL,
* if the node does not access the stack frame or is no back-end node.
* Try to avoid this function and better call arch_get_frame_entity!
*
* Returns the frame entity used by the be node
*/
entity *be_get_frame_entity(const ir_node *irn);
void be_set_frame_entity(const ir_node *irn, entity* ent);
entity* be_get_frame_entity(const ir_node *irn);
ir_node* be_get_Reload_mem(const ir_node *irn);
ir_node* be_get_Reload_frame(const ir_node* irn);
......
......@@ -33,10 +33,8 @@
#include "bejavacoal.h"
// only rematerialise when costs are less than REMAT_COST_LIMIT
#define REMAT_COST_LIMIT 4
/* This enables re-computation of values. Current state: Unfinished and buggy. */
#undef BUGGY_REMAT
// TODO determine a good value here...
#define REMAT_COST_LIMIT 80
typedef struct _reloader_t reloader_t;
......@@ -54,6 +52,7 @@ typedef struct _spill_info_t {
struct _spill_env_t {
const arch_register_class_t *cls;
const arch_env_t *arch_env;
const be_chordal_env_t *chordal_env;
struct obstack obst;
set *spills; /**< all spill_info_t's, which must be placed */
......@@ -103,6 +102,7 @@ spill_env_t *be_new_spill_env(const be_chordal_env_t *chordal_env) {
env->spills = new_set(cmp_spillinfo, 1024);
env->cls = chordal_env->cls;
env->chordal_env = chordal_env;
env->arch_env = env->chordal_env->birg->main_env->arch_env;
env->mem_phis = pset_new_ptr_default();
obstack_init(&env->obst);
return env;
......@@ -130,7 +130,7 @@ void be_add_reload(spill_env_t *env, ir_node *to_spill, ir_node *before) {
reloader_t *rel;
assert(sched_is_scheduled(before));
assert(arch_irn_consider_in_reg_alloc(env->chordal_env->birg->main_env->arch_env, env->cls, to_spill));
assert(arch_irn_consider_in_reg_alloc(env->arch_env, env->cls, to_spill));
info = get_spillinfo(env, to_spill);
......@@ -230,7 +230,6 @@ static void sched_add_after_insn(ir_node *sched_after, ir_node *node) {
* @return a be_Spill node
*/
static void spill_irn(spill_env_t *env, spill_info_t *spillinfo) {
const be_main_env_t *mainenv = env->chordal_env->birg->main_env;
ir_node *to_spill = spillinfo->spilled_node;
DBG((env->dbg, LEVEL_1, "%+F\n", to_spill));
......@@ -246,7 +245,7 @@ static void spill_irn(spill_env_t *env, spill_info_t *spillinfo) {
return;
}
spillinfo->spill = be_spill(mainenv->arch_env, to_spill);
spillinfo->spill = be_spill(env->arch_env, to_spill);
sched_add_after_insn(to_spill, spillinfo->spill);
}
......@@ -333,36 +332,41 @@ static int is_value_available(spill_env_t *env, ir_node *arg, ir_node *reloader)
if(arg == get_irg_frame(env->chordal_env->irg))
return 1;
#if 0
/* we want to remat before the insn reloader
* thus an arguments is alive if
* - it interferes with the reloaders result
* or
* - or it is (last-) used by reloader itself
/* the following test does not work while spilling,
* because the liveness info is not adapted yet to the effects of the
* additional spills/reloads.
*
* So we can only do this test for ignore registers (of our register class)
*/
int i, m;
if (values_interfere(reloader, arg))
return 1;
if(arch_get_irn_reg_class(env->arch_env, arg, -1) == env->chordal_env->cls
&& arch_irn_is(env->arch_env, arg, ignore)) {
int i, arity;
for (i=0, m=get_irn_arity(reloader); i<m; ++i) {
ir_node *rel_arg = get_irn_n(reloader, i);
if (rel_arg == arg)
/* we want to remat before the insn reloader
* thus an arguments is alive if
* - it interferes with the reloaders result
* - or it is (last-) used by reloader itself
*/
if (values_interfere(env->chordal_env->lv, reloader, arg)) {
return 1;
}
}
/* arg is not alive before reloader */
return 0;
#endif
arity = get_irn_arity(reloader);
for (i = 0; i < arity; ++i) {
ir_node *rel_arg = get_irn_n(reloader, i);
if (rel_arg == arg)
return 1;
}
}
return 0;
return 0;
}
/**
* Checks whether the node can principally be rematerialized
*/
static int is_remat_node(spill_env_t *env, ir_node *node) {
const arch_env_t *arch_env = env->chordal_env->birg->main_env->arch_env;
const arch_env_t *arch_env = env->arch_env;
assert(!be_is_Spill(node));
......@@ -402,10 +406,8 @@ static int check_remat_conditions_costs(spill_env_t *env, ir_node *spilled, ir_n
if(be_is_Reload(spilled)) {
costs += 2;
} else if(is_Proj(spilled)) {
costs += 0;
} else {
costs += 1;
costs += arch_get_op_estimated_cost(env->arch_env, spilled);
}
if(parentcosts + costs >= REMAT_COST_LIMIT)
return REMAT_COST_LIMIT;
......@@ -492,7 +494,7 @@ static ir_node *do_remat(spill_env_t *env, ir_node *spilled, ir_node *reloader)
*/
void be_insert_spills_reloads(spill_env_t *env) {
const arch_env_t *arch_env = env->chordal_env->birg->main_env->arch_env;
const arch_env_t *arch_env = env->arch_env;
spill_info_t *si;
/* process each spilled node */
......
......@@ -49,6 +49,7 @@ typedef struct _affinity_edge_t {
typedef struct _ss_env_t {
struct obstack obst;
const arch_env_t *arch_env;
const be_chordal_env_t *chordal_env;
set *spills;
ir_node **reloads;
......@@ -89,11 +90,33 @@ static spill_t *get_spill(ss_env_t *env, ir_node *node) {
* |_|
*/
static spill_t *collect_spill(ss_env_t *env, ir_node *node, const arch_register_class_t *cls) {
static ir_node *get_memory_edge(const ir_node *node) {
int i, arity;
arity = get_irn_arity(node);
for(i = arity - 1; i >= 0; --i) {
ir_node *arg = get_irn_n(node, i);
if(get_irn_mode(arg) == mode_M)
return arg;
}
return NULL;
}
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);
assert(be_is_Spill(node));
assert(arch_irn_class_is(arch_env, node, spill));
if(be_is_Spill(node)) {
cls = arch_get_irn_reg_class(arch_env, node, be_pos_Spill_val);
} else {
// TODO add a way to detect the type of the spilled value
assert(0);
}
spill.spill = node;
res = set_find(env->spills, &spill, sizeof(spill), hash);
......@@ -102,14 +125,12 @@ static spill_t *collect_spill(ss_env_t *env, ir_node *node, const arch_register_
spill.spillslot = set_count(env->spills);
spill.cls = cls;
res = set_insert(env->spills, &spill, sizeof(spill), hash);
} else {
assert(cls == res->cls);
}
return res;
}
static spill_t *collect_memphi(ss_env_t *env, ir_node *node, const arch_register_class_t *cls) {
static spill_t *collect_memphi(ss_env_t *env, ir_node *node) {
int i, arity;
spill_t spill, *res;
int hash = HASH_PTR(node);
......@@ -123,7 +144,7 @@ static spill_t *collect_memphi(ss_env_t *env, ir_node *node, const arch_register
}
spill.spillslot = set_count(env->spills);
spill.cls = cls;
spill.cls = NULL;
res = set_insert(env->spills, &spill, sizeof(spill), hash);
// is 1 of the arguments a spill?
......@@ -133,11 +154,17 @@ static spill_t *collect_memphi(ss_env_t *env, ir_node *node, const arch_register
spill_t* arg_spill;
if(be_is_Spill(arg)) {
arg_spill = collect_spill(env, arg, cls);
arg_spill = collect_spill(env, arg);
} else {
// if it wasn't a spill then it must be a Mem-Phi
assert(is_Phi(arg));
arg_spill = collect_memphi(env, arg, cls);
arg_spill = collect_memphi(env, arg);
}
if(i == 0) {
res->cls = arg_spill->cls;
} else {
assert(res->cls == arg_spill->cls);
}
// add an affinity edge
......@@ -157,17 +184,26 @@ static spill_t *collect_memphi(ss_env_t *env, ir_node *node, const arch_register
*/
static void collect_spills_walker(ir_node *node, void *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))
return;
if(arch_irn_class_is(arch_env, node, reload)) {
ir_node *spillnode = get_memory_edge(node);
spill_t *spill;
if(be_is_Reload(node)) {
ir_node *spill = get_irn_n(node, be_pos_Reload_mem);
const arch_env_t *arch_env = env->chordal_env->birg->main_env->arch_env;
const arch_register_class_t *cls = arch_get_irn_reg_class(arch_env, node, -1);
assert(spill != NULL);
if(is_Phi(spill)) {
collect_memphi(env, spill, cls);
if(is_Phi(spillnode)) {
spill = collect_memphi(env, spillnode);
} else {
collect_spill(env, spill, cls);
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);
}
}
......@@ -382,7 +418,7 @@ static void do_greedy_coalescing(ss_env_t *env)
}
}
// assign spillslots
// assign spillslots to spills
for(i = 0; i < spillcount; ++i) {
spill_t *spill = spilllist[i];
......@@ -550,6 +586,7 @@ static void enlarge_spillslot(spill_slot_t *slot, int otheralign, int othersize)
* reload nodes.
*/
static void assign_spillslots(ss_env_t *env) {
const arch_env_t *arch_env = env->arch_env;
int i;
int spillcount;
spill_t *spill;
......@@ -585,9 +622,7 @@ static void assign_spillslots(ss_env_t *env) {
create_stack_entity(env, slot);
}
if(be_is_Spill(node)) {
be_set_frame_entity(node, slot->entity);
} else {
if(is_Phi(node)) {
int i, arity;
ir_node *block = get_nodes_block(node);
......@@ -624,18 +659,21 @@ static void assign_spillslots(ss_env_t *env) {
memperm->entries = entry;
}
}
} else {
assert(arch_irn_class_is(arch_env, node, spill));
arch_set_frame_entity(arch_env, node, slot->entity);
}
}
for(i = 0; i < ARR_LEN(env->reloads); ++i) {
const ir_node* reload = env->reloads[i];
ir_node* spillnode = get_irn_n(reload, be_pos_Reload_mem);
ir_node* reload = env->reloads[i];
ir_node* spillnode = get_memory_edge(reload);
spill_t *spill = get_spill(env, spillnode);
const spill_slot_t *slot = & spillslots[spill->spillslot];
assert(slot->entity != NULL);
be_set_frame_entity(reload, slot->entity);
arch_set_frame_entity(arch_env, reload, slot->entity);
}
}
......@@ -705,6 +743,7 @@ void be_coalesce_spillslots(const be_chordal_env_t *chordal_env) {
ss_env_t env;
obstack_init(&env.obst);
env.arch_env = chordal_env->birg->main_env->arch_env;
env.chordal_env = chordal_env;
env.spills = new_set(cmp_spill, 10);
env.reloads = NEW_ARR_F(ir_node*, 0);
......
......@@ -259,7 +259,7 @@ typedef struct _spill_t {
} spill_t;
typedef struct {
be_lv_t *lv;
const arch_env_t *arch_env;
ir_graph *irg;
set *spills;
ir_node **reloads;
......@@ -294,6 +294,22 @@ static spill_t *get_spill(be_verify_spillslots_env_t *env, ir_node *node, entity
return res;
}
static ir_node *get_memory_edge(const ir_node *node) {
int i, arity;
ir_node *result = NULL;
arity = get_irn_arity(node);
for(i = arity - 1; i >= 0; --i) {
ir_node *arg = get_irn_n(node, i);
if(get_irn_mode(arg) == mode_M) {
assert(result == NULL);
result = arg;
}
}
return result;
}
static void collect(be_verify_spillslots_env_t *env, ir_node *node, ir_node *reload, entity* ent);
static void check_entity(be_verify_spillslots_env_t *env, ir_node *node, entity *ent) {
......@@ -304,7 +320,7 @@ static void check_entity(be_verify_spillslots_env_t *env, ir_node *node, entity
}
static void collect_spill(be_verify_spillslots_env_t *env, ir_node *node, ir_node *reload, entity* ent) {
entity *spillent = be_get_frame_entity(node);
entity *spillent = arch_get_frame_entity(env->arch_env, node);
check_entity(env, node, spillent);
get_spill(env, node, ent);
......@@ -396,10 +412,21 @@ static void collect(be_verify_spillslots_env_t *env, ir_node *node, ir_node *rel
*/
static void collect_spills_walker(ir_node *node, void *data) {
be_verify_spillslots_env_t *env = data;
const arch_env_t *arch_env = env->arch_env;
if(be_is_Reload(node)) {
ir_node *spill = get_irn_n(node, be_pos_Reload_mem);
entity* ent = be_get_frame_entity(node);
// @@@ ia32_classify returns classification of Proj_pred :-/
if(is_Proj(node))
return;
if(arch_irn_class_is(arch_env, node, reload)) {
ir_node *spill = get_memory_edge(node);
if(spill == NULL) {
ir_fprintf(stderr, "Verify warning: No spill attached to reload %+F in block %+F(%s)\n",
node, get_nodes_block(node), get_irg_dump_name(env->irg));
env->problem_found = 1;
return;
}
entity* ent = arch_get_frame_entity(env->arch_env, node);
check_entity(env, node, ent);
collect(env, spill, node, ent);
......@@ -433,7 +460,6 @@ static void check_spillslot_interference(be_verify_spillslots_env_t *env) {
sp2->spill, get_nodes_block(sp2->spill), get_irg_dump_name(env->irg));
env->problem_found = 1;
my_values_interfere(sp1->spill, sp2->spill);
printf("Intf: %d\n", values_interfere(env->lv, sp1->spill, sp2->spill));
}
}
}
......@@ -445,7 +471,7 @@ static void check_lonely_spills(ir_node *node, void *data) {
if(be_is_Spill(node) || (is_Proj(node) && be_is_MemPerm(get_Proj_pred(node)))) {
spill_t *spill = find_spill(env, node);
if(be_is_Spill(node)) {
entity *ent = be_get_frame_entity(node);
entity *ent = arch_get_frame_entity(env->arch_env, node);
check_entity(env, node, ent);
}
......@@ -456,22 +482,21 @@ static void check_lonely_spills(ir_node *node, void *data) {
}
}
int be_verify_spillslots(ir_graph *irg)
int be_verify_spillslots(const arch_env_t *arch_env, ir_graph *irg)
{
be_verify_spillslots_env_t env;
env.arch_env = arch_env;
env.irg = irg;
env.spills = new_set(cmp_spill, 10);
env.reloads = NEW_ARR_F(ir_node*, 0);
env.problem_found = 0;
env.lv = be_liveness(irg);
irg_walk_graph(irg, collect_spills_walker, NULL, &env);
irg_walk_graph(irg, check_lonely_spills, NULL, &env);
check_spillslot_interference(&env);
be_liveness_free(env.lv);
DEL_ARR_F(env.reloads);
del_set(env.spills);
......
......@@ -43,7 +43,7 @@ int be_verify_schedule(ir_graph *irg);
* @param irg The irg to check
* @return 1 if spillslots are valid, 0 otherwise
*/
int be_verify_spillslots(ir_graph *irg);
int be_verify_spillslots(const arch_env_t *arch_env, ir_graph *irg);
/**
* Verify register allocation: Checks that no 2 live nodes have the same
......
......@@ -269,7 +269,7 @@ static entity *ia32_get_frame_entity(const void *self, const ir_node *irn) {
return is_ia32_irn(irn) ? get_ia32_frame_ent(irn) : NULL;
}
static void ia32_set_frame_entity(const void *self, const ir_node *irn, entity *ent) {
static void ia32_set_frame_entity(const void *self, ir_node *irn, entity *ent) {
set_ia32_frame_ent(irn, ent);
}
......@@ -884,7 +884,7 @@ static void ia32_before_ra(void *self) {
*/
static void transform_to_Load(ia32_transform_env_t *env) {
ir_node *irn = env->irn;
entity *ent = be_get_frame_entity(irn);
entity *ent = arch_get_frame_entity(env->cg->arch_env, irn);
ir_mode *mode = env->mode;
ir_node *noreg = ia32_new_NoReg_gp(env->cg);
ir_node *nomem = new_rd_NoMem(env->irg);
......@@ -940,7 +940,7 @@ static void transform_to_Load(ia32_transform_env_t *env) {
*/
static void transform_to_Store(ia32_transform_env_t *env) {
ir_node *irn = env->irn;
entity *ent = be_get_frame_entity(irn);
entity *ent = arch_get_frame_entity(env->cg->arch_env, irn);
ir_mode *mode = env->mode;
ir_node *noreg = ia32_new_NoReg_gp(env->cg);
ir_node *nomem = new_rd_NoMem(env->irg);
......
......@@ -2151,7 +2151,7 @@ static ir_node *gen_be_StackParam(ia32_transform_env_t *env) {
ir_node *noreg = ia32_new_NoReg_gp(env->cg);
ir_node *mem = new_rd_NoMem(env->irg);
ir_node *ptr = get_irn_n(node, 0);