This is the mail archive of the gcc-prs@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]

optimization/7924: internal compiler error


>Number:         7924
>Category:       optimization
>Synopsis:       internal compiler error
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    unassigned
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sun Sep 15 23:56:01 PDT 2002
>Closed-Date:
>Last-Modified:
>Originator:     Manuel Tobias Schiller
>Release:        gcc-3.2
>Organization:
>Environment:
System: Linux ws01 2.2.21 #3 Mon Aug 5 22:20:06 GMT 2002 i386 unknown
Architecture: i386
              bug also found on amd k6-2 system running linux 2.2.21 (same configuration options for gcc)
              both systems use glibc 2.2.5; see below for more details on glibc version
host: i386-pc-linux-gnu
build: i386-pc-linux-gnu
target: i386-pc-linux-gnu
configured with: ../gcc-3.2/configure --enable-shared --enable-languages=c,c++,java,f77 --disable-nls --enable-dwarf2
>Description:
When compiling a little program (see below), gcc aborts reporting an
internal compiler error (exact message printed by gcc along with the
flags used to compile the file see comments in the file switch.c.

When giving -O0 or -Os as compiler option, compilation seems to work
correctly. Compiling with -O2 and -O3 works, probably because gcc is
able to find a way to shorten this nonsense code. However, this code
fragment was simpified from a routine in the linux 2.2.21 kernel.
(I tried to compile new modules and had forgotten to make my old gcc
version available for kernel compilation; this version fails
completely to do so, mainly because the preprocessor doesn't like
the kernel's include files...) This original file also failed to
compile using higher optimization levels as the offending function's
complexity was considerably higher.
(The original file was
        linux-2.2.21/drivers/char/joy/joy-sidewinder.c
the function's head was
        static struct js_port __init *js_sw_probe(int io, struct js_port *port)
which starts around line 640 if I'm not mistaken)
However, I hope that a simplified version is better to track
things down.

As you might not have the same gcc sources available (because the
development of gcc goes on), the code fragment of my compiler
sources is included to give the context (the line where abort()
is called is marked by a comment containing many X's, see below,
the aborting routine taken from gcc/cfgrtl.c is included)

Apart from that, thanks for a fine compiler.


Details on the glibc versions used on the computers where
the bug showed up:

* i386:

GNU C Library stable release version 2.2.5, by Roland McGrath et al.
Copyright (C) 1992-2001, 2002 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 3.0.4.
Compiled on a Linux 2.2.21 system on 2002-08-12.
Available extensions:
        GNU libio by Per Bothner
        crypt add-on version 2.1 by Michael Glad and others
        linuxthreads-0.9 by Xavier Leroy
        BIND-8.2.3-T5B             libthread_db work sponsored by Alpha Processor Inc
        NIS(YP)/NIS+ NSS modules 0.19 by Thorsten Kukuk
Report bugs using the `glibcbug' script to <bugs@gnu.org>.

* amd k6-2:

GNU C Library stable release version 2.2.5, by Roland McGrath et al.
        Copyright (C) 1992-2001, 2002 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 3.2.
Compiled on a Linux 2.2.21 system on 2002-09-02.
Available extensions:
        GNU libio by Per Bothner
        crypt add-on version 2.1 by Michael Glad and others
        linuxthreads-0.9 by Xavier Leroy
        BIND-8.2.3-T5B
        libthread_db work sponsored by Alpha Processor Inc
        NIS(YP)/NIS+ NSS modules 0.19 by Thorsten Kukuk
Report bugs using the `glibcbug' script to <bugs@gnu.org>.

 * routine from gcc/cfgrtl.c
rtx
delete_insn (insn)
     rtx insn;
{
  rtx next = NEXT_INSN (insn);
  rtx note;
  bool really_delete = true;

  if (GET_CODE (insn) == CODE_LABEL)
    {
      /* Some labels can't be directly removed from the INSN chain, as they
         might be references via variables, constant pool etc.
         Convert them to the special NOTE_INSN_DELETED_LABEL note.  */
      if (! can_delete_label_p (insn))
        {
          const char *name = LABEL_NAME (insn);

          really_delete = false;
          PUT_CODE (insn, NOTE);
          NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED_LABEL;
          NOTE_SOURCE_FILE (insn) = name;
        }

      remove_node_from_expr_list (insn, &nonlocal_goto_handler_labels);
    }

  if (really_delete)
    {
      /* If this insn has already been deleted, something is very wrong.  */
      if (INSN_DELETED_P (insn))
        abort (); /* XXXXXXXXXXXXXXXXXXX - the compiler aborts here */
      remove_insn (insn);
      INSN_DELETED_P (insn) = 1;
    }

  /* If deleting a jump, decrement the use count of the label.  Deleting
     the label itself should happen in the normal course of block merging. */
  if (GET_CODE (insn) == JUMP_INSN
      && JUMP_LABEL (insn)
      && GET_CODE (JUMP_LABEL (insn)) == CODE_LABEL)
    LABEL_NUSES (JUMP_LABEL (insn))--;

  /* Also if deleting an insn that references a label.  */
  else if ((note = find_reg_note (insn, REG_LABEL, NULL_RTX)) != NULL_RTX
           && GET_CODE (XEXP (note, 0)) == CODE_LABEL)
    LABEL_NUSES (XEXP (note, 0))--;

  if (GET_CODE (insn) == JUMP_INSN
      && (GET_CODE (PATTERN (insn)) == ADDR_VEC
          || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC))
    {
      rtx pat = PATTERN (insn);
      int diff_vec_p = GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC;
      int len = XVECLEN (pat, diff_vec_p);
      int i;

      for (i = 0; i < len; i++)
        {
          rtx label = XEXP (XVECEXP (pat, diff_vec_p, i), 0);

          /* When deleting code in bulk (e.g. removing many unreachable
             blocks) we can delete a label that's a target of the vector
             before deleting the vector itself.  */
          if (GET_CODE (label) != NOTE)
            LABEL_NUSES (label)--;
        }
    }

  return next;
}
>How-To-Repeat:
compile attached file switch.c on ix86 system (possibly
running Linux is required, maybe not...) using the following
flags: -O1 -fomit-frame-pointer -c
>Fix:
Turn off optimization completely
>Release-Note:
>Audit-Trail:
>Unformatted:
----gnatsweb-attachment----
Content-Type: text/plain; name="switch.c"
Content-Disposition: inline; filename="switch.c"

/*
 * switch.c
 *
 * compile this file under gcc 3.2 on a ix86-pc-linux-gnu system with the
 * following flags to produce the bug: -O1 -fomit-frame-pointer -c
 * (note: compile only, do not try to link)
 *
 * the error message the compiler prints is:
 *
 *	switch.c: In function `bugproc':
 *	switch.c:94: Internal compiler error in delete_insn, at cfgrtl.c:139
 *	Please submit a full bug report,
 *	with preprocessed source if appropriate.
 *	See <URL:http://www.gnu.org/software/gcc/bugs.html> for instructions.
 */

/*
 * these function declarations are here to make sure the compiler knows what
 * sort of function to call, the functions themselves are of no importance
 * as the bug happens in the compilation state
 * these seem to be the functions with the simplest prototypes which reproduce
 * the bug
 * (it took me quite a while to strip off everything not needed from the real
 * world routine, but it seems to me that finding a compiler bug is simpler
 * when the offending piece of code is minimal, even if it is a bit senseless)
 */
extern int h1(int, int, ...);
extern long long h2(int, int, int, int, int);

/*
 * the routine bugproc seems to be the minimum required to trigger the bug
 */
static int bugproc(int a)
{
/*
 * don't try to remove one of the variables, it seems to be the minimal set to
 * reproduce the bug
 */
    int i = 000, j = 100, k = 200;

    do {
	if (k > i) {
/*
 * all these case labels below seem to be needed
 */
	    switch (i * k) {
	    case 8:
		i++;
	    case 6:
		if (i) break;
	    case 5:
		i++;
	    case 4:
		i++;
	    case 1:
		i = 2;
		break;
	    case 3:
	    case 2:
		i = 7;
		break;
	    case 7:
		if (j == 14) {
		    i = 3;
/*
 * interesting, i need to pass strings near the end of tje next line to
 * produce the bug...
 */
		    h1(1, 2, h2(1, 2, 3, 4, 5) ? "a" : "b");
		} else
		    i = 4;
		break;
/*
 * the following case label must be 102 or above - otherwise the bug will
 * not show up
 */
	    case 102:
		i = 5;
	    case 9:
		i = 6;
		break;
	    }
	}
    }
    while (k && !i);

/*
 * this strange if is also needed
 */
    if (!i)
	return a;

    return a;
}


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