xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/tree-outof-ssa.c (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
11debfc3dSmrg /* Convert a program in SSA form into Normal form.
2*8feb0f0bSmrg    Copyright (C) 2004-2020 Free Software Foundation, Inc.
31debfc3dSmrg    Contributed by Andrew Macleod <amacleod@redhat.com>
41debfc3dSmrg 
51debfc3dSmrg This file is part of GCC.
61debfc3dSmrg 
71debfc3dSmrg GCC is free software; you can redistribute it and/or modify
81debfc3dSmrg it under the terms of the GNU General Public License as published by
91debfc3dSmrg the Free Software Foundation; either version 3, or (at your option)
101debfc3dSmrg any later version.
111debfc3dSmrg 
121debfc3dSmrg GCC is distributed in the hope that it will be useful,
131debfc3dSmrg but WITHOUT ANY WARRANTY; without even the implied warranty of
141debfc3dSmrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
151debfc3dSmrg GNU General Public License for more details.
161debfc3dSmrg 
171debfc3dSmrg You should have received a copy of the GNU General Public License
181debfc3dSmrg along with GCC; see the file COPYING3.  If not see
191debfc3dSmrg <http://www.gnu.org/licenses/>.  */
201debfc3dSmrg 
211debfc3dSmrg #include "config.h"
221debfc3dSmrg #include "system.h"
231debfc3dSmrg #include "coretypes.h"
241debfc3dSmrg #include "backend.h"
251debfc3dSmrg #include "rtl.h"
261debfc3dSmrg #include "tree.h"
271debfc3dSmrg #include "gimple.h"
281debfc3dSmrg #include "cfghooks.h"
291debfc3dSmrg #include "ssa.h"
30c0a68be4Smrg #include "tree-ssa.h"
311debfc3dSmrg #include "memmodel.h"
321debfc3dSmrg #include "emit-rtl.h"
331debfc3dSmrg #include "gimple-pretty-print.h"
341debfc3dSmrg #include "diagnostic-core.h"
35c0a68be4Smrg #include "tree-dfa.h"
361debfc3dSmrg #include "stor-layout.h"
371debfc3dSmrg #include "cfgrtl.h"
381debfc3dSmrg #include "cfganal.h"
391debfc3dSmrg #include "tree-eh.h"
401debfc3dSmrg #include "gimple-iterator.h"
411debfc3dSmrg #include "tree-cfg.h"
421debfc3dSmrg #include "dumpfile.h"
431debfc3dSmrg #include "tree-ssa-live.h"
441debfc3dSmrg #include "tree-ssa-ter.h"
451debfc3dSmrg #include "tree-ssa-coalesce.h"
461debfc3dSmrg #include "tree-outof-ssa.h"
471debfc3dSmrg #include "dojump.h"
481debfc3dSmrg 
491debfc3dSmrg /* FIXME: A lot of code here deals with expanding to RTL.  All that code
501debfc3dSmrg    should be in cfgexpand.c.  */
511debfc3dSmrg #include "explow.h"
521debfc3dSmrg #include "expr.h"
531debfc3dSmrg 
541debfc3dSmrg /* Return TRUE if expression STMT is suitable for replacement.  */
551debfc3dSmrg 
561debfc3dSmrg bool
ssa_is_replaceable_p(gimple * stmt)571debfc3dSmrg ssa_is_replaceable_p (gimple *stmt)
581debfc3dSmrg {
591debfc3dSmrg   use_operand_p use_p;
601debfc3dSmrg   tree def;
611debfc3dSmrg   gimple *use_stmt;
621debfc3dSmrg 
631debfc3dSmrg   /* Only consider modify stmts.  */
641debfc3dSmrg   if (!is_gimple_assign (stmt))
651debfc3dSmrg     return false;
661debfc3dSmrg 
671debfc3dSmrg   /* If the statement may throw an exception, it cannot be replaced.  */
68c0a68be4Smrg   if (stmt_could_throw_p (cfun, stmt))
691debfc3dSmrg     return false;
701debfc3dSmrg 
711debfc3dSmrg   /* Punt if there is more than 1 def.  */
721debfc3dSmrg   def = SINGLE_SSA_TREE_OPERAND (stmt, SSA_OP_DEF);
731debfc3dSmrg   if (!def)
741debfc3dSmrg     return false;
751debfc3dSmrg 
761debfc3dSmrg   /* Only consider definitions which have a single use.  */
771debfc3dSmrg   if (!single_imm_use (def, &use_p, &use_stmt))
781debfc3dSmrg     return false;
791debfc3dSmrg 
801debfc3dSmrg   /* Used in this block, but at the TOP of the block, not the end.  */
811debfc3dSmrg   if (gimple_code (use_stmt) == GIMPLE_PHI)
821debfc3dSmrg     return false;
831debfc3dSmrg 
841debfc3dSmrg   /* There must be no VDEFs.  */
851debfc3dSmrg   if (gimple_vdef (stmt))
861debfc3dSmrg     return false;
871debfc3dSmrg 
881debfc3dSmrg   /* Float expressions must go through memory if float-store is on.  */
891debfc3dSmrg   if (flag_float_store
901debfc3dSmrg       && FLOAT_TYPE_P (gimple_expr_type (stmt)))
911debfc3dSmrg     return false;
921debfc3dSmrg 
931debfc3dSmrg   /* An assignment with a register variable on the RHS is not
941debfc3dSmrg      replaceable.  */
951debfc3dSmrg   if (gimple_assign_rhs_code (stmt) == VAR_DECL
961debfc3dSmrg       && DECL_HARD_REGISTER (gimple_assign_rhs1 (stmt)))
971debfc3dSmrg     return false;
981debfc3dSmrg 
991debfc3dSmrg   /* No function calls can be replaced.  */
1001debfc3dSmrg   if (is_gimple_call (stmt))
1011debfc3dSmrg     return false;
1021debfc3dSmrg 
1031debfc3dSmrg   /* Leave any stmt with volatile operands alone as well.  */
1041debfc3dSmrg   if (gimple_has_volatile_ops (stmt))
1051debfc3dSmrg     return false;
1061debfc3dSmrg 
1071debfc3dSmrg   return true;
1081debfc3dSmrg }
1091debfc3dSmrg 
1101debfc3dSmrg 
1111debfc3dSmrg /* Used to hold all the components required to do SSA PHI elimination.
1121debfc3dSmrg    The node and pred/succ list is a simple linear list of nodes and
1131debfc3dSmrg    edges represented as pairs of nodes.
1141debfc3dSmrg 
1151debfc3dSmrg    The predecessor and successor list:  Nodes are entered in pairs, where
1161debfc3dSmrg    [0] ->PRED, [1]->SUCC.  All the even indexes in the array represent
1171debfc3dSmrg    predecessors, all the odd elements are successors.
1181debfc3dSmrg 
1191debfc3dSmrg    Rationale:
1201debfc3dSmrg    When implemented as bitmaps, very large programs SSA->Normal times were
1211debfc3dSmrg    being dominated by clearing the interference graph.
1221debfc3dSmrg 
1231debfc3dSmrg    Typically this list of edges is extremely small since it only includes
1241debfc3dSmrg    PHI results and uses from a single edge which have not coalesced with
1251debfc3dSmrg    each other.  This means that no virtual PHI nodes are included, and
1261debfc3dSmrg    empirical evidence suggests that the number of edges rarely exceed
1271debfc3dSmrg    3, and in a bootstrap of GCC, the maximum size encountered was 7.
1281debfc3dSmrg    This also limits the number of possible nodes that are involved to
1291debfc3dSmrg    rarely more than 6, and in the bootstrap of gcc, the maximum number
1301debfc3dSmrg    of nodes encountered was 12.  */
1311debfc3dSmrg 
132*8feb0f0bSmrg class elim_graph
1331debfc3dSmrg {
134*8feb0f0bSmrg public:
1351debfc3dSmrg   elim_graph (var_map map);
1361debfc3dSmrg 
1371debfc3dSmrg   /* Size of the elimination vectors.  */
1381debfc3dSmrg   int size;
1391debfc3dSmrg 
1401debfc3dSmrg   /* List of nodes in the elimination graph.  */
1411debfc3dSmrg   auto_vec<int> nodes;
1421debfc3dSmrg 
1431debfc3dSmrg   /*  The predecessor and successor edge list.  */
1441debfc3dSmrg   auto_vec<int> edge_list;
1451debfc3dSmrg 
1461debfc3dSmrg   /* Source locus on each edge */
147c0a68be4Smrg   auto_vec<location_t> edge_locus;
1481debfc3dSmrg 
1491debfc3dSmrg   /* Visited vector.  */
1501debfc3dSmrg   auto_sbitmap visited;
1511debfc3dSmrg 
1521debfc3dSmrg   /* Stack for visited nodes.  */
1531debfc3dSmrg   auto_vec<int> stack;
1541debfc3dSmrg 
1551debfc3dSmrg   /* The variable partition map.  */
1561debfc3dSmrg   var_map map;
1571debfc3dSmrg 
1581debfc3dSmrg   /* Edge being eliminated by this graph.  */
1591debfc3dSmrg   edge e;
1601debfc3dSmrg 
1611debfc3dSmrg   /* List of constant copies to emit.  These are pushed on in pairs.  */
1621debfc3dSmrg   auto_vec<int> const_dests;
1631debfc3dSmrg   auto_vec<tree> const_copies;
1641debfc3dSmrg 
1651debfc3dSmrg   /* Source locations for any constant copies.  */
166c0a68be4Smrg   auto_vec<location_t> copy_locus;
1671debfc3dSmrg };
1681debfc3dSmrg 
1691debfc3dSmrg 
1701debfc3dSmrg /* For an edge E find out a good source location to associate with
1711debfc3dSmrg    instructions inserted on edge E.  If E has an implicit goto set,
1721debfc3dSmrg    use its location.  Otherwise search instructions in predecessors
1731debfc3dSmrg    of E for a location, and use that one.  That makes sense because
1741debfc3dSmrg    we insert on edges for PHI nodes, and effects of PHIs happen on
175*8feb0f0bSmrg    the end of the predecessor conceptually.  An exception is made
176*8feb0f0bSmrg    for EH edges because we don't want to drag the source location
177*8feb0f0bSmrg    of unrelated statements at the beginning of handlers; they would
178*8feb0f0bSmrg    be further reused for various EH constructs, which would damage
179*8feb0f0bSmrg    the coverage information.  */
1801debfc3dSmrg 
1811debfc3dSmrg static void
set_location_for_edge(edge e)1821debfc3dSmrg set_location_for_edge (edge e)
1831debfc3dSmrg {
1841debfc3dSmrg   if (e->goto_locus)
1851debfc3dSmrg     set_curr_insn_location (e->goto_locus);
186*8feb0f0bSmrg   else if (e->flags & EDGE_EH)
187*8feb0f0bSmrg     {
188*8feb0f0bSmrg       basic_block bb = e->dest;
189*8feb0f0bSmrg       gimple_stmt_iterator gsi;
190*8feb0f0bSmrg 
191*8feb0f0bSmrg       do
192*8feb0f0bSmrg 	{
193*8feb0f0bSmrg 	  for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
194*8feb0f0bSmrg 	    {
195*8feb0f0bSmrg 	      gimple *stmt = gsi_stmt (gsi);
196*8feb0f0bSmrg 	      if (is_gimple_debug (stmt))
197*8feb0f0bSmrg 		continue;
198*8feb0f0bSmrg 	      if (gimple_has_location (stmt) || gimple_block (stmt))
199*8feb0f0bSmrg 		{
200*8feb0f0bSmrg 		  set_curr_insn_location (gimple_location (stmt));
201*8feb0f0bSmrg 		  return;
202*8feb0f0bSmrg 		}
203*8feb0f0bSmrg 	    }
204*8feb0f0bSmrg 	  /* Nothing found in this basic block.  Make a half-assed attempt
205*8feb0f0bSmrg 	     to continue with another block.  */
206*8feb0f0bSmrg 	  if (single_succ_p (bb))
207*8feb0f0bSmrg 	    bb = single_succ (bb);
208*8feb0f0bSmrg 	  else
209*8feb0f0bSmrg 	    bb = e->dest;
210*8feb0f0bSmrg 	}
211*8feb0f0bSmrg       while (bb != e->dest);
2121debfc3dSmrg     }
2131debfc3dSmrg   else
2141debfc3dSmrg     {
2151debfc3dSmrg       basic_block bb = e->src;
2161debfc3dSmrg       gimple_stmt_iterator gsi;
2171debfc3dSmrg 
2181debfc3dSmrg       do
2191debfc3dSmrg 	{
2201debfc3dSmrg 	  for (gsi = gsi_last_bb (bb); !gsi_end_p (gsi); gsi_prev (&gsi))
2211debfc3dSmrg 	    {
2221debfc3dSmrg 	      gimple *stmt = gsi_stmt (gsi);
2231debfc3dSmrg 	      if (is_gimple_debug (stmt))
2241debfc3dSmrg 		continue;
2251debfc3dSmrg 	      if (gimple_has_location (stmt) || gimple_block (stmt))
2261debfc3dSmrg 		{
2271debfc3dSmrg 		  set_curr_insn_location (gimple_location (stmt));
2281debfc3dSmrg 		  return;
2291debfc3dSmrg 		}
2301debfc3dSmrg 	    }
2311debfc3dSmrg 	  /* Nothing found in this basic block.  Make a half-assed attempt
2321debfc3dSmrg 	     to continue with another block.  */
2331debfc3dSmrg 	  if (single_pred_p (bb))
2341debfc3dSmrg 	    bb = single_pred (bb);
2351debfc3dSmrg 	  else
2361debfc3dSmrg 	    bb = e->src;
2371debfc3dSmrg 	}
2381debfc3dSmrg       while (bb != e->src);
2391debfc3dSmrg     }
2401debfc3dSmrg }
2411debfc3dSmrg 
2421debfc3dSmrg /* Emit insns to copy SRC into DEST converting SRC if necessary.  As
2431debfc3dSmrg    SRC/DEST might be BLKmode memory locations SIZEEXP is a tree from
2441debfc3dSmrg    which we deduce the size to copy in that case.  */
2451debfc3dSmrg 
2461debfc3dSmrg static inline rtx_insn *
emit_partition_copy(rtx dest,rtx src,int unsignedsrcp,tree sizeexp)2471debfc3dSmrg emit_partition_copy (rtx dest, rtx src, int unsignedsrcp, tree sizeexp)
2481debfc3dSmrg {
2491debfc3dSmrg   start_sequence ();
2501debfc3dSmrg 
2511debfc3dSmrg   if (GET_MODE (src) != VOIDmode && GET_MODE (src) != GET_MODE (dest))
2521debfc3dSmrg     src = convert_to_mode (GET_MODE (dest), src, unsignedsrcp);
2531debfc3dSmrg   if (GET_MODE (src) == BLKmode)
2541debfc3dSmrg     {
2551debfc3dSmrg       gcc_assert (GET_MODE (dest) == BLKmode);
2561debfc3dSmrg       emit_block_move (dest, src, expr_size (sizeexp), BLOCK_OP_NORMAL);
2571debfc3dSmrg     }
2581debfc3dSmrg   else
2591debfc3dSmrg     emit_move_insn (dest, src);
2601debfc3dSmrg   do_pending_stack_adjust ();
2611debfc3dSmrg 
2621debfc3dSmrg   rtx_insn *seq = get_insns ();
2631debfc3dSmrg   end_sequence ();
2641debfc3dSmrg 
2651debfc3dSmrg   return seq;
2661debfc3dSmrg }
2671debfc3dSmrg 
2681debfc3dSmrg /* Insert a copy instruction from partition SRC to DEST onto edge E.  */
2691debfc3dSmrg 
2701debfc3dSmrg static void
insert_partition_copy_on_edge(edge e,int dest,int src,location_t locus)271c0a68be4Smrg insert_partition_copy_on_edge (edge e, int dest, int src, location_t locus)
2721debfc3dSmrg {
2731debfc3dSmrg   tree var;
2741debfc3dSmrg   if (dump_file && (dump_flags & TDF_DETAILS))
2751debfc3dSmrg     {
2761debfc3dSmrg       fprintf (dump_file,
2771debfc3dSmrg 	       "Inserting a partition copy on edge BB%d->BB%d : "
2781debfc3dSmrg 	       "PART.%d = PART.%d",
2791debfc3dSmrg 	       e->src->index,
2801debfc3dSmrg 	       e->dest->index, dest, src);
2811debfc3dSmrg       fprintf (dump_file, "\n");
2821debfc3dSmrg     }
2831debfc3dSmrg 
2841debfc3dSmrg   gcc_assert (SA.partition_to_pseudo[dest]);
2851debfc3dSmrg   gcc_assert (SA.partition_to_pseudo[src]);
2861debfc3dSmrg 
2871debfc3dSmrg   set_location_for_edge (e);
2881debfc3dSmrg   /* If a locus is provided, override the default.  */
2891debfc3dSmrg   if (locus)
2901debfc3dSmrg     set_curr_insn_location (locus);
2911debfc3dSmrg 
2921debfc3dSmrg   var = partition_to_var (SA.map, src);
2931debfc3dSmrg   rtx_insn *seq = emit_partition_copy (copy_rtx (SA.partition_to_pseudo[dest]),
2941debfc3dSmrg 				       copy_rtx (SA.partition_to_pseudo[src]),
2951debfc3dSmrg 				       TYPE_UNSIGNED (TREE_TYPE (var)),
2961debfc3dSmrg 				       var);
2971debfc3dSmrg 
2981debfc3dSmrg   insert_insn_on_edge (seq, e);
2991debfc3dSmrg }
3001debfc3dSmrg 
3011debfc3dSmrg /* Insert a copy instruction from expression SRC to partition DEST
3021debfc3dSmrg    onto edge E.  */
3031debfc3dSmrg 
3041debfc3dSmrg static void
insert_value_copy_on_edge(edge e,int dest,tree src,location_t locus)305c0a68be4Smrg insert_value_copy_on_edge (edge e, int dest, tree src, location_t locus)
3061debfc3dSmrg {
3071debfc3dSmrg   rtx dest_rtx, seq, x;
3081debfc3dSmrg   machine_mode dest_mode, src_mode;
3091debfc3dSmrg   int unsignedp;
3101debfc3dSmrg 
3111debfc3dSmrg   if (dump_file && (dump_flags & TDF_DETAILS))
3121debfc3dSmrg     {
3131debfc3dSmrg       fprintf (dump_file,
3141debfc3dSmrg 	       "Inserting a value copy on edge BB%d->BB%d : PART.%d = ",
3151debfc3dSmrg 	       e->src->index,
3161debfc3dSmrg 	       e->dest->index, dest);
3171debfc3dSmrg       print_generic_expr (dump_file, src, TDF_SLIM);
3181debfc3dSmrg       fprintf (dump_file, "\n");
3191debfc3dSmrg     }
3201debfc3dSmrg 
3211debfc3dSmrg   dest_rtx = copy_rtx (SA.partition_to_pseudo[dest]);
3221debfc3dSmrg   gcc_assert (dest_rtx);
3231debfc3dSmrg 
3241debfc3dSmrg   set_location_for_edge (e);
3251debfc3dSmrg   /* If a locus is provided, override the default.  */
3261debfc3dSmrg   if (locus)
3271debfc3dSmrg     set_curr_insn_location (locus);
3281debfc3dSmrg 
3291debfc3dSmrg   start_sequence ();
3301debfc3dSmrg 
3311debfc3dSmrg   tree name = partition_to_var (SA.map, dest);
3321debfc3dSmrg   src_mode = TYPE_MODE (TREE_TYPE (src));
3331debfc3dSmrg   dest_mode = GET_MODE (dest_rtx);
3341debfc3dSmrg   gcc_assert (src_mode == TYPE_MODE (TREE_TYPE (name)));
3351debfc3dSmrg   gcc_assert (!REG_P (dest_rtx)
3361debfc3dSmrg 	      || dest_mode == promote_ssa_mode (name, &unsignedp));
3371debfc3dSmrg 
3381debfc3dSmrg   if (src_mode != dest_mode)
3391debfc3dSmrg     {
3401debfc3dSmrg       x = expand_expr (src, NULL, src_mode, EXPAND_NORMAL);
3411debfc3dSmrg       x = convert_modes (dest_mode, src_mode, x, unsignedp);
3421debfc3dSmrg     }
3431debfc3dSmrg   else if (src_mode == BLKmode)
3441debfc3dSmrg     {
3451debfc3dSmrg       x = dest_rtx;
3461debfc3dSmrg       store_expr (src, x, 0, false, false);
3471debfc3dSmrg     }
3481debfc3dSmrg   else
3491debfc3dSmrg     x = expand_expr (src, dest_rtx, dest_mode, EXPAND_NORMAL);
3501debfc3dSmrg 
3511debfc3dSmrg   if (x != dest_rtx)
3521debfc3dSmrg     emit_move_insn (dest_rtx, x);
3531debfc3dSmrg   do_pending_stack_adjust ();
3541debfc3dSmrg 
3551debfc3dSmrg   seq = get_insns ();
3561debfc3dSmrg   end_sequence ();
3571debfc3dSmrg 
3581debfc3dSmrg   insert_insn_on_edge (seq, e);
3591debfc3dSmrg }
3601debfc3dSmrg 
3611debfc3dSmrg /* Insert a copy instruction from RTL expression SRC to partition DEST
3621debfc3dSmrg    onto edge E.  */
3631debfc3dSmrg 
3641debfc3dSmrg static void
insert_rtx_to_part_on_edge(edge e,int dest,rtx src,int unsignedsrcp,location_t locus)3651debfc3dSmrg insert_rtx_to_part_on_edge (edge e, int dest, rtx src, int unsignedsrcp,
366c0a68be4Smrg 			    location_t locus)
3671debfc3dSmrg {
3681debfc3dSmrg   if (dump_file && (dump_flags & TDF_DETAILS))
3691debfc3dSmrg     {
3701debfc3dSmrg       fprintf (dump_file,
3711debfc3dSmrg 	       "Inserting a temp copy on edge BB%d->BB%d : PART.%d = ",
3721debfc3dSmrg 	       e->src->index,
3731debfc3dSmrg 	       e->dest->index, dest);
3741debfc3dSmrg       print_simple_rtl (dump_file, src);
3751debfc3dSmrg       fprintf (dump_file, "\n");
3761debfc3dSmrg     }
3771debfc3dSmrg 
3781debfc3dSmrg   gcc_assert (SA.partition_to_pseudo[dest]);
3791debfc3dSmrg 
3801debfc3dSmrg   set_location_for_edge (e);
3811debfc3dSmrg   /* If a locus is provided, override the default.  */
3821debfc3dSmrg   if (locus)
3831debfc3dSmrg     set_curr_insn_location (locus);
3841debfc3dSmrg 
3851debfc3dSmrg   /* We give the destination as sizeexp in case src/dest are BLKmode
3861debfc3dSmrg      mems.  Usually we give the source.  As we result from SSA names
3871debfc3dSmrg      the left and right size should be the same (and no WITH_SIZE_EXPR
3881debfc3dSmrg      involved), so it doesn't matter.  */
3891debfc3dSmrg   rtx_insn *seq = emit_partition_copy (copy_rtx (SA.partition_to_pseudo[dest]),
3901debfc3dSmrg 				       src, unsignedsrcp,
3911debfc3dSmrg 				       partition_to_var (SA.map, dest));
3921debfc3dSmrg 
3931debfc3dSmrg   insert_insn_on_edge (seq, e);
3941debfc3dSmrg }
3951debfc3dSmrg 
3961debfc3dSmrg /* Insert a copy instruction from partition SRC to RTL lvalue DEST
3971debfc3dSmrg    onto edge E.  */
3981debfc3dSmrg 
3991debfc3dSmrg static void
insert_part_to_rtx_on_edge(edge e,rtx dest,int src,location_t locus)400c0a68be4Smrg insert_part_to_rtx_on_edge (edge e, rtx dest, int src, location_t locus)
4011debfc3dSmrg {
4021debfc3dSmrg   tree var;
4031debfc3dSmrg   if (dump_file && (dump_flags & TDF_DETAILS))
4041debfc3dSmrg     {
4051debfc3dSmrg       fprintf (dump_file,
4061debfc3dSmrg 	       "Inserting a temp copy on edge BB%d->BB%d : ",
4071debfc3dSmrg 	       e->src->index,
4081debfc3dSmrg 	       e->dest->index);
4091debfc3dSmrg       print_simple_rtl (dump_file, dest);
4101debfc3dSmrg       fprintf (dump_file, "= PART.%d\n", src);
4111debfc3dSmrg     }
4121debfc3dSmrg 
4131debfc3dSmrg   gcc_assert (SA.partition_to_pseudo[src]);
4141debfc3dSmrg 
4151debfc3dSmrg   set_location_for_edge (e);
4161debfc3dSmrg   /* If a locus is provided, override the default.  */
4171debfc3dSmrg   if (locus)
4181debfc3dSmrg     set_curr_insn_location (locus);
4191debfc3dSmrg 
4201debfc3dSmrg   var = partition_to_var (SA.map, src);
4211debfc3dSmrg   rtx_insn *seq = emit_partition_copy (dest,
4221debfc3dSmrg 				       copy_rtx (SA.partition_to_pseudo[src]),
4231debfc3dSmrg 				       TYPE_UNSIGNED (TREE_TYPE (var)),
4241debfc3dSmrg 				       var);
4251debfc3dSmrg 
4261debfc3dSmrg   insert_insn_on_edge (seq, e);
4271debfc3dSmrg }
4281debfc3dSmrg 
4291debfc3dSmrg 
4301debfc3dSmrg /* Create an elimination graph for map.  */
4311debfc3dSmrg 
elim_graph(var_map map)4321debfc3dSmrg elim_graph::elim_graph (var_map map) :
4331debfc3dSmrg   nodes (30), edge_list (20), edge_locus (10), visited (map->num_partitions),
4341debfc3dSmrg   stack (30), map (map), const_dests (20), const_copies (20), copy_locus (10)
4351debfc3dSmrg {
4361debfc3dSmrg }
4371debfc3dSmrg 
4381debfc3dSmrg 
4391debfc3dSmrg /* Empty elimination graph G.  */
4401debfc3dSmrg 
4411debfc3dSmrg static inline void
clear_elim_graph(elim_graph * g)4421debfc3dSmrg clear_elim_graph (elim_graph *g)
4431debfc3dSmrg {
4441debfc3dSmrg   g->nodes.truncate (0);
4451debfc3dSmrg   g->edge_list.truncate (0);
4461debfc3dSmrg   g->edge_locus.truncate (0);
4471debfc3dSmrg }
4481debfc3dSmrg 
4491debfc3dSmrg 
4501debfc3dSmrg /* Return the number of nodes in graph G.  */
4511debfc3dSmrg 
4521debfc3dSmrg static inline int
elim_graph_size(elim_graph * g)4531debfc3dSmrg elim_graph_size (elim_graph *g)
4541debfc3dSmrg {
4551debfc3dSmrg   return g->nodes.length ();
4561debfc3dSmrg }
4571debfc3dSmrg 
4581debfc3dSmrg 
4591debfc3dSmrg /* Add NODE to graph G, if it doesn't exist already.  */
4601debfc3dSmrg 
4611debfc3dSmrg static inline void
elim_graph_add_node(elim_graph * g,int node)4621debfc3dSmrg elim_graph_add_node (elim_graph *g, int node)
4631debfc3dSmrg {
4641debfc3dSmrg   int x;
4651debfc3dSmrg   int t;
4661debfc3dSmrg 
4671debfc3dSmrg   FOR_EACH_VEC_ELT (g->nodes, x, t)
4681debfc3dSmrg     if (t == node)
4691debfc3dSmrg       return;
4701debfc3dSmrg   g->nodes.safe_push (node);
4711debfc3dSmrg }
4721debfc3dSmrg 
4731debfc3dSmrg 
4741debfc3dSmrg /* Add the edge PRED->SUCC to graph G.  */
4751debfc3dSmrg 
4761debfc3dSmrg static inline void
elim_graph_add_edge(elim_graph * g,int pred,int succ,location_t locus)477c0a68be4Smrg elim_graph_add_edge (elim_graph *g, int pred, int succ, location_t locus)
4781debfc3dSmrg {
4791debfc3dSmrg   g->edge_list.safe_push (pred);
4801debfc3dSmrg   g->edge_list.safe_push (succ);
4811debfc3dSmrg   g->edge_locus.safe_push (locus);
4821debfc3dSmrg }
4831debfc3dSmrg 
4841debfc3dSmrg 
4851debfc3dSmrg /* Remove an edge from graph G for which NODE is the predecessor, and
4861debfc3dSmrg    return the successor node.  -1 is returned if there is no such edge.  */
4871debfc3dSmrg 
4881debfc3dSmrg static inline int
elim_graph_remove_succ_edge(elim_graph * g,int node,location_t * locus)489c0a68be4Smrg elim_graph_remove_succ_edge (elim_graph *g, int node, location_t *locus)
4901debfc3dSmrg {
4911debfc3dSmrg   int y;
4921debfc3dSmrg   unsigned x;
4931debfc3dSmrg   for (x = 0; x < g->edge_list.length (); x += 2)
4941debfc3dSmrg     if (g->edge_list[x] == node)
4951debfc3dSmrg       {
4961debfc3dSmrg         g->edge_list[x] = -1;
4971debfc3dSmrg 	y = g->edge_list[x + 1];
4981debfc3dSmrg 	g->edge_list[x + 1] = -1;
4991debfc3dSmrg 	*locus = g->edge_locus[x / 2];
5001debfc3dSmrg 	g->edge_locus[x / 2] = UNKNOWN_LOCATION;
5011debfc3dSmrg 	return y;
5021debfc3dSmrg       }
5031debfc3dSmrg   *locus = UNKNOWN_LOCATION;
5041debfc3dSmrg   return -1;
5051debfc3dSmrg }
5061debfc3dSmrg 
5071debfc3dSmrg 
5081debfc3dSmrg /* Find all the nodes in GRAPH which are successors to NODE in the
5091debfc3dSmrg    edge list.  VAR will hold the partition number found.  CODE is the
5101debfc3dSmrg    code fragment executed for every node found.  */
5111debfc3dSmrg 
5121debfc3dSmrg #define FOR_EACH_ELIM_GRAPH_SUCC(GRAPH, NODE, VAR, LOCUS, CODE)		\
5131debfc3dSmrg do {									\
5141debfc3dSmrg   unsigned x_;								\
5151debfc3dSmrg   int y_;								\
5161debfc3dSmrg   for (x_ = 0; x_ < (GRAPH)->edge_list.length (); x_ += 2)	\
5171debfc3dSmrg     {									\
5181debfc3dSmrg       y_ = (GRAPH)->edge_list[x_];					\
5191debfc3dSmrg       if (y_ != (NODE))							\
5201debfc3dSmrg         continue;							\
5211debfc3dSmrg       (void) ((VAR) = (GRAPH)->edge_list[x_ + 1]);			\
5221debfc3dSmrg       (void) ((LOCUS) = (GRAPH)->edge_locus[x_ / 2]);			\
5231debfc3dSmrg       CODE;								\
5241debfc3dSmrg     }									\
5251debfc3dSmrg } while (0)
5261debfc3dSmrg 
5271debfc3dSmrg 
5281debfc3dSmrg /* Find all the nodes which are predecessors of NODE in the edge list for
5291debfc3dSmrg    GRAPH.  VAR will hold the partition number found.  CODE is the
5301debfc3dSmrg    code fragment executed for every node found.  */
5311debfc3dSmrg 
5321debfc3dSmrg #define FOR_EACH_ELIM_GRAPH_PRED(GRAPH, NODE, VAR, LOCUS, CODE)		\
5331debfc3dSmrg do {									\
5341debfc3dSmrg   unsigned x_;								\
5351debfc3dSmrg   int y_;								\
5361debfc3dSmrg   for (x_ = 0; x_ < (GRAPH)->edge_list.length (); x_ += 2)	\
5371debfc3dSmrg     {									\
5381debfc3dSmrg       y_ = (GRAPH)->edge_list[x_ + 1];					\
5391debfc3dSmrg       if (y_ != (NODE))							\
5401debfc3dSmrg         continue;							\
5411debfc3dSmrg       (void) ((VAR) = (GRAPH)->edge_list[x_]);				\
5421debfc3dSmrg       (void) ((LOCUS) = (GRAPH)->edge_locus[x_ / 2]);			\
5431debfc3dSmrg       CODE;								\
5441debfc3dSmrg     }									\
5451debfc3dSmrg } while (0)
5461debfc3dSmrg 
5471debfc3dSmrg 
5481debfc3dSmrg /* Add T to elimination graph G.  */
5491debfc3dSmrg 
5501debfc3dSmrg static inline void
eliminate_name(elim_graph * g,int T)5511debfc3dSmrg eliminate_name (elim_graph *g, int T)
5521debfc3dSmrg {
5531debfc3dSmrg   elim_graph_add_node (g, T);
5541debfc3dSmrg }
5551debfc3dSmrg 
5561debfc3dSmrg /* Return true if this phi argument T should have a copy queued when using
5571debfc3dSmrg    var_map MAP.  PHI nodes should contain only ssa_names and invariants.  A
5581debfc3dSmrg    test for ssa_name is definitely simpler, but don't let invalid contents
5591debfc3dSmrg    slip through in the meantime.  */
5601debfc3dSmrg 
5611debfc3dSmrg static inline bool
queue_phi_copy_p(var_map map,tree t)5621debfc3dSmrg queue_phi_copy_p (var_map map, tree t)
5631debfc3dSmrg {
5641debfc3dSmrg   if (TREE_CODE (t) == SSA_NAME)
5651debfc3dSmrg     {
5661debfc3dSmrg       if (var_to_partition (map, t) == NO_PARTITION)
5671debfc3dSmrg         return true;
5681debfc3dSmrg       return false;
5691debfc3dSmrg     }
5701debfc3dSmrg   gcc_checking_assert (is_gimple_min_invariant (t));
5711debfc3dSmrg   return true;
5721debfc3dSmrg }
5731debfc3dSmrg 
5741debfc3dSmrg /* Build elimination graph G for basic block BB on incoming PHI edge
5751debfc3dSmrg    G->e.  */
5761debfc3dSmrg 
5771debfc3dSmrg static void
eliminate_build(elim_graph * g)5781debfc3dSmrg eliminate_build (elim_graph *g)
5791debfc3dSmrg {
5801debfc3dSmrg   tree Ti;
5811debfc3dSmrg   int p0, pi;
5821debfc3dSmrg   gphi_iterator gsi;
5831debfc3dSmrg 
5841debfc3dSmrg   clear_elim_graph (g);
5851debfc3dSmrg 
5861debfc3dSmrg   for (gsi = gsi_start_phis (g->e->dest); !gsi_end_p (gsi); gsi_next (&gsi))
5871debfc3dSmrg     {
5881debfc3dSmrg       gphi *phi = gsi.phi ();
589c0a68be4Smrg       location_t locus;
5901debfc3dSmrg 
5911debfc3dSmrg       p0 = var_to_partition (g->map, gimple_phi_result (phi));
5921debfc3dSmrg       /* Ignore results which are not in partitions.  */
5931debfc3dSmrg       if (p0 == NO_PARTITION)
5941debfc3dSmrg 	continue;
5951debfc3dSmrg 
5961debfc3dSmrg       Ti = PHI_ARG_DEF (phi, g->e->dest_idx);
597*8feb0f0bSmrg       /* See set_location_for_edge for the rationale.  */
598*8feb0f0bSmrg       if (g->e->flags & EDGE_EH)
599*8feb0f0bSmrg 	locus = UNKNOWN_LOCATION;
600*8feb0f0bSmrg       else
6011debfc3dSmrg 	locus = gimple_phi_arg_location_from_edge (phi, g->e);
6021debfc3dSmrg 
6031debfc3dSmrg       /* If this argument is a constant, or a SSA_NAME which is being
6041debfc3dSmrg 	 left in SSA form, just queue a copy to be emitted on this
6051debfc3dSmrg 	 edge.  */
6061debfc3dSmrg       if (queue_phi_copy_p (g->map, Ti))
6071debfc3dSmrg         {
6081debfc3dSmrg 	  /* Save constant copies until all other copies have been emitted
6091debfc3dSmrg 	     on this edge.  */
6101debfc3dSmrg 	  g->const_dests.safe_push (p0);
6111debfc3dSmrg 	  g->const_copies.safe_push (Ti);
6121debfc3dSmrg 	  g->copy_locus.safe_push (locus);
6131debfc3dSmrg 	}
6141debfc3dSmrg       else
6151debfc3dSmrg         {
6161debfc3dSmrg 	  pi = var_to_partition (g->map, Ti);
6171debfc3dSmrg 	  if (p0 != pi)
6181debfc3dSmrg 	    {
6191debfc3dSmrg 	      eliminate_name (g, p0);
6201debfc3dSmrg 	      eliminate_name (g, pi);
6211debfc3dSmrg 	      elim_graph_add_edge (g, p0, pi, locus);
6221debfc3dSmrg 	    }
6231debfc3dSmrg 	}
6241debfc3dSmrg     }
6251debfc3dSmrg }
6261debfc3dSmrg 
6271debfc3dSmrg 
6281debfc3dSmrg /* Push successors of T onto the elimination stack for G.  */
6291debfc3dSmrg 
6301debfc3dSmrg static void
elim_forward(elim_graph * g,int T)6311debfc3dSmrg elim_forward (elim_graph *g, int T)
6321debfc3dSmrg {
6331debfc3dSmrg   int S;
634c0a68be4Smrg   location_t locus;
6351debfc3dSmrg 
6361debfc3dSmrg   bitmap_set_bit (g->visited, T);
6371debfc3dSmrg   FOR_EACH_ELIM_GRAPH_SUCC (g, T, S, locus,
6381debfc3dSmrg     {
6391debfc3dSmrg       if (!bitmap_bit_p (g->visited, S))
6401debfc3dSmrg         elim_forward (g, S);
6411debfc3dSmrg     });
6421debfc3dSmrg   g->stack.safe_push (T);
6431debfc3dSmrg }
6441debfc3dSmrg 
6451debfc3dSmrg 
6461debfc3dSmrg /* Return 1 if there unvisited predecessors of T in graph G.  */
6471debfc3dSmrg 
6481debfc3dSmrg static int
elim_unvisited_predecessor(elim_graph * g,int T)6491debfc3dSmrg elim_unvisited_predecessor (elim_graph *g, int T)
6501debfc3dSmrg {
6511debfc3dSmrg   int P;
652c0a68be4Smrg   location_t locus;
6531debfc3dSmrg 
6541debfc3dSmrg   FOR_EACH_ELIM_GRAPH_PRED (g, T, P, locus,
6551debfc3dSmrg     {
6561debfc3dSmrg       if (!bitmap_bit_p (g->visited, P))
6571debfc3dSmrg         return 1;
6581debfc3dSmrg     });
6591debfc3dSmrg   return 0;
6601debfc3dSmrg }
6611debfc3dSmrg 
6621debfc3dSmrg /* Process predecessors first, and insert a copy.  */
6631debfc3dSmrg 
6641debfc3dSmrg static void
elim_backward(elim_graph * g,int T)6651debfc3dSmrg elim_backward (elim_graph *g, int T)
6661debfc3dSmrg {
6671debfc3dSmrg   int P;
668c0a68be4Smrg   location_t locus;
6691debfc3dSmrg 
6701debfc3dSmrg   bitmap_set_bit (g->visited, T);
6711debfc3dSmrg   FOR_EACH_ELIM_GRAPH_PRED (g, T, P, locus,
6721debfc3dSmrg     {
6731debfc3dSmrg       if (!bitmap_bit_p (g->visited, P))
6741debfc3dSmrg         {
6751debfc3dSmrg 	  elim_backward (g, P);
6761debfc3dSmrg 	  insert_partition_copy_on_edge (g->e, P, T, locus);
6771debfc3dSmrg 	}
6781debfc3dSmrg     });
6791debfc3dSmrg }
6801debfc3dSmrg 
6811debfc3dSmrg /* Allocate a new pseudo register usable for storing values sitting
6821debfc3dSmrg    in NAME (a decl or SSA name), i.e. with matching mode and attributes.  */
6831debfc3dSmrg 
6841debfc3dSmrg static rtx
get_temp_reg(tree name)6851debfc3dSmrg get_temp_reg (tree name)
6861debfc3dSmrg {
6871debfc3dSmrg   tree type = TREE_TYPE (name);
6881debfc3dSmrg   int unsignedp;
6891debfc3dSmrg   machine_mode reg_mode = promote_ssa_mode (name, &unsignedp);
690a05ac97eSmrg   if (reg_mode == BLKmode)
691a05ac97eSmrg     return assign_temp (type, 0, 0);
6921debfc3dSmrg   rtx x = gen_reg_rtx (reg_mode);
6931debfc3dSmrg   if (POINTER_TYPE_P (type))
6941debfc3dSmrg     mark_reg_pointer (x, TYPE_ALIGN (TREE_TYPE (type)));
6951debfc3dSmrg   return x;
6961debfc3dSmrg }
6971debfc3dSmrg 
6981debfc3dSmrg /* Insert required copies for T in graph G.  Check for a strongly connected
6991debfc3dSmrg    region, and create a temporary to break the cycle if one is found.  */
7001debfc3dSmrg 
7011debfc3dSmrg static void
elim_create(elim_graph * g,int T)7021debfc3dSmrg elim_create (elim_graph *g, int T)
7031debfc3dSmrg {
7041debfc3dSmrg   int P, S;
705c0a68be4Smrg   location_t locus;
7061debfc3dSmrg 
7071debfc3dSmrg   if (elim_unvisited_predecessor (g, T))
7081debfc3dSmrg     {
7091debfc3dSmrg       tree var = partition_to_var (g->map, T);
7101debfc3dSmrg       rtx U = get_temp_reg (var);
7111debfc3dSmrg       int unsignedsrcp = TYPE_UNSIGNED (TREE_TYPE (var));
7121debfc3dSmrg 
7131debfc3dSmrg       insert_part_to_rtx_on_edge (g->e, U, T, UNKNOWN_LOCATION);
7141debfc3dSmrg       FOR_EACH_ELIM_GRAPH_PRED (g, T, P, locus,
7151debfc3dSmrg 	{
7161debfc3dSmrg 	  if (!bitmap_bit_p (g->visited, P))
7171debfc3dSmrg 	    {
7181debfc3dSmrg 	      elim_backward (g, P);
7191debfc3dSmrg 	      insert_rtx_to_part_on_edge (g->e, P, U, unsignedsrcp, locus);
7201debfc3dSmrg 	    }
7211debfc3dSmrg 	});
7221debfc3dSmrg     }
7231debfc3dSmrg   else
7241debfc3dSmrg     {
7251debfc3dSmrg       S = elim_graph_remove_succ_edge (g, T, &locus);
7261debfc3dSmrg       if (S != -1)
7271debfc3dSmrg 	{
7281debfc3dSmrg 	  bitmap_set_bit (g->visited, T);
7291debfc3dSmrg 	  insert_partition_copy_on_edge (g->e, T, S, locus);
7301debfc3dSmrg 	}
7311debfc3dSmrg     }
7321debfc3dSmrg }
7331debfc3dSmrg 
7341debfc3dSmrg 
7351debfc3dSmrg /* Eliminate all the phi nodes on edge E in graph G.  */
7361debfc3dSmrg 
7371debfc3dSmrg static void
eliminate_phi(edge e,elim_graph * g)7381debfc3dSmrg eliminate_phi (edge e, elim_graph *g)
7391debfc3dSmrg {
7401debfc3dSmrg   int x;
7411debfc3dSmrg 
7421debfc3dSmrg   gcc_assert (g->const_copies.length () == 0);
7431debfc3dSmrg   gcc_assert (g->copy_locus.length () == 0);
7441debfc3dSmrg 
7451debfc3dSmrg   /* Abnormal edges already have everything coalesced.  */
7461debfc3dSmrg   if (e->flags & EDGE_ABNORMAL)
7471debfc3dSmrg     return;
7481debfc3dSmrg 
7491debfc3dSmrg   g->e = e;
7501debfc3dSmrg 
7511debfc3dSmrg   eliminate_build (g);
7521debfc3dSmrg 
7531debfc3dSmrg   if (elim_graph_size (g) != 0)
7541debfc3dSmrg     {
7551debfc3dSmrg       int part;
7561debfc3dSmrg 
7571debfc3dSmrg       bitmap_clear (g->visited);
7581debfc3dSmrg       g->stack.truncate (0);
7591debfc3dSmrg 
7601debfc3dSmrg       FOR_EACH_VEC_ELT (g->nodes, x, part)
7611debfc3dSmrg         {
7621debfc3dSmrg 	  if (!bitmap_bit_p (g->visited, part))
7631debfc3dSmrg 	    elim_forward (g, part);
7641debfc3dSmrg 	}
7651debfc3dSmrg 
7661debfc3dSmrg       bitmap_clear (g->visited);
7671debfc3dSmrg       while (g->stack.length () > 0)
7681debfc3dSmrg 	{
7691debfc3dSmrg 	  x = g->stack.pop ();
7701debfc3dSmrg 	  if (!bitmap_bit_p (g->visited, x))
7711debfc3dSmrg 	    elim_create (g, x);
7721debfc3dSmrg 	}
7731debfc3dSmrg     }
7741debfc3dSmrg 
7751debfc3dSmrg   /* If there are any pending constant copies, issue them now.  */
7761debfc3dSmrg   while (g->const_copies.length () > 0)
7771debfc3dSmrg     {
7781debfc3dSmrg       int dest;
7791debfc3dSmrg       tree src;
780c0a68be4Smrg       location_t locus;
7811debfc3dSmrg 
7821debfc3dSmrg       src = g->const_copies.pop ();
7831debfc3dSmrg       dest = g->const_dests.pop ();
7841debfc3dSmrg       locus = g->copy_locus.pop ();
7851debfc3dSmrg       insert_value_copy_on_edge (e, dest, src, locus);
7861debfc3dSmrg     }
7871debfc3dSmrg }
7881debfc3dSmrg 
7891debfc3dSmrg 
7901debfc3dSmrg /* Remove each argument from PHI.  If an arg was the last use of an SSA_NAME,
7911debfc3dSmrg    check to see if this allows another PHI node to be removed.  */
7921debfc3dSmrg 
7931debfc3dSmrg static void
remove_gimple_phi_args(gphi * phi)7941debfc3dSmrg remove_gimple_phi_args (gphi *phi)
7951debfc3dSmrg {
7961debfc3dSmrg   use_operand_p arg_p;
7971debfc3dSmrg   ssa_op_iter iter;
7981debfc3dSmrg 
7991debfc3dSmrg   if (dump_file && (dump_flags & TDF_DETAILS))
8001debfc3dSmrg     {
8011debfc3dSmrg       fprintf (dump_file, "Removing Dead PHI definition: ");
8021debfc3dSmrg       print_gimple_stmt (dump_file, phi, 0, TDF_SLIM);
8031debfc3dSmrg     }
8041debfc3dSmrg 
8051debfc3dSmrg   FOR_EACH_PHI_ARG (arg_p, phi, iter, SSA_OP_USE)
8061debfc3dSmrg     {
8071debfc3dSmrg       tree arg = USE_FROM_PTR (arg_p);
8081debfc3dSmrg       if (TREE_CODE (arg) == SSA_NAME)
8091debfc3dSmrg         {
8101debfc3dSmrg 	  /* Remove the reference to the existing argument.  */
8111debfc3dSmrg 	  SET_USE (arg_p, NULL_TREE);
8121debfc3dSmrg 	  if (has_zero_uses (arg))
8131debfc3dSmrg 	    {
8141debfc3dSmrg 	      gimple *stmt;
8151debfc3dSmrg 	      gimple_stmt_iterator gsi;
8161debfc3dSmrg 
8171debfc3dSmrg 	      stmt = SSA_NAME_DEF_STMT (arg);
8181debfc3dSmrg 
8191debfc3dSmrg 	      /* Also remove the def if it is a PHI node.  */
8201debfc3dSmrg 	      if (gimple_code (stmt) == GIMPLE_PHI)
8211debfc3dSmrg 		{
8221debfc3dSmrg 		  remove_gimple_phi_args (as_a <gphi *> (stmt));
8231debfc3dSmrg 		  gsi = gsi_for_stmt (stmt);
8241debfc3dSmrg 		  remove_phi_node (&gsi, true);
8251debfc3dSmrg 		}
8261debfc3dSmrg 
8271debfc3dSmrg 	    }
8281debfc3dSmrg 	}
8291debfc3dSmrg     }
8301debfc3dSmrg }
8311debfc3dSmrg 
8321debfc3dSmrg /* Remove any PHI node which is a virtual PHI, or a PHI with no uses.  */
8331debfc3dSmrg 
8341debfc3dSmrg static void
eliminate_useless_phis(void)8351debfc3dSmrg eliminate_useless_phis (void)
8361debfc3dSmrg {
8371debfc3dSmrg   basic_block bb;
8381debfc3dSmrg   gphi_iterator gsi;
8391debfc3dSmrg   tree result;
8401debfc3dSmrg 
8411debfc3dSmrg   FOR_EACH_BB_FN (bb, cfun)
8421debfc3dSmrg     {
8431debfc3dSmrg       for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); )
8441debfc3dSmrg         {
8451debfc3dSmrg 	  gphi *phi = gsi.phi ();
8461debfc3dSmrg 	  result = gimple_phi_result (phi);
8471debfc3dSmrg 	  if (virtual_operand_p (result))
8481debfc3dSmrg 	    remove_phi_node (&gsi, true);
8491debfc3dSmrg           else
8501debfc3dSmrg 	    {
8511debfc3dSmrg 	      /* Also remove real PHIs with no uses.  */
8521debfc3dSmrg 	      if (has_zero_uses (result))
8531debfc3dSmrg 	        {
8541debfc3dSmrg 		  remove_gimple_phi_args (phi);
8551debfc3dSmrg 		  remove_phi_node (&gsi, true);
8561debfc3dSmrg 		}
8571debfc3dSmrg 	      else
8581debfc3dSmrg 		gsi_next (&gsi);
8591debfc3dSmrg 	    }
8601debfc3dSmrg 	}
8611debfc3dSmrg     }
8621debfc3dSmrg }
8631debfc3dSmrg 
8641debfc3dSmrg 
8651debfc3dSmrg /* This function will rewrite the current program using the variable mapping
8661debfc3dSmrg    found in MAP.  If the replacement vector VALUES is provided, any
8671debfc3dSmrg    occurrences of partitions with non-null entries in the vector will be
8681debfc3dSmrg    replaced with the expression in the vector instead of its mapped
8691debfc3dSmrg    variable.  */
8701debfc3dSmrg 
8711debfc3dSmrg static void
rewrite_trees(var_map map)8721debfc3dSmrg rewrite_trees (var_map map)
8731debfc3dSmrg {
8741debfc3dSmrg   if (!flag_checking)
8751debfc3dSmrg     return;
8761debfc3dSmrg 
8771debfc3dSmrg   basic_block bb;
8781debfc3dSmrg   /* Search for PHIs where the destination has no partition, but one
8791debfc3dSmrg      or more arguments has a partition.  This should not happen and can
8801debfc3dSmrg      create incorrect code.  */
8811debfc3dSmrg   FOR_EACH_BB_FN (bb, cfun)
8821debfc3dSmrg     {
8831debfc3dSmrg       gphi_iterator gsi;
8841debfc3dSmrg       for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
8851debfc3dSmrg 	{
8861debfc3dSmrg 	  gphi *phi = gsi.phi ();
8871debfc3dSmrg 	  tree T0 = var_to_partition_to_var (map, gimple_phi_result (phi));
8881debfc3dSmrg 	  if (T0 == NULL_TREE)
8891debfc3dSmrg 	    {
8901debfc3dSmrg 	      size_t i;
8911debfc3dSmrg 	      for (i = 0; i < gimple_phi_num_args (phi); i++)
8921debfc3dSmrg 		{
8931debfc3dSmrg 		  tree arg = PHI_ARG_DEF (phi, i);
8941debfc3dSmrg 
8951debfc3dSmrg 		  if (TREE_CODE (arg) == SSA_NAME
8961debfc3dSmrg 		      && var_to_partition (map, arg) != NO_PARTITION)
8971debfc3dSmrg 		    {
8981debfc3dSmrg 		      fprintf (stderr, "Argument of PHI is in a partition :(");
8991debfc3dSmrg 		      print_generic_expr (stderr, arg, TDF_SLIM);
9001debfc3dSmrg 		      fprintf (stderr, "), but the result is not :");
9011debfc3dSmrg 		      print_gimple_stmt (stderr, phi, 0, TDF_SLIM);
9021debfc3dSmrg 		      internal_error ("SSA corruption");
9031debfc3dSmrg 		    }
9041debfc3dSmrg 		}
9051debfc3dSmrg 	    }
9061debfc3dSmrg 	}
9071debfc3dSmrg     }
9081debfc3dSmrg }
9091debfc3dSmrg 
910c0a68be4Smrg /* Create a default def for VAR.  */
911c0a68be4Smrg 
912c0a68be4Smrg static void
create_default_def(tree var,void * arg ATTRIBUTE_UNUSED)913c0a68be4Smrg create_default_def (tree var, void *arg ATTRIBUTE_UNUSED)
914c0a68be4Smrg {
915c0a68be4Smrg   if (!is_gimple_reg (var))
916c0a68be4Smrg     return;
917c0a68be4Smrg 
918c0a68be4Smrg   tree ssa = get_or_create_ssa_default_def (cfun, var);
919c0a68be4Smrg   gcc_assert (ssa);
920c0a68be4Smrg }
921c0a68be4Smrg 
922c0a68be4Smrg /* Call CALLBACK for all PARM_DECLs and RESULT_DECLs for which
923c0a68be4Smrg    assign_parms may ask for a default partition.  */
924c0a68be4Smrg 
925c0a68be4Smrg static void
for_all_parms(void (* callback)(tree var,void * arg),void * arg)926c0a68be4Smrg for_all_parms (void (*callback)(tree var, void *arg), void *arg)
927c0a68be4Smrg {
928c0a68be4Smrg   for (tree var = DECL_ARGUMENTS (current_function_decl); var;
929c0a68be4Smrg        var = DECL_CHAIN (var))
930c0a68be4Smrg     callback (var, arg);
931c0a68be4Smrg   if (!VOID_TYPE_P (TREE_TYPE (DECL_RESULT (current_function_decl))))
932c0a68be4Smrg     callback (DECL_RESULT (current_function_decl), arg);
933c0a68be4Smrg   if (cfun->static_chain_decl)
934c0a68be4Smrg     callback (cfun->static_chain_decl, arg);
935c0a68be4Smrg }
936c0a68be4Smrg 
937c0a68be4Smrg /* We need to pass two arguments to set_parm_default_def_partition,
938c0a68be4Smrg    but for_all_parms only supports one.  Use a pair.  */
939c0a68be4Smrg 
940c0a68be4Smrg typedef std::pair<var_map, bitmap> parm_default_def_partition_arg;
941c0a68be4Smrg 
942c0a68be4Smrg /* Set in ARG's PARTS bitmap the bit corresponding to the partition in
943c0a68be4Smrg    ARG's MAP containing VAR's default def.  */
944c0a68be4Smrg 
945c0a68be4Smrg static void
set_parm_default_def_partition(tree var,void * arg_)946c0a68be4Smrg set_parm_default_def_partition (tree var, void *arg_)
947c0a68be4Smrg {
948c0a68be4Smrg   parm_default_def_partition_arg *arg = (parm_default_def_partition_arg *)arg_;
949c0a68be4Smrg   var_map map = arg->first;
950c0a68be4Smrg   bitmap parts = arg->second;
951c0a68be4Smrg 
952c0a68be4Smrg   if (!is_gimple_reg (var))
953c0a68be4Smrg     return;
954c0a68be4Smrg 
955c0a68be4Smrg   tree ssa = ssa_default_def (cfun, var);
956c0a68be4Smrg   gcc_assert (ssa);
957c0a68be4Smrg 
958c0a68be4Smrg   int version = var_to_partition (map, ssa);
959c0a68be4Smrg   gcc_assert (version != NO_PARTITION);
960c0a68be4Smrg 
961c0a68be4Smrg   bool changed = bitmap_set_bit (parts, version);
962c0a68be4Smrg   gcc_assert (changed);
963c0a68be4Smrg }
964c0a68be4Smrg 
965c0a68be4Smrg /* Allocate and return a bitmap that has a bit set for each partition
966c0a68be4Smrg    that contains a default def for a parameter.  */
967c0a68be4Smrg 
968c0a68be4Smrg static bitmap
get_parm_default_def_partitions(var_map map)969c0a68be4Smrg get_parm_default_def_partitions (var_map map)
970c0a68be4Smrg {
971c0a68be4Smrg   bitmap parm_default_def_parts = BITMAP_ALLOC (NULL);
972c0a68be4Smrg 
973c0a68be4Smrg   parm_default_def_partition_arg
974c0a68be4Smrg     arg = std::make_pair (map, parm_default_def_parts);
975c0a68be4Smrg 
976c0a68be4Smrg   for_all_parms (set_parm_default_def_partition, &arg);
977c0a68be4Smrg 
978c0a68be4Smrg   return parm_default_def_parts;
979c0a68be4Smrg }
980c0a68be4Smrg 
981c0a68be4Smrg /* Allocate and return a bitmap that has a bit set for each partition
982c0a68be4Smrg    that contains an undefined value.  */
983c0a68be4Smrg 
984c0a68be4Smrg static bitmap
get_undefined_value_partitions(var_map map)985c0a68be4Smrg get_undefined_value_partitions (var_map map)
986c0a68be4Smrg {
987c0a68be4Smrg   bitmap undefined_value_parts = BITMAP_ALLOC (NULL);
988c0a68be4Smrg 
989c0a68be4Smrg   for (unsigned int i = 1; i < num_ssa_names; i++)
990c0a68be4Smrg     {
991c0a68be4Smrg       tree var = ssa_name (i);
992c0a68be4Smrg       if (var
993c0a68be4Smrg 	  && !virtual_operand_p (var)
994c0a68be4Smrg 	  && !has_zero_uses (var)
995c0a68be4Smrg 	  && ssa_undefined_value_p (var))
996c0a68be4Smrg 	{
997c0a68be4Smrg 	  const int p = var_to_partition (map, var);
998c0a68be4Smrg 	  if (p != NO_PARTITION)
999c0a68be4Smrg 	    bitmap_set_bit (undefined_value_parts, p);
1000c0a68be4Smrg 	}
1001c0a68be4Smrg     }
1002c0a68be4Smrg 
1003c0a68be4Smrg   return undefined_value_parts;
1004c0a68be4Smrg }
1005c0a68be4Smrg 
10061debfc3dSmrg /* Given the out-of-ssa info object SA (with prepared partitions)
10071debfc3dSmrg    eliminate all phi nodes in all basic blocks.  Afterwards no
10081debfc3dSmrg    basic block will have phi nodes anymore and there are possibly
10091debfc3dSmrg    some RTL instructions inserted on edges.  */
10101debfc3dSmrg 
10111debfc3dSmrg void
expand_phi_nodes(struct ssaexpand * sa)10121debfc3dSmrg expand_phi_nodes (struct ssaexpand *sa)
10131debfc3dSmrg {
10141debfc3dSmrg   basic_block bb;
10151debfc3dSmrg   elim_graph g (sa->map);
10161debfc3dSmrg 
10171debfc3dSmrg   FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb,
10181debfc3dSmrg 		  EXIT_BLOCK_PTR_FOR_FN (cfun), next_bb)
10191debfc3dSmrg     if (!gimple_seq_empty_p (phi_nodes (bb)))
10201debfc3dSmrg       {
10211debfc3dSmrg 	edge e;
10221debfc3dSmrg 	edge_iterator ei;
10231debfc3dSmrg 	FOR_EACH_EDGE (e, ei, bb->preds)
10241debfc3dSmrg 	  eliminate_phi (e, &g);
10251debfc3dSmrg 	set_phi_nodes (bb, NULL);
10261debfc3dSmrg 	/* We can't redirect EH edges in RTL land, so we need to do this
10271debfc3dSmrg 	   here.  Redirection happens only when splitting is necessary,
10281debfc3dSmrg 	   which it is only for critical edges, normally.  For EH edges
10291debfc3dSmrg 	   it might also be necessary when the successor has more than
10301debfc3dSmrg 	   one predecessor.  In that case the edge is either required to
10311debfc3dSmrg 	   be fallthru (which EH edges aren't), or the predecessor needs
10321debfc3dSmrg 	   to end with a jump (which again, isn't the case with EH edges).
10331debfc3dSmrg 	   Hence, split all EH edges on which we inserted instructions
10341debfc3dSmrg 	   and whose successor has multiple predecessors.  */
10351debfc3dSmrg 	for (ei = ei_start (bb->preds); (e = ei_safe_edge (ei)); )
10361debfc3dSmrg 	  {
10371debfc3dSmrg 	    if (e->insns.r && (e->flags & EDGE_EH)
10381debfc3dSmrg 		&& !single_pred_p (e->dest))
10391debfc3dSmrg 	      {
10401debfc3dSmrg 		rtx_insn *insns = e->insns.r;
10411debfc3dSmrg 		basic_block bb;
10421debfc3dSmrg 		e->insns.r = NULL;
10431debfc3dSmrg 		bb = split_edge (e);
10441debfc3dSmrg 		single_pred_edge (bb)->insns.r = insns;
10451debfc3dSmrg 	      }
10461debfc3dSmrg 	    else
10471debfc3dSmrg 	      ei_next (&ei);
10481debfc3dSmrg 	  }
10491debfc3dSmrg       }
10501debfc3dSmrg }
10511debfc3dSmrg 
10521debfc3dSmrg 
10531debfc3dSmrg /* Remove the ssa-names in the current function and translate them into normal
10541debfc3dSmrg    compiler variables.  PERFORM_TER is true if Temporary Expression Replacement
10551debfc3dSmrg    should also be used.  */
10561debfc3dSmrg 
10571debfc3dSmrg static void
remove_ssa_form(bool perform_ter,struct ssaexpand * sa)10581debfc3dSmrg remove_ssa_form (bool perform_ter, struct ssaexpand *sa)
10591debfc3dSmrg {
10601debfc3dSmrg   bitmap values = NULL;
10611debfc3dSmrg   var_map map;
10621debfc3dSmrg 
1063c0a68be4Smrg   for_all_parms (create_default_def, NULL);
1064c0a68be4Smrg   map = init_var_map (num_ssa_names);
1065c0a68be4Smrg   coalesce_ssa_name (map);
10661debfc3dSmrg 
10671debfc3dSmrg   /* Return to viewing the variable list as just all reference variables after
10681debfc3dSmrg      coalescing has been performed.  */
10691debfc3dSmrg   partition_view_normal (map);
10701debfc3dSmrg 
10711debfc3dSmrg   if (dump_file && (dump_flags & TDF_DETAILS))
10721debfc3dSmrg     {
10731debfc3dSmrg       fprintf (dump_file, "After Coalescing:\n");
10741debfc3dSmrg       dump_var_map (dump_file, map);
10751debfc3dSmrg     }
10761debfc3dSmrg 
10771debfc3dSmrg   if (perform_ter)
10781debfc3dSmrg     {
10791debfc3dSmrg       values = find_replaceable_exprs (map);
10801debfc3dSmrg       if (values && dump_file && (dump_flags & TDF_DETAILS))
10811debfc3dSmrg 	dump_replaceable_exprs (dump_file, values);
10821debfc3dSmrg     }
10831debfc3dSmrg 
10841debfc3dSmrg   rewrite_trees (map);
10851debfc3dSmrg 
10861debfc3dSmrg   sa->map = map;
10871debfc3dSmrg   sa->values = values;
10881debfc3dSmrg   sa->partitions_for_parm_default_defs = get_parm_default_def_partitions (map);
1089a2dc1f3fSmrg   sa->partitions_for_undefined_values = get_undefined_value_partitions (map);
10901debfc3dSmrg }
10911debfc3dSmrg 
10921debfc3dSmrg 
10931debfc3dSmrg /* If not already done so for basic block BB, assign increasing uids
10941debfc3dSmrg    to each of its instructions.  */
10951debfc3dSmrg 
10961debfc3dSmrg static void
maybe_renumber_stmts_bb(basic_block bb)10971debfc3dSmrg maybe_renumber_stmts_bb (basic_block bb)
10981debfc3dSmrg {
10991debfc3dSmrg   unsigned i = 0;
11001debfc3dSmrg   gimple_stmt_iterator gsi;
11011debfc3dSmrg 
11021debfc3dSmrg   if (!bb->aux)
11031debfc3dSmrg     return;
11041debfc3dSmrg   bb->aux = NULL;
11051debfc3dSmrg   for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
11061debfc3dSmrg     {
11071debfc3dSmrg       gimple *stmt = gsi_stmt (gsi);
11081debfc3dSmrg       gimple_set_uid (stmt, i);
11091debfc3dSmrg       i++;
11101debfc3dSmrg     }
11111debfc3dSmrg }
11121debfc3dSmrg 
11131debfc3dSmrg 
11141debfc3dSmrg /* Return true if we can determine that the SSA_NAMEs RESULT (a result
11151debfc3dSmrg    of a PHI node) and ARG (one of its arguments) conflict.  Return false
11161debfc3dSmrg    otherwise, also when we simply aren't sure.  */
11171debfc3dSmrg 
11181debfc3dSmrg static bool
trivially_conflicts_p(basic_block bb,tree result,tree arg)11191debfc3dSmrg trivially_conflicts_p (basic_block bb, tree result, tree arg)
11201debfc3dSmrg {
11211debfc3dSmrg   use_operand_p use;
11221debfc3dSmrg   imm_use_iterator imm_iter;
11231debfc3dSmrg   gimple *defa = SSA_NAME_DEF_STMT (arg);
11241debfc3dSmrg 
11251debfc3dSmrg   /* If ARG isn't defined in the same block it's too complicated for
11261debfc3dSmrg      our little mind.  */
11271debfc3dSmrg   if (gimple_bb (defa) != bb)
11281debfc3dSmrg     return false;
11291debfc3dSmrg 
11301debfc3dSmrg   FOR_EACH_IMM_USE_FAST (use, imm_iter, result)
11311debfc3dSmrg     {
11321debfc3dSmrg       gimple *use_stmt = USE_STMT (use);
11331debfc3dSmrg       if (is_gimple_debug (use_stmt))
11341debfc3dSmrg 	continue;
11351debfc3dSmrg       /* Now, if there's a use of RESULT that lies outside this basic block,
11361debfc3dSmrg 	 then there surely is a conflict with ARG.  */
11371debfc3dSmrg       if (gimple_bb (use_stmt) != bb)
11381debfc3dSmrg 	return true;
11391debfc3dSmrg       if (gimple_code (use_stmt) == GIMPLE_PHI)
11401debfc3dSmrg 	continue;
11411debfc3dSmrg       /* The use now is in a real stmt of BB, so if ARG was defined
11421debfc3dSmrg          in a PHI node (like RESULT) both conflict.  */
11431debfc3dSmrg       if (gimple_code (defa) == GIMPLE_PHI)
11441debfc3dSmrg 	return true;
11451debfc3dSmrg       maybe_renumber_stmts_bb (bb);
11461debfc3dSmrg       /* If the use of RESULT occurs after the definition of ARG,
11471debfc3dSmrg          the two conflict too.  */
11481debfc3dSmrg       if (gimple_uid (defa) < gimple_uid (use_stmt))
11491debfc3dSmrg 	return true;
11501debfc3dSmrg     }
11511debfc3dSmrg 
11521debfc3dSmrg   return false;
11531debfc3dSmrg }
11541debfc3dSmrg 
11551debfc3dSmrg 
11561debfc3dSmrg /* Search every PHI node for arguments associated with backedges which
11571debfc3dSmrg    we can trivially determine will need a copy (the argument is either
11581debfc3dSmrg    not an SSA_NAME or the argument has a different underlying variable
11591debfc3dSmrg    than the PHI result).
11601debfc3dSmrg 
11611debfc3dSmrg    Insert a copy from the PHI argument to a new destination at the
11621debfc3dSmrg    end of the block with the backedge to the top of the loop.  Update
11631debfc3dSmrg    the PHI argument to reference this new destination.  */
11641debfc3dSmrg 
11651debfc3dSmrg static void
insert_backedge_copies(void)11661debfc3dSmrg insert_backedge_copies (void)
11671debfc3dSmrg {
11681debfc3dSmrg   basic_block bb;
11691debfc3dSmrg   gphi_iterator gsi;
11701debfc3dSmrg 
11711debfc3dSmrg   mark_dfs_back_edges ();
11721debfc3dSmrg 
11731debfc3dSmrg   FOR_EACH_BB_FN (bb, cfun)
11741debfc3dSmrg     {
11751debfc3dSmrg       /* Mark block as possibly needing calculation of UIDs.  */
11761debfc3dSmrg       bb->aux = &bb->aux;
11771debfc3dSmrg 
11781debfc3dSmrg       for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
11791debfc3dSmrg 	{
11801debfc3dSmrg 	  gphi *phi = gsi.phi ();
11811debfc3dSmrg 	  tree result = gimple_phi_result (phi);
11821debfc3dSmrg 	  size_t i;
11831debfc3dSmrg 
11841debfc3dSmrg 	  if (virtual_operand_p (result))
11851debfc3dSmrg 	    continue;
11861debfc3dSmrg 
11871debfc3dSmrg 	  for (i = 0; i < gimple_phi_num_args (phi); i++)
11881debfc3dSmrg 	    {
11891debfc3dSmrg 	      tree arg = gimple_phi_arg_def (phi, i);
11901debfc3dSmrg 	      edge e = gimple_phi_arg_edge (phi, i);
1191c0a68be4Smrg 	      /* We are only interested in copies emitted on critical
1192c0a68be4Smrg                  backedges.  */
1193c0a68be4Smrg 	      if (!(e->flags & EDGE_DFS_BACK)
1194c0a68be4Smrg 		  || !EDGE_CRITICAL_P (e))
1195c0a68be4Smrg 		continue;
11961debfc3dSmrg 
11971debfc3dSmrg 	      /* If the argument is not an SSA_NAME, then we will need a
1198c0a68be4Smrg 		 constant initialization.  If the argument is an SSA_NAME then
1199c0a68be4Smrg 		 a copy statement may be needed.  First handle the case
1200c0a68be4Smrg 		 where we cannot insert before the argument definition.  */
1201c0a68be4Smrg 	      if (TREE_CODE (arg) != SSA_NAME
1202c0a68be4Smrg 		  || (gimple_code (SSA_NAME_DEF_STMT (arg)) == GIMPLE_PHI
1203c0a68be4Smrg 		      && trivially_conflicts_p (bb, result, arg)))
12041debfc3dSmrg 		{
12051debfc3dSmrg 		  tree name;
12061debfc3dSmrg 		  gassign *stmt;
12071debfc3dSmrg 		  gimple *last = NULL;
12081debfc3dSmrg 		  gimple_stmt_iterator gsi2;
12091debfc3dSmrg 
12101debfc3dSmrg 		  gsi2 = gsi_last_bb (gimple_phi_arg_edge (phi, i)->src);
12111debfc3dSmrg 		  if (!gsi_end_p (gsi2))
12121debfc3dSmrg 		    last = gsi_stmt (gsi2);
12131debfc3dSmrg 
12141debfc3dSmrg 		  /* In theory the only way we ought to get back to the
12151debfc3dSmrg 		     start of a loop should be with a COND_EXPR or GOTO_EXPR.
12161debfc3dSmrg 		     However, better safe than sorry.
12171debfc3dSmrg 		     If the block ends with a control statement or
12181debfc3dSmrg 		     something that might throw, then we have to
12191debfc3dSmrg 		     insert this assignment before the last
12201debfc3dSmrg 		     statement.  Else insert it after the last statement.  */
12211debfc3dSmrg 		  if (last && stmt_ends_bb_p (last))
12221debfc3dSmrg 		    {
12231debfc3dSmrg 		      /* If the last statement in the block is the definition
12241debfc3dSmrg 			 site of the PHI argument, then we can't insert
12251debfc3dSmrg 			 anything after it.  */
12261debfc3dSmrg 		      if (TREE_CODE (arg) == SSA_NAME
12271debfc3dSmrg 			  && SSA_NAME_DEF_STMT (arg) == last)
12281debfc3dSmrg 			continue;
12291debfc3dSmrg 		    }
12301debfc3dSmrg 
12311debfc3dSmrg 		  /* Create a new instance of the underlying variable of the
12321debfc3dSmrg 		     PHI result.  */
12331debfc3dSmrg 		  name = copy_ssa_name (result);
12341debfc3dSmrg 		  stmt = gimple_build_assign (name,
12351debfc3dSmrg 					      gimple_phi_arg_def (phi, i));
12361debfc3dSmrg 
12371debfc3dSmrg 		  /* copy location if present.  */
12381debfc3dSmrg 		  if (gimple_phi_arg_has_location (phi, i))
12391debfc3dSmrg 		    gimple_set_location (stmt,
12401debfc3dSmrg 					 gimple_phi_arg_location (phi, i));
12411debfc3dSmrg 
12421debfc3dSmrg 		  /* Insert the new statement into the block and update
12431debfc3dSmrg 		     the PHI node.  */
12441debfc3dSmrg 		  if (last && stmt_ends_bb_p (last))
12451debfc3dSmrg 		    gsi_insert_before (&gsi2, stmt, GSI_NEW_STMT);
12461debfc3dSmrg 		  else
12471debfc3dSmrg 		    gsi_insert_after (&gsi2, stmt, GSI_NEW_STMT);
12481debfc3dSmrg 		  SET_PHI_ARG_DEF (phi, i, name);
12491debfc3dSmrg 		}
1250c0a68be4Smrg 	      /* Insert a copy before the definition of the backedge value
1251c0a68be4Smrg 		 and adjust all conflicting uses.  */
1252c0a68be4Smrg 	      else if (trivially_conflicts_p (bb, result, arg))
1253c0a68be4Smrg 		{
1254c0a68be4Smrg 		  gimple *def = SSA_NAME_DEF_STMT (arg);
1255c0a68be4Smrg 		  if (gimple_nop_p (def)
1256c0a68be4Smrg 		      || gimple_code (def) == GIMPLE_PHI)
1257c0a68be4Smrg 		    continue;
1258c0a68be4Smrg 		  tree name = copy_ssa_name (result);
1259c0a68be4Smrg 		  gimple *stmt = gimple_build_assign (name, result);
1260c0a68be4Smrg 		  imm_use_iterator imm_iter;
1261c0a68be4Smrg 		  gimple *use_stmt;
1262c0a68be4Smrg 		  /* The following matches trivially_conflicts_p.  */
1263c0a68be4Smrg 		  FOR_EACH_IMM_USE_STMT (use_stmt, imm_iter, result)
1264c0a68be4Smrg 		    {
1265c0a68be4Smrg 		      if (gimple_bb (use_stmt) != bb
1266c0a68be4Smrg 			  || (gimple_code (use_stmt) != GIMPLE_PHI
1267c0a68be4Smrg 			      && (maybe_renumber_stmts_bb (bb), true)
1268c0a68be4Smrg 			      && gimple_uid (use_stmt) > gimple_uid (def)))
1269c0a68be4Smrg 			{
1270c0a68be4Smrg 			  use_operand_p use;
1271c0a68be4Smrg 			  FOR_EACH_IMM_USE_ON_STMT (use, imm_iter)
1272c0a68be4Smrg 			    SET_USE (use, name);
1273c0a68be4Smrg 			}
1274c0a68be4Smrg 		    }
1275c0a68be4Smrg 		  gimple_stmt_iterator gsi = gsi_for_stmt (def);
1276c0a68be4Smrg 		  gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
1277c0a68be4Smrg 		}
12781debfc3dSmrg 	    }
12791debfc3dSmrg 	}
12801debfc3dSmrg 
12811debfc3dSmrg       /* Unmark this block again.  */
12821debfc3dSmrg       bb->aux = NULL;
12831debfc3dSmrg     }
12841debfc3dSmrg }
12851debfc3dSmrg 
12861debfc3dSmrg /* Free all memory associated with going out of SSA form.  SA is
12871debfc3dSmrg    the outof-SSA info object.  */
12881debfc3dSmrg 
12891debfc3dSmrg void
finish_out_of_ssa(struct ssaexpand * sa)12901debfc3dSmrg finish_out_of_ssa (struct ssaexpand *sa)
12911debfc3dSmrg {
12921debfc3dSmrg   free (sa->partition_to_pseudo);
12931debfc3dSmrg   if (sa->values)
12941debfc3dSmrg     BITMAP_FREE (sa->values);
12951debfc3dSmrg   delete_var_map (sa->map);
12961debfc3dSmrg   BITMAP_FREE (sa->partitions_for_parm_default_defs);
1297a2dc1f3fSmrg   BITMAP_FREE (sa->partitions_for_undefined_values);
12981debfc3dSmrg   memset (sa, 0, sizeof *sa);
12991debfc3dSmrg }
13001debfc3dSmrg 
13011debfc3dSmrg /* Take the current function out of SSA form, translating PHIs as described in
13021debfc3dSmrg    R. Morgan, ``Building an Optimizing Compiler'',
13031debfc3dSmrg    Butterworth-Heinemann, Boston, MA, 1998. pp 176-186.  */
13041debfc3dSmrg 
13051debfc3dSmrg unsigned int
rewrite_out_of_ssa(struct ssaexpand * sa)13061debfc3dSmrg rewrite_out_of_ssa (struct ssaexpand *sa)
13071debfc3dSmrg {
13081debfc3dSmrg   /* If elimination of a PHI requires inserting a copy on a backedge,
13091debfc3dSmrg      then we will have to split the backedge which has numerous
13101debfc3dSmrg      undesirable performance effects.
13111debfc3dSmrg 
13121debfc3dSmrg      A significant number of such cases can be handled here by inserting
13131debfc3dSmrg      copies into the loop itself.  */
13141debfc3dSmrg   insert_backedge_copies ();
13151debfc3dSmrg 
13161debfc3dSmrg 
13171debfc3dSmrg   /* Eliminate PHIs which are of no use, such as virtual or dead phis.  */
13181debfc3dSmrg   eliminate_useless_phis ();
13191debfc3dSmrg 
13201debfc3dSmrg   if (dump_file && (dump_flags & TDF_DETAILS))
13211debfc3dSmrg     gimple_dump_cfg (dump_file, dump_flags & ~TDF_DETAILS);
13221debfc3dSmrg 
13231debfc3dSmrg   remove_ssa_form (flag_tree_ter, sa);
13241debfc3dSmrg 
13251debfc3dSmrg   if (dump_file && (dump_flags & TDF_DETAILS))
13261debfc3dSmrg     gimple_dump_cfg (dump_file, dump_flags & ~TDF_DETAILS);
13271debfc3dSmrg 
13281debfc3dSmrg   return 0;
13291debfc3dSmrg }
1330