xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/tree-ssa-loop-ch.c (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
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