#ifndef _BELIVE_T_H
#define _BELIVE_T_H
-#include "config.h"
+#include "firm_config.h"
+
+#include "irgraph_t.h"
+#include "iredges_t.h"
#include "belive.h"
#include "pset.h"
+#include "set.h"
+#include "list.h"
+#include "hashptr.h"
-typedef struct _block_live_info_t {
- pset *in; /**< The set of all values live in at that block. */
- pset *out; /**< The set of all values live out. */
- pset *end; /**< The set of all values live at the end
- of the block (contains all live out). */
-} block_live_info_t;
+typedef enum _live_state_t {
+ live_state_in = 1,
+ live_state_end = 2,
+ live_state_out = 4,
+ live_state_block = 8,
+} live_state_t;
-typedef struct _node_live_info_t {
- int is_phi_op; /**< Marks the node as a phi operand. */
-} node_live_info_t;
+typedef struct _irn_live_t {
+ const ir_node *block;
+ const ir_node *irn;
+ unsigned state;
+ struct _irn_live_t *next;
+} irn_live_t;
-typedef struct _live_info_t {
- union {
- block_live_info_t block;
- node_live_info_t node;
- } v;
-} live_info_t;
+typedef struct _irg_live_info_t {
+ set *live;
+} irg_live_info_t;
-extern size_t live_irn_data_offset;
+extern size_t live_irg_data_offset;
-#define get_irn_live_info(irn) get_irn_data(irn, live_info_t, live_irn_data_offset)
-#define get_live_info_irn(inf) get_irn_data_base(inf, live_irn_data_offset)
+#define get_irg_live_info(irg) (get_irg_data(irg, irg_live_info_t, live_irg_data_offset))
-#define get_block_live_info(irn) (&(get_irn_live_info(irn)->v.block))
-#define get_node_live_info(irn) (&(get_irn_live_info(irn)->v.node))
+#define live_is_in(live) (((live)->state & live_state_in) != 0)
+#define live_is_end(live) (((live)->state & live_state_end) != 0)
+#define live_is_out(live) (((live)->state & live_state_out) != 0)
-static INLINE int __is_phi_operand(const ir_node *irn)
+static INLINE irn_live_t *_get_or_set_live(const ir_node *block, const ir_node *irn, int state)
{
- assert(!is_Block(irn) && "No block node allowed here");
- return get_node_live_info(irn)->is_phi_op;
+ irg_live_info_t *live_info = get_irg_live_info(get_irn_irg(block));
+ unsigned hash = HASH_PTR(block) + 37 * HASH_PTR(irn);
+ irn_live_t *live, templ;
+
+ templ.block = block;
+ templ.irn = irn;
+ templ.state = -1;
+ templ.next = NULL;
+
+ live = set_insert(live_info->live, &templ, sizeof(templ), hash);
+ if(live->state == -1) {
+
+ if(!is_Block(irn)) {
+ irn_live_t *bl_live = _get_or_set_live(block, block, live_state_block);
+ live->next = bl_live->next;
+ bl_live->next = live;
+ }
+
+ live->state = state;
+ }
+
+ live->state |= state;
+
+ return live;
}
-static INLINE int __is_live_in(const ir_node *block, const ir_node *irn)
+static INLINE int _is_live_in(const ir_node *block, const ir_node *irn)
{
- block_live_info_t *info = get_block_live_info(block);
-
- assert(is_Block(block) && "Need a block here");
- return pset_find_ptr(info->in, irn) != NULL;
+ return (_get_or_set_live(block, irn, 0)->state & live_state_in) != 0;
}
-static INLINE int __is_live_out(const ir_node *block, const ir_node *irn)
+static INLINE int _is_live_out(const ir_node *block, const ir_node *irn)
{
- block_live_info_t *info = get_block_live_info(block);
+ return (_get_or_set_live(block, irn, 0)->state & live_state_out) != 0;
+}
- assert(is_Block(block) && "Need a block here");
- return pset_find_ptr(info->out, irn) != NULL;
+static INLINE int _is_live_end(const ir_node *block, const ir_node *irn)
+{
+ return (_get_or_set_live(block, irn, 0)->state & live_state_end) != 0;
}
-static INLINE int __is_live_end(const ir_node *block, const ir_node *irn)
+#define live_foreach(block, live_info) \
+ for(live_info = _get_or_set_live(block, block, 0)->next; live_info; live_info = live_info->next)
+
+static INLINE void _put_live(const ir_node *block, int state, pset *s)
{
- block_live_info_t *info = get_block_live_info(block);
+ irn_live_t *live;
+
+ live_foreach(block, live) {
+ if(live->state & state)
+ pset_insert_ptr(s, live->irn);
+ }
+}
- assert(is_Block(block) && "Need a block here");
- return pset_find_ptr(info->end, irn) != NULL;
+static INLINE pset *_put_live_in(const ir_node *block, pset *s)
+{
+ _put_live(block, live_state_in, s);
+ return s;
}
-static INLINE pset *__get_live_in(const ir_node *block)
+static INLINE pset *_put_live_out(const ir_node *block, pset *s)
{
- assert(is_Block(block) && "Need a block here");
- return get_block_live_info(block)->in;
+ _put_live(block, live_state_out, s);
+ return s;
}
-static INLINE pset *__get_live_out(const ir_node *block)
+static INLINE pset *_put_live_end(const ir_node *block, pset *s)
{
- assert(is_Block(block) && "Need a block here");
- return get_block_live_info(block)->out;
+ _put_live(block, live_state_end, s);
+ return s;
}
-static INLINE pset *__get_live_end(const ir_node *block)
+static INLINE int _is_phi_arg(const ir_node *irn)
{
- assert(is_Block(block) && "Need a block here");
- return get_block_live_info(block)->end;
+ const ir_edge_t *edge;
+
+ assert(edges_activated(get_irn_irg(irn)) && "Please compute the out edges");
+ foreach_out_edge(irn, edge)
+ if(is_Phi(edge->src))
+ return 1;
+
+ return 0;
}
-#define is_phi_operand(irn) __is_phi_operand(irn)
-#define is_live_in(bl,irn) __is_live_in(bl, irn)
-#define is_live_out(bl,irn) __is_live_out(bl, irn)
-#define is_live_end(bl,irn) __is_live_end(bl, irn)
-#define get_live_in(bl) __get_live_in(bl)
-#define get_live_out(bl) __get_live_out(bl)
-#define get_live_end(bl) __get_live_end(bl)
+
+#define is_live_in(bl,irn) _is_live_in(bl, irn)
+#define is_live_out(bl,irn) _is_live_out(bl, irn)
+#define is_live_end(bl,irn) _is_live_end(bl, irn)
+#define put_live_in(bl,s) _put_live_in(bl, s)
+#define put_live_out(bl,s) _put_live_out(bl, s)
+#define put_live_end(bl,s) _put_live_end(bl, s)
+#define is_phi_arg(irn) _is_phi_arg(irn)
/**
* Initialize the liveness module.