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