You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#include "config.h"
#include "system.h"
#include "tree-gimple.h"
#include "tree-inline.h"
#include "timevar.h"
-#include "tree-alias-common.h"
#include "hashtab.h"
#include "tree-dump.h"
#include "tree-ssa-live.h"
#include "tree-pass.h"
-
-extern void rename_ssa_copies (void);
+#include "langhooks.h"
/* The following routines implement the SSA copy renaming phase.
Each copy is examined to determine if it is possible to rename the base
variable of one of the operands to the same variable as the other operand.
- ie.
+ i.e.
T.3_5 = <blah>
a_1 = T.3_5
{
int p1, p2, p3;
tree root1, root2;
+ tree rep1, rep2;
var_ann_t ann1, ann2, ann3;
- bool gimp1, gimp2;
+ bool ign1, ign2, abnorm;
-#ifdef ENABLE_CHECKING
- if (TREE_CODE (var1) != SSA_NAME || TREE_CODE (var2) != SSA_NAME)
- abort ();
-#endif
+ gcc_assert (TREE_CODE (var1) == SSA_NAME);
+ gcc_assert (TREE_CODE (var2) == SSA_NAME);
register_ssa_partition (map, var1, false);
register_ssa_partition (map, var2, true);
fprintf (debug, "(P%d)", p2);
}
-#ifdef ENABLE_CHECKING
- if (p1 == NO_PARTITION || p2 == NO_PARTITION)
- abort ();
-#endif
+ gcc_assert (p1 != NO_PARTITION);
+ gcc_assert (p2 != NO_PARTITION);
- root1 = SSA_NAME_VAR (partition_to_var (map, p1));
- root2 = SSA_NAME_VAR (partition_to_var (map, p2));
-
- if (DECL_HARD_REGISTER (root1) || DECL_HARD_REGISTER (root2))
- {
- if (debug)
- {
- if (DECL_HARD_REGISTER (root1))
- print_generic_expr (debug, var1, TDF_SLIM);
- else
- print_generic_expr (debug, var2, TDF_SLIM);
- fprintf (debug, " is a hardware register. No Coalescing.\n");
- }
- return;
- }
+ rep1 = partition_to_var (map, p1);
+ rep2 = partition_to_var (map, p2);
+ root1 = SSA_NAME_VAR (rep1);
+ root2 = SSA_NAME_VAR (rep2);
ann1 = var_ann (root1);
ann2 = var_ann (root2);
return;
}
+ /* Don't coalesce if one of the variables occurs in an abnormal PHI. */
+ abnorm = (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rep1)
+ || SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rep2));
+ if (abnorm)
+ {
+ if (debug)
+ fprintf (debug, " : Abnormal PHI barrier. No coalesce.\n");
+ return;
+ }
+
/* Partitions already have the same root, simply merge them. */
if (root1 == root2)
{
return;
}
- gimp1 = is_gimple_tmp_var (root1);
- gimp2 = is_gimple_tmp_var (root2);
+ ign1 = TREE_CODE (root1) == VAR_DECL && DECL_IGNORED_P (root1);
+ ign2 = TREE_CODE (root2) == VAR_DECL && DECL_IGNORED_P (root2);
/* Never attempt to coalesce 2 user variables unless one is an inline
variable. */
- if (!gimp1 && !gimp2)
+ if (!ign1 && !ign2)
{
if (DECL_FROM_INLINE (root2))
- gimp2 = true;
- else
- if (DECL_FROM_INLINE (root1))
- gimp1 = true;
- else
- {
- if (debug)
- fprintf (debug, " : 2 different USER vars. No coalesce.\n");
- return;
- }
+ ign2 = true;
+ else if (DECL_FROM_INLINE (root1))
+ ign1 = true;
+ else
+ {
+ if (debug)
+ fprintf (debug, " : 2 different USER vars. No coalesce.\n");
+ return;
+ }
}
-
/* Don't coalesce if there are two different memory tags. */
- if (ann1->type_mem_tag && ann2->type_mem_tag
- && ann1->type_mem_tag != ann2->type_mem_tag)
+ if (ann1->symbol_mem_tag
+ && ann2->symbol_mem_tag
+ && ann1->symbol_mem_tag != ann2->symbol_mem_tag)
{
if (debug)
fprintf (debug, " : 2 memory tags. No coalesce.\n");
}
else
{
- gimp2 = true;
- gimp1 = false;
+ ign2 = true;
+ ign1 = false;
}
}
- else
- if (default_def (root2))
- {
- gimp1 = true;
- gimp2 = false;
- }
+ else if (default_def (root2))
+ {
+ ign1 = true;
+ ign2 = false;
+ }
+
+ /* Don't coalesce if the two variables aren't type compatible. */
+ if (!lang_hooks.types_compatible_p (TREE_TYPE (root1), TREE_TYPE (root2)))
+ {
+ if (debug)
+ fprintf (debug, " : Incompatible types. No coalesce.\n");
+ return;
+ }
+
+ /* Don't coalesce if the aliasing sets of the types are different. */
+ if (POINTER_TYPE_P (TREE_TYPE (root1))
+ && POINTER_TYPE_P (TREE_TYPE (root2))
+ && get_alias_set (TREE_TYPE (TREE_TYPE (root1)))
+ != get_alias_set (TREE_TYPE (TREE_TYPE (root2))))
+ {
+ if (debug)
+ fprintf (debug, " : 2 different aliasing sets. No coalesce.\n");
+ return;
+ }
+
/* Merge the two partitions. */
p3 = partition_union (map->var_partition, p1, p2);
/* Set the root variable of the partition to the better choice, if there is
one. */
- if (!gimp2)
- SSA_NAME_VAR (partition_to_var (map, p3)) = root2;
- else
- if (!gimp1)
- SSA_NAME_VAR (partition_to_var (map, p3)) = root1;
+ if (!ign2)
+ replace_ssa_name_symbol (partition_to_var (map, p3), root2);
+ else if (!ign1)
+ replace_ssa_name_symbol (partition_to_var (map, p3), root1);
/* Update the various flag widgitry of the current base representative. */
ann3 = var_ann (SSA_NAME_VAR (partition_to_var (map, p3)));
- if (ann1->type_mem_tag)
- ann3->type_mem_tag = ann1->type_mem_tag;
+ if (ann1->symbol_mem_tag)
+ ann3->symbol_mem_tag = ann1->symbol_mem_tag;
else
- ann3->type_mem_tag = ann2->type_mem_tag;
+ ann3->symbol_mem_tag = ann2->symbol_mem_tag;
if (debug)
{
then cause the SSA->normal pass to attempt to coalesce them all to the same
variable. */
-void
+static unsigned int
rename_ssa_copies (void)
{
var_map map;
else
debug = NULL;
- map = init_var_map (highest_ssa_version + 1);
+ map = init_var_map (num_ssa_names + 1);
FOR_EACH_BB (bb)
{
tree lhs = TREE_OPERAND (stmt, 0);
tree rhs = TREE_OPERAND (stmt, 1);
- if (TREE_CODE (lhs) == SSA_NAME
- && !has_hidden_use (SSA_NAME_VAR (lhs))
- && TREE_CODE (rhs) == SSA_NAME)
+ if (TREE_CODE (lhs) == SSA_NAME && TREE_CODE (rhs) == SSA_NAME)
copy_rename_partition_coalesce (map, lhs, rhs, debug);
}
}
FOR_EACH_BB (bb)
{
/* Treat PHI nodes as copies between the result and each argument. */
- for (phi = phi_nodes (bb); phi; phi = TREE_CHAIN (phi))
+ for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
{
int i;
tree res = PHI_RESULT (phi);
- /* Do not process virtual SSA_NAMES or variables which have
- hidden uses. */
- if (!is_gimple_reg (SSA_NAME_VAR (res))
- || has_hidden_use (SSA_NAME_VAR (res)))
+ /* Do not process virtual SSA_NAMES. */
+ if (!is_gimple_reg (SSA_NAME_VAR (res)))
continue;
for (i = 0; i < PHI_NUM_ARGS (phi); i++)
/* Now one more pass to make all elements of a partition share the same
root variable. */
- for (x = 1; x <= highest_ssa_version; x++)
+ for (x = 1; x <= num_ssa_names; x++)
{
part_var = partition_to_var (map, x);
if (!part_var)
fprintf (debug, "\n");
}
}
- SSA_NAME_VAR (var) = SSA_NAME_VAR (part_var);
+ replace_ssa_name_symbol (var, SSA_NAME_VAR (part_var));
}
delete_var_map (map);
+ return 0;
}
/* Return true if copy rename is to be performed. */
NULL, /* next */
0, /* static_pass_number */
TV_TREE_COPY_RENAME, /* tv_id */
- PROP_cfg | PROP_ssa, /* properties_required */
+ PROP_cfg | PROP_ssa | PROP_alias, /* properties_required */
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
- TODO_dump_func | TODO_verify_ssa /* todo_flags_finish */
+ TODO_dump_func | TODO_verify_ssa, /* todo_flags_finish */
+ 0 /* letter */
};