Commit f94d2925 authored by Matthias Braun's avatar Matthias Braun
Browse files

- fix stack bias wrongly calculated with non-scheduled projs in ia32 mode

- switch all liveness users to use ir_nodesets
- fixed warnings

[r14708]
parent 1eca6d8b
......@@ -530,12 +530,16 @@ arm_shift_modifier get_arm_shift_modifier(const ir_node *node) {
}
/* Set the ARM machine node attributes to default values. */
static void init_arm_attributes(ir_node *node, int flags, const arch_register_req_t ** in_reqs,
const arch_register_req_t ** out_reqs, const be_execution_unit_t ***execution_units,
void init_arm_attributes(ir_node *node, int flags,
const arch_register_req_t ** in_reqs,
const arch_register_req_t ** out_reqs,
const be_execution_unit_t ***execution_units,
int n_res, unsigned latency) {
ir_graph *irg = get_irn_irg(node);
struct obstack *obst = get_irg_obstack(irg);
arm_attr_t *attr = get_arm_attr(node);
(void) execution_units;
(void) latency;
attr->in_req = in_reqs;
attr->out_req = out_reqs;
......@@ -680,11 +684,15 @@ static int cmp_attr_arm(ir_node *a, ir_node *b) {
}
static int cmp_attr_arm_CondJmp(ir_node *a, ir_node *b) {
(void) a;
(void) b;
/* never identical */
return 1;
}
static int cmp_attr_arm_SwitchJmp(ir_node *a, ir_node *b) {
(void) a;
(void) b;
/* never identical */
return 1;
}
......
......@@ -2233,6 +2233,7 @@ static int process_stack_bias(be_abi_irg_t *env, ir_node *bl, int bias)
ir_node *irn;
sched_foreach(bl, irn) {
int ofs;
/*
Check, if the node relates to an entity on the stack frame.
......@@ -2246,12 +2247,12 @@ static int process_stack_bias(be_abi_irg_t *env, ir_node *bl, int bias)
DBG((env->dbg, LEVEL_2, "%F has offset %d (including bias %d)\n", ent, offset, bias));
}
/*
If the node modifies the stack pointer by a constant offset,
record that in the bias.
*/
if(arch_irn_is(arch_env, irn, modify_sp)) {
int ofs = arch_get_sp_bias(arch_env, irn);
if(omit_fp) {
/*
* If the node modifies the stack pointer by a constant offset,
* record that in the bias.
*/
ofs = arch_get_sp_bias(arch_env, irn);
if(be_is_IncSP(irn)) {
if(ofs == BE_STACK_FRAME_SIZE_EXPAND) {
......@@ -2263,8 +2264,7 @@ static int process_stack_bias(be_abi_irg_t *env, ir_node *bl, int bias)
}
}
if(omit_fp)
bias += ofs;
bias += ofs;
}
}
......
......@@ -967,15 +967,16 @@ static int appel_get_live_end_nr(appel_clique_walker_t *env, ir_node *bl, ir_nod
return -1;
}
static int appel_dump_clique(appel_clique_walker_t *env, pset *live, ir_node *bl, int curr_nr, int start_nr)
static int appel_dump_clique(appel_clique_walker_t *env, const ir_nodeset_t *live, ir_node *bl, int curr_nr, int start_nr)
{
ir_node **live_arr = alloca(env->co->cls->n_regs * sizeof(live_arr[0]));
ir_node *irn;
int n_live;
int j;
ir_nodeset_iterator_t iter;
n_live = 0;
foreach_pset(live, irn)
foreach_ir_nodeset(live, irn, iter)
live_arr[n_live++] = irn;
/* dump the live after clique */
......@@ -1017,7 +1018,8 @@ static void appel_walker(ir_node *bl, void *data)
appel_block_info_t *bli = phase_get_or_set_irn_data(&env->ph, bl);
struct obstack *obst = &env->obst;
void *base = obstack_base(obst);
pset *live = pset_new_ptr_default();
ir_nodeset_t live;
ir_nodeset_iterator_t iter;
be_lv_t *lv = env->co->cenv->birg->lv;
int n_insns = 0;
......@@ -1052,7 +1054,8 @@ static void appel_walker(ir_node *bl, void *data)
}
DBG((dbg, LEVEL_2, "%+F\n", bl));
be_liveness_end_of_block(lv, env->co->aenv, env->co->cls, bl, live);
ir_nodeset_init(&live);
be_liveness_end_of_block(lv, env->co->aenv, env->co->cls, bl, &live);
/* Generate the bad and ugly. */
for(i = n_insns - 1; i >= 0; --i) {
......@@ -1061,7 +1064,7 @@ static void appel_walker(ir_node *bl, void *data)
/* The first live set has to be saved in the block border set. */
if(i == n_insns - 1) {
j = 0;
foreach_pset(live, irn) {
foreach_ir_nodeset(&live, irn, iter) {
bli->live_end[j] = irn;
bli->live_end_nr[j] = curr_nr + j;
++j;
......@@ -1074,21 +1077,20 @@ static void appel_walker(ir_node *bl, void *data)
ir_node *op = insn->ops[j].carrier;
bitset_t *adm = insn->ops[j].regs;
int k;
int nr;
size_t nr;
if(!insn->ops[j].has_constraints)
continue;
nr = 0;
foreach_pset(live, irn) {
foreach_ir_nodeset(&live, irn, iter) {
if(irn == op) {
pset_break(live);
break;
}
++nr;
}
assert(nr < pset_count(live));
assert(nr < ir_nodeset_size(&live));
for(k = 0; k < env->co->cls->n_regs; ++k) {
int mapped_col = env->color_map[k];
......@@ -1099,11 +1101,11 @@ static void appel_walker(ir_node *bl, void *data)
}
/* dump the clique and update the stuff. */
curr_nr = appel_dump_clique(env, live, bl, curr_nr, start_nr);
curr_nr = appel_dump_clique(env, &live, bl, curr_nr, start_nr);
/* remove all defs. */
for(j = 0; j < insn->use_start; ++j)
pset_remove_ptr(live, insn->ops[j].carrier);
ir_nodeset_remove(&live, insn->ops[j].carrier);
if(is_Phi(insn->irn) && arch_irn_consider_in_reg_alloc(env->co->aenv, env->co->cls, insn->irn)) {
bli->phi[bli->n_phi] = insn->irn;
......@@ -1114,21 +1116,21 @@ static void appel_walker(ir_node *bl, void *data)
/* add all uses */
else
for(j = insn->use_start; j < insn->n_ops; ++j)
pset_insert_ptr(live, insn->ops[j].carrier);
ir_nodeset_insert(&live, insn->ops[j].carrier);
}
/* print the start clique. */
curr_nr = appel_dump_clique(env, live, bl, curr_nr, start_nr);
curr_nr = appel_dump_clique(env, &live, bl, curr_nr, start_nr);
i = 0;
foreach_pset(live, irn) {
foreach_ir_nodeset(&live, irn, iter) {
bli->live_in[i] = irn;
bli->live_in_nr[i] = PTR_TO_INT(get_irn_link(irn));
++i;
}
bli->n_live_in = i;
del_pset(live);
ir_nodeset_destroy(&live);
free(insns);
obstack_free(obst, base);
env->curr_nr = curr_nr;
......
......@@ -88,30 +88,33 @@ ir_node *insert_Perm_after(be_irg_t *birg,
be_lv_t *lv = birg->lv;
ir_node *bl = is_Block(pos) ? pos : get_nodes_block(pos);
ir_graph *irg = get_irn_irg(bl);
pset *live = pset_new_ptr_default();
ir_nodeset_t live;
ir_nodeset_iterator_t iter;
ir_node *curr, *irn, *perm, **nodes;
int i, n;
size_t i, n;
DBG((dbg, LEVEL_1, "Insert Perm after: %+F\n", pos));
be_liveness_nodes_live_at(lv, arch_env, cls, pos, live);
n = pset_count(live);
ir_nodeset_init(&live);
be_liveness_nodes_live_at(lv, arch_env, cls, pos, &live);
n = ir_nodeset_size(&live);
if(n == 0) {
del_pset(live);
ir_nodeset_destroy(&live);
return NULL;
}
nodes = xmalloc(n * sizeof(nodes[0]));
DBG((dbg, LEVEL_1, "live:\n"));
for(irn = pset_first(live), i = 0; irn; irn = pset_next(live), i++) {
i = 0;
foreach_ir_nodeset(&live, irn, iter) {
DBG((dbg, LEVEL_1, "\t%+F\n", irn));
nodes[i] = irn;
i++;
}
del_pset(live);
ir_nodeset_destroy(&live);
perm = be_new_Perm(cls, irg, bl, n, nodes);
sched_add_after(pos, perm);
......
......@@ -759,49 +759,9 @@ int be_check_dominance(ir_graph *irg)
return !problem_found;
}
pset *be_liveness_transfer(const arch_env_t *arch_env, const arch_register_class_t *cls, ir_node *irn, pset *live)
{
int i, n;
/* You should better break out of your loop when hitting the first phi function. */
assert(!is_Phi(irn) && "liveness_transfer produces invalid results for phi nodes");
#ifndef SCHEDULE_PROJS
/* kill all Proj's if a node is killed */
if (get_irn_mode(irn) == mode_T) {
const ir_edge_t *edge;
foreach_out_edge(irn, edge) {
ir_node *proj = get_edge_src_irn(edge);
if (arch_irn_consider_in_reg_alloc(arch_env, cls, proj)) {
ir_node *del = pset_remove_ptr(live, proj);
(void) del;
assert(proj == del);
}
}
}
#endif
if (arch_irn_consider_in_reg_alloc(arch_env, cls, irn)) {
ir_node *del = pset_remove_ptr(live, irn);
(void) del;
assert(irn == del);
}
for (i = 0, n = get_irn_arity(irn); i < n; ++i) {
ir_node *op = get_irn_n(irn, i);
if (arch_irn_consider_in_reg_alloc(arch_env, cls, op))
pset_insert_ptr(live, op);
}
return live;
}
void be_liveness_transfer_ir_nodeset(const arch_env_t *arch_env,
const arch_register_class_t *cls,
ir_node *node, ir_nodeset_t *nodeset)
void be_liveness_transfer(const arch_env_t *arch_env,
const arch_register_class_t *cls,
ir_node *node, ir_nodeset_t *nodeset)
{
int i, arity;
......@@ -839,24 +799,9 @@ void be_liveness_transfer_ir_nodeset(const arch_env_t *arch_env,
pset *be_liveness_end_of_block(const be_lv_t *lv, const arch_env_t *arch_env, const arch_register_class_t *cls, const ir_node *bl, pset *live)
{
int i;
assert(lv->nodes && "live sets must be computed");
be_lv_foreach(lv, bl, be_lv_state_end, i) {
ir_node *irn = be_lv_get_irn(lv, bl, i);
if(arch_irn_consider_in_reg_alloc(arch_env, cls, irn))
pset_insert_ptr(live, irn);
}
return live;
}
void be_liveness_end_of_block_ir_nodeset(const be_lv_t *lv,
const arch_env_t *arch_env,
const arch_register_class_t *cls,
const ir_node *block,
ir_nodeset_t *live)
void be_liveness_end_of_block(const be_lv_t *lv, const arch_env_t *arch_env,
const arch_register_class_t *cls,
const ir_node *block, ir_nodeset_t *live)
{
int i;
......@@ -872,7 +817,9 @@ void be_liveness_end_of_block_ir_nodeset(const be_lv_t *lv,
pset *be_liveness_nodes_live_at(const be_lv_t *lv, const arch_env_t *arch_env, const arch_register_class_t *cls, const ir_node *pos, pset *live)
void be_liveness_nodes_live_at(const be_lv_t *lv, const arch_env_t *arch_env,
const arch_register_class_t *cls,
const ir_node *pos, ir_nodeset_t *live)
{
const ir_node *bl = is_Block(pos) ? pos : get_nodes_block(pos);
ir_node *irn;
......@@ -884,15 +831,16 @@ pset *be_liveness_nodes_live_at(const be_lv_t *lv, const arch_env_t *arch_env, c
* exit immediately, so that this node is still live
*/
if(irn == pos)
return live;
return;
be_liveness_transfer(arch_env, cls, irn, live);
}
return live;
}
pset *be_liveness_nodes_live_at_input(const be_lv_t *lv, const arch_env_t *arch_env, const arch_register_class_t *cls, const ir_node *pos, pset *live)
void be_liveness_nodes_live_at_input(const be_lv_t *lv,
const arch_env_t *arch_env,
const arch_register_class_t *cls,
const ir_node *pos, ir_nodeset_t *live)
{
const ir_node *bl = is_Block(pos) ? pos : get_nodes_block(pos);
ir_node *irn;
......@@ -902,10 +850,8 @@ pset *be_liveness_nodes_live_at_input(const be_lv_t *lv, const arch_env_t *arch_
sched_foreach_reverse(bl, irn) {
be_liveness_transfer(arch_env, cls, irn, live);
if(irn == pos)
return live;
return;
}
return live;
}
static void collect_node(ir_node *irn, void *data)
......
......@@ -152,9 +152,9 @@ int be_check_dominance(ir_graph *irg);
* the nodes live after irn.
* @return live.
*/
pset *be_liveness_transfer(const arch_env_t *arch_env, const arch_register_class_t *cls, ir_node *irn, pset *live);
void be_liveness_transfer_ir_nodeset(const arch_env_t *arch_env, const arch_register_class_t *cls, ir_node *node, ir_nodeset_t *nodeset);
void be_liveness_transfer(const arch_env_t *arch_env,
const arch_register_class_t *cls, ir_node *node,
ir_nodeset_t *nodeset);
/**
* Put all node live at the end of a block into a set.
......@@ -164,9 +164,9 @@ void be_liveness_transfer_ir_nodeset(const arch_env_t *arch_env, const arch_regi
* @param live The set to put them into.
* @return live.
*/
pset *be_liveness_end_of_block(const be_lv_t *lv, const arch_env_t *arch_env, const arch_register_class_t *cls, const ir_node *bl, pset *live);
void be_liveness_end_of_block_ir_nodeset(const be_lv_t *lv, const arch_env_t *arch_env, const arch_register_class_t *cls, const ir_node *bl, ir_nodeset_t *nodeset);
void be_liveness_end_of_block(const be_lv_t *lv, const arch_env_t *arch_env,
const arch_register_class_t *cls,
const ir_node *bl, ir_nodeset_t *nodeset);
/**
* Compute a set of nodes which are live at another node.
......@@ -176,9 +176,10 @@ void be_liveness_end_of_block_ir_nodeset(const be_lv_t *lv, const arch_env_t *ar
* @param cls The register class to consider.
* @param pos The node.
* @param live The set to put them into.
* @return live.
*/
pset *be_liveness_nodes_live_at(const be_lv_t *lv, const arch_env_t *arch_env, const arch_register_class_t *cls, const ir_node *pos, pset *live);
void be_liveness_nodes_live_at(const be_lv_t *lv, const arch_env_t *arch_env,
const arch_register_class_t *cls,
const ir_node *pos, ir_nodeset_t *live);
/**
* Compute a set of nodes which are live at another node.
......@@ -188,9 +189,11 @@ pset *be_liveness_nodes_live_at(const be_lv_t *lv, const arch_env_t *arch_env, c
* @param cls The register class to consider.
* @param pos The node.
* @param live The set to put them into.
* @return live.
*/
pset *be_liveness_nodes_live_at_input(const be_lv_t *lv, const arch_env_t *arch_env, const arch_register_class_t *cls, const ir_node *pos, pset *live);
void be_liveness_nodes_live_at_input(const be_lv_t *lv,
const arch_env_t *arch_env,
const arch_register_class_t *cls,
const ir_node *pos, ir_nodeset_t *live);
/**
* Make sure the live sets are computed.
......
......@@ -76,15 +76,16 @@ static unsigned be_compute_block_pressure(be_loopana_t *loop_ana, ir_node *block
const be_irg_t *birg = loop_ana->birg;
const arch_env_t *aenv = be_get_birg_arch_env(birg);
be_lv_t *lv = be_get_birg_liveness(birg);
pset *live_nodes = pset_new_ptr_default();
ir_nodeset_t live_nodes;
ir_node *irn;
int max_live;
DBG((dbg, LEVEL_1, "Processing Block %+F\n", block));
/* determine largest pressure with this block */
live_nodes = be_liveness_end_of_block(lv, aenv, cls, block, live_nodes);
max_live = pset_count(live_nodes);
ir_nodeset_init(&live_nodes);
be_liveness_end_of_block(lv, aenv, cls, block, &live_nodes);
max_live = ir_nodeset_size(&live_nodes);
sched_foreach_reverse(block, irn) {
int cnt;
......@@ -92,14 +93,14 @@ static unsigned be_compute_block_pressure(be_loopana_t *loop_ana, ir_node *block
if (is_Phi(irn))
break;
live_nodes = be_liveness_transfer(aenv, cls, irn, live_nodes);
cnt = pset_count(live_nodes);
be_liveness_transfer(aenv, cls, irn, &live_nodes);
cnt = ir_nodeset_size(&live_nodes);
max_live = MAX(cnt, max_live);
}
DBG((dbg, LEVEL_1, "Finished with Block %+F (%s %u)\n", block, cls->name, max_live));
del_pset(live_nodes);
ir_nodeset_destroy(&live_nodes);
return max_live;
}
......
......@@ -1034,7 +1034,7 @@ found_front:
static void lower_nodes_after_ra_walker(ir_node *irn, void *walk_env) {
if (! is_Block(irn) && ! is_Proj(irn)) {
if (be_is_Perm(irn)) {
int perm_stayed = 1; //push_through_perm(irn, walk_env);
int perm_stayed = push_through_perm(irn, walk_env);
if (perm_stayed)
lower_perm_node(irn, walk_env);
}
......
......@@ -157,7 +157,7 @@ typedef struct _rss {
unsigned max_height; /**< maximum height in the current block */
rss_opts_t *opts; /**< The options */
be_lv_t *liveness; /**< The liveness information for this irg */
pset *live_block; /**< Values alive at end of block */
ir_nodeset_t live_block; /**< Values alive at end of block */
const arch_register_class_t *cls; /**< The current register class */
DEBUG_ONLY(firm_dbg_module_t *dbg);
} rss_t;
......@@ -2068,8 +2068,8 @@ static void process_block(ir_node *block, void *env) {
DBG((rss->dbg, LEVEL_1, "register class %s\n", arch_register_class_name(cls)));
/* Get all live value at end of Block having current register class */
rss->live_block = pset_new_ptr(10);
be_liveness_end_of_block(rss->liveness, rss->arch_env, rss->cls, rss->block, rss->live_block);
ir_nodeset_init(&rss->live_block);
be_liveness_end_of_block(rss->liveness, rss->arch_env, rss->cls, rss->block, &rss->live_block);
/* reset the list of interesting nodes */
plist_clear(rss->nodes);
......@@ -2126,7 +2126,7 @@ static void process_block(ir_node *block, void *env) {
*/
perform_value_serialization_heuristic(rss);
del_pset(rss->live_block);
ir_nodeset_destroy(&rss->live_block);
}
phase_free(&rss->ph);
......
......@@ -309,7 +309,7 @@ void spill_block(ir_node *block, void *data)
DBG((dbg, LEVEL_1, "spilling block %+F\n", block));
ir_nodeset_init(&live_nodes);
be_liveness_end_of_block_ir_nodeset(lv, arch_env, cls, block, &live_nodes);
be_liveness_end_of_block(lv, arch_env, cls, block, &live_nodes);
foreach_ir_nodeset(&live_nodes, node, iter) {
DBG((dbg, LEVEL_2, "\t%+F is live-end... ", node));
......
......@@ -466,11 +466,13 @@ static int reduce_register_pressure_in_block(morgan_env_t *env, const ir_node* b
ir_node *node;
int max_pressure;
int loop_unused_spills_needed;
pset *live_nodes = pset_new_ptr_default();
ir_nodeset_t live_nodes;
const be_lv_t *lv = env->lv;
be_liveness_end_of_block(lv, env->arch, env->cls, block, live_nodes);
max_pressure = pset_count(live_nodes);
ir_nodeset_init(&live_nodes);
be_liveness_end_of_block(lv, env->arch, env->cls, block, &live_nodes);
max_pressure = ir_nodeset_size(&live_nodes);
DBG((dbg, DBG_LIVE, "Reduce pressure to %d In Block %+F:\n", env->registers_available, block));
......@@ -483,12 +485,12 @@ static int reduce_register_pressure_in_block(morgan_env_t *env, const ir_node* b
if(is_Phi(node))
break;
be_liveness_transfer(env->arch, env->cls, node, live_nodes);
pressure = pset_count(live_nodes);
be_liveness_transfer(env->arch, env->cls, node, &live_nodes);
pressure = ir_nodeset_size(&live_nodes);
if(pressure > max_pressure)
max_pressure = pressure;
}
del_pset(live_nodes);
ir_nodeset_destroy(&live_nodes);
loop_unused_spills_needed = max_pressure - env->registers_available;
......
......@@ -130,12 +130,13 @@ static void stat_reg_pressure_block(ir_node *block, void *data) {
for (i = 0; i < n; i++) {
const arch_register_class_t *cls = arch_isa_get_reg_class(aenv->isa, i);
ir_node *irn;
pset *live_nodes = pset_new_ptr(64);
int max_live;
ir_node *irn;
ir_nodeset_t live_nodes;
int max_live;
live_nodes = be_liveness_end_of_block(env->lv, aenv, cls, block, live_nodes);
max_live = pset_count(live_nodes);
ir_nodeset_init(&live_nodes);
be_liveness_end_of_block(env->lv, aenv, cls, block, &live_nodes);
max_live = ir_nodeset_size(&live_nodes);
sched_foreach_reverse(block, irn) {
int cnt;
......@@ -143,12 +144,13 @@ static void stat_reg_pressure_block(ir_node *block, void *data) {
if(is_Phi(irn))
break;
live_nodes = be_liveness_transfer(aenv, cls, irn, live_nodes);
cnt = pset_count(live_nodes);
be_liveness_transfer(aenv, cls, irn, &live_nodes);
cnt = ir_nodeset_size(&live_nodes);
max_live = cnt < max_live ? max_live : cnt;
}
stat_be_block_regpressure(irg, block, max_live, cls->name);
ir_nodeset_destroy(&live_nodes);
}
}
......
......@@ -62,11 +62,12 @@ typedef struct be_verify_register_pressure_env_t_ {
/**
* Print all nodes of a pset into a file.
*/
static void print_living_values(FILE *F, pset *live_nodes) {
static void print_living_values(FILE *F, const ir_nodeset_t *live_nodes) {
ir_nodeset_iterator_t iter;
ir_node *node;
ir_fprintf(F, "\t");
foreach_pset(live_nodes, node) {
foreach_ir_nodeset(live_nodes, node, iter) {
ir_fprintf(F, "%+F ", node);
}
ir_fprintf(F, "\n");
......@@ -77,18 +78,20 @@ static void print_living_values(FILE *F, pset *live_nodes) {
*/
static void verify_liveness_walker(ir_node *block, void *data) {
be_verify_register_pressure_env_t *env = (be_verify_register_pressure_env_t *)data;
pset *live_nodes = pset_new_ptr_default();
ir_nodeset_t live_nodes;
ir_node *irn;
int pressure;
/* collect register pressure info, start with end of a block */
be_liveness_end_of_block(env->lv, env->arch_env, env->cls, block, live_nodes);
ir_nodeset_init(&live_nodes);
be_liveness_end_of_block(env->lv, env->arch_env, env->cls, block,
&live_nodes);
pressure = pset_count(live_nodes);
pressure = ir_nodeset_size(&live_nodes);
if(pressure > env->registers_available) {
ir_fprintf(stderr, "Verify Warning: Register pressure too high at end of block %+F(%s) (%d/%d):\n",
block, get_irg_dump_name(env->irg), pressure, env->registers_available);
print_living_values(stderr, live_nodes);
print_living_values(stderr, &live_nodes);
env->problem_found = 1;
}
......@@ -96,18 +99,18 @@ static void verify_liveness_walker(ir_node *block, void *data) {
if (is_Phi(irn))
break;
be_liveness_transfer(env->arch_env, env->cls, irn, live_nodes);
be_liveness_transfer(env->arch_env, env->cls, irn, &live_nodes);
pressure = pset_count(live_nodes);
pressure = ir_nodeset_size(&live_nodes);
if(pressure > env->registers_available) {