2 * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved.
4 * This file is part of libFirm.
6 * This file may be distributed and/or modified under the terms of the
7 * GNU General Public License version 2 as published by the Free Software
8 * Foundation and appearing in the file LICENSE.GPL included in the
9 * packaging of this file.
11 * Licensees holding valid libFirm Professional Edition licenses may use
12 * this file in accordance with the libFirm Commercial License.
13 * Agreement provided with the Software.
15 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * @brief MIN-algorithm with some twists (aka belady spiller v3)
23 * @author Matthias Braun
28 * - handle phis correctly, decide wether we should spill them
29 * - merge multiple start worksets of blocks
30 * - how to and when to do the tentative phase...
42 #include "iredges_t.h"
48 #include "bespilloptions.h"
49 #include "besched_t.h"
52 DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
54 typedef struct worklist_entry_t worklist_entry_t;
55 struct worklist_entry_t {
56 struct list_head head;
59 ir_node *reload_point;
62 typedef struct worklist_t worklist_t;
64 struct list_head live_values;
66 unsigned current_timestep;
69 static const arch_env_t *arch_env;
70 static const arch_register_class_t *cls;
71 static struct obstack obst;
72 static spill_env_t *senv;
74 static int tentative_mode;
75 static ir_exec_freq *exec_freq;
77 static void init_worklist(worklist_t *worklist, unsigned timestep)
79 INIT_LIST_HEAD(&worklist->live_values);
80 worklist->n_live_values = 0;
81 worklist->current_timestep = timestep;
84 static void mark_irn_not_visited(ir_node *node)
86 set_irn_visited(node, get_irg_visited(current_ir_graph) - 1);
89 static void deactivate_worklist(const worklist_t *worklist)
91 struct list_head *entry;
93 list_for_each(entry, &worklist->live_values) {
94 worklist_entry_t *wl_entry
95 = list_entry(entry, worklist_entry_t, head);
96 assert(irn_visited(wl_entry->value));
97 mark_irn_not_visited(wl_entry->value);
98 set_irn_link(wl_entry->value, NULL);
102 static void activate_worklist(const worklist_t *worklist)
104 struct list_head *entry;
106 list_for_each(entry, &worklist->live_values) {
107 worklist_entry_t *wl_entry
108 = list_entry(entry, worklist_entry_t, head);
109 ir_node *value = wl_entry->value;
111 assert(irn_not_visited(value));
112 mark_irn_visited(value);
113 set_irn_link(value, wl_entry);
117 static worklist_t *duplicate_worklist(const worklist_t *worklist,
119 ir_node *succ_block, int succ_pos)
121 ir_node *reload_point = NULL;
122 struct list_head *entry;
123 worklist_t *new_worklist = obstack_alloc(&obst, sizeof(new_worklist[0]));
125 INIT_LIST_HEAD(&new_worklist->live_values);
127 if(succ_block != NULL && get_Block_n_cfgpreds(succ_block) > 1) {
128 reload_point = be_get_end_of_block_insertion_point(block);
131 new_worklist->current_timestep = worklist->current_timestep;
132 new_worklist->n_live_values = worklist->n_live_values;
134 list_for_each(entry, &worklist->live_values) {
135 worklist_entry_t *wl_entry
136 = list_entry(entry, worklist_entry_t, head);
137 worklist_entry_t *new_entry
138 = obstack_alloc(&obst, sizeof(new_entry[0]));
139 ir_node *value = wl_entry->value;
141 if(is_Phi(value) && get_nodes_block(value) == succ_block) {
142 value = get_Phi_pred(value, succ_pos);
145 new_entry->value = value;
146 new_entry->timestep = wl_entry->timestep;
147 if(reload_point != NULL) {
148 new_entry->reload_point = reload_point;
150 new_entry->reload_point = wl_entry->reload_point;
153 list_add_tail(&new_entry->head, &new_worklist->live_values);
160 static void print_worklist(const worklist_t *worklist, int level)
162 struct list_head *entry;
164 DB((dbg, level, "%d values (TS %u): ", worklist->n_live_values,
165 worklist->current_timestep));
166 list_for_each(entry, &worklist->live_values) {
167 worklist_entry_t *wl_entry
168 = list_entry(entry, worklist_entry_t, head);
170 //DB((dbg, level, "%+F(%+F) ", wl_entry->value,
171 // wl_entry->reload_point));
172 DB((dbg, level, "%+F ", wl_entry->value));
177 static void place_reload(worklist_entry_t *entry)
181 DB((dbg, LEVEL_1, "reload of %+F before %+F", entry->value,
182 entry->reload_point));
183 be_add_reload(senv, entry->value, entry->reload_point, cls, 1);
186 static void spill_non_live_nodes(const worklist_t *worklist)
188 struct list_head *entry;
190 list_for_each(entry, &worklist->live_values) {
191 worklist_entry_t *wl_entry
192 = list_entry(entry, worklist_entry_t, head);
193 ir_node *value = wl_entry->value;
195 if(irn_visited(value))
198 place_reload(wl_entry);
203 * makes sure the worklist contains not more than n_regs - room_needed entries
205 static void make_room(worklist_t *worklist, size_t room_needed)
207 int spills_needed = worklist->n_live_values + room_needed - n_regs;
208 if(spills_needed > 0) {
209 int i = spills_needed;
210 struct list_head *entry = worklist->live_values.next;
211 for(i = spills_needed; i > 0; --i) {
212 struct list_head *next = entry->next;
213 worklist_entry_t *wl_entry
214 = list_entry(entry, worklist_entry_t, head);
215 assert(irn_visited(wl_entry->value));
216 mark_irn_not_visited(wl_entry->value);
217 place_reload(wl_entry);
222 worklist->n_live_values -= spills_needed;
227 * a value was used, so bring it to the back of the worklist (which might
228 * result in a spill of another value).
230 static void val_used(worklist_t *worklist, ir_node *value, ir_node *sched_point)
232 /* is the node in the worklist already? */
233 worklist_entry_t *entry = get_irn_link(value);
234 if(irn_visited(value)) {
235 assert(entry != NULL);
237 assert(irn_visited(value));
238 list_del(&entry->head);
241 entry = obstack_alloc(&obst, sizeof(entry[0]));
242 entry->value = value;
243 set_irn_link(value, entry);
246 ++worklist->n_live_values;
247 mark_irn_visited(value);
250 entry->timestep = worklist->current_timestep;
251 entry->reload_point = sched_point;
252 list_add_tail(&entry->head, &worklist->live_values);
255 static void worklist_remove(worklist_t *worklist, ir_node *value)
257 worklist_entry_t *entry = get_irn_link(value);
258 assert(entry != NULL);
259 list_del(&entry->head);
260 --worklist->n_live_values;
262 assert(irn_visited(value));
263 mark_irn_not_visited(value);
266 static void do_spilling(ir_node *block, worklist_t *worklist)
270 assert(worklist != NULL);
273 DB((dbg, LEVEL_1, "worklist at end of %+F:", block));
274 print_worklist(worklist, LEVEL_1);
275 DB((dbg, LEVEL_1, "\n"));
278 sched_foreach_reverse(block, node) {
282 DB((dbg, LEVEL_2, "\t%+F... ", node));
286 /* TODO: if we have some free registers, then we could decide to
287 * not spill some phis (but not for phis where at least 1 input is
290 /* we have to spill all phis that are not live */
291 sched_foreach_reverse_from(node, node2) {
292 assert(is_Phi(node2));
294 if(irn_visited(node2))
296 if(!arch_irn_consider_in_reg_alloc(arch_env, cls, node2))
299 be_spill_phi(senv, node2);
304 /* remove values defined by this instruction from the workset. Values
305 * defined but not in the workset need free registers */
306 if(get_irn_mode(node) == mode_T) {
307 const ir_edge_t *edge;
309 foreach_out_edge(node, edge) {
310 ir_node *proj = get_edge_src_irn(edge);
311 if(!arch_irn_consider_in_reg_alloc(arch_env, cls, proj))
313 if(irn_visited(proj)) {
314 worklist_remove(worklist, proj);
319 } else if(arch_irn_consider_in_reg_alloc(arch_env, cls, node)) {
320 if(irn_visited(node)) {
321 worklist_remove(worklist, node);
327 /* make sure we have enough free registers for the spills */
328 make_room(worklist, n_defs);
330 /* put all values by the instruction into the workset */
331 arity = get_irn_arity(node);
332 for(i = 0; i < arity; ++i) {
333 ir_node *use = get_irn_n(node, i);
335 if(!arch_irn_consider_in_reg_alloc(arch_env, cls, use))
338 val_used(worklist, use, node);
341 /* we might have too many values in the worklist now and need to spill
343 make_room(worklist, 0);
345 ++worklist->current_timestep;
348 print_worklist(worklist, LEVEL_2);
349 DB((dbg, LEVEL_2, "\n"));
354 DB((dbg, LEVEL_1, "worklist at begin of %+F:", block));
355 print_worklist(worklist, LEVEL_1);
356 DB((dbg, LEVEL_1, "\n"));
360 static void process_block(ir_node *block, void *env)
363 const ir_edge_t *edge;
364 worklist_t *worklist = NULL;
365 double best_execfreq = -1;
366 ir_node *best_succ_block = NULL;
370 DB((dbg, LEVEL_1, "Processing %+F\n", block));
372 /* construct worklist */
373 foreach_block_succ(block, edge) {
374 ir_node *succ_block = get_edge_src_irn(edge);
375 double execfreq = get_block_execfreq(exec_freq, succ_block);
377 if(execfreq > best_execfreq) {
378 worklist_t *succ_worklist = get_irn_link(succ_block);
379 if(succ_worklist != NULL) {
380 best_execfreq = execfreq;
381 worklist = succ_worklist;
382 best_succ_block = succ_block;
383 best_pos = get_edge_src_pos(edge);
387 if(worklist == NULL) {
388 /* only the end-block has 0 successors */
389 assert(block == get_irg_end_block(get_irn_irg(block)));
391 worklist = obstack_alloc(&obst, sizeof(worklist[0]));
392 init_worklist(worklist, 0);
394 worklist = duplicate_worklist(worklist, block, best_succ_block,
396 activate_worklist(worklist);
398 /* now we could have live values in the succ worklists that are not
399 * live anymore in the worklist we picked. We need reloads for them.
401 if(!tentative_mode) {
402 foreach_block_succ(block, edge) {
403 ir_node *succ_block = get_edge_src_irn(edge);
404 worklist_t *succ_worklist = get_irn_link(succ_block);
406 spill_non_live_nodes(succ_worklist);
411 do_spilling(block, worklist);
412 deactivate_worklist(worklist);
414 set_irn_link(block, worklist);
416 /* we shouldn't have any live values left at the start block */
417 n_preds = get_Block_n_cfgpreds(block);
418 assert(n_preds != 0 || worklist->n_live_values == 0);
421 static void be_spill_belady3(be_irg_t *birg, const arch_register_class_t *ncls)
423 ir_graph *irg = be_get_birg_irg(birg);
426 n_regs = cls->n_regs - be_put_ignore_regs(birg, cls, NULL);
431 arch_env = be_get_birg_arch_env(birg);
432 exec_freq = be_get_birg_exec_freq(birg);
436 set_using_irn_link(irg);
437 set_using_irn_visited(irg);
438 inc_irg_visited(irg);
441 senv = be_new_spill_env(birg);
443 /* do a post-order walk over the CFG to make sure we have a maximum number
444 * of preds processed before entering a block */
445 irg_block_edges_walk(get_irg_start_block(irg), NULL, process_block, NULL);
447 clear_using_irn_link(irg);
448 clear_using_irn_visited(irg);
450 be_insert_spills_reloads(senv);
452 obstack_free(&obst, NULL);
455 be_delete_spill_env(senv);
458 void be_init_spillbelady3(void)
460 static be_spiller_t belady3_spiller = {
464 be_register_spiller("belady3", &belady3_spiller);
465 FIRM_DBG_REGISTER(dbg, "firm.be.spill.belady3");
468 BE_REGISTER_MODULE_CONSTRUCTOR(be_init_spillbelady3);