11debfc3dSmrg /* Induction variable canonicalization and loop peeling.
2*8feb0f0bSmrg Copyright (C) 2004-2020 Free Software Foundation, Inc.
31debfc3dSmrg
41debfc3dSmrg This file is part of GCC.
51debfc3dSmrg
61debfc3dSmrg GCC is free software; you can redistribute it and/or modify it
71debfc3dSmrg under the terms of the GNU General Public License as published by the
81debfc3dSmrg Free Software Foundation; either version 3, or (at your option) any
91debfc3dSmrg later version.
101debfc3dSmrg
111debfc3dSmrg GCC is distributed in the hope that it will be useful, but WITHOUT
121debfc3dSmrg ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
131debfc3dSmrg FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
141debfc3dSmrg for more details.
151debfc3dSmrg
161debfc3dSmrg You should have received a copy of the GNU General Public License
171debfc3dSmrg along with GCC; see the file COPYING3. If not see
181debfc3dSmrg <http://www.gnu.org/licenses/>. */
191debfc3dSmrg
201debfc3dSmrg /* This pass detects the loops that iterate a constant number of times,
211debfc3dSmrg adds a canonical induction variable (step -1, tested against 0)
221debfc3dSmrg and replaces the exit test. This enables the less powerful rtl
231debfc3dSmrg level analysis to use this information.
241debfc3dSmrg
251debfc3dSmrg This might spoil the code in some cases (by increasing register pressure).
261debfc3dSmrg Note that in the case the new variable is not needed, ivopts will get rid
271debfc3dSmrg of it, so it might only be a problem when there are no other linear induction
281debfc3dSmrg variables. In that case the created optimization possibilities are likely
291debfc3dSmrg to pay up.
301debfc3dSmrg
311debfc3dSmrg We also perform
321debfc3dSmrg - complete unrolling (or peeling) when the loops is rolling few enough
331debfc3dSmrg times
341debfc3dSmrg - simple peeling (i.e. copying few initial iterations prior the loop)
351debfc3dSmrg when number of iteration estimate is known (typically by the profile
361debfc3dSmrg info). */
371debfc3dSmrg
381debfc3dSmrg #include "config.h"
391debfc3dSmrg #include "system.h"
401debfc3dSmrg #include "coretypes.h"
411debfc3dSmrg #include "backend.h"
421debfc3dSmrg #include "tree.h"
431debfc3dSmrg #include "gimple.h"
441debfc3dSmrg #include "cfghooks.h"
451debfc3dSmrg #include "tree-pass.h"
461debfc3dSmrg #include "ssa.h"
471debfc3dSmrg #include "cgraph.h"
481debfc3dSmrg #include "gimple-pretty-print.h"
491debfc3dSmrg #include "fold-const.h"
501debfc3dSmrg #include "profile.h"
511debfc3dSmrg #include "gimple-fold.h"
521debfc3dSmrg #include "tree-eh.h"
531debfc3dSmrg #include "gimple-iterator.h"
541debfc3dSmrg #include "tree-cfg.h"
551debfc3dSmrg #include "tree-ssa-loop-manip.h"
561debfc3dSmrg #include "tree-ssa-loop-niter.h"
571debfc3dSmrg #include "tree-ssa-loop.h"
581debfc3dSmrg #include "tree-into-ssa.h"
591debfc3dSmrg #include "cfgloop.h"
601debfc3dSmrg #include "tree-chrec.h"
611debfc3dSmrg #include "tree-scalar-evolution.h"
621debfc3dSmrg #include "tree-inline.h"
631debfc3dSmrg #include "tree-cfgcleanup.h"
641debfc3dSmrg #include "builtins.h"
65c0a68be4Smrg #include "tree-ssa-sccvn.h"
66*8feb0f0bSmrg #include "dbgcnt.h"
671debfc3dSmrg
681debfc3dSmrg /* Specifies types of loops that may be unrolled. */
691debfc3dSmrg
701debfc3dSmrg enum unroll_level
711debfc3dSmrg {
721debfc3dSmrg UL_SINGLE_ITER, /* Only loops that exit immediately in the first
731debfc3dSmrg iteration. */
741debfc3dSmrg UL_NO_GROWTH, /* Only loops whose unrolling will not cause increase
751debfc3dSmrg of code size. */
761debfc3dSmrg UL_ALL /* All suitable loops. */
771debfc3dSmrg };
781debfc3dSmrg
791debfc3dSmrg /* Adds a canonical induction variable to LOOP iterating NITER times. EXIT
80a2dc1f3fSmrg is the exit edge whose condition is replaced. The ssa versions of the new
81a2dc1f3fSmrg IV before and after increment will be stored in VAR_BEFORE and VAR_AFTER
82a2dc1f3fSmrg if they are not NULL. */
831debfc3dSmrg
84a2dc1f3fSmrg void
85*8feb0f0bSmrg create_canonical_iv (class loop *loop, edge exit, tree niter,
86a2dc1f3fSmrg tree *var_before = NULL, tree *var_after = NULL)
871debfc3dSmrg {
881debfc3dSmrg edge in;
891debfc3dSmrg tree type, var;
901debfc3dSmrg gcond *cond;
911debfc3dSmrg gimple_stmt_iterator incr_at;
921debfc3dSmrg enum tree_code cmp;
931debfc3dSmrg
941debfc3dSmrg if (dump_file && (dump_flags & TDF_DETAILS))
951debfc3dSmrg {
961debfc3dSmrg fprintf (dump_file, "Added canonical iv to loop %d, ", loop->num);
971debfc3dSmrg print_generic_expr (dump_file, niter, TDF_SLIM);
981debfc3dSmrg fprintf (dump_file, " iterations.\n");
991debfc3dSmrg }
1001debfc3dSmrg
1011debfc3dSmrg cond = as_a <gcond *> (last_stmt (exit->src));
1021debfc3dSmrg in = EDGE_SUCC (exit->src, 0);
1031debfc3dSmrg if (in == exit)
1041debfc3dSmrg in = EDGE_SUCC (exit->src, 1);
1051debfc3dSmrg
1061debfc3dSmrg /* Note that we do not need to worry about overflows, since
1071debfc3dSmrg type of niter is always unsigned and all comparisons are
1081debfc3dSmrg just for equality/nonequality -- i.e. everything works
1091debfc3dSmrg with a modulo arithmetics. */
1101debfc3dSmrg
1111debfc3dSmrg type = TREE_TYPE (niter);
1121debfc3dSmrg niter = fold_build2 (PLUS_EXPR, type,
1131debfc3dSmrg niter,
1141debfc3dSmrg build_int_cst (type, 1));
1151debfc3dSmrg incr_at = gsi_last_bb (in->src);
1161debfc3dSmrg create_iv (niter,
1171debfc3dSmrg build_int_cst (type, -1),
1181debfc3dSmrg NULL_TREE, loop,
119a2dc1f3fSmrg &incr_at, false, var_before, &var);
120a2dc1f3fSmrg if (var_after)
121a2dc1f3fSmrg *var_after = var;
1221debfc3dSmrg
1231debfc3dSmrg cmp = (exit->flags & EDGE_TRUE_VALUE) ? EQ_EXPR : NE_EXPR;
1241debfc3dSmrg gimple_cond_set_code (cond, cmp);
1251debfc3dSmrg gimple_cond_set_lhs (cond, var);
1261debfc3dSmrg gimple_cond_set_rhs (cond, build_int_cst (type, 0));
1271debfc3dSmrg update_stmt (cond);
1281debfc3dSmrg }
1291debfc3dSmrg
1301debfc3dSmrg /* Describe size of loop as detected by tree_estimate_loop_size. */
1311debfc3dSmrg struct loop_size
1321debfc3dSmrg {
1331debfc3dSmrg /* Number of instructions in the loop. */
1341debfc3dSmrg int overall;
1351debfc3dSmrg
1361debfc3dSmrg /* Number of instructions that will be likely optimized out in
1371debfc3dSmrg peeled iterations of loop (i.e. computation based on induction
1381debfc3dSmrg variable where induction variable starts at known constant.) */
1391debfc3dSmrg int eliminated_by_peeling;
1401debfc3dSmrg
1411debfc3dSmrg /* Same statistics for last iteration of loop: it is smaller because
1421debfc3dSmrg instructions after exit are not executed. */
1431debfc3dSmrg int last_iteration;
1441debfc3dSmrg int last_iteration_eliminated_by_peeling;
1451debfc3dSmrg
1461debfc3dSmrg /* If some IV computation will become constant. */
1471debfc3dSmrg bool constant_iv;
1481debfc3dSmrg
1491debfc3dSmrg /* Number of call stmts that are not a builtin and are pure or const
1501debfc3dSmrg present on the hot path. */
1511debfc3dSmrg int num_pure_calls_on_hot_path;
1521debfc3dSmrg /* Number of call stmts that are not a builtin and are not pure nor const
1531debfc3dSmrg present on the hot path. */
1541debfc3dSmrg int num_non_pure_calls_on_hot_path;
1551debfc3dSmrg /* Number of statements other than calls in the loop. */
1561debfc3dSmrg int non_call_stmts_on_hot_path;
1571debfc3dSmrg /* Number of branches seen on the hot path. */
1581debfc3dSmrg int num_branches_on_hot_path;
1591debfc3dSmrg };
1601debfc3dSmrg
1611debfc3dSmrg /* Return true if OP in STMT will be constant after peeling LOOP. */
1621debfc3dSmrg
1631debfc3dSmrg static bool
constant_after_peeling(tree op,gimple * stmt,class loop * loop)164*8feb0f0bSmrg constant_after_peeling (tree op, gimple *stmt, class loop *loop)
1651debfc3dSmrg {
166*8feb0f0bSmrg if (CONSTANT_CLASS_P (op))
1671debfc3dSmrg return true;
1681debfc3dSmrg
1691debfc3dSmrg /* We can still fold accesses to constant arrays when index is known. */
1701debfc3dSmrg if (TREE_CODE (op) != SSA_NAME)
1711debfc3dSmrg {
1721debfc3dSmrg tree base = op;
1731debfc3dSmrg
1741debfc3dSmrg /* First make fast look if we see constant array inside. */
1751debfc3dSmrg while (handled_component_p (base))
1761debfc3dSmrg base = TREE_OPERAND (base, 0);
1771debfc3dSmrg if ((DECL_P (base)
1781debfc3dSmrg && ctor_for_folding (base) != error_mark_node)
1791debfc3dSmrg || CONSTANT_CLASS_P (base))
1801debfc3dSmrg {
1811debfc3dSmrg /* If so, see if we understand all the indices. */
1821debfc3dSmrg base = op;
1831debfc3dSmrg while (handled_component_p (base))
1841debfc3dSmrg {
1851debfc3dSmrg if (TREE_CODE (base) == ARRAY_REF
1861debfc3dSmrg && !constant_after_peeling (TREE_OPERAND (base, 1), stmt, loop))
1871debfc3dSmrg return false;
1881debfc3dSmrg base = TREE_OPERAND (base, 0);
1891debfc3dSmrg }
1901debfc3dSmrg return true;
1911debfc3dSmrg }
1921debfc3dSmrg return false;
1931debfc3dSmrg }
1941debfc3dSmrg
195a2dc1f3fSmrg /* Induction variables are constants when defined in loop. */
196a2dc1f3fSmrg if (loop_containing_stmt (stmt) != loop)
1971debfc3dSmrg return false;
198a2dc1f3fSmrg tree ev = analyze_scalar_evolution (loop, op);
199a2dc1f3fSmrg if (chrec_contains_undetermined (ev)
200a2dc1f3fSmrg || chrec_contains_symbols (ev))
2011debfc3dSmrg return false;
2021debfc3dSmrg return true;
2031debfc3dSmrg }
2041debfc3dSmrg
2051debfc3dSmrg /* Computes an estimated number of insns in LOOP.
2061debfc3dSmrg EXIT (if non-NULL) is an exite edge that will be eliminated in all but last
2071debfc3dSmrg iteration of the loop.
2081debfc3dSmrg EDGE_TO_CANCEL (if non-NULL) is an non-exit edge eliminated in the last iteration
2091debfc3dSmrg of loop.
2101debfc3dSmrg Return results in SIZE, estimate benefits for complete unrolling exiting by EXIT.
2111debfc3dSmrg Stop estimating after UPPER_BOUND is met. Return true in this case. */
2121debfc3dSmrg
2131debfc3dSmrg static bool
tree_estimate_loop_size(class loop * loop,edge exit,edge edge_to_cancel,struct loop_size * size,int upper_bound)214*8feb0f0bSmrg tree_estimate_loop_size (class loop *loop, edge exit, edge edge_to_cancel,
2151debfc3dSmrg struct loop_size *size, int upper_bound)
2161debfc3dSmrg {
2171debfc3dSmrg basic_block *body = get_loop_body (loop);
2181debfc3dSmrg gimple_stmt_iterator gsi;
2191debfc3dSmrg unsigned int i;
2201debfc3dSmrg bool after_exit;
2211debfc3dSmrg vec<basic_block> path = get_loop_hot_path (loop);
2221debfc3dSmrg
2231debfc3dSmrg size->overall = 0;
2241debfc3dSmrg size->eliminated_by_peeling = 0;
2251debfc3dSmrg size->last_iteration = 0;
2261debfc3dSmrg size->last_iteration_eliminated_by_peeling = 0;
2271debfc3dSmrg size->num_pure_calls_on_hot_path = 0;
2281debfc3dSmrg size->num_non_pure_calls_on_hot_path = 0;
2291debfc3dSmrg size->non_call_stmts_on_hot_path = 0;
2301debfc3dSmrg size->num_branches_on_hot_path = 0;
2311debfc3dSmrg size->constant_iv = 0;
2321debfc3dSmrg
2331debfc3dSmrg if (dump_file && (dump_flags & TDF_DETAILS))
2341debfc3dSmrg fprintf (dump_file, "Estimating sizes for loop %i\n", loop->num);
2351debfc3dSmrg for (i = 0; i < loop->num_nodes; i++)
2361debfc3dSmrg {
2371debfc3dSmrg if (edge_to_cancel && body[i] != edge_to_cancel->src
2381debfc3dSmrg && dominated_by_p (CDI_DOMINATORS, body[i], edge_to_cancel->src))
2391debfc3dSmrg after_exit = true;
2401debfc3dSmrg else
2411debfc3dSmrg after_exit = false;
2421debfc3dSmrg if (dump_file && (dump_flags & TDF_DETAILS))
2431debfc3dSmrg fprintf (dump_file, " BB: %i, after_exit: %i\n", body[i]->index,
2441debfc3dSmrg after_exit);
2451debfc3dSmrg
2461debfc3dSmrg for (gsi = gsi_start_bb (body[i]); !gsi_end_p (gsi); gsi_next (&gsi))
2471debfc3dSmrg {
2481debfc3dSmrg gimple *stmt = gsi_stmt (gsi);
2491debfc3dSmrg int num = estimate_num_insns (stmt, &eni_size_weights);
2501debfc3dSmrg bool likely_eliminated = false;
2511debfc3dSmrg bool likely_eliminated_last = false;
2521debfc3dSmrg bool likely_eliminated_peeled = false;
2531debfc3dSmrg
2541debfc3dSmrg if (dump_file && (dump_flags & TDF_DETAILS))
2551debfc3dSmrg {
2561debfc3dSmrg fprintf (dump_file, " size: %3i ", num);
257a2dc1f3fSmrg print_gimple_stmt (dump_file, gsi_stmt (gsi), 0);
2581debfc3dSmrg }
2591debfc3dSmrg
2601debfc3dSmrg /* Look for reasons why we might optimize this stmt away. */
2611debfc3dSmrg
2621debfc3dSmrg if (!gimple_has_side_effects (stmt))
2631debfc3dSmrg {
2641debfc3dSmrg /* Exit conditional. */
2651debfc3dSmrg if (exit && body[i] == exit->src
2661debfc3dSmrg && stmt == last_stmt (exit->src))
2671debfc3dSmrg {
2681debfc3dSmrg if (dump_file && (dump_flags & TDF_DETAILS))
2691debfc3dSmrg fprintf (dump_file, " Exit condition will be eliminated "
2701debfc3dSmrg "in peeled copies.\n");
2711debfc3dSmrg likely_eliminated_peeled = true;
2721debfc3dSmrg }
2731debfc3dSmrg if (edge_to_cancel && body[i] == edge_to_cancel->src
2741debfc3dSmrg && stmt == last_stmt (edge_to_cancel->src))
2751debfc3dSmrg {
2761debfc3dSmrg if (dump_file && (dump_flags & TDF_DETAILS))
2771debfc3dSmrg fprintf (dump_file, " Exit condition will be eliminated "
2781debfc3dSmrg "in last copy.\n");
2791debfc3dSmrg likely_eliminated_last = true;
2801debfc3dSmrg }
2811debfc3dSmrg /* Sets of IV variables */
2821debfc3dSmrg if (gimple_code (stmt) == GIMPLE_ASSIGN
2831debfc3dSmrg && constant_after_peeling (gimple_assign_lhs (stmt), stmt, loop))
2841debfc3dSmrg {
2851debfc3dSmrg if (dump_file && (dump_flags & TDF_DETAILS))
2861debfc3dSmrg fprintf (dump_file, " Induction variable computation will"
2871debfc3dSmrg " be folded away.\n");
2881debfc3dSmrg likely_eliminated = true;
2891debfc3dSmrg }
2901debfc3dSmrg /* Assignments of IV variables. */
2911debfc3dSmrg else if (gimple_code (stmt) == GIMPLE_ASSIGN
2921debfc3dSmrg && TREE_CODE (gimple_assign_lhs (stmt)) == SSA_NAME
2931debfc3dSmrg && constant_after_peeling (gimple_assign_rhs1 (stmt),
2941debfc3dSmrg stmt, loop)
2951debfc3dSmrg && (gimple_assign_rhs_class (stmt) != GIMPLE_BINARY_RHS
2961debfc3dSmrg || constant_after_peeling (gimple_assign_rhs2 (stmt),
297*8feb0f0bSmrg stmt, loop))
298*8feb0f0bSmrg && gimple_assign_rhs_class (stmt) != GIMPLE_TERNARY_RHS)
2991debfc3dSmrg {
3001debfc3dSmrg size->constant_iv = true;
3011debfc3dSmrg if (dump_file && (dump_flags & TDF_DETAILS))
3021debfc3dSmrg fprintf (dump_file,
3031debfc3dSmrg " Constant expression will be folded away.\n");
3041debfc3dSmrg likely_eliminated = true;
3051debfc3dSmrg }
3061debfc3dSmrg /* Conditionals. */
3071debfc3dSmrg else if ((gimple_code (stmt) == GIMPLE_COND
3081debfc3dSmrg && constant_after_peeling (gimple_cond_lhs (stmt), stmt,
3091debfc3dSmrg loop)
3101debfc3dSmrg && constant_after_peeling (gimple_cond_rhs (stmt), stmt,
3111debfc3dSmrg loop)
3121debfc3dSmrg /* We don't simplify all constant compares so make sure
3131debfc3dSmrg they are not both constant already. See PR70288. */
3141debfc3dSmrg && (! is_gimple_min_invariant (gimple_cond_lhs (stmt))
3151debfc3dSmrg || ! is_gimple_min_invariant
3161debfc3dSmrg (gimple_cond_rhs (stmt))))
3171debfc3dSmrg || (gimple_code (stmt) == GIMPLE_SWITCH
3181debfc3dSmrg && constant_after_peeling (gimple_switch_index (
3191debfc3dSmrg as_a <gswitch *>
3201debfc3dSmrg (stmt)),
3211debfc3dSmrg stmt, loop)
3221debfc3dSmrg && ! is_gimple_min_invariant
3231debfc3dSmrg (gimple_switch_index
3241debfc3dSmrg (as_a <gswitch *> (stmt)))))
3251debfc3dSmrg {
3261debfc3dSmrg if (dump_file && (dump_flags & TDF_DETAILS))
3271debfc3dSmrg fprintf (dump_file, " Constant conditional.\n");
3281debfc3dSmrg likely_eliminated = true;
3291debfc3dSmrg }
3301debfc3dSmrg }
3311debfc3dSmrg
3321debfc3dSmrg size->overall += num;
3331debfc3dSmrg if (likely_eliminated || likely_eliminated_peeled)
3341debfc3dSmrg size->eliminated_by_peeling += num;
3351debfc3dSmrg if (!after_exit)
3361debfc3dSmrg {
3371debfc3dSmrg size->last_iteration += num;
3381debfc3dSmrg if (likely_eliminated || likely_eliminated_last)
3391debfc3dSmrg size->last_iteration_eliminated_by_peeling += num;
3401debfc3dSmrg }
3411debfc3dSmrg if ((size->overall * 3 / 2 - size->eliminated_by_peeling
3421debfc3dSmrg - size->last_iteration_eliminated_by_peeling) > upper_bound)
3431debfc3dSmrg {
3441debfc3dSmrg free (body);
3451debfc3dSmrg path.release ();
3461debfc3dSmrg return true;
3471debfc3dSmrg }
3481debfc3dSmrg }
3491debfc3dSmrg }
3501debfc3dSmrg while (path.length ())
3511debfc3dSmrg {
3521debfc3dSmrg basic_block bb = path.pop ();
3531debfc3dSmrg for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
3541debfc3dSmrg {
3551debfc3dSmrg gimple *stmt = gsi_stmt (gsi);
3561debfc3dSmrg if (gimple_code (stmt) == GIMPLE_CALL
3571debfc3dSmrg && !gimple_inexpensive_call_p (as_a <gcall *> (stmt)))
3581debfc3dSmrg {
3591debfc3dSmrg int flags = gimple_call_flags (stmt);
3601debfc3dSmrg if (flags & (ECF_PURE | ECF_CONST))
3611debfc3dSmrg size->num_pure_calls_on_hot_path++;
3621debfc3dSmrg else
3631debfc3dSmrg size->num_non_pure_calls_on_hot_path++;
3641debfc3dSmrg size->num_branches_on_hot_path ++;
3651debfc3dSmrg }
3661debfc3dSmrg /* Count inexpensive calls as non-calls, because they will likely
3671debfc3dSmrg expand inline. */
3681debfc3dSmrg else if (gimple_code (stmt) != GIMPLE_DEBUG)
3691debfc3dSmrg size->non_call_stmts_on_hot_path++;
3701debfc3dSmrg if (((gimple_code (stmt) == GIMPLE_COND
3711debfc3dSmrg && (!constant_after_peeling (gimple_cond_lhs (stmt), stmt, loop)
372a2dc1f3fSmrg || !constant_after_peeling (gimple_cond_rhs (stmt), stmt,
3731debfc3dSmrg loop)))
3741debfc3dSmrg || (gimple_code (stmt) == GIMPLE_SWITCH
3751debfc3dSmrg && !constant_after_peeling (gimple_switch_index (
3761debfc3dSmrg as_a <gswitch *> (stmt)),
3771debfc3dSmrg stmt, loop)))
3781debfc3dSmrg && (!exit || bb != exit->src))
3791debfc3dSmrg size->num_branches_on_hot_path++;
3801debfc3dSmrg }
3811debfc3dSmrg }
3821debfc3dSmrg path.release ();
3831debfc3dSmrg if (dump_file && (dump_flags & TDF_DETAILS))
3841debfc3dSmrg fprintf (dump_file, "size: %i-%i, last_iteration: %i-%i\n", size->overall,
3851debfc3dSmrg size->eliminated_by_peeling, size->last_iteration,
3861debfc3dSmrg size->last_iteration_eliminated_by_peeling);
3871debfc3dSmrg
3881debfc3dSmrg free (body);
3891debfc3dSmrg return false;
3901debfc3dSmrg }
3911debfc3dSmrg
3921debfc3dSmrg /* Estimate number of insns of completely unrolled loop.
3931debfc3dSmrg It is (NUNROLL + 1) * size of loop body with taking into account
3941debfc3dSmrg the fact that in last copy everything after exit conditional
3951debfc3dSmrg is dead and that some instructions will be eliminated after
3961debfc3dSmrg peeling.
3971debfc3dSmrg
3981debfc3dSmrg Loop body is likely going to simplify further, this is difficult
3991debfc3dSmrg to guess, we just decrease the result by 1/3. */
4001debfc3dSmrg
4011debfc3dSmrg static unsigned HOST_WIDE_INT
estimated_unrolled_size(struct loop_size * size,unsigned HOST_WIDE_INT nunroll)4021debfc3dSmrg estimated_unrolled_size (struct loop_size *size,
4031debfc3dSmrg unsigned HOST_WIDE_INT nunroll)
4041debfc3dSmrg {
4051debfc3dSmrg HOST_WIDE_INT unr_insns = ((nunroll)
4061debfc3dSmrg * (HOST_WIDE_INT) (size->overall
4071debfc3dSmrg - size->eliminated_by_peeling));
4081debfc3dSmrg if (!nunroll)
4091debfc3dSmrg unr_insns = 0;
4101debfc3dSmrg unr_insns += size->last_iteration - size->last_iteration_eliminated_by_peeling;
4111debfc3dSmrg
4121debfc3dSmrg unr_insns = unr_insns * 2 / 3;
4131debfc3dSmrg if (unr_insns <= 0)
4141debfc3dSmrg unr_insns = 1;
4151debfc3dSmrg
4161debfc3dSmrg return unr_insns;
4171debfc3dSmrg }
4181debfc3dSmrg
4191debfc3dSmrg /* Loop LOOP is known to not loop. See if there is an edge in the loop
4201debfc3dSmrg body that can be remove to make the loop to always exit and at
4211debfc3dSmrg the same time it does not make any code potentially executed
4221debfc3dSmrg during the last iteration dead.
4231debfc3dSmrg
4241debfc3dSmrg After complete unrolling we still may get rid of the conditional
4251debfc3dSmrg on the exit in the last copy even if we have no idea what it does.
4261debfc3dSmrg This is quite common case for loops of form
4271debfc3dSmrg
4281debfc3dSmrg int a[5];
4291debfc3dSmrg for (i=0;i<b;i++)
4301debfc3dSmrg a[i]=0;
4311debfc3dSmrg
4321debfc3dSmrg Here we prove the loop to iterate 5 times but we do not know
4331debfc3dSmrg it from induction variable.
4341debfc3dSmrg
4351debfc3dSmrg For now we handle only simple case where there is exit condition
4361debfc3dSmrg just before the latch block and the latch block contains no statements
4371debfc3dSmrg with side effect that may otherwise terminate the execution of loop
4381debfc3dSmrg (such as by EH or by terminating the program or longjmp).
4391debfc3dSmrg
4401debfc3dSmrg In the general case we may want to cancel the paths leading to statements
4411debfc3dSmrg loop-niter identified as having undefined effect in the last iteration.
4421debfc3dSmrg The other cases are hopefully rare and will be cleaned up later. */
4431debfc3dSmrg
4441debfc3dSmrg static edge
loop_edge_to_cancel(class loop * loop)445*8feb0f0bSmrg loop_edge_to_cancel (class loop *loop)
4461debfc3dSmrg {
4471debfc3dSmrg vec<edge> exits;
4481debfc3dSmrg unsigned i;
4491debfc3dSmrg edge edge_to_cancel;
4501debfc3dSmrg gimple_stmt_iterator gsi;
4511debfc3dSmrg
4521debfc3dSmrg /* We want only one predecestor of the loop. */
4531debfc3dSmrg if (EDGE_COUNT (loop->latch->preds) > 1)
4541debfc3dSmrg return NULL;
4551debfc3dSmrg
4561debfc3dSmrg exits = get_loop_exit_edges (loop);
4571debfc3dSmrg
4581debfc3dSmrg FOR_EACH_VEC_ELT (exits, i, edge_to_cancel)
4591debfc3dSmrg {
4601debfc3dSmrg /* Find the other edge than the loop exit
4611debfc3dSmrg leaving the conditoinal. */
4621debfc3dSmrg if (EDGE_COUNT (edge_to_cancel->src->succs) != 2)
4631debfc3dSmrg continue;
4641debfc3dSmrg if (EDGE_SUCC (edge_to_cancel->src, 0) == edge_to_cancel)
4651debfc3dSmrg edge_to_cancel = EDGE_SUCC (edge_to_cancel->src, 1);
4661debfc3dSmrg else
4671debfc3dSmrg edge_to_cancel = EDGE_SUCC (edge_to_cancel->src, 0);
4681debfc3dSmrg
4691debfc3dSmrg /* We only can handle conditionals. */
4701debfc3dSmrg if (!(edge_to_cancel->flags & (EDGE_TRUE_VALUE | EDGE_FALSE_VALUE)))
4711debfc3dSmrg continue;
4721debfc3dSmrg
4731debfc3dSmrg /* We should never have conditionals in the loop latch. */
4741debfc3dSmrg gcc_assert (edge_to_cancel->dest != loop->header);
4751debfc3dSmrg
4761debfc3dSmrg /* Check that it leads to loop latch. */
4771debfc3dSmrg if (edge_to_cancel->dest != loop->latch)
4781debfc3dSmrg continue;
4791debfc3dSmrg
4801debfc3dSmrg exits.release ();
4811debfc3dSmrg
4821debfc3dSmrg /* Verify that the code in loop latch does nothing that may end program
4831debfc3dSmrg execution without really reaching the exit. This may include
4841debfc3dSmrg non-pure/const function calls, EH statements, volatile ASMs etc. */
4851debfc3dSmrg for (gsi = gsi_start_bb (loop->latch); !gsi_end_p (gsi); gsi_next (&gsi))
4861debfc3dSmrg if (gimple_has_side_effects (gsi_stmt (gsi)))
4871debfc3dSmrg return NULL;
4881debfc3dSmrg return edge_to_cancel;
4891debfc3dSmrg }
4901debfc3dSmrg exits.release ();
4911debfc3dSmrg return NULL;
4921debfc3dSmrg }
4931debfc3dSmrg
4941debfc3dSmrg /* Remove all tests for exits that are known to be taken after LOOP was
4951debfc3dSmrg peeled NPEELED times. Put gcc_unreachable before every statement
4961debfc3dSmrg known to not be executed. */
4971debfc3dSmrg
4981debfc3dSmrg static bool
remove_exits_and_undefined_stmts(class loop * loop,unsigned int npeeled)499*8feb0f0bSmrg remove_exits_and_undefined_stmts (class loop *loop, unsigned int npeeled)
5001debfc3dSmrg {
501*8feb0f0bSmrg class nb_iter_bound *elt;
5021debfc3dSmrg bool changed = false;
5031debfc3dSmrg
5041debfc3dSmrg for (elt = loop->bounds; elt; elt = elt->next)
5051debfc3dSmrg {
5061debfc3dSmrg /* If statement is known to be undefined after peeling, turn it
5071debfc3dSmrg into unreachable (or trap when debugging experience is supposed
5081debfc3dSmrg to be good). */
5091debfc3dSmrg if (!elt->is_exit
5101debfc3dSmrg && wi::ltu_p (elt->bound, npeeled))
5111debfc3dSmrg {
5121debfc3dSmrg gimple_stmt_iterator gsi = gsi_for_stmt (elt->stmt);
5131debfc3dSmrg gcall *stmt = gimple_build_call
5141debfc3dSmrg (builtin_decl_implicit (BUILT_IN_UNREACHABLE), 0);
5151debfc3dSmrg gimple_set_location (stmt, gimple_location (elt->stmt));
5161debfc3dSmrg gsi_insert_before (&gsi, stmt, GSI_NEW_STMT);
5171debfc3dSmrg split_block (gimple_bb (stmt), stmt);
5181debfc3dSmrg changed = true;
5191debfc3dSmrg if (dump_file && (dump_flags & TDF_DETAILS))
5201debfc3dSmrg {
5211debfc3dSmrg fprintf (dump_file, "Forced statement unreachable: ");
522a2dc1f3fSmrg print_gimple_stmt (dump_file, elt->stmt, 0);
5231debfc3dSmrg }
5241debfc3dSmrg }
5251debfc3dSmrg /* If we know the exit will be taken after peeling, update. */
5261debfc3dSmrg else if (elt->is_exit
5271debfc3dSmrg && wi::leu_p (elt->bound, npeeled))
5281debfc3dSmrg {
5291debfc3dSmrg basic_block bb = gimple_bb (elt->stmt);
5301debfc3dSmrg edge exit_edge = EDGE_SUCC (bb, 0);
5311debfc3dSmrg
5321debfc3dSmrg if (dump_file && (dump_flags & TDF_DETAILS))
5331debfc3dSmrg {
5341debfc3dSmrg fprintf (dump_file, "Forced exit to be taken: ");
535a2dc1f3fSmrg print_gimple_stmt (dump_file, elt->stmt, 0);
5361debfc3dSmrg }
5371debfc3dSmrg if (!loop_exit_edge_p (loop, exit_edge))
5381debfc3dSmrg exit_edge = EDGE_SUCC (bb, 1);
539a2dc1f3fSmrg exit_edge->probability = profile_probability::always ();
5401debfc3dSmrg gcc_checking_assert (loop_exit_edge_p (loop, exit_edge));
5411debfc3dSmrg gcond *cond_stmt = as_a <gcond *> (elt->stmt);
5421debfc3dSmrg if (exit_edge->flags & EDGE_TRUE_VALUE)
5431debfc3dSmrg gimple_cond_make_true (cond_stmt);
5441debfc3dSmrg else
5451debfc3dSmrg gimple_cond_make_false (cond_stmt);
5461debfc3dSmrg update_stmt (cond_stmt);
5471debfc3dSmrg changed = true;
5481debfc3dSmrg }
5491debfc3dSmrg }
5501debfc3dSmrg return changed;
5511debfc3dSmrg }
5521debfc3dSmrg
5531debfc3dSmrg /* Remove all exits that are known to be never taken because of the loop bound
5541debfc3dSmrg discovered. */
5551debfc3dSmrg
5561debfc3dSmrg static bool
remove_redundant_iv_tests(class loop * loop)557*8feb0f0bSmrg remove_redundant_iv_tests (class loop *loop)
5581debfc3dSmrg {
559*8feb0f0bSmrg class nb_iter_bound *elt;
5601debfc3dSmrg bool changed = false;
5611debfc3dSmrg
5621debfc3dSmrg if (!loop->any_upper_bound)
5631debfc3dSmrg return false;
5641debfc3dSmrg for (elt = loop->bounds; elt; elt = elt->next)
5651debfc3dSmrg {
5661debfc3dSmrg /* Exit is pointless if it won't be taken before loop reaches
5671debfc3dSmrg upper bound. */
5681debfc3dSmrg if (elt->is_exit && loop->any_upper_bound
5691debfc3dSmrg && wi::ltu_p (loop->nb_iterations_upper_bound, elt->bound))
5701debfc3dSmrg {
5711debfc3dSmrg basic_block bb = gimple_bb (elt->stmt);
5721debfc3dSmrg edge exit_edge = EDGE_SUCC (bb, 0);
573*8feb0f0bSmrg class tree_niter_desc niter;
5741debfc3dSmrg
5751debfc3dSmrg if (!loop_exit_edge_p (loop, exit_edge))
5761debfc3dSmrg exit_edge = EDGE_SUCC (bb, 1);
5771debfc3dSmrg
5781debfc3dSmrg /* Only when we know the actual number of iterations, not
5791debfc3dSmrg just a bound, we can remove the exit. */
5801debfc3dSmrg if (!number_of_iterations_exit (loop, exit_edge,
5811debfc3dSmrg &niter, false, false)
5821debfc3dSmrg || !integer_onep (niter.assumptions)
5831debfc3dSmrg || !integer_zerop (niter.may_be_zero)
5841debfc3dSmrg || !niter.niter
5851debfc3dSmrg || TREE_CODE (niter.niter) != INTEGER_CST
5861debfc3dSmrg || !wi::ltu_p (loop->nb_iterations_upper_bound,
5871debfc3dSmrg wi::to_widest (niter.niter)))
5881debfc3dSmrg continue;
5891debfc3dSmrg
5901debfc3dSmrg if (dump_file && (dump_flags & TDF_DETAILS))
5911debfc3dSmrg {
5921debfc3dSmrg fprintf (dump_file, "Removed pointless exit: ");
593a2dc1f3fSmrg print_gimple_stmt (dump_file, elt->stmt, 0);
5941debfc3dSmrg }
5951debfc3dSmrg gcond *cond_stmt = as_a <gcond *> (elt->stmt);
5961debfc3dSmrg if (exit_edge->flags & EDGE_TRUE_VALUE)
5971debfc3dSmrg gimple_cond_make_false (cond_stmt);
5981debfc3dSmrg else
5991debfc3dSmrg gimple_cond_make_true (cond_stmt);
6001debfc3dSmrg update_stmt (cond_stmt);
6011debfc3dSmrg changed = true;
6021debfc3dSmrg }
6031debfc3dSmrg }
6041debfc3dSmrg return changed;
6051debfc3dSmrg }
6061debfc3dSmrg
6071debfc3dSmrg /* Stores loops that will be unlooped and edges that will be removed
6081debfc3dSmrg after we process whole loop tree. */
6091debfc3dSmrg static vec<loop_p> loops_to_unloop;
6101debfc3dSmrg static vec<int> loops_to_unloop_nunroll;
6111debfc3dSmrg static vec<edge> edges_to_remove;
6121debfc3dSmrg /* Stores loops that has been peeled. */
6131debfc3dSmrg static bitmap peeled_loops;
6141debfc3dSmrg
6151debfc3dSmrg /* Cancel all fully unrolled loops by putting __builtin_unreachable
6161debfc3dSmrg on the latch edge.
6171debfc3dSmrg We do it after all unrolling since unlooping moves basic blocks
6181debfc3dSmrg across loop boundaries trashing loop closed SSA form as well
6191debfc3dSmrg as SCEV info needed to be intact during unrolling.
6201debfc3dSmrg
6211debfc3dSmrg IRRED_INVALIDATED is used to bookkeep if information about
6221debfc3dSmrg irreducible regions may become invalid as a result
6231debfc3dSmrg of the transformation.
6241debfc3dSmrg LOOP_CLOSED_SSA_INVALIDATED is used to bookkepp the case
6251debfc3dSmrg when we need to go into loop closed SSA form. */
6261debfc3dSmrg
6271debfc3dSmrg static void
unloop_loops(bitmap loop_closed_ssa_invalidated,bool * irred_invalidated)6281debfc3dSmrg unloop_loops (bitmap loop_closed_ssa_invalidated,
6291debfc3dSmrg bool *irred_invalidated)
6301debfc3dSmrg {
6311debfc3dSmrg while (loops_to_unloop.length ())
6321debfc3dSmrg {
633*8feb0f0bSmrg class loop *loop = loops_to_unloop.pop ();
6341debfc3dSmrg int n_unroll = loops_to_unloop_nunroll.pop ();
6351debfc3dSmrg basic_block latch = loop->latch;
6361debfc3dSmrg edge latch_edge = loop_latch_edge (loop);
6371debfc3dSmrg int flags = latch_edge->flags;
6381debfc3dSmrg location_t locus = latch_edge->goto_locus;
6391debfc3dSmrg gcall *stmt;
6401debfc3dSmrg gimple_stmt_iterator gsi;
6411debfc3dSmrg
6421debfc3dSmrg remove_exits_and_undefined_stmts (loop, n_unroll);
6431debfc3dSmrg
6441debfc3dSmrg /* Unloop destroys the latch edge. */
6451debfc3dSmrg unloop (loop, irred_invalidated, loop_closed_ssa_invalidated);
6461debfc3dSmrg
6471debfc3dSmrg /* Create new basic block for the latch edge destination and wire
6481debfc3dSmrg it in. */
6491debfc3dSmrg stmt = gimple_build_call (builtin_decl_implicit (BUILT_IN_UNREACHABLE), 0);
6501debfc3dSmrg latch_edge = make_edge (latch, create_basic_block (NULL, NULL, latch), flags);
651a2dc1f3fSmrg latch_edge->probability = profile_probability::never ();
6521debfc3dSmrg latch_edge->flags |= flags;
6531debfc3dSmrg latch_edge->goto_locus = locus;
6541debfc3dSmrg
6551debfc3dSmrg add_bb_to_loop (latch_edge->dest, current_loops->tree_root);
656a2dc1f3fSmrg latch_edge->dest->count = profile_count::zero ();
6571debfc3dSmrg set_immediate_dominator (CDI_DOMINATORS, latch_edge->dest, latch_edge->src);
6581debfc3dSmrg
6591debfc3dSmrg gsi = gsi_start_bb (latch_edge->dest);
6601debfc3dSmrg gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
6611debfc3dSmrg }
6621debfc3dSmrg loops_to_unloop.release ();
6631debfc3dSmrg loops_to_unloop_nunroll.release ();
6641debfc3dSmrg
665a2dc1f3fSmrg /* Remove edges in peeled copies. Given remove_path removes dominated
666a2dc1f3fSmrg regions we need to cope with removal of already removed paths. */
6671debfc3dSmrg unsigned i;
6681debfc3dSmrg edge e;
669a2dc1f3fSmrg auto_vec<int, 20> src_bbs;
670a2dc1f3fSmrg src_bbs.reserve_exact (edges_to_remove.length ());
6711debfc3dSmrg FOR_EACH_VEC_ELT (edges_to_remove, i, e)
672a2dc1f3fSmrg src_bbs.quick_push (e->src->index);
673a2dc1f3fSmrg FOR_EACH_VEC_ELT (edges_to_remove, i, e)
674a2dc1f3fSmrg if (BASIC_BLOCK_FOR_FN (cfun, src_bbs[i]))
6751debfc3dSmrg {
676a2dc1f3fSmrg bool ok = remove_path (e, irred_invalidated,
677a2dc1f3fSmrg loop_closed_ssa_invalidated);
6781debfc3dSmrg gcc_assert (ok);
6791debfc3dSmrg }
6801debfc3dSmrg edges_to_remove.release ();
6811debfc3dSmrg }
6821debfc3dSmrg
6831debfc3dSmrg /* Tries to unroll LOOP completely, i.e. NITER times.
6841debfc3dSmrg UL determines which loops we are allowed to unroll.
6851debfc3dSmrg EXIT is the exit of the loop that should be eliminated.
6861debfc3dSmrg MAXITER specfy bound on number of iterations, -1 if it is
6871debfc3dSmrg not known or too large for HOST_WIDE_INT. The location
6881debfc3dSmrg LOCUS corresponding to the loop is used when emitting
6891debfc3dSmrg a summary of the unroll to the dump file. */
6901debfc3dSmrg
6911debfc3dSmrg static bool
try_unroll_loop_completely(class loop * loop,edge exit,tree niter,bool may_be_zero,enum unroll_level ul,HOST_WIDE_INT maxiter,dump_user_location_t locus,bool allow_peel)692*8feb0f0bSmrg try_unroll_loop_completely (class loop *loop,
693a2dc1f3fSmrg edge exit, tree niter, bool may_be_zero,
6941debfc3dSmrg enum unroll_level ul,
6951debfc3dSmrg HOST_WIDE_INT maxiter,
696c0a68be4Smrg dump_user_location_t locus, bool allow_peel)
6971debfc3dSmrg {
698a2dc1f3fSmrg unsigned HOST_WIDE_INT n_unroll = 0;
6991debfc3dSmrg bool n_unroll_found = false;
7001debfc3dSmrg edge edge_to_cancel = NULL;
7011debfc3dSmrg
7021debfc3dSmrg /* See if we proved number of iterations to be low constant.
7031debfc3dSmrg
7041debfc3dSmrg EXIT is an edge that will be removed in all but last iteration of
7051debfc3dSmrg the loop.
7061debfc3dSmrg
7071debfc3dSmrg EDGE_TO_CACNEL is an edge that will be removed from the last iteration
7081debfc3dSmrg of the unrolled sequence and is expected to make the final loop not
7091debfc3dSmrg rolling.
7101debfc3dSmrg
7111debfc3dSmrg If the number of execution of loop is determined by standard induction
7121debfc3dSmrg variable test, then EXIT and EDGE_TO_CANCEL are the two edges leaving
7131debfc3dSmrg from the iv test. */
7141debfc3dSmrg if (tree_fits_uhwi_p (niter))
7151debfc3dSmrg {
7161debfc3dSmrg n_unroll = tree_to_uhwi (niter);
7171debfc3dSmrg n_unroll_found = true;
7181debfc3dSmrg edge_to_cancel = EDGE_SUCC (exit->src, 0);
7191debfc3dSmrg if (edge_to_cancel == exit)
7201debfc3dSmrg edge_to_cancel = EDGE_SUCC (exit->src, 1);
7211debfc3dSmrg }
7221debfc3dSmrg /* We do not know the number of iterations and thus we cannot eliminate
7231debfc3dSmrg the EXIT edge. */
7241debfc3dSmrg else
7251debfc3dSmrg exit = NULL;
7261debfc3dSmrg
7271debfc3dSmrg /* See if we can improve our estimate by using recorded loop bounds. */
728a2dc1f3fSmrg if ((allow_peel || maxiter == 0 || ul == UL_NO_GROWTH)
729a2dc1f3fSmrg && maxiter >= 0
7301debfc3dSmrg && (!n_unroll_found || (unsigned HOST_WIDE_INT)maxiter < n_unroll))
7311debfc3dSmrg {
7321debfc3dSmrg n_unroll = maxiter;
7331debfc3dSmrg n_unroll_found = true;
7341debfc3dSmrg /* Loop terminates before the IV variable test, so we cannot
7351debfc3dSmrg remove it in the last iteration. */
7361debfc3dSmrg edge_to_cancel = NULL;
7371debfc3dSmrg }
7381debfc3dSmrg
7391debfc3dSmrg if (!n_unroll_found)
7401debfc3dSmrg return false;
7411debfc3dSmrg
742a2dc1f3fSmrg if (!loop->unroll
743*8feb0f0bSmrg && n_unroll > (unsigned) param_max_completely_peel_times)
7441debfc3dSmrg {
7451debfc3dSmrg if (dump_file && (dump_flags & TDF_DETAILS))
7461debfc3dSmrg fprintf (dump_file, "Not unrolling loop %d "
7471debfc3dSmrg "(--param max-completely-peel-times limit reached).\n",
7481debfc3dSmrg loop->num);
7491debfc3dSmrg return false;
7501debfc3dSmrg }
7511debfc3dSmrg
7521debfc3dSmrg if (!edge_to_cancel)
7531debfc3dSmrg edge_to_cancel = loop_edge_to_cancel (loop);
7541debfc3dSmrg
7551debfc3dSmrg if (n_unroll)
7561debfc3dSmrg {
7571debfc3dSmrg if (ul == UL_SINGLE_ITER)
7581debfc3dSmrg return false;
7591debfc3dSmrg
760a2dc1f3fSmrg if (loop->unroll)
761a2dc1f3fSmrg {
762a2dc1f3fSmrg /* If the unrolling factor is too large, bail out. */
763a2dc1f3fSmrg if (n_unroll > (unsigned)loop->unroll)
764a2dc1f3fSmrg {
765a2dc1f3fSmrg if (dump_file && (dump_flags & TDF_DETAILS))
766a2dc1f3fSmrg fprintf (dump_file,
767a2dc1f3fSmrg "Not unrolling loop %d: "
768a2dc1f3fSmrg "user didn't want it unrolled completely.\n",
769a2dc1f3fSmrg loop->num);
770a2dc1f3fSmrg return false;
771a2dc1f3fSmrg }
772a2dc1f3fSmrg }
773a2dc1f3fSmrg else
774a2dc1f3fSmrg {
775a2dc1f3fSmrg struct loop_size size;
7761debfc3dSmrg /* EXIT can be removed only if we are sure it passes first N_UNROLL
7771debfc3dSmrg iterations. */
7781debfc3dSmrg bool remove_exit = (exit && niter
7791debfc3dSmrg && TREE_CODE (niter) == INTEGER_CST
7801debfc3dSmrg && wi::leu_p (n_unroll, wi::to_widest (niter)));
781a2dc1f3fSmrg bool large
782a2dc1f3fSmrg = tree_estimate_loop_size
7831debfc3dSmrg (loop, remove_exit ? exit : NULL, edge_to_cancel, &size,
784*8feb0f0bSmrg param_max_completely_peeled_insns);
7851debfc3dSmrg if (large)
7861debfc3dSmrg {
7871debfc3dSmrg if (dump_file && (dump_flags & TDF_DETAILS))
7881debfc3dSmrg fprintf (dump_file, "Not unrolling loop %d: it is too large.\n",
7891debfc3dSmrg loop->num);
7901debfc3dSmrg return false;
7911debfc3dSmrg }
7921debfc3dSmrg
793a2dc1f3fSmrg unsigned HOST_WIDE_INT ninsns = size.overall;
794a2dc1f3fSmrg unsigned HOST_WIDE_INT unr_insns
795a2dc1f3fSmrg = estimated_unrolled_size (&size, n_unroll);
7961debfc3dSmrg if (dump_file && (dump_flags & TDF_DETAILS))
7971debfc3dSmrg {
7981debfc3dSmrg fprintf (dump_file, " Loop size: %d\n", (int) ninsns);
7991debfc3dSmrg fprintf (dump_file, " Estimated size after unrolling: %d\n",
8001debfc3dSmrg (int) unr_insns);
8011debfc3dSmrg }
8021debfc3dSmrg
803a2dc1f3fSmrg /* If the code is going to shrink, we don't need to be extra
804a2dc1f3fSmrg cautious on guessing if the unrolling is going to be
805a2dc1f3fSmrg profitable. */
8061debfc3dSmrg if (unr_insns
807a2dc1f3fSmrg /* If there is IV variable that will become constant, we
808a2dc1f3fSmrg save one instruction in the loop prologue we do not
809a2dc1f3fSmrg account otherwise. */
8101debfc3dSmrg <= ninsns + (size.constant_iv != false))
8111debfc3dSmrg ;
812a2dc1f3fSmrg /* We unroll only inner loops, because we do not consider it
813a2dc1f3fSmrg profitable otheriwse. We still can cancel loopback edge
814a2dc1f3fSmrg of not rolling loop; this is always a good idea. */
8151debfc3dSmrg else if (ul == UL_NO_GROWTH)
8161debfc3dSmrg {
8171debfc3dSmrg if (dump_file && (dump_flags & TDF_DETAILS))
8181debfc3dSmrg fprintf (dump_file, "Not unrolling loop %d: size would grow.\n",
8191debfc3dSmrg loop->num);
8201debfc3dSmrg return false;
8211debfc3dSmrg }
822a2dc1f3fSmrg /* Outer loops tend to be less interesting candidates for
823a2dc1f3fSmrg complete unrolling unless we can do a lot of propagation
824a2dc1f3fSmrg into the inner loop body. For now we disable outer loop
825a2dc1f3fSmrg unrolling when the code would grow. */
8261debfc3dSmrg else if (loop->inner)
8271debfc3dSmrg {
8281debfc3dSmrg if (dump_file && (dump_flags & TDF_DETAILS))
8291debfc3dSmrg fprintf (dump_file, "Not unrolling loop %d: "
8301debfc3dSmrg "it is not innermost and code would grow.\n",
8311debfc3dSmrg loop->num);
8321debfc3dSmrg return false;
8331debfc3dSmrg }
8341debfc3dSmrg /* If there is call on a hot path through the loop, then
8351debfc3dSmrg there is most probably not much to optimize. */
8361debfc3dSmrg else if (size.num_non_pure_calls_on_hot_path)
8371debfc3dSmrg {
8381debfc3dSmrg if (dump_file && (dump_flags & TDF_DETAILS))
8391debfc3dSmrg fprintf (dump_file, "Not unrolling loop %d: "
8401debfc3dSmrg "contains call and code would grow.\n",
8411debfc3dSmrg loop->num);
8421debfc3dSmrg return false;
8431debfc3dSmrg }
844a2dc1f3fSmrg /* If there is pure/const call in the function, then we can
845a2dc1f3fSmrg still optimize the unrolled loop body if it contains some
846a2dc1f3fSmrg other interesting code than the calls and code storing or
847a2dc1f3fSmrg cumulating the return value. */
8481debfc3dSmrg else if (size.num_pure_calls_on_hot_path
849a2dc1f3fSmrg /* One IV increment, one test, one ivtmp store and
850a2dc1f3fSmrg one useful stmt. That is about minimal loop
8511debfc3dSmrg doing pure call. */
8521debfc3dSmrg && (size.non_call_stmts_on_hot_path
8531debfc3dSmrg <= 3 + size.num_pure_calls_on_hot_path))
8541debfc3dSmrg {
8551debfc3dSmrg if (dump_file && (dump_flags & TDF_DETAILS))
8561debfc3dSmrg fprintf (dump_file, "Not unrolling loop %d: "
8571debfc3dSmrg "contains just pure calls and code would grow.\n",
8581debfc3dSmrg loop->num);
8591debfc3dSmrg return false;
8601debfc3dSmrg }
861a2dc1f3fSmrg /* Complete unrolling is major win when control flow is
862a2dc1f3fSmrg removed and one big basic block is created. If the loop
863a2dc1f3fSmrg contains control flow the optimization may still be a win
864a2dc1f3fSmrg because of eliminating the loop overhead but it also may
865a2dc1f3fSmrg blow the branch predictor tables. Limit number of
866a2dc1f3fSmrg branches on the hot path through the peeled sequence. */
8671debfc3dSmrg else if (size.num_branches_on_hot_path * (int)n_unroll
868*8feb0f0bSmrg > param_max_peel_branches)
8691debfc3dSmrg {
8701debfc3dSmrg if (dump_file && (dump_flags & TDF_DETAILS))
8711debfc3dSmrg fprintf (dump_file, "Not unrolling loop %d: "
872a2dc1f3fSmrg "number of branches on hot path in the unrolled "
873a2dc1f3fSmrg "sequence reaches --param max-peel-branches limit.\n",
8741debfc3dSmrg loop->num);
8751debfc3dSmrg return false;
8761debfc3dSmrg }
8771debfc3dSmrg else if (unr_insns
878*8feb0f0bSmrg > (unsigned) param_max_completely_peeled_insns)
8791debfc3dSmrg {
8801debfc3dSmrg if (dump_file && (dump_flags & TDF_DETAILS))
8811debfc3dSmrg fprintf (dump_file, "Not unrolling loop %d: "
882a2dc1f3fSmrg "number of insns in the unrolled sequence reaches "
883a2dc1f3fSmrg "--param max-completely-peeled-insns limit.\n",
8841debfc3dSmrg loop->num);
8851debfc3dSmrg return false;
8861debfc3dSmrg }
887a2dc1f3fSmrg }
8881debfc3dSmrg
889*8feb0f0bSmrg if (!dbg_cnt (gimple_unroll))
890*8feb0f0bSmrg return false;
891*8feb0f0bSmrg
8921debfc3dSmrg initialize_original_copy_tables ();
8931debfc3dSmrg auto_sbitmap wont_exit (n_unroll + 1);
8941debfc3dSmrg if (exit && niter
8951debfc3dSmrg && TREE_CODE (niter) == INTEGER_CST
8961debfc3dSmrg && wi::leu_p (n_unroll, wi::to_widest (niter)))
8971debfc3dSmrg {
8981debfc3dSmrg bitmap_ones (wont_exit);
8991debfc3dSmrg if (wi::eq_p (wi::to_widest (niter), n_unroll)
9001debfc3dSmrg || edge_to_cancel)
9011debfc3dSmrg bitmap_clear_bit (wont_exit, 0);
9021debfc3dSmrg }
9031debfc3dSmrg else
9041debfc3dSmrg {
9051debfc3dSmrg exit = NULL;
9061debfc3dSmrg bitmap_clear (wont_exit);
9071debfc3dSmrg }
908a2dc1f3fSmrg if (may_be_zero)
909a2dc1f3fSmrg bitmap_clear_bit (wont_exit, 1);
9101debfc3dSmrg
9111debfc3dSmrg if (!gimple_duplicate_loop_to_header_edge (loop, loop_preheader_edge (loop),
9121debfc3dSmrg n_unroll, wont_exit,
9131debfc3dSmrg exit, &edges_to_remove,
9141debfc3dSmrg DLTHE_FLAG_UPDATE_FREQ
9151debfc3dSmrg | DLTHE_FLAG_COMPLETTE_PEEL))
9161debfc3dSmrg {
9171debfc3dSmrg free_original_copy_tables ();
9181debfc3dSmrg if (dump_file && (dump_flags & TDF_DETAILS))
9191debfc3dSmrg fprintf (dump_file, "Failed to duplicate the loop\n");
9201debfc3dSmrg return false;
9211debfc3dSmrg }
9221debfc3dSmrg
9231debfc3dSmrg free_original_copy_tables ();
9241debfc3dSmrg }
9251debfc3dSmrg
9261debfc3dSmrg /* Remove the conditional from the last copy of the loop. */
9271debfc3dSmrg if (edge_to_cancel)
9281debfc3dSmrg {
9291debfc3dSmrg gcond *cond = as_a <gcond *> (last_stmt (edge_to_cancel->src));
9301debfc3dSmrg force_edge_cold (edge_to_cancel, true);
9311debfc3dSmrg if (edge_to_cancel->flags & EDGE_TRUE_VALUE)
9321debfc3dSmrg gimple_cond_make_false (cond);
9331debfc3dSmrg else
9341debfc3dSmrg gimple_cond_make_true (cond);
9351debfc3dSmrg update_stmt (cond);
936a2dc1f3fSmrg /* Do not remove the path, as doing so may remove outer loop and
937a2dc1f3fSmrg confuse bookkeeping code in tree_unroll_loops_completely. */
9381debfc3dSmrg }
9391debfc3dSmrg
9401debfc3dSmrg /* Store the loop for later unlooping and exit removal. */
9411debfc3dSmrg loops_to_unloop.safe_push (loop);
9421debfc3dSmrg loops_to_unloop_nunroll.safe_push (n_unroll);
9431debfc3dSmrg
9441debfc3dSmrg if (dump_enabled_p ())
9451debfc3dSmrg {
9461debfc3dSmrg if (!n_unroll)
9471debfc3dSmrg dump_printf_loc (MSG_OPTIMIZED_LOCATIONS | TDF_DETAILS, locus,
9481debfc3dSmrg "loop turned into non-loop; it never loops\n");
9491debfc3dSmrg else
9501debfc3dSmrg {
9511debfc3dSmrg dump_printf_loc (MSG_OPTIMIZED_LOCATIONS | TDF_DETAILS, locus,
9521debfc3dSmrg "loop with %d iterations completely unrolled",
953a2dc1f3fSmrg (int) n_unroll);
954a2dc1f3fSmrg if (loop->header->count.initialized_p ())
9551debfc3dSmrg dump_printf (MSG_OPTIMIZED_LOCATIONS | TDF_DETAILS,
9561debfc3dSmrg " (header execution count %d)",
957a2dc1f3fSmrg (int)loop->header->count.to_gcov_type ());
9581debfc3dSmrg dump_printf (MSG_OPTIMIZED_LOCATIONS | TDF_DETAILS, "\n");
9591debfc3dSmrg }
9601debfc3dSmrg }
9611debfc3dSmrg
9621debfc3dSmrg if (dump_file && (dump_flags & TDF_DETAILS))
9631debfc3dSmrg {
9641debfc3dSmrg if (exit)
9651debfc3dSmrg fprintf (dump_file, "Exit condition of peeled iterations was "
9661debfc3dSmrg "eliminated.\n");
9671debfc3dSmrg if (edge_to_cancel)
9681debfc3dSmrg fprintf (dump_file, "Last iteration exit edge was proved true.\n");
9691debfc3dSmrg else
9701debfc3dSmrg fprintf (dump_file, "Latch of last iteration was marked by "
9711debfc3dSmrg "__builtin_unreachable ().\n");
9721debfc3dSmrg }
9731debfc3dSmrg
9741debfc3dSmrg return true;
9751debfc3dSmrg }
9761debfc3dSmrg
9771debfc3dSmrg /* Return number of instructions after peeling. */
9781debfc3dSmrg static unsigned HOST_WIDE_INT
estimated_peeled_sequence_size(struct loop_size * size,unsigned HOST_WIDE_INT npeel)9791debfc3dSmrg estimated_peeled_sequence_size (struct loop_size *size,
9801debfc3dSmrg unsigned HOST_WIDE_INT npeel)
9811debfc3dSmrg {
9821debfc3dSmrg return MAX (npeel * (HOST_WIDE_INT) (size->overall
9831debfc3dSmrg - size->eliminated_by_peeling), 1);
9841debfc3dSmrg }
9851debfc3dSmrg
9861debfc3dSmrg /* If the loop is expected to iterate N times and is
9871debfc3dSmrg small enough, duplicate the loop body N+1 times before
9881debfc3dSmrg the loop itself. This way the hot path will never
9891debfc3dSmrg enter the loop.
9901debfc3dSmrg Parameters are the same as for try_unroll_loops_completely */
9911debfc3dSmrg
9921debfc3dSmrg static bool
try_peel_loop(class loop * loop,edge exit,tree niter,bool may_be_zero,HOST_WIDE_INT maxiter)993*8feb0f0bSmrg try_peel_loop (class loop *loop,
994a2dc1f3fSmrg edge exit, tree niter, bool may_be_zero,
9951debfc3dSmrg HOST_WIDE_INT maxiter)
9961debfc3dSmrg {
9971debfc3dSmrg HOST_WIDE_INT npeel;
9981debfc3dSmrg struct loop_size size;
9991debfc3dSmrg int peeled_size;
10001debfc3dSmrg
1001a2dc1f3fSmrg if (!flag_peel_loops
1002*8feb0f0bSmrg || param_max_peel_times <= 0
10031debfc3dSmrg || !peeled_loops)
10041debfc3dSmrg return false;
10051debfc3dSmrg
10061debfc3dSmrg if (bitmap_bit_p (peeled_loops, loop->num))
10071debfc3dSmrg {
10081debfc3dSmrg if (dump_file)
10091debfc3dSmrg fprintf (dump_file, "Not peeling: loop is already peeled\n");
10101debfc3dSmrg return false;
10111debfc3dSmrg }
10121debfc3dSmrg
1013a2dc1f3fSmrg /* We don't peel loops that will be unrolled as this can duplicate a
1014a2dc1f3fSmrg loop more times than the user requested. */
1015a2dc1f3fSmrg if (loop->unroll)
1016a2dc1f3fSmrg {
1017a2dc1f3fSmrg if (dump_file)
1018a2dc1f3fSmrg fprintf (dump_file, "Not peeling: user didn't want it peeled.\n");
1019a2dc1f3fSmrg return false;
1020a2dc1f3fSmrg }
1021a2dc1f3fSmrg
10221debfc3dSmrg /* Peel only innermost loops.
10231debfc3dSmrg While the code is perfectly capable of peeling non-innermost loops,
10241debfc3dSmrg the heuristics would probably need some improvements. */
10251debfc3dSmrg if (loop->inner)
10261debfc3dSmrg {
10271debfc3dSmrg if (dump_file)
10281debfc3dSmrg fprintf (dump_file, "Not peeling: outer loop\n");
10291debfc3dSmrg return false;
10301debfc3dSmrg }
10311debfc3dSmrg
10321debfc3dSmrg if (!optimize_loop_for_speed_p (loop))
10331debfc3dSmrg {
10341debfc3dSmrg if (dump_file)
10351debfc3dSmrg fprintf (dump_file, "Not peeling: cold loop\n");
10361debfc3dSmrg return false;
10371debfc3dSmrg }
10381debfc3dSmrg
10391debfc3dSmrg /* Check if there is an estimate on the number of iterations. */
10401debfc3dSmrg npeel = estimated_loop_iterations_int (loop);
10411debfc3dSmrg if (npeel < 0)
10421debfc3dSmrg npeel = likely_max_loop_iterations_int (loop);
10431debfc3dSmrg if (npeel < 0)
10441debfc3dSmrg {
10451debfc3dSmrg if (dump_file)
10461debfc3dSmrg fprintf (dump_file, "Not peeling: number of iterations is not "
10471debfc3dSmrg "estimated\n");
10481debfc3dSmrg return false;
10491debfc3dSmrg }
10501debfc3dSmrg if (maxiter >= 0 && maxiter <= npeel)
10511debfc3dSmrg {
10521debfc3dSmrg if (dump_file)
10531debfc3dSmrg fprintf (dump_file, "Not peeling: upper bound is known so can "
10541debfc3dSmrg "unroll completely\n");
10551debfc3dSmrg return false;
10561debfc3dSmrg }
10571debfc3dSmrg
10581debfc3dSmrg /* We want to peel estimated number of iterations + 1 (so we never
10591debfc3dSmrg enter the loop on quick path). Check against PARAM_MAX_PEEL_TIMES
10601debfc3dSmrg and be sure to avoid overflows. */
1061*8feb0f0bSmrg if (npeel > param_max_peel_times - 1)
10621debfc3dSmrg {
10631debfc3dSmrg if (dump_file)
10641debfc3dSmrg fprintf (dump_file, "Not peeling: rolls too much "
10651debfc3dSmrg "(%i + 1 > --param max-peel-times)\n", (int) npeel);
10661debfc3dSmrg return false;
10671debfc3dSmrg }
10681debfc3dSmrg npeel++;
10691debfc3dSmrg
10701debfc3dSmrg /* Check peeled loops size. */
10711debfc3dSmrg tree_estimate_loop_size (loop, exit, NULL, &size,
1072*8feb0f0bSmrg param_max_peeled_insns);
10731debfc3dSmrg if ((peeled_size = estimated_peeled_sequence_size (&size, (int) npeel))
1074*8feb0f0bSmrg > param_max_peeled_insns)
10751debfc3dSmrg {
10761debfc3dSmrg if (dump_file)
10771debfc3dSmrg fprintf (dump_file, "Not peeling: peeled sequence size is too large "
10781debfc3dSmrg "(%i insns > --param max-peel-insns)", peeled_size);
10791debfc3dSmrg return false;
10801debfc3dSmrg }
10811debfc3dSmrg
1082*8feb0f0bSmrg if (!dbg_cnt (gimple_unroll))
1083*8feb0f0bSmrg return false;
1084*8feb0f0bSmrg
10851debfc3dSmrg /* Duplicate possibly eliminating the exits. */
10861debfc3dSmrg initialize_original_copy_tables ();
10871debfc3dSmrg auto_sbitmap wont_exit (npeel + 1);
10881debfc3dSmrg if (exit && niter
10891debfc3dSmrg && TREE_CODE (niter) == INTEGER_CST
10901debfc3dSmrg && wi::leu_p (npeel, wi::to_widest (niter)))
10911debfc3dSmrg {
10921debfc3dSmrg bitmap_ones (wont_exit);
10931debfc3dSmrg bitmap_clear_bit (wont_exit, 0);
10941debfc3dSmrg }
10951debfc3dSmrg else
10961debfc3dSmrg {
10971debfc3dSmrg exit = NULL;
10981debfc3dSmrg bitmap_clear (wont_exit);
10991debfc3dSmrg }
1100a2dc1f3fSmrg if (may_be_zero)
1101a2dc1f3fSmrg bitmap_clear_bit (wont_exit, 1);
11021debfc3dSmrg if (!gimple_duplicate_loop_to_header_edge (loop, loop_preheader_edge (loop),
11031debfc3dSmrg npeel, wont_exit,
11041debfc3dSmrg exit, &edges_to_remove,
11051debfc3dSmrg DLTHE_FLAG_UPDATE_FREQ))
11061debfc3dSmrg {
11071debfc3dSmrg free_original_copy_tables ();
11081debfc3dSmrg return false;
11091debfc3dSmrg }
11101debfc3dSmrg free_original_copy_tables ();
11111debfc3dSmrg if (dump_file && (dump_flags & TDF_DETAILS))
11121debfc3dSmrg {
11131debfc3dSmrg fprintf (dump_file, "Peeled loop %d, %i times.\n",
11141debfc3dSmrg loop->num, (int) npeel);
11151debfc3dSmrg }
11161debfc3dSmrg if (loop->any_estimate)
11171debfc3dSmrg {
11181debfc3dSmrg if (wi::ltu_p (npeel, loop->nb_iterations_estimate))
11191debfc3dSmrg loop->nb_iterations_estimate -= npeel;
11201debfc3dSmrg else
11211debfc3dSmrg loop->nb_iterations_estimate = 0;
11221debfc3dSmrg }
11231debfc3dSmrg if (loop->any_upper_bound)
11241debfc3dSmrg {
11251debfc3dSmrg if (wi::ltu_p (npeel, loop->nb_iterations_upper_bound))
11261debfc3dSmrg loop->nb_iterations_upper_bound -= npeel;
11271debfc3dSmrg else
11281debfc3dSmrg loop->nb_iterations_upper_bound = 0;
11291debfc3dSmrg }
11301debfc3dSmrg if (loop->any_likely_upper_bound)
11311debfc3dSmrg {
11321debfc3dSmrg if (wi::ltu_p (npeel, loop->nb_iterations_likely_upper_bound))
11331debfc3dSmrg loop->nb_iterations_likely_upper_bound -= npeel;
11341debfc3dSmrg else
11351debfc3dSmrg {
11361debfc3dSmrg loop->any_estimate = true;
11371debfc3dSmrg loop->nb_iterations_estimate = 0;
11381debfc3dSmrg loop->nb_iterations_likely_upper_bound = 0;
11391debfc3dSmrg }
11401debfc3dSmrg }
1141a2dc1f3fSmrg profile_count entry_count = profile_count::zero ();
11421debfc3dSmrg
11431debfc3dSmrg edge e;
11441debfc3dSmrg edge_iterator ei;
11451debfc3dSmrg FOR_EACH_EDGE (e, ei, loop->header->preds)
11461debfc3dSmrg if (e->src != loop->latch)
11471debfc3dSmrg {
1148a2dc1f3fSmrg if (e->src->count.initialized_p ())
1149c0a68be4Smrg entry_count += e->src->count;
11501debfc3dSmrg gcc_assert (!flow_bb_inside_loop_p (loop, e->src));
11511debfc3dSmrg }
1152c0a68be4Smrg profile_probability p;
1153a2dc1f3fSmrg p = entry_count.probability_in (loop->header->count);
1154a2dc1f3fSmrg scale_loop_profile (loop, p, 0);
11551debfc3dSmrg bitmap_set_bit (peeled_loops, loop->num);
11561debfc3dSmrg return true;
11571debfc3dSmrg }
11581debfc3dSmrg /* Adds a canonical induction variable to LOOP if suitable.
11591debfc3dSmrg CREATE_IV is true if we may create a new iv. UL determines
11601debfc3dSmrg which loops we are allowed to completely unroll. If TRY_EVAL is true, we try
11611debfc3dSmrg to determine the number of iterations of a loop by direct evaluation.
11621debfc3dSmrg Returns true if cfg is changed. */
11631debfc3dSmrg
11641debfc3dSmrg static bool
canonicalize_loop_induction_variables(class loop * loop,bool create_iv,enum unroll_level ul,bool try_eval,bool allow_peel)1165*8feb0f0bSmrg canonicalize_loop_induction_variables (class loop *loop,
11661debfc3dSmrg bool create_iv, enum unroll_level ul,
1167a2dc1f3fSmrg bool try_eval, bool allow_peel)
11681debfc3dSmrg {
11691debfc3dSmrg edge exit = NULL;
11701debfc3dSmrg tree niter;
11711debfc3dSmrg HOST_WIDE_INT maxiter;
11721debfc3dSmrg bool modified = false;
1173c0a68be4Smrg dump_user_location_t locus;
1174*8feb0f0bSmrg class tree_niter_desc niter_desc;
1175a2dc1f3fSmrg bool may_be_zero = false;
11761debfc3dSmrg
1177a2dc1f3fSmrg /* For unrolling allow conditional constant or zero iterations, thus
1178a2dc1f3fSmrg perform loop-header copying on-the-fly. */
11791debfc3dSmrg exit = single_exit (loop);
1180a2dc1f3fSmrg niter = chrec_dont_know;
1181a2dc1f3fSmrg if (exit && number_of_iterations_exit (loop, exit, &niter_desc, false))
1182a2dc1f3fSmrg {
1183a2dc1f3fSmrg niter = niter_desc.niter;
1184a2dc1f3fSmrg may_be_zero
1185a2dc1f3fSmrg = niter_desc.may_be_zero && !integer_zerop (niter_desc.may_be_zero);
1186a2dc1f3fSmrg }
11871debfc3dSmrg if (TREE_CODE (niter) == INTEGER_CST)
1188c0a68be4Smrg locus = last_stmt (exit->src);
11891debfc3dSmrg else
11901debfc3dSmrg {
1191a2dc1f3fSmrg /* For non-constant niter fold may_be_zero into niter again. */
1192a2dc1f3fSmrg if (may_be_zero)
1193a2dc1f3fSmrg {
1194a2dc1f3fSmrg if (COMPARISON_CLASS_P (niter_desc.may_be_zero))
1195a2dc1f3fSmrg niter = fold_build3 (COND_EXPR, TREE_TYPE (niter),
1196a2dc1f3fSmrg niter_desc.may_be_zero,
1197a2dc1f3fSmrg build_int_cst (TREE_TYPE (niter), 0), niter);
1198a2dc1f3fSmrg else
1199a2dc1f3fSmrg niter = chrec_dont_know;
1200a2dc1f3fSmrg may_be_zero = false;
1201a2dc1f3fSmrg }
1202a2dc1f3fSmrg
12031debfc3dSmrg /* If the loop has more than one exit, try checking all of them
12041debfc3dSmrg for # of iterations determinable through scev. */
12051debfc3dSmrg if (!exit)
12061debfc3dSmrg niter = find_loop_niter (loop, &exit);
12071debfc3dSmrg
12081debfc3dSmrg /* Finally if everything else fails, try brute force evaluation. */
12091debfc3dSmrg if (try_eval
12101debfc3dSmrg && (chrec_contains_undetermined (niter)
12111debfc3dSmrg || TREE_CODE (niter) != INTEGER_CST))
12121debfc3dSmrg niter = find_loop_niter_by_eval (loop, &exit);
12131debfc3dSmrg
12141debfc3dSmrg if (exit)
1215c0a68be4Smrg locus = last_stmt (exit->src);
12161debfc3dSmrg
12171debfc3dSmrg if (TREE_CODE (niter) != INTEGER_CST)
12181debfc3dSmrg exit = NULL;
12191debfc3dSmrg }
12201debfc3dSmrg
12211debfc3dSmrg /* We work exceptionally hard here to estimate the bound
12221debfc3dSmrg by find_loop_niter_by_eval. Be sure to keep it for future. */
12231debfc3dSmrg if (niter && TREE_CODE (niter) == INTEGER_CST)
12241debfc3dSmrg {
1225*8feb0f0bSmrg vec<edge> exits = get_loop_exit_edges (loop);
12261debfc3dSmrg record_niter_bound (loop, wi::to_widest (niter),
1227*8feb0f0bSmrg exit == single_likely_exit (loop, exits), true);
1228*8feb0f0bSmrg exits.release ();
12291debfc3dSmrg }
12301debfc3dSmrg
12311debfc3dSmrg /* Force re-computation of loop bounds so we can remove redundant exits. */
12321debfc3dSmrg maxiter = max_loop_iterations_int (loop);
12331debfc3dSmrg
12341debfc3dSmrg if (dump_file && (dump_flags & TDF_DETAILS)
12351debfc3dSmrg && TREE_CODE (niter) == INTEGER_CST)
12361debfc3dSmrg {
12371debfc3dSmrg fprintf (dump_file, "Loop %d iterates ", loop->num);
12381debfc3dSmrg print_generic_expr (dump_file, niter, TDF_SLIM);
12391debfc3dSmrg fprintf (dump_file, " times.\n");
12401debfc3dSmrg }
12411debfc3dSmrg if (dump_file && (dump_flags & TDF_DETAILS)
12421debfc3dSmrg && maxiter >= 0)
12431debfc3dSmrg {
12441debfc3dSmrg fprintf (dump_file, "Loop %d iterates at most %i times.\n", loop->num,
12451debfc3dSmrg (int)maxiter);
12461debfc3dSmrg }
12471debfc3dSmrg if (dump_file && (dump_flags & TDF_DETAILS)
12481debfc3dSmrg && likely_max_loop_iterations_int (loop) >= 0)
12491debfc3dSmrg {
12501debfc3dSmrg fprintf (dump_file, "Loop %d likely iterates at most %i times.\n",
12511debfc3dSmrg loop->num, (int)likely_max_loop_iterations_int (loop));
12521debfc3dSmrg }
12531debfc3dSmrg
12541debfc3dSmrg /* Remove exits that are known to be never taken based on loop bound.
12551debfc3dSmrg Needs to be called after compilation of max_loop_iterations_int that
12561debfc3dSmrg populates the loop bounds. */
12571debfc3dSmrg modified |= remove_redundant_iv_tests (loop);
12581debfc3dSmrg
1259a2dc1f3fSmrg if (try_unroll_loop_completely (loop, exit, niter, may_be_zero, ul,
1260a2dc1f3fSmrg maxiter, locus, allow_peel))
12611debfc3dSmrg return true;
12621debfc3dSmrg
12631debfc3dSmrg if (create_iv
12641debfc3dSmrg && niter && !chrec_contains_undetermined (niter)
12651debfc3dSmrg && exit && just_once_each_iteration_p (loop, exit->src))
1266a2dc1f3fSmrg {
1267a2dc1f3fSmrg tree iv_niter = niter;
1268a2dc1f3fSmrg if (may_be_zero)
1269a2dc1f3fSmrg {
1270a2dc1f3fSmrg if (COMPARISON_CLASS_P (niter_desc.may_be_zero))
1271a2dc1f3fSmrg iv_niter = fold_build3 (COND_EXPR, TREE_TYPE (iv_niter),
1272a2dc1f3fSmrg niter_desc.may_be_zero,
1273a2dc1f3fSmrg build_int_cst (TREE_TYPE (iv_niter), 0),
1274a2dc1f3fSmrg iv_niter);
1275a2dc1f3fSmrg else
1276a2dc1f3fSmrg iv_niter = NULL_TREE;
1277a2dc1f3fSmrg }
1278a2dc1f3fSmrg if (iv_niter)
1279a2dc1f3fSmrg create_canonical_iv (loop, exit, iv_niter);
1280a2dc1f3fSmrg }
12811debfc3dSmrg
12821debfc3dSmrg if (ul == UL_ALL)
1283a2dc1f3fSmrg modified |= try_peel_loop (loop, exit, niter, may_be_zero, maxiter);
12841debfc3dSmrg
12851debfc3dSmrg return modified;
12861debfc3dSmrg }
12871debfc3dSmrg
12881debfc3dSmrg /* The main entry point of the pass. Adds canonical induction variables
12891debfc3dSmrg to the suitable loops. */
12901debfc3dSmrg
12911debfc3dSmrg unsigned int
canonicalize_induction_variables(void)12921debfc3dSmrg canonicalize_induction_variables (void)
12931debfc3dSmrg {
1294*8feb0f0bSmrg class loop *loop;
12951debfc3dSmrg bool changed = false;
12961debfc3dSmrg bool irred_invalidated = false;
12971debfc3dSmrg bitmap loop_closed_ssa_invalidated = BITMAP_ALLOC (NULL);
12981debfc3dSmrg
1299a2dc1f3fSmrg estimate_numbers_of_iterations (cfun);
13001debfc3dSmrg
13011debfc3dSmrg FOR_EACH_LOOP (loop, LI_FROM_INNERMOST)
13021debfc3dSmrg {
13031debfc3dSmrg changed |= canonicalize_loop_induction_variables (loop,
13041debfc3dSmrg true, UL_SINGLE_ITER,
1305a2dc1f3fSmrg true, false);
13061debfc3dSmrg }
13071debfc3dSmrg gcc_assert (!need_ssa_update_p (cfun));
13081debfc3dSmrg
13091debfc3dSmrg unloop_loops (loop_closed_ssa_invalidated, &irred_invalidated);
13101debfc3dSmrg if (irred_invalidated
13111debfc3dSmrg && loops_state_satisfies_p (LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS))
13121debfc3dSmrg mark_irreducible_loops ();
13131debfc3dSmrg
13141debfc3dSmrg /* Clean up the information about numbers of iterations, since brute force
13151debfc3dSmrg evaluation could reveal new information. */
1316a2dc1f3fSmrg free_numbers_of_iterations_estimates (cfun);
13171debfc3dSmrg scev_reset ();
13181debfc3dSmrg
13191debfc3dSmrg if (!bitmap_empty_p (loop_closed_ssa_invalidated))
13201debfc3dSmrg {
13211debfc3dSmrg gcc_checking_assert (loops_state_satisfies_p (LOOP_CLOSED_SSA));
13221debfc3dSmrg rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa);
13231debfc3dSmrg }
13241debfc3dSmrg BITMAP_FREE (loop_closed_ssa_invalidated);
13251debfc3dSmrg
13261debfc3dSmrg if (changed)
13271debfc3dSmrg return TODO_cleanup_cfg;
13281debfc3dSmrg return 0;
13291debfc3dSmrg }
13301debfc3dSmrg
13311debfc3dSmrg /* Process loops from innermost to outer, stopping at the innermost
13321debfc3dSmrg loop we unrolled. */
13331debfc3dSmrg
13341debfc3dSmrg static bool
tree_unroll_loops_completely_1(bool may_increase_size,bool unroll_outer,bitmap father_bbs,class loop * loop)13351debfc3dSmrg tree_unroll_loops_completely_1 (bool may_increase_size, bool unroll_outer,
1336*8feb0f0bSmrg bitmap father_bbs, class loop *loop)
13371debfc3dSmrg {
1338*8feb0f0bSmrg class loop *loop_father;
13391debfc3dSmrg bool changed = false;
1340*8feb0f0bSmrg class loop *inner;
13411debfc3dSmrg enum unroll_level ul;
1342a2dc1f3fSmrg unsigned num = number_of_loops (cfun);
13431debfc3dSmrg
1344a2dc1f3fSmrg /* Process inner loops first. Don't walk loops added by the recursive
1345a2dc1f3fSmrg calls because SSA form is not up-to-date. They can be handled in the
1346a2dc1f3fSmrg next iteration. */
1347c0a68be4Smrg bitmap child_father_bbs = NULL;
13481debfc3dSmrg for (inner = loop->inner; inner != NULL; inner = inner->next)
1349a2dc1f3fSmrg if ((unsigned) inner->num < num)
1350c0a68be4Smrg {
1351c0a68be4Smrg if (!child_father_bbs)
1352c0a68be4Smrg child_father_bbs = BITMAP_ALLOC (NULL);
1353c0a68be4Smrg if (tree_unroll_loops_completely_1 (may_increase_size, unroll_outer,
1354c0a68be4Smrg child_father_bbs, inner))
1355c0a68be4Smrg {
1356c0a68be4Smrg bitmap_ior_into (father_bbs, child_father_bbs);
1357c0a68be4Smrg bitmap_clear (child_father_bbs);
1358c0a68be4Smrg changed = true;
1359c0a68be4Smrg }
1360c0a68be4Smrg }
1361c0a68be4Smrg if (child_father_bbs)
1362c0a68be4Smrg BITMAP_FREE (child_father_bbs);
13631debfc3dSmrg
13641debfc3dSmrg /* If we changed an inner loop we cannot process outer loops in this
13651debfc3dSmrg iteration because SSA form is not up-to-date. Continue with
13661debfc3dSmrg siblings of outer loops instead. */
13671debfc3dSmrg if (changed)
1368c0a68be4Smrg {
1369c0a68be4Smrg /* If we are recorded as father clear all other fathers that
1370c0a68be4Smrg are necessarily covered already to avoid redundant work. */
1371c0a68be4Smrg if (bitmap_bit_p (father_bbs, loop->header->index))
1372c0a68be4Smrg {
1373c0a68be4Smrg bitmap_clear (father_bbs);
1374c0a68be4Smrg bitmap_set_bit (father_bbs, loop->header->index);
1375c0a68be4Smrg }
13761debfc3dSmrg return true;
1377c0a68be4Smrg }
13781debfc3dSmrg
13791debfc3dSmrg /* Don't unroll #pragma omp simd loops until the vectorizer
13801debfc3dSmrg attempts to vectorize those. */
13811debfc3dSmrg if (loop->force_vectorize)
13821debfc3dSmrg return false;
13831debfc3dSmrg
13841debfc3dSmrg /* Try to unroll this loop. */
13851debfc3dSmrg loop_father = loop_outer (loop);
13861debfc3dSmrg if (!loop_father)
13871debfc3dSmrg return false;
13881debfc3dSmrg
1389a2dc1f3fSmrg if (loop->unroll > 1)
1390a2dc1f3fSmrg ul = UL_ALL;
1391a2dc1f3fSmrg else if (may_increase_size && optimize_loop_nest_for_speed_p (loop)
13921debfc3dSmrg /* Unroll outermost loops only if asked to do so or they do
13931debfc3dSmrg not cause code growth. */
13941debfc3dSmrg && (unroll_outer || loop_outer (loop_father)))
13951debfc3dSmrg ul = UL_ALL;
13961debfc3dSmrg else
13971debfc3dSmrg ul = UL_NO_GROWTH;
13981debfc3dSmrg
13991debfc3dSmrg if (canonicalize_loop_induction_variables
1400a2dc1f3fSmrg (loop, false, ul, !flag_tree_loop_ivcanon, unroll_outer))
14011debfc3dSmrg {
14021debfc3dSmrg /* If we'll continue unrolling, we need to propagate constants
14031debfc3dSmrg within the new basic blocks to fold away induction variable
14041debfc3dSmrg computations; otherwise, the size might blow up before the
14051debfc3dSmrg iteration is complete and the IR eventually cleaned up. */
14061debfc3dSmrg if (loop_outer (loop_father))
1407c0a68be4Smrg {
1408c0a68be4Smrg /* Once we process our father we will have processed
1409c0a68be4Smrg the fathers of our children as well, so avoid doing
1410c0a68be4Smrg redundant work and clear fathers we've gathered sofar. */
1411c0a68be4Smrg bitmap_clear (father_bbs);
14121debfc3dSmrg bitmap_set_bit (father_bbs, loop_father->header->index);
1413c0a68be4Smrg }
14141debfc3dSmrg
14151debfc3dSmrg return true;
14161debfc3dSmrg }
14171debfc3dSmrg
14181debfc3dSmrg return false;
14191debfc3dSmrg }
14201debfc3dSmrg
14211debfc3dSmrg /* Unroll LOOPS completely if they iterate just few times. Unless
14221debfc3dSmrg MAY_INCREASE_SIZE is true, perform the unrolling only if the
14231debfc3dSmrg size of the code does not increase. */
14241debfc3dSmrg
1425a2dc1f3fSmrg static unsigned int
tree_unroll_loops_completely(bool may_increase_size,bool unroll_outer)14261debfc3dSmrg tree_unroll_loops_completely (bool may_increase_size, bool unroll_outer)
14271debfc3dSmrg {
14281debfc3dSmrg bitmap father_bbs = BITMAP_ALLOC (NULL);
14291debfc3dSmrg bool changed;
14301debfc3dSmrg int iteration = 0;
14311debfc3dSmrg bool irred_invalidated = false;
14321debfc3dSmrg
1433a2dc1f3fSmrg estimate_numbers_of_iterations (cfun);
1434a2dc1f3fSmrg
14351debfc3dSmrg do
14361debfc3dSmrg {
14371debfc3dSmrg changed = false;
14381debfc3dSmrg bitmap loop_closed_ssa_invalidated = NULL;
14391debfc3dSmrg
14401debfc3dSmrg if (loops_state_satisfies_p (LOOP_CLOSED_SSA))
14411debfc3dSmrg loop_closed_ssa_invalidated = BITMAP_ALLOC (NULL);
14421debfc3dSmrg
14431debfc3dSmrg free_numbers_of_iterations_estimates (cfun);
1444a2dc1f3fSmrg estimate_numbers_of_iterations (cfun);
14451debfc3dSmrg
14461debfc3dSmrg changed = tree_unroll_loops_completely_1 (may_increase_size,
14471debfc3dSmrg unroll_outer, father_bbs,
14481debfc3dSmrg current_loops->tree_root);
14491debfc3dSmrg if (changed)
14501debfc3dSmrg {
14511debfc3dSmrg unsigned i;
14521debfc3dSmrg
14531debfc3dSmrg unloop_loops (loop_closed_ssa_invalidated, &irred_invalidated);
14541debfc3dSmrg
14551debfc3dSmrg /* We cannot use TODO_update_ssa_no_phi because VOPS gets confused. */
14561debfc3dSmrg if (loop_closed_ssa_invalidated
14571debfc3dSmrg && !bitmap_empty_p (loop_closed_ssa_invalidated))
14581debfc3dSmrg rewrite_into_loop_closed_ssa (loop_closed_ssa_invalidated,
14591debfc3dSmrg TODO_update_ssa);
14601debfc3dSmrg else
14611debfc3dSmrg update_ssa (TODO_update_ssa);
14621debfc3dSmrg
14631debfc3dSmrg /* father_bbs is a bitmap of loop father header BB indices.
14641debfc3dSmrg Translate that to what non-root loops these BBs belong to now. */
14651debfc3dSmrg bitmap_iterator bi;
14661debfc3dSmrg bitmap fathers = BITMAP_ALLOC (NULL);
14671debfc3dSmrg EXECUTE_IF_SET_IN_BITMAP (father_bbs, 0, i, bi)
14681debfc3dSmrg {
14691debfc3dSmrg basic_block unrolled_loop_bb = BASIC_BLOCK_FOR_FN (cfun, i);
14701debfc3dSmrg if (! unrolled_loop_bb)
14711debfc3dSmrg continue;
14721debfc3dSmrg if (loop_outer (unrolled_loop_bb->loop_father))
14731debfc3dSmrg bitmap_set_bit (fathers,
14741debfc3dSmrg unrolled_loop_bb->loop_father->num);
14751debfc3dSmrg }
14761debfc3dSmrg bitmap_clear (father_bbs);
14771debfc3dSmrg /* Propagate the constants within the new basic blocks. */
14781debfc3dSmrg EXECUTE_IF_SET_IN_BITMAP (fathers, 0, i, bi)
14791debfc3dSmrg {
14801debfc3dSmrg loop_p father = get_loop (cfun, i);
1481c0a68be4Smrg bitmap exit_bbs = BITMAP_ALLOC (NULL);
1482c0a68be4Smrg loop_exit *exit = father->exits->next;
1483c0a68be4Smrg while (exit->e)
1484c0a68be4Smrg {
1485c0a68be4Smrg bitmap_set_bit (exit_bbs, exit->e->dest->index);
1486c0a68be4Smrg exit = exit->next;
1487c0a68be4Smrg }
1488c0a68be4Smrg do_rpo_vn (cfun, loop_preheader_edge (father), exit_bbs);
14891debfc3dSmrg }
14901debfc3dSmrg BITMAP_FREE (fathers);
14911debfc3dSmrg
14921debfc3dSmrg /* This will take care of removing completely unrolled loops
14931debfc3dSmrg from the loop structures so we can continue unrolling now
14941debfc3dSmrg innermost loops. */
14951debfc3dSmrg if (cleanup_tree_cfg ())
14961debfc3dSmrg update_ssa (TODO_update_ssa_only_virtuals);
14971debfc3dSmrg
14981debfc3dSmrg /* Clean up the information about numbers of iterations, since
14991debfc3dSmrg complete unrolling might have invalidated it. */
15001debfc3dSmrg scev_reset ();
15011debfc3dSmrg if (flag_checking && loops_state_satisfies_p (LOOP_CLOSED_SSA))
15021debfc3dSmrg verify_loop_closed_ssa (true);
15031debfc3dSmrg }
15041debfc3dSmrg if (loop_closed_ssa_invalidated)
15051debfc3dSmrg BITMAP_FREE (loop_closed_ssa_invalidated);
15061debfc3dSmrg }
15071debfc3dSmrg while (changed
1508*8feb0f0bSmrg && ++iteration <= param_max_unroll_iterations);
15091debfc3dSmrg
15101debfc3dSmrg BITMAP_FREE (father_bbs);
15111debfc3dSmrg
15121debfc3dSmrg if (irred_invalidated
15131debfc3dSmrg && loops_state_satisfies_p (LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS))
15141debfc3dSmrg mark_irreducible_loops ();
15151debfc3dSmrg
15161debfc3dSmrg return 0;
15171debfc3dSmrg }
15181debfc3dSmrg
15191debfc3dSmrg /* Canonical induction variable creation pass. */
15201debfc3dSmrg
15211debfc3dSmrg namespace {
15221debfc3dSmrg
15231debfc3dSmrg const pass_data pass_data_iv_canon =
15241debfc3dSmrg {
15251debfc3dSmrg GIMPLE_PASS, /* type */
15261debfc3dSmrg "ivcanon", /* name */
15271debfc3dSmrg OPTGROUP_LOOP, /* optinfo_flags */
15281debfc3dSmrg TV_TREE_LOOP_IVCANON, /* tv_id */
15291debfc3dSmrg ( PROP_cfg | PROP_ssa ), /* properties_required */
15301debfc3dSmrg 0, /* properties_provided */
15311debfc3dSmrg 0, /* properties_destroyed */
15321debfc3dSmrg 0, /* todo_flags_start */
15331debfc3dSmrg 0, /* todo_flags_finish */
15341debfc3dSmrg };
15351debfc3dSmrg
15361debfc3dSmrg class pass_iv_canon : public gimple_opt_pass
15371debfc3dSmrg {
15381debfc3dSmrg public:
pass_iv_canon(gcc::context * ctxt)15391debfc3dSmrg pass_iv_canon (gcc::context *ctxt)
15401debfc3dSmrg : gimple_opt_pass (pass_data_iv_canon, ctxt)
15411debfc3dSmrg {}
15421debfc3dSmrg
15431debfc3dSmrg /* opt_pass methods: */
gate(function *)15441debfc3dSmrg virtual bool gate (function *) { return flag_tree_loop_ivcanon != 0; }
15451debfc3dSmrg virtual unsigned int execute (function *fun);
15461debfc3dSmrg
15471debfc3dSmrg }; // class pass_iv_canon
15481debfc3dSmrg
15491debfc3dSmrg unsigned int
execute(function * fun)15501debfc3dSmrg pass_iv_canon::execute (function *fun)
15511debfc3dSmrg {
15521debfc3dSmrg if (number_of_loops (fun) <= 1)
15531debfc3dSmrg return 0;
15541debfc3dSmrg
15551debfc3dSmrg return canonicalize_induction_variables ();
15561debfc3dSmrg }
15571debfc3dSmrg
15581debfc3dSmrg } // anon namespace
15591debfc3dSmrg
15601debfc3dSmrg gimple_opt_pass *
make_pass_iv_canon(gcc::context * ctxt)15611debfc3dSmrg make_pass_iv_canon (gcc::context *ctxt)
15621debfc3dSmrg {
15631debfc3dSmrg return new pass_iv_canon (ctxt);
15641debfc3dSmrg }
15651debfc3dSmrg
15661debfc3dSmrg /* Complete unrolling of loops. */
15671debfc3dSmrg
15681debfc3dSmrg namespace {
15691debfc3dSmrg
15701debfc3dSmrg const pass_data pass_data_complete_unroll =
15711debfc3dSmrg {
15721debfc3dSmrg GIMPLE_PASS, /* type */
15731debfc3dSmrg "cunroll", /* name */
15741debfc3dSmrg OPTGROUP_LOOP, /* optinfo_flags */
15751debfc3dSmrg TV_COMPLETE_UNROLL, /* tv_id */
15761debfc3dSmrg ( PROP_cfg | PROP_ssa ), /* properties_required */
15771debfc3dSmrg 0, /* properties_provided */
15781debfc3dSmrg 0, /* properties_destroyed */
15791debfc3dSmrg 0, /* todo_flags_start */
15801debfc3dSmrg 0, /* todo_flags_finish */
15811debfc3dSmrg };
15821debfc3dSmrg
15831debfc3dSmrg class pass_complete_unroll : public gimple_opt_pass
15841debfc3dSmrg {
15851debfc3dSmrg public:
pass_complete_unroll(gcc::context * ctxt)15861debfc3dSmrg pass_complete_unroll (gcc::context *ctxt)
15871debfc3dSmrg : gimple_opt_pass (pass_data_complete_unroll, ctxt)
15881debfc3dSmrg {}
15891debfc3dSmrg
15901debfc3dSmrg /* opt_pass methods: */
15911debfc3dSmrg virtual unsigned int execute (function *);
15921debfc3dSmrg
15931debfc3dSmrg }; // class pass_complete_unroll
15941debfc3dSmrg
15951debfc3dSmrg unsigned int
execute(function * fun)15961debfc3dSmrg pass_complete_unroll::execute (function *fun)
15971debfc3dSmrg {
15981debfc3dSmrg if (number_of_loops (fun) <= 1)
15991debfc3dSmrg return 0;
16001debfc3dSmrg
16011debfc3dSmrg /* If we ever decide to run loop peeling more than once, we will need to
16021debfc3dSmrg track loops already peeled in loop structures themselves to avoid
16031debfc3dSmrg re-peeling the same loop multiple times. */
16041debfc3dSmrg if (flag_peel_loops)
16051debfc3dSmrg peeled_loops = BITMAP_ALLOC (NULL);
1606*8feb0f0bSmrg unsigned int val = tree_unroll_loops_completely (flag_cunroll_grow_size,
1607*8feb0f0bSmrg true);
16081debfc3dSmrg if (peeled_loops)
16091debfc3dSmrg {
16101debfc3dSmrg BITMAP_FREE (peeled_loops);
16111debfc3dSmrg peeled_loops = NULL;
16121debfc3dSmrg }
16131debfc3dSmrg return val;
16141debfc3dSmrg }
16151debfc3dSmrg
16161debfc3dSmrg } // anon namespace
16171debfc3dSmrg
16181debfc3dSmrg gimple_opt_pass *
make_pass_complete_unroll(gcc::context * ctxt)16191debfc3dSmrg make_pass_complete_unroll (gcc::context *ctxt)
16201debfc3dSmrg {
16211debfc3dSmrg return new pass_complete_unroll (ctxt);
16221debfc3dSmrg }
16231debfc3dSmrg
16241debfc3dSmrg /* Complete unrolling of inner loops. */
16251debfc3dSmrg
16261debfc3dSmrg namespace {
16271debfc3dSmrg
16281debfc3dSmrg const pass_data pass_data_complete_unrolli =
16291debfc3dSmrg {
16301debfc3dSmrg GIMPLE_PASS, /* type */
16311debfc3dSmrg "cunrolli", /* name */
16321debfc3dSmrg OPTGROUP_LOOP, /* optinfo_flags */
16331debfc3dSmrg TV_COMPLETE_UNROLL, /* tv_id */
16341debfc3dSmrg ( PROP_cfg | PROP_ssa ), /* properties_required */
16351debfc3dSmrg 0, /* properties_provided */
16361debfc3dSmrg 0, /* properties_destroyed */
16371debfc3dSmrg 0, /* todo_flags_start */
16381debfc3dSmrg 0, /* todo_flags_finish */
16391debfc3dSmrg };
16401debfc3dSmrg
16411debfc3dSmrg class pass_complete_unrolli : public gimple_opt_pass
16421debfc3dSmrg {
16431debfc3dSmrg public:
pass_complete_unrolli(gcc::context * ctxt)16441debfc3dSmrg pass_complete_unrolli (gcc::context *ctxt)
16451debfc3dSmrg : gimple_opt_pass (pass_data_complete_unrolli, ctxt)
16461debfc3dSmrg {}
16471debfc3dSmrg
16481debfc3dSmrg /* opt_pass methods: */
gate(function *)16491debfc3dSmrg virtual bool gate (function *) { return optimize >= 2; }
16501debfc3dSmrg virtual unsigned int execute (function *);
16511debfc3dSmrg
16521debfc3dSmrg }; // class pass_complete_unrolli
16531debfc3dSmrg
16541debfc3dSmrg unsigned int
execute(function * fun)16551debfc3dSmrg pass_complete_unrolli::execute (function *fun)
16561debfc3dSmrg {
16571debfc3dSmrg unsigned ret = 0;
16581debfc3dSmrg
1659a2dc1f3fSmrg loop_optimizer_init (LOOPS_NORMAL | LOOPS_HAVE_RECORDED_EXITS);
16601debfc3dSmrg if (number_of_loops (fun) > 1)
16611debfc3dSmrg {
16621debfc3dSmrg scev_initialize ();
16631debfc3dSmrg ret = tree_unroll_loops_completely (optimize >= 3, false);
16641debfc3dSmrg scev_finalize ();
16651debfc3dSmrg }
16661debfc3dSmrg loop_optimizer_finalize ();
16671debfc3dSmrg
16681debfc3dSmrg return ret;
16691debfc3dSmrg }
16701debfc3dSmrg
16711debfc3dSmrg } // anon namespace
16721debfc3dSmrg
16731debfc3dSmrg gimple_opt_pass *
make_pass_complete_unrolli(gcc::context * ctxt)16741debfc3dSmrg make_pass_complete_unrolli (gcc::context *ctxt)
16751debfc3dSmrg {
16761debfc3dSmrg return new pass_complete_unrolli (ctxt);
16771debfc3dSmrg }
16781debfc3dSmrg
16791debfc3dSmrg
1680