Bug 16590 - [3.4 regression] Incorrect execution when compiling with -O2
Summary: [3.4 regression] Incorrect execution when compiling with -O2
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: rtl-optimization (show other bugs)
Version: 3.4.1
: P2 critical
Target Milestone: 3.4.2
Assignee: Not yet assigned to anyone
URL:
Keywords: monitored, wrong-code
Depends on:
Blocks:
 
Reported: 2004-07-16 14:56 UTC by Michele Galante
Modified: 2004-10-30 21:10 UTC (History)
4 users (show)

See Also:
Host: mingw32 / i686-pc-sco3.2v5.0.6
Target: mingw32 / i686-pc-sco3.2v5.0.6
Build:
Known to work: 3.3.4 4.0.0
Known to fail: 3.4.0
Last reconfirmed: 2004-07-16 15:39:46


Attachments
Patch (426 bytes, patch)
2004-08-17 23:10 UTC, Mark Mitchell
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Michele Galante 2004-07-16 14:56:33 UTC
I have reduced the testcase to a small file that only includes <cassert> in 
order to show where the execution fails. The assert in main() should never 
fail, but it fails if you compile with:

  g++ -O2 bug.cpp
  
The assert does not fail if you compile with one of the following:
  g++ -O0 bug.cpp
  g++ -O1 bug.cpp
  g++ -O2 -DWORKAROUND bug.cpp

This happens with gcc 3.4.1 (mingw special) on Windows XP and gcc 3.4.0 on SCO 
OPENSERVER 5.0.6, but NOT with gcc 3.4.0 on SUN Solaris; perhaps a bug in 
generating code for INTEL X86?


Output of "gcc -v" for gcc 3.4.1/MinGW on Windows XP (assert FAILS):
Reading specs from c:/mingw/bin/../lib/gcc/mingw32/3.4.1/specs
Configured with: ../gcc/configure --with-gcc --with-gnu-ld --with-gnu-as --
host=mingw32 --target=mingw32 --prefix=/mingw --enable-threads --disable-nls --
enable-languages=c,c++,f77,ada,objc,java --disable-win32-registry --disable-
shared --enable-sjlj-exceptions --enable-libgcj --disable-java-awt --without-
x --enable-java-gc=boehm --disable-libgcj-debug --enable-interpreter --enable-
hash-synchronization --enable-libstdcxx-debug
Thread model: win32
gcc version 3.4.1 (mingw special)


Output of "gcc -v" for gcc 3.4.0 on SCO OpenServer (assert FAILS):
Reading specs from /home/local/gcc-3.4.0/bin/../lib/gcc/i686-pc-
sco3.2v5.0.6/3.4.0/specs
Configured with: ../gcc-3.4.0/configure --with-gnu-as --prefix=/usr/local/gcc-
3.4.0
Thread model: single
gcc version 3.4.0


Output of "gcc -v" for gcc 3.4.0 on SUN Solaris (assert does NOT FAIL):
Reading specs from /usr/local/gcc-3.4.0/lib/gcc/sparc-sun-
solaris2.8/3.4.0/specs
Configured with: ../gcc-3.4.0/configure --disable-shared --
prefix=/usr/local/gcc-3.4.0
Thread model: posix
gcc version 3.4.0


// -------------------- bug.cpp ------------------------

#include <cassert>

typedef char* iterator_type;

struct queue;

struct iterator
{
#ifdef WORKAROUND
  iterator_type volatile pos_;
#else
  iterator_type pos_;
#endif
  queue const* queue_;

  iterator(queue const* queue, iterator_type pos) : pos_(pos), queue_(queue) {}
  iterator& operator--();
};

struct queue
{
  iterator_type const first_, last_;
  iterator_type put_, get_;

  queue(iterator_type first, iterator_type last)
  : first_(first), last_(last), put_(first), get_(first)
  {}

  iterator pbegin() const { return iterator(this, put_); }
  iterator pend() const { iterator end(this, get_); return --end; }
};

