diff options
author | upstream source tree <ports@midipix.org> | 2015-03-15 20:14:05 -0400 |
---|---|---|
committer | upstream source tree <ports@midipix.org> | 2015-03-15 20:14:05 -0400 |
commit | 554fd8c5195424bdbcabf5de30fdc183aba391bd (patch) | |
tree | 976dc5ab7fddf506dadce60ae936f43f58787092 /gcc/testsuite/g++.dg/opt/unroll1.C | |
download | cbb-gcc-4.6.4-15d2061ac0796199866debe9ac87130894b0cdd3.tar.bz2 cbb-gcc-4.6.4-15d2061ac0796199866debe9ac87130894b0cdd3.tar.xz |
obtained gcc-4.6.4.tar.bz2 from upstream website;upstream
verified gcc-4.6.4.tar.bz2.sig;
imported gcc-4.6.4 source tree from verified upstream tarball.
downloading a git-generated archive based on the 'upstream' tag
should provide you with a source tree that is binary identical
to the one extracted from the above tarball.
if you have obtained the source via the command 'git clone',
however, do note that line-endings of files in your working
directory might differ from line-endings of the respective
files in the upstream repository.
Diffstat (limited to 'gcc/testsuite/g++.dg/opt/unroll1.C')
-rw-r--r-- | gcc/testsuite/g++.dg/opt/unroll1.C | 420 |
1 files changed, 420 insertions, 0 deletions
diff --git a/gcc/testsuite/g++.dg/opt/unroll1.C b/gcc/testsuite/g++.dg/opt/unroll1.C new file mode 100644 index 000000000..fd07f889a --- /dev/null +++ b/gcc/testsuite/g++.dg/opt/unroll1.C @@ -0,0 +1,420 @@ +// 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; +} |