Changed semantics of sched_prev and sched_next.
[libfirm] / ir / be / besched_t.h
1
2 #ifndef _BESCHED_T_H
3 #define _BESCHED_T_H
4
5 #define SCHED_INITIAL_GRANULARITY (1 << 14)
6
7 #include "list.h"
8 #include "irnode_t.h"
9 #include "irgraph_t.h"
10
11 #include "besched.h"
12
13 typedef unsigned int sched_timestep_t;
14
15 extern size_t sched_irn_data_offset;
16
17 /**
18  * The schedule structure which is present at each ir node.
19  */
20 typedef struct _sched_info_t {
21         struct list_head list;         /**< The list head to list the nodes in a schedule. */
22         sched_timestep_t time_step;    /**< If a is after b in a schedule, its time step is
23                                         larger than b's. */
24
25     int scheduled : 1;             /**< 1, if the node is in the schedule of the block, 0 else. */
26 } sched_info_t;
27
28 #define _sched_entry(list_head) (list_entry(list_head, sched_info_t, list))
29
30 #define get_irn_sched_info(irn) get_irn_data(irn, sched_info_t, sched_irn_data_offset)
31 #define get_sched_info_irn(sched_info) get_irn_data_base(sched_info, sched_irn_data_offset)
32
33 /**
34  * Init the scheduling stuff.
35  * To be called from the central backend initialization routine.
36  */
37 void be_sched_init(void);
38
39 /**
40  * Get the time step of an irn in a schedule.
41  * @param irn The node.
42  * @return The time step in the schedule.
43  */
44 static INLINE int _sched_get_time_step(const ir_node *irn)
45 {
46         return get_irn_sched_info(irn)->time_step;
47 }
48
49 /**
50  * Check, if an ir_node has a scheduling successor.
51  * @param irn The ir node.
52  * @return 1, if the node has a scheduling successor, 0 if not.
53  */
54 static INLINE int _sched_has_next(const ir_node *irn)
55 {
56     const ir_node *block = is_Block(irn) ? irn : get_nodes_block(irn);
57         const sched_info_t *info = get_irn_sched_info(irn);
58         const sched_info_t *block_info = get_irn_sched_info(block);
59         return info->list.next != &block_info->list;
60 }
61
62 /**
63  * Check, if an ir_node has a scheduling predecessor.
64  * @param irn The ir node.
65  * @return 1, if the node has a scheduling predecessor, 0 if not.
66  */
67 static INLINE int _sched_has_prev(const ir_node *irn)
68 {
69     const ir_node *block = is_Block(irn) ? irn : get_nodes_block(irn);
70         const sched_info_t *info = get_irn_sched_info(irn);
71         const sched_info_t *block_info = get_irn_sched_info(block);
72         return info->list.prev != &block_info->list;
73 }
74
75 /**
76  * Get the scheduling successor of a node.
77  * @param irn The node.
78  * @return The next ir node in the schedule or the block, if the node has no next node.
79  */
80 static INLINE ir_node *_sched_next(const ir_node *irn)
81 {
82         const sched_info_t *info = get_irn_sched_info(irn);
83         return get_sched_info_irn(_sched_entry(info->list.next));
84 }
85
86 /**
87  * Get the scheduling predecessor of a node.
88  * @param irn The node.
89  * @return The next ir node in the schedule or the block, if the node has no predecessor.
90  * predecessor.
91  */
92 static INLINE ir_node *_sched_prev(const ir_node *irn)
93 {
94         const sched_info_t *info = get_irn_sched_info(irn);
95         return get_sched_info_irn(_sched_entry(info->list.prev));
96 }
97
98 /**
99  * Get the first node in a block schedule.
100  * @param block The block of which to get the schedule.
101  * @return The first node in the schedule or the block itself if there is node in the schedule.
102  */
103 static INLINE ir_node *_sched_first(const ir_node *block)
104 {
105         assert(is_Block(block) && "Need a block here");
106         return _sched_next(block);
107 }
108
109 /**
110  * Get the last node in a schedule.
111  * @param block The block to get the schedule for.
112  * @return The last ir node in a schedule, or the block itself, if there is node in the schedule.
113  * or it is empty.
114  */
115 static INLINE ir_node *_sched_last(const ir_node *block)
116 {
117         assert(is_Block(block) && "Need a block here");
118         return _sched_prev(block);
119 }
120
121 /**
122  * Reassign the time steps in the schedule.
123  * @param block The schedule to update.
124  */
125 void sched_renumber(const ir_node *block);
126
127 static INLINE void _sched_set_time_stamp(ir_node *irn)
128 {
129   sched_info_t *inf = get_irn_sched_info(irn);
130   sched_timestep_t before_ts = _sched_entry(inf->list.prev)->time_step;
131   sched_timestep_t after_ts = _sched_entry(inf->list.next)->time_step;
132
133   /*
134    * If we are the last, we can give us a big time step,
135    * else we have to compute our time step from our
136    * neighbours.
137    */
138   if(after_ts == 0)
139     inf->time_step = before_ts + SCHED_INITIAL_GRANULARITY;
140   else {
141     sched_timestep_t ts = (before_ts + after_ts) / 2;
142
143     /*
144      * If the resolution went out, we have to renumber
145      * this block.
146      */
147     if(ts == before_ts || ts == after_ts)
148       sched_renumber(get_nodes_block(irn));
149   }
150 }
151
152 /**
153  * Add a node to a block schedule.
154  * @param block The block to whose schedule the node shall be added to.
155  * @param irn The node to add.
156  * @return The given node.
157  */
158 static INLINE ir_node *_sched_add_before(ir_node *before, ir_node *irn)
159 {
160         list_add_tail(&get_irn_sched_info(irn)->list, &get_irn_sched_info(before)->list);
161   _sched_set_time_stamp(irn);
162         return irn;
163 }
164
165 /**
166  * Add a node to a block schedule.
167  * @param block The block to whose schedule the node shall be added to.
168  * @param irn The node to add.
169  * @return The given node.
170  */
171 static INLINE ir_node *_sched_add_after(ir_node *after, ir_node *irn)
172 {
173         list_add(&get_irn_sched_info(irn)->list, &get_irn_sched_info(after)->list);
174   _sched_set_time_stamp(irn);
175         return irn;
176 }
177
178 /**
179  * Check, if thenode is scheduled.
180  * @param irn The node.
181  * @return 1, if the node is scheduled, 0 if not.
182  */
183 static INLINE int _sched_is_scheduled(ir_node *irn)
184 {
185     return get_irn_sched_info(irn)->scheduled;
186 }
187
188 /**
189  * Verify a schedule.
190  * @param block The block whose schedule to verify.
191  * @return      1, if the schedule is proper, 0 if not.
192  */
193 extern int sched_verify(const ir_node *block);
194
195 /**
196  * Verify the schedules in all blocks of the irg.
197  * @param irg The program graph.
198  * @return    1, if all schedules were right, 0 if not.
199  */
200 extern int sched_verify_irg(ir_graph *irg);
201
202
203 #define sched_get_time_step(irn)            _sched_get_time_step(irn)
204 #define sched_has_succ(irn)                               _sched_has_succ(irn)
205 #define sched_has_prev(irn)                               _sched_has_prev(irn)
206 #define sched_succ(irn)                                                   _sched_succ(irn)
207 #define sched_prev(irn)                                                   _sched_prev(irn)
208 #define sched_first(irn)                                                  _sched_first(irn)
209 #define sched_last(irn)                                                   _sched_last(irn)
210 #define sched_add_before(before, irn)   _sched_add_before(before, irn)
211 #define sched_add_after(after, irn)     _sched_add_after(after, irn)
212 #define sched_is_scheduled(irn)         _sched_is_scheduled(irn)
213
214 #endif