inline iterator& iterator::operator--()
{
  if(pos_ == queue_->first_) pos_ = queue_->last_;
  --pos_;
  return *this;
}

int main()
{
  char mem[4+1];
  queue buf(mem, mem+4+1);
  assert(buf.pend().pos_ == buf.pbegin().pos_+4);
  return 0;
}
Comment 1 Wolfgang Bangerth 2004-07-16 15:39:46 UTC
Confirmed. Here's a very fragile testcase (if you change a bit, the 
bug goes away): 
------------------------ 
extern "C" void abort(); 
 
struct iterator { 
    char * p; 
    int *dummy; 
}; 
 
static iterator pend(char * start) { 
  iterator p = {start, 0}; 
  if (p.p == start) p.p = start+5; 
  --p.p; 
  return p; 
} 
 
int main() { 
  char mem[4+1]; 
 
  if(pend(mem).p != mem+4) 
    abort (); 
} 
------------------------ 
g/x> /home/bangerth/bin/gcc-3.4-pre/bin/c++ x.cc ; ./a.out  
g/x> /home/bangerth/bin/gcc-3.4-pre/bin/c++ -O2 x.cc ; ./a.out  
Aborted 
 
The bug doesn't happen with 3.3.4 and mainline, but who knows whether this 
is due to a fix or just by chance. It's a regression in any case, so 
should be investigated, then we can see whether the same fix is 
necessary on other branches than 3.4.x as well. 
 
W. 
Comment 2 Mark Mitchell 2004-08-17 23:02:51 UTC
This is a GCSE bug.

In the 07.addressof dump, we have:

(insn 56 104 57 1 (parallel [
            (set (reg/f:SI 77)
                (plus:SI (reg/f:SI 20 frame)
                    (const_int -11 [0xfffffff5])))
            (clobber (reg:CC 17 flags))
        ]) 138 {*addsi_1} (nil)
    (nil))

(insn 57 56 58 1 (set (mem/s:SI (plus:SI (reg/f:SI 20 frame)
                (const_int -24 [0xffffffe8])) [4 p.p+0 S4 A32])
        (reg/f:SI 77)) 36 {*movsi_1} (nil)
    (nil))

(code_label 58 57 105 2 3 "" [1 uses])

(note 105 58 62 2 [bb 2] NOTE_INSN_BASIC_BLOCK)

(insn 62 105 63 2 (set (reg:SI 78 [ p.p ])
        (mem/s:SI (plus:SI (reg/f:SI 20 frame)
                (const_int -24 [0xffffffe8])) [4 p.p+0 S4 A32])) 36 {*movsi_1} (nil)
    (nil))

(insn 63 62 64 2 (parallel [
            (set (reg:SI 79)
                (plus:SI (reg:SI 78 [ p.p ])
                    (const_int -1 [0xffffffff])))
            (clobber (reg:CC 17 flags))
        ]) 138 {*addsi_1} (nil)
    (nil))

After GCSE, we have:

(insn 56 104 114 1 (parallel [
        (set (reg/f:SI 77)
                (plus:SI (reg/f:SI 20 frame)
                    (const_int -11 [0xfffffff5])))
            (clobber (reg:CC 17 flags))
        ]) 138 {*addsi_1} (nil)
    (nil))

(insn 114 56 58 1 (set (reg/f:SI 86 [ start ])
        (reg/f:SI 77)) -1 (nil)
    (nil))                                                                     

(code_label 58 114 105 2 3 "" [1 uses])

(note 105 58 112 2 [bb 2] NOTE_INSN_BASIC_BLOCK)

(insn 112 105 63 2 (set (reg/f:SI 78 [ p.p ])
        (reg/f:SI 86 [ start ])) -1 (nil)
    (expr_list:REG_EQUAL (mem/s:SI (plus:SI (reg/f:SI 20 frame)
                (const_int -24 [0xffffffe8])) [4 p.p+0 S4 A32])
        (nil)))

