xref: /dflybsd-src/contrib/gcc-4.7/gcc/tree-outof-ssa.c (revision 04febcfb30580676d3e95f58a16c5137ee478b32)
1*e4b17023SJohn Marino /* Convert a program in SSA form into Normal form.
2*e4b17023SJohn Marino    Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010
3*e4b17023SJohn Marino    Free Software Foundation, Inc.
4*e4b17023SJohn Marino    Contributed by Andrew Macleod <amacleod@redhat.com>
5*e4b17023SJohn Marino 
6*e4b17023SJohn Marino This file is part of GCC.
7*e4b17023SJohn Marino 
8*e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify
9*e4b17023SJohn Marino it under the terms of the GNU General Public License as published by
10*e4b17023SJohn Marino the Free Software Foundation; either version 3, or (at your option)
11*e4b17023SJohn Marino any later version.
12*e4b17023SJohn Marino 
13*e4b17023SJohn Marino GCC is distributed in the hope that it will be useful,
14*e4b17023SJohn Marino but WITHOUT ANY WARRANTY; without even the implied warranty of
15*e4b17023SJohn Marino MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16*e4b17023SJohn Marino GNU General Public License for more details.
17*e4b17023SJohn Marino 
18*e4b17023SJohn Marino You should have received a copy of the GNU General Public License
19*e4b17023SJohn Marino along with GCC; see the file COPYING3.  If not see
20*e4b17023SJohn Marino <http://www.gnu.org/licenses/>.  */
21*e4b17023SJohn Marino 
22*e4b17023SJohn Marino #include "config.h"
23*e4b17023SJohn Marino #include "system.h"
24*e4b17023SJohn Marino #include "coretypes.h"
25*e4b17023SJohn Marino #include "tm.h"
26*e4b17023SJohn Marino #include "tree.h"
27*e4b17023SJohn Marino #include "ggc.h"
28*e4b17023SJohn Marino #include "basic-block.h"
29*e4b17023SJohn Marino #include "tree-pretty-print.h"
30*e4b17023SJohn Marino #include "gimple-pretty-print.h"
31*e4b17023SJohn Marino #include "bitmap.h"
32*e4b17023SJohn Marino #include "tree-flow.h"
33*e4b17023SJohn Marino #include "timevar.h"
34*e4b17023SJohn Marino #include "tree-dump.h"
35*e4b17023SJohn Marino #include "tree-pass.h"
36*e4b17023SJohn Marino #include "diagnostic-core.h"
37*e4b17023SJohn Marino #include "ssaexpand.h"
38*e4b17023SJohn Marino 
39*e4b17023SJohn Marino /* FIXME: A lot of code here deals with expanding to RTL.  All that code
40*e4b17023SJohn Marino    should be in cfgexpand.c.  */
41*e4b17023SJohn Marino #include "expr.h"
42*e4b17023SJohn Marino 
43*e4b17023SJohn Marino 
44*e4b17023SJohn Marino DEF_VEC_I(source_location);
45*e4b17023SJohn Marino DEF_VEC_ALLOC_I(source_location,heap);
46*e4b17023SJohn Marino 
47*e4b17023SJohn Marino /* Used to hold all the components required to do SSA PHI elimination.
48*e4b17023SJohn Marino    The node and pred/succ list is a simple linear list of nodes and
49*e4b17023SJohn Marino    edges represented as pairs of nodes.
50*e4b17023SJohn Marino 
51*e4b17023SJohn Marino    The predecessor and successor list:  Nodes are entered in pairs, where
52*e4b17023SJohn Marino    [0] ->PRED, [1]->SUCC.  All the even indexes in the array represent
53*e4b17023SJohn Marino    predecessors, all the odd elements are successors.
54*e4b17023SJohn Marino 
55*e4b17023SJohn Marino    Rationale:
56*e4b17023SJohn Marino    When implemented as bitmaps, very large programs SSA->Normal times were
57*e4b17023SJohn Marino    being dominated by clearing the interference graph.
58*e4b17023SJohn Marino 
59*e4b17023SJohn Marino    Typically this list of edges is extremely small since it only includes
60*e4b17023SJohn Marino    PHI results and uses from a single edge which have not coalesced with
61*e4b17023SJohn Marino    each other.  This means that no virtual PHI nodes are included, and
62*e4b17023SJohn Marino    empirical evidence suggests that the number of edges rarely exceed
63*e4b17023SJohn Marino    3, and in a bootstrap of GCC, the maximum size encountered was 7.
64*e4b17023SJohn Marino    This also limits the number of possible nodes that are involved to
65*e4b17023SJohn Marino    rarely more than 6, and in the bootstrap of gcc, the maximum number
66*e4b17023SJohn Marino    of nodes encountered was 12.  */
67*e4b17023SJohn Marino 
68*e4b17023SJohn Marino typedef struct _elim_graph {
69*e4b17023SJohn Marino   /* Size of the elimination vectors.  */
70*e4b17023SJohn Marino   int size;
71*e4b17023SJohn Marino 
72*e4b17023SJohn Marino   /* List of nodes in the elimination graph.  */
73*e4b17023SJohn Marino   VEC(int,heap) *nodes;
74*e4b17023SJohn Marino 
75*e4b17023SJohn Marino   /*  The predecessor and successor edge list.  */
76*e4b17023SJohn Marino   VEC(int,heap) *edge_list;
77*e4b17023SJohn Marino 
78*e4b17023SJohn Marino   /* Source locus on each edge */
79*e4b17023SJohn Marino   VEC(source_location,heap) *edge_locus;
80*e4b17023SJohn Marino 
81*e4b17023SJohn Marino   /* Visited vector.  */
82*e4b17023SJohn Marino   sbitmap visited;
83*e4b17023SJohn Marino 
84*e4b17023SJohn Marino   /* Stack for visited nodes.  */
85*e4b17023SJohn Marino   VEC(int,heap) *stack;
86*e4b17023SJohn Marino 
87*e4b17023SJohn Marino   /* The variable partition map.  */
88*e4b17023SJohn Marino   var_map map;
89*e4b17023SJohn Marino 
90*e4b17023SJohn Marino   /* Edge being eliminated by this graph.  */
91*e4b17023SJohn Marino   edge e;
92*e4b17023SJohn Marino 
93*e4b17023SJohn Marino   /* List of constant copies to emit.  These are pushed on in pairs.  */
94*e4b17023SJohn Marino   VEC(int,heap) *const_dests;
95*e4b17023SJohn Marino   VEC(tree,heap) *const_copies;
96*e4b17023SJohn Marino 
97*e4b17023SJohn Marino   /* Source locations for any constant copies.  */
98*e4b17023SJohn Marino   VEC(source_location,heap) *copy_locus;
99*e4b17023SJohn Marino } *elim_graph;
100*e4b17023SJohn Marino 
101*e4b17023SJohn Marino 
102*e4b17023SJohn Marino /* For an edge E find out a good source location to associate with
103*e4b17023SJohn Marino    instructions inserted on edge E.  If E has an implicit goto set,
104*e4b17023SJohn Marino    use its location.  Otherwise search instructions in predecessors
105*e4b17023SJohn Marino    of E for a location, and use that one.  That makes sense because
106*e4b17023SJohn Marino    we insert on edges for PHI nodes, and effects of PHIs happen on
107*e4b17023SJohn Marino    the end of the predecessor conceptually.  */
108*e4b17023SJohn Marino 
109*e4b17023SJohn Marino static void
set_location_for_edge(edge e)110*e4b17023SJohn Marino set_location_for_edge (edge e)
111*e4b17023SJohn Marino {
112*e4b17023SJohn Marino   if (e->goto_locus)
113*e4b17023SJohn Marino     {
114*e4b17023SJohn Marino       set_curr_insn_source_location (e->goto_locus);
115*e4b17023SJohn Marino       set_curr_insn_block (e->goto_block);
116*e4b17023SJohn Marino     }
117*e4b17023SJohn Marino   else
118*e4b17023SJohn Marino     {
119*e4b17023SJohn Marino       basic_block bb = e->src;
120*e4b17023SJohn Marino       gimple_stmt_iterator gsi;
121*e4b17023SJohn Marino 
122*e4b17023SJohn Marino       do
123*e4b17023SJohn Marino 	{
124*e4b17023SJohn Marino 	  for (gsi = gsi_last_bb (bb); !gsi_end_p (gsi); gsi_prev (&gsi))
125*e4b17023SJohn Marino 	    {
126*e4b17023SJohn Marino 	      gimple stmt = gsi_stmt (gsi);
127*e4b17023SJohn Marino 	      if (is_gimple_debug (stmt))
128*e4b17023SJohn Marino 		continue;
129*e4b17023SJohn Marino 	      if (gimple_has_location (stmt) || gimple_block (stmt))
130*e4b17023SJohn Marino 		{
131*e4b17023SJohn Marino 		  set_curr_insn_source_location (gimple_location (stmt));
132*e4b17023SJohn Marino 		  set_curr_insn_block (gimple_block (stmt));
133*e4b17023SJohn Marino 		  return;
134*e4b17023SJohn Marino 		}
135*e4b17023SJohn Marino 	    }
136*e4b17023SJohn Marino 	  /* Nothing found in this basic block.  Make a half-assed attempt
137*e4b17023SJohn Marino 	     to continue with another block.  */
138*e4b17023SJohn Marino 	  if (single_pred_p (bb))
139*e4b17023SJohn Marino 	    bb = single_pred (bb);
140*e4b17023SJohn Marino 	  else
141*e4b17023SJohn Marino 	    bb = e->src;
142*e4b17023SJohn Marino 	}
143*e4b17023SJohn Marino       while (bb != e->src);
144*e4b17023SJohn Marino     }
145*e4b17023SJohn Marino }
146*e4b17023SJohn Marino 
147*e4b17023SJohn Marino /* Emit insns to copy SRC into DEST converting SRC if necessary.  As
148*e4b17023SJohn Marino    SRC/DEST might be BLKmode memory locations SIZEEXP is a tree from
149*e4b17023SJohn Marino    which we deduce the size to copy in that case.  */
150*e4b17023SJohn Marino 
151*e4b17023SJohn Marino static inline rtx
emit_partition_copy(rtx dest,rtx src,int unsignedsrcp,tree sizeexp)152*e4b17023SJohn Marino emit_partition_copy (rtx dest, rtx src, int unsignedsrcp, tree sizeexp)
153*e4b17023SJohn Marino {
154*e4b17023SJohn Marino   rtx seq;
155*e4b17023SJohn Marino 
156*e4b17023SJohn Marino   start_sequence ();
157*e4b17023SJohn Marino 
158*e4b17023SJohn Marino   if (GET_MODE (src) != VOIDmode && GET_MODE (src) != GET_MODE (dest))
159*e4b17023SJohn Marino     src = convert_to_mode (GET_MODE (dest), src, unsignedsrcp);
160*e4b17023SJohn Marino   if (GET_MODE (src) == BLKmode)
161*e4b17023SJohn Marino     {
162*e4b17023SJohn Marino       gcc_assert (GET_MODE (dest) == BLKmode);
163*e4b17023SJohn Marino       emit_block_move (dest, src, expr_size (sizeexp), BLOCK_OP_NORMAL);
164*e4b17023SJohn Marino     }
165*e4b17023SJohn Marino   else
166*e4b17023SJohn Marino     emit_move_insn (dest, src);
167*e4b17023SJohn Marino 
168*e4b17023SJohn Marino   seq = get_insns ();
169*e4b17023SJohn Marino   end_sequence ();
170*e4b17023SJohn Marino 
171*e4b17023SJohn Marino   return seq;
172*e4b17023SJohn Marino }
173*e4b17023SJohn Marino 
174*e4b17023SJohn Marino /* Insert a copy instruction from partition SRC to DEST onto edge E.  */
175*e4b17023SJohn Marino 
176*e4b17023SJohn Marino static void
insert_partition_copy_on_edge(edge e,int dest,int src,source_location locus)177*e4b17023SJohn Marino insert_partition_copy_on_edge (edge e, int dest, int src, source_location locus)
178*e4b17023SJohn Marino {
179*e4b17023SJohn Marino   tree var;
180*e4b17023SJohn Marino   rtx seq;
181*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
182*e4b17023SJohn Marino     {
183*e4b17023SJohn Marino       fprintf (dump_file,
184*e4b17023SJohn Marino 	       "Inserting a partition copy on edge BB%d->BB%d :"
185*e4b17023SJohn Marino 	       "PART.%d = PART.%d",
186*e4b17023SJohn Marino 	       e->src->index,
187*e4b17023SJohn Marino 	       e->dest->index, dest, src);
188*e4b17023SJohn Marino       fprintf (dump_file, "\n");
189*e4b17023SJohn Marino     }
190*e4b17023SJohn Marino 
191*e4b17023SJohn Marino   gcc_assert (SA.partition_to_pseudo[dest]);
192*e4b17023SJohn Marino   gcc_assert (SA.partition_to_pseudo[src]);
193*e4b17023SJohn Marino 
194*e4b17023SJohn Marino   set_location_for_edge (e);
195*e4b17023SJohn Marino   /* If a locus is provided, override the default.  */
196*e4b17023SJohn Marino   if (locus)
197*e4b17023SJohn Marino     set_curr_insn_source_location (locus);
198*e4b17023SJohn Marino 
199*e4b17023SJohn Marino   var = partition_to_var (SA.map, src);
200*e4b17023SJohn Marino   seq = emit_partition_copy (SA.partition_to_pseudo[dest],
201*e4b17023SJohn Marino 			     SA.partition_to_pseudo[src],
202*e4b17023SJohn Marino 			     TYPE_UNSIGNED (TREE_TYPE (var)),
203*e4b17023SJohn Marino 			     var);
204*e4b17023SJohn Marino 
205*e4b17023SJohn Marino   insert_insn_on_edge (seq, e);
206*e4b17023SJohn Marino }
207*e4b17023SJohn Marino 
208*e4b17023SJohn Marino /* Insert a copy instruction from expression SRC to partition DEST
209*e4b17023SJohn Marino    onto edge E.  */
210*e4b17023SJohn Marino 
211*e4b17023SJohn Marino static void
insert_value_copy_on_edge(edge e,int dest,tree src,source_location locus)212*e4b17023SJohn Marino insert_value_copy_on_edge (edge e, int dest, tree src, source_location locus)
213*e4b17023SJohn Marino {
214*e4b17023SJohn Marino   rtx seq, x;
215*e4b17023SJohn Marino   enum machine_mode dest_mode, src_mode;
216*e4b17023SJohn Marino   int unsignedp;
217*e4b17023SJohn Marino   tree var;
218*e4b17023SJohn Marino 
219*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
220*e4b17023SJohn Marino     {
221*e4b17023SJohn Marino       fprintf (dump_file,
222*e4b17023SJohn Marino 	       "Inserting a value copy on edge BB%d->BB%d : PART.%d = ",
223*e4b17023SJohn Marino 	       e->src->index,
224*e4b17023SJohn Marino 	       e->dest->index, dest);
225*e4b17023SJohn Marino       print_generic_expr (dump_file, src, TDF_SLIM);
226*e4b17023SJohn Marino       fprintf (dump_file, "\n");
227*e4b17023SJohn Marino     }
228*e4b17023SJohn Marino 
229*e4b17023SJohn Marino   gcc_assert (SA.partition_to_pseudo[dest]);
230*e4b17023SJohn Marino 
231*e4b17023SJohn Marino   set_location_for_edge (e);
232*e4b17023SJohn Marino   /* If a locus is provided, override the default.  */
233*e4b17023SJohn Marino   if (locus)
234*e4b17023SJohn Marino     set_curr_insn_source_location (locus);
235*e4b17023SJohn Marino 
236*e4b17023SJohn Marino   start_sequence ();
237*e4b17023SJohn Marino 
238*e4b17023SJohn Marino   var = SSA_NAME_VAR (partition_to_var (SA.map, dest));
239*e4b17023SJohn Marino   src_mode = TYPE_MODE (TREE_TYPE (src));
240*e4b17023SJohn Marino   dest_mode = GET_MODE (SA.partition_to_pseudo[dest]);
241*e4b17023SJohn Marino   gcc_assert (src_mode == TYPE_MODE (TREE_TYPE (var)));
242*e4b17023SJohn Marino   gcc_assert (!REG_P (SA.partition_to_pseudo[dest])
243*e4b17023SJohn Marino 	      || dest_mode == promote_decl_mode (var, &unsignedp));
244*e4b17023SJohn Marino 
245*e4b17023SJohn Marino   if (src_mode != dest_mode)
246*e4b17023SJohn Marino     {
247*e4b17023SJohn Marino       x = expand_expr (src, NULL, src_mode, EXPAND_NORMAL);
248*e4b17023SJohn Marino       x = convert_modes (dest_mode, src_mode, x, unsignedp);
249*e4b17023SJohn Marino     }
250*e4b17023SJohn Marino   else if (src_mode == BLKmode)
251*e4b17023SJohn Marino     {
252*e4b17023SJohn Marino       x = SA.partition_to_pseudo[dest];
253*e4b17023SJohn Marino       store_expr (src, x, 0, false);
254*e4b17023SJohn Marino     }
255*e4b17023SJohn Marino   else
256*e4b17023SJohn Marino     x = expand_expr (src, SA.partition_to_pseudo[dest],
257*e4b17023SJohn Marino 		     dest_mode, EXPAND_NORMAL);
258*e4b17023SJohn Marino 
259*e4b17023SJohn Marino   if (x != SA.partition_to_pseudo[dest])
260*e4b17023SJohn Marino     emit_move_insn (SA.partition_to_pseudo[dest], x);
261*e4b17023SJohn Marino   seq = get_insns ();
262*e4b17023SJohn Marino   end_sequence ();
263*e4b17023SJohn Marino 
264*e4b17023SJohn Marino   insert_insn_on_edge (seq, e);
265*e4b17023SJohn Marino }
266*e4b17023SJohn Marino 
267*e4b17023SJohn Marino /* Insert a copy instruction from RTL expression SRC to partition DEST
268*e4b17023SJohn Marino    onto edge E.  */
269*e4b17023SJohn Marino 
270*e4b17023SJohn Marino static void
insert_rtx_to_part_on_edge(edge e,int dest,rtx src,int unsignedsrcp,source_location locus)271*e4b17023SJohn Marino insert_rtx_to_part_on_edge (edge e, int dest, rtx src, int unsignedsrcp,
272*e4b17023SJohn Marino 			    source_location locus)
273*e4b17023SJohn Marino {
274*e4b17023SJohn Marino   rtx seq;
275*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
276*e4b17023SJohn Marino     {
277*e4b17023SJohn Marino       fprintf (dump_file,
278*e4b17023SJohn Marino 	       "Inserting a temp copy on edge BB%d->BB%d : PART.%d = ",
279*e4b17023SJohn Marino 	       e->src->index,
280*e4b17023SJohn Marino 	       e->dest->index, dest);
281*e4b17023SJohn Marino       print_simple_rtl (dump_file, src);
282*e4b17023SJohn Marino       fprintf (dump_file, "\n");
283*e4b17023SJohn Marino     }
284*e4b17023SJohn Marino 
285*e4b17023SJohn Marino   gcc_assert (SA.partition_to_pseudo[dest]);
286*e4b17023SJohn Marino 
287*e4b17023SJohn Marino   set_location_for_edge (e);
288*e4b17023SJohn Marino   /* If a locus is provided, override the default.  */
289*e4b17023SJohn Marino   if (locus)
290*e4b17023SJohn Marino     set_curr_insn_source_location (locus);
291*e4b17023SJohn Marino 
292*e4b17023SJohn Marino   /* We give the destination as sizeexp in case src/dest are BLKmode
293*e4b17023SJohn Marino      mems.  Usually we give the source.  As we result from SSA names
294*e4b17023SJohn Marino      the left and right size should be the same (and no WITH_SIZE_EXPR
295*e4b17023SJohn Marino      involved), so it doesn't matter.  */
296*e4b17023SJohn Marino   seq = emit_partition_copy (SA.partition_to_pseudo[dest],
297*e4b17023SJohn Marino 			     src, unsignedsrcp,
298*e4b17023SJohn Marino 			     partition_to_var (SA.map, dest));
299*e4b17023SJohn Marino 
300*e4b17023SJohn Marino   insert_insn_on_edge (seq, e);
301*e4b17023SJohn Marino }
302*e4b17023SJohn Marino 
303*e4b17023SJohn Marino /* Insert a copy instruction from partition SRC to RTL lvalue DEST
304*e4b17023SJohn Marino    onto edge E.  */
305*e4b17023SJohn Marino 
306*e4b17023SJohn Marino static void
insert_part_to_rtx_on_edge(edge e,rtx dest,int src,source_location locus)307*e4b17023SJohn Marino insert_part_to_rtx_on_edge (edge e, rtx dest, int src, source_location locus)
308*e4b17023SJohn Marino {
309*e4b17023SJohn Marino   tree var;
310*e4b17023SJohn Marino   rtx seq;
311*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
312*e4b17023SJohn Marino     {
313*e4b17023SJohn Marino       fprintf (dump_file,
314*e4b17023SJohn Marino 	       "Inserting a temp copy on edge BB%d->BB%d : ",
315*e4b17023SJohn Marino 	       e->src->index,
316*e4b17023SJohn Marino 	       e->dest->index);
317*e4b17023SJohn Marino       print_simple_rtl (dump_file, dest);
318*e4b17023SJohn Marino       fprintf (dump_file, "= PART.%d\n", src);
319*e4b17023SJohn Marino     }
320*e4b17023SJohn Marino 
321*e4b17023SJohn Marino   gcc_assert (SA.partition_to_pseudo[src]);
322*e4b17023SJohn Marino 
323*e4b17023SJohn Marino   set_location_for_edge (e);
324*e4b17023SJohn Marino   /* If a locus is provided, override the default.  */
325*e4b17023SJohn Marino   if (locus)
326*e4b17023SJohn Marino     set_curr_insn_source_location (locus);
327*e4b17023SJohn Marino 
328*e4b17023SJohn Marino   var = partition_to_var (SA.map, src);
329*e4b17023SJohn Marino   seq = emit_partition_copy (dest,
330*e4b17023SJohn Marino 			     SA.partition_to_pseudo[src],
331*e4b17023SJohn Marino 			     TYPE_UNSIGNED (TREE_TYPE (var)),
332*e4b17023SJohn Marino 			     var);
333*e4b17023SJohn Marino 
334*e4b17023SJohn Marino   insert_insn_on_edge (seq, e);
335*e4b17023SJohn Marino }
336*e4b17023SJohn Marino 
337*e4b17023SJohn Marino 
338*e4b17023SJohn Marino /* Create an elimination graph with SIZE nodes and associated data
339*e4b17023SJohn Marino    structures.  */
340*e4b17023SJohn Marino 
341*e4b17023SJohn Marino static elim_graph
new_elim_graph(int size)342*e4b17023SJohn Marino new_elim_graph (int size)
343*e4b17023SJohn Marino {
344*e4b17023SJohn Marino   elim_graph g = (elim_graph) xmalloc (sizeof (struct _elim_graph));
345*e4b17023SJohn Marino 
346*e4b17023SJohn Marino   g->nodes = VEC_alloc (int, heap, 30);
347*e4b17023SJohn Marino   g->const_dests = VEC_alloc (int, heap, 20);
348*e4b17023SJohn Marino   g->const_copies = VEC_alloc (tree, heap, 20);
349*e4b17023SJohn Marino   g->copy_locus = VEC_alloc (source_location, heap, 10);
350*e4b17023SJohn Marino   g->edge_list = VEC_alloc (int, heap, 20);
351*e4b17023SJohn Marino   g->edge_locus = VEC_alloc (source_location, heap, 10);
352*e4b17023SJohn Marino   g->stack = VEC_alloc (int, heap, 30);
353*e4b17023SJohn Marino 
354*e4b17023SJohn Marino   g->visited = sbitmap_alloc (size);
355*e4b17023SJohn Marino 
356*e4b17023SJohn Marino   return g;
357*e4b17023SJohn Marino }
358*e4b17023SJohn Marino 
359*e4b17023SJohn Marino 
360*e4b17023SJohn Marino /* Empty elimination graph G.  */
361*e4b17023SJohn Marino 
362*e4b17023SJohn Marino static inline void
clear_elim_graph(elim_graph g)363*e4b17023SJohn Marino clear_elim_graph (elim_graph g)
364*e4b17023SJohn Marino {
365*e4b17023SJohn Marino   VEC_truncate (int, g->nodes, 0);
366*e4b17023SJohn Marino   VEC_truncate (int, g->edge_list, 0);
367*e4b17023SJohn Marino   VEC_truncate (source_location, g->edge_locus, 0);
368*e4b17023SJohn Marino }
369*e4b17023SJohn Marino 
370*e4b17023SJohn Marino 
371*e4b17023SJohn Marino /* Delete elimination graph G.  */
372*e4b17023SJohn Marino 
373*e4b17023SJohn Marino static inline void
delete_elim_graph(elim_graph g)374*e4b17023SJohn Marino delete_elim_graph (elim_graph g)
375*e4b17023SJohn Marino {
376*e4b17023SJohn Marino   sbitmap_free (g->visited);
377*e4b17023SJohn Marino   VEC_free (int, heap, g->stack);
378*e4b17023SJohn Marino   VEC_free (int, heap, g->edge_list);
379*e4b17023SJohn Marino   VEC_free (tree, heap, g->const_copies);
380*e4b17023SJohn Marino   VEC_free (int, heap, g->const_dests);
381*e4b17023SJohn Marino   VEC_free (int, heap, g->nodes);
382*e4b17023SJohn Marino   VEC_free (source_location, heap, g->copy_locus);
383*e4b17023SJohn Marino   VEC_free (source_location, heap, g->edge_locus);
384*e4b17023SJohn Marino 
385*e4b17023SJohn Marino   free (g);
386*e4b17023SJohn Marino }
387*e4b17023SJohn Marino 
388*e4b17023SJohn Marino 
389*e4b17023SJohn Marino /* Return the number of nodes in graph G.  */
390*e4b17023SJohn Marino 
391*e4b17023SJohn Marino static inline int
elim_graph_size(elim_graph g)392*e4b17023SJohn Marino elim_graph_size (elim_graph g)
393*e4b17023SJohn Marino {
394*e4b17023SJohn Marino   return VEC_length (int, g->nodes);
395*e4b17023SJohn Marino }
396*e4b17023SJohn Marino 
397*e4b17023SJohn Marino 
398*e4b17023SJohn Marino /* Add NODE to graph G, if it doesn't exist already.  */
399*e4b17023SJohn Marino 
400*e4b17023SJohn Marino static inline void
elim_graph_add_node(elim_graph g,int node)401*e4b17023SJohn Marino elim_graph_add_node (elim_graph g, int node)
402*e4b17023SJohn Marino {
403*e4b17023SJohn Marino   int x;
404*e4b17023SJohn Marino   int t;
405*e4b17023SJohn Marino 
406*e4b17023SJohn Marino   FOR_EACH_VEC_ELT (int, g->nodes, x, t)
407*e4b17023SJohn Marino     if (t == node)
408*e4b17023SJohn Marino       return;
409*e4b17023SJohn Marino   VEC_safe_push (int, heap, g->nodes, node);
410*e4b17023SJohn Marino }
411*e4b17023SJohn Marino 
412*e4b17023SJohn Marino 
413*e4b17023SJohn Marino /* Add the edge PRED->SUCC to graph G.  */
414*e4b17023SJohn Marino 
415*e4b17023SJohn Marino static inline void
elim_graph_add_edge(elim_graph g,int pred,int succ,source_location locus)416*e4b17023SJohn Marino elim_graph_add_edge (elim_graph g, int pred, int succ, source_location locus)
417*e4b17023SJohn Marino {
418*e4b17023SJohn Marino   VEC_safe_push (int, heap, g->edge_list, pred);
419*e4b17023SJohn Marino   VEC_safe_push (int, heap, g->edge_list, succ);
420*e4b17023SJohn Marino   VEC_safe_push (source_location, heap, g->edge_locus, locus);
421*e4b17023SJohn Marino }
422*e4b17023SJohn Marino 
423*e4b17023SJohn Marino 
424*e4b17023SJohn Marino /* Remove an edge from graph G for which NODE is the predecessor, and
425*e4b17023SJohn Marino    return the successor node.  -1 is returned if there is no such edge.  */
426*e4b17023SJohn Marino 
427*e4b17023SJohn Marino static inline int
elim_graph_remove_succ_edge(elim_graph g,int node,source_location * locus)428*e4b17023SJohn Marino elim_graph_remove_succ_edge (elim_graph g, int node, source_location *locus)
429*e4b17023SJohn Marino {
430*e4b17023SJohn Marino   int y;
431*e4b17023SJohn Marino   unsigned x;
432*e4b17023SJohn Marino   for (x = 0; x < VEC_length (int, g->edge_list); x += 2)
433*e4b17023SJohn Marino     if (VEC_index (int, g->edge_list, x) == node)
434*e4b17023SJohn Marino       {
435*e4b17023SJohn Marino         VEC_replace (int, g->edge_list, x, -1);
436*e4b17023SJohn Marino 	y = VEC_index (int, g->edge_list, x + 1);
437*e4b17023SJohn Marino 	VEC_replace (int, g->edge_list, x + 1, -1);
438*e4b17023SJohn Marino 	*locus = VEC_index (source_location, g->edge_locus, x / 2);
439*e4b17023SJohn Marino 	VEC_replace (source_location, g->edge_locus, x / 2, UNKNOWN_LOCATION);
440*e4b17023SJohn Marino 	return y;
441*e4b17023SJohn Marino       }
442*e4b17023SJohn Marino   *locus = UNKNOWN_LOCATION;
443*e4b17023SJohn Marino   return -1;
444*e4b17023SJohn Marino }
445*e4b17023SJohn Marino 
446*e4b17023SJohn Marino 
447*e4b17023SJohn Marino /* Find all the nodes in GRAPH which are successors to NODE in the
448*e4b17023SJohn Marino    edge list.  VAR will hold the partition number found.  CODE is the
449*e4b17023SJohn Marino    code fragment executed for every node found.  */
450*e4b17023SJohn Marino 
451*e4b17023SJohn Marino #define FOR_EACH_ELIM_GRAPH_SUCC(GRAPH, NODE, VAR, LOCUS, CODE)		\
452*e4b17023SJohn Marino do {									\
453*e4b17023SJohn Marino   unsigned x_;								\
454*e4b17023SJohn Marino   int y_;								\
455*e4b17023SJohn Marino   for (x_ = 0; x_ < VEC_length (int, (GRAPH)->edge_list); x_ += 2)	\
456*e4b17023SJohn Marino     {									\
457*e4b17023SJohn Marino       y_ = VEC_index (int, (GRAPH)->edge_list, x_);			\
458*e4b17023SJohn Marino       if (y_ != (NODE))							\
459*e4b17023SJohn Marino         continue;							\
460*e4b17023SJohn Marino       (void) ((VAR) = VEC_index (int, (GRAPH)->edge_list, x_ + 1));	\
461*e4b17023SJohn Marino       (void) ((LOCUS) = VEC_index (source_location,			\
462*e4b17023SJohn Marino 				   (GRAPH)->edge_locus, x_ / 2));	\
463*e4b17023SJohn Marino       CODE;								\
464*e4b17023SJohn Marino     }									\
465*e4b17023SJohn Marino } while (0)
466*e4b17023SJohn Marino 
467*e4b17023SJohn Marino 
468*e4b17023SJohn Marino /* Find all the nodes which are predecessors of NODE in the edge list for
469*e4b17023SJohn Marino    GRAPH.  VAR will hold the partition number found.  CODE is the
470*e4b17023SJohn Marino    code fragment executed for every node found.  */
471*e4b17023SJohn Marino 
472*e4b17023SJohn Marino #define FOR_EACH_ELIM_GRAPH_PRED(GRAPH, NODE, VAR, LOCUS, CODE)		\
473*e4b17023SJohn Marino do {									\
474*e4b17023SJohn Marino   unsigned x_;								\
475*e4b17023SJohn Marino   int y_;								\
476*e4b17023SJohn Marino   for (x_ = 0; x_ < VEC_length (int, (GRAPH)->edge_list); x_ += 2)	\
477*e4b17023SJohn Marino     {									\
478*e4b17023SJohn Marino       y_ = VEC_index (int, (GRAPH)->edge_list, x_ + 1);			\
479*e4b17023SJohn Marino       if (y_ != (NODE))							\
480*e4b17023SJohn Marino         continue;							\
481*e4b17023SJohn Marino       (void) ((VAR) = VEC_index (int, (GRAPH)->edge_list, x_));		\
482*e4b17023SJohn Marino       (void) ((LOCUS) = VEC_index (source_location,			\
483*e4b17023SJohn Marino 				   (GRAPH)->edge_locus, x_ / 2));	\
484*e4b17023SJohn Marino       CODE;								\
485*e4b17023SJohn Marino     }									\
486*e4b17023SJohn Marino } while (0)
487*e4b17023SJohn Marino 
488*e4b17023SJohn Marino 
489*e4b17023SJohn Marino /* Add T to elimination graph G.  */
490*e4b17023SJohn Marino 
491*e4b17023SJohn Marino static inline void
eliminate_name(elim_graph g,int T)492*e4b17023SJohn Marino eliminate_name (elim_graph g, int T)
493*e4b17023SJohn Marino {
494*e4b17023SJohn Marino   elim_graph_add_node (g, T);
495*e4b17023SJohn Marino }
496*e4b17023SJohn Marino 
497*e4b17023SJohn Marino 
498*e4b17023SJohn Marino /* Build elimination graph G for basic block BB on incoming PHI edge
499*e4b17023SJohn Marino    G->e.  */
500*e4b17023SJohn Marino 
501*e4b17023SJohn Marino static void
eliminate_build(elim_graph g)502*e4b17023SJohn Marino eliminate_build (elim_graph g)
503*e4b17023SJohn Marino {
504*e4b17023SJohn Marino   tree Ti;
505*e4b17023SJohn Marino   int p0, pi;
506*e4b17023SJohn Marino   gimple_stmt_iterator gsi;
507*e4b17023SJohn Marino 
508*e4b17023SJohn Marino   clear_elim_graph (g);
509*e4b17023SJohn Marino 
510*e4b17023SJohn Marino   for (gsi = gsi_start_phis (g->e->dest); !gsi_end_p (gsi); gsi_next (&gsi))
511*e4b17023SJohn Marino     {
512*e4b17023SJohn Marino       gimple phi = gsi_stmt (gsi);
513*e4b17023SJohn Marino       source_location locus;
514*e4b17023SJohn Marino 
515*e4b17023SJohn Marino       p0 = var_to_partition (g->map, gimple_phi_result (phi));
516*e4b17023SJohn Marino       /* Ignore results which are not in partitions.  */
517*e4b17023SJohn Marino       if (p0 == NO_PARTITION)
518*e4b17023SJohn Marino 	continue;
519*e4b17023SJohn Marino 
520*e4b17023SJohn Marino       Ti = PHI_ARG_DEF (phi, g->e->dest_idx);
521*e4b17023SJohn Marino       locus = gimple_phi_arg_location_from_edge (phi, g->e);
522*e4b17023SJohn Marino 
523*e4b17023SJohn Marino       /* If this argument is a constant, or a SSA_NAME which is being
524*e4b17023SJohn Marino 	 left in SSA form, just queue a copy to be emitted on this
525*e4b17023SJohn Marino 	 edge.  */
526*e4b17023SJohn Marino       if (!phi_ssa_name_p (Ti)
527*e4b17023SJohn Marino 	  || (TREE_CODE (Ti) == SSA_NAME
528*e4b17023SJohn Marino 	      && var_to_partition (g->map, Ti) == NO_PARTITION))
529*e4b17023SJohn Marino         {
530*e4b17023SJohn Marino 	  /* Save constant copies until all other copies have been emitted
531*e4b17023SJohn Marino 	     on this edge.  */
532*e4b17023SJohn Marino 	  VEC_safe_push (int, heap, g->const_dests, p0);
533*e4b17023SJohn Marino 	  VEC_safe_push (tree, heap, g->const_copies, Ti);
534*e4b17023SJohn Marino 	  VEC_safe_push (source_location, heap, g->copy_locus, locus);
535*e4b17023SJohn Marino 	}
536*e4b17023SJohn Marino       else
537*e4b17023SJohn Marino         {
538*e4b17023SJohn Marino 	  pi = var_to_partition (g->map, Ti);
539*e4b17023SJohn Marino 	  if (p0 != pi)
540*e4b17023SJohn Marino 	    {
541*e4b17023SJohn Marino 	      eliminate_name (g, p0);
542*e4b17023SJohn Marino 	      eliminate_name (g, pi);
543*e4b17023SJohn Marino 	      elim_graph_add_edge (g, p0, pi, locus);
544*e4b17023SJohn Marino 	    }
545*e4b17023SJohn Marino 	}
546*e4b17023SJohn Marino     }
547*e4b17023SJohn Marino }
548*e4b17023SJohn Marino 
549*e4b17023SJohn Marino 
550*e4b17023SJohn Marino /* Push successors of T onto the elimination stack for G.  */
551*e4b17023SJohn Marino 
552*e4b17023SJohn Marino static void
elim_forward(elim_graph g,int T)553*e4b17023SJohn Marino elim_forward (elim_graph g, int T)
554*e4b17023SJohn Marino {
555*e4b17023SJohn Marino   int S;
556*e4b17023SJohn Marino   source_location locus;
557*e4b17023SJohn Marino 
558*e4b17023SJohn Marino   SET_BIT (g->visited, T);
559*e4b17023SJohn Marino   FOR_EACH_ELIM_GRAPH_SUCC (g, T, S, locus,
560*e4b17023SJohn Marino     {
561*e4b17023SJohn Marino       if (!TEST_BIT (g->visited, S))
562*e4b17023SJohn Marino         elim_forward (g, S);
563*e4b17023SJohn Marino     });
564*e4b17023SJohn Marino   VEC_safe_push (int, heap, g->stack, T);
565*e4b17023SJohn Marino }
566*e4b17023SJohn Marino 
567*e4b17023SJohn Marino 
568*e4b17023SJohn Marino /* Return 1 if there unvisited predecessors of T in graph G.  */
569*e4b17023SJohn Marino 
570*e4b17023SJohn Marino static int
elim_unvisited_predecessor(elim_graph g,int T)571*e4b17023SJohn Marino elim_unvisited_predecessor (elim_graph g, int T)
572*e4b17023SJohn Marino {
573*e4b17023SJohn Marino   int P;
574*e4b17023SJohn Marino   source_location locus;
575*e4b17023SJohn Marino 
576*e4b17023SJohn Marino   FOR_EACH_ELIM_GRAPH_PRED (g, T, P, locus,
577*e4b17023SJohn Marino     {
578*e4b17023SJohn Marino       if (!TEST_BIT (g->visited, P))
579*e4b17023SJohn Marino         return 1;
580*e4b17023SJohn Marino     });
581*e4b17023SJohn Marino   return 0;
582*e4b17023SJohn Marino }
583*e4b17023SJohn Marino 
584*e4b17023SJohn Marino /* Process predecessors first, and insert a copy.  */
585*e4b17023SJohn Marino 
586*e4b17023SJohn Marino static void
elim_backward(elim_graph g,int T)587*e4b17023SJohn Marino elim_backward (elim_graph g, int T)
588*e4b17023SJohn Marino {
589*e4b17023SJohn Marino   int P;
590*e4b17023SJohn Marino   source_location locus;
591*e4b17023SJohn Marino 
592*e4b17023SJohn Marino   SET_BIT (g->visited, T);
593*e4b17023SJohn Marino   FOR_EACH_ELIM_GRAPH_PRED (g, T, P, locus,
594*e4b17023SJohn Marino     {
595*e4b17023SJohn Marino       if (!TEST_BIT (g->visited, P))
596*e4b17023SJohn Marino         {
597*e4b17023SJohn Marino 	  elim_backward (g, P);
598*e4b17023SJohn Marino 	  insert_partition_copy_on_edge (g->e, P, T, locus);
599*e4b17023SJohn Marino 	}
600*e4b17023SJohn Marino     });
601*e4b17023SJohn Marino }
602*e4b17023SJohn Marino 
603*e4b17023SJohn Marino /* Allocate a new pseudo register usable for storing values sitting
604*e4b17023SJohn Marino    in NAME (a decl or SSA name), i.e. with matching mode and attributes.  */
605*e4b17023SJohn Marino 
606*e4b17023SJohn Marino static rtx
get_temp_reg(tree name)607*e4b17023SJohn Marino get_temp_reg (tree name)
608*e4b17023SJohn Marino {
609*e4b17023SJohn Marino   tree var = TREE_CODE (name) == SSA_NAME ? SSA_NAME_VAR (name) : name;
610*e4b17023SJohn Marino   tree type = TREE_TYPE (var);
611*e4b17023SJohn Marino   int unsignedp;
612*e4b17023SJohn Marino   enum machine_mode reg_mode = promote_decl_mode (var, &unsignedp);
613*e4b17023SJohn Marino   rtx x = gen_reg_rtx (reg_mode);
614*e4b17023SJohn Marino   if (POINTER_TYPE_P (type))
615*e4b17023SJohn Marino     mark_reg_pointer (x, TYPE_ALIGN (TREE_TYPE (TREE_TYPE (var))));
616*e4b17023SJohn Marino   return x;
617*e4b17023SJohn Marino }
618*e4b17023SJohn Marino 
619*e4b17023SJohn Marino /* Insert required copies for T in graph G.  Check for a strongly connected
620*e4b17023SJohn Marino    region, and create a temporary to break the cycle if one is found.  */
621*e4b17023SJohn Marino 
622*e4b17023SJohn Marino static void
elim_create(elim_graph g,int T)623*e4b17023SJohn Marino elim_create (elim_graph g, int T)
624*e4b17023SJohn Marino {
625*e4b17023SJohn Marino   int P, S;
626*e4b17023SJohn Marino   source_location locus;
627*e4b17023SJohn Marino 
628*e4b17023SJohn Marino   if (elim_unvisited_predecessor (g, T))
629*e4b17023SJohn Marino     {
630*e4b17023SJohn Marino       tree var = partition_to_var (g->map, T);
631*e4b17023SJohn Marino       rtx U = get_temp_reg (var);
632*e4b17023SJohn Marino       int unsignedsrcp = TYPE_UNSIGNED (TREE_TYPE (var));
633*e4b17023SJohn Marino 
634*e4b17023SJohn Marino       insert_part_to_rtx_on_edge (g->e, U, T, UNKNOWN_LOCATION);
635*e4b17023SJohn Marino       FOR_EACH_ELIM_GRAPH_PRED (g, T, P, locus,
636*e4b17023SJohn Marino 	{
637*e4b17023SJohn Marino 	  if (!TEST_BIT (g->visited, P))
638*e4b17023SJohn Marino 	    {
639*e4b17023SJohn Marino 	      elim_backward (g, P);
640*e4b17023SJohn Marino 	      insert_rtx_to_part_on_edge (g->e, P, U, unsignedsrcp, locus);
641*e4b17023SJohn Marino 	    }
642*e4b17023SJohn Marino 	});
643*e4b17023SJohn Marino     }
644*e4b17023SJohn Marino   else
645*e4b17023SJohn Marino     {
646*e4b17023SJohn Marino       S = elim_graph_remove_succ_edge (g, T, &locus);
647*e4b17023SJohn Marino       if (S != -1)
648*e4b17023SJohn Marino 	{
649*e4b17023SJohn Marino 	  SET_BIT (g->visited, T);
650*e4b17023SJohn Marino 	  insert_partition_copy_on_edge (g->e, T, S, locus);
651*e4b17023SJohn Marino 	}
652*e4b17023SJohn Marino     }
653*e4b17023SJohn Marino }
654*e4b17023SJohn Marino 
655*e4b17023SJohn Marino 
656*e4b17023SJohn Marino /* Eliminate all the phi nodes on edge E in graph G.  */
657*e4b17023SJohn Marino 
658*e4b17023SJohn Marino static void
eliminate_phi(edge e,elim_graph g)659*e4b17023SJohn Marino eliminate_phi (edge e, elim_graph g)
660*e4b17023SJohn Marino {
661*e4b17023SJohn Marino   int x;
662*e4b17023SJohn Marino 
663*e4b17023SJohn Marino   gcc_assert (VEC_length (tree, g->const_copies) == 0);
664*e4b17023SJohn Marino   gcc_assert (VEC_length (source_location, g->copy_locus) == 0);
665*e4b17023SJohn Marino 
666*e4b17023SJohn Marino   /* Abnormal edges already have everything coalesced.  */
667*e4b17023SJohn Marino   if (e->flags & EDGE_ABNORMAL)
668*e4b17023SJohn Marino     return;
669*e4b17023SJohn Marino 
670*e4b17023SJohn Marino   g->e = e;
671*e4b17023SJohn Marino 
672*e4b17023SJohn Marino   eliminate_build (g);
673*e4b17023SJohn Marino 
674*e4b17023SJohn Marino   if (elim_graph_size (g) != 0)
675*e4b17023SJohn Marino     {
676*e4b17023SJohn Marino       int part;
677*e4b17023SJohn Marino 
678*e4b17023SJohn Marino       sbitmap_zero (g->visited);
679*e4b17023SJohn Marino       VEC_truncate (int, g->stack, 0);
680*e4b17023SJohn Marino 
681*e4b17023SJohn Marino       FOR_EACH_VEC_ELT (int, g->nodes, x, part)
682*e4b17023SJohn Marino         {
683*e4b17023SJohn Marino 	  if (!TEST_BIT (g->visited, part))
684*e4b17023SJohn Marino 	    elim_forward (g, part);
685*e4b17023SJohn Marino 	}
686*e4b17023SJohn Marino 
687*e4b17023SJohn Marino       sbitmap_zero (g->visited);
688*e4b17023SJohn Marino       while (VEC_length (int, g->stack) > 0)
689*e4b17023SJohn Marino 	{
690*e4b17023SJohn Marino 	  x = VEC_pop (int, g->stack);
691*e4b17023SJohn Marino 	  if (!TEST_BIT (g->visited, x))
692*e4b17023SJohn Marino 	    elim_create (g, x);
693*e4b17023SJohn Marino 	}
694*e4b17023SJohn Marino     }
695*e4b17023SJohn Marino 
696*e4b17023SJohn Marino   /* If there are any pending constant copies, issue them now.  */
697*e4b17023SJohn Marino   while (VEC_length (tree, g->const_copies) > 0)
698*e4b17023SJohn Marino     {
699*e4b17023SJohn Marino       int dest;
700*e4b17023SJohn Marino       tree src;
701*e4b17023SJohn Marino       source_location locus;
702*e4b17023SJohn Marino 
703*e4b17023SJohn Marino       src = VEC_pop (tree, g->const_copies);
704*e4b17023SJohn Marino       dest = VEC_pop (int, g->const_dests);
705*e4b17023SJohn Marino       locus = VEC_pop (source_location, g->copy_locus);
706*e4b17023SJohn Marino       insert_value_copy_on_edge (e, dest, src, locus);
707*e4b17023SJohn Marino     }
708*e4b17023SJohn Marino }
709*e4b17023SJohn Marino 
710*e4b17023SJohn Marino 
711*e4b17023SJohn Marino /* Remove each argument from PHI.  If an arg was the last use of an SSA_NAME,
712*e4b17023SJohn Marino    check to see if this allows another PHI node to be removed.  */
713*e4b17023SJohn Marino 
714*e4b17023SJohn Marino static void
remove_gimple_phi_args(gimple phi)715*e4b17023SJohn Marino remove_gimple_phi_args (gimple phi)
716*e4b17023SJohn Marino {
717*e4b17023SJohn Marino   use_operand_p arg_p;
718*e4b17023SJohn Marino   ssa_op_iter iter;
719*e4b17023SJohn Marino 
720*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
721*e4b17023SJohn Marino     {
722*e4b17023SJohn Marino       fprintf (dump_file, "Removing Dead PHI definition: ");
723*e4b17023SJohn Marino       print_gimple_stmt (dump_file, phi, 0, TDF_SLIM);
724*e4b17023SJohn Marino     }
725*e4b17023SJohn Marino 
726*e4b17023SJohn Marino   FOR_EACH_PHI_ARG (arg_p, phi, iter, SSA_OP_USE)
727*e4b17023SJohn Marino     {
728*e4b17023SJohn Marino       tree arg = USE_FROM_PTR (arg_p);
729*e4b17023SJohn Marino       if (TREE_CODE (arg) == SSA_NAME)
730*e4b17023SJohn Marino         {
731*e4b17023SJohn Marino 	  /* Remove the reference to the existing argument.  */
732*e4b17023SJohn Marino 	  SET_USE (arg_p, NULL_TREE);
733*e4b17023SJohn Marino 	  if (has_zero_uses (arg))
734*e4b17023SJohn Marino 	    {
735*e4b17023SJohn Marino 	      gimple stmt;
736*e4b17023SJohn Marino 	      gimple_stmt_iterator gsi;
737*e4b17023SJohn Marino 
738*e4b17023SJohn Marino 	      stmt = SSA_NAME_DEF_STMT (arg);
739*e4b17023SJohn Marino 
740*e4b17023SJohn Marino 	      /* Also remove the def if it is a PHI node.  */
741*e4b17023SJohn Marino 	      if (gimple_code (stmt) == GIMPLE_PHI)
742*e4b17023SJohn Marino 		{
743*e4b17023SJohn Marino 		  remove_gimple_phi_args (stmt);
744*e4b17023SJohn Marino 		  gsi = gsi_for_stmt (stmt);
745*e4b17023SJohn Marino 		  remove_phi_node (&gsi, true);
746*e4b17023SJohn Marino 		}
747*e4b17023SJohn Marino 
748*e4b17023SJohn Marino 	    }
749*e4b17023SJohn Marino 	}
750*e4b17023SJohn Marino     }
751*e4b17023SJohn Marino }
752*e4b17023SJohn Marino 
753*e4b17023SJohn Marino /* Remove any PHI node which is a virtual PHI, or a PHI with no uses.  */
754*e4b17023SJohn Marino 
755*e4b17023SJohn Marino static void
eliminate_useless_phis(void)756*e4b17023SJohn Marino eliminate_useless_phis (void)
757*e4b17023SJohn Marino {
758*e4b17023SJohn Marino   basic_block bb;
759*e4b17023SJohn Marino   gimple_stmt_iterator gsi;
760*e4b17023SJohn Marino   tree result;
761*e4b17023SJohn Marino 
762*e4b17023SJohn Marino   FOR_EACH_BB (bb)
763*e4b17023SJohn Marino     {
764*e4b17023SJohn Marino       for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); )
765*e4b17023SJohn Marino         {
766*e4b17023SJohn Marino 	  gimple phi = gsi_stmt (gsi);
767*e4b17023SJohn Marino 	  result = gimple_phi_result (phi);
768*e4b17023SJohn Marino 	  if (!is_gimple_reg (SSA_NAME_VAR (result)))
769*e4b17023SJohn Marino 	    {
770*e4b17023SJohn Marino #ifdef ENABLE_CHECKING
771*e4b17023SJohn Marino 	      size_t i;
772*e4b17023SJohn Marino 	      /* There should be no arguments which are not virtual, or the
773*e4b17023SJohn Marino 	         results will be incorrect.  */
774*e4b17023SJohn Marino 	      for (i = 0; i < gimple_phi_num_args (phi); i++)
775*e4b17023SJohn Marino 	        {
776*e4b17023SJohn Marino 		  tree arg = PHI_ARG_DEF (phi, i);
777*e4b17023SJohn Marino 		  if (TREE_CODE (arg) == SSA_NAME
778*e4b17023SJohn Marino 		      && is_gimple_reg (SSA_NAME_VAR (arg)))
779*e4b17023SJohn Marino 		    {
780*e4b17023SJohn Marino 		      fprintf (stderr, "Argument of PHI is not virtual (");
781*e4b17023SJohn Marino 		      print_generic_expr (stderr, arg, TDF_SLIM);
782*e4b17023SJohn Marino 		      fprintf (stderr, "), but the result is :");
783*e4b17023SJohn Marino 		      print_gimple_stmt (stderr, phi, 0, TDF_SLIM);
784*e4b17023SJohn Marino 		      internal_error ("SSA corruption");
785*e4b17023SJohn Marino 		    }
786*e4b17023SJohn Marino 		}
787*e4b17023SJohn Marino #endif
788*e4b17023SJohn Marino 	      remove_phi_node (&gsi, true);
789*e4b17023SJohn Marino 	    }
790*e4b17023SJohn Marino           else
791*e4b17023SJohn Marino 	    {
792*e4b17023SJohn Marino 	      /* Also remove real PHIs with no uses.  */
793*e4b17023SJohn Marino 	      if (has_zero_uses (result))
794*e4b17023SJohn Marino 	        {
795*e4b17023SJohn Marino 		  remove_gimple_phi_args (phi);
796*e4b17023SJohn Marino 		  remove_phi_node (&gsi, true);
797*e4b17023SJohn Marino 		}
798*e4b17023SJohn Marino 	      else
799*e4b17023SJohn Marino 		gsi_next (&gsi);
800*e4b17023SJohn Marino 	    }
801*e4b17023SJohn Marino 	}
802*e4b17023SJohn Marino     }
803*e4b17023SJohn Marino }
804*e4b17023SJohn Marino 
805*e4b17023SJohn Marino 
806*e4b17023SJohn Marino /* This function will rewrite the current program using the variable mapping
807*e4b17023SJohn Marino    found in MAP.  If the replacement vector VALUES is provided, any
808*e4b17023SJohn Marino    occurrences of partitions with non-null entries in the vector will be
809*e4b17023SJohn Marino    replaced with the expression in the vector instead of its mapped
810*e4b17023SJohn Marino    variable.  */
811*e4b17023SJohn Marino 
812*e4b17023SJohn Marino static void
rewrite_trees(var_map map ATTRIBUTE_UNUSED)813*e4b17023SJohn Marino rewrite_trees (var_map map ATTRIBUTE_UNUSED)
814*e4b17023SJohn Marino {
815*e4b17023SJohn Marino #ifdef ENABLE_CHECKING
816*e4b17023SJohn Marino   basic_block bb;
817*e4b17023SJohn Marino   /* Search for PHIs where the destination has no partition, but one
818*e4b17023SJohn Marino      or more arguments has a partition.  This should not happen and can
819*e4b17023SJohn Marino      create incorrect code.  */
820*e4b17023SJohn Marino   FOR_EACH_BB (bb)
821*e4b17023SJohn Marino     {
822*e4b17023SJohn Marino       gimple_stmt_iterator gsi;
823*e4b17023SJohn Marino       for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
824*e4b17023SJohn Marino 	{
825*e4b17023SJohn Marino 	  gimple phi = gsi_stmt (gsi);
826*e4b17023SJohn Marino 	  tree T0 = var_to_partition_to_var (map, gimple_phi_result (phi));
827*e4b17023SJohn Marino 	  if (T0 == NULL_TREE)
828*e4b17023SJohn Marino 	    {
829*e4b17023SJohn Marino 	      size_t i;
830*e4b17023SJohn Marino 	      for (i = 0; i < gimple_phi_num_args (phi); i++)
831*e4b17023SJohn Marino 		{
832*e4b17023SJohn Marino 		  tree arg = PHI_ARG_DEF (phi, i);
833*e4b17023SJohn Marino 
834*e4b17023SJohn Marino 		  if (TREE_CODE (arg) == SSA_NAME
835*e4b17023SJohn Marino 		      && var_to_partition (map, arg) != NO_PARTITION)
836*e4b17023SJohn Marino 		    {
837*e4b17023SJohn Marino 		      fprintf (stderr, "Argument of PHI is in a partition :(");
838*e4b17023SJohn Marino 		      print_generic_expr (stderr, arg, TDF_SLIM);
839*e4b17023SJohn Marino 		      fprintf (stderr, "), but the result is not :");
840*e4b17023SJohn Marino 		      print_gimple_stmt (stderr, phi, 0, TDF_SLIM);
841*e4b17023SJohn Marino 		      internal_error ("SSA corruption");
842*e4b17023SJohn Marino 		    }
843*e4b17023SJohn Marino 		}
844*e4b17023SJohn Marino 	    }
845*e4b17023SJohn Marino 	}
846*e4b17023SJohn Marino     }
847*e4b17023SJohn Marino #endif
848*e4b17023SJohn Marino }
849*e4b17023SJohn Marino 
850*e4b17023SJohn Marino /* Given the out-of-ssa info object SA (with prepared partitions)
851*e4b17023SJohn Marino    eliminate all phi nodes in all basic blocks.  Afterwards no
852*e4b17023SJohn Marino    basic block will have phi nodes anymore and there are possibly
853*e4b17023SJohn Marino    some RTL instructions inserted on edges.  */
854*e4b17023SJohn Marino 
855*e4b17023SJohn Marino void
expand_phi_nodes(struct ssaexpand * sa)856*e4b17023SJohn Marino expand_phi_nodes (struct ssaexpand *sa)
857*e4b17023SJohn Marino {
858*e4b17023SJohn Marino   basic_block bb;
859*e4b17023SJohn Marino   elim_graph g = new_elim_graph (sa->map->num_partitions);
860*e4b17023SJohn Marino   g->map = sa->map;
861*e4b17023SJohn Marino 
862*e4b17023SJohn Marino   FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR->next_bb, EXIT_BLOCK_PTR, next_bb)
863*e4b17023SJohn Marino     if (!gimple_seq_empty_p (phi_nodes (bb)))
864*e4b17023SJohn Marino       {
865*e4b17023SJohn Marino 	edge e;
866*e4b17023SJohn Marino 	edge_iterator ei;
867*e4b17023SJohn Marino 	FOR_EACH_EDGE (e, ei, bb->preds)
868*e4b17023SJohn Marino 	  eliminate_phi (e, g);
869*e4b17023SJohn Marino 	set_phi_nodes (bb, NULL);
870*e4b17023SJohn Marino 	/* We can't redirect EH edges in RTL land, so we need to do this
871*e4b17023SJohn Marino 	   here.  Redirection happens only when splitting is necessary,
872*e4b17023SJohn Marino 	   which it is only for critical edges, normally.  For EH edges
873*e4b17023SJohn Marino 	   it might also be necessary when the successor has more than
874*e4b17023SJohn Marino 	   one predecessor.  In that case the edge is either required to
875*e4b17023SJohn Marino 	   be fallthru (which EH edges aren't), or the predecessor needs
876*e4b17023SJohn Marino 	   to end with a jump (which again, isn't the case with EH edges).
877*e4b17023SJohn Marino 	   Hence, split all EH edges on which we inserted instructions
878*e4b17023SJohn Marino 	   and whose successor has multiple predecessors.  */
879*e4b17023SJohn Marino 	for (ei = ei_start (bb->preds); (e = ei_safe_edge (ei)); )
880*e4b17023SJohn Marino 	  {
881*e4b17023SJohn Marino 	    if (e->insns.r && (e->flags & EDGE_EH)
882*e4b17023SJohn Marino 		&& !single_pred_p (e->dest))
883*e4b17023SJohn Marino 	      {
884*e4b17023SJohn Marino 		rtx insns = e->insns.r;
885*e4b17023SJohn Marino 		basic_block bb;
886*e4b17023SJohn Marino 		e->insns.r = NULL_RTX;
887*e4b17023SJohn Marino 		bb = split_edge (e);
888*e4b17023SJohn Marino 		single_pred_edge (bb)->insns.r = insns;
889*e4b17023SJohn Marino 	      }
890*e4b17023SJohn Marino 	    else
891*e4b17023SJohn Marino 	      ei_next (&ei);
892*e4b17023SJohn Marino 	  }
893*e4b17023SJohn Marino       }
894*e4b17023SJohn Marino 
895*e4b17023SJohn Marino   delete_elim_graph (g);
896*e4b17023SJohn Marino }
897*e4b17023SJohn Marino 
898*e4b17023SJohn Marino 
899*e4b17023SJohn Marino /* Remove the ssa-names in the current function and translate them into normal
900*e4b17023SJohn Marino    compiler variables.  PERFORM_TER is true if Temporary Expression Replacement
901*e4b17023SJohn Marino    should also be used.  */
902*e4b17023SJohn Marino 
903*e4b17023SJohn Marino static void
remove_ssa_form(bool perform_ter,struct ssaexpand * sa)904*e4b17023SJohn Marino remove_ssa_form (bool perform_ter, struct ssaexpand *sa)
905*e4b17023SJohn Marino {
906*e4b17023SJohn Marino   bitmap values = NULL;
907*e4b17023SJohn Marino   var_map map;
908*e4b17023SJohn Marino   unsigned i;
909*e4b17023SJohn Marino 
910*e4b17023SJohn Marino   map = coalesce_ssa_name ();
911*e4b17023SJohn Marino 
912*e4b17023SJohn Marino   /* Return to viewing the variable list as just all reference variables after
913*e4b17023SJohn Marino      coalescing has been performed.  */
914*e4b17023SJohn Marino   partition_view_normal (map, false);
915*e4b17023SJohn Marino 
916*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
917*e4b17023SJohn Marino     {
918*e4b17023SJohn Marino       fprintf (dump_file, "After Coalescing:\n");
919*e4b17023SJohn Marino       dump_var_map (dump_file, map);
920*e4b17023SJohn Marino     }
921*e4b17023SJohn Marino 
922*e4b17023SJohn Marino   if (perform_ter)
923*e4b17023SJohn Marino     {
924*e4b17023SJohn Marino       values = find_replaceable_exprs (map);
925*e4b17023SJohn Marino       if (values && dump_file && (dump_flags & TDF_DETAILS))
926*e4b17023SJohn Marino 	dump_replaceable_exprs (dump_file, values);
927*e4b17023SJohn Marino     }
928*e4b17023SJohn Marino 
929*e4b17023SJohn Marino   rewrite_trees (map);
930*e4b17023SJohn Marino 
931*e4b17023SJohn Marino   sa->map = map;
932*e4b17023SJohn Marino   sa->values = values;
933*e4b17023SJohn Marino   sa->partition_has_default_def = BITMAP_ALLOC (NULL);
934*e4b17023SJohn Marino   for (i = 1; i < num_ssa_names; i++)
935*e4b17023SJohn Marino     {
936*e4b17023SJohn Marino       tree t = ssa_name (i);
937*e4b17023SJohn Marino       if (t && SSA_NAME_IS_DEFAULT_DEF (t))
938*e4b17023SJohn Marino 	{
939*e4b17023SJohn Marino 	  int p = var_to_partition (map, t);
940*e4b17023SJohn Marino 	  if (p != NO_PARTITION)
941*e4b17023SJohn Marino 	    bitmap_set_bit (sa->partition_has_default_def, p);
942*e4b17023SJohn Marino 	}
943*e4b17023SJohn Marino     }
944*e4b17023SJohn Marino }
945*e4b17023SJohn Marino 
946*e4b17023SJohn Marino 
947*e4b17023SJohn Marino /* If not already done so for basic block BB, assign increasing uids
948*e4b17023SJohn Marino    to each of its instructions.  */
949*e4b17023SJohn Marino 
950*e4b17023SJohn Marino static void
maybe_renumber_stmts_bb(basic_block bb)951*e4b17023SJohn Marino maybe_renumber_stmts_bb (basic_block bb)
952*e4b17023SJohn Marino {
953*e4b17023SJohn Marino   unsigned i = 0;
954*e4b17023SJohn Marino   gimple_stmt_iterator gsi;
955*e4b17023SJohn Marino 
956*e4b17023SJohn Marino   if (!bb->aux)
957*e4b17023SJohn Marino     return;
958*e4b17023SJohn Marino   bb->aux = NULL;
959*e4b17023SJohn Marino   for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
960*e4b17023SJohn Marino     {
961*e4b17023SJohn Marino       gimple stmt = gsi_stmt (gsi);
962*e4b17023SJohn Marino       gimple_set_uid (stmt, i);
963*e4b17023SJohn Marino       i++;
964*e4b17023SJohn Marino     }
965*e4b17023SJohn Marino }
966*e4b17023SJohn Marino 
967*e4b17023SJohn Marino 
968*e4b17023SJohn Marino /* Return true if we can determine that the SSA_NAMEs RESULT (a result
969*e4b17023SJohn Marino    of a PHI node) and ARG (one of its arguments) conflict.  Return false
970*e4b17023SJohn Marino    otherwise, also when we simply aren't sure.  */
971*e4b17023SJohn Marino 
972*e4b17023SJohn Marino static bool
trivially_conflicts_p(basic_block bb,tree result,tree arg)973*e4b17023SJohn Marino trivially_conflicts_p (basic_block bb, tree result, tree arg)
974*e4b17023SJohn Marino {
975*e4b17023SJohn Marino   use_operand_p use;
976*e4b17023SJohn Marino   imm_use_iterator imm_iter;
977*e4b17023SJohn Marino   gimple defa = SSA_NAME_DEF_STMT (arg);
978*e4b17023SJohn Marino 
979*e4b17023SJohn Marino   /* If ARG isn't defined in the same block it's too complicated for
980*e4b17023SJohn Marino      our little mind.  */
981*e4b17023SJohn Marino   if (gimple_bb (defa) != bb)
982*e4b17023SJohn Marino     return false;
983*e4b17023SJohn Marino 
984*e4b17023SJohn Marino   FOR_EACH_IMM_USE_FAST (use, imm_iter, result)
985*e4b17023SJohn Marino     {
986*e4b17023SJohn Marino       gimple use_stmt = USE_STMT (use);
987*e4b17023SJohn Marino       if (is_gimple_debug (use_stmt))
988*e4b17023SJohn Marino 	continue;
989*e4b17023SJohn Marino       /* Now, if there's a use of RESULT that lies outside this basic block,
990*e4b17023SJohn Marino 	 then there surely is a conflict with ARG.  */
991*e4b17023SJohn Marino       if (gimple_bb (use_stmt) != bb)
992*e4b17023SJohn Marino 	return true;
993*e4b17023SJohn Marino       if (gimple_code (use_stmt) == GIMPLE_PHI)
994*e4b17023SJohn Marino 	continue;
995*e4b17023SJohn Marino       /* The use now is in a real stmt of BB, so if ARG was defined
996*e4b17023SJohn Marino          in a PHI node (like RESULT) both conflict.  */
997*e4b17023SJohn Marino       if (gimple_code (defa) == GIMPLE_PHI)
998*e4b17023SJohn Marino 	return true;
999*e4b17023SJohn Marino       maybe_renumber_stmts_bb (bb);
1000*e4b17023SJohn Marino       /* If the use of RESULT occurs after the definition of ARG,
1001*e4b17023SJohn Marino          the two conflict too.  */
1002*e4b17023SJohn Marino       if (gimple_uid (defa) < gimple_uid (use_stmt))
1003*e4b17023SJohn Marino 	return true;
1004*e4b17023SJohn Marino     }
1005*e4b17023SJohn Marino 
1006*e4b17023SJohn Marino   return false;
1007*e4b17023SJohn Marino }
1008*e4b17023SJohn Marino 
1009*e4b17023SJohn Marino 
1010*e4b17023SJohn Marino /* Search every PHI node for arguments associated with backedges which
1011*e4b17023SJohn Marino    we can trivially determine will need a copy (the argument is either
1012*e4b17023SJohn Marino    not an SSA_NAME or the argument has a different underlying variable
1013*e4b17023SJohn Marino    than the PHI result).
1014*e4b17023SJohn Marino 
1015*e4b17023SJohn Marino    Insert a copy from the PHI argument to a new destination at the
1016*e4b17023SJohn Marino    end of the block with the backedge to the top of the loop.  Update
1017*e4b17023SJohn Marino    the PHI argument to reference this new destination.  */
1018*e4b17023SJohn Marino 
1019*e4b17023SJohn Marino static void
insert_backedge_copies(void)1020*e4b17023SJohn Marino insert_backedge_copies (void)
1021*e4b17023SJohn Marino {
1022*e4b17023SJohn Marino   basic_block bb;
1023*e4b17023SJohn Marino   gimple_stmt_iterator gsi;
1024*e4b17023SJohn Marino 
1025*e4b17023SJohn Marino   mark_dfs_back_edges ();
1026*e4b17023SJohn Marino 
1027*e4b17023SJohn Marino   FOR_EACH_BB (bb)
1028*e4b17023SJohn Marino     {
1029*e4b17023SJohn Marino       /* Mark block as possibly needing calculation of UIDs.  */
1030*e4b17023SJohn Marino       bb->aux = &bb->aux;
1031*e4b17023SJohn Marino 
1032*e4b17023SJohn Marino       for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
1033*e4b17023SJohn Marino 	{
1034*e4b17023SJohn Marino 	  gimple phi = gsi_stmt (gsi);
1035*e4b17023SJohn Marino 	  tree result = gimple_phi_result (phi);
1036*e4b17023SJohn Marino 	  tree result_var;
1037*e4b17023SJohn Marino 	  size_t i;
1038*e4b17023SJohn Marino 
1039*e4b17023SJohn Marino 	  if (!is_gimple_reg (result))
1040*e4b17023SJohn Marino 	    continue;
1041*e4b17023SJohn Marino 
1042*e4b17023SJohn Marino 	  result_var = SSA_NAME_VAR (result);
1043*e4b17023SJohn Marino 	  for (i = 0; i < gimple_phi_num_args (phi); i++)
1044*e4b17023SJohn Marino 	    {
1045*e4b17023SJohn Marino 	      tree arg = gimple_phi_arg_def (phi, i);
1046*e4b17023SJohn Marino 	      edge e = gimple_phi_arg_edge (phi, i);
1047*e4b17023SJohn Marino 
1048*e4b17023SJohn Marino 	      /* If the argument is not an SSA_NAME, then we will need a
1049*e4b17023SJohn Marino 		 constant initialization.  If the argument is an SSA_NAME with
1050*e4b17023SJohn Marino 		 a different underlying variable then a copy statement will be
1051*e4b17023SJohn Marino 		 needed.  */
1052*e4b17023SJohn Marino 	      if ((e->flags & EDGE_DFS_BACK)
1053*e4b17023SJohn Marino 		  && (TREE_CODE (arg) != SSA_NAME
1054*e4b17023SJohn Marino 		      || SSA_NAME_VAR (arg) != result_var
1055*e4b17023SJohn Marino 		      || trivially_conflicts_p (bb, result, arg)))
1056*e4b17023SJohn Marino 		{
1057*e4b17023SJohn Marino 		  tree name;
1058*e4b17023SJohn Marino 		  gimple stmt, last = NULL;
1059*e4b17023SJohn Marino 		  gimple_stmt_iterator gsi2;
1060*e4b17023SJohn Marino 
1061*e4b17023SJohn Marino 		  gsi2 = gsi_last_bb (gimple_phi_arg_edge (phi, i)->src);
1062*e4b17023SJohn Marino 		  if (!gsi_end_p (gsi2))
1063*e4b17023SJohn Marino 		    last = gsi_stmt (gsi2);
1064*e4b17023SJohn Marino 
1065*e4b17023SJohn Marino 		  /* In theory the only way we ought to get back to the
1066*e4b17023SJohn Marino 		     start of a loop should be with a COND_EXPR or GOTO_EXPR.
1067*e4b17023SJohn Marino 		     However, better safe than sorry.
1068*e4b17023SJohn Marino 		     If the block ends with a control statement or
1069*e4b17023SJohn Marino 		     something that might throw, then we have to
1070*e4b17023SJohn Marino 		     insert this assignment before the last
1071*e4b17023SJohn Marino 		     statement.  Else insert it after the last statement.  */
1072*e4b17023SJohn Marino 		  if (last && stmt_ends_bb_p (last))
1073*e4b17023SJohn Marino 		    {
1074*e4b17023SJohn Marino 		      /* If the last statement in the block is the definition
1075*e4b17023SJohn Marino 			 site of the PHI argument, then we can't insert
1076*e4b17023SJohn Marino 			 anything after it.  */
1077*e4b17023SJohn Marino 		      if (TREE_CODE (arg) == SSA_NAME
1078*e4b17023SJohn Marino 			  && SSA_NAME_DEF_STMT (arg) == last)
1079*e4b17023SJohn Marino 			continue;
1080*e4b17023SJohn Marino 		    }
1081*e4b17023SJohn Marino 
1082*e4b17023SJohn Marino 		  /* Create a new instance of the underlying variable of the
1083*e4b17023SJohn Marino 		     PHI result.  */
1084*e4b17023SJohn Marino 		  stmt = gimple_build_assign (result_var,
1085*e4b17023SJohn Marino 					      gimple_phi_arg_def (phi, i));
1086*e4b17023SJohn Marino 		  name = make_ssa_name (result_var, stmt);
1087*e4b17023SJohn Marino 		  gimple_assign_set_lhs (stmt, name);
1088*e4b17023SJohn Marino 
1089*e4b17023SJohn Marino 		  /* copy location if present.  */
1090*e4b17023SJohn Marino 		  if (gimple_phi_arg_has_location (phi, i))
1091*e4b17023SJohn Marino 		    gimple_set_location (stmt,
1092*e4b17023SJohn Marino 					 gimple_phi_arg_location (phi, i));
1093*e4b17023SJohn Marino 
1094*e4b17023SJohn Marino 		  /* Insert the new statement into the block and update
1095*e4b17023SJohn Marino 		     the PHI node.  */
1096*e4b17023SJohn Marino 		  if (last && stmt_ends_bb_p (last))
1097*e4b17023SJohn Marino 		    gsi_insert_before (&gsi2, stmt, GSI_NEW_STMT);
1098*e4b17023SJohn Marino 		  else
1099*e4b17023SJohn Marino 		    gsi_insert_after (&gsi2, stmt, GSI_NEW_STMT);
1100*e4b17023SJohn Marino 		  SET_PHI_ARG_DEF (phi, i, name);
1101*e4b17023SJohn Marino 		}
1102*e4b17023SJohn Marino 	    }
1103*e4b17023SJohn Marino 	}
1104*e4b17023SJohn Marino 
1105*e4b17023SJohn Marino       /* Unmark this block again.  */
1106*e4b17023SJohn Marino       bb->aux = NULL;
1107*e4b17023SJohn Marino     }
1108*e4b17023SJohn Marino }
1109*e4b17023SJohn Marino 
1110*e4b17023SJohn Marino /* Free all memory associated with going out of SSA form.  SA is
1111*e4b17023SJohn Marino    the outof-SSA info object.  */
1112*e4b17023SJohn Marino 
1113*e4b17023SJohn Marino void
finish_out_of_ssa(struct ssaexpand * sa)1114*e4b17023SJohn Marino finish_out_of_ssa (struct ssaexpand *sa)
1115*e4b17023SJohn Marino {
1116*e4b17023SJohn Marino   free (sa->partition_to_pseudo);
1117*e4b17023SJohn Marino   if (sa->values)
1118*e4b17023SJohn Marino     BITMAP_FREE (sa->values);
1119*e4b17023SJohn Marino   delete_var_map (sa->map);
1120*e4b17023SJohn Marino   BITMAP_FREE (sa->partition_has_default_def);
1121*e4b17023SJohn Marino   memset (sa, 0, sizeof *sa);
1122*e4b17023SJohn Marino }
1123*e4b17023SJohn Marino 
1124*e4b17023SJohn Marino /* Take the current function out of SSA form, translating PHIs as described in
1125*e4b17023SJohn Marino    R. Morgan, ``Building an Optimizing Compiler'',
1126*e4b17023SJohn Marino    Butterworth-Heinemann, Boston, MA, 1998. pp 176-186.  */
1127*e4b17023SJohn Marino 
1128*e4b17023SJohn Marino unsigned int
rewrite_out_of_ssa(struct ssaexpand * sa)1129*e4b17023SJohn Marino rewrite_out_of_ssa (struct ssaexpand *sa)
1130*e4b17023SJohn Marino {
1131*e4b17023SJohn Marino   /* If elimination of a PHI requires inserting a copy on a backedge,
1132*e4b17023SJohn Marino      then we will have to split the backedge which has numerous
1133*e4b17023SJohn Marino      undesirable performance effects.
1134*e4b17023SJohn Marino 
1135*e4b17023SJohn Marino      A significant number of such cases can be handled here by inserting
1136*e4b17023SJohn Marino      copies into the loop itself.  */
1137*e4b17023SJohn Marino   insert_backedge_copies ();
1138*e4b17023SJohn Marino 
1139*e4b17023SJohn Marino 
1140*e4b17023SJohn Marino   /* Eliminate PHIs which are of no use, such as virtual or dead phis.  */
1141*e4b17023SJohn Marino   eliminate_useless_phis ();
1142*e4b17023SJohn Marino 
1143*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
1144*e4b17023SJohn Marino     gimple_dump_cfg (dump_file, dump_flags & ~TDF_DETAILS);
1145*e4b17023SJohn Marino 
1146*e4b17023SJohn Marino   remove_ssa_form (flag_tree_ter, sa);
1147*e4b17023SJohn Marino 
1148*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
1149*e4b17023SJohn Marino     gimple_dump_cfg (dump_file, dump_flags & ~TDF_DETAILS);
1150*e4b17023SJohn Marino 
1151*e4b17023SJohn Marino   return 0;
1152*e4b17023SJohn Marino }
1153