re PR middle-end/38474 (compile time explosion in dataflow_set_preserve_mem_locs at -O3)
PR middle-end/38474 * cfgexpand.c (add_alias_set_conflicts): Remove. (expand_used_vars): Don't call it. (aggregate_contains_union_type): Remove. * function.c (n_temp_slots_in_use): New static data. (make_slot_available, assign_stack_temp_for_type): Update it. (init_temp_slots): Zero it. (remove_unused_temp_slot_addresses): Use it for quicker removal. (remove_unused_temp_slot_addresses_1): Use htab_clear_slot. From-SVN: r188667
This commit is contained in:
parent
4c53d18336
commit
f8395d62c1
|
@ -1,3 +1,15 @@
|
|||
2012-06-15 Michael Matz <matz@suse.de>
|
||||
|
||||
PR middle-end/38474
|
||||
* cfgexpand.c (add_alias_set_conflicts): Remove.
|
||||
(expand_used_vars): Don't call it.
|
||||
(aggregate_contains_union_type): Remove.
|
||||
* function.c (n_temp_slots_in_use): New static data.
|
||||
(make_slot_available, assign_stack_temp_for_type): Update it.
|
||||
(init_temp_slots): Zero it.
|
||||
(remove_unused_temp_slot_addresses): Use it for quicker removal.
|
||||
(remove_unused_temp_slot_addresses_1): Use htab_clear_slot.
|
||||
|
||||
2012-06-15 Michael Matz <matz@suse.de>
|
||||
|
||||
* gimplify.c (gimplify_compound_literal_expr): Take gimple_test_f
|
||||
|
|
|
@ -329,70 +329,6 @@ stack_var_conflict_p (size_t x, size_t y)
|
|||
return bitmap_bit_p (a->conflicts, y);
|
||||
}
|
||||
|
||||
/* Returns true if TYPE is or contains a union type. */
|
||||
|
||||
static bool
|
||||
aggregate_contains_union_type (tree type)
|
||||
{
|
||||
tree field;
|
||||
|
||||
if (TREE_CODE (type) == UNION_TYPE
|
||||
|| TREE_CODE (type) == QUAL_UNION_TYPE)
|
||||
return true;
|
||||
if (TREE_CODE (type) == ARRAY_TYPE)
|
||||
return aggregate_contains_union_type (TREE_TYPE (type));
|
||||
if (TREE_CODE (type) != RECORD_TYPE)
|
||||
return false;
|
||||
|
||||
for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
|
||||
if (TREE_CODE (field) == FIELD_DECL)
|
||||
if (aggregate_contains_union_type (TREE_TYPE (field)))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* A subroutine of expand_used_vars. If two variables X and Y have alias
|
||||
sets that do not conflict, then do add a conflict for these variables
|
||||
in the interference graph. We also need to make sure to add conflicts
|
||||
for union containing structures. Else RTL alias analysis comes along
|
||||
and due to type based aliasing rules decides that for two overlapping
|
||||
union temporaries { short s; int i; } accesses to the same mem through
|
||||
different types may not alias and happily reorders stores across
|
||||
life-time boundaries of the temporaries (See PR25654). */
|
||||
|
||||
static void
|
||||
add_alias_set_conflicts (void)
|
||||
{
|
||||
size_t i, j, n = stack_vars_num;
|
||||
|
||||
for (i = 0; i < n; ++i)
|
||||
{
|
||||
tree type_i = TREE_TYPE (stack_vars[i].decl);
|
||||
bool aggr_i = AGGREGATE_TYPE_P (type_i);
|
||||
bool contains_union;
|
||||
|
||||
contains_union = aggregate_contains_union_type (type_i);
|
||||
for (j = 0; j < i; ++j)
|
||||
{
|
||||
tree type_j = TREE_TYPE (stack_vars[j].decl);
|
||||
bool aggr_j = AGGREGATE_TYPE_P (type_j);
|
||||
if (aggr_i != aggr_j
|
||||
/* Either the objects conflict by means of type based
|
||||
aliasing rules, or we need to add a conflict. */
|
||||
|| !objects_must_conflict_p (type_i, type_j)
|
||||
/* In case the types do not conflict ensure that access
|
||||
to elements will conflict. In case of unions we have
|
||||
to be careful as type based aliasing rules may say
|
||||
access to the same memory does not conflict. So play
|
||||
safe and add a conflict in this case when
|
||||
-fstrict-aliasing is used. */
|
||||
|| (contains_union && flag_strict_aliasing))
|
||||
add_stack_var_conflict (i, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Callback for walk_stmt_ops. If OP is a decl touched by add_stack_var
|
||||
enter its partition number into bitmap DATA. */
|
||||
|
||||
|
@ -1625,10 +1561,6 @@ expand_used_vars (void)
|
|||
if (stack_vars_num > 0)
|
||||
{
|
||||
add_scope_conflicts ();
|
||||
/* Due to the way alias sets work, no variables with non-conflicting
|
||||
alias sets may be assigned the same address. Add conflicts to
|
||||
reflect this. */
|
||||
add_alias_set_conflicts ();
|
||||
|
||||
/* If stack protection is enabled, we don't share space between
|
||||
vulnerable data and non-vulnerable data. */
|
||||
|
|
|
@ -571,6 +571,7 @@ struct GTY(()) temp_slot {
|
|||
/* A table of addresses that represent a stack slot. The table is a mapping
|
||||
from address RTXen to a temp slot. */
|
||||
static GTY((param_is(struct temp_slot_address_entry))) htab_t temp_slot_address_table;
|
||||
static size_t n_temp_slots_in_use;
|
||||
|
||||
/* Entry for the above hash table. */
|
||||
struct GTY(()) temp_slot_address_entry {
|
||||
|
@ -647,6 +648,7 @@ make_slot_available (struct temp_slot *temp)
|
|||
insert_slot_to_list (temp, &avail_temp_slots);
|
||||
temp->in_use = 0;
|
||||
temp->level = -1;
|
||||
n_temp_slots_in_use--;
|
||||
}
|
||||
|
||||
/* Compute the hash value for an address -> temp slot mapping.
|
||||
|
@ -699,7 +701,7 @@ remove_unused_temp_slot_addresses_1 (void **slot, void *data ATTRIBUTE_UNUSED)
|
|||
const struct temp_slot_address_entry *t;
|
||||
t = (const struct temp_slot_address_entry *) *slot;
|
||||
if (! t->temp_slot->in_use)
|
||||
*slot = NULL;
|
||||
htab_clear_slot (temp_slot_address_table, slot);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -707,9 +709,13 @@ remove_unused_temp_slot_addresses_1 (void **slot, void *data ATTRIBUTE_UNUSED)
|
|||
static void
|
||||
remove_unused_temp_slot_addresses (void)
|
||||
{
|
||||
/* Use quicker clearing if there aren't any active temp slots. */
|
||||
if (n_temp_slots_in_use)
|
||||
htab_traverse (temp_slot_address_table,
|
||||
remove_unused_temp_slot_addresses_1,
|
||||
NULL);
|
||||
else
|
||||
htab_empty (temp_slot_address_table);
|
||||
}
|
||||
|
||||
/* Find the temp slot corresponding to the object at address X. */
|
||||
|
@ -901,6 +907,7 @@ assign_stack_temp_for_type (enum machine_mode mode, HOST_WIDE_INT size,
|
|||
p->in_use = 1;
|
||||
p->type = type;
|
||||
p->level = temp_slot_level;
|
||||
n_temp_slots_in_use++;
|
||||
|
||||
pp = temp_slots_at_level (p->level);
|
||||
insert_slot_to_list (p, pp);
|
||||
|
@ -1212,6 +1219,7 @@ init_temp_slots (void)
|
|||
avail_temp_slots = 0;
|
||||
used_temp_slots = 0;
|
||||
temp_slot_level = 0;
|
||||
n_temp_slots_in_use = 0;
|
||||
|
||||
/* Set up the table to map addresses to temp slots. */
|
||||
if (! temp_slot_address_table)
|
||||
|
@ -4496,7 +4504,6 @@ allocate_struct_function (tree fndecl, bool abstract_p)
|
|||
/* ??? This could be set on a per-function basis by the front-end
|
||||
but is this worth the hassle? */
|
||||
cfun->can_throw_non_call_exceptions = flag_non_call_exceptions;
|
||||
cfun->can_delete_dead_exceptions = flag_delete_dead_exceptions;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue