* @version $Id$
*
* TODO:
- * - handle phis correctly, decide wether we should spill them
- * - merge multiple start worksets of blocks
+ * - handle phis correctly, decide wether we should spill them ~ok
+ * - merge multiple start worksets of blocks ~ok
* - how to and when to do the tentative phase...
*/
#ifdef HAVE_CONFIG_H
static int tentative_mode;
static ir_exec_freq *exec_freq;
-static void init_worklist(worklist_t *worklist, unsigned timestep)
+static worklist_t *new_worklist(void)
{
+ worklist_t *worklist = obstack_alloc(&obst, sizeof(worklist[0]));
+
INIT_LIST_HEAD(&worklist->live_values);
worklist->n_live_values = 0;
- worklist->current_timestep = timestep;
+ worklist->current_timestep = 0;
+
+ return worklist;
}
static void mark_irn_not_visited(ir_node *node)
}
}
-static void activate_worklist(const worklist_t *worklist)
-{
- struct list_head *entry;
-
- list_for_each(entry, &worklist->live_values) {
- worklist_entry_t *wl_entry
- = list_entry(entry, worklist_entry_t, head);
- ir_node *value = wl_entry->value;
-
- assert(irn_not_visited(value));
- mark_irn_visited(value);
- set_irn_link(value, wl_entry);
- }
-}
-
-static worklist_t *duplicate_worklist(const worklist_t *worklist,
- ir_node *block,
- ir_node *succ_block, int succ_pos)
+static worklist_t *duplicate_activate_worklist(const worklist_t *worklist,
+ ir_node *block, ir_node *succ_block, int succ_pos)
{
- ir_node *reload_point = NULL;
+ ir_node *reload_point = NULL;
+ size_t n_live_values = 0;
+ worklist_t *new_worklist;
struct list_head *entry;
- worklist_t *new_worklist = obstack_alloc(&obst, sizeof(new_worklist[0]));
-
- INIT_LIST_HEAD(&new_worklist->live_values);
if(succ_block != NULL && get_Block_n_cfgpreds(succ_block) > 1) {
+ ir_fprintf(stderr, "adjust reload point from %+F to %+F\n", succ_block, block);
reload_point = be_get_end_of_block_insertion_point(block);
}
+ new_worklist = obstack_alloc(&obst, sizeof(new_worklist[0]));
+ INIT_LIST_HEAD(&new_worklist->live_values);
new_worklist->current_timestep = worklist->current_timestep;
- new_worklist->n_live_values = worklist->n_live_values;
list_for_each(entry, &worklist->live_values) {
- worklist_entry_t *wl_entry
- = list_entry(entry, worklist_entry_t, head);
+ worklist_entry_t *wl_entry = list_entry(entry, worklist_entry_t, head);
+ ir_node *value = wl_entry->value;
worklist_entry_t *new_entry
= obstack_alloc(&obst, sizeof(new_entry[0]));
- ir_node *value = wl_entry->value;
if(is_Phi(value) && get_nodes_block(value) == succ_block) {
value = get_Phi_pred(value, succ_pos);
new_entry->reload_point = wl_entry->reload_point;
}
- list_add_tail(&new_entry->head, &new_worklist->live_values);
+ if(irn_not_visited(value)) {
+ list_add_tail(&new_entry->head, &new_worklist->live_values);
+ ++n_live_values;
+
+ mark_irn_visited(value);
+ set_irn_link(value, new_entry);
+ } else {
+ /* the only way we might visit a value again, is when we get it as
+ * phi predecessor */
+ assert(is_Phi(wl_entry->value));
+ }
}
+ new_worklist->n_live_values = n_live_values;
return new_worklist;
}
worklist_entry_t *wl_entry
= list_entry(entry, worklist_entry_t, head);
- //DB((dbg, level, "%+F(%+F) ", wl_entry->value,
- // wl_entry->reload_point));
DB((dbg, level, "%+F ", wl_entry->value));
}
}
if(!arch_irn_consider_in_reg_alloc(arch_env, cls, node2))
continue;
- be_spill_phi(senv, node2);
+ if(!tentative_mode)
+ be_spill_phi(senv, node2);
}
break;
}
}
}
if(worklist == NULL) {
- /* only the end-block has 0 successors */
- assert(block == get_irg_end_block(get_irn_irg(block)));
+ /* at least 1 successor block must have been processed unless it was
+ * the end block */
+ assert(tentative_mode || block == get_irg_end_block(get_irn_irg(block)));
- worklist = obstack_alloc(&obst, sizeof(worklist[0]));
- init_worklist(worklist, 0);
+ worklist = new_worklist();
} else {
- worklist = duplicate_worklist(worklist, block, best_succ_block,
- best_pos);
- activate_worklist(worklist);
+ worklist = duplicate_activate_worklist(worklist, block, best_succ_block,
+ best_pos);
/* now we could have live values in the succ worklists that are not
- * live anymore in the worklist we picked. We need reloads for them.
- */
+ * live anymore in the worklist we picked. We need reloads for them. */
if(!tentative_mode) {
foreach_block_succ(block, edge) {
ir_node *succ_block = get_edge_src_irn(edge);
arch_env = be_get_birg_arch_env(birg);
exec_freq = be_get_birg_exec_freq(birg);
- tentative_mode = 0;
be_clear_links(irg);
set_using_irn_link(irg);
/* do a post-order walk over the CFG to make sure we have a maximum number
* of preds processed before entering a block */
+ tentative_mode = 1;
+ irg_block_edges_walk(get_irg_start_block(irg), NULL, process_block, NULL);
+
+ tentative_mode = 0;
irg_block_edges_walk(get_irg_start_block(irg), NULL, process_block, NULL);
clear_using_irn_link(irg);