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