Home | History | Annotate | Download | only in jni
      1 // PR optimization/12340
      2 // Origin: Richard Guenther <richard.guenther (at) uni-tuebingen.de>
      3 // Testcase by Eric Botcazou <ebotcazou (at) libertysurf.fr>
      4 
      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.
      8 
      9 // { dg-do run }
     10 // { dg-options "-O2 -fno-exceptions -funroll-loops" }
     11 
     12 typedef __SIZE_TYPE__ size_t;
     13 
     14 inline void* operator new(size_t, void* __p) throw() { return __p; }
     15 inline void operator delete (void*, void*) throw() { };
     16 
     17 class Loc;
     18 class Interval;
     19 
     20 template<class DT>
     21 class DomainBase
     22 {
     23 public:
     24   typedef typename DT::Domain_t Domain_t;
     25   typedef typename DT::Storage_t Storage_t;
     26 
     27   Domain_t &unwrap() { return *static_cast<Domain_t *>(this); }
     28 
     29   const Domain_t &unwrap() const {
     30     return *static_cast<Domain_t *>(const_cast<DomainBase<DT> *>(this));
     31   }
     32 
     33 protected:
     34   Storage_t domain_m;
     35 };
     36 
     37 template<class DT>
     38 class Domain : public DomainBase<DT>
     39 {
     40   typedef DomainBase<DT> Base_t;
     41 
     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;
     47 
     48   Domain_t &operator[](int) { return this->unwrap(); }
     49 
     50   const Domain_t &operator[](int) const { return this->unwrap(); }
     51 
     52   template<class T>
     53   void setDomain(const T &newdom) {
     54     DT::setDomain(this->domain_m, newdom);
     55   }
     56 
     57   Element_t first() const { return DT::first(this->domain_m); }
     58 
     59   Size_t length() const { return DT::length(this->domain_m); }
     60 
     61   Size_t size() const { return length(); }
     62 };
     63 
     64 template<class T>
     65 struct DomainTraits;
     66 
     67 template<>
     68 struct DomainTraits<Interval>
     69 {
     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 };
     78 
     79   static int first(const Storage_t &d) { return d[0]; }
     80 
     81   static int length(const Storage_t &d) { return d[1]; }
     82 
     83   static OneDomain_t &getDomain(Domain_t &d, int) { return d; }
     84 
     85   static const OneDomain_t &getDomain(const Domain_t &d, int) { return d; }
     86 
     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   }
     92 
     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   }
     98 
     99 };
    100 
    101 class Interval : public Domain<DomainTraits<Interval> >
    102 {
    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   }
    109 
    110   Interval(int a) : Domain<DomainTraits<Interval> >()
    111   {
    112     DomainTraits<Interval>::setDomain(domain_m, 0, a - 1);
    113   }
    114 };
    115 
    116 template<>
    117 struct DomainTraits<Loc>
    118 {
    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;
    125 
    126   static int first(int d) { return d; }
    127 
    128   template<class T>
    129   static void setDomain(int &dom, const T &newdom) {
    130     dom = DomainTraits<T>::getFirst(newdom);
    131   }
    132 };
    133 
    134 template<>
    135 struct DomainTraits<int>
    136  {
    137   enum { dimensions = 1 };
    138   enum { wildcard = false };
    139 
    140   static int getPointDomain(int d, int) { return d; }
    141 
    142   static int getFirst(const int &d) { return d; }
    143 };
    144 
    145 class Loc : public Domain<DomainTraits<Loc> >
    146 {
    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   }
    152 };
    153 
    154 struct ElementProperties
    155 {
    156   enum { hasTrivialDefaultConstructor = false };
    157   enum { hasTrivialDestructor = false };
    158 
    159   static void construct(double* addr)
    160   {
    161     new (addr) double();
    162   }
    163 
    164   static void construct(double* addr, const double& model)
    165   {
    166     new (addr) double(model);
    167   }
    168 
    169   static void destruct(double *addr) {}
    170 };
    171 
    172 class RefCounted
    173 {
    174 public:
    175   RefCounted() : count_m(0) {}
    176 
    177   void addReference() { ++count_m; }
    178   bool removeRefAndCheckGarbage()
    179   {
    180     return (--count_m == 0);
    181   }
    182 
    183 private:
    184   int count_m;
    185 };
    186 
    187 class RefBlockController : public RefCounted
    188 {
    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);
    194 
    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   }
    206 
    207   double *begin() const
    208   {
    209     return pBegin_m;
    210   }
    211 
    212   double *end() const
    213   {
    214     return pEnd_m;
    215   }
    216 
    217   bool isMine() const
    218   {
    219     return dealloc_m;
    220   }
    221 
    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);
    230 
    231         char *tmp = reinterpret_cast<char *>(pBegin_m);
    232         delete [] tmp;
    233       }
    234   }
    235 
    236   void reallocateStorage(unsigned int newsize, bool copyold = false)
    237   {
    238     double *pBeginNew = 0;
    239     double *pEndNew = 0;
    240     double *pEndOfStorageNew = 0;
    241 
    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));
    249 
    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       }
    258 
    259     deleteStorage();
    260 
    261     pBegin_m = pBeginNew;
    262     pEnd_m = pEndNew;
    263     pEndOfStorage_m = pEndOfStorageNew;
    264     dealloc_m = true;
    265   }
    266 
    267   double *pBegin_m;
    268   double *pEnd_m;
    269   double *pEndOfStorage_m;
    270   bool dealloc_m;
    271 };
    272 
    273 class DataBlockController : public RefBlockController
    274 {
    275 public:
    276   explicit
    277   DataBlockController(unsigned int size)
    278     : RefBlockController(size), dataObjectPtr_m(new char), owned_m(true) {}
    279 
    280   ~DataBlockController()
    281   {
    282     if (owned_m) delete dataObjectPtr_m;
    283   }
    284 
    285 private:
    286   mutable char *dataObjectPtr_m;
    287   bool owned_m;
    288 };
    289 
    290 class RefCountedPtr
    291 {
    292 public:
    293   RefCountedPtr(DataBlockController * const pT) : ptr_m(pT)
    294     { if (isValid()) ptr_m->addReference(); }
    295 
    296   ~RefCountedPtr() { invalidate(); }
    297 
    298   DataBlockController* operator->() const { return ptr_m; }
    299   void invalidate();
    300   bool isValid() const { return ptr_m != 0; }
    301 
    302 private:
    303   friend class RefCountedBlockPtr;
    304   DataBlockController * ptr_m;
    305 };
    306 
    307 inline void RefCountedPtr::invalidate()
    308 {
    309   if ( isValid() && ptr_m->removeRefAndCheckGarbage() )
    310     delete ptr_m;
    311   ptr_m = 0;
    312 }
    313 
    314 class RefCountedBlockPtr
    315 {
    316 public:
    317   explicit RefCountedBlockPtr(unsigned int size)
    318     : offset_m(0),
    319       blockControllerPtr_m(new DataBlockController(size)) {}
    320 
    321   int offset() const
    322   {
    323     return offset_m;
    324   }
    325 
    326   double *beginPointer() const
    327   {
    328     return blockControllerPtr_m->begin();
    329   }
    330 
    331   double *currentPointer() const
    332   {
    333     return beginPointer() + offset();
    334   }
    335 
    336 protected:
    337   int offset_m;
    338   RefCountedPtr blockControllerPtr_m;
    339 };
    340 
    341 class DataBlockPtr : public RefCountedBlockPtr
    342 {
    343 public:
    344   explicit DataBlockPtr(unsigned int size) : RefCountedBlockPtr(size) {}
    345 };
    346 
    347 class Node
    348 {
    349 public:
    350   Node(const Interval &owned, const Interval &allocated)
    351     : domain_m(owned), allocated_m(allocated) {}
    352 
    353   const Interval &allocated() const { return allocated_m; }
    354 
    355 private:
    356   Interval domain_m;
    357   Interval allocated_m;
    358 };
    359 
    360 class DomainLayout
    361 {
    362 public:
    363   explicit DomainLayout(const Interval &dom) : node_m(0, dom) {}
    364 
    365   const Interval &domain() const
    366   {
    367     return node_m.allocated();
    368   }
    369 
    370 private:
    371   Node node_m;
    372 };
    373 
    374 class BrickBase
    375 {
    376 public:
    377   explicit BrickBase(const Interval &domain);
    378 
    379   int offset(const Loc &dom) const { return off_m + dom[0].first(); }
    380 
    381 protected:
    382   DomainLayout layout_m;
    383   int firsts_m;
    384   int off_m;
    385 };
    386 
    387 BrickBase::BrickBase(const Interval &dom)
    388   : layout_m(dom)
    389 {
    390   firsts_m = layout_m.domain()[0].first();
    391   off_m = -firsts_m;
    392 }
    393 
    394 class Engine : public BrickBase
    395 {
    396 public:
    397   explicit Engine(const Interval &dom)
    398   : BrickBase(dom), dataBlock_m(dom.size()), data_m(dataBlock_m.currentPointer()) {}
    399 
    400   double& operator()(const Loc &loc) const
    401   {
    402     return data_m[this->offset(loc)];
    403   }
    404 
    405 private:
    406   DataBlockPtr dataBlock_m;
    407   double *data_m;
    408 };
    409 
    410 int
    411 main()
    412 {
    413   Interval I(10);
    414   Engine A(I);
    415 
    416   for (int i = 0; i < 10; i++)
    417     A(Loc(i)) = 2.0 + i - i*i;
    418 
    419   return 0;
    420 }
    421