tree-ssa-copyrename.c [plain text]
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tm.h"
#include "tree.h"
#include "flags.h"
#include "basic-block.h"
#include "function.h"
#include "diagnostic.h"
#include "bitmap.h"
#include "tree-flow.h"
#include "tree-gimple.h"
#include "tree-inline.h"
#include "timevar.h"
#include "hashtab.h"
#include "tree-dump.h"
#include "tree-ssa-live.h"
#include "tree-pass.h"
#include "langhooks.h"
static void
copy_rename_partition_coalesce (var_map map, tree var1, tree var2, FILE *debug)
{
int p1, p2, p3;
tree root1, root2;
tree rep1, rep2;
var_ann_t ann1, ann2, ann3;
bool ign1, ign2, abnorm;
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);
p1 = partition_find (map->var_partition, SSA_NAME_VERSION (var1));
p2 = partition_find (map->var_partition, SSA_NAME_VERSION (var2));
if (debug)
{
fprintf (debug, "Try : ");
print_generic_expr (debug, var1, TDF_SLIM);
fprintf (debug, "(P%d) & ", p1);
print_generic_expr (debug, var2, TDF_SLIM);
fprintf (debug, "(P%d)", p2);
}
gcc_assert (p1 != NO_PARTITION);
gcc_assert (p2 != NO_PARTITION);
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);
if (p1 == p2)
{
if (debug)
fprintf (debug, " : Already coalesced.\n");
return;
}
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;
}
if (root1 == root2)
{
p1 = partition_union (map->var_partition, p1, p2);
if (debug)
fprintf (debug, " : Same root, coalesced --> P%d.\n", p1);
return;
}
if (TREE_CODE (root1) == PARM_DECL && TREE_CODE (root2) == PARM_DECL)
{
if (debug)
fprintf (debug, " : 2 different PARM_DECLS. No coalesce.\n");
return;
}
if ((TREE_CODE (root1) == RESULT_DECL) != (TREE_CODE (root2) == RESULT_DECL))
{
if (debug)
fprintf (debug, " : One root a RESULT_DECL. No coalesce.\n");
return;
}
ign1 = TREE_CODE (root1) == VAR_DECL && DECL_IGNORED_P (root1);
ign2 = TREE_CODE (root2) == VAR_DECL && DECL_IGNORED_P (root2);
if (!ign1 && !ign2)
{
if (DECL_FROM_INLINE (root2))
ign2 = true;
else if (DECL_FROM_INLINE (root1))
ign1 = true;
else
{
if (debug)
fprintf (debug, " : 2 different USER vars. No coalesce.\n");
return;
}
}
if (ann1->type_mem_tag && ann2->type_mem_tag
&& ann1->type_mem_tag != ann2->type_mem_tag)
{
if (debug)
fprintf (debug, " : 2 memory tags. No coalesce.\n");
return;
}
if (default_def (root1))
{
if (default_def (root2))
{
if (debug)
fprintf (debug, " : 2 default defs. No coalesce.\n");
return;
}
else
{
ign2 = true;
ign1 = false;
}
}
else if (default_def (root2))
{
ign1 = true;
ign2 = false;
}
if (!lang_hooks.types_compatible_p (TREE_TYPE (root1), TREE_TYPE (root2)))
{
if (debug)
fprintf (debug, " : Incompatible types. No coalesce.\n");
return;
}
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 alasing sets. No coalesce.\n");
return;
}
p3 = partition_union (map->var_partition, p1, p2);
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);
ann3 = var_ann (SSA_NAME_VAR (partition_to_var (map, p3)));
if (ann1->type_mem_tag)
ann3->type_mem_tag = ann1->type_mem_tag;
else
ann3->type_mem_tag = ann2->type_mem_tag;
if (debug)
{
fprintf (debug, " --> P%d ", p3);
print_generic_expr (debug, SSA_NAME_VAR (partition_to_var (map, p3)),
TDF_SLIM);
fprintf (debug, "\n");
}
}
static void
rename_ssa_copies (void)
{
var_map map;
basic_block bb;
block_stmt_iterator bsi;
tree phi, stmt, var, part_var;
unsigned x;
FILE *debug;
if (dump_file && (dump_flags & TDF_DETAILS))
debug = dump_file;
else
debug = NULL;
map = init_var_map (num_ssa_names + 1);
FOR_EACH_BB (bb)
{
for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
{
stmt = bsi_stmt (bsi);
if (TREE_CODE (stmt) == MODIFY_EXPR)
{
tree lhs = TREE_OPERAND (stmt, 0);
tree rhs = TREE_OPERAND (stmt, 1);
if (TREE_CODE (lhs) == SSA_NAME && TREE_CODE (rhs) == SSA_NAME)
copy_rename_partition_coalesce (map, lhs, rhs, debug);
}
}
}
FOR_EACH_BB (bb)
{
for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
{
int i;
tree res = PHI_RESULT (phi);
if (!is_gimple_reg (SSA_NAME_VAR (res)))
continue;
for (i = 0; i < PHI_NUM_ARGS (phi); i++)
{
tree arg = PHI_ARG_DEF (phi, i);
if (TREE_CODE (arg) == SSA_NAME)
copy_rename_partition_coalesce (map, res, arg, debug);
}
}
}
if (debug)
dump_var_map (debug, map);
for (x = 1; x <= num_ssa_names; x++)
{
part_var = partition_to_var (map, x);
if (!part_var)
continue;
var = map->partition_to_var[x];
if (debug)
{
if (SSA_NAME_VAR (var) != SSA_NAME_VAR (part_var))
{
fprintf (debug, "Coalesced ");
print_generic_expr (debug, var, TDF_SLIM);
fprintf (debug, " to ");
print_generic_expr (debug, part_var, TDF_SLIM);
fprintf (debug, "\n");
}
}
replace_ssa_name_symbol (var, SSA_NAME_VAR (part_var));
}
delete_var_map (map);
}
static bool
gate_copyrename (void)
{
return flag_tree_copyrename != 0;
}
struct tree_opt_pass pass_rename_ssa_copies =
{
"copyrename",
gate_copyrename,
rename_ssa_copies,
NULL,
NULL,
0,
TV_TREE_COPY_RENAME,
PROP_cfg | PROP_ssa | PROP_alias,
0,
0,
0,
TODO_dump_func | TODO_verify_ssa,
0
};