Commit 0b1140d1 authored by Matthias Braun's avatar Matthias Braun
Browse files

simplify and speedup belady/loopana a bit

[r22392]
parent b59e00b6
......@@ -72,7 +72,9 @@ static int cmp_loop_info(const void *a, const void *b, size_t size) {
* @param cls The register class to compute pressure for.
* @return The highest register pressure in the given block.
*/
static unsigned be_compute_block_pressure(be_loopana_t *loop_ana, ir_node *block, const arch_register_class_t *cls) {
static unsigned be_compute_block_pressure(be_loopana_t *loop_ana,
ir_node *block, const arch_register_class_t *cls)
{
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);
......@@ -184,7 +186,9 @@ be_loopana_t *be_new_loop_pressure_cls(be_irg_t *birg,
* @param birg The backend irg object
* @return The loop analysis object.
*/
be_loopana_t *be_new_loop_pressure(be_irg_t *birg) {
be_loopana_t *be_new_loop_pressure(be_irg_t *birg,
const arch_register_class_t *cls)
{
ir_graph *irg = be_get_birg_irg(birg);
be_loopana_t *loop_ana = xmalloc(sizeof(*loop_ana));
ir_loop *irg_loop = get_irg_loop(irg);
......@@ -199,12 +203,16 @@ be_loopana_t *be_new_loop_pressure(be_irg_t *birg) {
construct_cf_backedges(irg);
}
for (i = arch_env_get_n_reg_class(arch_env) - 1; i >= 0; --i) {
const arch_register_class_t *cls = arch_env_get_reg_class(arch_env, i);
DBG((dbg, LEVEL_1, "\n=====================================================\n", cls->name));
DBG((dbg, LEVEL_1, " Computing register pressure for class %s:\n", cls->name));
DBG((dbg, LEVEL_1, "=====================================================\n", cls->name));
if (cls != NULL) {
be_compute_loop_pressure(loop_ana, irg_loop, cls);
} else {
for (i = arch_env_get_n_reg_class(arch_env) - 1; i >= 0; --i) {
const arch_register_class_t *cls = arch_env_get_reg_class(arch_env, i);
DBG((dbg, LEVEL_1, "\n=====================================================\n", cls->name));
DBG((dbg, LEVEL_1, " Computing register pressure for class %s:\n", cls->name));
DBG((dbg, LEVEL_1, "=====================================================\n", cls->name));
be_compute_loop_pressure(loop_ana, irg_loop, cls);
}
}
return loop_ana;
......
......@@ -43,11 +43,14 @@ typedef struct _be_loopana_t be_loopana_t;
be_loopana_t *be_new_loop_pressure_cls(be_irg_t *birg, const arch_register_class_t *cls);
/**
* Compute the register pressure for all classes of all loops in the birg.
* Compute the register pressure of all loops in the birg.
* @param birg The backend irg object
* @param cls register class to compute loop pressure for,
* if NULL computes for all classes
* @return The loop analysis object.
*/
be_loopana_t *be_new_loop_pressure(be_irg_t *birg);
be_loopana_t *be_new_loop_pressure(be_irg_t *birg,
const arch_register_class_t *cls);
/**
* Returns the computed register pressure for the given class and loop.
......
......@@ -42,7 +42,6 @@
#include "irprintf.h"
#include "irnodeset.h"
#include "xmalloc.h"
#include "pdeq.h"
#include "beutil.h"
#include "bearch_t.h"
......@@ -99,7 +98,7 @@ static ir_node *instr; /**< current instruction */
static unsigned instr_nr; /**< current instruction number
(relative to block start) */
static spill_env_t *senv; /**< see bespill.h */
static pdeq *worklist;
static ir_node **blocklist;
static bool move_spills = true;
static bool respectloopdepth = true;
......@@ -753,50 +752,31 @@ static void decide_start_workset(const ir_node *block)
* whether it is used from a register or is reloaded
* before the use.
*/
static void belady(ir_node *block)
static void process_block(ir_node *block)
{
workset_t *new_vals;
ir_node *irn;
int iter;
block_info_t *block_info;
int i, arity;
int has_backedges = 0;
//int first = 0;
const ir_edge_t *edge;
int arity;
/* no need to process a block twice */
if (get_block_info(block) != NULL) {
return;
}
assert(get_block_info(block) == NULL);
/* check if all predecessor blocks are processed yet (though for backedges
* we have to make an exception as we can't process them first) */
/* construct start workset */
arity = get_Block_n_cfgpreds(block);
for(i = 0; i < arity; ++i) {
ir_node *pred_block = get_Block_cfgpred_block(block, i);
block_info_t *pred_info = get_block_info(pred_block);
if (pred_info == NULL) {
/* process predecessor first (it will be in the queue already) */
if (!is_backedge(block, i)) {
return;
}
has_backedges = 1;
}
}
(void) has_backedges;
if (arity == 0) {
/* no predecessor -> empty set */
workset_clear(ws);
} else if (arity == 1) {
/* one predecessor, copy it's end workset */
ir_node *pred_block = get_Block_cfgpred_block(block, 0);
block_info_t *pred_info = get_block_info(pred_block);
assert(pred_info != NULL);
workset_copy(ws, pred_info->end_workset);
} else {
/* we need 2 heuristics here, for the case when all predecessor blocks
* are known and when some are backedges (and therefore can't be known
* yet) */
/* multiple predecessors, do more advanced magic :) */
decide_start_workset(block);
}
......@@ -872,12 +852,6 @@ static void belady(ir_node *block)
workset_foreach(ws, irn, iter)
DB((dbg, DBG_WSETS, " %+F (%u)\n", irn,
workset_get_time(ws, iter)));
/* add successor blocks into worklist */
foreach_block_succ(block, edge) {
ir_node *succ = get_edge_src_irn(edge);
pdeq_putr(worklist, succ);
}
}
/**
......@@ -979,45 +953,62 @@ static void fix_block_borders(ir_node *block, void *data)
}
}
static void add_block(ir_node *block, void *data)
{
(void) data;
ARR_APP1(ir_node*, blocklist, block);
}
static void be_spill_belady(be_irg_t *birg, const arch_register_class_t *rcls)
{
int i;
ir_graph *irg = be_get_birg_irg(birg);
be_liveness_assure_sets(be_assure_liveness(birg));
stat_ev_tim_push();
/* construct control flow loop tree */
if (! (get_irg_loopinfo_state(irg) & loopinfo_cf_consistent)) {
construct_cf_backedges(irg);
}
stat_ev_tim_pop("belady_time_backedges");
stat_ev_tim_push();
be_clear_links(irg);
stat_ev_tim_pop("belady_time_clear_links");
ir_reserve_resources(irg, IR_RESOURCE_IRN_LINK);
/* init belady env */
stat_ev_tim_push();
obstack_init(&obst);
arch_env = birg->main_env->arch_env;
cls = rcls;
lv = be_get_birg_liveness(birg);
n_regs = cls->n_regs - be_put_ignore_regs(birg, cls, NULL);
ws = new_workset();
uses = be_begin_uses(irg, lv);
loop_ana = be_new_loop_pressure(birg);
senv = be_new_spill_env(birg);
worklist = new_pdeq();
pdeq_putr(worklist, get_irg_start_block(irg));
while(!pdeq_empty(worklist)) {
ir_node *block = pdeq_getl(worklist);
belady(block);
arch_env = birg->main_env->arch_env;
cls = rcls;
lv = be_get_birg_liveness(birg);
n_regs = cls->n_regs - be_put_ignore_regs(birg, cls, NULL);
ws = new_workset();
uses = be_begin_uses(irg, lv);
loop_ana = be_new_loop_pressure(birg, cls);
senv = be_new_spill_env(birg);
blocklist = NEW_ARR_F(ir_node*, 0);
irg_block_edges_walk(get_irg_start_block(irg), NULL, add_block, NULL);
stat_ev_tim_pop("belady_time_init");
stat_ev_tim_push();
/* walk blocks in reverse postorder */
for (i = ARR_LEN(blocklist) - 1; i >= 0; --i) {
process_block(blocklist[i]);
}
/* end block might not be reachable in endless loops */
belady(get_irg_end_block(irg));
del_pdeq(worklist);
DEL_ARR_F(blocklist);
stat_ev_tim_pop("belady_time_belady");
stat_ev_tim_push();
/* belady was block-local, fix the global flow by adding reloads on the
* edges */
irg_block_walk_graph(irg, fix_block_borders, NULL, NULL);
stat_ev_tim_pop("belady_time_fix_borders");
ir_free_resources(irg, IR_RESOURCE_IRN_LINK);
/* Insert spill/reload nodes into the graph and fix usages */
be_insert_spills_reloads(senv);
......
......@@ -370,8 +370,6 @@ void set_sched_step_walker(ir_node *block, void *data)
set_irn_link(node, INT_TO_PTR(step));
if(is_Phi(node))
continue;
if(is_Proj(node))
continue;
++step;
}
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment