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