static bool remove_redundant_iv_tests (struct loop *loop) { struct nb_iter_bound *elt; bool changed = false; if (!loop->any_upper_bound) return false; for (elt = loop->bounds; elt; elt = elt->next) { /* Exit is pointless if it won't be taken before loop reaches upper bound. */ if (elt->is_exit && loop->any_upper_bound && wi::ltu_p (loop->nb_iterations_upper_bound, elt->bound)) { basic_block bb = gimple_bb (elt->stmt); edge exit_edge = EDGE_SUCC (bb, 0); struct tree_niter_desc niter; if (!loop_exit_edge_p (loop, exit_edge)) exit_edge = EDGE_SUCC (bb, 1); /* Only when we know the actual number of iterations, not just a bound, we can remove the exit. */ if (!number_of_iterations_exit (loop, exit_edge, &niter, false, false) || !integer_onep (niter.assumptions) || !integer_zerop (niter.may_be_zero) || !niter.niter || TREE_CODE (niter.niter) != INTEGER_CST || !wi::ltu_p (loop->nb_iterations_upper_bound, wi::to_widest (niter.niter))) continue; if (dump_file && (dump_flags & TDF_DETAILS)) { fprintf (dump_file, "Removed pointless exit: "); print_gimple_stmt (dump_file, elt->stmt, 0, 0); } gcond *cond_stmt = as_a <gcond *> (elt->stmt); if (exit_edge->flags & EDGE_TRUE_VALUE) gimple_cond_make_false (cond_stmt); else gimple_cond_make_true (cond_stmt); update_stmt (cond_stmt); changed = true; } } return changed; }
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); }