This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Fix latent bug in crossjumping
- From: Josef Zlomek <zlomj9am at artax dot karlin dot mff dot cuni dot cz>
- To: gcc-patches at gcc dot gnu dot org
- Cc: gcc-bugs at gcc dot gnu dot org, gcc-gnats at gcc dot gnu dot org,pfeifer at dbai dot tuwien dot ac dot at, dalej at apple dot com, gcc-prs at gcc dot gnu dot org,Jan Hubicka <jh at suse dot cz>,Steven Bosscher <s dot bosscher at student dot tudelft dot nl>
- Date: Thu, 13 Feb 2003 14:09:34 +0100
- Subject: Fix latent bug in crossjumping
- References: <1044994461.2333.60.camel@steven> <1045000492.3956.105.camel@steven>
Hi,
gcc creates a reference to an undefined label when compiling the
attached testcase with "-O -fpic".
I have analyzed it and have found out that problem is in the condition
in the beginning of function outgoing_edges_match in cfgcleanup.c
When BB1 and BB2 end with a table jump insn
(i.e. a jump_insn which has a parallel of set pc and use label inside
and which jumps to jump_insn with addr_vec or addr_dif_vec inside)
tablejump instruction)
the function outgoing_edges_match returns that the outgoing edges match
without checking the tablejumps (comparing and unifying of tablejumps is
not implemented yet) and it never reaches the comment
/* Generic case - we are seeing a computed jump, table jump or trapping
instruction. */
which should be reached the we have a tablejump.
One table jump is then removed (without checking whether it is identical
with the second one so it may produce wrong code too) and the label
references are not updated.
This patch changes the condition in the beginning of function
outgoing_edges_match.
When there is one normal (!(EDGE_COMPLEX | EDGE_FAKE)) outgoing edge from bb1
and one normal outgoing edge from bb2, each block must end with a
non-jump insn or a simplejump_p jump (i.e. when there is a jump in the
end of block it is a simplejump and not some of the strange jumps).
This patch fixes the bug when compiling the testcase.
Bootstrapped/regtested mainline i386 (pentium4).
OK for mainline, 3_3-branch and 3_2-branch?
Josef
PS: I thank Steven Bosscher <s.bosscher@student.tudelft.nl>
for locating the bug to crossjumping.
Testcase:
int *g;
int main (void)
{
switch (*g)
{
case 0:
{
switch (*g)
{
case 0: *g = 1; break;
case 1:
case 2: *g = 1; break;
case 3:
case 4: *g = 1; break;
}
break;
}
case 1:
{
switch (*g)
{
case 0: *g = 1; break;
case 1:
case 2: *g = 1; break;
case 3:
case 4: *g = 1; break;
}
}
}
return 0;
}
2003-02-13 Josef Zlomek <zlomekj@suse.cz>,
* cfgcleanup.c (outgoing_edges_match): When there is single outgoing edge
and block ends with a jump insn it must be simple jump.
Index: cfgcleanup.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cfgcleanup.c,v
retrieving revision 1.71
diff -u -c -3 -p -r1.71 cfgcleanup.c
*** cfgcleanup.c 10 Feb 2003 19:18:42 -0000 1.71
--- cfgcleanup.c 13 Feb 2003 10:23:04 -0000
*************** outgoing_edges_match (mode, bb1, bb2)
*** 1119,1127 ****
/* If BB1 has only one successor, we may be looking at either an
unconditional jump, or a fake edge to exit. */
if (bb1->succ && !bb1->succ->succ_next
! && !(bb1->succ->flags & (EDGE_COMPLEX | EDGE_FAKE)))
return (bb2->succ && !bb2->succ->succ_next
! && (bb2->succ->flags & (EDGE_COMPLEX | EDGE_FAKE)) == 0);
/* Match conditional jumps - this may get tricky when fallthru and branch
edges are crossed. */
--- 1119,1129 ----
/* If BB1 has only one successor, we may be looking at either an
unconditional jump, or a fake edge to exit. */
if (bb1->succ && !bb1->succ->succ_next
! && (bb1->succ->flags & (EDGE_COMPLEX | EDGE_FAKE)) == 0
! && (GET_CODE (bb1->end) != JUMP_INSN || simplejump_p (bb1->end)))
return (bb2->succ && !bb2->succ->succ_next
! && (bb2->succ->flags & (EDGE_COMPLEX | EDGE_FAKE)) == 0
! && (GET_CODE (bb2->end) != JUMP_INSN || simplejump_p (bb2->end)));
/* Match conditional jumps - this may get tricky when fallthru and branch
edges are crossed. */