GCC build failed with your patch on 2000-11-09T01:35:00Z.
Richard Henderson
rth@redhat.com
Thu Nov 9 18:11:00 GMT 2000
On Thu, Nov 09, 2000 at 02:20:21AM +0000, GCC regression checker wrote:
> .../libio/outfloat.c: In function `_IO_outfloat':
> .../libio/outfloat.c:210: Internal compiler error in
> verify_local_live_at_start, at flow.c:2896
> Please submit a full bug report.
> See <URL: http://www.gnu.org/software/gcc/bugs.html > for instructions.
> make[1]: *** [outfloat.o] Error 1
This is a latent bug in the auto-inc code.
(insn 341 338 344 (set (mem:QI (reg/v:SI 104) 0)
(subreg/s/u:QI (reg/v:SI 170) 0)) 285 {*movsi_internal2+2} (nil)
(nil))
(insn 344 341 347 (set (reg/v:SI 104)
(plus:SI (reg/v:SI 104)
(const_int -1 [0xffffffff]))) 36 {*addsi3_internal1} (nil)
(nil))
(insn 347 344 348 (set (mem:QI (reg/v:SI 104) 0)
(subreg:QI (reg/v:SI 106) 0)) 285 {*movsi_internal2+2} (nil)
(nil))
Previously we would scrog the memories in mem_set_list so that we
didn't see that the MEMs from insn 347 and insn 341 are rtx_equal_p,
so we didn't consider insn 341 dead.
After the previous fix, we now see that they are equal, so we delete
insn 341, which means r170 is no longer live, which leads to the abort.
Of course, insn 341 *isn't* dead, and we should have flushed the
entry from mem_set_list when processing insn 344.
r~
* flow.c (invalidate_mems_from_set): Split out from ...
(mark_set_1): ... here.
(try_pre_increment_1): Use it. Use propagate_block_delete_insn
instead of turning insn into a NOTE_INSN_DELETED.
Index: flow.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/flow.c,v
retrieving revision 1.348
diff -c -p -d -r1.348 flow.c
*** flow.c 2000/11/09 00:26:34 1.348
--- flow.c 2000/11/10 02:00:49
*************** static void dump_edge_info PARAMS ((FIL
*** 408,413 ****
--- 408,415 ----
static void invalidate_mems_from_autoinc PARAMS ((struct propagate_block_info *,
rtx));
+ static void invalidate_mems_from_set PARAMS ((struct propagate_block_info *,
+ rtx));
static void remove_fake_successors PARAMS ((basic_block));
static void flow_nodes_print PARAMS ((const char *, const sbitmap,
FILE *));
*************** invalidate_mems_from_autoinc (pbi, insn)
*** 4352,4357 ****
--- 4354,4392 ----
}
}
+ /* EXP is either a MEM or a REG. Remove any dependant entries
+ from pbi->mem_set_list. */
+
+ static void
+ invalidate_mems_from_set (pbi, exp)
+ struct propagate_block_info *pbi;
+ rtx exp;
+ {
+ rtx temp = pbi->mem_set_list;
+ rtx prev = NULL_RTX;
+ rtx next;
+
+ while (temp)
+ {
+ next = XEXP (temp, 1);
+ if ((GET_CODE (exp) == MEM
+ && output_dependence (XEXP (temp, 0), exp))
+ || (GET_CODE (exp) == REG
+ && reg_overlap_mentioned_p (exp, XEXP (temp, 0))))
+ {
+ /* Splice this entry out of the list. */
+ if (prev)
+ XEXP (prev, 1) = next;
+ else
+ pbi->mem_set_list = next;
+ free_EXPR_LIST_node (temp);
+ }
+ else
+ prev = temp;
+ temp = next;
+ }
+ }
+
/* Process the registers that are set within X. Their bits are set to
1 in the regset DEAD, because they are dead prior to this insn.
*************** mark_set_1 (pbi, code, reg, cond, insn,
*** 4533,4563 ****
if (optimize && (flags & PROP_SCAN_DEAD_CODE))
{
if (GET_CODE (reg) == MEM || GET_CODE (reg) == REG)
! {
! rtx temp = pbi->mem_set_list;
! rtx prev = NULL_RTX;
! rtx next;
!
! while (temp)
! {
! next = XEXP (temp, 1);
! if ((GET_CODE (reg) == MEM
! && output_dependence (XEXP (temp, 0), reg))
! || (GET_CODE (reg) == REG
! && reg_overlap_mentioned_p (reg, XEXP (temp, 0))))
! {
! /* Splice this entry out of the list. */
! if (prev)
! XEXP (prev, 1) = next;
! else
! pbi->mem_set_list = next;
! free_EXPR_LIST_node (temp);
! }
! else
! prev = temp;
! temp = next;
! }
! }
/* If the memory reference had embedded side effects (autoincrement
address modes. Then we may need to kill some entries on the
--- 4568,4574 ----
if (optimize && (flags & PROP_SCAN_DEAD_CODE))
{
if (GET_CODE (reg) == MEM || GET_CODE (reg) == REG)
! invalidate_mems_from_set (pbi, reg);
/* If the memory reference had embedded side effects (autoincrement
address modes. Then we may need to kill some entries on the
*************** try_pre_increment_1 (pbi, insn)
*** 5763,5784 ****
&& ! dead_or_set_p (y, SET_DEST (x))
&& try_pre_increment (y, SET_DEST (x), amount))
{
! /* We have found a suitable auto-increment
! and already changed insn Y to do it.
! So flush this increment-instruction. */
! PUT_CODE (insn, NOTE);
! NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
! NOTE_SOURCE_FILE (insn) = 0;
! /* Count a reference to this reg for the increment
! insn we are deleting. When a reg is incremented.
! spilling it is worse, so we want to make that
! less likely. */
if (regno >= FIRST_PSEUDO_REGISTER)
{
REG_N_REFS (regno) += (optimize_size ? 1
: pbi->bb->loop_depth + 1);
REG_N_SETS (regno)++;
}
return 1;
}
return 0;
--- 5774,5797 ----
&& ! dead_or_set_p (y, SET_DEST (x))
&& try_pre_increment (y, SET_DEST (x), amount))
{
! /* We have found a suitable auto-increment and already changed
! insn Y to do it. So flush this increment instruction. */
! propagate_block_delete_insn (pbi->bb, insn);
!
! /* Count a reference to this reg for the increment insn we are
! deleting. When a reg is incremented, spilling it is worse,
! so we want to make that less likely. */
if (regno >= FIRST_PSEUDO_REGISTER)
{
REG_N_REFS (regno) += (optimize_size ? 1
: pbi->bb->loop_depth + 1);
REG_N_SETS (regno)++;
}
+
+ /* Flush any remembered memories depending on the value of
+ the incremented register. */
+ invalidate_mems_from_set (pbi, SET_DEST (x));
+
return 1;
}
return 0;
More information about the Gcc-regression
mailing list