Compiler crash in cselib_invalidate_regno() patch
Bernd Schmidt
bernds@balti.cygnus.co.uk
Sat Apr 29 08:10:00 GMT 2000
On Tue, 25 Apr 2000, Toshiyasu Morita wrote:
> Here is a patch which fixes the problem I posted earlier in gcc-bugs.
> With this patch, my file compiles correctly - please review for correctness.
This is not the right fix. It just hides the real problem.
> ! /* For an rtx like:
> !
> ! (insn 867 865 869 (parallel[
> ! (set (reg:SF 24 fr0)
> ! (reg:SF 24 fr0))
> ! (use (reg/v:PSI 48 fpscr))
> ! (clobber (scratch:SI))
> ! ] ) 153 {movsf_ie} (insn_list 865 (nil))
> ! (nil))
> !
> ! ... unchain_one_elt_list can set *l = 0 (e.g. v->locs = 0),
> ! so we must check for this case here. */
> !
> ! if (!*l)
> ! continue;
unchain_one_elt_list can never touch the locs field, so this can't be correct.
I'm currently testing the patch below. The real problem is that we're getting
confused about which values are useless. More specifically, in
cselib_record_sets some values may temporarily lose all their locations due to
the note_stores call, and later become useful again because of the call to
cselib_record_set. Unfortunately, once they have been in the "useless" state,
there is nothing that prevents them from getting reclaimed. The result is a
memory corruption bug.
OK to install if it bootstraps?
Bernd
* simplify-rtx.c (check_value_useless): Delete function.
(discard_useless_locs): Don't call it; manage N_USELES_VALUES counter
by hand.
(cselib_invalidate_regno): Likewise.
(cselib_invalidate_mem_1): Likewise.
(references_value_p): Recognize useless values by the fact that they
have no locations.
(discard_useless_values): Likewise.
(add_mem_for_addr): This may turn a useless value into a useful one.
(cselib_record_set): Likewise.
Index: simplify-rtx.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/simplify-rtx.c,v
retrieving revision 1.13
diff -c -p -r1.13 simplify-rtx.c
*** simplify-rtx.c 2000/04/18 20:42:00 1.13
--- simplify-rtx.c 2000/04/29 14:52:55
*************** static void unchain_one_value PARAMS ((
*** 106,112 ****
static void unchain_one_elt_list PARAMS ((struct elt_list **));
static void unchain_one_elt_loc_list PARAMS ((struct elt_loc_list **));
static void clear_table PARAMS ((void));
- static int check_value_useless PARAMS ((cselib_val *));
static int discard_useless_locs PARAMS ((void **, void *));
static int discard_useless_values PARAMS ((void **, void *));
static void remove_useless_values PARAMS ((void));
--- 106,111 ----
*************** get_value_hash (entry)
*** 2183,2208 ****
return v->value;
}
- /* If there are no more locations that hold a value, the value has become
- useless. See whether that is the case for V. Return 1 if this has
- just become useless. */
-
- static int
- check_value_useless (v)
- cselib_val *v;
- {
- if (v->locs != 0)
- return 0;
-
- if (v->value == 0)
- return 0;
-
- /* This is a marker to indicate that the value will be reclaimed. */
- v->value = 0;
- n_useless_values++;
- return 1;
- }
-
/* Return true if X contains a VALUE rtx. If ONLY_USELESS is set, we
only return true for values which point to a cselib_val whose value
element has been set to zero, which implies the cselib_val will be
--- 2182,2187 ----
*************** references_value_p (x, only_useless)
*** 2218,2224 ****
int i, j;
if (GET_CODE (x) == VALUE
! && (! only_useless || CSELIB_VAL_PTR (x)->value == 0))
return 1;
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
--- 2197,2203 ----
int i, j;
if (GET_CODE (x) == VALUE
! && (! only_useless || CSELIB_VAL_PTR (x)->locs == 0))
return 1;
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
*************** discard_useless_locs (x, info)
*** 2245,2250 ****
--- 2224,2230 ----
{
cselib_val *v = (cselib_val *)*x;
struct elt_loc_list **p = &v->locs;
+ int had_locs = v->locs != 0;
while (*p)
{
*************** discard_useless_locs (x, info)
*** 2254,2262 ****
p = &(*p)->next;
}
! if (check_value_useless (v))
! values_became_useless = 1;
!
return 1;
}
--- 2234,2244 ----
p = &(*p)->next;
}
! if (had_locs && v->locs == 0)
! {
! n_useless_values++;
! values_became_useless = 1;
! }
return 1;
}
*************** discard_useless_values (x, info)
*** 2269,2275 ****
{
cselib_val *v = (cselib_val *)*x;
! if (v->value == 0)
{
htab_clear_slot (hash_table, x);
unchain_one_value (v);
--- 2251,2257 ----
{
cselib_val *v = (cselib_val *)*x;
! if (v->locs == 0)
{
htab_clear_slot (hash_table, x);
unchain_one_value (v);
*************** add_mem_for_addr (addr_elt, mem_elt, x)
*** 2627,2632 ****
--- 2609,2617 ----
RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (x);
MEM_COPY_ATTRIBUTES (new, x);
+ if (mem_elt->locs == 0)
+ n_useless_values--;
+
mem_elt->locs = new_elt_loc_list (mem_elt->locs, new);
}
*************** cselib_invalidate_regno (regno, mode)
*** 2877,2884 ****
break;
}
}
!
! check_value_useless (v);
}
}
}
--- 2862,2869 ----
break;
}
}
! if (v->locs == 0)
! n_useless_values++;
}
}
}
*************** cselib_invalidate_mem_1 (slot, info)
*** 2951,2956 ****
--- 2936,2942 ----
cselib_val *v = (cselib_val *) *slot;
rtx mem_rtx = (rtx) info;
struct elt_loc_list **p = &v->locs;
+ int had_locs = v->locs != 0;
while (*p)
{
*************** cselib_invalidate_mem_1 (slot, info)
*** 2985,2992 ****
unchain_one_elt_loc_list (p);
}
- check_value_useless (v);
return 1;
}
--- 2971,2980 ----
unchain_one_elt_loc_list (p);
}
+
+ if (had_locs && v->locs == 0)
+ n_useless_values++;
return 1;
}
*************** cselib_record_set (dest, src_elt, dest_a
*** 3045,3050 ****
--- 3033,3040 ----
if (dreg >= 0)
{
REG_VALUES (dreg) = new_elt_list (REG_VALUES (dreg), src_elt);
+ if (src_elt->locs == 0)
+ n_useless_values--;
src_elt->locs = new_elt_loc_list (src_elt->locs, dest);
}
else if (GET_CODE (dest) == MEM && dest_addr_elt != 0)
More information about the Gcc-patches
mailing list