Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5564 serge 1
/*
2
 * Copyright © 2012 Intel Corporation
3
 *
4
 * Permission is hereby granted, free of charge, to any person obtaining a
5
 * copy of this software and associated documentation files (the "Software"),
6
 * to deal in the Software without restriction, including without limitation
7
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8
 * and/or sell copies of the Software, and to permit persons to whom the
9
 * Software is furnished to do so, subject to the following conditions:
10
 *
11
 * The above copyright notice and this permission notice (including the next
12
 * paragraph) shall be included in all copies or substantial portions of the
13
 * Software.
14
 *
15
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21
 * IN THE SOFTWARE.
22
 *
23
 * Authors:
24
 *    Eric Anholt 
25
 *
26
 */
27
 
28
#pragma once
29
#ifndef BRW_CFG_H
30
#define BRW_CFG_H
31
 
32
#include "brw_shader.h"
33
 
34
struct bblock_t;
35
 
36
struct bblock_link {
37
#ifdef __cplusplus
38
   DECLARE_RALLOC_CXX_OPERATORS(bblock_link)
39
 
40
   bblock_link(bblock_t *block)
41
      : block(block)
42
   {
43
   }
44
#endif
45
 
46
   struct exec_node link;
47
   struct bblock_t *block;
48
};
49
 
50
struct backend_instruction;
51
 
52
struct bblock_t {
53
#ifdef __cplusplus
54
   DECLARE_RALLOC_CXX_OPERATORS(bblock_t)
55
 
56
   explicit bblock_t(cfg_t *cfg);
57
 
58
   void add_successor(void *mem_ctx, bblock_t *successor);
59
   bool is_predecessor_of(const bblock_t *block) const;
60
   bool is_successor_of(const bblock_t *block) const;
61
   bool can_combine_with(const bblock_t *that) const;
62
   void combine_with(bblock_t *that);
63
   void dump(backend_visitor *v) const;
64
 
65
   backend_instruction *start();
66
   const backend_instruction *start() const;
67
   backend_instruction *end();
68
   const backend_instruction *end() const;
69
 
70
   bblock_t *next();
71
   const bblock_t *next() const;
72
   bblock_t *prev();
73
   const bblock_t *prev() const;
74
 
75
   bool starts_with_control_flow() const;
76
   bool ends_with_control_flow() const;
77
 
78
   backend_instruction *first_non_control_flow_inst();
79
   backend_instruction *last_non_control_flow_inst();
80
#endif
81
 
82
   struct exec_node link;
83
   struct cfg_t *cfg;
84
   struct bblock_t *idom;
85
 
86
   int start_ip;
87
   int end_ip;
88
 
89
   struct exec_list instructions;
90
   struct exec_list parents;
91
   struct exec_list children;
92
   int num;
93
};
94
 
95
static inline struct backend_instruction *
96
bblock_start(struct bblock_t *block)
97
{
98
   return (struct backend_instruction *)exec_list_get_head(&block->instructions);
99
}
100
 
101
static inline const struct backend_instruction *
102
bblock_start_const(const struct bblock_t *block)
103
{
104
   return (const struct backend_instruction *)exec_list_get_head_const(&block->instructions);
105
}
106
 
107
static inline struct backend_instruction *
108
bblock_end(struct bblock_t *block)
109
{
110
   return (struct backend_instruction *)exec_list_get_tail(&block->instructions);
111
}
112
 
113
static inline const struct backend_instruction *
114
bblock_end_const(const struct bblock_t *block)
115
{
116
   return (const struct backend_instruction *)exec_list_get_tail_const(&block->instructions);
117
}
118
 
119
static inline struct bblock_t *
120
bblock_next(struct bblock_t *block)
121
{
122
   return (struct bblock_t *)block->link.next;
123
}
124
 
125
static inline const struct bblock_t *
126
bblock_next_const(const struct bblock_t *block)
127
{
128
   return (const struct bblock_t *)block->link.next;
129
}
130
 
131
static inline struct bblock_t *
132
bblock_prev(struct bblock_t *block)
133
{
134
   return (struct bblock_t *)block->link.prev;
135
}
136
 
137
static inline const struct bblock_t *
138
bblock_prev_const(const struct bblock_t *block)
139
{
140
   return (const struct bblock_t *)block->link.prev;
141
}
142
 
143
static inline bool
144
bblock_starts_with_control_flow(const struct bblock_t *block)
145
{
146
   enum opcode op = bblock_start_const(block)->opcode;
147
   return op == BRW_OPCODE_DO || op == BRW_OPCODE_ENDIF;
148
}
149
 
150
static inline bool
151
bblock_ends_with_control_flow(const struct bblock_t *block)
152
{
153
   enum opcode op = bblock_end_const(block)->opcode;
154
   return op == BRW_OPCODE_IF ||
155
          op == BRW_OPCODE_ELSE ||
156
          op == BRW_OPCODE_WHILE ||
157
          op == BRW_OPCODE_BREAK ||
158
          op == BRW_OPCODE_CONTINUE;
159
}
160
 
161
static inline struct backend_instruction *
162
bblock_first_non_control_flow_inst(struct bblock_t *block)
163
{
164
   struct backend_instruction *inst = bblock_start(block);
165
   if (bblock_starts_with_control_flow(block))
166
#ifdef __cplusplus
167
      inst = (struct backend_instruction *)inst->next;
168
#else
169
      inst = (struct backend_instruction *)inst->link.next;
170
#endif
171
   return inst;
172
}
173
 
