-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;
-}
-#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(ir_graph *irg, ir_node *block, ir_mode *mode,
+ ir_node **in, int ins, ir_node *phi0) {
+ int i;
+ ir_node *res, *known;
+
+ /* 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);
+
+ /* 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. Don't consider Bad nodes! */
+ known = res;
+ for (i=0; i < ins; ++i)
+ {
+ assert(in[i]);
+
+ in[i] = skip_Id(in[i]); /* increases the number of freed Phis. */
+
+ /* Optimize self referencing Phis: We can't detect them yet properly, as
+ they still refer to the Phi0 they will replace. So replace right now. */
+ if (phi0 && in[i] == phi0) in[i] = res;
+
+ if (in[i]==res || in[i]==known || is_Bad(in[i])) 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 (res != known) {
+ edges_node_deleted(res, current_ir_graph);
+ obstack_free (current_ir_graph->obst, res);
+ if (is_Phi(known)) {
+ /* If pred is a phi node we want to optimize it: If loops are matured in a bad
+ order, an enclosing Phi know may get superfluous. */
+ res = optimize_in_place_2(known);
+ if (res != known)
+ exchange(known, res);
+
+ }
+ else
+ res = known;
+ } else {
+ /* A undefined value, e.g., in unreachable code. */
+ res = new_Bad();
+ }
+ } else {
+ res = optimize_node (res); /* This is necessary to add the node to the hash table for cse. */
+ IRN_VRFY_IRG(res, irg);
+ /* Memory Phis in endless loops must be kept alive.
+ As we can't distinguish these easily we keep all of them alive. */
+ if ((res->op == op_Phi) && (mode == mode_M))
+ add_End_keepalive(get_irg_end(irg), res);
+ }
+
+ return res;
+} /* new_rd_Phi_in */