-/* 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);
- }
- }
-}
-
-
-/* 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, i;
- sbitmap live;
- tree var, phi;
- root_var_p rv;
- tree_live_info_p liveinfo;
- var_ann_t ann;
- conflict_graph graph;
- basic_block bb;
- coalesce_list_p cl = NULL;
-
- if (num_var_partitions (map) <= 1)
- return NULL;
-
- /* If no preference given, use cheap coalescing of all partitions. */
- if ((flags & (SSANORM_COALESCE_PARTITIONS | SSANORM_USE_COALESCE_LIST)) == 0)
- flags |= SSANORM_COALESCE_PARTITIONS;
-
- liveinfo = calculate_live_on_entry (map);
- calculate_live_on_exit (liveinfo);
- rv = root_var_init (map);
-
- /* Remove single element variable from the list. */
- root_var_compact (rv);
-
- if (flags & SSANORM_USE_COALESCE_LIST)
- {
- cl = create_coalesce_list (map);
-
- /* Add all potential copies via PHI arguments to the list. */
- 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);
- if (p == NO_PARTITION)
- continue;
- for (x = 0; x < (unsigned)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)
- add_coalesce (cl, p, p2, 1);
- }
- }
- }
-
- /* Coalesce all the result decls together. */
- var = NULL_TREE;
- i = 0;
- for (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, 1);
- }
- }
- }
-
- /* 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. */
-
- live = sbitmap_alloc (num_var_partitions (map));
- sbitmap_zero (live);
-
- /* Set 'live' vector to indicate live on entry partitions. */
- num = num_var_partitions (map);
- for (x = 0 ; x < num; x++)
- {
- var = partition_to_var (map, x);
- if (default_def (SSA_NAME_VAR (var)) == var)
- SET_BIT (live, x);
- }
-
- if ((flags & SSANORM_COMBINE_TEMPS) == 0)
- {
- 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,
- {
- var = root_var (rv, root_var_find (rv, x));
- 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. */
- if (flags & SSANORM_USE_COALESCE_LIST)
- 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;
-}
-
-