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]

relevant testcase fixed in mainline, broken in branch


Does anybody have any idea of what fixed the following testcase in
the trunk?

// Build don't link:

// Copyright (C) 1999 Free Software Foundation

// by Alexandre Oliva <oliva@lsd.ic.unicamp.br>
// Derived from GNU lilypond.

// crash test

struct foo {
  foo();
  foo(const foo&);
  ~foo();
};

struct bar {
  foo foo_member;
  bar();
  bar(const bar&);
  // ~bar();
};

struct baz {
  void error (bar s);
};

void fail() __attribute__((noreturn));

void baz::error (bar s) {
  fail();
}

2.95.1 and the current release branch crash with -O1 or higher on
GNU/Linux/alpha and DU4.0/alpha, but on none of my sparc, x86 or mips
(IRIX5) platforms, while inlining the destructor of bar:

Starting program: /usr/local/tmp/gcc-2.95/gcc/cc1plus test.ii -O1
 void baz::error(bar) bar::~bar()
Program received signal SIGSEGV, Segmentation fault.
0x120103560 in cse_insn (insn=0x1400dd440, libcall_insn=0x0)
    at /home/msc/oliva/src/gcc-2.95/gcc/cse.c:7499
7499                    p = PREV_INSN (delete_insn (NEXT_INSN (p)));
(gdb) where
#0  0x120103560 in cse_insn (insn=0x1400dd440, libcall_insn=0x0)
    at /home/msc/oliva/src/gcc-2.95/gcc/cse.c:7499
#1  0x120106c34 in cse_basic_block (from=0x1e, to=0x0, 
    next_branch=0x11fffe2f0, around_loop=1)
    at /home/msc/oliva/src/gcc-2.95/gcc/cse.c:8969
#2  0x1201066e0 in cse_main (f=0x140079630, nregs=0, after_loop=0, file=0x0)
    at /home/msc/oliva/src/gcc-2.95/gcc/cse.c:8834
#3  0x12003aec8 in rest_of_compilation (decl=0x1400d4e10)
    at /home/msc/oliva/src/gcc-2.95/gcc/toplev.c:3871
#4  0x1201fe300 in finish_function (lineno=24, flags=0, nested=0)
    at /home/msc/oliva/src/gcc-2.95/gcc/cp/decl.c:14451
#5  0x12023f6a8 in yyparse () at parse.y:648
#6  0x120039bb0 in compile_file (name=0x140000060 "")
    at /home/msc/oliva/src/gcc-2.95/gcc/toplev.c:3265
#7  0x12003e1c8 in main (argc=3, argv=0x11ffff488)
    at /home/msc/oliva/src/gcc-2.95/gcc/toplev.c:5441

delete_insn has returned null, because the whole block has been
eliminated as dead.  The following patch fixes this problem in the
branch, and it seems to be pretty safe, since the introduced code will
only be executed where gcc would crash anyway.  It might be applied to
the trunk too; even though this particular testcase doesn't trigger
it, it might happen, unless delete_insn ensures otherwise.

