-/* There are two implementations of the Phi node construction. The first
- is faster, but does not work for blocks with more than 2 predecessors.
- The second works always but is slower and causes more unnecessary Phi
- nodes.
- Select the implementations by the following preprocessor flag set in
- common/common.h: */
-#if USE_FAST_PHI_CONSTRUCTION
-
-/* This is a stack used for allocating and deallocating nodes in
- new_rd_Phi_in. The original implementation used the obstack
- to model this stack, now it is explicit. This reduces side effects.
-*/
-#if USE_EXPLICIT_PHI_IN_STACK
-Phi_in_stack *
-new_Phi_in_stack(void) {
- Phi_in_stack *res;
-
- res = (Phi_in_stack *) malloc ( sizeof (Phi_in_stack));
-
- res->stack = NEW_ARR_F (ir_node *, 0);
- res->pos = 0;
-
- return res;
-} /* new_Phi_in_stack */
-
-void
-free_Phi_in_stack(Phi_in_stack *s) {
- DEL_ARR_F(s->stack);
- free(s);
-} /* free_Phi_in_stack */
-
-static INLINE void
-free_to_Phi_in_stack(ir_node *phi) {
- if (ARR_LEN(current_ir_graph->Phi_in_stack->stack) ==
- current_ir_graph->Phi_in_stack->pos)
- ARR_APP1 (ir_node *, current_ir_graph->Phi_in_stack->stack, phi);
- else
- current_ir_graph->Phi_in_stack->stack[current_ir_graph->Phi_in_stack->pos] = phi;
-
- (current_ir_graph->Phi_in_stack->pos)++;
-} /* free_to_Phi_in_stack */
-
-static INLINE ir_node *
-alloc_or_pop_from_Phi_in_stack(ir_graph *irg, ir_node *block, ir_mode *mode,
- int arity, ir_node **in) {
- ir_node *res;
- ir_node **stack = current_ir_graph->Phi_in_stack->stack;
- int pos = current_ir_graph->Phi_in_stack->pos;
-
-
- if (pos == 0) {
- /* We need to allocate a new node */
- res = new_ir_node (db, irg, block, op_Phi, mode, arity, in);
- res->attr.phi_backedge = new_backedge_arr(irg->obst, arity);
- } else {
- /* reuse the old node and initialize it again. */
- res = stack[pos-1];
-
- assert(res->kind == k_ir_node);
- assert(res->op == op_Phi);
- res->mode = mode;
- res->visited = 0;
- res->link = NULL;
- assert(arity >= 0);
- /* ???!!! How to free the old in array?? Not at all: on obstack ?!! */
- res->in = NEW_ARR_D(ir_node *, irg->obst, (arity+1));
- res->in[0] = block;
- memcpy (&res->in[1], in, sizeof (ir_node *) * arity);
-
- (current_ir_graph->Phi_in_stack->pos)--;
- }
- return res;
-} /* alloc_or_pop_from_Phi_in_stack */
-#endif /* USE_EXPLICIT_PHI_IN_STACK */
-
-/**
- * Creates a Phi node with a given, fixed array **in of predecessors.
- * If the Phi node is unnecessary, as the same value reaches the block
- * through all control flow paths, it is eliminated and the value
- * returned directly. This constructor is only intended for use in
- * the automatic Phi node generation triggered by get_value or mature.
- * The implementation is quite tricky and depends on the fact, that
- * the nodes are allocated on a stack:
- * The in array contains predecessors and NULLs. The NULLs appear,
- * if get_r_value_internal, that computed the predecessors, reached
- * the same block on two paths. In this case the same value reaches
- * this block on both paths, there is no definition in between. We need
- * not allocate a Phi where these path's merge, but we have to communicate
- * this fact to the caller. This happens by returning a pointer to the
- * node the caller _will_ allocate. (Yes, we predict the address. We can
- * do so because the nodes are allocated on the obstack.) The caller then
- * finds a pointer to itself and, when this routine is called again,
- * eliminates itself.
- */
-static INLINE ir_node *
-new_rd_Phi_in(ir_graph *irg, ir_node *block, ir_mode *mode, ir_node **in, int ins) {
- int i;
- ir_node *res, *known;
-
- /* Allocate a new node on the obstack. This can return a node to
- which some of the pointers in the in-array already point.
- Attention: the constructor copies the in array, i.e., the later
- changes to the array in this routine do not affect the
- constructed node! If the in array contains NULLs, there will be
- missing predecessors in the returned node. Is this a possible
- internal state of the Phi node generation? */
-#if USE_EXPLICIT_PHI_IN_STACK
- res = known = alloc_or_pop_from_Phi_in_stack(irg, block, mode, ins, in);
-#else
- res = known = new_ir_node (NULL, irg, block, op_Phi, mode, ins, in);
- res->attr.phi_backedge = new_backedge_arr(irg->obst, ins);
-#endif
-
- /* The in-array can contain NULLs. These were returned by
- get_r_value_internal if it reached the same block/definition on a
- second path. The NULLs are replaced by the node itself to
- simplify the test in the next loop. */
- for (i = 0; i < ins; ++i) {
- if (in[i] == NULL)
- in[i] = res;
- }
-
- /* 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 Phi
- node merges the same definition on several paths and therefore is
- not needed. */
- for (i = 0; i < ins; ++i) {
- if (in[i] == res || in[i] == known)
- continue;
-
- if (known == res)
- known = in[i];
- else
- break;
- }
-
- /* i==ins: there is at most one predecessor, we don't need a phi node. */
- if (i==ins) {
-#if USE_EXPLICIT_PHI_IN_STACK
- free_to_Phi_in_stack(res);
-#else
- edges_node_deleted(res, current_ir_graph);
- obstack_free(current_ir_graph->obst, res);
-#endif
- res = known;
- } else {
- res = optimize_node (res);
- IRN_VRFY_IRG(res, irg);
- }
-
- /* return the pointer to the Phi node. This node might be deallocated! */
- return res;
-} /* new_rd_Phi_in */
-
-static ir_node *
-get_r_value_internal(ir_node *block, int pos, ir_mode *mode);