This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[testcase] GCC 3.1 NRV related miscompilation
- From: Jakub Jelinek <jakub at redhat dot com>
- To: jason at redhat dot com, mark at codesourcery dot com
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Thu, 11 Jul 2002 11:28:29 +0200
- Subject: [testcase] GCC 3.1 NRV related miscompilation
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
Hi!
The following testcase is miscompiled by g++ 3.1 (haven't tried 3.2 yet)
on IA-32, a regression from 3.0 and earlier.
The problem is I think in NRV optimization, already in .rtl dump there is
(pseudo 62 is never set, no jumps in this sequence):
(insn 30 28 32 (set (mem/s:SI (plus:SI (reg/f:SI 54 virtual-stack-vars)
(const_int -4 [0xfffffffc])) [0 S4 A32])
(reg:SI 62)) -1 (nil)
(nil))
...very long code to set low 8 bits of (mem/s:SI (virtual-stack-vars - 4))
to 0x55 while leaving garbage in the upper 24 bits (of padding)...
(insn 104 102 106 (set (mem/s:SI (plus:SI (reg/f:SI 54 virtual-stack-vars)
(const_int -4 [0xfffffffc])) [0 S4 A32])
(reg:SI 62)) -1 (nil)
(nil))
and this insn (uid 104) smashes everything computed so far, so
in the final assembly we end up with
movl %ecx, %eax
andl $-4, %eax
where %ecx was never initialized in the routine, thus only low 2 bits
are correct and the 6 single-bit bitfields s1..s6 contain random garbage.
If I force NRV not to be used (adding "&& 0" to cp/decl.c:
14298 /* This is only worth doing for fns that return in memory--and
14299 simpler, since we don't have to worry about promoted modes. */
14300 if (r != error_mark_node
14301 && aggregate_value_p (TREE_TYPE (TREE_TYPE (fndecl))))
), then the testcase is compiled correctly (although another thing is that
it is not optimized as it should:
movl %edx, %eax
andl $-4, %eax
orl $1, %eax
movl %eax, %edx
orl $4, %eax
movb %al, %dl
andb $-9, %dl
orb $16, %dl
andb $-33, %dl
orb $64, %dl
movl %edx, %eax
andl $-132, %eax
is terrible code for
movl $0x54, %eax
or if the random garbage is really needed (which it is not),
movb $0x54, %dl
movl %edx, %eax
).
2002-07-11 Jakub Jelinek <jakub@redhat.com>
* g++.dg/opt/nrv3.C: New test.
--- gcc/testsuite/g++.dg/opt/nrv3.C.jj Thu Apr 11 16:25:15 2002
+++ gcc/testsuite/g++.dg/opt/nrv3.C Thu Jul 11 11:29:33 2002
@@ -0,0 +1,52 @@
+// Test for the named return value optimization with inlining.
+// Contributed by Jakub Jelinek <jakub@redhat.com>.
+// { dg-do run }
+// { dg-options -O2 }
+
+enum E { E0, E1, E2, E3 };
+
+struct S
+{
+ E s0 : 2;
+ bool s1 : 1, s2 : 1, s3 : 1, s4 : 1, s5 : 1, s6 : 1;
+ S () : s1 (true), s2 (false), s0 (E1), s3 (true), s4 (false), s5 (true), s6 (false) {}
+ void foo (E x) { this->s0 = x; }
+};
+
+inline S foo ()
+{
+ S s;
+ s.foo (E0);
+ return s;
+}
+
+inline S bar ()
+{
+ S s;
+ s.foo (E2);
+ return s;
+}
+
+void check (S &s, bool isfoo);
+
+void test (bool isfoo)
+{
+ S a = isfoo ? foo () : bar ();
+ check (a, isfoo);
+}
+
+extern "C" void abort ();
+
+void check (S &s, bool isfoo)
+{
+ if (! s.s1 || s.s2 || ! s.s3 || s.s4 || ! s.s5 || s.s6)
+ abort ();
+ if (s.s0 != (isfoo ? E0 : E2))
+ abort ();
+}
+
+int main ()
+{
+ test (true);
+ test (false);
+}
Jakub