mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-25 01:11:10 +08:00
var-tracking.c (struct variable_def): Added field refcount.
PR/14362 * var-tracking.c (struct variable_def): Added field refcount. (variable_htab_free): Decrease the refcount and delete variable only if there are no more references. (unshare_variable): New function. (vars_copy_1): Increase refcount instead of copying the variable. (variable_union): Share the variables where possible, unshare the variables if needed. (variable_different_p): Return false if var1 and var2 are the same structure. (variable_was_changed): Init the refcount of new variable. (set_frame_base_location): Unshare variable if needed. (set_variable_part): Init the refcount of new variable. Unshare the variables if needed. (delete_variable_part): Unshare the variables if needed. (emit_notes_for_differences_1): Init the refcount of new variable. (vt_add_function_parameters): Do not add function parameters to IN set of ENTRY_BLOCK_PTR because it is unused anyway. (vt_initialize): Do not add frame_base_decl to IN set of ENTRY_BLOCK_PTR because it is unused anyway. From-SVN: r79307
This commit is contained in:
parent
f2bd98d4c5
commit
81f2eadbed
@ -1,3 +1,26 @@
|
||||
2004-03-11 Josef Zlomek <zlomekj@suse.cz>
|
||||
|
||||
PR/14362
|
||||
* var-tracking.c (struct variable_def): Added field refcount.
|
||||
(variable_htab_free): Decrease the refcount and delete variable
|
||||
only if there are no more references.
|
||||
(unshare_variable): New function.
|
||||
(vars_copy_1): Increase refcount instead of copying the variable.
|
||||
(variable_union): Share the variables where possible, unshare
|
||||
the variables if needed.
|
||||
(variable_different_p): Return false if var1 and var2 are
|
||||
the same structure.
|
||||
(variable_was_changed): Init the refcount of new variable.
|
||||
(set_frame_base_location): Unshare variable if needed.
|
||||
(set_variable_part): Init the refcount of new variable.
|
||||
Unshare the variables if needed.
|
||||
(delete_variable_part): Unshare the variables if needed.
|
||||
(emit_notes_for_differences_1): Init the refcount of new variable.
|
||||
(vt_add_function_parameters): Do not add function parameters to
|
||||
IN set of ENTRY_BLOCK_PTR because it is unused anyway.
|
||||
(vt_initialize): Do not add frame_base_decl to IN set of
|
||||
ENTRY_BLOCK_PTR because it is unused anyway.
|
||||
|
||||
2004-03-11 Josef Zlomek <zlomekj@suse.cz>
|
||||
|
||||
* var-tracking.c (vars_copy_1): Cleanup and speedup chain operations.
|
||||
|
@ -233,6 +233,9 @@ typedef struct variable_def
|
||||
/* The declaration of the variable. */
|
||||
tree decl;
|
||||
|
||||
/* Reference count. */
|
||||
int refcount;
|
||||
|
||||
/* Number of variable parts. */
|
||||
int n_var_parts;
|
||||
|
||||
@ -285,6 +288,7 @@ static void attrs_list_copy (attrs *, attrs);
|
||||
static void attrs_list_union (attrs *, attrs);
|
||||
|
||||
static void vars_clear (htab_t);
|
||||
static variable unshare_variable (dataflow_set *set, variable var);
|
||||
static int vars_copy_1 (void **, void *);
|
||||
static void vars_copy (htab_t, htab_t);
|
||||
static void var_reg_delete_and_set (dataflow_set *, rtx);
|
||||
@ -629,6 +633,15 @@ variable_htab_free (void *elem)
|
||||
variable var = (variable) elem;
|
||||
location_chain node, next;
|
||||
|
||||
#ifdef ENABLE_CHECKING
|
||||
if (var->refcount <= 0)
|
||||
abort ();
|
||||
#endif
|
||||
|
||||
var->refcount--;
|
||||
if (var->refcount > 0)
|
||||
return;
|
||||
|
||||
for (i = 0; i < var->n_var_parts; i++)
|
||||
{
|
||||
for (node = var->var_part[i].loc_chain; node; node = next)
|
||||
@ -732,32 +745,29 @@ vars_clear (htab_t vars)
|
||||
htab_empty (vars);
|
||||
}
|
||||
|
||||
/* Copy one variable from *SLOT to hash table DATA. */
|
||||
/* Return a copy of a variable VAR and insert it to dataflow set SET. */
|
||||
|
||||
static int
|
||||
vars_copy_1 (void **slot, void *data)
|
||||
static variable
|
||||
unshare_variable (dataflow_set *set, variable var)
|
||||
{
|
||||
htab_t dst = (htab_t) data;
|
||||
variable src, *dstp, var;
|
||||
void **slot;
|
||||
variable new_var;
|
||||
int i;
|
||||
|
||||
src = *(variable *) slot;
|
||||
dstp = (variable *) htab_find_slot_with_hash (dst, src->decl,
|
||||
VARIABLE_HASH_VAL (src->decl),
|
||||
INSERT);
|
||||
var = pool_alloc (var_pool);
|
||||
var->decl = src->decl;
|
||||
var->n_var_parts = src->n_var_parts;
|
||||
*dstp = (void *) var;
|
||||
new_var = pool_alloc (var_pool);
|
||||
new_var->decl = var->decl;
|
||||
new_var->refcount = 1;
|
||||
var->refcount--;
|
||||
new_var->n_var_parts = var->n_var_parts;
|
||||
|
||||
for (i = 0; i < var->n_var_parts; i++)
|
||||
{
|
||||
location_chain node;
|
||||
location_chain *nextp;
|
||||
|
||||
var->var_part[i].offset = src->var_part[i].offset;
|
||||
nextp = &var->var_part[i].loc_chain;
|
||||
for (node = src->var_part[i].loc_chain; node; node = node->next)
|
||||
new_var->var_part[i].offset = var->var_part[i].offset;
|
||||
nextp = &new_var->var_part[i].loc_chain;
|
||||
for (node = var->var_part[i].loc_chain; node; node = node->next)
|
||||
{
|
||||
location_chain new_lc;
|
||||
|
||||
@ -771,12 +781,36 @@ vars_copy_1 (void **slot, void *data)
|
||||
|
||||
/* We are at the basic block boundary when copying variable description
|
||||
so set the CUR_LOC to be the first element of the chain. */
|
||||
if (var->var_part[i].loc_chain)
|
||||
var->var_part[i].cur_loc = var->var_part[i].loc_chain->loc;
|
||||
if (new_var->var_part[i].loc_chain)
|
||||
new_var->var_part[i].cur_loc = new_var->var_part[i].loc_chain->loc;
|
||||
else
|
||||
var->var_part[i].cur_loc = NULL;
|
||||
new_var->var_part[i].cur_loc = NULL;
|
||||
}
|
||||
|
||||
slot = htab_find_slot_with_hash (set->vars, new_var->decl,
|
||||
VARIABLE_HASH_VAL (new_var->decl),
|
||||
INSERT);
|
||||
*slot = new_var;
|
||||
return new_var;
|
||||
}
|
||||
|
||||
/* Add a variable from *SLOT to hash table DATA and increase its reference
|
||||
count. */
|
||||
|
||||
static int
|
||||
vars_copy_1 (void **slot, void *data)
|
||||
{
|
||||
htab_t dst = (htab_t) data;
|
||||
variable src, *dstp;
|
||||
|
||||
src = *(variable *) slot;
|
||||
src->refcount++;
|
||||
|
||||
dstp = (variable *) htab_find_slot_with_hash (dst, src->decl,
|
||||
VARIABLE_HASH_VAL (src->decl),
|
||||
INSERT);
|
||||
*dstp = src;
|
||||
|
||||
/* Continue traversing the hash table. */
|
||||
return 1;
|
||||
}
|
||||
@ -972,9 +1006,37 @@ variable_union (void **slot, void *data)
|
||||
INSERT);
|
||||
if (!*dstp)
|
||||
{
|
||||
*dstp = dst = pool_alloc (var_pool);
|
||||
dst->decl = src->decl;
|
||||
dst->n_var_parts = 0;
|
||||
src->refcount++;
|
||||
|
||||
/* If CUR_LOC of some variable part is not the first element of
|
||||
the location chain we are going to change it so we have to make
|
||||
a copy of the variable. */
|
||||
for (k = 0; k < src->n_var_parts; k++)
|
||||
{
|
||||
if (src->var_part[k].loc_chain)
|
||||
{
|
||||
#ifdef ENABLE_CHECKING
|
||||
if (src->var_part[k].cur_loc == NULL)
|
||||
abort ();
|
||||
#endif
|
||||
if (src->var_part[k].cur_loc != src->var_part[k].loc_chain->loc)
|
||||
break;
|
||||
}
|
||||
#ifdef ENABLE_CHECKING
|
||||
else
|
||||
{
|
||||
if (src->var_part[k].cur_loc != NULL)
|
||||
abort ();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (k < src->n_var_parts)
|
||||
unshare_variable (set, src);
|
||||
else
|
||||
*dstp = src;
|
||||
|
||||
/* Continue traversing the hash table. */
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
dst = *dstp;
|
||||
@ -998,10 +1060,8 @@ variable_union (void **slot, void *data)
|
||||
else
|
||||
j++;
|
||||
}
|
||||
if (i < src->n_var_parts)
|
||||
k += src->n_var_parts - i;
|
||||
if (j < dst->n_var_parts)
|
||||
k += dst->n_var_parts - j;
|
||||
k += src->n_var_parts - i;
|
||||
k += dst->n_var_parts - j;
|
||||
#ifdef ENABLE_CHECKING
|
||||
/* We track only variables whose size is <= MAX_VAR_PARTS bytes
|
||||
thus there are at most MAX_VAR_PARTS different offsets. */
|
||||
@ -1009,13 +1069,16 @@ variable_union (void **slot, void *data)
|
||||
abort ();
|
||||
#endif
|
||||
|
||||
if (dst->refcount > 1 && dst->n_var_parts != k)
|
||||
dst = unshare_variable (set, dst);
|
||||
|
||||
i = src->n_var_parts - 1;
|
||||
j = dst->n_var_parts - 1;
|
||||
dst->n_var_parts = k;
|
||||
|
||||
for (k--; k >= 0; k--)
|
||||
{
|
||||
location_chain node;
|
||||
location_chain node, node2;
|
||||
|
||||
if (i >= 0 && j >= 0
|
||||
&& src->var_part[i].offset == dst->var_part[j].offset)
|
||||
@ -1026,7 +1089,26 @@ variable_union (void **slot, void *data)
|
||||
int dst_l, src_l;
|
||||
int ii, jj, n;
|
||||
struct variable_union_info *vui;
|
||||
|
||||
|
||||
/* If DST is shared compare the location chains.
|
||||
If they are different we will modify the chain in DST with
|
||||
high probability so make a copy of DST. */
|
||||
if (dst->refcount > 1)
|
||||
{
|
||||
for (node = src->var_part[i].loc_chain,
|
||||
node2 = dst->var_part[j].loc_chain; node && node2;
|
||||
node = node->next, node2 = node2->next)
|
||||
{
|
||||
if (!((GET_CODE (node2->loc) == REG
|
||||
&& GET_CODE (node->loc) == REG
|
||||
&& REGNO (node2->loc) == REGNO (node->loc))
|
||||
|| rtx_equal_p (node2->loc, node->loc)))
|
||||
break;
|
||||
}
|
||||
if (node || node2)
|
||||
dst = unshare_variable (set, dst);
|
||||
}
|
||||
|
||||
src_l = 0;
|
||||
for (node = src->var_part[i].loc_chain; node; node = node->next)
|
||||
src_l++;
|
||||
@ -1187,6 +1269,9 @@ variable_different_p (variable var1, variable var2)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (var1 == var2)
|
||||
return false;
|
||||
|
||||
if (var1->n_var_parts != var2->n_var_parts)
|
||||
return true;
|
||||
|
||||
@ -1791,6 +1876,7 @@ variable_was_changed (variable var, htab_t htab)
|
||||
|
||||
empty_var = pool_alloc (var_pool);
|
||||
empty_var->decl = var->decl;
|
||||
empty_var->refcount = 1;
|
||||
empty_var->n_var_parts = 0;
|
||||
*slot = empty_var;
|
||||
|
||||
@ -1843,7 +1929,12 @@ set_frame_base_location (dataflow_set *set, rtx loc)
|
||||
abort ();
|
||||
#endif
|
||||
|
||||
/* If frame_base_decl is shared unshare it first. */
|
||||
if (var->refcount > 1)
|
||||
var = unshare_variable (set, var);
|
||||
|
||||
var->var_part[0].loc_chain->loc = loc;
|
||||
var->var_part[0].cur_loc = loc;
|
||||
variable_was_changed (var, set->vars);
|
||||
}
|
||||
|
||||
@ -1867,6 +1958,7 @@ set_variable_part (dataflow_set *set, rtx loc, tree decl, HOST_WIDE_INT offset)
|
||||
/* Create new variable information. */
|
||||
var = pool_alloc (var_pool);
|
||||
var->decl = decl;
|
||||
var->refcount = 1;
|
||||
var->n_var_parts = 1;
|
||||
var->var_part[0].offset = offset;
|
||||
var->var_part[0].loc_chain = NULL;
|
||||
@ -1891,9 +1983,33 @@ set_variable_part (dataflow_set *set, rtx loc, tree decl, HOST_WIDE_INT offset)
|
||||
}
|
||||
pos = low;
|
||||
|
||||
if (pos == var->n_var_parts || var->var_part[pos].offset != offset)
|
||||
if (pos < var->n_var_parts && var->var_part[pos].offset == offset)
|
||||
{
|
||||
/* We have not find the location part, new one will be created. */
|
||||
node = var->var_part[pos].loc_chain;
|
||||
|
||||
if (node
|
||||
&& ((GET_CODE (node->loc) == REG && GET_CODE (loc) == REG
|
||||
&& REGNO (node->loc) == REGNO (loc))
|
||||
|| rtx_equal_p (node->loc, loc)))
|
||||
{
|
||||
/* LOC is in the beginning of the chain so we have nothing
|
||||
to do. */
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We have to make a copy of a shared variable. */
|
||||
if (var->refcount > 1)
|
||||
var = unshare_variable (set, var);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We have not found the location part, new one will be created. */
|
||||
|
||||
/* We have to make a copy of the shared variable. */
|
||||
if (var->refcount > 1)
|
||||
var = unshare_variable (set, var);
|
||||
|
||||
#ifdef ENABLE_CHECKING
|
||||
/* We track only variables whose size is <= MAX_VAR_PARTS bytes
|
||||
@ -1914,7 +2030,7 @@ set_variable_part (dataflow_set *set, rtx loc, tree decl, HOST_WIDE_INT offset)
|
||||
}
|
||||
}
|
||||
|
||||
/* Delete the location from list. */
|
||||
/* Delete the location from the list. */
|
||||
nextp = &var->var_part[pos].loc_chain;
|
||||
for (node = var->var_part[pos].loc_chain; node; node = next)
|
||||
{
|
||||
@ -1981,6 +2097,23 @@ delete_variable_part (dataflow_set *set, rtx loc, tree decl,
|
||||
location_chain *nextp;
|
||||
bool changed;
|
||||
|
||||
if (var->refcount > 1)
|
||||
{
|
||||
/* If the variable contains the location part we have to
|
||||
make a copy of the variable. */
|
||||
for (node = var->var_part[pos].loc_chain; node;
|
||||
node = node->next)
|
||||
{
|
||||
if ((GET_CODE (node->loc) == REG && GET_CODE (loc) == REG
|
||||
&& REGNO (node->loc) == REGNO (loc))
|
||||
|| rtx_equal_p (node->loc, loc))
|
||||
{
|
||||
var = unshare_variable (set, var);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Delete the location part. */
|
||||
nextp = &var->var_part[pos].loc_chain;
|
||||
for (node = *nextp; node; node = next)
|
||||
@ -2149,6 +2282,7 @@ emit_notes_for_differences_1 (void **slot, void *data)
|
||||
|
||||
empty_var = pool_alloc (var_pool);
|
||||
empty_var->decl = old_var->decl;
|
||||
empty_var->refcount = 1;
|
||||
empty_var->n_var_parts = 0;
|
||||
variable_was_changed (empty_var, NULL);
|
||||
}
|
||||
@ -2357,7 +2491,7 @@ vt_add_function_parameters (void)
|
||||
rtx incoming = DECL_INCOMING_RTL (parm);
|
||||
tree decl;
|
||||
HOST_WIDE_INT offset;
|
||||
dataflow_set *in, *out;
|
||||
dataflow_set *out;
|
||||
|
||||
if (TREE_CODE (parm) != PARM_DECL)
|
||||
continue;
|
||||
@ -2386,7 +2520,6 @@ vt_add_function_parameters (void)
|
||||
incoming = eliminate_regs (incoming, 0, NULL_RTX);
|
||||
if (!frame_pointer_needed && GET_CODE (incoming) == MEM)
|
||||
incoming = adjust_stack_reference (incoming, -stack_adjust);
|
||||
in = &VTI (ENTRY_BLOCK_PTR)->in;
|
||||
out = &VTI (ENTRY_BLOCK_PTR)->out;
|
||||
|
||||
if (GET_CODE (incoming) == REG)
|
||||
@ -2395,16 +2528,12 @@ vt_add_function_parameters (void)
|
||||
if (REGNO (incoming) >= FIRST_PSEUDO_REGISTER)
|
||||
abort ();
|
||||
#endif
|
||||
attrs_list_insert (&in->regs[REGNO (incoming)],
|
||||
parm, offset, incoming);
|
||||
attrs_list_insert (&out->regs[REGNO (incoming)],
|
||||
parm, offset, incoming);
|
||||
set_variable_part (in, incoming, parm, offset);
|
||||
set_variable_part (out, incoming, parm, offset);
|
||||
}
|
||||
else if (GET_CODE (incoming) == MEM)
|
||||
{
|
||||
set_variable_part (in, incoming, parm, offset);
|
||||
set_variable_part (out, incoming, parm, offset);
|
||||
}
|
||||
}
|
||||
@ -2564,7 +2693,6 @@ vt_initialize (void)
|
||||
|
||||
/* Set its initial "location". */
|
||||
base = gen_rtx_MEM (Pmode, stack_pointer_rtx);
|
||||
set_variable_part (&VTI (ENTRY_BLOCK_PTR)->in, base, frame_base_decl, 0);
|
||||
set_variable_part (&VTI (ENTRY_BLOCK_PTR)->out, base, frame_base_decl, 0);
|
||||
}
|
||||
else
|
||||
|
Loading…
x
Reference in New Issue
Block a user