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.
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() { };
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));
38 class Domain : public DomainBase<DT>
40 typedef DomainBase<DT> Base_t;
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(); }
53 void setDomain(const T &newdom) {
54 DT::setDomain(this->domain_m, newdom);
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(); }
68 struct DomainTraits<Interval>
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; }
88 static void setDomain(Storage_t &dom, const T &newdom) {
89 dom[0] = newdom.first();
90 dom[1] = newdom.length();
93 template<class T1, class T2>
94 static void setDomain(Storage_t &dom, const T1 &begval, const T2 &endval) {
96 dom[1] = (endval - begval + 1);
101 class Interval : public Domain<DomainTraits<Interval> >
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));
110 Interval(int a) : Domain<DomainTraits<Interval> >()
112 DomainTraits<Interval>::setDomain(domain_m, 0, a - 1);
117 struct DomainTraits<Loc>
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; }
129 static void setDomain(int &dom, const T &newdom) {
130 dom = DomainTraits<T>::getFirst(newdom);
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> >
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));
154 struct ElementProperties
156 enum { hasTrivialDefaultConstructor = false };
157 enum { hasTrivialDestructor = false };
159 static void construct(double* addr)
164 static void construct(double* addr, const double& model)
166 new (addr) double(model);
169 static void destruct(double *addr) {}
175 RefCounted() : count_m(0) {}
177 void addReference() { ++count_m; }
178 bool removeRefAndCheckGarbage()
180 return (--count_m == 0);
187 class RefBlockController : public RefCounted
190 explicit RefBlockController(unsigned int size)
191 : pBegin_m(0), pEnd_m(0), pEndOfStorage_m(0), dealloc_m(false)
193 reallocateStorage(size, false);
195 if (!ElementProperties::hasTrivialDefaultConstructor)
197 for (double * pt = begin(); pt != end(); ++pt)
198 ElementProperties::construct(pt);
202 ~RefBlockController()
207 double *begin() const
225 if (isMine() && pBegin_m != 0)
227 if (!ElementProperties::hasTrivialDestructor)
228 for (double *pt = begin(); pt != end(); ++pt)
229 ElementProperties::destruct(pt);
231 char *tmp = reinterpret_cast<char *>(pBegin_m);
236 void reallocateStorage(unsigned int newsize, bool copyold = false)
238 double *pBeginNew = 0;
240 double *pEndOfStorageNew = 0;
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));
252 double * pOld = begin();
253 double * pNew = pBeginNew;
254 while (pOld != end() && pNew != pEndNew)
255 ElementProperties::construct(pNew++,*pOld++);
261 pBegin_m = pBeginNew;
263 pEndOfStorage_m = pEndOfStorageNew;
269 double *pEndOfStorage_m;
273 class DataBlockController : public RefBlockController
277 DataBlockController(unsigned int size)
278 : RefBlockController(size), dataObjectPtr_m(new char), owned_m(true) {}
280 ~DataBlockController()
282 if (owned_m) delete dataObjectPtr_m;
286 mutable char *dataObjectPtr_m;
293 RefCountedPtr(DataBlockController * const pT) : ptr_m(pT)
294 { if (isValid()) ptr_m->addReference(); }
296 ~RefCountedPtr() { invalidate(); }
298 DataBlockController* operator->() const { return ptr_m; }
300 bool isValid() const { return ptr_m != 0; }
303 friend class RefCountedBlockPtr;
304 DataBlockController * ptr_m;
307 inline void RefCountedPtr::invalidate()
309 if ( isValid() && ptr_m->removeRefAndCheckGarbage() )
314 class RefCountedBlockPtr
317 explicit RefCountedBlockPtr(unsigned int size)
319 blockControllerPtr_m(new DataBlockController(size)) {}
326 double *beginPointer() const
328 return blockControllerPtr_m->begin();
331 double *currentPointer() const
333 return beginPointer() + offset();
338 RefCountedPtr blockControllerPtr_m;
341 class DataBlockPtr : public RefCountedBlockPtr
344 explicit DataBlockPtr(unsigned int size) : RefCountedBlockPtr(size) {}
350 Node(const Interval &owned, const Interval &allocated)
351 : domain_m(owned), allocated_m(allocated) {}
353 const Interval &allocated() const { return allocated_m; }
357 Interval allocated_m;
363 explicit DomainLayout(const Interval &dom) : node_m(0, dom) {}
365 const Interval &domain() const
367 return node_m.allocated();
377 explicit BrickBase(const Interval &domain);
379 int offset(const Loc &dom) const { return off_m + dom[0].first(); }
382 DomainLayout layout_m;
387 BrickBase::BrickBase(const Interval &dom)
390 firsts_m = layout_m.domain()[0].first();
394 class Engine : public BrickBase
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
402 return data_m[this->offset(loc)];
406 DataBlockPtr dataBlock_m;
416 for (int i = 0; i < 10; i++)
417 A(Loc(i)) = 2.0 + i - i*i;