11debfc3dSmrg /* Loop header copying on trees.
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 #include "config.h"
211debfc3dSmrg #include "system.h"
221debfc3dSmrg #include "coretypes.h"
231debfc3dSmrg #include "backend.h"
241debfc3dSmrg #include "tree.h"
251debfc3dSmrg #include "gimple.h"
261debfc3dSmrg #include "cfghooks.h"
271debfc3dSmrg #include "tree-pass.h"
281debfc3dSmrg #include "gimple-ssa.h"
291debfc3dSmrg #include "gimple-iterator.h"
301debfc3dSmrg #include "tree-cfg.h"
311debfc3dSmrg #include "tree-into-ssa.h"
321debfc3dSmrg #include "cfgloop.h"
331debfc3dSmrg #include "tree-inline.h"
341debfc3dSmrg #include "tree-ssa-scopedtables.h"
351debfc3dSmrg #include "tree-ssa-threadedge.h"
36c0a68be4Smrg #include "tree-ssa-sccvn.h"
37c0a68be4Smrg #include "tree-phinodes.h"
38c0a68be4Smrg #include "ssa-iterators.h"
391debfc3dSmrg
401debfc3dSmrg /* Duplicates headers of loops if they are small enough, so that the statements
411debfc3dSmrg in the loop body are always executed when the loop is entered. This
421debfc3dSmrg increases effectiveness of code motion optimizations, and reduces the need
431debfc3dSmrg for loop preconditioning. */
441debfc3dSmrg
451debfc3dSmrg /* Check whether we should duplicate HEADER of LOOP. At most *LIMIT
461debfc3dSmrg instructions should be duplicated, limit is decreased by the actual
471debfc3dSmrg amount. */
481debfc3dSmrg
491debfc3dSmrg static bool
should_duplicate_loop_header_p(basic_block header,class loop * loop,int * limit)50*8feb0f0bSmrg should_duplicate_loop_header_p (basic_block header, class loop *loop,
511debfc3dSmrg int *limit)
521debfc3dSmrg {
531debfc3dSmrg gimple_stmt_iterator bsi;
541debfc3dSmrg
551debfc3dSmrg gcc_assert (!header->aux);
561debfc3dSmrg
571debfc3dSmrg /* Loop header copying usually increases size of the code. This used not to
581debfc3dSmrg be true, since quite often it is possible to verify that the condition is
591debfc3dSmrg satisfied in the first iteration and therefore to eliminate it. Jump
601debfc3dSmrg threading handles these cases now. */
611debfc3dSmrg if (optimize_loop_for_size_p (loop)
621debfc3dSmrg && !loop->force_vectorize)
631debfc3dSmrg {
641debfc3dSmrg if (dump_file && (dump_flags & TDF_DETAILS))
651debfc3dSmrg fprintf (dump_file,
661debfc3dSmrg " Not duplicating bb %i: optimizing for size.\n",
671debfc3dSmrg header->index);
681debfc3dSmrg return false;
691debfc3dSmrg }
701debfc3dSmrg
711debfc3dSmrg gcc_assert (EDGE_COUNT (header->succs) > 0);
721debfc3dSmrg if (single_succ_p (header))
731debfc3dSmrg {
741debfc3dSmrg if (dump_file && (dump_flags & TDF_DETAILS))
751debfc3dSmrg fprintf (dump_file,
761debfc3dSmrg " Not duplicating bb %i: it is single succ.\n",
771debfc3dSmrg header->index);
781debfc3dSmrg return false;
791debfc3dSmrg }
801debfc3dSmrg
811debfc3dSmrg if (flow_bb_inside_loop_p (loop, EDGE_SUCC (header, 0)->dest)
821debfc3dSmrg && flow_bb_inside_loop_p (loop, EDGE_SUCC (header, 1)->dest))
831debfc3dSmrg {
841debfc3dSmrg if (dump_file && (dump_flags & TDF_DETAILS))
851debfc3dSmrg fprintf (dump_file,
86*8feb0f0bSmrg " Not duplicating bb %i: both successors are in loop.\n",
871debfc3dSmrg loop->num);
881debfc3dSmrg return false;
891debfc3dSmrg }
901debfc3dSmrg
911debfc3dSmrg /* If this is not the original loop header, we want it to have just
921debfc3dSmrg one predecessor in order to match the && pattern. */
931debfc3dSmrg if (header != loop->header && !single_pred_p (header))
941debfc3dSmrg {
951debfc3dSmrg if (dump_file && (dump_flags & TDF_DETAILS))
961debfc3dSmrg fprintf (dump_file,
971debfc3dSmrg " Not duplicating bb %i: it has mutiple predecestors.\n",
981debfc3dSmrg header->index);
991debfc3dSmrg return false;
1001debfc3dSmrg }
1011debfc3dSmrg
102c0a68be4Smrg gcond *last = safe_dyn_cast <gcond *> (last_stmt (header));
103c0a68be4Smrg if (!last)
1041debfc3dSmrg {
1051debfc3dSmrg if (dump_file && (dump_flags & TDF_DETAILS))
1061debfc3dSmrg fprintf (dump_file,
1071debfc3dSmrg " Not duplicating bb %i: it does not end by conditional.\n",
1081debfc3dSmrg header->index);
1091debfc3dSmrg return false;
1101debfc3dSmrg }
1111debfc3dSmrg
112c0a68be4Smrg for (gphi_iterator psi = gsi_start_phis (header); !gsi_end_p (psi);
113c0a68be4Smrg gsi_next (&psi))
114c0a68be4Smrg {
115c0a68be4Smrg gphi *phi = psi.phi ();
116c0a68be4Smrg tree res = gimple_phi_result (phi);
117c0a68be4Smrg if (INTEGRAL_TYPE_P (TREE_TYPE (res))
118c0a68be4Smrg || POINTER_TYPE_P (TREE_TYPE (res)))
119c0a68be4Smrg gimple_set_uid (phi, 1 /* IV */);
120c0a68be4Smrg else
121c0a68be4Smrg gimple_set_uid (phi, 0);
122c0a68be4Smrg }
123c0a68be4Smrg
124c0a68be4Smrg /* Count number of instructions and punt on calls.
125c0a68be4Smrg Populate stmts INV/IV flag to later apply heuristics to the
126c0a68be4Smrg kind of conditions we want to copy. */
1271debfc3dSmrg for (bsi = gsi_start_bb (header); !gsi_end_p (bsi); gsi_next (&bsi))
1281debfc3dSmrg {
129c0a68be4Smrg gimple *last = gsi_stmt (bsi);
1301debfc3dSmrg
1311debfc3dSmrg if (gimple_code (last) == GIMPLE_LABEL)
1321debfc3dSmrg continue;
1331debfc3dSmrg
1341debfc3dSmrg if (is_gimple_debug (last))
1351debfc3dSmrg continue;
1361debfc3dSmrg
1371debfc3dSmrg if (gimple_code (last) == GIMPLE_CALL
138a2dc1f3fSmrg && (!gimple_inexpensive_call_p (as_a <gcall *> (last))
139a2dc1f3fSmrg /* IFN_LOOP_DIST_ALIAS means that inner loop is distributed
140a2dc1f3fSmrg at current loop's header. Don't copy in this case. */
141a2dc1f3fSmrg || gimple_call_internal_p (last, IFN_LOOP_DIST_ALIAS)))
1421debfc3dSmrg {
1431debfc3dSmrg if (dump_file && (dump_flags & TDF_DETAILS))
1441debfc3dSmrg fprintf (dump_file,
1451debfc3dSmrg " Not duplicating bb %i: it contains call.\n",
1461debfc3dSmrg header->index);
1471debfc3dSmrg return false;
1481debfc3dSmrg }
1491debfc3dSmrg
1501debfc3dSmrg *limit -= estimate_num_insns (last, &eni_size_weights);
1511debfc3dSmrg if (*limit < 0)
1521debfc3dSmrg {
1531debfc3dSmrg if (dump_file && (dump_flags & TDF_DETAILS))
1541debfc3dSmrg fprintf (dump_file,
1551debfc3dSmrg " Not duplicating bb %i contains too many insns.\n",
1561debfc3dSmrg header->index);
1571debfc3dSmrg return false;
1581debfc3dSmrg }
159c0a68be4Smrg
160c0a68be4Smrg /* Classify the stmt based on whether its computation is based
161c0a68be4Smrg on a IV or whether it is invariant in the loop. */
162c0a68be4Smrg gimple_set_uid (last, 0);
163c0a68be4Smrg if (!gimple_vuse (last))
164c0a68be4Smrg {
165c0a68be4Smrg bool inv = true;
166c0a68be4Smrg bool iv = false;
167c0a68be4Smrg ssa_op_iter i;
168c0a68be4Smrg tree op;
169c0a68be4Smrg FOR_EACH_SSA_TREE_OPERAND (op, last, i, SSA_OP_USE)
170c0a68be4Smrg if (!SSA_NAME_IS_DEFAULT_DEF (op)
171c0a68be4Smrg && flow_bb_inside_loop_p (loop,
172c0a68be4Smrg gimple_bb (SSA_NAME_DEF_STMT (op))))
173c0a68be4Smrg {
174c0a68be4Smrg if (!(gimple_uid (SSA_NAME_DEF_STMT (op)) & 2 /* INV */))
175c0a68be4Smrg inv = false;
176c0a68be4Smrg if (gimple_uid (SSA_NAME_DEF_STMT (op)) & 1 /* IV */)
177c0a68be4Smrg iv = true;
1781debfc3dSmrg }
179c0a68be4Smrg gimple_set_uid (last, (iv ? 1 : 0) | (inv ? 2 : 0));
180c0a68be4Smrg }
181c0a68be4Smrg }
182c0a68be4Smrg
183c0a68be4Smrg /* If the condition tests a non-IV loop variant we do not want to rotate
184c0a68be4Smrg the loop further. Unless this is the original loop header. */
185c0a68be4Smrg tree lhs = gimple_cond_lhs (last);
186c0a68be4Smrg tree rhs = gimple_cond_rhs (last);
187c0a68be4Smrg if (header != loop->header
188c0a68be4Smrg && ((TREE_CODE (lhs) == SSA_NAME
189c0a68be4Smrg && !SSA_NAME_IS_DEFAULT_DEF (lhs)
190c0a68be4Smrg && flow_bb_inside_loop_p (loop, gimple_bb (SSA_NAME_DEF_STMT (lhs)))
191c0a68be4Smrg && gimple_uid (SSA_NAME_DEF_STMT (lhs)) == 0)
192c0a68be4Smrg || (TREE_CODE (rhs) == SSA_NAME
193c0a68be4Smrg && !SSA_NAME_IS_DEFAULT_DEF (rhs)
194c0a68be4Smrg && flow_bb_inside_loop_p (loop,
195c0a68be4Smrg gimple_bb (SSA_NAME_DEF_STMT (rhs)))
196c0a68be4Smrg && gimple_uid (SSA_NAME_DEF_STMT (rhs)) == 0)))
197c0a68be4Smrg {
198c0a68be4Smrg if (dump_file && (dump_flags & TDF_DETAILS))
199c0a68be4Smrg fprintf (dump_file,
200c0a68be4Smrg " Not duplicating bb %i: condition based on non-IV loop"
201c0a68be4Smrg " variant.\n", header->index);
202c0a68be4Smrg return false;
203c0a68be4Smrg }
204c0a68be4Smrg
2051debfc3dSmrg if (dump_file && (dump_flags & TDF_DETAILS))
2061debfc3dSmrg fprintf (dump_file, " Will duplicate bb %i\n", header->index);
2071debfc3dSmrg return true;
2081debfc3dSmrg }
2091debfc3dSmrg
2101debfc3dSmrg /* Checks whether LOOP is a do-while style loop. */
2111debfc3dSmrg
2121debfc3dSmrg static bool
do_while_loop_p(class loop * loop)213*8feb0f0bSmrg do_while_loop_p (class loop *loop)
2141debfc3dSmrg {
2151debfc3dSmrg gimple *stmt = last_stmt (loop->latch);
2161debfc3dSmrg
2171debfc3dSmrg /* If the latch of the loop is not empty, it is not a do-while loop. */
2181debfc3dSmrg if (stmt
2191debfc3dSmrg && gimple_code (stmt) != GIMPLE_LABEL)
2201debfc3dSmrg {
2211debfc3dSmrg if (dump_file && (dump_flags & TDF_DETAILS))
2221debfc3dSmrg fprintf (dump_file,
2231debfc3dSmrg "Loop %i is not do-while loop: latch is not empty.\n",
2241debfc3dSmrg loop->num);
2251debfc3dSmrg return false;
2261debfc3dSmrg }
2271debfc3dSmrg
228c0a68be4Smrg /* If the latch does not have a single predecessor, it is not a
229c0a68be4Smrg do-while loop. */
230c0a68be4Smrg if (!single_pred_p (loop->latch))
2311debfc3dSmrg {
2321debfc3dSmrg if (dump_file && (dump_flags & TDF_DETAILS))
2331debfc3dSmrg fprintf (dump_file,
234c0a68be4Smrg "Loop %i is not do-while loop: latch has multiple "
235c0a68be4Smrg "predecessors.\n", loop->num);
2361debfc3dSmrg return false;
2371debfc3dSmrg }
238c0a68be4Smrg
239c0a68be4Smrg /* If the latch predecessor doesn't exit the loop, it is not a
240c0a68be4Smrg do-while loop. */
241c0a68be4Smrg if (!loop_exits_from_bb_p (loop, single_pred (loop->latch)))
242c0a68be4Smrg {
243c0a68be4Smrg if (dump_file && (dump_flags & TDF_DETAILS))
244c0a68be4Smrg fprintf (dump_file,
245c0a68be4Smrg "Loop %i is not do-while loop: latch predecessor "
246c0a68be4Smrg "does not exit loop.\n", loop->num);
247c0a68be4Smrg return false;
248c0a68be4Smrg }
249c0a68be4Smrg
2501debfc3dSmrg if (dump_file && (dump_flags & TDF_DETAILS))
2511debfc3dSmrg fprintf (dump_file, "Loop %i is do-while loop\n", loop->num);
2521debfc3dSmrg
2531debfc3dSmrg return true;
2541debfc3dSmrg }
2551debfc3dSmrg
2561debfc3dSmrg namespace {
2571debfc3dSmrg
2581debfc3dSmrg /* Common superclass for both header-copying phases. */
2591debfc3dSmrg class ch_base : public gimple_opt_pass
2601debfc3dSmrg {
2611debfc3dSmrg protected:
ch_base(pass_data data,gcc::context * ctxt)2621debfc3dSmrg ch_base (pass_data data, gcc::context *ctxt)
2631debfc3dSmrg : gimple_opt_pass (data, ctxt)
2641debfc3dSmrg {}
2651debfc3dSmrg
2661debfc3dSmrg /* Copies headers of all loops in FUN for which process_loop_p is true. */
2671debfc3dSmrg unsigned int copy_headers (function *fun);
2681debfc3dSmrg
2691debfc3dSmrg /* Return true to copy headers of LOOP or false to skip. */
270*8feb0f0bSmrg virtual bool process_loop_p (class loop *loop) = 0;
2711debfc3dSmrg };
2721debfc3dSmrg
2731debfc3dSmrg const pass_data pass_data_ch =
2741debfc3dSmrg {
2751debfc3dSmrg GIMPLE_PASS, /* type */
2761debfc3dSmrg "ch", /* name */
2771debfc3dSmrg OPTGROUP_LOOP, /* optinfo_flags */
2781debfc3dSmrg TV_TREE_CH, /* tv_id */
2791debfc3dSmrg ( PROP_cfg | PROP_ssa ), /* properties_required */
2801debfc3dSmrg 0, /* properties_provided */
2811debfc3dSmrg 0, /* properties_destroyed */
2821debfc3dSmrg 0, /* todo_flags_start */
2831debfc3dSmrg 0, /* todo_flags_finish */
2841debfc3dSmrg };
2851debfc3dSmrg
2861debfc3dSmrg class pass_ch : public ch_base
2871debfc3dSmrg {
2881debfc3dSmrg public:
pass_ch(gcc::context * ctxt)2891debfc3dSmrg pass_ch (gcc::context *ctxt)
2901debfc3dSmrg : ch_base (pass_data_ch, ctxt)
2911debfc3dSmrg {}
2921debfc3dSmrg
2931debfc3dSmrg /* opt_pass methods: */
gate(function *)2941debfc3dSmrg virtual bool gate (function *) { return flag_tree_ch != 0; }
2951debfc3dSmrg
2961debfc3dSmrg /* Initialize and finalize loop structures, copying headers inbetween. */
2971debfc3dSmrg virtual unsigned int execute (function *);
2981debfc3dSmrg
clone()2991debfc3dSmrg opt_pass * clone () { return new pass_ch (m_ctxt); }
3001debfc3dSmrg
3011debfc3dSmrg protected:
3021debfc3dSmrg /* ch_base method: */
303*8feb0f0bSmrg virtual bool process_loop_p (class loop *loop);
3041debfc3dSmrg }; // class pass_ch
3051debfc3dSmrg
3061debfc3dSmrg const pass_data pass_data_ch_vect =
3071debfc3dSmrg {
3081debfc3dSmrg GIMPLE_PASS, /* type */
3091debfc3dSmrg "ch_vect", /* name */
3101debfc3dSmrg OPTGROUP_LOOP, /* optinfo_flags */
3111debfc3dSmrg TV_TREE_CH, /* tv_id */
3121debfc3dSmrg ( PROP_cfg | PROP_ssa ), /* properties_required */
3131debfc3dSmrg 0, /* properties_provided */
3141debfc3dSmrg 0, /* properties_destroyed */
3151debfc3dSmrg 0, /* todo_flags_start */
3161debfc3dSmrg 0, /* todo_flags_finish */
3171debfc3dSmrg };
3181debfc3dSmrg
3191debfc3dSmrg /* This is a more aggressive version of the same pass, designed to run just
3201debfc3dSmrg before if-conversion and vectorization, to put more loops into the form
3211debfc3dSmrg required for those phases. */
3221debfc3dSmrg class pass_ch_vect : public ch_base
3231debfc3dSmrg {
3241debfc3dSmrg public:
pass_ch_vect(gcc::context * ctxt)3251debfc3dSmrg pass_ch_vect (gcc::context *ctxt)
3261debfc3dSmrg : ch_base (pass_data_ch_vect, ctxt)
3271debfc3dSmrg {}
3281debfc3dSmrg
3291debfc3dSmrg /* opt_pass methods: */
gate(function * fun)3301debfc3dSmrg virtual bool gate (function *fun)
3311debfc3dSmrg {
3321debfc3dSmrg return flag_tree_ch != 0
3331debfc3dSmrg && (flag_tree_loop_vectorize != 0 || fun->has_force_vectorize_loops);
3341debfc3dSmrg }
3351debfc3dSmrg
3361debfc3dSmrg /* Just copy headers, no initialization/finalization of loop structures. */
3371debfc3dSmrg virtual unsigned int execute (function *);
3381debfc3dSmrg
3391debfc3dSmrg protected:
3401debfc3dSmrg /* ch_base method: */
341*8feb0f0bSmrg virtual bool process_loop_p (class loop *loop);
3421debfc3dSmrg }; // class pass_ch_vect
3431debfc3dSmrg
3441debfc3dSmrg /* For all loops, copy the condition at the end of the loop body in front
3451debfc3dSmrg of the loop. This is beneficial since it increases efficiency of
3461debfc3dSmrg code motion optimizations. It also saves one jump on entry to the loop. */
3471debfc3dSmrg
3481debfc3dSmrg unsigned int
copy_headers(function * fun)3491debfc3dSmrg ch_base::copy_headers (function *fun)
3501debfc3dSmrg {
351*8feb0f0bSmrg class loop *loop;
3521debfc3dSmrg basic_block header;
3531debfc3dSmrg edge exit, entry;
3541debfc3dSmrg basic_block *bbs, *copied_bbs;
3551debfc3dSmrg unsigned n_bbs;
3561debfc3dSmrg unsigned bbs_size;
3571debfc3dSmrg bool changed = false;
3581debfc3dSmrg
3591debfc3dSmrg if (number_of_loops (fun) <= 1)
3601debfc3dSmrg return 0;
3611debfc3dSmrg
3621debfc3dSmrg bbs = XNEWVEC (basic_block, n_basic_blocks_for_fn (fun));
3631debfc3dSmrg copied_bbs = XNEWVEC (basic_block, n_basic_blocks_for_fn (fun));
3641debfc3dSmrg bbs_size = n_basic_blocks_for_fn (fun);
3651debfc3dSmrg
366c0a68be4Smrg auto_vec<std::pair<edge, loop_p> > copied;
367c0a68be4Smrg
3681debfc3dSmrg FOR_EACH_LOOP (loop, 0)
3691debfc3dSmrg {
370*8feb0f0bSmrg int initial_limit = param_max_loop_header_insns;
3711debfc3dSmrg int remaining_limit = initial_limit;
3721debfc3dSmrg if (dump_file && (dump_flags & TDF_DETAILS))
3731debfc3dSmrg fprintf (dump_file,
3741debfc3dSmrg "Analyzing loop %i\n", loop->num);
3751debfc3dSmrg
3761debfc3dSmrg header = loop->header;
3771debfc3dSmrg
3781debfc3dSmrg /* If the loop is already a do-while style one (either because it was
3791debfc3dSmrg written as such, or because jump threading transformed it into one),
3801debfc3dSmrg we might be in fact peeling the first iteration of the loop. This
381c0a68be4Smrg in general is not a good idea. Also avoid touching infinite loops. */
382c0a68be4Smrg if (!loop_has_exit_edges (loop)
383c0a68be4Smrg || !process_loop_p (loop))
3841debfc3dSmrg continue;
3851debfc3dSmrg
3861debfc3dSmrg /* Iterate the header copying up to limit; this takes care of the cases
3871debfc3dSmrg like while (a && b) {...}, where we want to have both of the conditions
3881debfc3dSmrg copied. TODO -- handle while (a || b) - like cases, by not requiring
3891debfc3dSmrg the header to have just a single successor and copying up to
3901debfc3dSmrg postdominator. */
3911debfc3dSmrg
3921debfc3dSmrg exit = NULL;
3931debfc3dSmrg n_bbs = 0;
3941debfc3dSmrg while (should_duplicate_loop_header_p (header, loop, &remaining_limit))
3951debfc3dSmrg {
3961debfc3dSmrg /* Find a successor of header that is inside a loop; i.e. the new
3971debfc3dSmrg header after the condition is copied. */
3981debfc3dSmrg if (flow_bb_inside_loop_p (loop, EDGE_SUCC (header, 0)->dest))
3991debfc3dSmrg exit = EDGE_SUCC (header, 0);
4001debfc3dSmrg else
4011debfc3dSmrg exit = EDGE_SUCC (header, 1);
4021debfc3dSmrg bbs[n_bbs++] = header;
4031debfc3dSmrg gcc_assert (bbs_size > n_bbs);
4041debfc3dSmrg header = exit->dest;
4051debfc3dSmrg }
4061debfc3dSmrg
4071debfc3dSmrg if (!exit)
4081debfc3dSmrg continue;
4091debfc3dSmrg
4101debfc3dSmrg if (dump_file && (dump_flags & TDF_DETAILS))
4111debfc3dSmrg fprintf (dump_file,
4121debfc3dSmrg "Duplicating header of the loop %d up to edge %d->%d,"
4131debfc3dSmrg " %i insns.\n",
4141debfc3dSmrg loop->num, exit->src->index, exit->dest->index,
4151debfc3dSmrg initial_limit - remaining_limit);
4161debfc3dSmrg
4171debfc3dSmrg /* Ensure that the header will have just the latch as a predecessor
4181debfc3dSmrg inside the loop. */
4191debfc3dSmrg if (!single_pred_p (exit->dest))
4201debfc3dSmrg exit = single_pred_edge (split_edge (exit));
4211debfc3dSmrg
4221debfc3dSmrg entry = loop_preheader_edge (loop);
4231debfc3dSmrg
4241debfc3dSmrg propagate_threaded_block_debug_into (exit->dest, entry->dest);
4251debfc3dSmrg if (!gimple_duplicate_sese_region (entry, exit, bbs, n_bbs, copied_bbs,
4261debfc3dSmrg true))
4271debfc3dSmrg {
4281debfc3dSmrg fprintf (dump_file, "Duplication failed.\n");
4291debfc3dSmrg continue;
4301debfc3dSmrg }
431c0a68be4Smrg copied.safe_push (std::make_pair (entry, loop));
4321debfc3dSmrg
4331debfc3dSmrg /* If the loop has the form "for (i = j; i < j + 10; i++)" then
4341debfc3dSmrg this copying can introduce a case where we rely on undefined
4351debfc3dSmrg signed overflow to eliminate the preheader condition, because
4361debfc3dSmrg we assume that "j < j + 10" is true. We don't want to warn
4371debfc3dSmrg about that case for -Wstrict-overflow, because in general we
4381debfc3dSmrg don't warn about overflow involving loops. Prevent the
4391debfc3dSmrg warning by setting the no_warning flag in the condition. */
4401debfc3dSmrg if (warn_strict_overflow > 0)
4411debfc3dSmrg {
4421debfc3dSmrg unsigned int i;
4431debfc3dSmrg
4441debfc3dSmrg for (i = 0; i < n_bbs; ++i)
4451debfc3dSmrg {
4461debfc3dSmrg gimple_stmt_iterator bsi;
4471debfc3dSmrg
4481debfc3dSmrg for (bsi = gsi_start_bb (copied_bbs[i]);
4491debfc3dSmrg !gsi_end_p (bsi);
4501debfc3dSmrg gsi_next (&bsi))
4511debfc3dSmrg {
4521debfc3dSmrg gimple *stmt = gsi_stmt (bsi);
4531debfc3dSmrg if (gimple_code (stmt) == GIMPLE_COND)
454a05ac97eSmrg {
455a05ac97eSmrg tree lhs = gimple_cond_lhs (stmt);
456a05ac97eSmrg if (gimple_cond_code (stmt) != EQ_EXPR
457a05ac97eSmrg && gimple_cond_code (stmt) != NE_EXPR
458a05ac97eSmrg && INTEGRAL_TYPE_P (TREE_TYPE (lhs))
459a05ac97eSmrg && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (lhs)))
4601debfc3dSmrg gimple_set_no_warning (stmt, true);
461a05ac97eSmrg }
4621debfc3dSmrg else if (is_gimple_assign (stmt))
4631debfc3dSmrg {
4641debfc3dSmrg enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
465a05ac97eSmrg tree rhs1 = gimple_assign_rhs1 (stmt);
466a05ac97eSmrg if (TREE_CODE_CLASS (rhs_code) == tcc_comparison
467a05ac97eSmrg && rhs_code != EQ_EXPR
468a05ac97eSmrg && rhs_code != NE_EXPR
469a05ac97eSmrg && INTEGRAL_TYPE_P (TREE_TYPE (rhs1))
470a05ac97eSmrg && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (rhs1)))
4711debfc3dSmrg gimple_set_no_warning (stmt, true);
4721debfc3dSmrg }
4731debfc3dSmrg }
4741debfc3dSmrg }
4751debfc3dSmrg }
4761debfc3dSmrg
4771debfc3dSmrg /* Ensure that the latch and the preheader is simple (we know that they
4781debfc3dSmrg are not now, since there was the loop exit condition. */
4791debfc3dSmrg split_edge (loop_preheader_edge (loop));
4801debfc3dSmrg split_edge (loop_latch_edge (loop));
4811debfc3dSmrg
482c0a68be4Smrg if (dump_file && (dump_flags & TDF_DETAILS))
483c0a68be4Smrg {
484c0a68be4Smrg if (do_while_loop_p (loop))
485c0a68be4Smrg fprintf (dump_file, "Loop %d is now do-while loop.\n", loop->num);
486c0a68be4Smrg else
487c0a68be4Smrg fprintf (dump_file, "Loop %d is still not do-while loop.\n",
488c0a68be4Smrg loop->num);
489c0a68be4Smrg }
490c0a68be4Smrg
4911debfc3dSmrg changed = true;
4921debfc3dSmrg }
4931debfc3dSmrg
4941debfc3dSmrg if (changed)
495c0a68be4Smrg {
4961debfc3dSmrg update_ssa (TODO_update_ssa);
497c0a68be4Smrg /* After updating SSA form perform CSE on the loop header
498c0a68be4Smrg copies. This is esp. required for the pass before
499c0a68be4Smrg vectorization since nothing cleans up copied exit tests
500c0a68be4Smrg that can now be simplified. CSE from the entry of the
501c0a68be4Smrg region we copied till all loop exit blocks but not
502c0a68be4Smrg entering the loop itself. */
503c0a68be4Smrg for (unsigned i = 0; i < copied.length (); ++i)
504c0a68be4Smrg {
505c0a68be4Smrg edge entry = copied[i].first;
506c0a68be4Smrg loop_p loop = copied[i].second;
507c0a68be4Smrg vec<edge> exit_edges = get_loop_exit_edges (loop);
508c0a68be4Smrg bitmap exit_bbs = BITMAP_ALLOC (NULL);
509c0a68be4Smrg for (unsigned j = 0; j < exit_edges.length (); ++j)
510c0a68be4Smrg bitmap_set_bit (exit_bbs, exit_edges[j]->dest->index);
511c0a68be4Smrg bitmap_set_bit (exit_bbs, loop->header->index);
512c0a68be4Smrg do_rpo_vn (cfun, entry, exit_bbs);
513c0a68be4Smrg BITMAP_FREE (exit_bbs);
514c0a68be4Smrg exit_edges.release ();
515c0a68be4Smrg }
516c0a68be4Smrg }
5171debfc3dSmrg free (bbs);
5181debfc3dSmrg free (copied_bbs);
5191debfc3dSmrg
5201debfc3dSmrg return changed ? TODO_cleanup_cfg : 0;
5211debfc3dSmrg }
5221debfc3dSmrg
5231debfc3dSmrg /* Initialize the loop structures we need, and finalize after. */
5241debfc3dSmrg
5251debfc3dSmrg unsigned int
execute(function * fun)5261debfc3dSmrg pass_ch::execute (function *fun)
5271debfc3dSmrg {
5281debfc3dSmrg loop_optimizer_init (LOOPS_HAVE_PREHEADERS
529c0a68be4Smrg | LOOPS_HAVE_SIMPLE_LATCHES
530c0a68be4Smrg | LOOPS_HAVE_RECORDED_EXITS);
5311debfc3dSmrg
5321debfc3dSmrg unsigned int res = copy_headers (fun);
5331debfc3dSmrg
5341debfc3dSmrg loop_optimizer_finalize ();
5351debfc3dSmrg return res;
5361debfc3dSmrg }
5371debfc3dSmrg
5381debfc3dSmrg /* Assume an earlier phase has already initialized all the loop structures that
5391debfc3dSmrg we need here (and perhaps others too), and that these will be finalized by
5401debfc3dSmrg a later phase. */
5411debfc3dSmrg
5421debfc3dSmrg unsigned int
execute(function * fun)5431debfc3dSmrg pass_ch_vect::execute (function *fun)
5441debfc3dSmrg {
5451debfc3dSmrg return copy_headers (fun);
5461debfc3dSmrg }
5471debfc3dSmrg
5481debfc3dSmrg /* Apply header copying according to a very simple test of do-while shape. */
5491debfc3dSmrg
5501debfc3dSmrg bool
process_loop_p(class loop * loop)551*8feb0f0bSmrg pass_ch::process_loop_p (class loop *loop)
5521debfc3dSmrg {
5531debfc3dSmrg return !do_while_loop_p (loop);
5541debfc3dSmrg }
5551debfc3dSmrg
5561debfc3dSmrg /* Apply header-copying to loops where we might enable vectorization. */
5571debfc3dSmrg
5581debfc3dSmrg bool
process_loop_p(class loop * loop)559*8feb0f0bSmrg pass_ch_vect::process_loop_p (class loop *loop)
5601debfc3dSmrg {
561a2dc1f3fSmrg if (!flag_tree_loop_vectorize && !loop->force_vectorize)
5621debfc3dSmrg return false;
5631debfc3dSmrg
5641debfc3dSmrg if (loop->dont_vectorize)
5651debfc3dSmrg return false;
5661debfc3dSmrg
5671debfc3dSmrg /* The vectorizer won't handle anything with multiple exits, so skip. */
5681debfc3dSmrg edge exit = single_exit (loop);
5691debfc3dSmrg if (!exit)
5701debfc3dSmrg return false;
5711debfc3dSmrg
572c0a68be4Smrg if (!do_while_loop_p (loop))
5731debfc3dSmrg return true;
5741debfc3dSmrg
5751debfc3dSmrg return false;
5761debfc3dSmrg }
5771debfc3dSmrg
5781debfc3dSmrg } // anon namespace
5791debfc3dSmrg
5801debfc3dSmrg gimple_opt_pass *
make_pass_ch_vect(gcc::context * ctxt)5811debfc3dSmrg make_pass_ch_vect (gcc::context *ctxt)
5821debfc3dSmrg {
5831debfc3dSmrg return new pass_ch_vect (ctxt);
5841debfc3dSmrg }
5851debfc3dSmrg
5861debfc3dSmrg gimple_opt_pass *
make_pass_ch(gcc::context * ctxt)5871debfc3dSmrg make_pass_ch (gcc::context *ctxt)
5881debfc3dSmrg {
5891debfc3dSmrg return new pass_ch (ctxt);
5901debfc3dSmrg }
591