On Wed, Feb 05, 2014 at 05:27:26AM +0000, Iyer, Balaji V wrote: > Attached, please find a fixed patch (diff.txt) that will do as you > requested (model _Cilk_for like a #pragma omp parallel for). Along with this, > I have also attached two Changelog entries (1 for C and 1 for C++). > It passes all the tests on my x86_64 box (both 32 and 64 bit modes) and > does not affect any other tests in the testsuite. > Is this Ok for trunk?
A step in the right direction, but I still see issues just from looking at the *.gimple dump: For the first testcase, I see: iter = std::vector<int>::begin (array); [return slot optimization] iter.1 = iter; D.13615 = std::vector<int>::end (array); [return slot optimization] try { retval.0 = __gnu_cxx::operator-<int*, std::vector<int> > (&D.13615, &iter); } finally { D.13615 = {CLOBBER}; } #pragma omp parallel schedule(cilk-for grain,0) if(retval.0) #shared(iter.1) shared(D.13632) shared(D.13615) shared(iter) { difference_type retval.2; const difference_type D.13633; int D.13725; struct __normal_iterator & D.13726; bool retval.3; int & D.13728; int D.13729; int & D.13732; iter = iter.1; private(D.13631) _Cilk_for (D.13631 = 0; D.13631 != retval.2; D.13631 = D.13631 + 1) D.13725 = D.13631 - D.13632; So, the issues I see: 1) what is iter.1, why do you have it at all, and, after all, the iterator is a class that needs to be constructed/destructed in the general way, so creating any further copies of something is both costly and undesirable 2) the schedule clause doesn't belong on the omp parallel, but on the _Cilk_for 3) iter should be firstprivate, and there should be no explicit private var with assignment during gimplification, just handle it like any other firstprivate during omp lowering 4) the printing looks weird for _Cilk_for, as I said earlier, the clauses should probably be printed after the closing ) of _Cilk_for rather than after nothing on the previous line; also, there is no {} printed around the _Cilk_for body and the next line is weirdly indented But more importantly, if I create some testcase with a generic C++ conforming iterator (copied over from libgomp/testsuite/libgomp.c++/for-1.C), as in the second testcase, the *.gimple dump shows that _Cilk_for is still around the #pragma omp parallel. The intent of the second testcase is that you can really eyeball all the ctors/dtors/copy ctors etc. that should happen, and for -O0 shouldn't be really inlined. Jakub
#include <vector> void foo (std::vector<int> &array) { _Cilk_for (std::vector<int>::iterator iter = array.begin(); iter != array.end(); iter++) { if (*iter == 6) *iter = 13; } }
typedef __PTRDIFF_TYPE__ ptrdiff_t; template <typename T> class I { public: typedef ptrdiff_t difference_type; I (); ~I (); I (T *); I (const I &); T &operator * (); T *operator -> (); T &operator [] (const difference_type &) const; I &operator = (const I &); I &operator ++ (); I operator ++ (int); I &operator -- (); I operator -- (int); I &operator += (const difference_type &); I &operator -= (const difference_type &); I operator + (const difference_type &) const; I operator - (const difference_type &) const; template <typename S> friend bool operator == (I<S> &, I<S> &); template <typename S> friend bool operator == (const I<S> &, const I<S> &); template <typename S> friend bool operator < (I<S> &, I<S> &); template <typename S> friend bool operator < (const I<S> &, const I<S> &); template <typename S> friend bool operator <= (I<S> &, I<S> &); template <typename S> friend bool operator <= (const I<S> &, const I<S> &); template <typename S> friend bool operator > (I<S> &, I<S> &); template <typename S> friend bool operator > (const I<S> &, const I<S> &); template <typename S> friend bool operator >= (I<S> &, I<S> &); template <typename S> friend bool operator >= (const I<S> &, const I<S> &); template <typename S> friend typename I<S>::difference_type operator - (I<S> &, I<S> &); template <typename S> friend typename I<S>::difference_type operator - (const I<S> &, const I<S> &); template <typename S> friend I<S> operator + (typename I<S>::difference_type , const I<S> &); private: T *p; }; template <typename T> I<T>::I () : p (0) {} template <typename T> I<T>::~I () {} template <typename T> I<T>::I (T *x) : p (x) {} template <typename T> I<T>::I (const I &x) : p (x.p) {} template <typename T> T &I<T>::operator * () { return *p; } template <typename T> T *I<T>::operator -> () { return p; } template <typename T> T &I<T>::operator [] (const difference_type &x) const { return p[x]; } template <typename T> I<T> &I<T>::operator = (const I &x) { p = x.p; return *this; } template <typename T> I<T> &I<T>::operator ++ () { ++p; return *this; } template <typename T> I<T> I<T>::operator ++ (int) { return I (p++); } template <typename T> I<T> &I<T>::operator -- () { --p; return *this; } template <typename T> I<T> I<T>::operator -- (int) { return I (p--); } template <typename T> I<T> &I<T>::operator += (const difference_type &x) { p += x; return *this; } template <typename T> I<T> &I<T>::operator -= (const difference_type &x) { p -= x; return *this; } template <typename T> I<T> I<T>::operator + (const difference_type &x) const { return I (p + x); } template <typename T> I<T> I<T>::operator - (const difference_type &x) const { return I (p - x); } template <typename T> bool operator == (I<T> &x, I<T> &y) { return x.p == y.p; } template <typename T> bool operator == (const I<T> &x, const I<T> &y) { return x.p == y.p; } template <typename T> bool operator != (I<T> &x, I<T> &y) { return !(x == y); } template <typename T> bool operator != (const I<T> &x, const I<T> &y) { return !(x == y); } template <typename T> bool operator < (I<T> &x, I<T> &y) { return x.p < y.p; } template <typename T> bool operator < (const I<T> &x, const I<T> &y) { return x.p < y.p; } template <typename T> bool operator <= (I<T> &x, I<T> &y) { return x.p <= y.p; } template <typename T> bool operator <= (const I<T> &x, const I<T> &y) { return x.p <= y.p; } template <typename T> bool operator > (I<T> &x, I<T> &y) { return x.p > y.p; } template <typename T> bool operator > (const I<T> &x, const I<T> &y) { return x.p > y.p; } template <typename T> bool operator >= (I<T> &x, I<T> &y) { return x.p >= y.p; } template <typename T> bool operator >= (const I<T> &x, const I<T> &y) { return x.p >= y.p; } template <typename T> typename I<T>::difference_type operator - (I<T> &x, I<T> &y) { return x.p - y.p; } template <typename T> typename I<T>::difference_type operator - (const I<T> &x, const I<T> &y) { return x.p - y.p; } template <typename T> I<T> operator + (typename I<T>::difference_type x, const I<T> &y) { return I<T> (x + y.p); } template <typename T> class J { public: J(const I<T> &x, const I<T> &y) : b (x), e (y) {} const I<T> &begin (); const I<T> &end (); private: I<T> b, e; }; template <typename T> const I<T> &J<T>::begin () { return b; } template <typename T> const I<T> &J<T>::end () { return e; } template <typename T> void baz (I<T> &i); void foo (J<int> j) { _Cilk_for (I<int> i = j.begin (); i < j.end (); i += 2) baz (i); }