Commit c228bf8f authored by Michael Beck's avatar Michael Beck
Browse files

- Phi nodes are now collected by collect_phiprojs() and stored into a phi-list attribute of blocks

- collect_phiprojs() collects all partBlocks of an MacroBlock
- partBlock() now handles MacroBlocks better: the lower part of teh splittet block forms a new MacroBlock
- links should now be free even during construction ...

[r17498]
parent 37fa7fe2
......@@ -59,8 +59,8 @@ static unsigned *mere_get_backarray(ir_node *n) {
}
break;
case iro_Phi:
assert(n->attr.phi_backedge && "backedge array not allocated!");
return n->attr.phi_backedge;
assert(n->attr.phi.u.backedge && "backedge array not allocated!");
return n->attr.phi.u.backedge;
break;
case iro_Filter:
if (get_interprocedural_view()) {
......@@ -116,7 +116,7 @@ void fix_backedges(struct obstack *obst, ir_node *n) {
opc = get_irn_opcode(n);
if (opc == iro_Phi)
n->attr.phi_backedge = arr;
n->attr.phi.u.backedge = arr;
else if (opc == iro_Block) {
if (!get_interprocedural_view())
n->attr.block.backedge = arr;
......@@ -222,7 +222,7 @@ void new_backedge_info(ir_node *n) {
n->attr.block.backedge = new_backedge_arr(current_ir_graph->obst, get_irn_arity(n));
break;
case iro_Phi:
n->attr.phi_backedge = new_backedge_arr(current_ir_graph->obst, get_irn_arity(n));
n->attr.phi.u.backedge = new_backedge_arr(current_ir_graph->obst, get_irn_arity(n));
break;
case iro_Filter:
n->attr.filter.backedge = new_backedge_arr(current_ir_graph->obst, get_irn_arity(n));
......
......@@ -250,7 +250,7 @@ new_bd_Phi(dbg_info *db, ir_node *block, int arity, ir_node **in, ir_mode *mode)
res = new_ir_node(db, irg, block, op_Phi, mode, arity, in);
res->attr.phi_backedge = new_backedge_arr(irg->obst, arity);
res->attr.phi.u.backedge = new_backedge_arr(irg->obst, arity);
for (i = arity - 1; i >= 0; --i)
if (get_irn_op(in[i]) == op_Unknown) {
......@@ -1807,7 +1807,7 @@ new_rd_Phi_in(ir_graph *irg, ir_node *block, ir_mode *mode,
/* Allocate a new node on the obstack. The allocation copies the in
array. */
res = new_ir_node (NULL, irg, block, op_Phi, mode, ins, in);
res->attr.phi_backedge = new_backedge_arr(irg->obst, ins);
res->attr.phi.u.backedge = new_backedge_arr(irg->obst, ins);
/* This loop checks whether the Phi has more than one predecessor.
If so, it is a real Phi node and we break the loop. Else the
......@@ -1975,9 +1975,9 @@ get_r_frag_value_internal(ir_node *block, ir_node *cfOp, int pos, ir_mode *mode)
res = phi_merge(block, pos, mode, nin, ins);
} else {
res = new_rd_Phi0(current_ir_graph, block, mode);
res->attr.phi0.pos = pos;
res->link = block->link;
block->link = res;
res->attr.phi.u.pos = pos;
res->attr.phi.next = block->attr.block.phis;
block->attr.block.phis = res;
}
assert(res);
/* @@@ tested by Flo: set_frag_value(frag_arr, pos, res);
......@@ -2215,9 +2215,9 @@ get_r_value_internal(ir_node *block, int pos, ir_mode *mode) {
Phi is computed, pos is used to update the array with the local
values. */
res = new_rd_Phi0(current_ir_graph, block, mode);
res->attr.phi0.pos = pos;
res->link = block->link;
block->link = res;
res->attr.phi.u.pos = pos;
res->attr.phi.next = block->attr.block.phis;
block->attr.block.phis = res;
}
/* If we get here, the frontend missed a use-before-definition error */
......@@ -2258,10 +2258,10 @@ mature_immBlock(ir_node *block) {
/* Traverse a chain of Phi nodes attached to this block and mature
these, too. **/
for (n = block->link; n; n = next) {
for (n = block->attr.block.phis; n; n = next) {
inc_irg_visited(current_ir_graph);
next = n->link;
exchange(n, phi_merge(block, n->attr.phi0.pos, n->mode, nin, ins));
next = n->attr.phi.next;
exchange(n, phi_merge(block, n->attr.phi.u.pos, n->mode, nin, ins));
}
block->attr.block.is_matured = 1;
......
......@@ -121,16 +121,18 @@ void exchange(ir_node *old, ir_node *nw) {
/*--------------------------------------------------------------------*/
/**
* Walker: links all Phi nodes to their Blocks and
* all Proj nodes to there predecessors
* Walker: links all Phi nodes to their Blocks lists,
* all Proj nodes to there predecessors and all
* partBlocks to there MacroBlock header.
*/
static void collect(ir_node *n, void *env) {
ir_node *pred;
(void) env;
if (is_Phi(n)) {
set_irn_link(n, get_irn_link(get_nodes_block(n)));
set_irn_link(get_nodes_block(n), n);
ir_node *block = get_nodes_block(n);
set_Phi_next(n, get_Block_phis(block));
set_Block_phis(block, n);
} else if (is_Proj(n)) {
pred = n;
do {
......@@ -139,11 +141,31 @@ static void collect(ir_node *n, void *env) {
set_irn_link(n, get_irn_link(pred));
set_irn_link(pred, n);
} else if (is_Block(n)) {
ir_node *mbh = get_Block_MacroBlock(n);
if (mbh != n) {
set_irn_link(n, get_irn_link(mbh));
set_irn_link(mbh, n);
}
}
}
/**
* clear all links, including the Phi list of blocks and Phi nodes.
*/
static void clear_links(ir_node *n, void *env) {
(void) env;
set_irn_link(n, NULL);
if (is_Block(n))
set_Block_phis(n, NULL);
else if (is_Phi(n))
set_Phi_next(n, NULL);
}
void collect_phiprojs(ir_graph *irg) {
irg_walk_graph(irg, firm_clear_link, collect, NULL);
irg_walk_graph(irg, clear_links, collect, NULL);
}
......@@ -187,6 +209,7 @@ void part_block(ir_node *node) {
ir_node *new_block;
ir_node *old_block;
ir_node *phi;
ir_node *mbh;
/* Turn off optimizations so that blocks are not merged again. */
int rem_opt = get_opt_optimize();
......@@ -194,8 +217,9 @@ void part_block(ir_node *node) {
/* Transform the control flow */
old_block = get_nodes_block(node);
mbh = get_Block_MacroBlock(old_block);
new_block = new_Block(get_Block_n_cfgpreds(old_block),
get_Block_cfgpred_arr(old_block));
get_Block_cfgpred_arr(old_block));
set_irg_current_block(current_ir_graph, new_block);
{
ir_node *jmp = new_Jmp();
......@@ -215,6 +239,28 @@ void part_block(ir_node *node) {
phi = get_irn_link(phi);
}
/* rewire partBlocks */
if (mbh != old_block) {
ir_node *block;
for (block = get_irn_link(mbh); block != NULL; block = get_irn_link(block)) {
ir_node *curr = block;
for (;;) {
if (curr == old_block) {
/* old_block dominates the block, so old_block will be
the new macro block header */
set_irn_n(block, -1, old_block);
break;
}
if (curr == mbh)
break;
assert(get_Block_n_cfgpreds(curr) == 1);
curr = get_Block_cfgpred_block(curr, 0);
}
}
}
set_optimize(rem_opt);
}
......
......@@ -762,7 +762,7 @@ static void relink_bad_predecessors(ir_node *n, void *env) {
}
ARR_SETLEN(ir_node *, n->in, new_irn_arity);
ARR_SETLEN(int, n->attr.phi_backedge, new_irn_arity);
ARR_SETLEN(int, n->attr.phi.u.backedge, new_irn_arity);
}
} /* n is a Phi node */
}
......
......@@ -595,10 +595,9 @@ get_irn_sel_attr(ir_node *node) {
return &node->attr.sel;
}
int
get_irn_phi0_attr(ir_node *node) {
assert(is_Phi0(node));
return node->attr.phi0.pos;
phi_attr *
get_irn_phi_attr(ir_node *node) {
return &node->attr.phi;
}
block_attr *
......
......@@ -46,14 +46,14 @@ ir_node **get_irn_in (const ir_node *node);
/** @{ */
/** access attributes directly */
const_attr *get_irn_const_attr (ir_node *node);
long get_irn_proj_attr (ir_node *node);
long get_irn_proj_attr (ir_node *node);
alloc_attr *get_irn_alloc_attr (ir_node *node);
free_attr *get_irn_free_attr (ir_node *node);
symconst_attr *get_irn_symconst_attr (ir_node *node);
ir_type *get_irn_call_attr (ir_node *node);
ir_type *get_irn_funccall_attr (ir_node *node);
sel_attr *get_irn_sel_attr (ir_node *node);
int get_irn_phi0_attr (ir_node *node);
phi_attr *get_irn_phi_attr (ir_node *node);
block_attr *get_irn_block_attr (ir_node *node);
load_attr *get_irn_load_attr (ir_node *node);
store_attr *get_irn_store_attr (ir_node *node);
......@@ -357,11 +357,7 @@ _irn_not_visited(const ir_node *node) {
*/
static INLINE void
_set_irn_link(ir_node *node, void *link) {
assert(node);
/* Link field is used for Phi construction and various optimizations
in iropt. */
assert(get_irg_phase_state(get_irn_irg(node)) != phase_building);
assert(node);
node->link = link;
}
......@@ -910,6 +906,45 @@ static INLINE void _set_irn_dbg_info(ir_node *n, dbg_info *db) {
n->dbi = db;
}
/**
* Sets the Phi list of a block.
*/
static INLINE void
_set_Block_phis(ir_node *block, ir_node *phi) {
assert(_is_Block(block));
assert(phi == NULL || _is_Phi(phi));
block->attr.block.phis = phi;
}
/**
* Returns the link of a node.
* Intern version of libFirm.
*/
static INLINE ir_node *
_get_Block_phis(const ir_node *block) {
assert(_is_Block(block));
return block->attr.block.phis;
}
/**
* Sets the next link of a Phi.
*/
static INLINE void
_set_Phi_next(ir_node *phi, ir_node *next) {
assert(_is_Phi(phi));
phi->attr.phi.next = next;
}
/**
* Returns the link of a node.
* Intern version of libFirm.
*/
static INLINE ir_node *
_get_Phi_next(const ir_node *phi) {
assert(_is_Phi(phi));
return phi->attr.phi.next;
}
/* this section MUST contain all inline functions */
#define is_ir_node(thing) _is_ir_node(thing)
#define get_irn_intra_arity(node) _get_irn_intra_arity(node)
......@@ -1027,4 +1062,9 @@ static INLINE void _set_irn_dbg_info(ir_node *n, dbg_info *db) {
#define get_irn_dbg_info(node) _get_irn_dbg_info(node)
#define set_irn_dbg_info(node, db) _set_irn_dbg_info(node, db)
#define set_Block_phis(node, phi) _set_Block_phis(node, phi)
#define get_Block_phis(node) _get_Block_phis(node)
#define set_Phi_next(node, phi) _set_Phi_next(node, phi)
#define get_Phi_next(node) _get_Phi_next(node)
#endif
......@@ -152,6 +152,7 @@ block_copy_attr(const ir_node *old_node, ir_node *new_node) {
ir_graph *irg = current_ir_graph;
default_copy_attr(old_node, new_node);
new_node->attr.block.phis = NULL;
new_node->attr.block.cg_backedge = NULL;
new_node->attr.block.backedge = new_backedge_arr(irg->obst, get_irn_arity(new_node));
INIT_LIST_HEAD(&new_node->attr.block.succ_head);
......@@ -165,7 +166,8 @@ phi_copy_attr(const ir_node *old_node, ir_node *new_node) {
ir_graph *irg = current_ir_graph;
default_copy_attr(old_node, new_node);
new_node->attr.phi_backedge = new_backedge_arr(irg->obst, get_irn_arity(new_node));
new_node->attr.phi.next = NULL;
new_node->attr.phi.u.backedge = new_backedge_arr(irg->obst, get_irn_arity(new_node));
}
/**
......@@ -325,7 +327,7 @@ init_op(void)
op_Carry = new_ir_op(iro_Carry, "Carry", op_pin_state_floats, C, oparity_binary, 0, 0, NULL);
op_Borrow = new_ir_op(iro_Borrow, "Borrow", op_pin_state_floats, N, oparity_binary, 0, 0, NULL);
op_Phi = new_ir_op(iro_Phi, "Phi", op_pin_state_pinned, N, oparity_variable, -1, sizeof(phi0_attr), NULL);
op_Phi = new_ir_op(iro_Phi, "Phi", op_pin_state_pinned, N, oparity_variable, -1, sizeof(phi_attr), NULL);
op_Load = new_ir_op(iro_Load, "Load", op_pin_state_exc_pinned, F|M, oparity_any, -1, sizeof(load_attr), NULL);
op_Store = new_ir_op(iro_Store, "Store", op_pin_state_exc_pinned, F|M, oparity_any, -1, sizeof(store_attr), NULL);
......
......@@ -5015,8 +5015,8 @@ static int node_cmp_attr_Phi(ir_node *a, ir_node *b) {
/* we can only enter this function if both nodes have the same number of inputs,
hence it is enough to check if one of them is a Phi0 */
if (is_Phi0(a)) {
/* check the Phi0 attribute */
return get_irn_phi0_attr(a) != get_irn_phi0_attr(b);
/* check the Phi0 pos attribute */
return get_irn_phi_attr(a)->u.pos != get_irn_phi_attr(b)->u.pos;
}
return 0;
} /* node_cmp_attr_Phi */
......
......@@ -143,6 +143,7 @@ typedef struct {
ir_region *region; /**< The immediate structural region this block belongs to. */
unsigned mb_depth; /**< The macroblock depth: A distance from the macroblock header */
ir_label_t label; /**< The block label if assigned. */
ir_node *phis; /**< The list of Phi nodes in this block. */
struct list_head succ_head; /**< A list head for all successor edges of a block. */
} block_attr;
......@@ -241,13 +242,18 @@ typedef struct {
} store_attr;
typedef struct {
int pos; /**< For Phi0. Used to remember the value defined by
this Phi node. Needed when the Phi is completed
to call get_r_internal_value to find the
predecessors. If this attribute is set, the Phi
node takes the role of the obsolete Phi0 node,
therefore the name. */
} phi0_attr;
ir_node *next; /**< Points to the next Phi in the Phi list of a block. */
union {
unsigned *backedge; /**< Raw Bitfield: bit n is set to true if pred n is backedge. */
int pos; /**< For Phi0. Used to remember the value defined by
this Phi node. Needed when the Phi is completed
to call get_r_internal_value() to find the
predecessors. If this attribute is set, the Phi
node takes the role of the obsolete Phi0 node,
therefore the name. */
} u;
} phi_attr;
/**< Confirm attribute. */
typedef struct {
......@@ -301,9 +307,7 @@ typedef union {
cast_attr cast; /**< For Cast. */
load_attr load; /**< For Load. */
store_attr store; /**< For Store. */
phi0_attr phi0; /**< for Phi0 nodes. */
unsigned *phi_backedge; /**< For Phi after construction.
Raw Bitfield n set to true if pred n is backedge. */
phi_attr phi; /**< For Phi. */
long proj; /**< For Proj: contains the result position to project */
confirm_attr confirm; /**< For Confirm: compare operation and region. */
filter_attr filter; /**< For Filter */
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment