------- Comment #73 from rguenth at gcc dot gnu dot org  2007-05-16 15:02 
-------
For the following testcase, loop store motion re-orders the writes to *l and *f
at -O2.  (Note as is, the testcase is only valid for n == 1)

inline void* operator new(unsigned long, void* __p) throw() { return __p; }

extern void bar();

long foo(double *p, int n)
{
  long *f;
  for (int i=0; i<n; ++i)
  {
    int *l = (int *)p;
    *l = 0;
    f = new (p) long;
    *f = -1;
  }
  bar ();
  return *f;
}

and we end up with

<bb 2>:
  if (n > 0)
    goto <bb 3>;
  else
    goto <bb 4>;

<bb 3>:
  f = (long int *) p;
  <<<change_dynamic_type (long int *) p)>>>
  # SMT.4_27 = VDEF <SMT.4_19(D)>
  *f = -1;
  # SMT.5_35 = VDEF <SMT.5_20(D)>
  *(int *) p = 0;

<bb 4>:
  # SMT.4_23 = VDEF <SMT.4_32>
  # SMT.5_24 = VDEF <SMT.5_34>
  bar ();
  return *f;

which is wrong.  Runtime testcase that aborts:

inline void* operator new(unsigned long, void* __p) throw() { return __p; }

void __attribute__((noinline)) bar() {};

long __attribute__((noinline)) foo(double *p, int n)
{
  long *f;
  for (int i=0; i<n; ++i)
  {
    int *l = (int *)p;
    *l = 0;
    f = new (p) long;
    *f = -1;
  }
  bar ();
  return *f;
}

extern "C" void abort(void);
int main()
{
  union {
    int i;
    long l;
  } u;
  if (foo((double *)&u, 1) != -1)
    abort ();
  return 0;
}


-- 


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

Reply via email to