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; }
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.
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.
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.
Jeff, would you please take a look at my analysis and confirm/deny? Thanks, -- Mark
Postponed until GCC 3.4.3.
Subject: Bug 16590 CVSROOT: /cvs/gcc Module name: gcc Branch: gcc-3_4-branch Changes by: mmitchel@gcc.gnu.org 2004-08-29 19:34:34 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&only_with_tag=gcc-3_4-branch&r1=2.2326.2.601&r2=2.2326.2.602 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/gcse.c.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=1.288.2.4&r2=1.288.2.5 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/opt/loop1.C.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=NONE&r2=1.1.2.1 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/ChangeLog.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=1.3389.2.261&r2=1.3389.2.262
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
Fixed in GCC 3.4.2.
Looks more like a bug in load/store motion to me, not a bogus REG_EQUAL note.
Subject: Bug 16590 CVSROOT: /cvs/gcc Module name: gcc Branch: gcc-3_4-branch Changes by: mmitchel@gcc.gnu.org 2004-08-31 06:28:43 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&only_with_tag=gcc-3_4-branch&r1=2.2326.2.602&r2=2.2326.2.603 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/gcse.c.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=1.288.2.5&r2=1.288.2.6 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/ChangeLog.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=1.3389.2.262&r2=1.3389.2.263 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/opt/loop1.C.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=1.1.2.1&r2=1.1.2.2
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
Fixed with today's checkin to gcse.c.
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.
> 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