- if (block->attr.block.is_matured) { /* case 3 */
-
- /* The Phi has the same amount of ins as the corresponding block. */
- int n_in = get_irn_arity(block);
- ir_node **in;
- NEW_ARR_A(ir_node *, in, n_in);
-
- /* Phi merge collects the predecessors and then creates a node. */
- res = phi_merge(block, pos, mode, n_in, in);
- } else { /* case 1 */
- /* The block is not mature, we don't know how many in's are needed. A Phi
- with zero predecessors is created. Such a Phi node is called Phi0
- node. The Phi0 is then added to the list of Phi0 nodes in this block
- to be matured by mature_immBlock later.
- The Phi0 has to remember the pos of it's internal value. If the real
- Phi is computed, pos is used to update the array with the local
- values. */
- res = new_rd_Phi0(block, mode);
- res->attr.phi.u.pos = pos;
+ /* We ran into a cycle. This may happen in unreachable loops. */
+ if (irn_visited_else_mark(block)) {
+ /* Since the loop is unreachable, return a Bad. */
+ return new_r_Bad(irg, mode);
+ }
+
+ /* in a matured block we can immediately determine the phi arguments */
+ if (get_Block_matured(block)) {
+ int arity = get_irn_arity(block);
+ /* no predecessors: use unknown value */
+ if (arity == 0 && block == get_irg_start_block(get_irn_irg(block))) {
+ ir_graph *irg = get_irn_irg(block);
+ if (default_initialize_local_variable != NULL) {
+ ir_node *rem = get_r_cur_block(irg);
+ set_r_cur_block(irg, block);
+ res = default_initialize_local_variable(irg, mode, pos - 1);
+ set_r_cur_block(irg, rem);
+ } else {
+ res = new_r_Unknown(irg, mode);
+ }
+ /* one predecessor just use its value */
+ } else if (arity == 1) {
+ ir_node *cfgpred = get_Block_cfgpred(block, 0);
+ if (is_Bad(cfgpred)) {
+ res = new_r_Bad(irg, mode);
+ } else {
+ ir_node *cfgpred_block = get_nodes_block(cfgpred);
+ res = get_r_value_internal(cfgpred_block, pos, mode);
+ }
+ /* multiple predecessors construct Phi */
+ } else {
+ res = new_rd_Phi0(NULL, block, mode, pos);
+ /* enter phi0 into our variable value table to break cycles
+ * arising from set_phi_arguments */
+ block->attr.block.graph_arr[pos] = res;
+ res = set_phi_arguments(res, pos);
+ }
+ } else {
+ /* in case of immature block we have to keep a Phi0 */
+ res = new_rd_Phi0(NULL, block, mode, pos);
+ /* enqueue phi so we can set arguments once the block matures */