174
static inline struct backend_instruction *
175
bblock_last_non_control_flow_inst(struct bblock_t *block)
176
{
177
   struct backend_instruction *inst = bblock_end(block);
178
   if (bblock_ends_with_control_flow(block))
179
#ifdef __cplusplus
180
      inst = (struct backend_instruction *)inst->prev;
181
#else
182
      inst = (struct backend_instruction *)inst->link.prev;
183
#endif
184
   return inst;
185
}
186
 
187
#ifdef __cplusplus
188
inline backend_instruction *
189
bblock_t::start()
190
{
191
   return bblock_start(this);
192
}
193
 
194
inline const backend_instruction *
195
bblock_t::start() const
196
{
197
   return bblock_start_const(this);
198
}
199
 
200
inline backend_instruction *
201
bblock_t::end()
202
{
203
   return bblock_end(this);
204
}
205
 
206
inline const backend_instruction *
207
bblock_t::end() const
208
{
209
   return bblock_end_const(this);
210
}
211
 
212
inline bblock_t *
213
bblock_t::next()
214
{
215
   return bblock_next(this);
216
}
217
 
218
inline const bblock_t *
219
bblock_t::next() const
220
{
221
   return bblock_next_const(this);
222
}
223
 
224
inline bblock_t *
225
bblock_t::prev()
226
{
227
   return bblock_prev(this);
228
}
229
 
230
inline const bblock_t *
231
bblock_t::prev() const
232
{
233
   return bblock_prev_const(this);
234
}
235
 
236
inline bool
237
bblock_t::starts_with_control_flow() const
238
{
239
   return bblock_starts_with_control_flow(this);
240
}
241
 
242
inline bool
243
bblock_t::ends_with_control_flow() const
244
{
245
   return bblock_ends_with_control_flow(this);
246
}
247
 
248
inline backend_instruction *
249
bblock_t::first_non_control_flow_inst()
250
{
251
   return bblock_first_non_control_flow_inst(this);
252
}
253
 
254
inline backend_instruction *
255
bblock_t::last_non_control_flow_inst()
256
{
257
   return bblock_last_non_control_flow_inst(this);
258
}
259
#endif
260
 
261
struct cfg_t {
262
#ifdef __cplusplus
263
   DECLARE_RALLOC_CXX_OPERATORS(cfg_t)
264
 
265
   cfg_t(exec_list *instructions);
266
   ~cfg_t();
267
 
268
   void remove_block(bblock_t *block);
269
 
270
   bblock_t *new_block();
271
   void set_next_block(bblock_t **cur, bblock_t *block, int ip);
272
   void make_block_array();
273
   void calculate_idom();
274
   static bblock_t *intersect(bblock_t *b1, bblock_t *b2);
275
 
276
   void dump(backend_visitor *v);
277
   void dump_cfg();
278
   void dump_domtree();
279
#endif
280
   void *mem_ctx;
281
 
282
   /** Ordered list (by ip) of basic blocks */
283
   struct exec_list block_list;
284
   struct bblock_t **blocks;
285
   int num_blocks;
286
 
287
   bool idom_dirty;
288
};
289
 
290
/* Note that this is implemented with a double for loop -- break will
291
 * break from the inner loop only!
292
 */
293
#define foreach_block_and_inst(__block, __type, __inst, __cfg) \
294
   foreach_block (__block, __cfg)                              \
295
      foreach_inst_in_block (__type, __inst, __block)
296
 
297
/* Note that this is implemented with a double for loop -- break will
298
 * break from the inner loop only!
299
 */
300
#define foreach_block_and_inst_safe(__block, __type, __inst, __cfg) \
301
   foreach_block_safe (__block, __cfg)                              \
302
      foreach_inst_in_block_safe (__type, __inst, __block)
303
 
304
#define foreach_block(__block, __cfg)                          \
305
   foreach_list_typed (bblock_t, __block, link, &(__cfg)->block_list)
306
 
307
#define foreach_block_reverse(__block, __cfg)                  \
308
   foreach_list_typed_reverse (bblock_t, __block, link, &(__cfg)->block_list)
309
 
310
#define foreach_block_safe(__block, __cfg)                     \
311
   foreach_list_typed_safe (bblock_t, __block, link, &(__cfg)->block_list)
312
 
313
#define foreach_inst_in_block(__type, __inst, __block)         \
314
   foreach_in_list(__type, __inst, &(__block)->instructions)
315
 
316
#define foreach_inst_in_block_safe(__type, __inst, __block)    \
317
   for (__type *__inst = (__type *)__block->instructions.head, \
318
               *__next = (__type *)__inst->next,               \
319
               *__end = (__type *)__block->instructions.tail;  \
320
        __next != __end;                                       \
321
        __inst = __next,                                       \
322
        __next = (__type *)__next->next)
323
 
324
#define foreach_inst_in_block_reverse(__type, __inst, __block) \
325
   foreach_in_list_reverse(__type, __inst, &(__block)->instructions)
326
 
327
#define foreach_inst_in_block_reverse_safe(__type, __inst, __block) \
328
   foreach_in_list_reverse_safe(__type, __inst, &(__block)->instructions)
329
 
330
#define foreach_inst_in_block_starting_from(__type, __scan_inst, __inst, __block) \
331
   for (__type *__scan_inst = (__type *)__inst->next;          \
332
        !__scan_inst->is_tail_sentinel();                      \
333
        __scan_inst = (__type *)__scan_inst->next)
334
 
335
#define foreach_inst_in_block_reverse_starting_from(__type, __scan_inst, __inst, __block) \
336
   for (__type *__scan_inst = (__type *)__inst->prev;          \
337
        !__scan_inst->is_head_sentinel();                      \
338
        __scan_inst = (__type *)__scan_inst->prev)
339
 
340
#endif /* BRW_CFG_H */