/* Struct-reorg optimization.
- Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
Contributed by Olga Golovanevsky <olga@il.ibm.com>
(Initial version of this code was developed
by Caroline Tice and Mostafa Hagog.)
#include "target.h"
#include "cgraph.h"
#include "diagnostic.h"
+#include "tree-pretty-print.h"
+#include "gimple-pretty-print.h"
#include "timevar.h"
#include "params.h"
#include "fibheap.h"
finalize_stmt (stmt);
}
+/* This function returns true if two fields FIELD1 and FIELD2 are
+ semantically equal, and false otherwise. */
+
+static bool
+compare_fields (tree field1, tree field2)
+{
+ if (DECL_NAME (field1) && DECL_NAME (field2))
+ {
+ const char *name1 = IDENTIFIER_POINTER (DECL_NAME (field1));
+ const char *name2 = IDENTIFIER_POINTER (DECL_NAME (field2));
+
+ gcc_assert (name1 && name2);
+
+ if (strcmp (name1, name2))
+ return false;
+
+ }
+ else if (DECL_NAME (field1) || DECL_NAME (field2))
+ return false;
+
+ if (!is_equal_types (TREE_TYPE (field1), TREE_TYPE (field2)))
+ return false;
+
+ return true;
+}
+
/* Given structure type SRT_TYPE and field FIELD,
this function is looking for a field with the same name
and type as FIELD in STR_TYPE. It returns it if found,
for (str_field = TYPE_FIELDS (str_type); str_field;
str_field = TREE_CHAIN (str_field))
{
- const char *str_field_name;
- const char *field_name;
if (!DECL_NAME (str_field))
continue;
- str_field_name = IDENTIFIER_POINTER (DECL_NAME (str_field));
- field_name = IDENTIFIER_POINTER (DECL_NAME (field));
-
- gcc_assert (str_field_name);
- gcc_assert (field_name);
-
- if (!strcmp (str_field_name, field_name))
- {
- /* Check field types. */
- if (is_equal_types (TREE_TYPE (str_field), TREE_TYPE (field)))
- return str_field;
- }
+ if (compare_fields (field, str_field))
+ return str_field;
}
return NULL_TREE;
static inline struct field_access_site *
make_field_acc_node (void)
{
- int size = sizeof (struct field_access_site);
-
- return (struct field_access_site *) xcalloc (1, size);
+ return XCNEW (struct field_access_site);
}
/* This function returns the structure field access, defined by STMT,
{
void **slot;
- acc = (struct access_site *) xmalloc (sizeof (struct access_site));
+ acc = XNEW (struct access_site);
acc->stmt = stmt;
- acc->vars = VEC_alloc (tree, heap, 10);
+ if (!is_gimple_debug (stmt))
+ acc->vars = VEC_alloc (tree, heap, 10);
+ else
+ acc->vars = NULL;
slot = htab_find_slot_with_hash (accs, stmt,
htab_hash_pointer (stmt), INSERT);
*slot = acc;
-
}
- VEC_safe_push (tree, heap, acc->vars, var);
+ if (!is_gimple_debug (stmt))
+ VEC_safe_push (tree, heap, acc->vars, var);
}
/* This function adds NEW_DECL to function
is_in_new_vars_htab (tree decl, htab_t new_vars_htab)
{
return (new_var) htab_find_with_hash (new_vars_htab, decl,
- htab_hash_pointer (decl));
+ DECL_UID (decl));
}
/* Given original variable ORIG_VAR, this function returns
create_new_stmts_for_cond_expr (stmt);
break;
+ case GIMPLE_DEBUG:
+ /* It is very hard to maintain usable debug info after struct peeling,
+ for now just reset all debug stmts referencing objects that have
+ been peeled. */
+ gimple_debug_bind_reset_value (stmt);
+ update_stmt (stmt);
+ break;
+
default:
create_new_stmts_for_general_acc (acc, str);
}
name1 = get_type_name (type1);
name2 = get_type_name (type2);
- if (name1 && name2 && !strcmp (name1, name2))
- return true;
-
- if (name1 && name2 && strcmp (name1, name2))
- return false;
+ if (name1 && name2)
+ return strcmp (name1, name2) == 0;
switch (TREE_CODE (type1))
{
case QUAL_UNION_TYPE:
case ENUMERAL_TYPE:
{
- tree field1;
+ tree field1, field2;
+
/* Compare fields of structure. */
- for (field1 = TYPE_FIELDS (type1); field1;
- field1 = TREE_CHAIN (field1))
+ for (field1 = TYPE_FIELDS (type1), field2 = TYPE_FIELDS (type2);
+ field1 && field2;
+ field1 = TREE_CHAIN (field1), field2 = TREE_CHAIN (field2))
{
- tree field2 = find_field_in_struct_1 (type2, field1);
- if (!field2)
+ if (!compare_fields (field1, field2))
return false;
}
- return true;
+ if (field1 || field2)
+ return false;
+ else
+ return true;
}
break;
void **slot;
slot = htab_find_slot_with_hash (new_vars_htab, new_node->orig_var,
- htab_hash_pointer (new_node->orig_var),
+ DECL_UID (new_node->orig_var),
INSERT);
*slot = new_node;
}
{
new_var node;
- node = (new_var) xmalloc (sizeof (struct new_var_data));
+ node = XNEW (struct new_var_data);
node->orig_var = var;
node->new_vars = VEC_alloc (tree, heap, VEC_length (tree, str->new_types));
return node;
static hashval_t
new_var_hash (const void *x)
{
- return htab_hash_pointer (((const_new_var)x)->orig_var);
+ return DECL_UID (((const_new_var)x)->orig_var);
}
-/* This function returns nonzero if orig_var of new_var X is equal to Y. */
+/* This function returns nonzero if orig_var of new_var X
+ and tree Y have equal UIDs. */
static int
new_var_eq (const void *x, const void *y)
{
- return ((const_new_var)x)->orig_var == (const_tree)y;
+ if (DECL_P ((const_tree)y))
+ return DECL_UID (((const_new_var)x)->orig_var) == DECL_UID ((const_tree)y);
+ else
+ return 0;
}
/* This function check whether a structure type represented by STR
tree t = TYPE_FIELDS (struct_decl);
int idx = 0;
- list =
- (struct field_entry *) xmalloc (num_fields * sizeof (struct field_entry));
+ list = XNEWVEC (struct field_entry, num_fields);
for (idx = 0 ; t; t = TREE_CHAIN (t), idx++)
if (TREE_CODE (t) == FIELD_DECL)
if (i != VEC_length (structure, structures))
{
+ if (is_gimple_debug (stmt))
+ {
+ d_str str;
+
+ str = VEC_index (structure, structures, i);
+ add_access_to_acc_sites (stmt, NULL, str->accs);
+ *walk_subtrees = 0;
+ break;
+ }
if (dump_file)
{
fprintf (dump_file, "\nThe type ");
struct field_entry * field =
find_field_in_struct (str, field_decl);
+ if (is_gimple_debug (stmt))
+ {
+ add_access_to_acc_sites (stmt, NULL, str->accs);
+ *walk_subtrees = 0;
+ break;
+ }
+
if (field)
{
struct field_access_site *acc = make_field_acc_node ();
{
void **slot;
- fallocs = (fallocs_t)
- xmalloc (sizeof (struct func_alloc_sites));
+ fallocs = XNEW (struct func_alloc_sites);
fallocs->func = fn_decl;
fallocs->allocs = VEC_alloc (alloc_site_t, heap, 1);
slot = htab_find_slot_with_hash (alloc_sites, fn_decl,
static void
gen_cluster (sbitmap fields, d_str str)
{
- struct field_cluster *crr_cluster = NULL;
+ struct field_cluster *crr_cluster = XCNEW (struct field_cluster);
- crr_cluster =
- (struct field_cluster *) xcalloc (1, sizeof (struct field_cluster));
crr_cluster->sibling = str->struct_clustering;
str->struct_clustering = crr_cluster;
crr_cluster->fields_in_cluster = fields;
static void
peel_field (int i, d_str ds)
{
- struct field_cluster *crr_cluster = NULL;
+ struct field_cluster *crr_cluster = XCNEW (struct field_cluster);
- crr_cluster =
- (struct field_cluster *) xcalloc (1, sizeof (struct field_cluster));
crr_cluster->sibling = ds->struct_clustering;
ds->struct_clustering = crr_cluster;
crr_cluster->fields_in_cluster =
create_new_accesses_for_func ();
update_ssa (TODO_update_ssa);
cleanup_tree_cfg ();
+ cgraph_rebuild_references ();
/* Free auxiliary data representing local variables. */
free_new_vars_htab (new_local_vars);
struct cgraph_node *c_node;
struct cgraph_node *c_node2;
struct cgraph_edge *c_edge;
- tree fndecl;
tree fndecl2;
for (c_node = cgraph_nodes; c_node; c_node = c_node->next)
{
- fndecl = c_node->decl;
-
for (c_edge = c_node->callees; c_edge; c_edge = c_edge->next_callee)
{
c_node2 = c_edge->callee;