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