1// { dg-do compile }
2// { dg-options "-O2 -fstrict-aliasing -fdump-tree-pre-details" }
3
4// Make sure we hoist invariants out of the loop even in the presence
5// of placement new.  This is similar to code in tramp3d.
6
7typedef __SIZE_TYPE__ size_t;
8
9inline void* operator new(size_t, void* __p) throw() { return __p; }
10
11template <class T, int D>
12class Vector
13{
14public:
15   Vector()
16   {
17     for (int i = 0; i < D; ++i)
18        new (&x_m[i]) T();
19   }
20   T& operator[](int i) { return x_m[i]; }
21
22private:
23   T x_m[D];
24};
25
26struct sia
27{
28  int ai[3];
29};
30
31struct s
32{
33  struct si
34  {
35    sia* p;
36  } asi[3];
37  float* pd;
38};
39
40class c
41{
42  int foo(int, int, int);
43  s sm;
44};
45
46
47extern void bar(Vector<float, 3>*, int);
48int c::foo(int f1, int f2, int f3)
49{
50  float sum = 0;
51  for (int i = 0; i < 3; ++i)
52    {
53      for (int j = 0; j < 3; ++j)
54	{
55	  Vector<float, 3> v;
56	  v[0] = 1.0;
57	  v[1] = 2.0;
58	  v[2] = 3.0;
59	  for (int k = 0; k < 3; ++k)
60	    {
61	      float f = (f1 * this->sm.asi[0].p->ai[0]
62			 + f2 * this->sm.asi[1].p->ai[0]
63			 + f3 * this->sm.asi[2].p->ai[0]);
64	      sum += f * v[k];
65	    }
66	  *this->sm.pd = sum;
67	}
68    }
69  return sum;
70}
71
72// { dg-final { scan-tree-dump "Replaced.*->ai\\\[0\\\]" "pre" } }
73// { dg-final { cleanup-tree-dump "pre" } }
74