improved belady3
[libfirm] / ir / be / bespillbelady3.c
1 /*
2  * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
3  *
4  * This file is part of libFirm.
5  *
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.
10  *
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.
14  *
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
17  * PURPOSE.
18  */
19
20 /**
21  * @file
22  * @brief       MIN-algorithm with some twists (aka belady spiller v3)
23  * @author      Matthias Braun
24  * @date        15.01.2008
25  * @version     $Id$
26  *
27  * TODO:
28  *   - handle phis correctly, decide wether we should spill them ~ok
29  *   - merge multiple start worksets of blocks ~ok
30  *   - how to and when to do the tentative phase...
31  */
32 #ifdef HAVE_CONFIG_H
33 #include "config.h"
34 #endif
35
36 #include <stdbool.h>
37
38 #include "debug.h"
39 #include "list.h"
40 #include "pdeq.h"
41
42 #include "irnode_t.h"
43 #include "irprintf.h"
44 #include "iredges_t.h"
45 #include "irloop_t.h"
46 #include "irgwalk.h"
47 #include "execfreq.h"
48
49 #include "bemodule.h"
50 #include "bespill.h"
51 #include "beutil.h"
52 #include "bespilloptions.h"
53 #include "besched_t.h"
54 #include "be_t.h"
55
56 DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
57
58 typedef struct loop_edge_t loop_edge_t;
59 struct loop_edge_t {
60         ir_node     *block;
61         int          pos;
62         loop_edge_t *next;
63 };
64
65 typedef struct loop_info_t loop_info_t;
66 struct loop_info_t {
67         loop_edge_t *entry_edges;
68         loop_edge_t *exit_edges;
69         size_t       max_register_pressure;
70 };
71
72 typedef struct worklist_entry_t worklist_entry_t;
73 struct worklist_entry_t {
74         struct list_head  head;
75         ir_node          *value;
76         ir_node          *reload_point;
77         worklist_entry_t *next_reload;
78 };
79
80 typedef struct worklist_t worklist_t;
81 struct worklist_t {
82         struct list_head  live_values;
83         size_t            n_live_values;
84 };
85
86 typedef struct block_info_t block_info_t;
87 struct block_info_t {
88         worklist_t *start_worklist;
89         worklist_t *end_worklist;
90 };
91
92 static const arch_env_t            *arch_env;
93 static const arch_register_class_t *cls;
94 static struct obstack               obst;
95 static spill_env_t                 *senv;
96 static size_t                       n_regs;
97 static size_t                       max_register_pressure;
98 static bool                         tentative_mode;
99 static bool                         should_have_reached_fixpoint;
100 static ir_exec_freq                *exec_freq;
101
102 static worklist_t *new_worklist(void)
103 {
104         worklist_t *worklist = obstack_alloc(&obst, sizeof(worklist[0]));
105
106         INIT_LIST_HEAD(&worklist->live_values);
107         worklist->n_live_values    = 0;
108
109         return worklist;
110 }
111
112 static void mark_irn_not_visited(ir_node *node)
113 {
114         set_irn_visited(node, get_irg_visited(current_ir_graph) - 1);
115 }
116
117 static bool worklist_contains(const ir_node *node)
118 {
119         return irn_visited(node);
120 }
121
122 static block_info_t *get_block_info(ir_node *block)
123 {
124         block_info_t *info = get_irn_link(block);
125         if (info != NULL)
126                 return info;
127
128         info = obstack_alloc(&obst, sizeof(info[0]));
129         memset(info, 0, sizeof(info[0]));
130         set_irn_link(block, info);
131         return info;
132 }
133
134 static void deactivate_worklist(const worklist_t *worklist)
135 {
136         struct list_head *entry;
137
138         list_for_each(entry, &worklist->live_values) {
139                 worklist_entry_t *wl_entry
140                         = list_entry(entry, worklist_entry_t, head);
141                 assert(worklist_contains(wl_entry->value));
142                 mark_irn_not_visited(wl_entry->value);
143                 set_irn_link(wl_entry->value, NULL);
144         }
145 }
146
147 static void activate_worklist(const worklist_t *worklist)
148 {
149         struct list_head *entry;
150
151         list_for_each(entry, &worklist->live_values) {
152                 worklist_entry_t *wl_entry
153                         = list_entry(entry, worklist_entry_t, head);
154                 assert(!worklist_contains(wl_entry->value));
155                 mark_irn_visited(wl_entry->value);
156                 set_irn_link(wl_entry->value, wl_entry);
157         }
158 }
159
160 /**
161  * duplicate a worklist and directly activates it
162  */
163 static worklist_t *duplicate_activate_worklist(const worklist_t *worklist,
164                 ir_node *block, ir_node *succ_block, int succ_pos)
165 {
166         ir_node          *reload_point  = NULL;
167         size_t            n_live_values = 0;
168         worklist_t       *new_worklist;
169         struct list_head *entry;
170
171         if (succ_block != NULL &&
172                         (get_Block_n_cfgpreds(succ_block) > 1
173                          || get_irn_n_edges_kind(block, EDGE_KIND_BLOCK) > 1)) {
174                 reload_point = be_get_end_of_block_insertion_point(block);
175         }
176
177         new_worklist = obstack_alloc(&obst, sizeof(new_worklist[0]));
178         INIT_LIST_HEAD(&new_worklist->live_values);
179
180         list_for_each(entry, &worklist->live_values) {
181                 worklist_entry_t *wl_entry  = list_entry(entry, worklist_entry_t, head);
182                 ir_node          *value     = wl_entry->value;
183
184                 if (is_Phi(value) && get_nodes_block(value) == succ_block) {
185                         value = get_Phi_pred(value, succ_pos);
186
187                         /* can happen for unknown phi preds */
188                         if (!arch_irn_consider_in_reg_alloc(arch_env, cls, value))
189                                 continue;
190                 }
191
192                 worklist_entry_t *new_entry
193                         = obstack_alloc(&obst, sizeof(new_entry[0]));
194                 new_entry->value = value;
195                 if (reload_point != NULL) {
196                         new_entry->reload_point = reload_point;
197                 } else {
198                         new_entry->reload_point = wl_entry->reload_point;
199                 }
200                 new_entry->next_reload = NULL;
201
202                 if (irn_not_visited(value)) {
203                         list_add_tail(&new_entry->head, &new_worklist->live_values);
204                         ++n_live_values;
205
206                         mark_irn_visited(value);
207                         set_irn_link(value, new_entry);
208                 }
209 #if 0
210                 else {
211                         /* the only way we might visit a value again, is when we get it as
212                          * phi predecessor */
213                         assert(is_Phi(wl_entry->value)
214                                         && get_nodes_block(wl_entry->value) == succ_block);
215                 }
216 #endif
217         }
218         new_worklist->n_live_values = n_live_values;
219
220         return new_worklist;
221 }
222
223 static worklist_t *duplicate_worklist(const worklist_t *worklist)
224 {
225         worklist_t       *new_worklist;
226         struct list_head *entry;
227
228         new_worklist = obstack_alloc(&obst, sizeof(new_worklist[0]));
229         INIT_LIST_HEAD(&new_worklist->live_values);
230         new_worklist->n_live_values = worklist->n_live_values;
231
232         list_for_each(entry, &worklist->live_values) {
233                 worklist_entry_t *wl_entry  = list_entry(entry, worklist_entry_t, head);
234                 worklist_entry_t *new_entry
235                         = obstack_alloc(&obst, sizeof(new_entry[0]));
236
237                 memcpy(new_entry, wl_entry, sizeof(new_entry[0]));
238                 list_add_tail(&new_entry->head, &new_worklist->live_values);
239         }
240
241         return new_worklist;
242 }
243
244 #ifdef DEBUG_libfirm
245 static void print_worklist(const worklist_t *worklist, int level)
246 {
247         struct list_head *entry;
248
249         DB((dbg, level, "%d values: ", worklist->n_live_values));
250         list_for_each(entry, &worklist->live_values) {
251                 worklist_entry_t *wl_entry
252                         = list_entry(entry, worklist_entry_t, head);
253
254                 DB((dbg, level, "%+F ", wl_entry->value));
255         }
256 }
257 #endif
258
259
260
261 static void clear_loop_info(ir_loop *loop)
262 {
263         int n_elements = get_loop_n_elements(loop);
264         int i;
265
266         loop->link = NULL;
267         for (i = 0; i < n_elements; ++i) {
268                 loop_element element = get_loop_element(loop, i);
269                 if (*element.kind != k_ir_loop)
270                         continue;
271
272                 clear_loop_info(element.son);
273         }
274 }
275
276 static loop_info_t *get_loop_info(ir_loop *loop)
277 {
278         loop_info_t *info = loop->link;
279         if (info != NULL)
280                 return info;
281
282         info = obstack_alloc(&obst, sizeof(info[0]));
283         memset(info, 0, sizeof(info[0]));
284         loop->link = info;
285         return info;
286 }
287
288 /**
289  * constructs loop in+out edges when called in a block walker
290  */
291 static void construct_loop_edges(ir_node *block, void *data)
292 {
293         int      n_cfgpreds = get_Block_n_cfgpreds(block);
294         ir_loop *loop       = get_irn_loop(block);
295         int      i;
296
297         (void) data;
298
299         for (i = 0; i < n_cfgpreds; ++i) {
300                 ir_node     *cfgpred_block = get_Block_cfgpred_block(block, i);
301                 ir_loop     *cfgpred_loop  = get_irn_loop(cfgpred_block);
302                 loop_edge_t *edge;
303
304                 if (cfgpred_loop == loop)
305                         continue;
306
307                 /* critical edges are splitted, so we can't jump from 1 loop
308                  * directly into another without going out of it */
309                 assert(get_loop_depth(cfgpred_loop) != get_loop_depth(loop));
310
311                 /* edge out of loop */
312                 bool is_exit_edge;
313                 ir_loop *l, *goal;
314                 if (get_loop_depth(cfgpred_loop) > get_loop_depth(loop)) {
315                         is_exit_edge = true;
316                         l            = cfgpred_loop;
317                         goal         = loop;
318                 } else {
319                         is_exit_edge = false;
320                         l            = loop;
321                         goal         = cfgpred_loop;
322                 }
323
324                 /* this might be a jump out/in multiple loops */
325                 do {
326                         loop_info_t *l_info = get_loop_info(l);
327
328                         edge = obstack_alloc(&obst, sizeof(edge[0]));
329                         memset(edge, 0, sizeof(edge[0]));
330                         edge->block = block;
331                         edge->pos   = i;
332
333                         if (is_exit_edge) {
334                                 ir_fprintf(stderr, "Loop %p exit edge %+F:%d\n",
335                                            l, block, i);
336                                 edge->next         = l_info->exit_edges;
337                                 l_info->exit_edges = edge;
338                                 assert(get_loop_depth(loop) < get_loop_depth(l));
339                         } else {
340                                 ir_fprintf(stderr, "Loop %p entry edge %+F:%d\n",
341                                            l, block, i);
342                                 edge->next          = l_info->entry_edges;
343                                 l_info->entry_edges = edge;
344                                 assert(get_loop_depth(cfgpred_loop) < get_loop_depth(l));
345                         }
346                         l = get_loop_outer_loop(l);
347                 } while(l != goal);
348         }
349 }
350
351
352
353
354 static void place_reload(worklist_entry_t *entry)
355 {
356         if (tentative_mode)
357                 return;
358
359         /* walk list of reload points */
360         do {
361                 DB((dbg, LEVEL_1, "reload of %+F before %+F\n", entry->value,
362                     entry->reload_point));
363                 assert(entry->reload_point != NULL);
364                 be_add_reload(senv, entry->value, entry->reload_point, cls, 1);
365                 entry->reload_point = NULL;
366
367                 entry = entry->next_reload;
368         } while(entry != NULL);
369 }
370
371 #if 0
372 /**
373  * does stuff required for non-active worklists: spills all values not live
374  * in the active worklist; links live values to the current worklist
375  */
376 static void process_non_active_worklist(const worklist_t *worklist,
377                                         worklist_t *current_worklist)
378 {
379         struct list_head *entry;
380
381         list_for_each(entry, &worklist->live_values) {
382                 worklist_entry_t *wl_entry = list_entry(entry, worklist_entry_t, head);
383                 ir_node          *value    = wl_entry->value;
384
385                 if (!worklist_contains(value)) {
386                         /* if we still have room in the worklist, then we can simply take
387                          * the value */
388                         if (current_worklist->n_live_values < n_regs) {
389                                 worklist_entry_t *new_entry
390                                         = obstack_alloc(&obst, sizeof(new_entry[0]));
391
392                                 new_entry->value        = value;
393                                 new_entry->reload_point = wl_entry->reload_point;
394                                 new_entry->next_reload  = wl_entry->next_reload;
395                                 set_irn_link(value, new_entry);
396                                 mark_irn_visited(value);
397                                 list_add(&new_entry->head, &current_worklist->live_values);
398                                 ++current_worklist->n_live_values;
399                         } else {
400                                 /* value is not in current worklist, place reloads */
401                                 place_reload(wl_entry);
402                         }
403                 } else {
404                         /* value is in current worklist, link it with the reload point
405                          * from this path */
406                         worklist_entry_t *active_entry = get_irn_link(value);
407                         wl_entry->next_reload          = active_entry->next_reload;
408                         active_entry->next_reload      = wl_entry;
409                 }
410         }
411 }
412 #endif
413
414 /**
415  * makes sure the worklist contains not more than n_regs - room_needed entries
416  */
417 static void make_room(worklist_t *worklist, size_t room_needed)
418 {
419         int               i;
420         int               spills_needed;
421         struct list_head *entry;
422
423         spills_needed = worklist->n_live_values + room_needed - n_regs;
424         if (spills_needed <= 0)
425                 return;
426
427         entry = worklist->live_values.next;
428         for(i = spills_needed; i > 0; --i) {
429                 struct list_head *next = entry->next;
430                 worklist_entry_t *wl_entry
431                         = list_entry(entry, worklist_entry_t, head);
432
433                 assert(worklist_contains(wl_entry->value));
434                 mark_irn_not_visited(wl_entry->value);
435                 place_reload(wl_entry);
436                 list_del(entry);
437
438                 entry = next;
439         }
440         worklist->n_live_values -= spills_needed;
441 }
442
443 /**
444  * a value was used, so bring it to the back of the worklist (which might
445  * result in a spill of another value).
446  */
447 static void val_used(worklist_t *worklist, ir_node *value, ir_node *sched_point)
448 {
449         assert(arch_irn_consider_in_reg_alloc(arch_env, cls, value));
450
451         /* already in the worklist? move around, otherwise add at back */
452         worklist_entry_t *entry = get_irn_link(value);
453         if (worklist_contains(value)) {
454                 assert(entry != NULL);
455
456                 list_del(&entry->head);
457         } else {
458                 if (entry == NULL) {
459                         entry        = obstack_alloc(&obst, sizeof(entry[0]));
460                         entry->value = value;
461                         set_irn_link(value, entry);
462                 }
463
464                 ++worklist->n_live_values;
465                 mark_irn_visited(value);
466         }
467
468         entry->reload_point = sched_point;
469         entry->next_reload  = NULL;
470         list_add_tail(&entry->head, &worklist->live_values);
471 }
472
473 static void worklist_remove(worklist_t *worklist, ir_node *value)
474 {
475         worklist_entry_t *entry = get_irn_link(value);
476         assert(entry != NULL);
477         list_del(&entry->head);
478         --worklist->n_live_values;
479
480         assert(worklist_contains(value));
481         mark_irn_not_visited(value);
482 }
483
484 static void update_max_pressure(worklist_t *worklist)
485 {
486         if (worklist->n_live_values > max_register_pressure)
487                 max_register_pressure = worklist->n_live_values;
488 }
489
490 static void do_spilling(ir_node *block, worklist_t *worklist)
491 {
492         ir_node *node;
493
494         assert(worklist != NULL);
495
496         sched_foreach_reverse(block, node) {
497                 int    i, arity;
498                 size_t n_defs = 0;
499
500                 DB((dbg, LEVEL_2, "\t%+F... ", node));
501                 update_max_pressure(worklist);
502
503                 if (is_Phi(node)) {
504                         ir_node *node2;
505                         /* TODO: if we have some free registers, then we could decide to
506                          * not spill some phis (but not for phis where at least 1 input is
507                          * themselfes) */
508
509                         /* we have to spill all phis that are not live */
510                         sched_foreach_reverse_from(node, node2) {
511                                 assert(is_Phi(node2));
512
513                                 if (worklist_contains(node2))
514                                         continue;
515                                 if (!arch_irn_consider_in_reg_alloc(arch_env, cls, node2))
516                                         continue;
517
518                                 if (!tentative_mode)
519                                         be_spill_phi(senv, node2);
520                         }
521                         DB((dbg, LEVEL_2, "\n"));
522                         break;
523                 }
524
525                 /* remove values defined by this instruction from the workset. Values
526                  * defined but not in the workset need free registers */
527                 if (get_irn_mode(node) == mode_T) {
528                         const ir_edge_t *edge;
529
530                         foreach_out_edge(node, edge) {
531                                 ir_node *proj = get_edge_src_irn(edge);
532                                 if (!arch_irn_consider_in_reg_alloc(arch_env, cls, proj))
533                                         continue;
534                                 if (worklist_contains(proj)) {
535                                         worklist_remove(worklist, proj);
536                                 } else {
537                                         ++n_defs;
538                                 }
539                         }
540                 } else if (arch_irn_consider_in_reg_alloc(arch_env, cls, node)) {
541                         if (worklist_contains(node)) {
542                                 worklist_remove(worklist, node);
543                         } else {
544                                 n_defs = 1;
545                         }
546                 }
547
548                 /* make sure we have enough free registers for the spills */
549                 make_room(worklist, n_defs);
550
551                 /* put all values used by the instruction into the workset */
552                 arity = get_irn_arity(node);
553                 for(i = 0; i < arity; ++i) {
554                         ir_node *use = get_irn_n(node, i);
555
556                         if (!arch_irn_consider_in_reg_alloc(arch_env, cls, use))
557                                 continue;
558
559                         val_used(worklist, use, node);
560                 }
561
562                 /* we might have too many values in the worklist now and need to spill
563                  * some */
564                 make_room(worklist, 0);
565
566 #ifdef DEBUG_libfirm
567                 print_worklist(worklist, LEVEL_2);
568                 DB((dbg, LEVEL_2, "\n"));
569 #endif
570         }
571
572         update_max_pressure(worklist);
573
574 #ifdef DEBUG_libfirm
575         DB((dbg, LEVEL_1, "worklist at begin of %+F:", block));
576         print_worklist(worklist, LEVEL_1);
577         DB((dbg, LEVEL_1, "\n"));
578 #endif
579 }
580
581 static bool worklists_equal(const worklist_t *wl1, const worklist_t *wl2)
582 {
583         const struct list_head *i1 = &wl1->live_values;
584         const struct list_head *i2 = &wl2->live_values;
585
586         for ( ; i1 != &wl1->live_values && i2 != &wl2->live_values;
587                         i1 = i1->next, i2 = i2->next) {
588                 worklist_entry_t *entry1 = list_entry(i1, worklist_entry_t, head);
589                 worklist_entry_t *entry2 = list_entry(i2, worklist_entry_t, head);
590
591                 if (entry1->value != entry2->value)
592                         return false;
593         }
594         /* both lists at the end */
595         if (i1 != &wl1->live_values || i2 != &wl2->live_values)
596                 return false;
597
598         return true;
599 }
600
601 static void process_block(ir_node *block, void *env)
602 {
603         block_info_t    *block_info      = NULL;
604         worklist_t      *worklist        = NULL;
605         double           best_execfreq   = -1;
606         ir_node         *best_succ_block = NULL;
607         int              best_pos        = -1;
608         int              n_preds;
609         const ir_edge_t *edge;
610
611         (void) env;
612         DB((dbg, LEVEL_1, "Processing %+F\n", block));
613
614         /* construct worklist */
615         foreach_block_succ(block, edge) {
616                 ir_node *succ_block = get_edge_src_irn(edge);
617                 double   execfreq   = get_block_execfreq(exec_freq, succ_block);
618
619                 if (execfreq > best_execfreq) {
620                         block_info_t *block_info    = get_block_info(succ_block);
621                         worklist_t   *succ_worklist = block_info->start_worklist;
622                         if (succ_worklist != NULL) {
623                                 best_execfreq   = execfreq;
624                                 worklist        = succ_worklist;
625                                 best_succ_block = succ_block;
626                                 best_pos        = get_edge_src_pos(edge);
627                         }
628                 }
629         }
630         if (worklist == NULL) {
631                 /* at least 1 successor block must have been processed unless it was
632                  * the end block */
633                 assert(tentative_mode || block == get_irg_end_block(get_irn_irg(block)));
634
635                 worklist = new_worklist();
636         } else {
637                 worklist = duplicate_activate_worklist(worklist, block, best_succ_block,
638                                                        best_pos);
639
640                 /* handle this in fix_blocks later... */
641 #if 0
642                 /* now we could have live values in the succ worklists that are not
643                  * live anymore in the worklist we picked. We need reloads for them. */
644                 foreach_block_succ(block, edge) {
645                         ir_node      *succ_block    = get_edge_src_irn(edge);
646                         block_info_t *block_info    = get_block_info(succ_block);
647                         worklist_t   *succ_worklist = block_info->start_worklist;
648
649                         if (succ_block == best_succ_block)
650                                 continue;
651
652                         process_non_active_worklist(succ_worklist, worklist);
653                 }
654 #endif
655         }
656
657         block_info = get_block_info(block);
658
659 #ifdef DEBUG_libfirm
660         DB((dbg, LEVEL_1, "worklist at end of %+F:", block));
661         print_worklist(worklist, LEVEL_1);
662         DB((dbg, LEVEL_1, "\n"));
663
664         if (should_have_reached_fixpoint) {
665                 assert(worklists_equal(block_info->end_worklist, worklist));
666         }
667 #endif
668         block_info->end_worklist = duplicate_worklist(worklist);
669
670         do_spilling(block, worklist);
671         deactivate_worklist(worklist);
672
673 #ifdef DEBUG_libfirm
674         if (should_have_reached_fixpoint) {
675                 assert(worklists_equal(block_info->start_worklist, worklist));
676         }
677 #endif
678         block_info->start_worklist = worklist;
679
680         /* we shouldn't have any live values left at the start block */
681         n_preds = get_Block_n_cfgpreds(block);
682         assert(n_preds != 0 || worklist->n_live_values == 0);
683 }
684
685 typedef struct block_or_loop_t block_or_loop_t;
686 struct block_or_loop_t {
687         union {
688                 ir_node *block;
689                 ir_loop *loop;
690         } v;
691         bool is_loop;
692 };
693
694 static block_or_loop_t *loop_blocks;
695 static ir_loop         *current_loop;
696
697 static void find_blocks(ir_node *block);
698
699 static void find_in_loop(ir_loop *loop, ir_node *entry)
700 {
701         loop_info_t *loop_info = get_loop_info(loop);
702
703         /* simply mark 1 block in the loop to indicate that the loop was already
704          * processed */
705         ir_node *some_block = loop_info->entry_edges->block;
706         if (Block_block_visited(some_block))
707                 return;
708
709         block_or_loop_t block_or_loop;
710         block_or_loop.v.loop  = loop;
711         block_or_loop.is_loop = true;
712         ARR_APP1(block_or_loop_t, loop_blocks, block_or_loop);
713
714 #ifndef NDEBUG
715         {
716                 /* we should be 1 of the entry blocks */
717                 loop_edge_t *edge  = loop_info->entry_edges;
718                 bool         found = false;
719                 for ( ; edge != NULL; edge = edge->next) {
720                         if (edge->block == entry)
721                                 found = true;
722                 }
723                 assert(found);
724         }
725 #endif
726         /* check all loop successors */
727         loop_edge_t *edge = loop_info->exit_edges;
728         for ( ; edge != NULL; edge = edge->next) {
729                 ir_node     *succ      = edge->block;
730                 ir_loop     *succ_loop = get_irn_loop(succ);
731
732                 if (succ_loop == current_loop) {
733                         find_blocks(succ);
734                 } else {
735                         assert(get_loop_depth(succ_loop) < get_loop_depth(current_loop));
736                 }
737         }
738 }
739
740 static void find_blocks(ir_node *block)
741 {
742         const ir_edge_t *edge;
743
744         if (Block_block_visited(block))
745                 return;
746
747         block_or_loop_t block_or_loop;
748         block_or_loop.v.block = block;
749         block_or_loop.is_loop = false;
750
751         ARR_APP1(block_or_loop_t, loop_blocks, block_or_loop);
752         mark_Block_block_visited(block);
753
754         foreach_block_succ(block, edge) {
755                 ir_node *succ = get_edge_src_irn(edge);
756
757                 /* is it part of the current loop? */
758                 ir_loop *loop = get_irn_loop(succ);
759                 if (loop != current_loop) {
760                         /* a sub-loop? */
761                         if (get_loop_depth(loop) > get_loop_depth(current_loop)) {
762                                 find_in_loop(loop, succ);
763                         } else {
764                                 /* parent loop: we're not interested in the block */
765                         }
766                 } else {
767                         find_blocks(succ);
768                 }
769         }
770 }
771
772 static void process_block_or_loop(const block_or_loop_t *block_or_loop)
773 {
774         if (block_or_loop->is_loop) {
775                 loop_info_t *loop_info = get_loop_info(block_or_loop->v.loop);
776
777                 if (loop_info->max_register_pressure > max_register_pressure)
778                         max_register_pressure = loop_info->max_register_pressure;
779
780                 /* TODO: push unused livethroughs... */
781                 return;
782         }
783         process_block(block_or_loop->v.block, NULL);
784 }
785
786 static void process_loop(ir_loop *loop)
787 {
788         /* first handle all sub-loops */
789         int n_elements = get_loop_n_elements(loop);
790         int i;
791
792         for (i = 0; i < n_elements; ++i) {
793                 loop_element element = get_loop_element(loop, i);
794                 if (*element.kind != k_ir_loop)
795                         continue;
796
797                 process_loop(element.son);
798         }
799
800         /* create a postorder of the blocks */
801         loop_info_t *loop_info = get_loop_info(loop);
802         loop_edge_t *edge      = loop_info->entry_edges;
803         ir_node     *some_block;
804         if (edge != NULL) {
805                 some_block = edge->block;
806         } else {
807                 assert(loop == get_irg_loop(current_ir_graph));
808                 some_block = get_irg_start_block(current_ir_graph);
809         }
810
811         loop_blocks  = NEW_ARR_F(block_or_loop_t,0);
812         current_loop = loop;
813
814         ir_reserve_resources(current_ir_graph, IR_RESOURCE_BLOCK_VISITED);
815         inc_irg_block_visited(current_ir_graph);
816         find_blocks(some_block);
817         /* for endless loops the end-block might be unreachable */
818         if (loop == get_irg_loop(current_ir_graph)) {
819                 find_blocks(get_irg_end_block(current_ir_graph));
820         }
821         ir_free_resources(current_ir_graph, IR_RESOURCE_BLOCK_VISITED);
822
823         fprintf(stderr, "Block List for loop %p\n", loop);
824         int len = ARR_LEN(loop_blocks);
825         for (i = 0; i < len; ++i) {
826                 block_or_loop_t *block_or_loop = &loop_blocks[i];
827                 if (block_or_loop->is_loop) {
828                         ir_fprintf(stderr, " L-%p", block_or_loop->v.loop);
829                 } else {
830                         ir_fprintf(stderr, " B-%+F", block_or_loop->v.block);
831                 }
832         }
833         fprintf(stderr, "\n");
834
835         max_register_pressure = 0;
836
837         /* run1: tentative phase */
838         tentative_mode = true;
839         for (i = len-1; i >= 0; --i) {
840                 process_block_or_loop(&loop_blocks[i]);
841         }
842
843         /* run2: tentative phase - should reach fixpoint */
844         tentative_mode = true;
845         for (i = len-1; i >= 0; --i) {
846                 process_block_or_loop(&loop_blocks[i]);
847         }
848
849 #ifndef NDEBUG
850         /* run3: tentative phase - check fixpoint */
851         tentative_mode               = true;
852         should_have_reached_fixpoint = true;
853         for (i = len-1; i >= 0; --i) {
854                 process_block_or_loop(&loop_blocks[i]);
855         }
856         should_have_reached_fixpoint = false;
857 #endif
858
859         /* run4: add spills/reloads */
860         tentative_mode = false;
861         for (i = len-1; i >= 0; --i) {
862                 process_block_or_loop(&loop_blocks[i]);
863         }
864
865         loop_info->max_register_pressure = max_register_pressure;
866         ir_fprintf(stderr, "Regpressure in loop %p: %u\n", loop,
867                    (unsigned) max_register_pressure);
868
869         DEL_ARR_F(loop_blocks);
870 }
871
872 static void fix_block_borders(ir_node *block, void *data)
873 {
874         block_info_t *block_info     = get_block_info(block);
875         worklist_t   *start_worklist = block_info->start_worklist;
876         int           n_cfgpreds     = get_Block_n_cfgpreds(block);
877         int           i;
878
879         (void) data;
880         assert(start_worklist != NULL);
881
882         for (i = 0; i < n_cfgpreds; ++i) {
883                 ir_node      *pred_block      = get_Block_cfgpred_block(block, i);
884                 block_info_t *pred_block_info = get_block_info(pred_block);
885                 worklist_t   *end_worklist    = pred_block_info->end_worklist;
886
887                 assert(end_worklist != NULL);
888
889                 /* reload missing values */
890                 struct list_head *entry;
891
892                 activate_worklist(end_worklist);
893
894                 list_for_each(entry, &start_worklist->live_values) {
895                         worklist_entry_t *wl_entry
896                                 = list_entry(entry, worklist_entry_t, head);
897                         ir_node          *value = wl_entry->value;
898
899                         if (is_Phi(value) && get_nodes_block(value) == block) {
900                                 value = get_irn_n(value, i);
901
902                                 /* we might have unknowns as argument for the phi */
903                                 if (!arch_irn_consider_in_reg_alloc(arch_env, cls, value))
904                                         continue;
905                         }
906
907                         if (worklist_contains(value))
908                                 continue;
909
910                         be_add_reload_on_edge(senv, value, block, i, cls, 1);
911                 }
912
913                 deactivate_worklist(end_worklist);
914         }
915 }
916
917 static void be_spill_belady3(be_irg_t *birg, const arch_register_class_t *ncls)
918 {
919         ir_graph *irg = be_get_birg_irg(birg);
920
921         cls    = ncls;
922         n_regs = cls->n_regs - be_put_ignore_regs(birg, cls, NULL);
923
924         /* shortcut for register classes with ignore regs only */
925         if (n_regs == 0)
926                 return;
927
928         arch_env  = be_get_birg_arch_env(birg);
929         exec_freq = be_get_birg_exec_freq(birg);
930
931         be_clear_links(irg);
932         ir_reserve_resources(irg, IR_RESOURCE_IRN_VISITED | IR_RESOURCE_IRN_LINK
933                         | IR_RESOURCE_LOOP_LINK);
934         inc_irg_visited(irg);
935
936         obstack_init(&obst);
937         senv = be_new_spill_env(birg);
938
939         assure_cf_loop(irg);
940         clear_loop_info(get_irg_loop(irg));
941         irg_block_walk_graph(irg, construct_loop_edges, NULL, NULL);
942
943         process_loop(get_irg_loop(current_ir_graph));
944
945 #if 0
946         /* do a post-order walk over the CFG to make sure we have a maximum number
947          * of preds processed before entering a block */
948         tentative_mode = 1;
949         irg_block_edges_walk(get_irg_start_block(irg), NULL, process_block, NULL);
950
951         tentative_mode = 1;
952         irg_block_edges_walk(get_irg_start_block(irg), NULL, process_block, NULL);
953
954         tentative_mode = 0;
955         irg_block_edges_walk(get_irg_start_block(irg), NULL, process_block, NULL);
956 #endif
957
958         irg_block_walk_graph(irg, fix_block_borders, NULL, NULL);
959
960         ir_free_resources(irg, IR_RESOURCE_IRN_VISITED | IR_RESOURCE_IRN_LINK
961                         | IR_RESOURCE_LOOP_LINK);
962
963         be_insert_spills_reloads(senv);
964
965         obstack_free(&obst, NULL);
966
967         /* clean up */
968         be_delete_spill_env(senv);
969 }
970
971 void be_init_spillbelady3(void)
972 {
973         static be_spiller_t belady3_spiller = {
974                 be_spill_belady3
975         };
976
977         be_register_spiller("belady3", &belady3_spiller);
978         FIRM_DBG_REGISTER(dbg, "firm.be.spill.belady3");
979 }
980
981 BE_REGISTER_MODULE_CONSTRUCTOR(be_init_spillbelady3);