Which reminds of another very simple patch I posted two weeks ago.  It
happens to modify the next few lines of cse.c, adding a test to avoid
trying to add a barrier after the current insn if it was deleted.  I
repost it here, for your convenience.  It seems less trivial than it
is because it reindents a whole block, but there's just one new test
around it all (should such patches be generated with `diff -b'?)  It
is also pretty safe, since emit_barrier_before would also crash when
given a deleted insn.

May I install any of these ok in the trunk and/or in the branch?

The new patch:

Index: gcc/ChangeLog
from  Alexandre Oliva  <oliva@lsd.ic.unicamp.br>
	
	* cse.c (cse_insn): If delete_insn returns 0 when deleting dead
	code, stop and emit a barrier after the unconditional jump.
	
Index: gcc/cse.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cse.c,v
retrieving revision 1.72.4.4
diff -u -p -r1.72.4.4 cse.c
--- gcc/cse.c	1999/09/07 07:38:54	1.72.4.4
+++ gcc/cse.c	1999/09/18 11:56:59
@@ -7495,9 +7495,14 @@ cse_insn (insn, libcall_insn)
 		 delete_insn, otherwise we could get an infinite loop
 		 if NEXT_INSN (p) had INSN_DELETED_P set.  */
 	      if (GET_CODE (NEXT_INSN (p)) != NOTE
-		  || NOTE_LINE_NUMBER (NEXT_INSN (p)) == NOTE_INSN_DELETED)
-		p = PREV_INSN (delete_insn (NEXT_INSN (p)));
-	      else
+		  || NOTE_LINE_NUMBER (NEXT_INSN (p)) == NOTE_INSN_DELETED) {
+		rtx n = delete_insn (NEXT_INSN (p));
+		if (n == 0) {
+		  p = insn;
+		  break;
+		} else
+		  p = PREV_INSN (n);
+	      } else
 		p = NEXT_INSN (p);
 	    }
 

The old patch:

Index: gcc/ChangeLog
from  Alexandre Oliva  <oliva@dcc.unicamp.br>
	
	* cse.c (cse_insn): Do not bother to put a barrier after a deleted
	insn.  Fixes gcc.c-torture/compile/990801-2.c.
	
Index: gcc/cse.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cse.c,v
retrieving revision 1.87
diff -u -r1.87 cse.c
--- gcc/cse.c	1999/08/31 22:48:58	1.87
+++ gcc/cse.c	1999/09/05 01:41:03
@@ -7444,20 +7444,31 @@
 		p = NEXT_INSN (p);
 	    }
 
-	  /* If we don't have a BARRIER immediately after INSN, put one there.
-	     Much code assumes that there are no NOTEs between a JUMP_INSN and
-	     BARRIER.  */
+	  /* If we happened to delete de current insn (for example, in
+	     gcc.c-torture/compile/990801-2.c on sparc), don't bother
+	     to create a barrier.  If it's really needed, it will have
+	     already been created.  But where?  Maybe we'd better skip
+	     deleted insns until we find one that is not deleted, then
+	     insert a barrier before it...  -oliva) */
+	  if (! INSN_DELETED_P (insn))
+	    {
+	      /* If we don't have a BARRIER immediately after INSN,
+		 put one there.  Much code assumes that there are no
+		 NOTEs between a JUMP_INSN and BARRIER.  */
 
-	  if (NEXT_INSN (insn) == 0
-	      || GET_CODE (NEXT_INSN (insn)) != BARRIER)
-	    emit_barrier_before (NEXT_INSN (insn));
+	      if (NEXT_INSN (insn) == 0
+		  || GET_CODE (NEXT_INSN (insn)) != BARRIER)
+		{
+		  emit_barrier_before (NEXT_INSN (insn));
+		}
 
-	  /* We might have two BARRIERs separated by notes.  Delete the second
-	     one if so.  */
+	      /* We might have two BARRIERs separated by notes.
+		 Delete the second one if so.  */
 
-	  if (p != insn && NEXT_INSN (p) != 0
-	      && GET_CODE (NEXT_INSN (p)) == BARRIER)
-	    delete_insn (NEXT_INSN (p));
+	      if (p != insn && NEXT_INSN (p) != 0
+		  && GET_CODE (NEXT_INSN (p)) == BARRIER)
+		delete_insn (NEXT_INSN (p));
+	    }
 
 	  cse_jumps_altered = 1;
 	  sets[i].rtl = 0;


-- 
Alexandre Oliva http://www.dcc.unicamp.br/~oliva IC-Unicamp, Bra[sz]il
oliva@{lsd.ic.unicamp.br,guarana.{org,com}} aoliva@{acm,computer}.org
oliva@{gnu.org,kaffe.org,{egcs,sourceware}.cygnus.com,samba.org}
** I may forward mail about projects to mailing lists; please use them

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