Bug 7814 - incorrect scheduling for glibc-2.2.92 stpcpy test
Summary: incorrect scheduling for glibc-2.2.92 stpcpy test
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: rtl-optimization (show other bugs)
Version: 3.2
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: wrong-code
Depends on:
Blocks:
 
Reported: 2002-09-02 12:26 UTC by glen
Modified: 2003-07-25 17:33 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments
stpcpy.i (7.77 KB, text/x-c)
2003-05-21 15:17 UTC, glen
Details

Note You need to log in before you can comment on or make changes to this bug.
Description glen 2002-09-02 09:36:09 UTC
From: Glen Nakamura <glen@imodulo.com>
To: gcc-gnats@gcc.gnu.org, gcc-bugs@gcc.gnu.org
Cc:  
Subject: Re: other/7814: incorrect scheduling for glibc-2.2.92 stpcpy test
Date: Mon, 2 Sep 2002 09:36:09 -1000

 --J2SCkAp4GZ/dPZZf
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: inline
 
 Hmm, I intended to file this under optimization, but I must have selected
 other by mistake... *grr*  Anyway, here is the C source for the uploaded
 testcase.
 
 http://gcc.gnu.org/cgi-bin/gnatsweb.pl?cmd=view%20audit-trail&database=gcc&pr=7814
 
 --J2SCkAp4GZ/dPZZf
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: attachment; filename="stpcpy.c"
 
 #define _GNU_SOURCE
 
 #include <stdio.h>
 #include <string.h>
 
 const char *it = "<UNSET>";	/* Routine name for message routines. */
 size_t errors = 0;
 
 /* Complain if condition is not true.  */
 static void
 check (int thing, int number)
 {
   if (!thing)
     {
       printf("%s flunked test %d\n", it, number);
       ++errors;
     }
 }
 
 /* Complain if first two args don't strcmp as equal.  */
 static void
 equal (const char *a, const char *b, int number)
 {
   check(a != NULL && b != NULL && (strcmp (a, b) == 0), number);
 }
 
 char one[50];
 char two[50];
 char *cp;
 
 #undef __stpcpy
 #    define __stpcpy(dest, src) \
   (__extension__ (__builtin_constant_p (src)                                  \
                   ? (__string2_1bptr_p (src) && strlen (src) + 1 <= 8         \
                      ? __builtin_strcpy (dest, src) + strlen (src)            \
                      : ((char *) (__mempcpy) (dest, src, strlen (src) + 1)    \
                         - 1))                                                 \
                   : __stpcpy (dest, src)))
 
 static void
 test_stpcpy (void)
 {
   it = "stpcpy";
   check ((stpcpy (one, "a") - one) == 1, 1);
   equal (one, "a", 2);
 
   check ((stpcpy (one, "ab") - one) == 2, 3);
   equal (one, "ab", 4);
 
   check ((stpcpy (one, "abc") - one) == 3, 5);
   equal (one, "abc", 6);
 
   check ((stpcpy (one, "abcd") - one) == 4, 7);
   equal (one, "abcd", 8);
 
   check ((stpcpy (one, "abcde") - one) == 5, 9);
   equal (one, "abcde", 10);
 
   check ((stpcpy (one, "abcdef") - one) == 6, 11);
   equal (one, "abcdef", 12);
 
   check ((stpcpy (one, "abcdefg") - one) == 7, 13);
   equal (one, "abcdefg", 14);
 
   check ((stpcpy (one, "abcdefgh") - one) == 8, 15);
   equal (one, "abcdefgh", 16);
 
   check ((stpcpy (one, "abcdefghi") - one) == 9, 17);
   equal (one, "abcdefghi", 18);
 
   check ((stpcpy (one, "x") - one) == 1, 19);
   equal (one, "x", 20);			/* Writeover. */
   equal (one+2, "cdefghi", 21);		/* Wrote too much? */
 
   check ((stpcpy (one, "xx") - one) == 2, 22);
   equal (one, "xx", 23);		/* Writeover. */
   equal (one+3, "defghi", 24);		/* Wrote too much? */
 
   check ((stpcpy (one, "xxx") - one) == 3, 25);
   equal (one, "xxx", 26);		/* Writeover. */
   equal (one+4, "efghi", 27);		/* Wrote too much? */
 
   check ((stpcpy (one, "xxxx") - one) == 4, 28);
   equal (one, "xxxx", 29);		/* Writeover. */
   equal (one+5, "fghi", 30);		/* Wrote too much? */
 
   check ((stpcpy (one, "xxxxx") - one) == 5, 31);
   equal (one, "xxxxx", 32);		/* Writeover. */
   equal (one+6, "ghi", 33);		/* Wrote too much? */
 
   check ((stpcpy (one, "xxxxxx") - one) == 6, 34);
   equal (one, "xxxxxx", 35);		/* Writeover. */
   equal (one+7, "hi", 36);		/* Wrote too much? */
 
   check ((stpcpy (one, "xxxxxxx") - one) == 7, 37);
   equal (one, "xxxxxxx", 38);		/* Writeover. */
   equal (one+8, "i", 39);		/* Wrote too much? */
 
   check ((stpcpy (stpcpy (stpcpy (one, "a"), "b"), "c") - one) == 3, 40);
   equal (one, "abc", 41);
   equal (one + 4, "xxx", 42);
 }
 
 int
 main (void)
 {
   int status;
 
   /* A closely related function is stpcpy.  */
   test_stpcpy ();
 
   if (errors == 0)
     {
       status = 0;
       puts("No errors.");
     }
   else
     {
       status = 1;
       printf("%Zd errors.\n", errors);
     }
 
   return status;
 }
 
 --J2SCkAp4GZ/dPZZf--