Note that we now have a REG_EQUAL note on insn 112 that is a lie, since insn 114
no longer sets the memory.
Comment 3 Mark Mitchell 2004-08-17 23:10:46 UTC
Created attachment 6951 [details]
Patch

I see no justification for GCSE assuming that, after PRE eliminiation, the
REG_EQUAL note is valid -- unless the value is a constant, and in that I don't
think we should be travelling this code path.

This patch fixes the affected test-case by eliminating the note.
Comment 4 Mark Mitchell 2004-08-17 23:11:42 UTC
Jeff, would you please take a look at my analysis and confirm/deny?

Thanks, 

-- Mark
Comment 5 Mark Mitchell 2004-08-29 19:02:48 UTC
Postponed until GCC 3.4.3.
Comment 7 GCC Commits 2004-08-29 19:40:24 UTC
Subject: Bug 16590

CVSROOT:	/cvs/gcc
Module name:	gcc
Changes by:	mmitchel@gcc.gnu.org	2004-08-29 19:40:21

Modified files:
	gcc            : ChangeLog gcse.c 
	gcc/testsuite  : ChangeLog 
Added files:
	gcc/testsuite/g++.dg/opt: loop1.C 

Log message:
	PR rtl-optimization/16590
	* gcse.c (pre_delete): Do not create invalid REG_EQUAL notes.
	
	PR rtl-optimization/16590
	* g++.dg/opt/loop1.C: New test.

Patches:
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/ChangeLog.diff?cvsroot=gcc&r1=2.5135&r2=2.5136
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/gcse.c.diff?cvsroot=gcc&r1=1.310&r2=1.311
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/opt/loop1.C.diff?cvsroot=gcc&r1=1.1&r2=1.2
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/ChangeLog.diff?cvsroot=gcc&r1=1.4206&r2=1.4207

Comment 8 Mark Mitchell 2004-08-29 19:42:09 UTC
Fixed in GCC 3.4.2.
Comment 9 Jeffrey A. Law 2004-08-30 20:22:47 UTC
Looks more like a bug in load/store motion to me, not a bogus REG_EQUAL note.
Comment 11 GCC Commits 2004-08-31 06:31:08 UTC
Subject: Bug 16590

CVSROOT:	/cvs/gcc
Module name:	gcc
Changes by:	mmitchel@gcc.gnu.org	2004-08-31 06:31:06

Modified files:
	gcc            : ChangeLog gcse.c 
	gcc/testsuite  : ChangeLog 
	gcc/testsuite/g++.dg/opt: loop1.C 

Log message:
	Revert:
	2004-08-29  Mark Mitchell  <mark@codesourcery.com>
	PR rtl-optimization/16590
	* gcse.c (pre_delete): Do not create invalid REG_EQUAL notes.
	
	* g++.dg/opt/loop1.C: XFAIL.

Patches:
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/ChangeLog.diff?cvsroot=gcc&r1=2.5165&r2=2.5166
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/gcse.c.diff?cvsroot=gcc&r1=1.311&r2=1.312
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/ChangeLog.diff?cvsroot=gcc&r1=1.4212&r2=1.4213
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/opt/loop1.C.diff?cvsroot=gcc&r1=1.2&r2=1.3

Comment 12 Jeffrey A. Law 2004-09-01 05:41:22 UTC
Fixed with today's checkin to gcse.c.  
Comment 13 Volker Reichelt 2004-09-01 10:19:36 UTC
The testcase gcc/gcc/testsuite/g++.dg/opt/loop1.C
is still XFAILed on mainline (which was wrong IMHO anyway)
and 3.4 branch. This should be fixed before the 4.3.2 release.
Comment 14 Volker Reichelt 2004-09-02 09:39:21 UTC
> This should be fixed before the 4.3.2 release.

I meant the 3.4.2 release, of course. :-)

Just for the record: Mark took care of the testcases, see
http://gcc.gnu.org/ml/gcc-cvs/2004-09/msg00057.html
http://gcc.gnu.org/ml/gcc-cvs/2004-09/msg00055.html