This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Fix latent bug in crossjumping


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.  */


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]