summaryrefslogtreecommitdiff
path: root/gcc/tree-outof-ssa.c
diff options
context:
space:
mode:
authoramacleod <amacleod@138bc75d-0d04-0410-961f-82ee72b054a4>2006-12-10 21:25:40 +0000
committeramacleod <amacleod@138bc75d-0d04-0410-961f-82ee72b054a4>2006-12-10 21:25:40 +0000
commit2d043327e6bf9c316751af014a81548f08284a7b (patch)
tree02feab0e9ac8689b190a759c435c1c7653207328 /gcc/tree-outof-ssa.c
parent322026327df36027e148aabd5df318c8376ea1ab (diff)
downloadgcc-2d043327e6bf9c316751af014a81548f08284a7b.tar.gz
New out of ssa Coalescer.
2006-12-10 Andrew MacLeod <amacleod@redhat.com> * common.opt (-ftree-lrs): Remove live range splitting option. * makefile.in: Add tree-ssa-coalesce.o and reduce header dependancies. * opts.c (decode_options): Remove flag_tree_live_range_split. * tree-flow.h (struct var_ann_d): Rename fields from root_ to base_. * tree-flow-inline.h (single_imm_use_p): New. Check for single use. * tree-outof-ssa.c: Remove header files which aren't needed. (SSANORM_*): Remove flags. (print_exprs_edge, coalesce_abnormal_edges, coalesce_phi_operands, coalesce_result_decls_and_copies, coalesce_asm_operands): Remove. (coalesce_ssa_name): Move to tree-ssa-coalesce.c. (assign_vars): Use Basevar instead of root_var structure. (replace_def_variable): Dont do anything if def is replaceable. (remove_ssa_form): Integrate functional changes. (rewrite_out_of_ssa): Remove live-range_split option. * tree-ssa-coalesce.c: New File for ssa-name coalescing. (coalesce_cost): Calculate the cost of a coalesce. (coalesce_cost_bb): Calculate the coalesce cost within a BB. (coalesce_cost_edge): Calculate the coalesce cost on an edge. (pop_cost_one_pair): Remove the best coalesce with cost 1 from the list. (pop_best_coalesce): Remove the best coalesce from the list. (coalesce_pair_map_hash): Calculate coalesce pair hash. (coalesce_pair_map_eq): Compare 2 coalesce pairs for hash function. (create_coalesce_list): Create a coalesce list object. (delete_coalesce_list): Free a coalesce list object. (find_coalesce_pair): Find matching pair in the coalesce list. (add_cost_one_coalesce): Add a coalesce to the "cost one" list. (add_coalesce): Add a coalesce to the coalesce list. (compare_pairs): Comparision function to determine pair sorted order. (num_coalesce_pairs): Number of coalesced pairs. (first_coalesce_pair, end_coalesce_pair_p, next_coalesce_pair): Coalesce pair iterator functions. (sort_coalesce_list): Sort coalesce pairs in order of expense. (dump_coalesce_list): Show coalesce list. (ssa_conflicts_new): Create an SSA conflict graph. (ssa_conflicts_delete): Delete an SSA conflict graph. (ssa_conflicts_test_p): Test for conflicts. (ssa_conflicts_add_one): Add a single conflict. (ssa_conflicts_add): Add a conflict pair. (ssa_conflicts_merge): Merge conflicts. (struct live_track_d): Struct for tracking live partitions. (new_live_track): Create new live_track object. (delete_live_track): Delete a live_track object. (live_track_remove_partition): Remove a partition from the live list. (live_track_add_partition): Add a partition from the live list. (live_track_clear_var): Take VAR from the live list. (live_track_live_p): Is var live? (live_track_process_use): Make var come alive. (live_track_process_def): Make var go dead, add conflicts. (live_track_init): Initialize to a live on exit set. (live_track_clear_base_vars): Clear live partitions. (build_ssa_conflict_graph): Build a conflict graph. (print_exprs): Common debug output routine. (abnormal_corrupt): Output info about a failed coalesce across an abnormal edge. (fail_abnormal_edge_coalesce): Output info about a failed MUST_COALESCE. (create_outofssa_var_map): Create a var map and coalesce list. (attempt_coalesce): Coalesce a pair. (coalesce_partitions): Coalesce all pairs in a coalesce list. (coalesce_ssa_name): Entry point. Determine what ssa_names to coalesce. * tree-ssa-live.c: Remove header files which aren't needed. (var_map_base_init): New. Initialize a basevar list. (var_map_base_fini): New. Finish a basevar list. (init_var_map): Initialize new fields. (delete_var_map): Free new fields. (var_union): Use renamed fields. (compact_var_map): Remove. (partition_to_view_init): Use renamed fields, change order of an if. (partition_view_fini): Use renamed fields. (partition_view_normal): Create basevar list if requested. (partition_view_bitmap): Create a view based on a bitmap of partitions. (change_partition_var): Use renamed fields. (create_ssa_var_map): Remove. (tpa_init, tpa_remove_partition, tpa_delete, tpa_compact, root_var_init): Remove. (partition_pair_map_hash, partition_pair_map_eq, create_coalesce_list, delete_coalesce_list, find_partition_pair, coalesce_cost, add_coalesce, compare_pairs, num_coalesce_pairs, first_partition_pair, end_partition_pair_p, next_partition_pair, sort_coalesce_list, pop_best_coalesce, add_conflicts_if_valid, set_if_valid, build_tree_conflict_graph, coalesce_tpa_members, dump_coalesce_list, tpa_dump): Moved to tree-ssa-coalesce.c and/or renamed there. (dump_var_map): Use renamed fields. * tree-ssa-live.h (struct _var_map): Modify fields. (partition_to_var, version_to_var, var_to_partition): Use renamed fields. (basevar_index): New. Index of the base variable of a partition. (num_basevars): New. Number of unique base variables in partition map. (register_ssa_partition): Use renamed fields. (struct tree_partition_associator_d): Remove. (tpa_num_trees, tpa_tree, tpa_first_partition, tpa_next_partition, tpa_find_tree, tpa_decompact, root_var_init, root_var_num, root_var, root_var_first_partition, root_var_next_partition, root_var_dump, root_var_delete, root_var_remove_partition, root_var_find, root_var_compact, root_var_decompact): Remove. (struct partition_pair, struct coalesce_list_d): Moved to tree-ssa-coalesce.c * tree-ssa-ter.c: Remove header files which aren't needed. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@119711 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/tree-outof-ssa.c')
-rw-r--r--gcc/tree-outof-ssa.c601
1 files changed, 52 insertions, 549 deletions
diff --git a/gcc/tree-outof-ssa.c b/gcc/tree-outof-ssa.c
index 5edea642805..f591eb5ed97 100644
--- a/gcc/tree-outof-ssa.c
+++ b/gcc/tree-outof-ssa.c
@@ -1,5 +1,5 @@
/* Convert a program in SSA form into Normal form.
- Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
Contributed by Andrew Macleod <amacleod@redhat.com>
This file is part of GCC.
@@ -24,34 +24,17 @@ Boston, MA 02110-1301, USA. */
#include "coretypes.h"
#include "tm.h"
#include "tree.h"
-#include "flags.h"
-#include "rtl.h"
-#include "tm_p.h"
#include "ggc.h"
-#include "langhooks.h"
-#include "hard-reg-set.h"
#include "basic-block.h"
-#include "output.h"
-#include "expr.h"
-#include "function.h"
#include "diagnostic.h"
#include "bitmap.h"
#include "tree-flow.h"
-#include "tree-gimple.h"
-#include "tree-inline.h"
-#include "varray.h"
#include "timevar.h"
-#include "hashtab.h"
#include "tree-dump.h"
#include "tree-ssa-live.h"
#include "tree-pass.h"
#include "toplev.h"
-#include "vecprim.h"
-/* Flags to pass to remove_ssa_form. */
-
-#define SSANORM_PERFORM_TER 0x1
-#define SSANORM_COALESCE_PARTITIONS 0x4
/* Used to hold all the components required to do SSA PHI elimination.
The node and pred/succ list is a simple linear list of nodes and
@@ -101,36 +84,6 @@ typedef struct _elim_graph {
} *elim_graph;
-/* Local functions. */
-static tree create_temp (tree);
-static void insert_copy_on_edge (edge, tree, tree);
-static elim_graph new_elim_graph (int);
-static inline void delete_elim_graph (elim_graph);
-static inline void clear_elim_graph (elim_graph);
-static inline int elim_graph_size (elim_graph);
-static inline void elim_graph_add_node (elim_graph, tree);
-static inline void elim_graph_add_edge (elim_graph, int, int);
-static inline int elim_graph_remove_succ_edge (elim_graph, int);
-
-static inline void eliminate_name (elim_graph, tree);
-static void eliminate_build (elim_graph, basic_block);
-static void elim_forward (elim_graph, int);
-static int elim_unvisited_predecessor (elim_graph, int);
-static void elim_backward (elim_graph, int);
-static void elim_create (elim_graph, int);
-static void eliminate_phi (edge, elim_graph);
-static tree_live_info_p coalesce_ssa_name (var_map, int);
-static void assign_vars (var_map);
-static bool replace_use_variable (var_map, use_operand_p, tree *);
-static bool replace_def_variable (var_map, def_operand_p, tree *);
-static void eliminate_virtual_phis (void);
-static void coalesce_abnormal_edges (var_map, conflict_graph, root_var_p);
-static void print_exprs (FILE *, const char *, tree, const char *, tree,
- const char *);
-static void print_exprs_edge (FILE *, edge, const char *, tree, const char *,
- tree);
-
-
/* Create a temporary variable based on the type of variable T. Use T's name
as the prefix. */
@@ -489,6 +442,7 @@ elim_create (elim_graph g, int T)
}
+
/* Eliminate all the phi nodes on edge E in graph G. */
static void
@@ -541,407 +495,15 @@ eliminate_phi (edge e, elim_graph g)
}
-/* Shortcut routine to print messages to file F of the form:
- "STR1 EXPR1 STR2 EXPR2 STR3." */
-
-static void
-print_exprs (FILE *f, const char *str1, tree expr1, const char *str2,
- tree expr2, const char *str3)
-{
- fprintf (f, "%s", str1);
- print_generic_expr (f, expr1, TDF_SLIM);
- fprintf (f, "%s", str2);
- print_generic_expr (f, expr2, TDF_SLIM);
- fprintf (f, "%s", str3);
-}
-
-
-/* Shortcut routine to print abnormal edge messages to file F of the form:
- "STR1 EXPR1 STR2 EXPR2 across edge E. */
-
-static void
-print_exprs_edge (FILE *f, edge e, const char *str1, tree expr1,
- const char *str2, tree expr2)
-{
- print_exprs (f, str1, expr1, str2, expr2, " across an abnormal edge");
- fprintf (f, " from BB%d->BB%d\n", e->src->index,
- e->dest->index);
-}
-
-
-/* Coalesce partitions in MAP which are live across abnormal edges in GRAPH.
- RV is the root variable groupings of the partitions in MAP. Since code
- cannot be inserted on these edges, failure to coalesce something across
- an abnormal edge is an error. */
-
-static void
-coalesce_abnormal_edges (var_map map, conflict_graph graph, root_var_p rv)
-{
- basic_block bb;
- edge e;
- tree phi, var, tmp;
- int x, y, z;
- edge_iterator ei;
-
- /* Code cannot be inserted on abnormal edges. Look for all abnormal
- edges, and coalesce any PHI results with their arguments across
- that edge. */
-
- FOR_EACH_BB (bb)
- FOR_EACH_EDGE (e, ei, bb->succs)
- if (e->dest != EXIT_BLOCK_PTR && e->flags & EDGE_ABNORMAL)
- for (phi = phi_nodes (e->dest); phi; phi = PHI_CHAIN (phi))
- {
- /* Visit each PHI on the destination side of this abnormal
- edge, and attempt to coalesce the argument with the result. */
- var = PHI_RESULT (phi);
- x = var_to_partition (map, var);
-
- /* Ignore results which are not relevant. */
- if (x == NO_PARTITION)
- continue;
-
- tmp = PHI_ARG_DEF (phi, e->dest_idx);
-#ifdef ENABLE_CHECKING
- if (!phi_ssa_name_p (tmp))
- {
- print_exprs_edge (stderr, e,
- "\nConstant argument in PHI. Can't insert :",
- var, " = ", tmp);
- internal_error ("SSA corruption");
- }
-#else
- gcc_assert (phi_ssa_name_p (tmp));
-#endif
- y = var_to_partition (map, tmp);
- gcc_assert (x != NO_PARTITION);
- gcc_assert (y != NO_PARTITION);
-#ifdef ENABLE_CHECKING
- if (root_var_find (rv, x) != root_var_find (rv, y))
- {
- print_exprs_edge (stderr, e, "\nDifferent root vars: ",
- root_var (rv, root_var_find (rv, x)),
- " and ",
- root_var (rv, root_var_find (rv, y)));
- internal_error ("SSA corruption");
- }
-#else
- gcc_assert (root_var_find (rv, x) == root_var_find (rv, y));
-#endif
-
- if (x != y)
- {
-#ifdef ENABLE_CHECKING
- if (conflict_graph_conflict_p (graph, x, y))
- {
- print_exprs_edge (stderr, e, "\n Conflict ",
- partition_to_var (map, x),
- " and ", partition_to_var (map, y));
- internal_error ("SSA corruption");
- }
-#else
- gcc_assert (!conflict_graph_conflict_p (graph, x, y));
-#endif
-
- /* Now map the partitions back to their real variables. */
- var = partition_to_var (map, x);
- tmp = partition_to_var (map, y);
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- print_exprs_edge (dump_file, e,
- "ABNORMAL: Coalescing ",
- var, " and ", tmp);
- }
- z = var_union (map, var, tmp);
-#ifdef ENABLE_CHECKING
- if (z == NO_PARTITION)
- {
- print_exprs_edge (stderr, e, "\nUnable to coalesce",
- partition_to_var (map, x), " and ",
- partition_to_var (map, y));
- internal_error ("SSA corruption");
- }
-#else
- gcc_assert (z != NO_PARTITION);
-#endif
- gcc_assert (z == x || z == y);
- if (z == x)
- conflict_graph_merge_regs (graph, x, y);
- else
- conflict_graph_merge_regs (graph, y, x);
- }
- }
-}
-
-/* Coalesce potential copies via PHI arguments. */
-
-static void
-coalesce_phi_operands (var_map map, coalesce_list_p cl)
-{
- basic_block bb;
- tree phi;
-
- FOR_EACH_BB (bb)
- {
- for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
- {
- tree res = PHI_RESULT (phi);
- int p = var_to_partition (map, res);
- int x;
-
- if (p == NO_PARTITION)
- continue;
-
- for (x = 0; x < PHI_NUM_ARGS (phi); x++)
- {
- tree arg = PHI_ARG_DEF (phi, x);
- int p2;
-
- if (TREE_CODE (arg) != SSA_NAME)
- continue;
- if (SSA_NAME_VAR (res) != SSA_NAME_VAR (arg))
- continue;
- p2 = var_to_partition (map, PHI_ARG_DEF (phi, x));
- if (p2 != NO_PARTITION)
- {
- edge e = PHI_ARG_EDGE (phi, x);
- add_coalesce (cl, p, p2,
- coalesce_cost (EDGE_FREQUENCY (e),
- maybe_hot_bb_p (bb),
- EDGE_CRITICAL_P (e)));
- }
- }
- }
- }
-}
-
-/* Coalesce all the result decls together. */
-
-static void
-coalesce_result_decls (var_map map, coalesce_list_p cl)
-{
- unsigned int i, x;
- tree var = NULL;
-
- for (i = x = 0; x < num_var_partitions (map); x++)
- {
- tree p = partition_to_var (map, x);
- if (TREE_CODE (SSA_NAME_VAR (p)) == RESULT_DECL)
- {
- if (var == NULL_TREE)
- {
- var = p;
- i = x;
- }
- else
- add_coalesce (cl, i, x,
- coalesce_cost (EXIT_BLOCK_PTR->frequency,
- maybe_hot_bb_p (EXIT_BLOCK_PTR),
- false));
- }
- }
-}
-
-/* Coalesce matching constraints in asms. */
-
-static void
-coalesce_asm_operands (var_map map, coalesce_list_p cl)
-{
- basic_block bb;
-
- FOR_EACH_BB (bb)
- {
- block_stmt_iterator bsi;
- for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
- {
- tree stmt = bsi_stmt (bsi);
- unsigned long noutputs, i;
- tree *outputs, link;
-
- if (TREE_CODE (stmt) != ASM_EXPR)
- continue;
-
- noutputs = list_length (ASM_OUTPUTS (stmt));
- outputs = (tree *) alloca (noutputs * sizeof (tree));
- for (i = 0, link = ASM_OUTPUTS (stmt); link;
- ++i, link = TREE_CHAIN (link))
- outputs[i] = TREE_VALUE (link);
-
- for (link = ASM_INPUTS (stmt); link; link = TREE_CHAIN (link))
- {
- const char *constraint
- = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
- tree input = TREE_VALUE (link);
- char *end;
- unsigned long match;
- int p1, p2;
-
- if (TREE_CODE (input) != SSA_NAME && !DECL_P (input))
- continue;
-
- match = strtoul (constraint, &end, 10);
- if (match >= noutputs || end == constraint)
- continue;
-
- if (TREE_CODE (outputs[match]) != SSA_NAME
- && !DECL_P (outputs[match]))
- continue;
-
- p1 = var_to_partition (map, outputs[match]);
- if (p1 == NO_PARTITION)
- continue;
- p2 = var_to_partition (map, input);
- if (p2 == NO_PARTITION)
- continue;
-
- add_coalesce (cl, p1, p2, coalesce_cost (REG_BR_PROB_BASE,
- maybe_hot_bb_p (bb),
- false));
- }
- }
- }
-}
-
-/* Reduce the number of live ranges in MAP. Live range information is
- returned if FLAGS indicates that we are combining temporaries, otherwise
- NULL is returned. The only partitions which are associated with actual
- variables at this point are those which are forced to be coalesced for
- various reason. (live on entry, live across abnormal edges, etc.). */
-
-static tree_live_info_p
-coalesce_ssa_name (var_map map, int flags)
-{
- unsigned num, x;
- sbitmap live;
- root_var_p rv;
- tree_live_info_p liveinfo;
- conflict_graph graph;
- coalesce_list_p cl = NULL;
- sbitmap_iterator sbi;
-
- if (num_var_partitions (map) <= 1)
- return NULL;
-
- liveinfo = calculate_live_ranges (map);
- rv = root_var_init (map);
-
- /* Remove single element variable from the list. */
- root_var_compact (rv);
-
- cl = create_coalesce_list (map);
-
- coalesce_phi_operands (map, cl);
- coalesce_result_decls (map, cl);
- coalesce_asm_operands (map, cl);
-
- /* Build a conflict graph. */
- graph = build_tree_conflict_graph (liveinfo, rv, cl);
-
- if (cl)
- {
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, "Before sorting:\n");
- dump_coalesce_list (dump_file, cl);
- }
-
- sort_coalesce_list (cl);
-
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, "\nAfter sorting:\n");
- dump_coalesce_list (dump_file, cl);
- }
- }
-
- /* Put the single element variables back in. */
- root_var_decompact (rv);
-
- /* First, coalesce all live on entry variables to their root variable.
- This will ensure the first use is coming from the correct location. */
-
- num = num_var_partitions (map);
- live = sbitmap_alloc (num);
- sbitmap_zero (live);
-
- /* Set 'live' vector to indicate live on entry partitions. */
- for (x = 0 ; x < num; x++)
- {
- tree var = partition_to_var (map, x);
- if (gimple_default_def (cfun, SSA_NAME_VAR (var)) == var)
- SET_BIT (live, x);
- }
-
- delete_tree_live_info (liveinfo);
- liveinfo = NULL;
-
- /* Assign root variable as partition representative for each live on entry
- partition. */
- EXECUTE_IF_SET_IN_SBITMAP (live, 0, x, sbi)
- {
- tree var = root_var (rv, root_var_find (rv, x));
- var_ann_t ann = var_ann (var);
- /* If these aren't already coalesced... */
- if (partition_to_var (map, x) != var)
- {
- /* This root variable should have not already been assigned
- to another partition which is not coalesced with this one. */
- gcc_assert (!ann->out_of_ssa_tag);
-
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- print_exprs (dump_file, "Must coalesce ",
- partition_to_var (map, x),
- " with the root variable ", var, ".\n");
- }
-
- change_partition_var (map, var, x);
- }
- }
-
- sbitmap_free (live);
-
- /* Coalesce partitions live across abnormal edges. */
- coalesce_abnormal_edges (map, graph, rv);
-
- if (dump_file && (dump_flags & TDF_DETAILS))
- dump_var_map (dump_file, map);
-
- /* Coalesce partitions. */
- coalesce_tpa_members (rv, graph, map, cl,
- ((dump_flags & TDF_DETAILS) ? dump_file
- : NULL));
-
- if (flags & SSANORM_COALESCE_PARTITIONS)
- coalesce_tpa_members (rv, graph, map, NULL,
- ((dump_flags & TDF_DETAILS) ? dump_file
- : NULL));
- if (cl)
- delete_coalesce_list (cl);
- root_var_delete (rv);
- conflict_graph_delete (graph);
-
- return liveinfo;
-}
-
-
/* Take the ssa-name var_map MAP, and assign real variables to each
partition. */
static void
assign_vars (var_map map)
{
- int x, i, num, rep;
- tree t, var;
+ int x, num;
+ tree var, root;
var_ann_t ann;
- root_var_p rv;
-
- rv = root_var_init (map);
- if (!rv)
- return;
-
- /* Coalescing may already have forced some partitions to their root
- variable. Find these and tag them. */
num = num_var_partitions (map);
for (x = 0; x < num; x++)
@@ -949,63 +511,35 @@ assign_vars (var_map map)
var = partition_to_var (map, x);
if (TREE_CODE (var) != SSA_NAME)
{
- /* Coalescing will already have verified that more than one
- partition doesn't have the same root variable. Simply marked
- the variable as assigned. */
ann = var_ann (var);
- ann->out_of_ssa_tag = 1;
+ /* It must already be coalesced. */
+ gcc_assert (ann->out_of_ssa_tag == 1);
if (dump_file && (dump_flags & TDF_DETAILS))
{
- fprintf (dump_file, "partition %d has variable ", x);
+ fprintf (dump_file, "partition %d already has variable ", x);
print_generic_expr (dump_file, var, TDF_SLIM);
fprintf (dump_file, " assigned to it.\n");
}
-
}
- }
-
- num = root_var_num (rv);
- for (x = 0; x < num; x++)
- {
- var = root_var (rv, x);
- ann = var_ann (var);
- for (i = root_var_first_partition (rv, x);
- i != ROOT_VAR_NONE;
- i = root_var_next_partition (rv, i))
- {
- t = partition_to_var (map, i);
-
- if (t == var || TREE_CODE (t) != SSA_NAME)
- continue;
-
- rep = var_to_partition (map, t);
-
- if (!ann->out_of_ssa_tag)
+ else
+ {
+ root = SSA_NAME_VAR (var);
+ ann = var_ann (root);
+ /* If ROOT is already associated, create a new one. */
+ if (ann->out_of_ssa_tag)
{
- if (dump_file && (dump_flags & TDF_DETAILS))
- print_exprs (dump_file, "", t, " --> ", var, "\n");
- change_partition_var (map, var, rep);
- continue;
+ root = create_temp (root);
+ ann = var_ann (root);
}
-
- if (dump_file && (dump_flags & TDF_DETAILS))
- print_exprs (dump_file, "", t, " not coalesced with ", var,
- "");
-
- var = create_temp (t);
- change_partition_var (map, var, rep);
- ann = var_ann (var);
-
+ /* ROOT has not been coalesced yet, so use it. */
if (dump_file && (dump_flags & TDF_DETAILS))
{
- fprintf (dump_file, " --> New temp: '");
- print_generic_expr (dump_file, var, TDF_SLIM);
- fprintf (dump_file, "'\n");
+ fprintf (dump_file, "Partition %d is assigned to var ", x);
+ print_generic_stmt (dump_file, root, TDF_SLIM);
}
+ change_partition_var (map, root, x);
}
}
-
- root_var_delete (rv);
}
@@ -1028,6 +562,7 @@ replace_use_variable (var_map map, use_operand_p p, tree *expr)
{
tree new_expr = GIMPLE_STMT_OPERAND (expr[version], 1);
SET_USE (p, new_expr);
+
/* Clear the stmt's RHS, or GC might bite us. */
GIMPLE_STMT_OPERAND (expr[version], 1) = NULL_TREE;
return true;
@@ -1056,19 +591,9 @@ replace_def_variable (var_map map, def_operand_p def_p, tree *expr)
tree new_var;
tree var = DEF_FROM_PTR (def_p);
- /* Check if we are replacing this variable with an expression. */
- if (expr)
- {
- int version = SSA_NAME_VERSION (var);
- if (expr[version])
- {
- tree new_expr = TREE_OPERAND (expr[version], 1);
- SET_DEF (def_p, new_expr);
- /* Clear the stmt's RHS, or GC might bite us. */
- TREE_OPERAND (expr[version], 1) = NULL_TREE;
- return true;
- }
- }
+ /* Do nothing if we are replacing this variable with an expression. */
+ if (expr && expr[SSA_NAME_VERSION (var)])
+ return true;
new_var = var_to_partition_to_var (map, var);
if (new_var)
@@ -1144,15 +669,12 @@ rewrite_trees (var_map map, tree *values)
FOR_EACH_BB (bb)
{
tree phi;
-
for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
{
tree T0 = var_to_partition_to_var (map, PHI_RESULT (phi));
-
if (T0 == NULL_TREE)
{
int i;
-
for (i = 0; i < PHI_NUM_ARGS (phi); i++)
{
tree arg = PHI_ARG_DEF (phi, i);
@@ -1261,8 +783,10 @@ static edge leader_match = NULL;
/* Pass this function to make_forwarder_block so that all the edges with
- matching PENDING_STMT lists to 'curr_stmt_list' get redirected. */
-static bool
+ matching PENDING_STMT lists to 'curr_stmt_list' get redirected. E is the
+ edge to test for a match. */
+
+static inline bool
same_stmt_list_p (edge e)
{
return (e->aux == (PTR) leader_match) ? true : false;
@@ -1270,6 +794,7 @@ same_stmt_list_p (edge e)
/* Return TRUE if S1 and S2 are equivalent copies. */
+
static inline bool
identical_copies_p (tree s1, tree s2)
{
@@ -1293,7 +818,7 @@ identical_copies_p (tree s1, tree s2)
}
-/* Compare the PENDING_STMT list for two edges, and return true if the lists
+/* Compare the PENDING_STMT list for edges E1 and E2. Return true if the lists
contain the same sequence of copies. */
static inline bool
@@ -1380,6 +905,7 @@ analyze_edges_for_bb (basic_block bb)
bsi_commit_one_edge_insert (e, NULL);
return;
}
+
/* Find out how many edges there are with interesting pending stmts on them.
Commit the stmts on edges we are not interested in. */
FOR_EACH_EDGE (e, ei, bb->preds)
@@ -1470,11 +996,9 @@ analyze_edges_for_bb (basic_block bb)
return;
}
-
if (dump_file)
fprintf (dump_file, "\nOpportunities in BB %d for stmt/block reduction:\n",
bb->index);
-
/* For each common list, create a forwarding block and issue the stmt's
in that block. */
@@ -1601,28 +1125,23 @@ perform_edge_inserts (void)
}
-/* Remove the variables specified in MAP from SSA form. FLAGS indicate what
- options should be used. */
+/* Remove the ssa-names in the current function and translate them into normal
+ compiler variables. PERFORM_TER is true if Temporary Expression Replacement
+ should also be used. */
static void
-remove_ssa_form (var_map map, int flags)
+remove_ssa_form (bool perform_ter)
{
- tree_live_info_p liveinfo;
basic_block bb;
tree phi, next;
tree *values = NULL;
+ var_map map;
- /* If we are not combining temps, don't calculate live ranges for variables
- with only one SSA version. */
- compact_var_map (map, VARMAP_NO_SINGLE_DEFS);
-
- if (dump_file && (dump_flags & TDF_DETAILS))
- dump_var_map (dump_file, map);
-
- liveinfo = coalesce_ssa_name (map, flags);
+ map = coalesce_ssa_name ();
- /* Make sure even single occurrence variables are in the list now. */
- compact_var_map (map, VARMAP_NORMAL);
+ /* Return to viewing the variable list as just all reference variables after
+ coalescing has been performed. */
+ partition_view_normal (map, false);
if (dump_file && (dump_flags & TDF_DETAILS))
{
@@ -1630,7 +1149,7 @@ remove_ssa_form (var_map map, int flags)
dump_var_map (dump_file, map);
}
- if (flags & SSANORM_PERFORM_TER)
+ if (perform_ter)
{
values = find_replaceable_exprs (map);
if (values && dump_file && (dump_flags & TDF_DETAILS))
@@ -1642,13 +1161,10 @@ remove_ssa_form (var_map map, int flags)
if (dump_file && (dump_flags & TDF_DETAILS))
{
- fprintf (dump_file, "After Root variable replacement:\n");
+ fprintf (dump_file, "After Base variable replacement:\n");
dump_var_map (dump_file, map);
}
- if (liveinfo)
- delete_tree_live_info (liveinfo);
-
rewrite_trees (map, values);
if (values)
@@ -1669,8 +1185,11 @@ remove_ssa_form (var_map map, int flags)
/* If any copies were inserted on edges, analyze and insert them now. */
perform_edge_inserts ();
+
+ delete_var_map (map);
}
+
/* Search every PHI node for arguments associated with backedges which
we can trivially determine will need a copy (the argument is either
not an SSA_NAME or the argument has a different underlying variable
@@ -1704,11 +1223,10 @@ insert_backedge_copies (void)
tree arg = PHI_ARG_DEF (phi, i);
edge e = PHI_ARG_EDGE (phi, i);
- /* If the argument is not an SSA_NAME, then we will
- need a constant initialization. If the argument is
- an SSA_NAME with a different underlying variable and
- we are not combining temporaries, then we will
- need a copy statement. */
+ /* If the argument is not an SSA_NAME, then we will need a
+ constant initialization. If the argument is an SSA_NAME with
+ a different underlying variable then a copy statement will be
+ needed. */
if ((e->flags & EDGE_DFS_BACK)
&& (TREE_CODE (arg) != SSA_NAME
|| SSA_NAME_VAR (arg) != result_var))
@@ -1723,7 +1241,6 @@ insert_backedge_copies (void)
/* In theory the only way we ought to get back to the
start of a loop should be with a COND_EXPR or GOTO_EXPR.
However, better safe than sorry.
-
If the block ends with a control statement or
something that might throw, then we have to
insert this assignment before the last
@@ -1738,8 +1255,8 @@ insert_backedge_copies (void)
continue;
}
- /* Create a new instance of the underlying
- variable of the PHI result. */
+ /* Create a new instance of the underlying variable of the
+ PHI result. */
stmt = build2 (GIMPLE_MODIFY_STMT, TREE_TYPE (result_var),
NULL_TREE, PHI_ARG_DEF (phi, i));
name = make_ssa_name (result_var, stmt);
@@ -1758,16 +1275,13 @@ insert_backedge_copies (void)
}
}
-/* Take the current function out of SSA form, as described in
+/* Take the current function out of SSA form, translating PHIs as described in
R. Morgan, ``Building an Optimizing Compiler'',
Butterworth-Heinemann, Boston, MA, 1998. pp 176-186. */
static unsigned int
rewrite_out_of_ssa (void)
{
- var_map map;
- int ssa_flags = 0;
-
/* If elimination of a PHI requires inserting a copy on a backedge,
then we will have to split the backedge which has numerous
undesirable performance effects.
@@ -1776,27 +1290,16 @@ rewrite_out_of_ssa (void)
copies into the loop itself. */
insert_backedge_copies ();
- if (!flag_tree_live_range_split)
- ssa_flags |= SSANORM_COALESCE_PARTITIONS;
-
eliminate_virtual_phis ();
if (dump_file && (dump_flags & TDF_DETAILS))
dump_tree_cfg (dump_file, dump_flags & ~TDF_DETAILS);
- map = create_ssa_var_map ();
-
- if (flag_tree_ter && !flag_mudflap)
- ssa_flags |= SSANORM_PERFORM_TER;
-
- remove_ssa_form (map, ssa_flags);
+ remove_ssa_form (flag_tree_ter && !flag_mudflap);
if (dump_file && (dump_flags & TDF_DETAILS))
dump_tree_cfg (dump_file, dump_flags & ~TDF_DETAILS);
- /* Flush out flow graph and SSA data. */
- delete_var_map (map);
-
cfun->gimple_df->in_ssa_p = false;
return 0;
}