cleanup: Remove pointless assert(is_${NODE}(x)) just before get_${NODE}_${FOO}(x...
[libfirm] / ir / be / besched.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       Scheduling utilities for nodes in Blocks and Blocks.
23  * @author      Sebastian Hack
24  */
25 #include "config.h"
26
27 #include <stdlib.h>
28
29 #include "firm_types.h"
30 #include "iredges_t.h"
31 #include "ircons.h"
32 #include "irgmod.h"
33 #include "debug.h"
34
35 #include "bemodule.h"
36 #include "bearch.h"
37 #include "besched.h"
38 #include "beutil.h"
39 #include "belistsched.h"
40 #include "belive.h"
41
42 #include "lc_opts.h"
43 #include "lc_opts_enum.h"
44 #include "irtools.h"
45
46 #define SCHED_INITIAL_GRANULARITY (1 << 14)
47
48 static void sched_renumber(const ir_node *block)
49 {
50         sched_info_t *inf;
51         sched_timestep_t step = SCHED_INITIAL_GRANULARITY;
52
53         sched_foreach(block, irn) {
54                 inf = get_irn_sched_info(irn);
55                 inf->time_step = step;
56                 step += SCHED_INITIAL_GRANULARITY;
57         }
58 }
59
60 static inline void sched_set_time_stamp(const ir_node *irn)
61 {
62         sched_info_t       *info      = get_irn_sched_info(irn);
63         const sched_info_t *prev_info = get_irn_sched_info(info->prev);
64         const sched_info_t *next_info = get_irn_sched_info(info->next);
65         sched_timestep_t    before_ts = prev_info->time_step;
66         sched_timestep_t    after_ts  = next_info->time_step;
67
68         /*
69          * If we are the last, we can give us a big time step,
70          * else we have to compute our time step from our
71          * neighbours.
72          */
73         if(before_ts >= after_ts) {
74                 info->time_step = before_ts + SCHED_INITIAL_GRANULARITY;
75                 /* overflow? */
76                 if (info->time_step <= before_ts) {
77                         sched_renumber(get_nodes_block(irn));
78                 }
79         } else {
80                 sched_timestep_t ts = (before_ts + after_ts) / 2;
81
82                 /*
83                  * If the resolution went out, we have to renumber
84                  * this block.
85                  */
86                 if(ts == before_ts || ts == after_ts)
87                         sched_renumber(get_nodes_block(irn));
88                 else
89                         info->time_step = ts;
90         }
91 }
92
93 void sched_add_before(ir_node *before, ir_node *irn)
94 {
95         sched_info_t *info      = get_irn_sched_info(irn);
96         ir_node      *next      = before;
97         sched_info_t *next_info = get_irn_sched_info(next);
98         ir_node      *prev      = next_info->prev;
99         sched_info_t *prev_info = get_irn_sched_info(prev);
100         assert(sched_is_scheduled(before));
101         assert(!sched_is_scheduled(irn));
102         assert(!is_Proj(before));
103         assert(!is_Proj(irn));
104
105         info->prev = prev;
106         info->next = next;
107         prev_info->next = irn;
108         next_info->prev = irn;
109         sched_set_time_stamp(irn);
110 }
111
112 void sched_add_after(ir_node *after, ir_node *irn)
113 {
114         sched_info_t *info      = get_irn_sched_info(irn);
115         ir_node      *prev      = after;
116         sched_info_t *prev_info = get_irn_sched_info(prev);
117         ir_node      *next      = prev_info->next;
118         sched_info_t *next_info = get_irn_sched_info(next);
119         assert(sched_is_scheduled(after));
120         assert(!sched_is_scheduled(irn));
121         assert(!is_Proj(after));
122         assert(!is_Proj(irn));
123
124         info->prev = prev;
125         info->next = next;
126         prev_info->next = irn;
127         next_info->prev = irn;
128         sched_set_time_stamp(irn);
129 }
130
131 void sched_remove(ir_node *irn)
132 {
133         sched_info_t *info      = get_irn_sched_info(irn);
134         ir_node      *prev      = info->prev;
135         ir_node      *next      = info->next;
136         sched_info_t *prev_info = get_irn_sched_info(prev);
137         sched_info_t *next_info = get_irn_sched_info(next);
138         assert(sched_is_scheduled(irn));
139
140         prev_info->next = next;
141         next_info->prev = prev;
142         info->next      = NULL;
143         info->prev      = NULL;
144 }
145
146 void sched_replace(ir_node *const old, ir_node *const irn)
147 {
148         assert(sched_is_scheduled(old));
149         assert(!sched_is_scheduled(irn));
150
151         sched_info_t *const old_info = get_irn_sched_info(old);
152         sched_info_t *const irn_info = get_irn_sched_info(irn);
153         *irn_info = *old_info;
154
155         old_info->prev = NULL;
156         old_info->next = NULL;
157
158         ir_node *const prev = irn_info->prev;
159         ir_node *const next = irn_info->next;
160         get_irn_sched_info(prev)->next = irn;
161         get_irn_sched_info(next)->prev = irn;
162 }
163
164 static be_module_list_entry_t *schedulers;
165 static schedule_func           scheduler;
166
167 void be_register_scheduler(const char *name, schedule_func func)
168 {
169         if (scheduler == NULL)
170                 scheduler = func;
171         be_add_module_to_list(&schedulers, name, (void*)func);
172 }
173
174 void be_schedule_graph(ir_graph *irg)
175 {
176         scheduler(irg);
177 }
178
179 BE_REGISTER_MODULE_CONSTRUCTOR(be_init_sched)
180 void be_init_sched(void)
181 {
182         lc_opt_entry_t *be_grp = lc_opt_get_grp(firm_opt_get_root(), "be");
183         be_add_module_list_opt(be_grp, "scheduler", "scheduling algorithm",
184                                &schedulers, (void**)&scheduler);
185 }