Recent version :-)
[libfirm] / ir / be / belive_t.h
1 /**
2  * Internal headers for liveness analysis.
3  * @author Sebastian Hack
4  * @date 6.12.2004
5  */
6
7 #ifndef _BELIVE_T_H
8 #define _BELIVE_T_H
9
10 #include "config.h"
11
12 #include "irgraph_t.h"
13
14 #include "belive.h"
15 #include "pset.h"
16 #include "set.h"
17 #include "list.h"
18 #include "hashptr.h"
19
20 typedef enum _live_state_t {
21     live_state_in = 1,
22     live_state_end = 2,
23     live_state_out = 6,
24     live_state_block = 8,
25 } live_state_t;
26
27 typedef struct _irn_live_t {
28     const ir_node *block;
29     const ir_node *irn;
30     unsigned state;
31     struct _irn_live_t *next;
32 } irn_live_t;
33
34 typedef struct _irg_live_info_t {
35     set *live;
36 } irg_live_info_t;
37
38 extern size_t live_irg_data_offset;
39
40 #define get_irg_live_info(irg) (get_irg_data(irg, irg_live_info_t, live_irg_data_offset))
41
42 #define HASH_PTR_PAIR(x,y) (HASH_PTR(x) + 37 * HASH_PTR(y))
43
44 static INLINE irn_live_t *_get_or_set_live(const ir_node *block, const ir_node *irn, int state)
45 {
46   irg_live_info_t *live_info = get_irg_live_info(get_irn_irg(block));
47   irn_live_t *live, templ;
48
49   templ.block = block;
50   templ.irn = irn;
51   templ.state = -1;
52   templ.next = NULL;
53
54   live = set_insert(live_info->live, &templ, sizeof(templ), HASH_PTR_PAIR(block, irn));
55   if(live->state == -1) {
56
57     if(!is_Block(irn)) {
58       irn_live_t *bl_live = _get_or_set_live(block, block, live_state_block);
59       live->next = bl_live->next;
60       bl_live->next = live;
61     }
62
63     live->state = state;
64   }
65
66   live->state |= state;
67
68   return live;
69 }
70
71 static INLINE int _is_live_in(const ir_node *block, const ir_node *irn)
72 {
73     return (_get_or_set_live(block, irn, 0)->state & live_state_in) != 0;
74 }
75
76 static INLINE int _is_live_out(const ir_node *block, const ir_node *irn)
77 {
78     return (_get_or_set_live(block, irn, 0)->state & live_state_out) != 0;
79 }
80
81 static INLINE int _is_live_end(const ir_node *block, const ir_node *irn)
82 {
83     return (_get_or_set_live(block, irn, 0)->state & live_state_end) != 0;
84 }
85
86 #define live_foreach(block, live_info) \
87         for(live_info = _get_or_set_live(block, block, 0)->next; live_info; live_info = live_info->next)
88
89 static INLINE void _put_live(const ir_node *block, int state, pset *s)
90 {
91     irn_live_t *live;
92
93     live_foreach(block, live) {
94         if(live->state & state)
95             pset_insert_ptr(s, live->irn);
96     }
97 }
98
99 static INLINE pset *_put_live_in(const ir_node *block, pset *s)
100 {
101     _put_live(block, live_state_in, s);
102     return s;
103 }
104
105 static INLINE pset *_put_live_out(const ir_node *block, pset *s)
106 {
107     _put_live(block, live_state_out, s);
108     return s;
109 }
110
111 static INLINE pset *_put_live_end(const ir_node *block, pset *s)
112 {
113     _put_live(block, live_state_end, s);
114     return s;
115 }
116
117
118 #define is_live_in(bl,irn)                      _is_live_in(bl, irn)
119 #define is_live_out(bl,irn)             _is_live_out(bl, irn)
120 #define is_live_end(bl,irn)             _is_live_end(bl, irn)
121 #define put_live_in(bl,s)                       _put_live_in(bl, s)
122 #define put_live_out(bl,s)                      _put_live_out(bl, s)
123 #define put_live_end(bl,s)                      _put_live_end(bl, s)
124
125 /**
126  * Initialize the liveness module.
127  * To be called from be_init().
128  */
129 void be_liveness_init(void);
130
131 #endif