static gbb_type get_bb_type (basic_block bb, struct loop *last_loop) { vec<basic_block> dom; int nb_dom; struct loop *loop = bb->loop_father; /* Check, if we entry into a new loop. */ if (loop != last_loop) { if (single_exit (loop) != NULL) return GBB_LOOP_SING_EXIT_HEADER; else if (loop->num != 0) return GBB_LOOP_MULT_EXIT_HEADER; else return GBB_COND_HEADER; } dom = get_dominated_by (CDI_DOMINATORS, bb); nb_dom = dom.length (); dom.release (); if (nb_dom == 0) return GBB_LAST; if (nb_dom == 1 && single_succ_p (bb)) return GBB_SIMPLE; return GBB_COND_HEADER; }
static void create_bb_after_loop (struct loop *loop) { edge exit = single_exit (loop); if (!exit) return; split_edge (exit); }
static bool graphite_can_represent_loop (basic_block scop_entry, loop_p loop) { tree niter; struct tree_niter_desc niter_desc; /* FIXME: For the moment, graphite cannot be used on loops that iterate using induction variables that wrap. */ return number_of_iterations_exit (loop, single_exit (loop), &niter_desc, false) && niter_desc.control.no_overflow && (niter = number_of_latch_executions (loop)) && !chrec_contains_undetermined (niter) && graphite_can_represent_expr (scop_entry, loop, niter); }
static struct loop * copy_loop_before (struct loop *loop) { struct loop *res; edge preheader = loop_preheader_edge (loop); if (!single_exit (loop)) return NULL; initialize_original_copy_tables (); res = slpeel_tree_duplicate_loop_to_edge_cfg (loop, preheader); free_original_copy_tables (); if (!res) return NULL; update_phis_for_loop_copy (loop, res); rename_variables_in_loop (res); return res; }
static bool generate_builtin (struct loop *loop, bitmap partition, bool copy_p) { bool res = false; unsigned i, x = 0; basic_block *bbs; gimple write = NULL; tree op0, op1; gimple_stmt_iterator bsi; tree nb_iter = number_of_exit_cond_executions (loop); if (!nb_iter || nb_iter == chrec_dont_know) return false; bbs = get_loop_body_in_dom_order (loop); for (i = 0; i < loop->num_nodes; i++) { basic_block bb = bbs[i]; for (bsi = gsi_start_phis (bb); !gsi_end_p (bsi); gsi_next (&bsi)) x++; for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi)) { gimple stmt = gsi_stmt (bsi); if (bitmap_bit_p (partition, x++) && is_gimple_assign (stmt) && !is_gimple_reg (gimple_assign_lhs (stmt))) { /* Don't generate the builtins when there are more than one memory write. */ if (write != NULL) goto end; write = stmt; } } } if (!write) goto end; op0 = gimple_assign_lhs (write); op1 = gimple_assign_rhs1 (write); if (!(TREE_CODE (op0) == ARRAY_REF || TREE_CODE (op0) == INDIRECT_REF)) goto end; /* The new statements will be placed before LOOP. */ bsi = gsi_last_bb (loop_preheader_edge (loop)->src); if (gimple_assign_rhs_code (write) == INTEGER_CST && (integer_zerop (op1) || real_zerop (op1))) res = generate_memset_zero (write, op0, nb_iter, bsi); /* If this is the last partition for which we generate code, we have to destroy the loop. */ if (res && !copy_p) { unsigned nbbs = loop->num_nodes; basic_block src = loop_preheader_edge (loop)->src; basic_block dest = single_exit (loop)->dest; prop_phis (dest); make_edge (src, dest, EDGE_FALLTHRU); cancel_loop_tree (loop); for (i = 0; i < nbbs; i++) delete_basic_block (bbs[i]); set_immediate_dominator (CDI_DOMINATORS, dest, recompute_dominator (CDI_DOMINATORS, dest)); } end: free (bbs); return res; }
static bool generate_builtin (struct loop *loop, bitmap partition, bool copy_p) { bool res = false; unsigned i, x = 0; basic_block *bbs; gimple write = NULL; gimple_stmt_iterator bsi; tree nb_iter = number_of_exit_cond_executions (loop); if (!nb_iter || nb_iter == chrec_dont_know) return false; bbs = get_loop_body_in_dom_order (loop); for (i = 0; i < loop->num_nodes; i++) { basic_block bb = bbs[i]; for (bsi = gsi_start_phis (bb); !gsi_end_p (bsi); gsi_next (&bsi)) x++; for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi)) { gimple stmt = gsi_stmt (bsi); if (gimple_code (stmt) == GIMPLE_LABEL || is_gimple_debug (stmt)) continue; if (!bitmap_bit_p (partition, x++)) continue; /* If the stmt has uses outside of the loop fail. */ if (stmt_has_scalar_dependences_outside_loop (stmt)) goto end; if (is_gimple_assign (stmt) && !is_gimple_reg (gimple_assign_lhs (stmt))) { /* Don't generate the builtins when there are more than one memory write. */ if (write != NULL) goto end; write = stmt; if (bb == loop->latch) nb_iter = number_of_latch_executions (loop); } } } if (!stmt_with_adjacent_zero_store_dr_p (write)) goto end; /* The new statements will be placed before LOOP. */ bsi = gsi_last_bb (loop_preheader_edge (loop)->src); generate_memset_zero (write, gimple_assign_lhs (write), nb_iter, bsi); res = true; /* If this is the last partition for which we generate code, we have to destroy the loop. */ if (!copy_p) { unsigned nbbs = loop->num_nodes; edge exit = single_exit (loop); basic_block src = loop_preheader_edge (loop)->src, dest = exit->dest; redirect_edge_pred (exit, src); exit->flags &= ~(EDGE_TRUE_VALUE|EDGE_FALSE_VALUE); exit->flags |= EDGE_FALLTHRU; cancel_loop_tree (loop); rescan_loop_exit (exit, false, true); for (i = 0; i < nbbs; i++) delete_basic_block (bbs[i]); set_immediate_dominator (CDI_DOMINATORS, dest, recompute_dominator (CDI_DOMINATORS, dest)); } end: free (bbs); return res; }