Placement new is specified to end life-time of the object starting life-time of
a new one.  The current implementation messes up with aliasing though, so
stores are re-ordered:

#include <new>
struct Foo { long i; };
struct Bar { void *p; };
long foo(int n)
{
  Foo *f = new Foo;
  f->i = 1;
  for (int i=0; i<n; ++i)
    {
      Bar *b = new (f) Bar;
      b->p = 0;
      f = new (f) Foo;
      f->i = i;
    }
  return f->i;
}

Produces .099t.optimized:

long int foo(int) (n)
{
  struct Foo * f;
  void * D.2530;

<bb 2>:
  D.2530 = operator new (8);
  f = (struct Foo *) D.2530;
  f->i = 1;
  if (n > 0) goto <L7>; else goto <L2>;

<L7>:;
  f->i = (long int) ((unsigned int) n - 1);
  ((struct Bar *) f)->p = 0B;

<L2>:;
  return f->i;

}

where the stores to Bar::p and Foo:i are reordered.  Until .147r.bbro
everything looks like above on RTL level, too:

...
;; Start of basic block 3, registers live: 1 [dx] 3 [bx] 7 [sp]
(note:HI 21 19 22 3 [bb 3] NOTE_INSN_BASIC_BLOCK)

(note:HI 22 21 48 3 NOTE_INSN_DELETED)

(insn 48 22 24 3 (set (reg:DI 0 ax [63])
        (zero_extend:DI (subreg:SI (plus:DI (reg:DI 3 bx [orig:61 n ] [61])
                    (const_int -1 [0xffffffffffffffff])) 0))) 195 {*lea_1_zext}
(nil)
    (expr_list:REG_DEAD (reg:DI 3 bx [orig:61 n ] [61])
        (nil)))

(insn:HI 24 48 25 3 (set (mem/s:DI (reg/v/f:DI 1 dx [orig:58 f ] [58]) [3
<variable>.i+0 S8 A64])
        (reg:DI 0 ax [63])) 81 {*movdi_1_rex64} (insn_list:REG_DEP_TRUE 23
(nil))
    (expr_list:REG_DEAD (reg:DI 0 ax [63])
        (nil)))

(insn:HI 25 24 26 3 (set (mem/s/f:DI (reg/v/f:DI 1 dx [orig:58 f ] [58]) [5
<variable>.p+0 S8 A64])
        (const_int 0 [0x0])) 81 {*movdi_1_rex64} (nil)
    (nil))
;; End of basic block 3, registers live:
 1 [dx] 7 [sp]
...

but now (unfortunately) scheduling reorders them back (on x86_64), so the
assembly looks good again:

_Z3fooi:
.LFB15:
        pushq   %rbx
.LCFI0:
        movl    %edi, %ebx
        movl    $8, %edi
        call    _Znwm
        testl   %ebx, %ebx
        movq    %rax, %rdx
        movq    $1, (%rax)
        jle     .L2
        leal    -1(%rbx), %eax
        movq    $0, (%rdx)
        movq    %rax, (%rdx)
.L2:
        popq    %rbx
        movq    (%rdx), %rax
        ret

But with -O2 -fno-schedule-insns2 we finally get wrong-code for this:

_Z3fooi:
.LFB15:
        pushq   %rbx
.LCFI0:
        movl    %edi, %ebx
        movl    $8, %edi
        call    _Znwm
        movq    %rax, %rdx
        movq    $1, (%rax)
        testl   %ebx, %ebx
        jle     .L2
        leal    -1(%rbx), %eax
        movq    %rax, (%rdx)
        movq    $0, (%rdx)
.L2:
        movq    (%rdx), %rax
        popq    %rbx
        ret


-- 
           Summary: placement new does not provide required side-effects
           Product: gcc
           Version: 4.2.0
            Status: UNCONFIRMED
          Keywords: wrong-code, alias
          Severity: normal
          Priority: P3
         Component: libstdc++
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: rguenth at gcc dot gnu dot org


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29286

Reply via email to