2
0
mirror of git://gcc.gnu.org/git/gcc.git synced 2025-03-20 17:40:46 +08:00

re PR rtl-optimization/18861 (ICE Segmentation fault in try_crossjump_to_edge at ../../gcc/gcc/cfgcleanup.c:1637 with two switches (table jumps))

PR rtl-optimization/18861
	* cfgbuild.c (BLOCK_USED_BY_TABLEJUMP): Define.
	(FULL_STATE): Define.
	(mark_tablejump_edge): New function.
	(purge_dead_tablejump_edges): New function.
	(find_bb_boundaries): Use it.

	* gcc.dg/20050105-1.c: New test.

From-SVN: r93041
This commit is contained in:
Jakub Jelinek 2005-01-07 10:04:01 +01:00 committed by Jakub Jelinek
parent 8870e2121d
commit 0210ae141e
4 changed files with 105 additions and 0 deletions

@ -1,5 +1,12 @@
2005-01-07 Jakub Jelinek <jakub@redhat.com>
PR rtl-optimization/18861
* cfgbuild.c (BLOCK_USED_BY_TABLEJUMP): Define.
(FULL_STATE): Define.
(mark_tablejump_edge): New function.
(purge_dead_tablejump_edges): New function.
(find_bb_boundaries): Use it.
PR tree-optimization/18828
* builtins.c (expand_builtin_next_arg): Remove argument and all
the argument checking.

@ -559,14 +559,73 @@ enum state {BLOCK_NEW = 0, BLOCK_ORIGINAL, BLOCK_TO_SPLIT};
#define STATE(BB) (enum state) ((size_t) (BB)->aux)
#define SET_STATE(BB, STATE) ((BB)->aux = (void *) (size_t) (STATE))
/* Used internally by purge_dead_tablejump_edges, ORed into state. */
#define BLOCK_USED_BY_TABLEJUMP 32
#define FULL_STATE(BB) ((size_t) (BB)->aux)
static void
mark_tablejump_edge (rtx label)
{
basic_block bb;
gcc_assert (LABEL_P (label));
/* See comment in make_label_edge. */
if (INSN_UID (label) == 0)
return;
bb = BLOCK_FOR_INSN (label);
SET_STATE (bb, FULL_STATE (bb) | BLOCK_USED_BY_TABLEJUMP);
}
static void
purge_dead_tablejump_edges (basic_block bb, rtx table)
{
rtx insn = BB_END (bb), tmp;
rtvec vec;
int j;
edge_iterator ei;
edge e;
if (GET_CODE (PATTERN (table)) == ADDR_VEC)
vec = XVEC (PATTERN (table), 0);
else
vec = XVEC (PATTERN (table), 1);
for (j = GET_NUM_ELEM (vec) - 1; j >= 0; --j)
mark_tablejump_edge (XEXP (RTVEC_ELT (vec, j), 0));
/* Some targets (eg, ARM) emit a conditional jump that also
contains the out-of-range target. Scan for these and
add an edge if necessary. */
if ((tmp = single_set (insn)) != NULL
&& SET_DEST (tmp) == pc_rtx
&& GET_CODE (SET_SRC (tmp)) == IF_THEN_ELSE
&& GET_CODE (XEXP (SET_SRC (tmp), 2)) == LABEL_REF)
mark_tablejump_edge (XEXP (XEXP (SET_SRC (tmp), 2), 0));
for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
{
if (FULL_STATE (e->dest) & BLOCK_USED_BY_TABLEJUMP)
SET_STATE (e->dest, FULL_STATE (e->dest)
& ~(size_t) BLOCK_USED_BY_TABLEJUMP);
else if (!(e->flags & (EDGE_ABNORMAL | EDGE_EH)))
{
remove_edge (e);
continue;
}
ei_next (&ei);
}
}
/* Scan basic block BB for possible BB boundaries inside the block
and create new basic blocks in the progress. */
static void
find_bb_boundaries (basic_block bb)
{
basic_block orig_bb = bb;
rtx insn = BB_HEAD (bb);
rtx end = BB_END (bb);
rtx table;
rtx flow_transfer_insn = NULL_RTX;
edge fallthru = NULL;
@ -623,6 +682,11 @@ find_bb_boundaries (basic_block bb)
followed by cleanup at fallthru edge, so the outgoing edges may
be dead. */
purge_dead_edges (bb);
/* purge_dead_edges doesn't handle tablejump's, but if we have split the
basic block, we might need to kill some edges. */
if (bb != orig_bb && tablejump_p (BB_END (bb), NULL, &table))
purge_dead_tablejump_edges (bb, table);
}
/* Assume that frequency of basic block B is known. Compute frequencies

@ -1,5 +1,8 @@
2005-01-07 Jakub Jelinek <jakub@redhat.com>
PR rtl-optimization/18861
* gcc.dg/20050105-1.c: New test.
PR tree-optimization/18828
* gcc.dg/20050105-2.c: New test.

@ -0,0 +1,31 @@
/* PR rtl-optimization/18861 */
/* { dg-do compile } */
/* { dg-options "-O2 -floop-optimize2" } */
extern void abort (void);
int
foo (int code)
{
if (code >= 3)
switch (code)
{
case 3: return 4;
case 4: return 3;
case 5: return 6;
case 6: return 7;
case 7: return 8;
case 8: return 5;
default: abort ();
}
switch (code)
{
case 3: return 4;
case 4: return 3;
case 5: return 6;
case 6: return 7;
case 7: return 8;
case 8: return 5;
default: abort ();
}
}