Another version of copy elimination
[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 "firm_config.h"
11
12 #include "irgraph_t.h"
13 #include "iredges_t.h"
14
15 #include "belive.h"
16 #include "pset.h"
17 #include "set.h"
18 #include "list.h"
19 #include "hashptr.h"
20
21 typedef enum _live_state_t {
22     live_state_in = 1,
23     live_state_end = 2,
24     live_state_out = 4,
25     live_state_block = 8,
26 } live_state_t;
27
28 typedef struct _irn_live_t {
29     const ir_node *block;
30     const ir_node *irn;
31     unsigned state;
32     struct _irn_live_t *next;
33 } irn_live_t;
34
35 typedef struct _irg_live_info_t {
36     set *live;
37 } irg_live_info_t;
38
39 extern size_t live_irg_data_offset;
40
41 #define get_irg_live_info(irg) (get_irg_data(irg, irg_live_info_t, live_irg_data_offset))
42
43 #define live_is_in(live) (((live)->state & live_state_in) != 0)
44 #define live_is_end(live) (((live)->state & live_state_end) != 0)
45 #define live_is_out(live) (((live)->state & live_state_out) != 0)
46
47 static INLINE irn_live_t *_get_or_set_live(const ir_node *block, const ir_node *irn, int state)
48 {
49   irg_live_info_t *live_info = get_irg_live_info(get_irn_irg(block));
50   unsigned hash = HASH_PTR(block) + 37 * HASH_PTR(irn);
51   irn_live_t *live, templ;
52
53   templ.block = block;
54   templ.irn = irn;
55   templ.state = -1;
56   templ.next = NULL;
57
58   live = set_insert(live_info->live, &templ, sizeof(templ), hash);
59   if(live->state == -1) {
60
61     if(!is_Block(irn)) {
62       irn_live_t *bl_live = _get_or_set_live(block, block, live_state_block);
63       live->next    = bl_live->next;
64       bl_live->next = live;
65     }
66
67     live->state = state;
68   }
69
70   live->state |= state;
71
72   return live;
73 }
74
75 static INLINE int _is_live_in(const ir_node *block, const ir_node *irn)
76 {
77     return (_get_or_set_live(block, irn, 0)->state & live_state_in) != 0;
78 }
79
80 static INLINE int _is_live_out(const ir_node *block, const ir_node *irn)
81 {
82     return (_get_or_set_live(block, irn, 0)->state & live_state_out) != 0;
83 }
84
85 static INLINE int _is_live_end(const ir_node *block, const ir_node *irn)
86 {
87     return (_get_or_set_live(block, irn, 0)->state & live_state_end) != 0;
88 }
89
90 #define live_foreach(block, live_info) \
91         for(live_info = _get_or_set_live(block, block, 0)->next; live_info; live_info = live_info->next)
92
93 static INLINE void _put_live(const ir_node *block, int state, pset *s)
94 {
95     irn_live_t *live;
96
97     live_foreach(block, live) {
98         if(live->state & state)
99             pset_insert_ptr(s, live->irn);
100     }
101 }
102
103 static INLINE pset *_put_live_in(const ir_node *block, pset *s)
104 {
105     _put_live(block, live_state_in, s);
106     return s;
107 }
108
109 static INLINE pset *_put_live_out(const ir_node *block, pset *s)
110 {
111     _put_live(block, live_state_out, s);
112     return s;
113 }
114
115 static INLINE pset *_put_live_end(const ir_node *block, pset *s)
116 {
117     _put_live(block, live_state_end, s);
118     return s;
119 }
120
121 static INLINE int _is_phi_arg(const ir_node *irn)
122 {
123   const ir_edge_t *edge;
124
125   assert(edges_activated(get_irn_irg(irn)) && "Please compute the out edges");
126   foreach_out_edge(irn, edge)
127     if(is_Phi(edge->src))
128       return 1;
129
130   return 0;
131 }
132
133
134 #define is_live_in(bl,irn)                      _is_live_in(bl, irn)
135 #define is_live_out(bl,irn)             _is_live_out(bl, irn)
136 #define is_live_end(bl,irn)             _is_live_end(bl, irn)
137 #define put_live_in(bl,s)                         _put_live_in(bl, s)
138 #define put_live_out(bl,s)                      _put_live_out(bl, s)
139 #define put_live_end(bl,s)                      _put_live_end(bl, s)
140 #define is_phi_arg(irn)         _is_phi_arg(irn)
141
142 /**
143  * Initialize the liveness module.
144  * To be called from be_init().
145  */
146 void be_liveness_init(void);
147
148 #endif