Comment 1 glen 2002-09-02 10:24:48 UTC
From: Glen Nakamura <glen@imodulo.com>
To: gcc-gnats@gcc.gnu.org, gcc-bugs@gcc.gnu.org
Cc:  
Subject: Re: other/7814: incorrect scheduling for glibc-2.2.92 stpcpy test
Date: Mon, 2 Sep 2002 10:24:48 -1000

 http://gcc.gnu.org/cgi-bin/gnatsweb.pl?cmd=view%20audit-trail&database=gcc&pr=7814
 Okay, I think the problem is that when we flush the dependency lists
 (e.g. when ?_length > MAX_PENDING_LIST_LENGTH), we end up with a single
 insn in the 'clobbers' list while the 'sets' and 'uses' lists are empty.
 Now, if there is another clobber insn before any set or use insn, it won't
 be dependent on any previous insn because the 'sets' and 'uses' lists
 are empty...  The problem is fixed by adding the last insn to the 'sets'
 list after flushing.
 
 - glen
 
 Here is the patch:
 
 ChangeLog
 ===================================================================
 2002-09-02  Glen Nakamura  <glen@imodulo.com>
 
 	* sched-deps.c (sched_analyze_insn): Make sure to add insn
 	to reg_last->sets after flushing the dependency lists to guarantee
 	that subsequent clobbers will be dependent on it.
 
 Index: sched-deps.c
 ===================================================================
 RCS file: /cvsroot/gcc/gcc/gcc/sched-deps.c,v
 retrieving revision 1.34.6.1
 diff -c -3 -p -u -r1.34.6.1 sched-deps.c
 --- sched-deps.c	19 Aug 2002 18:59:31 -0000	1.34.6.1
 +++ sched-deps.c	2 Sep 2002 06:35:15 -0000
 @@ -1118,8 +1118,6 @@ sched_analyze_insn (deps, x, insn, loop_
  	  EXECUTE_IF_SET_IN_REG_SET (reg_pending_clobbers, 0, i,
  	    {
  	      struct deps_reg *reg_last = &deps->reg_last[i];
 -	      add_dependence_list (insn, reg_last->sets, REG_DEP_OUTPUT);
 -	      add_dependence_list (insn, reg_last->uses, REG_DEP_ANTI);
  	      if (reg_last->uses_length > MAX_PENDING_LIST_LENGTH
  		  || reg_last->clobbers_length > MAX_PENDING_LIST_LENGTH)
  		{
 @@ -1129,6 +1127,7 @@ sched_analyze_insn (deps, x, insn, loop_
  						REG_DEP_ANTI);
  		  add_dependence_list_and_free (insn, &reg_last->clobbers,
  						REG_DEP_OUTPUT);
 +		  reg_last->sets = alloc_INSN_LIST (insn, reg_last->sets);
  		  reg_last->clobbers_length = 0;
  		  reg_last->uses_length = 0;
  		}
Comment 2 glen 2002-09-02 12:26:01 UTC
GCC incorrectly generates scheduling dependencies...

test_stpcpy:
        pushl   %ebp
        movl    %esp, %ebp
        pushl   %edi
        pushl   %esi
        movl    $1, %esi
        pushl   %ebx
        movl    $one, %ebx
        subl    %ebx, %esi
        subl    $20, %esp
        movl    $.LC2, it
        leal    (%ebx,%esi), %edi
        pushl   $1
        cmpl    $1, %edi
        addl    $one+2, %esi      << incorrectly clobbers CC
        sete    %al
        andl    $255, %eax
        pushl   %eax
        movw    $97, one
        call    check
        addl    $12, %esp

Release:
gcc 3.2

Environment:
i586-pc-linux-gnu

How-To-Repeat:
bash:~# gcc -O2 -mcpu=i586 stpcpy.i
bash:~# ./a.out
stpcpy flunked test 1
1 errors.
Comment 3 glen 2002-09-02 12:26:01 UTC
Fix:
I'm testing a patch to sched-deps.c which I'll post soon.
Comment 4 Richard Henderson 2002-09-07 20:44:48 UTC
State-Changed-From-To: open->closed
State-Changed-Why: Fixed.