📄 unroll1.c
字号:
// PR optimization/12340// Origin: Richard Guenther <richard.guenther@uni-tuebingen.de>// Testcase by Eric Botcazou <ebotcazou@libertysurf.fr>// This used to segfault on x86 because the loop optimizer wrongly// interpreted a double assignment to a biv as a double increment,// which subsequently fooled the unroller.// { dg-do run }// { dg-options "-O2 -fno-exceptions -funroll-loops" }typedef __SIZE_TYPE__ size_t;inline void* operator new(size_t, void* __p) throw() { return __p; }inline void operator delete (void*, void*) throw() { };class Loc;class Interval;template<class DT>class DomainBase{public: typedef typename DT::Domain_t Domain_t; typedef typename DT::Storage_t Storage_t; Domain_t &unwrap() { return *static_cast<Domain_t *>(this); } const Domain_t &unwrap() const { return *static_cast<Domain_t *>(const_cast<DomainBase<DT> *>(this)); }protected: Storage_t domain_m;};template<class DT>class Domain : public DomainBase<DT>{ typedef DomainBase<DT> Base_t;public: typedef typename DT::Size_t Size_t; typedef typename DT::Element_t Element_t; typedef typename Base_t::Domain_t Domain_t; typedef typename Base_t::Storage_t Storage_t; Domain_t &operator[](int) { return this->unwrap(); } const Domain_t &operator[](int) const { return this->unwrap(); } template<class T> void setDomain(const T &newdom) { DT::setDomain(this->domain_m, newdom); } Element_t first() const { return DT::first(this->domain_m); } Size_t length() const { return DT::length(this->domain_m); } Size_t size() const { return length(); }};template<class T>struct DomainTraits;template<>struct DomainTraits<Interval>{ typedef int Size_t; typedef int Element_t; typedef Interval Domain_t; typedef Interval OneDomain_t; typedef Loc AskDomain_t; typedef int Storage_t[2]; enum { dimensions = 1 }; enum { wildcard = false }; static int first(const Storage_t &d) { return d[0]; } static int length(const Storage_t &d) { return d[1]; } static OneDomain_t &getDomain(Domain_t &d, int) { return d; } static const OneDomain_t &getDomain(const Domain_t &d, int) { return d; } template<class T> static void setDomain(Storage_t &dom, const T &newdom) { dom[0] = newdom.first(); dom[1] = newdom.length(); } template<class T1, class T2> static void setDomain(Storage_t &dom, const T1 &begval, const T2 &endval) { dom[0] = begval; dom[1] = (endval - begval + 1); }};class Interval : public Domain<DomainTraits<Interval> >{public: Interval(const Interval &a) : Domain<DomainTraits<Interval> >() { for (int i=0; i < DomainTraits<Interval>::dimensions; ++i) DomainTraits<Interval>::getDomain(*this, i).setDomain( DomainTraits<Interval>::getDomain(a, i)); } Interval(int a) : Domain<DomainTraits<Interval> >() { DomainTraits<Interval>::setDomain(domain_m, 0, a - 1); }};template<>struct DomainTraits<Loc>{ typedef int Size_t; typedef int Element_t; typedef Loc Domain_t; typedef Loc AskDomain_t; typedef Loc MultResult_t; typedef int Storage_t; static int first(int d) { return d; } template<class T> static void setDomain(int &dom, const T &newdom) { dom = DomainTraits<T>::getFirst(newdom); }};template<>struct DomainTraits<int> { enum { dimensions = 1 }; enum { wildcard = false }; static int getPointDomain(int d, int) { return d; } static int getFirst(const int &d) { return d; }};class Loc : public Domain<DomainTraits<Loc> >{public: explicit Loc(const int &a) : Domain<DomainTraits<Loc> >() { for (int i=0; i < 1; ++i) (*this)[i].setDomain(DomainTraits<int>::getPointDomain(a, 0)); }};struct ElementProperties{ enum { hasTrivialDefaultConstructor = false }; enum { hasTrivialDestructor = false }; static void construct(double* addr) { new (addr) double(); } static void construct(double* addr, const double& model) { new (addr) double(model); } static void destruct(double *addr) {}};class RefCounted{public: RefCounted() : count_m(0) {} void addReference() { ++count_m; } bool removeRefAndCheckGarbage() { return (--count_m == 0); }private: int count_m;};class RefBlockController : public RefCounted{public: explicit RefBlockController(unsigned int size) : pBegin_m(0), pEnd_m(0), pEndOfStorage_m(0), dealloc_m(false) { reallocateStorage(size, false); if (!ElementProperties::hasTrivialDefaultConstructor) { for (double * pt = begin(); pt != end(); ++pt) ElementProperties::construct(pt); } } ~RefBlockController() { deleteStorage(); } double *begin() const { return pBegin_m; } double *end() const { return pEnd_m; } bool isMine() const { return dealloc_m; }private: void deleteStorage() { if (isMine() && pBegin_m != 0) { if (!ElementProperties::hasTrivialDestructor) for (double *pt = begin(); pt != end(); ++pt) ElementProperties::destruct(pt); char *tmp = reinterpret_cast<char *>(pBegin_m); delete [] tmp; } } void reallocateStorage(unsigned int newsize, bool copyold = false) { double *pBeginNew = 0; double *pEndNew = 0; double *pEndOfStorageNew = 0; if (newsize > 0) { int nsize = newsize * sizeof(double); char *tmp = new char[nsize]; pBeginNew = reinterpret_cast<double *>(tmp); pEndNew = pBeginNew + newsize; pEndOfStorageNew = pBeginNew + (nsize / sizeof(double)); if (copyold) { double * pOld = begin(); double * pNew = pBeginNew; while (pOld != end() && pNew != pEndNew) ElementProperties::construct(pNew++,*pOld++); } } deleteStorage(); pBegin_m = pBeginNew; pEnd_m = pEndNew; pEndOfStorage_m = pEndOfStorageNew; dealloc_m = true; } double *pBegin_m; double *pEnd_m; double *pEndOfStorage_m; bool dealloc_m;};class DataBlockController : public RefBlockController{public: explicit DataBlockController(unsigned int size) : RefBlockController(size), dataObjectPtr_m(new char), owned_m(true) {} ~DataBlockController() { if (owned_m) delete dataObjectPtr_m; }private: mutable char *dataObjectPtr_m; bool owned_m;};class RefCountedPtr{public: RefCountedPtr(DataBlockController * const pT) : ptr_m(pT) { if (isValid()) ptr_m->addReference(); } ~RefCountedPtr() { invalidate(); } DataBlockController* operator->() const { return ptr_m; } void invalidate(); bool isValid() const { return ptr_m != 0; }private: friend class RefCountedBlockPtr; DataBlockController * ptr_m;};inline void RefCountedPtr::invalidate(){ if ( isValid() && ptr_m->removeRefAndCheckGarbage() ) delete ptr_m; ptr_m = 0;}class RefCountedBlockPtr{public: explicit RefCountedBlockPtr(unsigned int size) : offset_m(0), blockControllerPtr_m(new DataBlockController(size)) {} int offset() const { return offset_m; } double *beginPointer() const { return blockControllerPtr_m->begin(); } double *currentPointer() const { return beginPointer() + offset(); }protected: int offset_m; RefCountedPtr blockControllerPtr_m;};class DataBlockPtr : public RefCountedBlockPtr{public: explicit DataBlockPtr(unsigned int size) : RefCountedBlockPtr(size) {}};class Node{public: Node(const Interval &owned, const Interval &allocated) : domain_m(owned), allocated_m(allocated) {} const Interval &allocated() const { return allocated_m; }private: Interval domain_m; Interval allocated_m;};class DomainLayout{public: explicit DomainLayout(const Interval &dom) : node_m(0, dom) {} const Interval &domain() const { return node_m.allocated(); }private: Node node_m;};class BrickBase{public: explicit BrickBase(const Interval &domain); int offset(const Loc &dom) const { return off_m + dom[0].first(); }protected: DomainLayout layout_m; int firsts_m; int off_m;};BrickBase::BrickBase(const Interval &dom) : layout_m(dom){ firsts_m = layout_m.domain()[0].first(); off_m = -firsts_m;}class Engine : public BrickBase{public: explicit Engine(const Interval &dom) : BrickBase(dom), dataBlock_m(dom.size()), data_m(dataBlock_m.currentPointer()) {} double& operator()(const Loc &loc) const { return data_m[this->offset(loc)]; }private: DataBlockPtr dataBlock_m; double *data_m;};int main(){ Interval I(10); Engine A(I); for (int i = 0; i < 10; i++) A(Loc(i)) = 2.0 + i - i*i; return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -