diff options
author | Andrew Macleod <amacleod@redhat.com> | 2006-10-06 16:52:36 +0000 |
---|---|---|
committer | Andrew Macleod <amacleod@redhat.com> | 2006-10-06 16:52:36 +0000 |
commit | 0492261bb45fb9b79e1e8fe626552fd196b68411 (patch) | |
tree | bfa283ce7d2a6bdd833762f4d429e11b8f3784d2 | |
parent | 4c5d1803bfa2b7853bf1b0c5d14979501e93157b (diff) |
Split abnormal coalesces out from coalesce list.
2006-10-06 Andrew MacLeod <amacleod@redhat.com>
* tree-ssa-coalesce.c (struct coalesce_list_d): Remove present bitmap.
(version_in_coalesce_list_p): Delete.
(create_coalesce_list): Don't initialize 'present' bitmap.
(delete_coalesce_list): Don't free 'present' bitmap.
(find_coalesce_pair): Don't set 'present' bitmap.
(create_outofssa_var_map: Don't add abnormal pairs to coalesce list.
Update copy_used_in bitmap.
(attempt_coalesce): New. Split out from coalesce_partitions.
(coalesce_partitions): Coalesce abnormal edges first, then coalesce
list.
(coalesce_ssa_name): shuffles some orderig around.
git-svn-id: https://gcc.gnu.org/svn/gcc/branches/out-of-ssa-the-sequel@117507 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/ChangeLog | 14 | ||||
-rw-r--r-- | gcc/tree-ssa-coalesce.c | 689 |
2 files changed, 386 insertions, 317 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b272fceba35..4f335a8b99d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,19 @@ 2006-10-06 Andrew MacLeod <amacleod@redhat.com> + * tree-ssa-coalesce.c (struct coalesce_list_d): Remove present bitmap. + (version_in_coalesce_list_p): Delete. + (create_coalesce_list): Don't initialize 'present' bitmap. + (delete_coalesce_list): Don't free 'present' bitmap. + (find_coalesce_pair): Don't set 'present' bitmap. + (create_outofssa_var_map: Don't add abnormal pairs to coalesce list. + Update copy_used_in bitmap. + (attempt_coalesce): New. Split out from coalesce_partitions. + (coalesce_partitions): Coalesce abnormal edges first, then coalesce + list. + (coalesce_ssa_name): shuffles some orderig around. + +2006-10-06 Andrew MacLeod <amacleod@redhat.com> + * tree-ssa-coalesce.c (ssa_conflicts_test_p): Avoid bit test when able. (ssa_conflicts_merge): Be more efficient when possible. diff --git a/gcc/tree-ssa-coalesce.c b/gcc/tree-ssa-coalesce.c index 138421b3ed3..d899e92e788 100644 --- a/gcc/tree-ssa-coalesce.c +++ b/gcc/tree-ssa-coalesce.c @@ -56,22 +56,12 @@ typedef struct coalesce_list_d htab_t list; /* Hash table. */ coalesce_pair_p *sorted; /* List when sorted. */ int num_sorted; /* Number in the sorted list. */ - bitmap present; /* True if element number is in the list. */ } *coalesce_list_p; #define NO_BEST_COALESCE -1 #define MUST_COALESCE_COST INT_MAX -/* Return true if V is present in CL. */ - -static inline bool -version_in_coalesce_list_p (coalesce_list_p cl, int v) -{ - return bitmap_bit_p (cl->present, v); -} - - /* Return cost of execution of copy instruction with FREQUENCY possibly on CRITICAL edge and in HOT basic block. */ @@ -186,7 +176,6 @@ create_coalesce_list (void) coalesce_pair_map_eq, NULL); list->sorted = NULL; list->num_sorted = 0; - list->present = BITMAP_ALLOC (NULL); return list; } @@ -199,7 +188,6 @@ delete_coalesce_list (coalesce_list_p cl) htab_delete (cl->list); if (cl->sorted) free (cl->sorted); - BITMAP_FREE (cl->present); gcc_assert (cl->num_sorted == 0); free (cl); } @@ -235,8 +223,6 @@ find_coalesce_pair (coalesce_list_p cl, int p1, int p2, bool create) if (create && !pair) { gcc_assert (cl->sorted == NULL); - bitmap_set_bit (cl->present, p1); - bitmap_set_bit (cl->present, p2); pair = xmalloc (sizeof (struct coalesce_pair)); pair->first_element = p.first_element; pair->second_element = p.second_element; @@ -430,253 +416,7 @@ dump_coalesce_list (FILE *f, coalesce_list_p cl) } - -/* Shortcut routine to print messages to file F of the form: - "STR1 EXPR1 STR2 EXPR2 STR3." */ - -static inline 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); -} - - -/* Called if a coalesce across and abnormal edge cannot be performed. PHI is - the phi node at fault, I is the argument index at fault. A message is - printed and compilation is then terminated. */ - -static inline void -abnormal_corrupt (tree phi, int i) -{ - edge e = PHI_ARG_EDGE (phi, i); - tree res = PHI_RESULT (phi); - tree arg = PHI_ARG_DEF (phi, i); - - fprintf (stderr, " Corrupt SSA across abnormal edge BB%d->BB%d\n", - e->src->index, e->dest->index); - fprintf (stderr, "Argument %d (", i); - print_generic_expr (stderr, arg, TDF_SLIM); - if (TREE_CODE (arg) != SSA_NAME) - fprintf (stderr, ") is not an SSA_NAME.\n"); - else - { - gcc_assert (SSA_NAME_VAR (res) != SSA_NAME_VAR (arg)); - fprintf (stderr, ") does not have the same base variable as the result "); - print_generic_stmt (stderr, res, TDF_SLIM); - } - - internal_error ("SSA corruption"); -} - - -/* This function creates a var_map for the current function as well as creating - a coalesce list for use later in the out of ssa process. */ - -static var_map -create_outofssa_var_map (coalesce_list_p cl) -{ - block_stmt_iterator bsi; - basic_block bb; - tree var; - tree stmt; - tree first; - var_map map; - ssa_op_iter iter; - int v1, v2, cost; - unsigned i; - -#ifdef ENABLE_CHECKING - bitmap used_in_real_ops; - bitmap used_in_virtual_ops; - - used_in_real_ops = BITMAP_ALLOC (NULL); - used_in_virtual_ops = BITMAP_ALLOC (NULL); -#endif - - map = init_var_map (num_ssa_names + 1); - - FOR_EACH_BB (bb) - { - tree phi, arg; - - for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi)) - { - int i; - int ver; - tree res; - - res = PHI_RESULT (phi); - ver = SSA_NAME_VERSION (res); - register_ssa_partition (map, res); - - /* Register ssa_names and coalesces between the args and the result - of all PHI. */ - for (i = 0; i < PHI_NUM_ARGS (phi); i++) - { - edge e = PHI_ARG_EDGE (phi, i); - arg = PHI_ARG_DEF (phi, i); - if (TREE_CODE (arg) == SSA_NAME) - register_ssa_partition (map, arg); - if (TREE_CODE (arg) == SSA_NAME - && SSA_NAME_VAR (arg) == SSA_NAME_VAR (res)) - { - int cost = coalesce_cost_edge (e); - add_coalesce (cl, ver, SSA_NAME_VERSION (arg), cost); - } - else - if (e->flags & EDGE_ABNORMAL) - abnormal_corrupt (phi, i); - } - } - - for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi)) - { - stmt = bsi_stmt (bsi); - - /* Register USE and DEF operands in each statement. */ - FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, (SSA_OP_DEF|SSA_OP_USE)) - register_ssa_partition (map, var); - - /* Check for copy coalesces. */ - switch (TREE_CODE (stmt)) - { - case MODIFY_EXPR: - { - tree op1 = TREE_OPERAND (stmt, 0); - tree op2 = TREE_OPERAND (stmt, 1); - if (TREE_CODE (op1) == SSA_NAME - && TREE_CODE (op2) == SSA_NAME - && SSA_NAME_VAR (op1) == SSA_NAME_VAR (op2)) - { - v1 = SSA_NAME_VERSION (op1); - v2 = SSA_NAME_VERSION (op2); - cost = coalesce_cost_bb (bb); - add_coalesce (cl, v1, v2, cost); - } - } - break; - - case ASM_EXPR: - { - unsigned long noutputs, i; - tree *outputs, link; - 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; - - 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) - continue; - - v1 = SSA_NAME_VERSION (outputs[match]); - v2 = SSA_NAME_VERSION (input); - cost = coalesce_cost (REG_BR_PROB_BASE, - maybe_hot_bb_p (bb), - false); - - if (SSA_NAME_VAR (outputs[match]) == SSA_NAME_VAR (input)) - add_coalesce (cl, v1, v2, cost); - } - break; - } - - default: - break; - } - -#ifdef ENABLE_CHECKING - /* Mark real uses and defs. */ - FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, (SSA_OP_DEF|SSA_OP_USE)) - bitmap_set_bit (used_in_real_ops, DECL_UID (SSA_NAME_VAR (var))); - - /* Validate that virtual ops don't get used in funny ways. */ - FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, - SSA_OP_VIRTUAL_USES | SSA_OP_VMUSTDEF) - { - bitmap_set_bit (used_in_virtual_ops, - DECL_UID (SSA_NAME_VAR (var))); - } - -#endif /* ENABLE_CHECKING */ - } - } - - /* Now process result decls and live on entry variables. */ - first = NULL_TREE; - for (i = 1; i < num_ssa_names; i++) - { - var = map->partition_to_var[i]; - if (var != NULL_TREE) - { - /* Add coalesces between all the result decls. */ - if (TREE_CODE (SSA_NAME_VAR (var)) == RESULT_DECL) - { - if (first == NULL_TREE) - first = var; - else - { - gcc_assert (SSA_NAME_VAR (var) == SSA_NAME_VAR (first)); - v1 = SSA_NAME_VERSION (first); - v2 = SSA_NAME_VERSION (var); - cost = coalesce_cost_bb (EXIT_BLOCK_PTR); - add_coalesce (cl, v1, v2, cost); - } - } - /* Mark any default_def variables as being in the coalesce list - since they will have to be coalesced with the base variable. If - not marked as present, they won't be in the coalesce view. */ - if (default_def (SSA_NAME_VAR (var)) == var) - bitmap_set_bit (cl->present, SSA_NAME_VERSION (var)); - } - } - -#if defined ENABLE_CHECKING - { - unsigned i; - bitmap both = BITMAP_ALLOC (NULL); - bitmap_and (both, used_in_real_ops, used_in_virtual_ops); - if (!bitmap_empty_p (both)) - { - bitmap_iterator bi; - - EXECUTE_IF_SET_IN_BITMAP (both, 0, i, bi) - fprintf (stderr, "Variable %s used in real and virtual operands\n", - get_name (referenced_var (i))); - internal_error ("SSA corruption"); - } - - BITMAP_FREE (used_in_real_ops); - BITMAP_FREE (used_in_virtual_ops); - BITMAP_FREE (both); - } -#endif - - return map; -} - - -/* This prepresents a conflict graph. Implemented as an array of bitmaps. +/* This represents a conflict graph. Implemented as an array of bitmaps. A full matrix isused for conflicts rather than just upper triangular form. this make sit much simpler and faster to perform conflict merges. */ @@ -1041,6 +781,49 @@ build_ssa_conflict_graph (tree_live_info_p liveinfo) } +/* Shortcut routine to print messages to file F of the form: + "STR1 EXPR1 STR2 EXPR2 STR3." */ + +static inline 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); +} + + +/* Called if a coalesce across and abnormal edge cannot be performed. PHI is + the phi node at fault, I is the argument index at fault. A message is + printed and compilation is then terminated. */ + +static inline void +abnormal_corrupt (tree phi, int i) +{ + edge e = PHI_ARG_EDGE (phi, i); + tree res = PHI_RESULT (phi); + tree arg = PHI_ARG_DEF (phi, i); + + fprintf (stderr, " Corrupt SSA across abnormal edge BB%d->BB%d\n", + e->src->index, e->dest->index); + fprintf (stderr, "Argument %d (", i); + print_generic_expr (stderr, arg, TDF_SLIM); + if (TREE_CODE (arg) != SSA_NAME) + fprintf (stderr, ") is not an SSA_NAME.\n"); + else + { + gcc_assert (SSA_NAME_VAR (res) != SSA_NAME_VAR (arg)); + fprintf (stderr, ") does not have the same base variable as the result "); + print_generic_stmt (stderr, res, TDF_SLIM); + } + + internal_error ("SSA corruption"); +} + + /* Print a failure to coalesce a MUST_COALESCE pair X and Y. */ static inline void @@ -1056,77 +839,345 @@ fail_abnormal_edge_coalesce (int x, int y) } -/* Attempt to Coalesce partitions in MAP which occur in the list CL using - GRAPH. Debug output is sent to DEBUG if it is non-NULL. */ +/* This function creates a var_map for the current function as well as creating + a coalesce list for use later in the out of ssa process. */ -static void -coalesce_partitions (var_map map, ssa_conflicts_p graph, coalesce_list_p cl, - FILE *debug) +static var_map +create_outofssa_var_map (coalesce_list_p cl, bitmap used_in_copy) { - int x, y, z; - int p1,p2; - tree var1, var2; - int cost; + block_stmt_iterator bsi; + basic_block bb; + tree var; + tree stmt; + tree first; + var_map map; + ssa_op_iter iter; + int v1, v2, cost; + unsigned i; - while ((cost = pop_best_coalesce (cl, &x, &y)) != NO_BEST_COALESCE) +#ifdef ENABLE_CHECKING + bitmap used_in_real_ops; + bitmap used_in_virtual_ops; + + used_in_real_ops = BITMAP_ALLOC (NULL); + used_in_virtual_ops = BITMAP_ALLOC (NULL); +#endif + + map = init_var_map (num_ssa_names + 1); + + FOR_EACH_BB (bb) { - var1 = ssa_name (x); - var2 = ssa_name (y); - p1 = var_to_partition (map, var1); - p2 = var_to_partition (map, var2); + tree phi, arg; - if (debug) + for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi)) { - fprintf (debug, "Coalesce list: (%d)", x); - print_generic_expr (debug, partition_to_var (map, p1), TDF_SLIM); - fprintf (debug, " & (%d)", y); - print_generic_expr (debug, partition_to_var (map, p2), TDF_SLIM); - } + int i; + int ver; + tree res; + bool saw_copy = false; - if (p1 == p2) - { - if (debug) - fprintf (debug, ": Already Coalesced.\n"); - continue; + res = PHI_RESULT (phi); + ver = SSA_NAME_VERSION (res); + register_ssa_partition (map, res); + + /* Register ssa_names and coalesces between the args and the result + of all PHI. */ + for (i = 0; i < PHI_NUM_ARGS (phi); i++) + { + edge e = PHI_ARG_EDGE (phi, i); + arg = PHI_ARG_DEF (phi, i); + if (TREE_CODE (arg) == SSA_NAME) + register_ssa_partition (map, arg); + if (TREE_CODE (arg) == SSA_NAME + && SSA_NAME_VAR (arg) == SSA_NAME_VAR (res)) + { + saw_copy = true; + bitmap_set_bit (used_in_copy, SSA_NAME_VERSION (arg)); + if ((e->flags & EDGE_ABNORMAL) == 0) + { + int cost = coalesce_cost_edge (e); + add_coalesce (cl, ver, SSA_NAME_VERSION (arg), cost); + } + } + else + if (e->flags & EDGE_ABNORMAL) + abnormal_corrupt (phi, i); + } + if (saw_copy) + bitmap_set_bit (used_in_copy, ver); } - /* Assert the coalesces have the same base variable. */ - gcc_assert (SSA_NAME_VAR (var1) == SSA_NAME_VAR (var2)); + for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi)) + { + stmt = bsi_stmt (bsi); - if (debug) - fprintf (debug, " [map: %d, %d] ", p1, p2); + /* Register USE and DEF operands in each statement. */ + FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, (SSA_OP_DEF|SSA_OP_USE)) + register_ssa_partition (map, var); - if (!ssa_conflicts_test_p (graph, p1, p2)) - { - var1 = partition_to_var (map, p1); - var2 = partition_to_var (map, p2); - z = var_union (map, var1, var2); - if (z == NO_PARTITION) + /* Check for copy coalesces. */ + switch (TREE_CODE (stmt)) { - if (debug) - fprintf (debug, ": Unable to perform partition union.\n"); - if (cost == MUST_COALESCE_COST) - fail_abnormal_edge_coalesce (x, y); - continue; + case MODIFY_EXPR: + { + tree op1 = TREE_OPERAND (stmt, 0); + tree op2 = TREE_OPERAND (stmt, 1); + if (TREE_CODE (op1) == SSA_NAME + && TREE_CODE (op2) == SSA_NAME + && SSA_NAME_VAR (op1) == SSA_NAME_VAR (op2)) + { + v1 = SSA_NAME_VERSION (op1); + v2 = SSA_NAME_VERSION (op2); + cost = coalesce_cost_bb (bb); + add_coalesce (cl, v1, v2, cost); + bitmap_set_bit (used_in_copy, v1); + bitmap_set_bit (used_in_copy, v2); + } + } + break; + + case ASM_EXPR: + { + unsigned long noutputs, i; + tree *outputs, link; + 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; + + 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) + continue; + + v1 = SSA_NAME_VERSION (outputs[match]); + v2 = SSA_NAME_VERSION (input); + + if (SSA_NAME_VAR (outputs[match]) == SSA_NAME_VAR (input)) + { + cost = coalesce_cost (REG_BR_PROB_BASE, + maybe_hot_bb_p (bb), + false); + add_coalesce (cl, v1, v2, cost); + bitmap_set_bit (used_in_copy, v1); + bitmap_set_bit (used_in_copy, v2); + } + } + break; + } + + default: + break; } + +#ifdef ENABLE_CHECKING + /* Mark real uses and defs. */ + FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, (SSA_OP_DEF|SSA_OP_USE)) + bitmap_set_bit (used_in_real_ops, DECL_UID (SSA_NAME_VAR (var))); - /* z is the new combined partition. Remove the other partition from - the list, and merge the conflicts. */ - if (z == p1) - ssa_conflicts_merge (graph, p1, p2); - else - ssa_conflicts_merge (graph, p2, p1); + /* Validate that virtual ops don't get used in funny ways. */ + FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, + SSA_OP_VIRTUAL_USES | SSA_OP_VMUSTDEF) + { + bitmap_set_bit (used_in_virtual_ops, + DECL_UID (SSA_NAME_VAR (var))); + } - if (debug) - fprintf (debug, ": Success -> %d\n", z); +#endif /* ENABLE_CHECKING */ } - else + } + + /* Now process result decls and live on entry variables for entry into + the coalesce list. */ + first = NULL_TREE; + for (i = 1; i < num_ssa_names; i++) + { + var = map->partition_to_var[i]; + if (var != NULL_TREE) { + /* Add coalesces between all the result decls. */ + if (TREE_CODE (SSA_NAME_VAR (var)) == RESULT_DECL) + { + if (first == NULL_TREE) + first = var; + else + { + gcc_assert (SSA_NAME_VAR (var) == SSA_NAME_VAR (first)); + v1 = SSA_NAME_VERSION (first); + v2 = SSA_NAME_VERSION (var); + bitmap_set_bit (used_in_copy, v1); + bitmap_set_bit (used_in_copy, v2); + cost = coalesce_cost_bb (EXIT_BLOCK_PTR); + add_coalesce (cl, v1, v2, cost); + } + } + /* Mark any default_def variables as being in the coalesce list + since they will have to be coalesced with the base variable. If + not marked as present, they won't be in the coalesce view. */ + if (default_def (SSA_NAME_VAR (var)) == var) + bitmap_set_bit (used_in_copy, SSA_NAME_VERSION (var)); + } + } + +#if defined ENABLE_CHECKING + { + unsigned i; + bitmap both = BITMAP_ALLOC (NULL); + bitmap_and (both, used_in_real_ops, used_in_virtual_ops); + if (!bitmap_empty_p (both)) + { + bitmap_iterator bi; + + EXECUTE_IF_SET_IN_BITMAP (both, 0, i, bi) + fprintf (stderr, "Variable %s used in real and virtual operands\n", + get_name (referenced_var (i))); + internal_error ("SSA corruption"); + } + + BITMAP_FREE (used_in_real_ops); + BITMAP_FREE (used_in_virtual_ops); + BITMAP_FREE (both); + } +#endif + + return map; +} + + +/* Attempt to coalesce ssa verisosn X and Y together using the partition + mapping in MAP and checking conflicts in GRAPH. Output any debug info to + DEBUG, if it is nun-NULL. */ + +static inline bool +attempt_coalesce (var_map map, ssa_conflicts_p graph, int x, int y, + FILE *debug) +{ + int z; + tree var1, var2; + int p1, p2; + + p1 = var_to_partition (map, ssa_name (x)); + p2 = var_to_partition (map, ssa_name (y)); + + if (debug) + { + fprintf (debug, "(%d)", x); + print_generic_expr (debug, partition_to_var (map, p1), TDF_SLIM); + fprintf (debug, " & (%d)", y); + print_generic_expr (debug, partition_to_var (map, p2), TDF_SLIM); + } + + if (p1 == p2) + { + if (debug) + fprintf (debug, ": Already Coalesced.\n"); + return true; + } + + if (debug) + fprintf (debug, " [map: %d, %d] ", p1, p2); + + + if (!ssa_conflicts_test_p (graph, p1, p2)) + { + var1 = partition_to_var (map, p1); + var2 = partition_to_var (map, p2); + z = var_union (map, var1, var2); + if (z == NO_PARTITION) + { if (debug) - fprintf (debug, ": Fail due to conflict\n"); - if (cost == MUST_COALESCE_COST) - fail_abnormal_edge_coalesce (x, y); + fprintf (debug, ": Unable to perform partition union.\n"); + return false; } + + /* z is the new combined partition. Remove the other partition from + the list, and merge the conflicts. */ + if (z == p1) + ssa_conflicts_merge (graph, p1, p2); + else + ssa_conflicts_merge (graph, p2, p1); + + if (debug) + fprintf (debug, ": Success -> %d\n", z); + return true; + } + + if (debug) + fprintf (debug, ": Fail due to conflict\n"); + + return false; +} + + +/* Attempt to Coalesce partitions in MAP which occur in the list CL using + GRAPH. Debug output is sent to DEBUG if it is non-NULL. */ + +static void +coalesce_partitions (var_map map, ssa_conflicts_p graph, coalesce_list_p cl, + FILE *debug) +{ + int x, y; + tree var1, var2, phi; + int cost; + basic_block bb; + edge e; + edge_iterator ei; + + /* First, coalece all the copie across abnormal edges. These are not placed + in the coalesce list becase they do not need to be sorted, and simply + consume extra memory/compilation time in large programs. */ + + FOR_EACH_BB (bb) + { + FOR_EACH_EDGE (e, ei, bb->preds) + if (e->flags & EDGE_ABNORMAL) + { + for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi)) + { + tree res = PHI_RESULT (phi); + tree arg = PHI_ARG_DEF (phi, e->dest_idx); + int v1 = SSA_NAME_VERSION (res); + int v2 = SSA_NAME_VERSION (arg); + + if (SSA_NAME_VAR (arg) != SSA_NAME_VAR (res)) + abnormal_corrupt (phi, e->dest_idx); + + if (debug) + fprintf (debug, "Abnormal coalesce: "); + + if (!attempt_coalesce (map, graph, v1, v2, debug)) + fail_abnormal_edge_coalesce (v1, v2); + } + } + } + + /* Now process the items in the coalesce list. */ + + while ((cost = pop_best_coalesce (cl, &x, &y)) != NO_BEST_COALESCE) + { + var1 = ssa_name (x); + var2 = ssa_name (y); + + /* Assert the coalesces have the same base variable. */ + gcc_assert (SSA_NAME_VAR (var1) == SSA_NAME_VAR (var2)); + + if (debug) + fprintf (debug, "Coalesce list: "); + attempt_coalesce (map, graph, x, y, debug); } } @@ -1141,16 +1192,21 @@ coalesce_ssa_name (void) tree_live_info_p liveinfo; ssa_conflicts_p graph; coalesce_list_p cl; + bitmap used_in_copies = BITMAP_ALLOC (NULL); var_map map; cl = create_coalesce_list (); - map = create_outofssa_var_map (cl); + map = create_outofssa_var_map (cl, used_in_copies); /* Don't calculate live ranges for variables not in the coalesce list. */ - partition_view_bitmap (map, cl->present, true); + partition_view_bitmap (map, used_in_copies, true); + BITMAP_FREE (used_in_copies); if (num_var_partitions (map) <= 1) - return map; + { + delete_coalesce_list (cl); + return map; + } if (dump_file && (dump_flags & TDF_DETAILS)) dump_var_map (dump_file, map); @@ -1172,7 +1228,6 @@ coalesce_ssa_name (void) dump_coalesce_list (dump_file, cl); } - /* First, coalesce all live on entry variables to their base variable. This will ensure the first use is coming from the correct location. */ |