public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* gcc 2.95.3 optimization bug
@ 2003-11-18 14:55 David Taylor
  0 siblings, 0 replies; only message in thread
From: David Taylor @ 2003-11-18 14:55 UTC (permalink / raw)
  To: gcc-bugs

[I realize that there will be no more 2.x releases of GCC -- and that
therefore this bug fix will not appear in a release.  But, there are
people still using GCC 2.x.  EMC still uses 2.x (yes, we are migrating
to 3.x -- but, we will -- for some time -- care about 2.x for previous
releases of our product).]

The following problem was observed in a 2.95.3 x86 x powerpc-elf-eabi
GCC, though it is not powerpc specific.

Consider the following simple function (reduced from something much larger):

    int func (int x)
    {
      int y = 0;
      switch (x)
      {
	case 6:  { y = 3; break; }
	case 7:  { y = 4; break; }
	case 10: { y = 6; break; }
	case 11: { y = 7; break; }
	case 12: { y = 8; break; }
      }
      return (0);
    }

During the 5th (and final) call to jump_optimize_1, we have RTL that looks somewhat like:

    notes and insns (some deleted, some not)

    jump to code label 72 -- conditional

    notes and deleted insns

    jump to code label 72 -- unconditional

    note
    barrier
    code label 72 -- use count 2

    set return register to 0
    return

The code examines the first jump; decides it can delete it since it's
followed by an unconditional jump to same place and there are no
active instructions between the two.  Decrements the use count of
label 72.  All fine.

Then it examines the second jump; decides it can delete it since by
falling through and by jumping it ends up in the same place.  Fine.
It deletes the jump.  Fine.  It updates the use count of label 72.
All fine.  *BUT* it fails to delete the barrier because of the
intervening note.  Oops!

Then it examines the label -- now with a use count of 0 -- decides it
can delete it.  Fine.  Notices the barrier right before it (!!!!!);
decides that this is dead code and that it should delete forward until
the next label (or end of function).  Major OOPS -- this isn't dead
code.

Result: not only is the function return value not set, it doesn't
generate the return jump (in the powerpc case -- the blr instruction)
-- so it ends up falling into the next function in the executable.

The fix is to scan for the next instruction and notice the barrier.
Here's a context diff to delete_insn in jump.c:

Index: jump.c
===================================================================
RCS file: /emc/ucode/cvsroot_0/gcc-2.95.3/gcc/jump.c,v
retrieving revision 1.2
diff -c -r1.2 jump.c
*** jump.c	3 Mar 2003 16:58:39 -0000	1.2
--- jump.c	18 Nov 2003 14:22:51 -0000
***************
*** 4026,4031 ****
--- 4026,4041 ----
        INSN_DELETED_P (next) = 1;
        next = NEXT_INSN (next);
      }
+   else if (next != 0 && GET_CODE (next) == NOTE)
+     {
+       /* the next *REAL* instruction might be a barrier -- a barrier
+ 	 that should be deleted because the unconditional jump before
+ 	 it is now gone.  */
+       rtx next2 = next_nonnote_insn (next);
+ 
+       if (next2 && (GET_CODE (next2) == BARRIER))
+ 	delete_insn (next2);
+     }
  
    /* Patch out INSN (and the barrier if any) */
  


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2003-11-18 14:55 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-11-18 14:55 gcc 2.95.3 optimization bug David Taylor

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).