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

[testcase] GCC 3.1 NRV related miscompilation


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


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