static void update_phis_for_loop_copy (struct loop *orig_loop, struct loop *new_loop) { tree new_ssa_name; gimple_stmt_iterator si_new, si_orig; edge orig_loop_latch = loop_latch_edge (orig_loop); edge orig_entry_e = loop_preheader_edge (orig_loop); edge new_loop_entry_e = loop_preheader_edge (new_loop); /* Scan the phis in the headers of the old and new loops (they are organized in exactly the same order). */ for (si_new = gsi_start_phis (new_loop->header), si_orig = gsi_start_phis (orig_loop->header); !gsi_end_p (si_new) && !gsi_end_p (si_orig); gsi_next (&si_new), gsi_next (&si_orig)) { tree def; source_location locus; gimple phi_new = gsi_stmt (si_new); gimple phi_orig = gsi_stmt (si_orig); /* Add the first phi argument for the phi in NEW_LOOP (the one associated with the entry of NEW_LOOP) */ def = PHI_ARG_DEF_FROM_EDGE (phi_orig, orig_entry_e); locus = gimple_phi_arg_location_from_edge (phi_orig, orig_entry_e); add_phi_arg (phi_new, def, new_loop_entry_e, locus); /* Add the second phi argument for the phi in NEW_LOOP (the one associated with the latch of NEW_LOOP) */ def = PHI_ARG_DEF_FROM_EDGE (phi_orig, orig_loop_latch); locus = gimple_phi_arg_location_from_edge (phi_orig, orig_loop_latch); if (TREE_CODE (def) == SSA_NAME) { new_ssa_name = get_current_def (def); if (!new_ssa_name) /* This only happens if there are no definitions inside the loop. Use the phi_result in this case. */ new_ssa_name = PHI_RESULT (phi_new); } else /* Could be an integer. */ new_ssa_name = def; add_phi_arg (phi_new, new_ssa_name, loop_latch_edge (new_loop), locus); } }
static void sese_build_liveouts_bb (sese region, bitmap liveouts, basic_block bb) { edge e; edge_iterator ei; ssa_op_iter iter; use_operand_p use_p; FOR_EACH_EDGE (e, ei, bb->succs) for (gphi_iterator bsi = gsi_start_phis (e->dest); !gsi_end_p (bsi); gsi_next (&bsi)) sese_build_liveouts_use (region, liveouts, bb, PHI_ARG_DEF_FROM_EDGE (bsi.phi (), e)); for (gimple_stmt_iterator bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi)) { gimple *stmt = gsi_stmt (bsi); if (is_gimple_debug (stmt)) continue; FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_ALL_USES) sese_build_liveouts_use (region, liveouts, bb, USE_FROM_PTR (use_p)); } }
static bool same_phi_args_p (basic_block bb1, basic_block bb2, basic_block dest) { edge e1 = find_edge (bb1, dest); edge e2 = find_edge (bb2, dest); gimple_stmt_iterator gsi; gimple phi; for (gsi = gsi_start_phis (dest); !gsi_end_p (gsi); gsi_next (&gsi)) { phi = gsi_stmt (gsi); if (!operand_equal_p (PHI_ARG_DEF_FROM_EDGE (phi, e1), PHI_ARG_DEF_FROM_EDGE (phi, e2), 0)) return false; } return true; }
static tree propagate_through_phis (tree var, edge e) { basic_block dest = e->dest; gimple_stmt_iterator gsi; for (gsi = gsi_start_phis (dest); !gsi_end_p (gsi); gsi_next (&gsi)) { gimple phi = gsi_stmt (gsi); if (PHI_ARG_DEF_FROM_EDGE (phi, e) == var) return PHI_RESULT (phi); } return var; }
static void gather_default_values (tree default_case) { gimple_stmt_iterator gsi; basic_block bb = label_to_block (CASE_LABEL (default_case)); edge e; int i = 0; gcc_assert (CASE_LOW (default_case) == NULL_TREE); if (bb == info.final_bb) e = find_edge (info.switch_bb, bb); else e = single_succ_edge (bb); for (gsi = gsi_start_phis (info.final_bb); !gsi_end_p (gsi); gsi_next (&gsi)) { gimple phi = gsi_stmt (gsi); tree val = PHI_ARG_DEF_FROM_EDGE (phi, e); gcc_assert (val); info.default_values[i++] = val; } }
static tree independent_of_stmt_p (tree expr, gimple at, gimple_stmt_iterator gsi) { basic_block bb, call_bb, at_bb; edge e; edge_iterator ei; if (is_gimple_min_invariant (expr)) return expr; if (TREE_CODE (expr) != SSA_NAME) return NULL_TREE; /* Mark the blocks in the chain leading to the end. */ at_bb = gimple_bb (at); call_bb = gimple_bb (gsi_stmt (gsi)); for (bb = call_bb; bb != at_bb; bb = single_succ (bb)) bb->aux = &bb->aux; bb->aux = &bb->aux; while (1) { at = SSA_NAME_DEF_STMT (expr); bb = gimple_bb (at); /* The default definition or defined before the chain. */ if (!bb || !bb->aux) break; if (bb == call_bb) { for (; !gsi_end_p (gsi); gsi_next (&gsi)) if (gsi_stmt (gsi) == at) break; if (!gsi_end_p (gsi)) expr = NULL_TREE; break; } if (gimple_code (at) != GIMPLE_PHI) { expr = NULL_TREE; break; } FOR_EACH_EDGE (e, ei, bb->preds) if (e->src->aux) break; gcc_assert (e); expr = PHI_ARG_DEF_FROM_EDGE (at, e); if (TREE_CODE (expr) != SSA_NAME) { /* The value is a constant. */ break; } } /* Unmark the blocks. */ for (bb = call_bb; bb != at_bb; bb = single_succ (bb)) bb->aux = NULL; bb->aux = NULL; return expr; }
static void build_constructors (gimple swtch) { unsigned i, branch_num = gimple_switch_num_labels (swtch); tree pos = info.range_min; for (i = 1; i < branch_num; i++) { tree cs = gimple_switch_label (swtch, i); basic_block bb = label_to_block (CASE_LABEL (cs)); edge e; tree high; gimple_stmt_iterator gsi; int j; if (bb == info.final_bb) e = find_edge (info.switch_bb, bb); else e = single_succ_edge (bb); gcc_assert (e); while (tree_int_cst_lt (pos, CASE_LOW (cs))) { int k; for (k = 0; k < info.phi_count; k++) { constructor_elt *elt; elt = VEC_quick_push (constructor_elt, info.constructors[k], NULL); elt->index = int_const_binop (MINUS_EXPR, pos, info.range_min, 0); elt->value = info.default_values[k]; } pos = int_const_binop (PLUS_EXPR, pos, integer_one_node, 0); } gcc_assert (tree_int_cst_equal (pos, CASE_LOW (cs))); j = 0; if (CASE_HIGH (cs)) high = CASE_HIGH (cs); else high = CASE_LOW (cs); for (gsi = gsi_start_phis (info.final_bb); !gsi_end_p (gsi); gsi_next (&gsi)) { gimple phi = gsi_stmt (gsi); tree val = PHI_ARG_DEF_FROM_EDGE (phi, e); tree low = CASE_LOW (cs); pos = CASE_LOW (cs); do { constructor_elt *elt; elt = VEC_quick_push (constructor_elt, info.constructors[j], NULL); elt->index = int_const_binop (MINUS_EXPR, pos, info.range_min, 0); elt->value = val; pos = int_const_binop (PLUS_EXPR, pos, integer_one_node, 0); } while (!tree_int_cst_lt (high, pos) && tree_int_cst_lt (low, pos)); j++; } } }