/* Induction variable canonicalization and loop peeling.
- Copyright (C) 2004-2014 Free Software Foundation, Inc.
+ Copyright (C) 2004-2016 Free Software Foundation, Inc.
This file is part of GCC.
#include "config.h"
#include "system.h"
#include "coretypes.h"
-#include "tm.h"
+#include "backend.h"
#include "tree.h"
-#include "tm_p.h"
-#include "profile.h"
-#include "predict.h"
-#include "vec.h"
-#include "hashtab.h"
-#include "hash-set.h"
-#include "machmode.h"
-#include "hard-reg-set.h"
-#include "input.h"
-#include "function.h"
-#include "dominance.h"
-#include "cfg.h"
-#include "basic-block.h"
+#include "gimple.h"
+#include "cfghooks.h"
+#include "tree-pass.h"
+#include "ssa.h"
+#include "cgraph.h"
#include "gimple-pretty-print.h"
-#include "tree-ssa-alias.h"
-#include "internal-fn.h"
+#include "fold-const.h"
+#include "profile.h"
#include "gimple-fold.h"
#include "tree-eh.h"
-#include "gimple-expr.h"
-#include "is-a.h"
-#include "gimple.h"
#include "gimple-iterator.h"
-#include "gimple-ssa.h"
-#include "hash-map.h"
-#include "plugin-api.h"
-#include "ipa-ref.h"
-#include "cgraph.h"
#include "tree-cfg.h"
-#include "tree-phinodes.h"
-#include "ssa-iterators.h"
-#include "stringpool.h"
-#include "tree-ssanames.h"
#include "tree-ssa-loop-manip.h"
#include "tree-ssa-loop-niter.h"
#include "tree-ssa-loop.h"
#include "tree-into-ssa.h"
#include "cfgloop.h"
-#include "tree-pass.h"
#include "tree-chrec.h"
#include "tree-scalar-evolution.h"
#include "params.h"
-#include "flags.h"
#include "tree-inline.h"
-#include "target.h"
#include "tree-cfgcleanup.h"
#include "builtins.h"
{
edge in;
tree type, var;
- gimple cond;
+ gcond *cond;
gimple_stmt_iterator incr_at;
enum tree_code cmp;
fprintf (dump_file, " iterations.\n");
}
- cond = last_stmt (exit->src);
+ cond = as_a <gcond *> (last_stmt (exit->src));
in = EDGE_SUCC (exit->src, 0);
if (in == exit)
in = EDGE_SUCC (exit->src, 1);
/* Return true if OP in STMT will be constant after peeling LOOP. */
static bool
-constant_after_peeling (tree op, gimple stmt, struct loop *loop)
+constant_after_peeling (tree op, gimple *stmt, struct loop *loop)
{
affine_iv iv;
for (gsi = gsi_start_bb (body[i]); !gsi_end_p (gsi); gsi_next (&gsi))
{
- gimple stmt = gsi_stmt (gsi);
+ gimple *stmt = gsi_stmt (gsi);
int num = estimate_num_insns (stmt, &eni_size_weights);
bool likely_eliminated = false;
bool likely_eliminated_last = false;
/* Conditionals. */
else if ((gimple_code (stmt) == GIMPLE_COND
&& constant_after_peeling (gimple_cond_lhs (stmt), stmt, loop)
- && constant_after_peeling (gimple_cond_rhs (stmt), stmt, loop))
+ && constant_after_peeling (gimple_cond_rhs (stmt), stmt, loop)
+ /* We don't simplify all constant compares so make sure
+ they are not both constant already. See PR70288. */
+ && (! is_gimple_min_invariant (gimple_cond_lhs (stmt))
+ || ! is_gimple_min_invariant (gimple_cond_rhs (stmt))))
|| (gimple_code (stmt) == GIMPLE_SWITCH
- && constant_after_peeling (gimple_switch_index (stmt), stmt, loop)))
+ && constant_after_peeling (gimple_switch_index (
+ as_a <gswitch *> (stmt)),
+ stmt, loop)
+ && ! is_gimple_min_invariant (gimple_switch_index (
+ as_a <gswitch *> (stmt)))))
{
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, " Constant conditional.\n");
basic_block bb = path.pop ();
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
{
- gimple stmt = gsi_stmt (gsi);
+ gimple *stmt = gsi_stmt (gsi);
if (gimple_code (stmt) == GIMPLE_CALL)
{
int flags = gimple_call_flags (stmt);
&& (!constant_after_peeling (gimple_cond_lhs (stmt), stmt, loop)
|| constant_after_peeling (gimple_cond_rhs (stmt), stmt, loop)))
|| (gimple_code (stmt) == GIMPLE_SWITCH
- && !constant_after_peeling (gimple_switch_index (stmt), stmt, loop)))
+ && !constant_after_peeling (gimple_switch_index (
+ as_a <gswitch *> (stmt)),
+ stmt, loop)))
&& (!exit || bb != exit->src))
size->num_branches_on_hot_path++;
}
&& wi::ltu_p (elt->bound, npeeled))
{
gimple_stmt_iterator gsi = gsi_for_stmt (elt->stmt);
- gimple stmt = gimple_build_call
+ gcall *stmt = gimple_build_call
(builtin_decl_implicit (BUILT_IN_UNREACHABLE), 0);
-
gimple_set_location (stmt, gimple_location (elt->stmt));
gsi_insert_before (&gsi, stmt, GSI_NEW_STMT);
+ split_block (gimple_bb (stmt), stmt);
changed = true;
if (dump_file && (dump_flags & TDF_DETAILS))
{
if (!loop_exit_edge_p (loop, exit_edge))
exit_edge = EDGE_SUCC (bb, 1);
gcc_checking_assert (loop_exit_edge_p (loop, exit_edge));
+ gcond *cond_stmt = as_a <gcond *> (elt->stmt);
if (exit_edge->flags & EDGE_TRUE_VALUE)
- gimple_cond_make_true (elt->stmt);
+ gimple_cond_make_true (cond_stmt);
else
- gimple_cond_make_false (elt->stmt);
- update_stmt (elt->stmt);
+ gimple_cond_make_false (cond_stmt);
+ update_stmt (cond_stmt);
changed = true;
}
}
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 (elt->stmt);
+ gimple_cond_make_false (cond_stmt);
else
- gimple_cond_make_true (elt->stmt);
- update_stmt (elt->stmt);
+ gimple_cond_make_true (cond_stmt);
+ update_stmt (cond_stmt);
changed = true;
}
}
edge latch_edge = loop_latch_edge (loop);
int flags = latch_edge->flags;
location_t locus = latch_edge->goto_locus;
- gimple stmt;
+ gcall *stmt;
gimple_stmt_iterator gsi;
remove_exits_and_undefined_stmts (loop, n_unroll);
location_t locus)
{
unsigned HOST_WIDE_INT n_unroll = 0, ninsns, unr_insns;
- gimple cond;
struct loop_size size;
bool n_unroll_found = false;
edge edge_to_cancel = NULL;
/* Remove the conditional from the last copy of the loop. */
if (edge_to_cancel)
{
- cond = last_stmt (edge_to_cancel->src);
+ gcond *cond = as_a <gcond *> (last_stmt (edge_to_cancel->src));
if (edge_to_cancel->flags & EDGE_TRUE_VALUE)
gimple_cond_make_false (cond);
else
edge exit, tree niter,
HOST_WIDE_INT maxiter)
{
- int npeel;
+ HOST_WIDE_INT npeel;
struct loop_size size;
int peeled_size;
sbitmap wont_exit;
{
if (dump_file)
fprintf (dump_file, "Not peeling: rolls too much "
- "(%i + 1 > --param max-peel-times)\n", npeel);
+ "(%i + 1 > --param max-peel-times)\n", (int) npeel);
return false;
}
npeel++;
/* Check peeled loops size. */
tree_estimate_loop_size (loop, exit, NULL, &size,
PARAM_VALUE (PARAM_MAX_PEELED_INSNS));
- if ((peeled_size = estimated_peeled_sequence_size (&size, npeel))
+ if ((peeled_size = estimated_peeled_sequence_size (&size, (int) npeel))
> PARAM_VALUE (PARAM_MAX_PEELED_INSNS))
{
if (dump_file)
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "Peeled loop %d, %i times.\n",
- loop->num, npeel);
+ loop->num, (int) npeel);
}
if (loop->any_upper_bound)
loop->nb_iterations_upper_bound -= npeel;
bool irred_invalidated = false;
bitmap loop_closed_ssa_invalidated = BITMAP_ALLOC (NULL);
- free_numbers_of_iterations_estimates ();
+ free_numbers_of_iterations_estimates (cfun);
estimate_numbers_of_iterations ();
FOR_EACH_LOOP (loop, LI_FROM_INNERMOST)
return 0;
}
-/* Propagate VAL into all uses of SSA_NAME. */
-
-static void
-propagate_into_all_uses (tree ssa_name, tree val)
-{
- imm_use_iterator iter;
- gimple use_stmt;
-
- FOR_EACH_IMM_USE_STMT (use_stmt, iter, ssa_name)
- {
- gimple_stmt_iterator use_stmt_gsi = gsi_for_stmt (use_stmt);
- use_operand_p use;
-
- FOR_EACH_IMM_USE_ON_STMT (use, iter)
- SET_USE (use, val);
-
- if (is_gimple_assign (use_stmt)
- && get_gimple_rhs_class (gimple_assign_rhs_code (use_stmt))
- == GIMPLE_SINGLE_RHS)
- {
- tree rhs = gimple_assign_rhs1 (use_stmt);
-
- if (TREE_CODE (rhs) == ADDR_EXPR)
- recompute_tree_invariant_for_addr_expr (rhs);
- }
-
- fold_stmt_inplace (&use_stmt_gsi);
- update_stmt (use_stmt);
- maybe_clean_or_replace_eh_stmt (use_stmt, use_stmt);
- }
-}
-
/* Propagate constant SSA_NAMEs defined in basic block BB. */
static void
propagate_constants_for_unrolling (basic_block bb)
{
- gimple_stmt_iterator gsi;
-
/* Look for degenerate PHI nodes with constant argument. */
- for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); )
+ for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi); )
{
- gimple phi = gsi_stmt (gsi);
+ gphi *phi = gsi.phi ();
tree result = gimple_phi_result (phi);
tree arg = gimple_phi_arg_def (phi, 0);
- if (gimple_phi_num_args (phi) == 1 && TREE_CODE (arg) == INTEGER_CST)
+ if (! SSA_NAME_OCCURS_IN_ABNORMAL_PHI (result)
+ && gimple_phi_num_args (phi) == 1
+ && TREE_CODE (arg) == INTEGER_CST)
{
- propagate_into_all_uses (result, arg);
+ replace_uses_by (result, arg);
gsi_remove (&gsi, true);
release_ssa_name (result);
}
}
/* Look for assignments to SSA names with constant RHS. */
- for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); )
+ for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi); )
{
- gimple stmt = gsi_stmt (gsi);
+ gimple *stmt = gsi_stmt (gsi);
tree lhs;
if (is_gimple_assign (stmt)
&& (lhs = gimple_assign_lhs (stmt), TREE_CODE (lhs) == SSA_NAME)
&& !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
{
- propagate_into_all_uses (lhs, gimple_assign_rhs1 (stmt));
+ replace_uses_by (lhs, gimple_assign_rhs1 (stmt));
gsi_remove (&gsi, true);
release_ssa_name (lhs);
}
if (loops_state_satisfies_p (LOOP_CLOSED_SSA))
loop_closed_ssa_invalidated = BITMAP_ALLOC (NULL);
- free_numbers_of_iterations_estimates ();
+ free_numbers_of_iterations_estimates (cfun);
estimate_numbers_of_iterations ();
changed = tree_unroll_loops_completely_1 (may_increase_size,
/* Clean up the information about numbers of iterations, since
complete unrolling might have invalidated it. */
scev_reset ();
-#ifdef ENABLE_CHECKING
- if (loops_state_satisfies_p (LOOP_CLOSED_SSA))
+ if (flag_checking && loops_state_satisfies_p (LOOP_CLOSED_SSA))
verify_loop_closed_ssa (true);
-#endif
}
if (loop_closed_ssa_invalidated)
BITMAP_FREE (loop_closed_ssa_invalidated);
{
scev_initialize ();
ret = tree_unroll_loops_completely (optimize >= 3, false);
- free_numbers_of_iterations_estimates ();
+ free_numbers_of_iterations_estimates (fun);
scev_finalize ();
}
loop_optimizer_finalize ();