xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/tree-ssa-loop-unswitch.c (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
11debfc3dSmrg /* Loop unswitching.
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 "tree-pass.h"
271debfc3dSmrg #include "ssa.h"
281debfc3dSmrg #include "fold-const.h"
291debfc3dSmrg #include "gimplify.h"
301debfc3dSmrg #include "tree-cfg.h"
311debfc3dSmrg #include "tree-ssa.h"
321debfc3dSmrg #include "tree-ssa-loop-niter.h"
331debfc3dSmrg #include "tree-ssa-loop.h"
341debfc3dSmrg #include "tree-into-ssa.h"
351debfc3dSmrg #include "cfgloop.h"
361debfc3dSmrg #include "tree-inline.h"
371debfc3dSmrg #include "gimple-iterator.h"
381debfc3dSmrg #include "cfghooks.h"
391debfc3dSmrg #include "tree-ssa-loop-manip.h"
401debfc3dSmrg 
411debfc3dSmrg /* This file implements the loop unswitching, i.e. transformation of loops like
421debfc3dSmrg 
431debfc3dSmrg    while (A)
441debfc3dSmrg      {
451debfc3dSmrg        if (inv)
461debfc3dSmrg          B;
471debfc3dSmrg 
481debfc3dSmrg        X;
491debfc3dSmrg 
501debfc3dSmrg        if (!inv)
511debfc3dSmrg 	 C;
521debfc3dSmrg      }
531debfc3dSmrg 
541debfc3dSmrg    where inv is the loop invariant, into
551debfc3dSmrg 
561debfc3dSmrg    if (inv)
571debfc3dSmrg      {
581debfc3dSmrg        while (A)
591debfc3dSmrg 	 {
601debfc3dSmrg            B;
611debfc3dSmrg 	   X;
621debfc3dSmrg 	 }
631debfc3dSmrg      }
641debfc3dSmrg    else
651debfc3dSmrg      {
661debfc3dSmrg        while (A)
671debfc3dSmrg 	 {
681debfc3dSmrg 	   X;
691debfc3dSmrg 	   C;
701debfc3dSmrg 	 }
711debfc3dSmrg      }
721debfc3dSmrg 
731debfc3dSmrg    Inv is considered invariant iff the values it compares are both invariant;
741debfc3dSmrg    tree-ssa-loop-im.c ensures that all the suitable conditions are in this
751debfc3dSmrg    shape.  */
761debfc3dSmrg 
77*8feb0f0bSmrg static class loop *tree_unswitch_loop (class loop *, basic_block, tree);
78*8feb0f0bSmrg static bool tree_unswitch_single_loop (class loop *, int);
79*8feb0f0bSmrg static tree tree_may_unswitch_on (basic_block, class loop *);
80*8feb0f0bSmrg static bool tree_unswitch_outer_loop (class loop *);
81*8feb0f0bSmrg static edge find_loop_guard (class loop *);
82*8feb0f0bSmrg static bool empty_bb_without_guard_p (class loop *, basic_block);
83*8feb0f0bSmrg static bool used_outside_loop_p (class loop *, tree);
84*8feb0f0bSmrg static void hoist_guard (class loop *, edge);
85*8feb0f0bSmrg static bool check_exit_phi (class loop *);
86*8feb0f0bSmrg static tree get_vop_from_header (class loop *);
871debfc3dSmrg 
881debfc3dSmrg /* Main entry point.  Perform loop unswitching on all suitable loops.  */
891debfc3dSmrg 
901debfc3dSmrg unsigned int
tree_ssa_unswitch_loops(void)911debfc3dSmrg tree_ssa_unswitch_loops (void)
921debfc3dSmrg {
93*8feb0f0bSmrg   class loop *loop;
941debfc3dSmrg   bool changed = false;
951debfc3dSmrg 
961debfc3dSmrg   /* Go through all loops starting from innermost.  */
971debfc3dSmrg   FOR_EACH_LOOP (loop, LI_FROM_INNERMOST)
981debfc3dSmrg     {
991debfc3dSmrg       if (!loop->inner)
1001debfc3dSmrg 	/* Unswitch innermost loop.  */
1011debfc3dSmrg 	changed |= tree_unswitch_single_loop (loop, 0);
1021debfc3dSmrg       else
1031debfc3dSmrg 	changed |= tree_unswitch_outer_loop (loop);
1041debfc3dSmrg     }
1051debfc3dSmrg 
1061debfc3dSmrg   if (changed)
1071debfc3dSmrg     return TODO_cleanup_cfg;
1081debfc3dSmrg   return 0;
1091debfc3dSmrg }
1101debfc3dSmrg 
1111debfc3dSmrg /* Return TRUE if an SSA_NAME maybe undefined and is therefore
1121debfc3dSmrg    unsuitable for unswitching.  STMT is the statement we are
1131debfc3dSmrg    considering for unswitching and LOOP is the loop it appears in.  */
1141debfc3dSmrg 
1151debfc3dSmrg static bool
is_maybe_undefined(const tree name,gimple * stmt,class loop * loop)116*8feb0f0bSmrg is_maybe_undefined (const tree name, gimple *stmt, class loop *loop)
1171debfc3dSmrg {
1181debfc3dSmrg   /* The loop header is the only block we can trivially determine that
1191debfc3dSmrg      will always be executed.  If the comparison is in the loop
1201debfc3dSmrg      header, we know it's OK to unswitch on it.  */
1211debfc3dSmrg   if (gimple_bb (stmt) == loop->header)
1221debfc3dSmrg     return false;
1231debfc3dSmrg 
1241debfc3dSmrg   auto_bitmap visited_ssa;
1251debfc3dSmrg   auto_vec<tree> worklist;
1261debfc3dSmrg   worklist.safe_push (name);
1271debfc3dSmrg   bitmap_set_bit (visited_ssa, SSA_NAME_VERSION (name));
1281debfc3dSmrg   while (!worklist.is_empty ())
1291debfc3dSmrg     {
1301debfc3dSmrg       tree t = worklist.pop ();
1311debfc3dSmrg 
1321debfc3dSmrg       /* If it's obviously undefined, avoid further computations.  */
1331debfc3dSmrg       if (ssa_undefined_value_p (t, true))
1341debfc3dSmrg 	return true;
1351debfc3dSmrg 
1361debfc3dSmrg       if (ssa_defined_default_def_p (t))
1371debfc3dSmrg 	continue;
1381debfc3dSmrg 
1391debfc3dSmrg       gimple *def = SSA_NAME_DEF_STMT (t);
1401debfc3dSmrg 
1411debfc3dSmrg       /* Check that all the PHI args are fully defined.  */
1421debfc3dSmrg       if (gphi *phi = dyn_cast <gphi *> (def))
1431debfc3dSmrg 	{
1441debfc3dSmrg 	  for (unsigned i = 0; i < gimple_phi_num_args (phi); ++i)
1451debfc3dSmrg 	    {
1461debfc3dSmrg 	      tree t = gimple_phi_arg_def (phi, i);
1471debfc3dSmrg 	      /* If an SSA has already been seen, it may be a loop,
1481debfc3dSmrg 		 but we can continue and ignore this use.  Otherwise,
1491debfc3dSmrg 		 add the SSA_NAME to the queue and visit it later.  */
1501debfc3dSmrg 	      if (TREE_CODE (t) == SSA_NAME
1511debfc3dSmrg 		  && bitmap_set_bit (visited_ssa, SSA_NAME_VERSION (t)))
1521debfc3dSmrg 		worklist.safe_push (t);
1531debfc3dSmrg 	    }
1541debfc3dSmrg 	  continue;
1551debfc3dSmrg 	}
1561debfc3dSmrg 
1571debfc3dSmrg       /* Uses in stmts always executed when the region header executes
1581debfc3dSmrg 	 are fine.  */
1591debfc3dSmrg       if (dominated_by_p (CDI_DOMINATORS, loop->header, gimple_bb (def)))
1601debfc3dSmrg 	continue;
1611debfc3dSmrg 
1621debfc3dSmrg       /* Handle calls and memory loads conservatively.  */
1631debfc3dSmrg       if (!is_gimple_assign (def)
1641debfc3dSmrg 	  || (gimple_assign_single_p (def)
1651debfc3dSmrg 	      && gimple_vuse (def)))
1661debfc3dSmrg 	return true;
1671debfc3dSmrg 
1681debfc3dSmrg       /* Check that any SSA names used to define NAME are also fully
1691debfc3dSmrg 	 defined.  */
1701debfc3dSmrg       use_operand_p use_p;
1711debfc3dSmrg       ssa_op_iter iter;
1721debfc3dSmrg       FOR_EACH_SSA_USE_OPERAND (use_p, def, iter, SSA_OP_USE)
1731debfc3dSmrg 	{
1741debfc3dSmrg 	  tree t = USE_FROM_PTR (use_p);
1751debfc3dSmrg 	  /* If an SSA has already been seen, it may be a loop,
1761debfc3dSmrg 	     but we can continue and ignore this use.  Otherwise,
1771debfc3dSmrg 	     add the SSA_NAME to the queue and visit it later.  */
1781debfc3dSmrg 	  if (bitmap_set_bit (visited_ssa, SSA_NAME_VERSION (t)))
1791debfc3dSmrg 	    worklist.safe_push (t);
1801debfc3dSmrg 	}
1811debfc3dSmrg     }
1821debfc3dSmrg   return false;
1831debfc3dSmrg }
1841debfc3dSmrg 
1851debfc3dSmrg /* Checks whether we can unswitch LOOP on condition at end of BB -- one of its
1861debfc3dSmrg    basic blocks (for what it means see comments below).  */
1871debfc3dSmrg 
1881debfc3dSmrg static tree
tree_may_unswitch_on(basic_block bb,class loop * loop)189*8feb0f0bSmrg tree_may_unswitch_on (basic_block bb, class loop *loop)
1901debfc3dSmrg {
1911debfc3dSmrg   gimple *last, *def;
1921debfc3dSmrg   gcond *stmt;
1931debfc3dSmrg   tree cond, use;
1941debfc3dSmrg   basic_block def_bb;
1951debfc3dSmrg   ssa_op_iter iter;
1961debfc3dSmrg 
1971debfc3dSmrg   /* BB must end in a simple conditional jump.  */
1981debfc3dSmrg   last = last_stmt (bb);
1991debfc3dSmrg   if (!last || gimple_code (last) != GIMPLE_COND)
2001debfc3dSmrg     return NULL_TREE;
2011debfc3dSmrg   stmt = as_a <gcond *> (last);
2021debfc3dSmrg 
2031debfc3dSmrg   /* To keep the things simple, we do not directly remove the conditions,
2041debfc3dSmrg      but just replace tests with 0 != 0 resp. 1 != 0.  Prevent the infinite
2051debfc3dSmrg      loop where we would unswitch again on such a condition.  */
2061debfc3dSmrg   if (gimple_cond_true_p (stmt) || gimple_cond_false_p (stmt))
2071debfc3dSmrg     return NULL_TREE;
2081debfc3dSmrg 
2091debfc3dSmrg   /* Condition must be invariant.  */
2101debfc3dSmrg   FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE)
2111debfc3dSmrg     {
2121debfc3dSmrg       def = SSA_NAME_DEF_STMT (use);
2131debfc3dSmrg       def_bb = gimple_bb (def);
2141debfc3dSmrg       if (def_bb
2151debfc3dSmrg 	  && flow_bb_inside_loop_p (loop, def_bb))
2161debfc3dSmrg 	return NULL_TREE;
2171debfc3dSmrg       /* Unswitching on undefined values would introduce undefined
2181debfc3dSmrg 	 behavior that the original program might never exercise.  */
2191debfc3dSmrg       if (is_maybe_undefined (use, stmt, loop))
2201debfc3dSmrg 	return NULL_TREE;
2211debfc3dSmrg     }
2221debfc3dSmrg 
2231debfc3dSmrg   cond = build2 (gimple_cond_code (stmt), boolean_type_node,
2241debfc3dSmrg 		 gimple_cond_lhs (stmt), gimple_cond_rhs (stmt));
2251debfc3dSmrg 
2261debfc3dSmrg   return cond;
2271debfc3dSmrg }
2281debfc3dSmrg 
2291debfc3dSmrg /* Simplifies COND using checks in front of the entry of the LOOP.  Just very
2301debfc3dSmrg    simplish (sufficient to prevent us from duplicating loop in unswitching
2311debfc3dSmrg    unnecessarily).  */
2321debfc3dSmrg 
2331debfc3dSmrg static tree
simplify_using_entry_checks(class loop * loop,tree cond)234*8feb0f0bSmrg simplify_using_entry_checks (class loop *loop, tree cond)
2351debfc3dSmrg {
2361debfc3dSmrg   edge e = loop_preheader_edge (loop);
2371debfc3dSmrg   gimple *stmt;
2381debfc3dSmrg 
2391debfc3dSmrg   while (1)
2401debfc3dSmrg     {
2411debfc3dSmrg       stmt = last_stmt (e->src);
2421debfc3dSmrg       if (stmt
2431debfc3dSmrg 	  && gimple_code (stmt) == GIMPLE_COND
2441debfc3dSmrg 	  && gimple_cond_code (stmt) == TREE_CODE (cond)
2451debfc3dSmrg 	  && operand_equal_p (gimple_cond_lhs (stmt),
2461debfc3dSmrg 			      TREE_OPERAND (cond, 0), 0)
2471debfc3dSmrg 	  && operand_equal_p (gimple_cond_rhs (stmt),
2481debfc3dSmrg 			      TREE_OPERAND (cond, 1), 0))
2491debfc3dSmrg 	return (e->flags & EDGE_TRUE_VALUE
2501debfc3dSmrg 		? boolean_true_node
2511debfc3dSmrg 		: boolean_false_node);
2521debfc3dSmrg 
2531debfc3dSmrg       if (!single_pred_p (e->src))
2541debfc3dSmrg 	return cond;
2551debfc3dSmrg 
2561debfc3dSmrg       e = single_pred_edge (e->src);
2571debfc3dSmrg       if (e->src == ENTRY_BLOCK_PTR_FOR_FN (cfun))
2581debfc3dSmrg 	return cond;
2591debfc3dSmrg     }
2601debfc3dSmrg }
2611debfc3dSmrg 
2621debfc3dSmrg /* Unswitch single LOOP.  NUM is number of unswitchings done; we do not allow
2631debfc3dSmrg    it to grow too much, it is too easy to create example on that the code would
2641debfc3dSmrg    grow exponentially.  */
2651debfc3dSmrg 
2661debfc3dSmrg static bool
tree_unswitch_single_loop(class loop * loop,int num)267*8feb0f0bSmrg tree_unswitch_single_loop (class loop *loop, int num)
2681debfc3dSmrg {
2691debfc3dSmrg   basic_block *bbs;
270*8feb0f0bSmrg   class loop *nloop;
2711debfc3dSmrg   unsigned i, found;
2721debfc3dSmrg   tree cond = NULL_TREE;
2731debfc3dSmrg   gimple *stmt;
2741debfc3dSmrg   bool changed = false;
2751debfc3dSmrg   HOST_WIDE_INT iterations;
2761debfc3dSmrg 
2771debfc3dSmrg   /* Perform initial tests if unswitch is eligible.  */
2781debfc3dSmrg   if (num == 0)
2791debfc3dSmrg     {
2801debfc3dSmrg       /* Do not unswitch in cold regions. */
2811debfc3dSmrg       if (optimize_loop_for_size_p (loop))
2821debfc3dSmrg 	{
2831debfc3dSmrg 	  if (dump_file && (dump_flags & TDF_DETAILS))
2841debfc3dSmrg 	    fprintf (dump_file, ";; Not unswitching cold loops\n");
2851debfc3dSmrg 	  return false;
2861debfc3dSmrg 	}
2871debfc3dSmrg 
2881debfc3dSmrg       /* The loop should not be too large, to limit code growth. */
2891debfc3dSmrg       if (tree_num_loop_insns (loop, &eni_size_weights)
290*8feb0f0bSmrg 	  > (unsigned) param_max_unswitch_insns)
2911debfc3dSmrg 	{
2921debfc3dSmrg 	  if (dump_file && (dump_flags & TDF_DETAILS))
2931debfc3dSmrg 	    fprintf (dump_file, ";; Not unswitching, loop too big\n");
2941debfc3dSmrg 	  return false;
2951debfc3dSmrg 	}
2961debfc3dSmrg 
2971debfc3dSmrg       /* If the loop is not expected to iterate, there is no need
2981debfc3dSmrg 	 for unswitching.  */
2991debfc3dSmrg       iterations = estimated_loop_iterations_int (loop);
3001debfc3dSmrg       if (iterations < 0)
3011debfc3dSmrg         iterations = likely_max_loop_iterations_int (loop);
3021debfc3dSmrg       if (iterations >= 0 && iterations <= 1)
3031debfc3dSmrg 	{
3041debfc3dSmrg 	  if (dump_file && (dump_flags & TDF_DETAILS))
3051debfc3dSmrg 	    fprintf (dump_file, ";; Not unswitching, loop is not expected"
3061debfc3dSmrg 		     " to iterate\n");
3071debfc3dSmrg 	  return false;
3081debfc3dSmrg 	}
3091debfc3dSmrg     }
3101debfc3dSmrg 
3111debfc3dSmrg   i = 0;
3121debfc3dSmrg   bbs = get_loop_body (loop);
3131debfc3dSmrg   found = loop->num_nodes;
3141debfc3dSmrg 
3151debfc3dSmrg   while (1)
3161debfc3dSmrg     {
3171debfc3dSmrg       /* Find a bb to unswitch on.  */
3181debfc3dSmrg       for (; i < loop->num_nodes; i++)
3191debfc3dSmrg 	if ((cond = tree_may_unswitch_on (bbs[i], loop)))
3201debfc3dSmrg 	  break;
3211debfc3dSmrg 
3221debfc3dSmrg       if (i == loop->num_nodes)
3231debfc3dSmrg 	{
3241debfc3dSmrg 	  if (dump_file
325*8feb0f0bSmrg 	      && num > param_max_unswitch_level
3261debfc3dSmrg 	      && (dump_flags & TDF_DETAILS))
3271debfc3dSmrg 	    fprintf (dump_file, ";; Not unswitching anymore, hit max level\n");
3281debfc3dSmrg 
3291debfc3dSmrg 	  if (found == loop->num_nodes)
3301debfc3dSmrg 	    {
3311debfc3dSmrg 	      free (bbs);
3321debfc3dSmrg 	      return changed;
3331debfc3dSmrg 	    }
3341debfc3dSmrg 	  break;
3351debfc3dSmrg 	}
3361debfc3dSmrg 
3371debfc3dSmrg       cond = simplify_using_entry_checks (loop, cond);
3381debfc3dSmrg       stmt = last_stmt (bbs[i]);
3391debfc3dSmrg       if (integer_nonzerop (cond))
3401debfc3dSmrg 	{
3411debfc3dSmrg 	  /* Remove false path.  */
3421debfc3dSmrg 	  gimple_cond_set_condition_from_tree (as_a <gcond *> (stmt),
3431debfc3dSmrg 					       boolean_true_node);
3441debfc3dSmrg 	  changed = true;
3451debfc3dSmrg 	}
3461debfc3dSmrg       else if (integer_zerop (cond))
3471debfc3dSmrg 	{
3481debfc3dSmrg 	  /* Remove true path.  */
3491debfc3dSmrg 	  gimple_cond_set_condition_from_tree (as_a <gcond *> (stmt),
3501debfc3dSmrg 					       boolean_false_node);
3511debfc3dSmrg 	  changed = true;
3521debfc3dSmrg 	}
3531debfc3dSmrg       /* Do not unswitch too much.  */
354*8feb0f0bSmrg       else if (num > param_max_unswitch_level)
3551debfc3dSmrg 	{
3561debfc3dSmrg 	  i++;
3571debfc3dSmrg 	  continue;
3581debfc3dSmrg 	}
3591debfc3dSmrg       /* In nested tree_unswitch_single_loop first optimize all conditions
3601debfc3dSmrg 	 using entry checks, then discover still reachable blocks in the
3611debfc3dSmrg 	 loop and find the condition only among those still reachable bbs.  */
3621debfc3dSmrg       else if (num != 0)
3631debfc3dSmrg 	{
3641debfc3dSmrg 	  if (found == loop->num_nodes)
3651debfc3dSmrg 	    found = i;
3661debfc3dSmrg 	  i++;
3671debfc3dSmrg 	  continue;
3681debfc3dSmrg 	}
3691debfc3dSmrg       else
3701debfc3dSmrg 	{
3711debfc3dSmrg 	  found = i;
3721debfc3dSmrg 	  break;
3731debfc3dSmrg 	}
3741debfc3dSmrg 
3751debfc3dSmrg       update_stmt (stmt);
3761debfc3dSmrg       i++;
3771debfc3dSmrg     }
3781debfc3dSmrg 
3791debfc3dSmrg   if (num != 0)
3801debfc3dSmrg     {
3811debfc3dSmrg       basic_block *tos, *worklist;
3821debfc3dSmrg 
3831debfc3dSmrg       /* When called recursively, first do a quick discovery
3841debfc3dSmrg 	 of reachable bbs after the above changes and only
3851debfc3dSmrg 	 consider conditions in still reachable bbs.  */
3861debfc3dSmrg       tos = worklist = XNEWVEC (basic_block, loop->num_nodes);
3871debfc3dSmrg 
3881debfc3dSmrg       for (i = 0; i < loop->num_nodes; i++)
3891debfc3dSmrg 	bbs[i]->flags &= ~BB_REACHABLE;
3901debfc3dSmrg 
3911debfc3dSmrg       /* Start with marking header.  */
3921debfc3dSmrg       *tos++ = bbs[0];
3931debfc3dSmrg       bbs[0]->flags |= BB_REACHABLE;
3941debfc3dSmrg 
3951debfc3dSmrg       /* Iterate: find everything reachable from what we've already seen
3961debfc3dSmrg 	 within the same innermost loop.  Don't look through false edges
3971debfc3dSmrg 	 if condition is always true or true edges if condition is
3981debfc3dSmrg 	 always false.  */
3991debfc3dSmrg       while (tos != worklist)
4001debfc3dSmrg 	{
4011debfc3dSmrg 	  basic_block b = *--tos;
4021debfc3dSmrg 	  edge e;
4031debfc3dSmrg 	  edge_iterator ei;
4041debfc3dSmrg 	  int flags = 0;
4051debfc3dSmrg 
4061debfc3dSmrg 	  if (EDGE_COUNT (b->succs) == 2)
4071debfc3dSmrg 	    {
4081debfc3dSmrg 	      gimple *stmt = last_stmt (b);
4091debfc3dSmrg 	      if (stmt
4101debfc3dSmrg 		  && gimple_code (stmt) == GIMPLE_COND)
4111debfc3dSmrg 		{
4121debfc3dSmrg 		  gcond *cond_stmt = as_a <gcond *> (stmt);
4131debfc3dSmrg 		  if (gimple_cond_true_p (cond_stmt))
4141debfc3dSmrg 		    flags = EDGE_FALSE_VALUE;
4151debfc3dSmrg 		  else if (gimple_cond_false_p (cond_stmt))
4161debfc3dSmrg 		    flags = EDGE_TRUE_VALUE;
4171debfc3dSmrg 		}
4181debfc3dSmrg 	    }
4191debfc3dSmrg 
4201debfc3dSmrg 	  FOR_EACH_EDGE (e, ei, b->succs)
4211debfc3dSmrg 	    {
4221debfc3dSmrg 	      basic_block dest = e->dest;
4231debfc3dSmrg 
4241debfc3dSmrg 	      if (dest->loop_father == loop
4251debfc3dSmrg 		  && !(dest->flags & BB_REACHABLE)
4261debfc3dSmrg 		  && !(e->flags & flags))
4271debfc3dSmrg 		{
4281debfc3dSmrg 		  *tos++ = dest;
4291debfc3dSmrg 		  dest->flags |= BB_REACHABLE;
4301debfc3dSmrg 		}
4311debfc3dSmrg 	    }
4321debfc3dSmrg 	}
4331debfc3dSmrg 
4341debfc3dSmrg       free (worklist);
4351debfc3dSmrg 
4361debfc3dSmrg       /* Find a bb to unswitch on.  */
4371debfc3dSmrg       for (; found < loop->num_nodes; found++)
4381debfc3dSmrg 	if ((bbs[found]->flags & BB_REACHABLE)
4391debfc3dSmrg 	    && (cond = tree_may_unswitch_on (bbs[found], loop)))
4401debfc3dSmrg 	  break;
4411debfc3dSmrg 
4421debfc3dSmrg       if (found == loop->num_nodes)
4431debfc3dSmrg 	{
4441debfc3dSmrg 	  free (bbs);
4451debfc3dSmrg 	  return changed;
4461debfc3dSmrg 	}
4471debfc3dSmrg     }
4481debfc3dSmrg 
4491debfc3dSmrg   if (dump_file && (dump_flags & TDF_DETAILS))
4501debfc3dSmrg     fprintf (dump_file, ";; Unswitching loop\n");
4511debfc3dSmrg 
4521debfc3dSmrg   initialize_original_copy_tables ();
4531debfc3dSmrg   /* Unswitch the loop on this condition.  */
4541debfc3dSmrg   nloop = tree_unswitch_loop (loop, bbs[found], cond);
4551debfc3dSmrg   if (!nloop)
4561debfc3dSmrg     {
4571debfc3dSmrg       free_original_copy_tables ();
4581debfc3dSmrg       free (bbs);
4591debfc3dSmrg       return changed;
4601debfc3dSmrg     }
4611debfc3dSmrg 
4621debfc3dSmrg   /* Update the SSA form after unswitching.  */
4631debfc3dSmrg   update_ssa (TODO_update_ssa);
4641debfc3dSmrg   free_original_copy_tables ();
4651debfc3dSmrg 
4661debfc3dSmrg   /* Invoke itself on modified loops.  */
4671debfc3dSmrg   tree_unswitch_single_loop (nloop, num + 1);
4681debfc3dSmrg   tree_unswitch_single_loop (loop, num + 1);
4691debfc3dSmrg   free (bbs);
4701debfc3dSmrg   return true;
4711debfc3dSmrg }
4721debfc3dSmrg 
4731debfc3dSmrg /* Unswitch a LOOP w.r. to given basic block UNSWITCH_ON.  We only support
4741debfc3dSmrg    unswitching of innermost loops.  COND is the condition determining which
4751debfc3dSmrg    loop is entered -- the new loop is entered if COND is true.  Returns NULL
4761debfc3dSmrg    if impossible, new loop otherwise.  */
4771debfc3dSmrg 
478*8feb0f0bSmrg static class loop *
tree_unswitch_loop(class loop * loop,basic_block unswitch_on,tree cond)479*8feb0f0bSmrg tree_unswitch_loop (class loop *loop,
4801debfc3dSmrg 		    basic_block unswitch_on, tree cond)
4811debfc3dSmrg {
482a2dc1f3fSmrg   profile_probability prob_true;
4831debfc3dSmrg   edge edge_true, edge_false;
4841debfc3dSmrg 
4851debfc3dSmrg   /* Some sanity checking.  */
4861debfc3dSmrg   gcc_assert (flow_bb_inside_loop_p (loop, unswitch_on));
4871debfc3dSmrg   gcc_assert (EDGE_COUNT (unswitch_on->succs) == 2);
4881debfc3dSmrg   gcc_assert (loop->inner == NULL);
4891debfc3dSmrg 
4901debfc3dSmrg   extract_true_false_edges_from_block (unswitch_on, &edge_true, &edge_false);
4911debfc3dSmrg   prob_true = edge_true->probability;
4921debfc3dSmrg   return loop_version (loop, unshare_expr (cond),
493a2dc1f3fSmrg 		       NULL, prob_true,
494a2dc1f3fSmrg 		       prob_true.invert (),
495a2dc1f3fSmrg 		       prob_true, prob_true.invert (),
496a2dc1f3fSmrg 		       false);
4971debfc3dSmrg }
4981debfc3dSmrg 
4991debfc3dSmrg /* Unswitch outer loops by hoisting invariant guard on
5001debfc3dSmrg    inner loop without code duplication.  */
5011debfc3dSmrg static bool
tree_unswitch_outer_loop(class loop * loop)502*8feb0f0bSmrg tree_unswitch_outer_loop (class loop *loop)
5031debfc3dSmrg {
5041debfc3dSmrg   edge exit, guard;
5051debfc3dSmrg   HOST_WIDE_INT iterations;
5061debfc3dSmrg 
5071debfc3dSmrg   gcc_assert (loop->inner);
5081debfc3dSmrg   if (loop->inner->next)
5091debfc3dSmrg     return false;
5101debfc3dSmrg   /* Accept loops with single exit only which is not from inner loop.  */
5111debfc3dSmrg   exit = single_exit (loop);
5121debfc3dSmrg   if (!exit || exit->src->loop_father != loop)
5131debfc3dSmrg     return false;
5141debfc3dSmrg   /* Check that phi argument of exit edge is not defined inside loop.  */
5151debfc3dSmrg   if (!check_exit_phi (loop))
5161debfc3dSmrg     return false;
5171debfc3dSmrg   /* If the loop is not expected to iterate, there is no need
5181debfc3dSmrg       for unswitching.  */
5191debfc3dSmrg   iterations = estimated_loop_iterations_int (loop);
5201debfc3dSmrg   if (iterations < 0)
5211debfc3dSmrg     iterations = likely_max_loop_iterations_int (loop);
5221debfc3dSmrg   if (iterations >= 0 && iterations <= 1)
5231debfc3dSmrg     {
5241debfc3dSmrg       if (dump_file && (dump_flags & TDF_DETAILS))
5251debfc3dSmrg 	fprintf (dump_file, ";; Not unswitching, loop is not expected"
5261debfc3dSmrg 		 " to iterate\n");
5271debfc3dSmrg       return false;
5281debfc3dSmrg     }
5291debfc3dSmrg 
5301debfc3dSmrg   bool changed = false;
5311debfc3dSmrg   while ((guard = find_loop_guard (loop)))
5321debfc3dSmrg     {
5331debfc3dSmrg       if (! changed)
5341debfc3dSmrg 	rewrite_virtuals_into_loop_closed_ssa (loop);
5351debfc3dSmrg       hoist_guard (loop, guard);
5361debfc3dSmrg       changed = true;
5371debfc3dSmrg     }
5381debfc3dSmrg   return changed;
5391debfc3dSmrg }
5401debfc3dSmrg 
5411debfc3dSmrg /* Checks if the body of the LOOP is within an invariant guard.  If this
5421debfc3dSmrg    is the case, returns the edge that jumps over the real body of the loop,
5431debfc3dSmrg    otherwise returns NULL.  */
5441debfc3dSmrg 
5451debfc3dSmrg static edge
find_loop_guard(class loop * loop)546*8feb0f0bSmrg find_loop_guard (class loop *loop)
5471debfc3dSmrg {
5481debfc3dSmrg   basic_block header = loop->header;
5491debfc3dSmrg   edge guard_edge, te, fe;
5501debfc3dSmrg   basic_block *body = NULL;
5511debfc3dSmrg   unsigned i;
5521debfc3dSmrg   tree use;
5531debfc3dSmrg   ssa_op_iter iter;
5541debfc3dSmrg 
5551debfc3dSmrg   /* We check for the following situation:
5561debfc3dSmrg 
5571debfc3dSmrg      while (1)
5581debfc3dSmrg        {
5591debfc3dSmrg 	 [header]]
5601debfc3dSmrg          loop_phi_nodes;
5611debfc3dSmrg 	 something1;
5621debfc3dSmrg 	 if (cond1)
5631debfc3dSmrg 	   body;
5641debfc3dSmrg 	 nvar = phi(orig, bvar) ... for all variables changed in body;
5651debfc3dSmrg 	 [guard_end]
5661debfc3dSmrg 	 something2;
5671debfc3dSmrg 	 if (cond2)
5681debfc3dSmrg 	   break;
5691debfc3dSmrg 	 something3;
5701debfc3dSmrg        }
5711debfc3dSmrg 
5721debfc3dSmrg      where:
5731debfc3dSmrg 
5741debfc3dSmrg      1) cond1 is loop invariant
5751debfc3dSmrg      2) If cond1 is false, then the loop is essentially empty; i.e.,
5761debfc3dSmrg 	a) nothing in something1, something2 and something3 has side
5771debfc3dSmrg 	   effects
5781debfc3dSmrg 	b) anything defined in something1, something2 and something3
5791debfc3dSmrg 	   is not used outside of the loop.  */
5801debfc3dSmrg 
5811debfc3dSmrg   gcond *cond;
5821debfc3dSmrg   do
5831debfc3dSmrg     {
5841debfc3dSmrg       basic_block next = NULL;
5851debfc3dSmrg       if (single_succ_p (header))
5861debfc3dSmrg 	next = single_succ (header);
5871debfc3dSmrg       else
5881debfc3dSmrg 	{
589*8feb0f0bSmrg 	  cond = safe_dyn_cast <gcond *> (last_stmt (header));
5901debfc3dSmrg 	  if (! cond)
5911debfc3dSmrg 	    return NULL;
5921debfc3dSmrg 	  extract_true_false_edges_from_block (header, &te, &fe);
5931debfc3dSmrg 	  /* Make sure to skip earlier hoisted guards that are left
5941debfc3dSmrg 	     in place as if (true).  */
5951debfc3dSmrg 	  if (gimple_cond_true_p (cond))
5961debfc3dSmrg 	    next = te->dest;
5971debfc3dSmrg 	  else if (gimple_cond_false_p (cond))
5981debfc3dSmrg 	    next = fe->dest;
5991debfc3dSmrg 	  else
6001debfc3dSmrg 	    break;
6011debfc3dSmrg 	}
6021debfc3dSmrg       /* Never traverse a backedge.  */
6031debfc3dSmrg       if (header->loop_father->header == next)
6041debfc3dSmrg 	return NULL;
6051debfc3dSmrg       header = next;
6061debfc3dSmrg     }
6071debfc3dSmrg   while (1);
6081debfc3dSmrg   if (!flow_bb_inside_loop_p (loop, te->dest)
6091debfc3dSmrg       || !flow_bb_inside_loop_p (loop, fe->dest))
6101debfc3dSmrg     return NULL;
6111debfc3dSmrg 
6121debfc3dSmrg   if (just_once_each_iteration_p (loop, te->dest)
6131debfc3dSmrg       || (single_succ_p (te->dest)
6141debfc3dSmrg 	  && just_once_each_iteration_p (loop, single_succ (te->dest))))
6151debfc3dSmrg     {
6161debfc3dSmrg       if (just_once_each_iteration_p (loop, fe->dest))
6171debfc3dSmrg 	return NULL;
6181debfc3dSmrg       guard_edge = te;
6191debfc3dSmrg     }
6201debfc3dSmrg   else if (just_once_each_iteration_p (loop, fe->dest)
6211debfc3dSmrg 	   || (single_succ_p (fe->dest)
6221debfc3dSmrg 	       && just_once_each_iteration_p (loop, single_succ (fe->dest))))
6231debfc3dSmrg     guard_edge = fe;
6241debfc3dSmrg   else
6251debfc3dSmrg     return NULL;
6261debfc3dSmrg 
6271debfc3dSmrg   /* Guard edge must skip inner loop.  */
6281debfc3dSmrg   if (!dominated_by_p (CDI_DOMINATORS, loop->inner->header,
6291debfc3dSmrg       guard_edge == fe ? te->dest : fe->dest))
6301debfc3dSmrg     {
6311debfc3dSmrg       if (dump_file && (dump_flags & TDF_DETAILS))
6321debfc3dSmrg 	fprintf (dump_file, "Guard edge %d --> %d is not around the loop!\n",
6331debfc3dSmrg 		 guard_edge->src->index, guard_edge->dest->index);
6341debfc3dSmrg       return NULL;
6351debfc3dSmrg     }
6361debfc3dSmrg   if (guard_edge->dest == loop->latch)
6371debfc3dSmrg     {
6381debfc3dSmrg       if (dump_file && (dump_flags & TDF_DETAILS))
6391debfc3dSmrg 	fprintf (dump_file, "Guard edge destination is loop latch.\n");
6401debfc3dSmrg       return NULL;
6411debfc3dSmrg     }
6421debfc3dSmrg 
6431debfc3dSmrg   if (dump_file && (dump_flags & TDF_DETAILS))
6441debfc3dSmrg     fprintf (dump_file,
6451debfc3dSmrg 	     "Considering guard %d -> %d in loop %d\n",
6461debfc3dSmrg 	     guard_edge->src->index, guard_edge->dest->index, loop->num);
6471debfc3dSmrg   /* Check if condition operands do not have definitions inside loop since
6481debfc3dSmrg      any bb copying is not performed.  */
6491debfc3dSmrg   FOR_EACH_SSA_TREE_OPERAND (use, cond, iter, SSA_OP_USE)
6501debfc3dSmrg     {
6511debfc3dSmrg       gimple *def = SSA_NAME_DEF_STMT (use);
6521debfc3dSmrg       basic_block def_bb = gimple_bb (def);
6531debfc3dSmrg       if (def_bb
6541debfc3dSmrg           && flow_bb_inside_loop_p (loop, def_bb))
6551debfc3dSmrg 	{
6561debfc3dSmrg 	  if (dump_file && (dump_flags & TDF_DETAILS))
6571debfc3dSmrg 	    fprintf (dump_file, "  guard operands have definitions"
6581debfc3dSmrg 				" inside loop\n");
6591debfc3dSmrg 	  return NULL;
6601debfc3dSmrg 	}
6611debfc3dSmrg     }
6621debfc3dSmrg 
6631debfc3dSmrg   body = get_loop_body (loop);
6641debfc3dSmrg   for (i = 0; i < loop->num_nodes; i++)
6651debfc3dSmrg     {
6661debfc3dSmrg       basic_block bb = body[i];
6671debfc3dSmrg       if (bb->loop_father != loop)
6681debfc3dSmrg 	continue;
6691debfc3dSmrg       if (bb->flags & BB_IRREDUCIBLE_LOOP)
6701debfc3dSmrg 	{
6711debfc3dSmrg 	  if (dump_file && (dump_flags & TDF_DETAILS))
6721debfc3dSmrg 	    fprintf (dump_file, "Block %d is marked as irreducible in loop\n",
6731debfc3dSmrg 		      bb->index);
6741debfc3dSmrg 	  guard_edge = NULL;
6751debfc3dSmrg 	  goto end;
6761debfc3dSmrg 	}
6771debfc3dSmrg       if (!empty_bb_without_guard_p (loop, bb))
6781debfc3dSmrg 	{
6791debfc3dSmrg 	  if (dump_file && (dump_flags & TDF_DETAILS))
6801debfc3dSmrg 	    fprintf (dump_file, "  block %d has side effects\n", bb->index);
6811debfc3dSmrg 	  guard_edge = NULL;
6821debfc3dSmrg 	  goto end;
6831debfc3dSmrg 	}
6841debfc3dSmrg     }
6851debfc3dSmrg 
6861debfc3dSmrg   if (dump_file && (dump_flags & TDF_DETAILS))
6871debfc3dSmrg     fprintf (dump_file, "  suitable to hoist\n");
6881debfc3dSmrg end:
6891debfc3dSmrg   if (body)
6901debfc3dSmrg     free (body);
6911debfc3dSmrg   return guard_edge;
6921debfc3dSmrg }
6931debfc3dSmrg 
6941debfc3dSmrg /* Returns true if
6951debfc3dSmrg    1) no statement in BB has side effects
6961debfc3dSmrg    2) assuming that edge GUARD is always taken, all definitions in BB
6971debfc3dSmrg       are noy used outside of the loop.
6981debfc3dSmrg    KNOWN_INVARIANTS is a set of ssa names we know to be invariant, and
6991debfc3dSmrg    PROCESSED is a set of ssa names for that we already tested whether they
7001debfc3dSmrg    are invariant or not.  */
7011debfc3dSmrg 
7021debfc3dSmrg static bool
empty_bb_without_guard_p(class loop * loop,basic_block bb)703*8feb0f0bSmrg empty_bb_without_guard_p (class loop *loop, basic_block bb)
7041debfc3dSmrg {
7051debfc3dSmrg   basic_block exit_bb = single_exit (loop)->src;
7061debfc3dSmrg   bool may_be_used_outside = (bb == exit_bb
7071debfc3dSmrg 			      || !dominated_by_p (CDI_DOMINATORS, bb, exit_bb));
7081debfc3dSmrg   tree name;
7091debfc3dSmrg   ssa_op_iter op_iter;
7101debfc3dSmrg 
7111debfc3dSmrg   /* Phi nodes do not have side effects, but their results might be used
7121debfc3dSmrg      outside of the loop.  */
7131debfc3dSmrg   if (may_be_used_outside)
7141debfc3dSmrg     {
7151debfc3dSmrg       for (gphi_iterator gsi = gsi_start_phis (bb);
7161debfc3dSmrg 	   !gsi_end_p (gsi); gsi_next (&gsi))
7171debfc3dSmrg 	{
7181debfc3dSmrg 	  gphi *phi = gsi.phi ();
7191debfc3dSmrg 	  name = PHI_RESULT (phi);
7201debfc3dSmrg 	  if (virtual_operand_p (name))
7211debfc3dSmrg 	    continue;
7221debfc3dSmrg 
7231debfc3dSmrg 	  if (used_outside_loop_p (loop, name))
7241debfc3dSmrg 	    return false;
7251debfc3dSmrg 	}
7261debfc3dSmrg     }
7271debfc3dSmrg 
7281debfc3dSmrg   for (gimple_stmt_iterator gsi = gsi_start_bb (bb);
7291debfc3dSmrg        !gsi_end_p (gsi); gsi_next (&gsi))
7301debfc3dSmrg     {
7311debfc3dSmrg       gimple *stmt = gsi_stmt (gsi);
7321debfc3dSmrg       if (gimple_has_side_effects (stmt))
7331debfc3dSmrg 	return false;
7341debfc3dSmrg 
7351debfc3dSmrg       if (gimple_vdef(stmt))
7361debfc3dSmrg 	return false;
7371debfc3dSmrg 
7381debfc3dSmrg       FOR_EACH_SSA_TREE_OPERAND (name, stmt, op_iter, SSA_OP_DEF)
7391debfc3dSmrg 	{
7401debfc3dSmrg 	  if (may_be_used_outside
7411debfc3dSmrg 	      && used_outside_loop_p (loop, name))
7421debfc3dSmrg 	    return false;
7431debfc3dSmrg 	}
7441debfc3dSmrg     }
7451debfc3dSmrg   return true;
7461debfc3dSmrg }
7471debfc3dSmrg 
7481debfc3dSmrg /* Return true if NAME is used outside of LOOP.  */
7491debfc3dSmrg 
7501debfc3dSmrg static bool
used_outside_loop_p(class loop * loop,tree name)751*8feb0f0bSmrg used_outside_loop_p (class loop *loop, tree name)
7521debfc3dSmrg {
7531debfc3dSmrg   imm_use_iterator it;
7541debfc3dSmrg   use_operand_p use;
7551debfc3dSmrg 
7561debfc3dSmrg   FOR_EACH_IMM_USE_FAST (use, it, name)
7571debfc3dSmrg     {
7581debfc3dSmrg       gimple *stmt = USE_STMT (use);
7591debfc3dSmrg       if (!flow_bb_inside_loop_p (loop, gimple_bb (stmt)))
7601debfc3dSmrg 	return true;
7611debfc3dSmrg     }
7621debfc3dSmrg 
7631debfc3dSmrg   return false;
7641debfc3dSmrg }
7651debfc3dSmrg 
7661debfc3dSmrg /* Return argument for loop preheader edge in header virtual phi if any.  */
7671debfc3dSmrg 
7681debfc3dSmrg static tree
get_vop_from_header(class loop * loop)769*8feb0f0bSmrg get_vop_from_header (class loop *loop)
7701debfc3dSmrg {
7711debfc3dSmrg   for (gphi_iterator gsi = gsi_start_phis (loop->header);
7721debfc3dSmrg        !gsi_end_p (gsi); gsi_next (&gsi))
7731debfc3dSmrg     {
7741debfc3dSmrg       gphi *phi = gsi.phi ();
7751debfc3dSmrg       if (!virtual_operand_p (gimple_phi_result (phi)))
7761debfc3dSmrg 	continue;
7771debfc3dSmrg       return PHI_ARG_DEF_FROM_EDGE (phi, loop_preheader_edge (loop));
7781debfc3dSmrg     }
7791debfc3dSmrg   return NULL_TREE;
7801debfc3dSmrg }
7811debfc3dSmrg 
7821debfc3dSmrg /* Move the check of GUARD outside of LOOP.  */
7831debfc3dSmrg 
7841debfc3dSmrg static void
hoist_guard(class loop * loop,edge guard)785*8feb0f0bSmrg hoist_guard (class loop *loop, edge guard)
7861debfc3dSmrg {
7871debfc3dSmrg   edge exit = single_exit (loop);
7881debfc3dSmrg   edge preh = loop_preheader_edge (loop);
7891debfc3dSmrg   basic_block pre_header = preh->src;
7901debfc3dSmrg   basic_block bb;
7911debfc3dSmrg   edge te, fe, e, new_edge;
7921debfc3dSmrg   gimple *stmt;
7931debfc3dSmrg   basic_block guard_bb = guard->src;
7941debfc3dSmrg   edge not_guard;
7951debfc3dSmrg   gimple_stmt_iterator gsi;
7961debfc3dSmrg   int flags = 0;
7971debfc3dSmrg   bool fix_dom_of_exit;
7981debfc3dSmrg   gcond *cond_stmt, *new_cond_stmt;
7991debfc3dSmrg 
8001debfc3dSmrg   bb = get_immediate_dominator (CDI_DOMINATORS, exit->dest);
8011debfc3dSmrg   fix_dom_of_exit = flow_bb_inside_loop_p (loop, bb);
8021debfc3dSmrg   gsi = gsi_last_bb (guard_bb);
8031debfc3dSmrg   stmt = gsi_stmt (gsi);
8041debfc3dSmrg   gcc_assert (gimple_code (stmt) == GIMPLE_COND);
8051debfc3dSmrg   cond_stmt = as_a <gcond *> (stmt);
8061debfc3dSmrg   extract_true_false_edges_from_block (guard_bb, &te, &fe);
8071debfc3dSmrg   /* Insert guard to PRE_HEADER.  */
8081debfc3dSmrg   if (!empty_block_p (pre_header))
8091debfc3dSmrg     gsi = gsi_last_bb (pre_header);
8101debfc3dSmrg   else
8111debfc3dSmrg     gsi = gsi_start_bb (pre_header);
8121debfc3dSmrg   /* Create copy of COND_STMT.  */
8131debfc3dSmrg   new_cond_stmt = gimple_build_cond (gimple_cond_code (cond_stmt),
8141debfc3dSmrg 				     gimple_cond_lhs (cond_stmt),
8151debfc3dSmrg 				     gimple_cond_rhs (cond_stmt),
8161debfc3dSmrg 				     NULL_TREE, NULL_TREE);
8171debfc3dSmrg   gsi_insert_after (&gsi, new_cond_stmt, GSI_NEW_STMT);
8181debfc3dSmrg   /* Convert COND_STMT to true/false conditional.  */
8191debfc3dSmrg   if (guard == te)
8201debfc3dSmrg     gimple_cond_make_false (cond_stmt);
8211debfc3dSmrg   else
8221debfc3dSmrg     gimple_cond_make_true (cond_stmt);
8231debfc3dSmrg   update_stmt (cond_stmt);
8241debfc3dSmrg   /* Create new loop pre-header.  */
8251debfc3dSmrg   e = split_block (pre_header, last_stmt (pre_header));
8261debfc3dSmrg   if (dump_file && (dump_flags & TDF_DETAILS))
827a2dc1f3fSmrg     {
828a2dc1f3fSmrg       fprintf (dump_file, "  Moving guard %i->%i (prob ",
829a2dc1f3fSmrg 	       guard->src->index, guard->dest->index);
830a2dc1f3fSmrg       guard->probability.dump (dump_file);
831a2dc1f3fSmrg       fprintf (dump_file, ") to bb %i, new preheader is %i\n",
8321debfc3dSmrg 	       e->src->index, e->dest->index);
833a2dc1f3fSmrg     }
8341debfc3dSmrg 
8351debfc3dSmrg   gcc_assert (loop_preheader_edge (loop)->src == e->dest);
8361debfc3dSmrg 
8371debfc3dSmrg   if (guard == fe)
8381debfc3dSmrg     {
8391debfc3dSmrg       e->flags = EDGE_TRUE_VALUE;
8401debfc3dSmrg       flags |= EDGE_FALSE_VALUE;
8411debfc3dSmrg       not_guard = te;
8421debfc3dSmrg     }
8431debfc3dSmrg   else
8441debfc3dSmrg     {
8451debfc3dSmrg       e->flags = EDGE_FALSE_VALUE;
8461debfc3dSmrg       flags |= EDGE_TRUE_VALUE;
8471debfc3dSmrg       not_guard = fe;
8481debfc3dSmrg     }
8491debfc3dSmrg   new_edge = make_edge (pre_header, exit->dest, flags);
8501debfc3dSmrg 
8511debfc3dSmrg   /* Determine the probability that we skip the loop.  Assume that loop has
8521debfc3dSmrg      same average number of iterations regardless outcome of guard.  */
8531debfc3dSmrg   new_edge->probability = guard->probability;
854a2dc1f3fSmrg   profile_count skip_count = guard->src->count.nonzero_p ()
855a2dc1f3fSmrg 		   ? guard->count ().apply_scale (pre_header->count,
856a2dc1f3fSmrg 					       guard->src->count)
857a2dc1f3fSmrg 		   : guard->count ().apply_probability (new_edge->probability);
8581debfc3dSmrg 
859a2dc1f3fSmrg   if (skip_count > e->count ())
8601debfc3dSmrg     {
8611debfc3dSmrg       fprintf (dump_file, "  Capping count; expect profile inconsistency\n");
862a2dc1f3fSmrg       skip_count = e->count ();
8631debfc3dSmrg     }
8641debfc3dSmrg   if (dump_file && (dump_flags & TDF_DETAILS))
865a2dc1f3fSmrg     {
866a2dc1f3fSmrg       fprintf (dump_file, "  Estimated probability of skipping loop is ");
867a2dc1f3fSmrg       new_edge->probability.dump (dump_file);
868a2dc1f3fSmrg       fprintf (dump_file, "\n");
869a2dc1f3fSmrg     }
8701debfc3dSmrg 
8711debfc3dSmrg   /* Update profile after the transform:
8721debfc3dSmrg 
8731debfc3dSmrg      First decrease count of path from newly hoisted loop guard
8741debfc3dSmrg      to loop header...  */
875a2dc1f3fSmrg   e->probability = new_edge->probability.invert ();
876a2dc1f3fSmrg   e->dest->count = e->count ();
8771debfc3dSmrg 
8781debfc3dSmrg   /* ... now update profile to represent that original guard will be optimized
8791debfc3dSmrg      away ...  */
880a2dc1f3fSmrg   guard->probability = profile_probability::never ();
881a2dc1f3fSmrg   not_guard->probability = profile_probability::always ();
8821debfc3dSmrg 
8831debfc3dSmrg   /* ... finally scale everything in the loop except for guarded basic blocks
8841debfc3dSmrg      where profile does not change.  */
8851debfc3dSmrg   basic_block *body = get_loop_body (loop);
8861debfc3dSmrg 
8871debfc3dSmrg   if (dump_file && (dump_flags & TDF_DETAILS))
8881debfc3dSmrg     fprintf (dump_file, "  Scaling nonguarded BBs in loop:");
8891debfc3dSmrg   for (unsigned int i = 0; i < loop->num_nodes; i++)
8901debfc3dSmrg     {
8911debfc3dSmrg       basic_block bb = body[i];
8921debfc3dSmrg       if (!dominated_by_p (CDI_DOMINATORS, bb, not_guard->dest))
8931debfc3dSmrg 	{
8941debfc3dSmrg 	  if (dump_file && (dump_flags & TDF_DETAILS))
8951debfc3dSmrg 	    fprintf (dump_file, " %i", bb->index);
896a2dc1f3fSmrg 	  if (e->probability.initialized_p ())
897a2dc1f3fSmrg             scale_bbs_frequencies (&bb, 1, e->probability);
8981debfc3dSmrg   	}
8991debfc3dSmrg     }
9001debfc3dSmrg 
9011debfc3dSmrg   if (fix_dom_of_exit)
9021debfc3dSmrg     set_immediate_dominator (CDI_DOMINATORS, exit->dest, pre_header);
9031debfc3dSmrg   /* Add NEW_ADGE argument for all phi in post-header block.  */
9041debfc3dSmrg   bb = exit->dest;
9051debfc3dSmrg   for (gphi_iterator gsi = gsi_start_phis (bb);
9061debfc3dSmrg        !gsi_end_p (gsi); gsi_next (&gsi))
9071debfc3dSmrg     {
9081debfc3dSmrg       gphi *phi = gsi.phi ();
9091debfc3dSmrg       tree arg;
9101debfc3dSmrg       if (virtual_operand_p (gimple_phi_result (phi)))
9111debfc3dSmrg 	{
9121debfc3dSmrg 	  arg = get_vop_from_header (loop);
9131debfc3dSmrg 	  if (arg == NULL_TREE)
9141debfc3dSmrg 	    /* Use exit edge argument.  */
9151debfc3dSmrg 	    arg =  PHI_ARG_DEF_FROM_EDGE (phi, exit);
9161debfc3dSmrg 	  add_phi_arg (phi, arg, new_edge, UNKNOWN_LOCATION);
9171debfc3dSmrg 	}
9181debfc3dSmrg       else
9191debfc3dSmrg 	{
9201debfc3dSmrg 	  /* Use exit edge argument.  */
9211debfc3dSmrg 	  arg = PHI_ARG_DEF_FROM_EDGE (phi, exit);
9221debfc3dSmrg 	  add_phi_arg (phi, arg, new_edge, UNKNOWN_LOCATION);
9231debfc3dSmrg 	}
9241debfc3dSmrg     }
9251debfc3dSmrg 
9261debfc3dSmrg   if (dump_file && (dump_flags & TDF_DETAILS))
9271debfc3dSmrg     fprintf (dump_file, "\n  guard hoisted.\n");
9281debfc3dSmrg 
9291debfc3dSmrg   free (body);
9301debfc3dSmrg }
9311debfc3dSmrg 
9321debfc3dSmrg /* Return true if phi argument for exit edge can be used
9331debfc3dSmrg    for edge around loop.  */
9341debfc3dSmrg 
9351debfc3dSmrg static bool
check_exit_phi(class loop * loop)936*8feb0f0bSmrg check_exit_phi (class loop *loop)
9371debfc3dSmrg {
9381debfc3dSmrg   edge exit = single_exit (loop);
9391debfc3dSmrg   basic_block pre_header = loop_preheader_edge (loop)->src;
9401debfc3dSmrg 
9411debfc3dSmrg   for (gphi_iterator gsi = gsi_start_phis (exit->dest);
9421debfc3dSmrg        !gsi_end_p (gsi); gsi_next (&gsi))
9431debfc3dSmrg     {
9441debfc3dSmrg       gphi *phi = gsi.phi ();
9451debfc3dSmrg       tree arg;
9461debfc3dSmrg       gimple *def;
9471debfc3dSmrg       basic_block def_bb;
9481debfc3dSmrg       if (virtual_operand_p (gimple_phi_result (phi)))
9491debfc3dSmrg 	continue;
9501debfc3dSmrg       arg = PHI_ARG_DEF_FROM_EDGE (phi, exit);
9511debfc3dSmrg       if (TREE_CODE (arg) != SSA_NAME)
9521debfc3dSmrg 	continue;
9531debfc3dSmrg       def = SSA_NAME_DEF_STMT (arg);
9541debfc3dSmrg       if (!def)
9551debfc3dSmrg 	continue;
9561debfc3dSmrg       def_bb = gimple_bb (def);
9571debfc3dSmrg       if (!def_bb)
9581debfc3dSmrg 	continue;
9591debfc3dSmrg       if (!dominated_by_p (CDI_DOMINATORS, pre_header, def_bb))
9601debfc3dSmrg 	/* Definition inside loop!  */
9611debfc3dSmrg 	return false;
9621debfc3dSmrg       /* Check loop closed phi invariant.  */
9631debfc3dSmrg       if (!flow_bb_inside_loop_p (def_bb->loop_father, pre_header))
9641debfc3dSmrg 	return false;
9651debfc3dSmrg     }
9661debfc3dSmrg   return true;
9671debfc3dSmrg }
9681debfc3dSmrg 
9691debfc3dSmrg /* Loop unswitching pass.  */
9701debfc3dSmrg 
9711debfc3dSmrg namespace {
9721debfc3dSmrg 
9731debfc3dSmrg const pass_data pass_data_tree_unswitch =
9741debfc3dSmrg {
9751debfc3dSmrg   GIMPLE_PASS, /* type */
9761debfc3dSmrg   "unswitch", /* name */
9771debfc3dSmrg   OPTGROUP_LOOP, /* optinfo_flags */
9781debfc3dSmrg   TV_TREE_LOOP_UNSWITCH, /* tv_id */
9791debfc3dSmrg   PROP_cfg, /* properties_required */
9801debfc3dSmrg   0, /* properties_provided */
9811debfc3dSmrg   0, /* properties_destroyed */
9821debfc3dSmrg   0, /* todo_flags_start */
9831debfc3dSmrg   0, /* todo_flags_finish */
9841debfc3dSmrg };
9851debfc3dSmrg 
9861debfc3dSmrg class pass_tree_unswitch : public gimple_opt_pass
9871debfc3dSmrg {
9881debfc3dSmrg public:
pass_tree_unswitch(gcc::context * ctxt)9891debfc3dSmrg   pass_tree_unswitch (gcc::context *ctxt)
9901debfc3dSmrg     : gimple_opt_pass (pass_data_tree_unswitch, ctxt)
9911debfc3dSmrg   {}
9921debfc3dSmrg 
9931debfc3dSmrg   /* opt_pass methods: */
gate(function *)9941debfc3dSmrg   virtual bool gate (function *) { return flag_unswitch_loops != 0; }
9951debfc3dSmrg   virtual unsigned int execute (function *);
9961debfc3dSmrg 
9971debfc3dSmrg }; // class pass_tree_unswitch
9981debfc3dSmrg 
9991debfc3dSmrg unsigned int
execute(function * fun)10001debfc3dSmrg pass_tree_unswitch::execute (function *fun)
10011debfc3dSmrg {
10021debfc3dSmrg   if (number_of_loops (fun) <= 1)
10031debfc3dSmrg     return 0;
10041debfc3dSmrg 
10051debfc3dSmrg   return tree_ssa_unswitch_loops ();
10061debfc3dSmrg }
10071debfc3dSmrg 
10081debfc3dSmrg } // anon namespace
10091debfc3dSmrg 
10101debfc3dSmrg gimple_opt_pass *
make_pass_tree_unswitch(gcc::context * ctxt)10111debfc3dSmrg make_pass_tree_unswitch (gcc::context *ctxt)
10121debfc3dSmrg {
10131debfc3dSmrg   return new pass_tree_unswitch (ctxt);
10141debfc3dSmrg }
10151debfc3dSmrg 
10161debfc3dSmrg 
1017