Remove old autovect-branch by moving to "dead" directory.
[official-gcc.git] / old-autovect-branch / gcc / testsuite / g++.dg / opt / unroll1.C
blobfd07f889a1d1c548ba1943ea30338088a2ccde3c
1 // PR optimization/12340
2 // Origin: Richard Guenther <richard.guenther@uni-tuebingen.de>
3 // Testcase by Eric Botcazou <ebotcazou@libertysurf.fr>
5 // This used to segfault on x86 because the loop optimizer wrongly
6 // interpreted a double assignment to a biv as a double increment,
7 // which subsequently fooled the unroller.
9 // { dg-do run }
10 // { dg-options "-O2 -fno-exceptions -funroll-loops" }
12 typedef __SIZE_TYPE__ size_t;
14 inline void* operator new(size_t, void* __p) throw() { return __p; }
15 inline void operator delete (void*, void*) throw() { };
17 class Loc;
18 class Interval;
20 template<class DT>
21 class DomainBase
23 public:
24   typedef typename DT::Domain_t Domain_t;
25   typedef typename DT::Storage_t Storage_t;
27   Domain_t &unwrap() { return *static_cast<Domain_t *>(this); }
29   const Domain_t &unwrap() const {
30     return *static_cast<Domain_t *>(const_cast<DomainBase<DT> *>(this));
31   }
33 protected:
34   Storage_t domain_m;
37 template<class DT>
38 class Domain : public DomainBase<DT>
40   typedef DomainBase<DT> Base_t;
42 public:
43   typedef typename DT::Size_t Size_t;
44   typedef typename DT::Element_t Element_t;
45   typedef typename Base_t::Domain_t Domain_t;
46   typedef typename Base_t::Storage_t Storage_t;
48   Domain_t &operator[](int) { return this->unwrap(); }
50   const Domain_t &operator[](int) const { return this->unwrap(); }
52   template<class T>
53   void setDomain(const T &newdom) {
54     DT::setDomain(this->domain_m, newdom);
55   }
57   Element_t first() const { return DT::first(this->domain_m); }
59   Size_t length() const { return DT::length(this->domain_m); }
61   Size_t size() const { return length(); }
64 template<class T>
65 struct DomainTraits;
67 template<>
68 struct DomainTraits<Interval>
70   typedef int Size_t;
71   typedef int Element_t;
72   typedef Interval Domain_t;
73   typedef Interval OneDomain_t;
74   typedef Loc AskDomain_t;
75   typedef int Storage_t[2];
76   enum { dimensions = 1 };
77   enum { wildcard = false };
79   static int first(const Storage_t &d) { return d[0]; }
81   static int length(const Storage_t &d) { return d[1]; }
83   static OneDomain_t &getDomain(Domain_t &d, int) { return d; }
85   static const OneDomain_t &getDomain(const Domain_t &d, int) { return d; }
87   template<class T>
88   static void setDomain(Storage_t &dom, const T &newdom) {
89     dom[0] = newdom.first();  
90     dom[1] = newdom.length();
91   }
93   template<class T1, class T2>
94   static void setDomain(Storage_t &dom, const T1 &begval, const T2 &endval) {
95     dom[0] = begval;
96     dom[1] = (endval - begval + 1);
97   }
101 class Interval : public Domain<DomainTraits<Interval> >
103 public:
104   Interval(const Interval &a) : Domain<DomainTraits<Interval> >() {    
105     for (int i=0; i < DomainTraits<Interval>::dimensions; ++i)
106       DomainTraits<Interval>::getDomain(*this, i).setDomain(
107                                 DomainTraits<Interval>::getDomain(a, i));
108   }
110   Interval(int a) : Domain<DomainTraits<Interval> >()
111   {
112     DomainTraits<Interval>::setDomain(domain_m, 0, a - 1);
113   }
116 template<>
117 struct DomainTraits<Loc>
119   typedef int Size_t;
120   typedef int Element_t;
121   typedef Loc Domain_t;
122   typedef Loc AskDomain_t;
123   typedef Loc MultResult_t;
124   typedef int Storage_t;
126   static int first(int d) { return d; }
128   template<class T>
129   static void setDomain(int &dom, const T &newdom) {
130     dom = DomainTraits<T>::getFirst(newdom);
131   }
134 template<>
135 struct DomainTraits<int>
137   enum { dimensions = 1 };
138   enum { wildcard = false };
140   static int getPointDomain(int d, int) { return d; }
142   static int getFirst(const int &d) { return d; }
145 class Loc : public Domain<DomainTraits<Loc> >
147 public:
148   explicit Loc(const int &a) : Domain<DomainTraits<Loc> >() {
149     for (int i=0; i < 1; ++i)
150       (*this)[i].setDomain(DomainTraits<int>::getPointDomain(a, 0));
151   }
154 struct ElementProperties
156   enum { hasTrivialDefaultConstructor = false };
157   enum { hasTrivialDestructor = false };
159   static void construct(double* addr)
160   {
161     new (addr) double();
162   }
164   static void construct(double* addr, const double& model)
165   {
166     new (addr) double(model);
167   }
169   static void destruct(double *addr) {}
172 class RefCounted
174 public:
175   RefCounted() : count_m(0) {}
177   void addReference() { ++count_m; }
178   bool removeRefAndCheckGarbage()
179   {
180     return (--count_m == 0);
181   }
183 private:
184   int count_m;
187 class RefBlockController : public RefCounted
189 public:
190   explicit RefBlockController(unsigned int size)
191     : pBegin_m(0), pEnd_m(0), pEndOfStorage_m(0), dealloc_m(false)
192   {
193     reallocateStorage(size, false);
195     if (!ElementProperties::hasTrivialDefaultConstructor)
196       {
197         for (double * pt = begin(); pt != end(); ++pt)
198           ElementProperties::construct(pt);
199       }
200   }
201   
202   ~RefBlockController()
203   {
204     deleteStorage();
205   }
207   double *begin() const
208   {
209     return pBegin_m;
210   }
212   double *end() const
213   {
214     return pEnd_m;
215   }
217   bool isMine() const
218   {
219     return dealloc_m;
220   }
222 private:
223   void deleteStorage()
224   {
225     if (isMine() && pBegin_m != 0)
226       {
227         if (!ElementProperties::hasTrivialDestructor)
228           for (double *pt = begin(); pt != end(); ++pt)
229             ElementProperties::destruct(pt);
231         char *tmp = reinterpret_cast<char *>(pBegin_m);
232         delete [] tmp;
233       }
234   }
236   void reallocateStorage(unsigned int newsize, bool copyold = false)
237   {
238     double *pBeginNew = 0;
239     double *pEndNew = 0;
240     double *pEndOfStorageNew = 0;
242     if (newsize > 0)
243       {
244         int nsize = newsize * sizeof(double);
245         char *tmp = new char[nsize];
246         pBeginNew = reinterpret_cast<double *>(tmp);
247         pEndNew = pBeginNew + newsize;
248         pEndOfStorageNew = pBeginNew + (nsize / sizeof(double));
250         if (copyold)
251           {
252             double * pOld = begin();
253             double * pNew = pBeginNew;
254             while (pOld != end() && pNew != pEndNew)
255               ElementProperties::construct(pNew++,*pOld++);
256           }
257       }
259     deleteStorage();
261     pBegin_m = pBeginNew;
262     pEnd_m = pEndNew;
263     pEndOfStorage_m = pEndOfStorageNew;
264     dealloc_m = true;
265   }
267   double *pBegin_m;
268   double *pEnd_m;
269   double *pEndOfStorage_m;
270   bool dealloc_m;
273 class DataBlockController : public RefBlockController
275 public:
276   explicit
277   DataBlockController(unsigned int size)
278     : RefBlockController(size), dataObjectPtr_m(new char), owned_m(true) {}
280   ~DataBlockController()
281   {
282     if (owned_m) delete dataObjectPtr_m;
283   }
285 private:
286   mutable char *dataObjectPtr_m;
287   bool owned_m;
290 class RefCountedPtr
292 public:
293   RefCountedPtr(DataBlockController * const pT) : ptr_m(pT)
294     { if (isValid()) ptr_m->addReference(); }
296   ~RefCountedPtr() { invalidate(); }
298   DataBlockController* operator->() const { return ptr_m; }
299   void invalidate();
300   bool isValid() const { return ptr_m != 0; }
302 private:
303   friend class RefCountedBlockPtr;
304   DataBlockController * ptr_m;
307 inline void RefCountedPtr::invalidate()
309   if ( isValid() && ptr_m->removeRefAndCheckGarbage() )
310     delete ptr_m;
311   ptr_m = 0;
314 class RefCountedBlockPtr
316 public:
317   explicit RefCountedBlockPtr(unsigned int size)
318     : offset_m(0),
319       blockControllerPtr_m(new DataBlockController(size)) {}
321   int offset() const
322   {
323     return offset_m;
324   }
326   double *beginPointer() const
327   {
328     return blockControllerPtr_m->begin();
329   }
331   double *currentPointer() const
332   {
333     return beginPointer() + offset();
334   }
336 protected:
337   int offset_m;
338   RefCountedPtr blockControllerPtr_m;
341 class DataBlockPtr : public RefCountedBlockPtr
343 public:
344   explicit DataBlockPtr(unsigned int size) : RefCountedBlockPtr(size) {}
347 class Node
349 public:
350   Node(const Interval &owned, const Interval &allocated)
351     : domain_m(owned), allocated_m(allocated) {}
353   const Interval &allocated() const { return allocated_m; }
355 private:
356   Interval domain_m;
357   Interval allocated_m;
360 class DomainLayout
362 public:
363   explicit DomainLayout(const Interval &dom) : node_m(0, dom) {}
365   const Interval &domain() const
366   {
367     return node_m.allocated();
368   }
370 private:
371   Node node_m;
374 class BrickBase
376 public:
377   explicit BrickBase(const Interval &domain);
379   int offset(const Loc &dom) const { return off_m + dom[0].first(); }
381 protected:
382   DomainLayout layout_m;
383   int firsts_m;
384   int off_m;
387 BrickBase::BrickBase(const Interval &dom)
388   : layout_m(dom)
390   firsts_m = layout_m.domain()[0].first();
391   off_m = -firsts_m;
394 class Engine : public BrickBase
396 public:
397   explicit Engine(const Interval &dom)
398   : BrickBase(dom), dataBlock_m(dom.size()), data_m(dataBlock_m.currentPointer()) {}
400   double& operator()(const Loc &loc) const
401   {
402     return data_m[this->offset(loc)];
403   }
405 private:
406   DataBlockPtr dataBlock_m;
407   double *data_m;
411 int main()
413   Interval I(10);
414   Engine A(I);
416   for (int i = 0; i < 10; i++)
417     A(Loc(i)) = 2.0 + i - i*i;
419   return 0;