This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[gomp4.1] Fixup doacross lastprivate handling


On Thu, Sep 24, 2015 at 08:32:10PM +0200, Jakub Jelinek wrote:
> some edge for that case and condition checking), lastprivate also needs
> checking for all the cases,

This patch handles lastprivate in the doacross loops.  In certain cases
(C++ class iterators and addressable iterators) the user IVs are replaced
with artificial IVs, and the user IVs are assigned (non-class) or adjusted
(class iterators) inside of the body of the loop, but while for normal omp
for (both collapse == 1 and > 1) lastprivate is undefined if there are no
iterations, for doacross it is IMHO only if the collapsed loops have zero
iterations; but if they have non-zero iters, but the ordered loops nested in
them have zero iterations, then the body might be not actually ever invoked.
So we need slightly different lastprivate sequences in that case.  And, to
make it more complicated, for the collapsed > 1 loops we need to add step to
the artificial IV before that, while for collapse == 1 loops or >= collapse
loops we should not.

2015-10-01  Jakub Jelinek  <jakub@redhat.com>

	* gimplify.c (gimplify_omp_for): Fix handling of lastprivate
	iterators in doacross loops.
	* omp-low.c (expand_omp_for_ordered_loops): Add ordered_lastprivate
	argument.  If true, add extra initializers for IVs starting with the
	one inner to the first >= collapse loop that could have zero
	iterations.
	(expand_omp_for_generic): Adjust caller.

	* tree-pretty-print.c (dump_omp_clause): Remove unused variable.
gcc/cp/
	* semantics.c (handle_omp_for_class_iterator): Add collapse and
	ordered arguments.  Fix handling of lastprivate iterators in
	doacross loops.
	(finish_omp_for): Adjust caller.
libgomp/
	* testsuite/libgomp.c++/doacross-1.C: New test.

--- gcc/gimplify.c.jj	2015-09-24 20:20:32.000000000 +0200
+++ gcc/gimplify.c	2015-10-01 12:55:44.955218974 +0200
@@ -8108,9 +8108,7 @@ gimplify_omp_for (tree *expr_p, gimple_s
 	  OMP_CLAUSE_LINEAR_STEP (c2) = OMP_CLAUSE_LINEAR_STEP (c);
 	}
 
-      if ((var != decl || collapse > 1)
-	  && orig_for_stmt == for_stmt
-	  && i < collapse)
+      if ((var != decl || collapse > 1) && orig_for_stmt == for_stmt)
 	{
 	  for (c = OMP_FOR_CLAUSES (for_stmt); c ; c = OMP_CLAUSE_CHAIN (c))
 	    if (((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
@@ -8120,16 +8118,22 @@ gimplify_omp_for (tree *expr_p, gimple_s
 		     && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) == NULL))
 		&& OMP_CLAUSE_DECL (c) == decl)
 	      {
-		t = TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i);
-		gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
-		gcc_assert (TREE_OPERAND (t, 0) == var);
-		t = TREE_OPERAND (t, 1);
-		gcc_assert (TREE_CODE (t) == PLUS_EXPR
-			    || TREE_CODE (t) == MINUS_EXPR
-			    || TREE_CODE (t) == POINTER_PLUS_EXPR);
-		gcc_assert (TREE_OPERAND (t, 0) == var);
-		t = build2 (TREE_CODE (t), TREE_TYPE (decl), decl,
-			    TREE_OPERAND (t, 1));
+		if (is_doacross && (collapse == 1 || i >= collapse))
+		  t = var;
+		else
+		  {
+		    t = TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i);
+		    gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
+		    gcc_assert (TREE_OPERAND (t, 0) == var);
+		    t = TREE_OPERAND (t, 1);
+		    gcc_assert (TREE_CODE (t) == PLUS_EXPR
+				|| TREE_CODE (t) == MINUS_EXPR
+				|| TREE_CODE (t) == POINTER_PLUS_EXPR);
+		    gcc_assert (TREE_OPERAND (t, 0) == var);
+		    t = build2 (TREE_CODE (t), TREE_TYPE (decl),
+				is_doacross ? var : decl,
+				TREE_OPERAND (t, 1));
+		  }
 		gimple_seq *seq;
 		if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
 		  seq = &OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c);
--- gcc/omp-low.c.jj	2015-09-29 19:07:25.000000000 +0200
+++ gcc/omp-low.c	2015-09-30 12:09:13.866406256 +0200
@@ -7303,7 +7303,8 @@ expand_omp_ordered_source_sink (struct o
 
 static basic_block
 expand_omp_for_ordered_loops (struct omp_for_data *fd, tree *counts,
-			      basic_block cont_bb, basic_block body_bb)
+			      basic_block cont_bb, basic_block body_bb,
+			      bool ordered_lastprivate)
 {
   if (fd->ordered == fd->collapse)
     return cont_bb;
@@ -7411,6 +7412,31 @@ expand_omp_for_ordered_loops (struct omp
 	  add_loop (loop, body_bb->loop_father);
 	}
     }
+
+  /* If there are any lastprivate clauses and it is possible some loops
+     might have zero iterations, ensure all the decls are initialized,
+     otherwise we could crash evaluating C++ class iterators with lastprivate
+     clauses.  */
+  bool need_inits = false;
+  for (int i = fd->collapse; ordered_lastprivate && i < fd->ordered; i++)
+    if (need_inits)
+      {
+	tree type = TREE_TYPE (fd->loops[i].v);
+	gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
+	expand_omp_build_assign (&gsi, fd->loops[i].v,
+				 fold_convert (type, fd->loops[i].n1));
+      }
+    else
+      {
+	tree type = TREE_TYPE (fd->loops[i].v);
+	tree this_cond = fold_build2 (fd->loops[i].cond_code,
+				      boolean_type_node,
+				      fold_convert (type, fd->loops[i].n1),
+				      fold_convert (type, fd->loops[i].n2));
+	if (!integer_onep (this_cond))
+	  need_inits = true;
+      }
+
   return cont_bb;
 }
 
@@ -7524,6 +7550,7 @@ expand_omp_for_generic (struct omp_regio
   edge e, ne;
   tree *counts = NULL;
   int i;
+  bool ordered_lastprivate = false;
 
   gcc_assert (!broken_loop || !in_combined_parallel);
   gcc_assert (fd->iter_type == long_integer_type_node
@@ -7551,6 +7578,10 @@ expand_omp_for_generic (struct omp_regio
   gsi = gsi_last_bb (entry_bb);
 
   gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
+  if (fd->ordered
+      && find_omp_clause (gimple_omp_for_clauses (gsi_stmt (gsi)),
+			  OMP_CLAUSE_LASTPRIVATE))
+    ordered_lastprivate = false;
   if (fd->collapse > 1 || fd->ordered)
     {
       int first_zero_iter1 = -1, first_zero_iter2 = -1;
@@ -7982,7 +8013,8 @@ expand_omp_for_generic (struct omp_regio
 	    }
 	}
       expand_omp_ordered_source_sink (region, fd, counts, cont_bb);
-      cont_bb = expand_omp_for_ordered_loops (fd, counts, cont_bb, l1_bb);
+      cont_bb = expand_omp_for_ordered_loops (fd, counts, cont_bb, l1_bb,
+					      ordered_lastprivate);
       if (counts[fd->collapse - 1])
 	{
 	  gcc_assert (fd->collapse == 1);
--- gcc/tree-pretty-print.c.jj	2015-09-25 15:04:46.000000000 +0200
+++ gcc/tree-pretty-print.c	2015-09-30 14:03:06.581614091 +0200
@@ -568,7 +568,6 @@ dump_omp_clause (pretty_printer *pp, tre
 		dump_generic_node (pp, TREE_VALUE (t), spc, flags, false);
 		if (TREE_PURPOSE (t) != integer_zero_node)
 		  {
-		    tree p = TREE_PURPOSE (t);
 		    if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (t))
 		      pp_minus (pp);
 		    else
--- gcc/cp/semantics.c.jj	2015-09-10 10:58:25.000000000 +0200
+++ gcc/cp/semantics.c	2015-10-01 12:40:48.322177598 +0200
@@ -7202,7 +7202,7 @@ static bool
 handle_omp_for_class_iterator (int i, location_t locus, enum tree_code code,
 			       tree declv, tree initv, tree condv, tree incrv,
 			       tree *body, tree *pre_body, tree &clauses,
-			       tree *lastp)
+			       tree *lastp, int collapse, int ordered)
 {
   tree diff, iter_init, iter_incr = NULL, last;
   tree incr_var = NULL, orig_pre_body, orig_body, c;
@@ -7386,7 +7386,8 @@ handle_omp_for_class_iterator (int i, lo
   last = create_temporary_var (TREE_TYPE (diff));
   pushdecl (last);
   add_decl_expr (last);
-  if (c && iter_incr == NULL && TREE_CODE (incr) != INTEGER_CST)
+  if (c && iter_incr == NULL && TREE_CODE (incr) != INTEGER_CST
+      && (!ordered || (i < collapse && collapse > 1)))
     {
       incr_var = create_temporary_var (TREE_TYPE (diff));
       pushdecl (incr_var);
@@ -7422,7 +7423,8 @@ handle_omp_for_class_iterator (int i, lo
 					   iter, NOP_EXPR, init,
 					   tf_warning_or_error));
   init = build_int_cst (TREE_TYPE (diff), 0);
-  if (c && iter_incr == NULL)
+  if (c && iter_incr == NULL
+      && (!ordered || (i < collapse && collapse > 1)))
     {
       if (incr_var)
 	{
@@ -7435,6 +7437,8 @@ handle_omp_for_class_iterator (int i, lo
 				       iter, PLUS_EXPR, incr,
 				       tf_warning_or_error);
     }
+  if (c && ordered && i < collapse && collapse > 1)
+    iter_incr = incr;
   finish_expr_stmt (build_x_modify_expr (elocus,
 					 last, NOP_EXPR, init,
 					 tf_warning_or_error));
@@ -7471,7 +7475,22 @@ handle_omp_for_class_iterator (int i, lo
   if (c)
     {
       OMP_CLAUSE_LASTPRIVATE_STMT (c) = push_stmt_list ();
-      finish_expr_stmt (iter_incr);
+      if (!ordered)
+	finish_expr_stmt (iter_incr);
+      else
+	{
+	  iter_init = decl;
+	  if (i < collapse && collapse > 1 && !error_operand_p (iter_incr))
+	    iter_init = build2 (PLUS_EXPR, TREE_TYPE (diff),
+				iter_init, iter_incr);
+	  iter_init = build2 (MINUS_EXPR, TREE_TYPE (diff), iter_init, last);
+	  iter_init = build_x_modify_expr (elocus,
+					   iter, PLUS_EXPR, iter_init,
+					   tf_warning_or_error);
+	  if (iter_init != error_mark_node)
+	    iter_init = build1 (NOP_EXPR, void_type_node, iter_init);
+	  finish_expr_stmt (iter_init);
+	}
       OMP_CLAUSE_LASTPRIVATE_STMT (c)
 	= pop_stmt_list (OMP_CLAUSE_LASTPRIVATE_STMT (c));
     }
@@ -7502,10 +7521,20 @@ finish_omp_for (location_t locus, enum t
   tree last = NULL_TREE;
   location_t elocus;
   int i;
+  int collapse = 1;
+  int ordered = 0;
 
   gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (initv));
   gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (condv));
   gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (incrv));
+  if (TREE_VEC_LENGTH (declv) > 1)
+    {
+      tree c = find_omp_clause (clauses, OMP_CLAUSE_COLLAPSE);
+      if (c)
+	collapse = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (c));
+      if (collapse != TREE_VEC_LENGTH (declv))
+	ordered = TREE_VEC_LENGTH (declv);
+    }
   for (i = 0; i < TREE_VEC_LENGTH (declv); i++)
     {
       decl = TREE_VEC_ELT (declv, i);
@@ -7636,7 +7665,8 @@ finish_omp_for (location_t locus, enum t
 	    orig_decl = decl;
 	  if (handle_omp_for_class_iterator (i, locus, code, declv, initv,
 					     condv, incrv, &body, &pre_body,
-					     clauses, &last))
+					     clauses, &last, collapse,
+					     ordered))
 	    return NULL;
 	  continue;
 	}
--- libgomp/testsuite/libgomp.c++/doacross-1.C.jj	2015-10-01 13:00:31.636054501 +0200
+++ libgomp/testsuite/libgomp.c++/doacross-1.C	2015-10-01 13:03:13.079709288 +0200
@@ -0,0 +1,294 @@
+// { dg-do run }
+
+typedef __PTRDIFF_TYPE__ ptrdiff_t;
+extern "C" void abort ();
+
+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); }
+
+int results[2048];
+
+template <typename T>
+void
+baz (I<T> &i, I<T> &j, I<T> &k, T &l)
+{
+  if (*i < 0 || *i >= 16)
+    abort ();
+  if (*j < 0 || *j >= 16)
+    abort ();
+  if (*k < 0 || *k >= 16)
+    abort ();
+  if (l < 0 || l >= 16)
+    abort ();
+  #pragma omp atomic
+    results[512 * *i + 64 * *j + 8 * *k + l]++;
+}
+
+template <typename T>
+void
+baz (T &i, T &j, T &k, T &l)
+{
+  if (i < 0 || i >= 16)
+    abort ();
+  if (j < 0 || j >= 16)
+    abort ();
+  if (k < 0 || k >= 16)
+    abort ();
+  if (l < 0 || l >= 16)
+    abort ();
+  #pragma omp atomic
+    results[512 * i + 64 * j + 8 * k + l]++;
+}
+
+void
+f1 (const I<int> &a, const I<int> &b, const I<int> &c, const I<int> &d,
+    const I<int> &e, const I<int> &f, int g, int h,
+    I<int> &r1, I<int> &r2, I<int> &r3)
+{
+  I<int> i, j, k;
+  int l;
+#pragma omp parallel for ordered(4) lastprivate (i, j, k) schedule(static, 1)
+  for (i = a; i <= b; i++)
+    for (j = c; j < d; j++)
+      for (k = e; k < f; k++)
+	for (l = g; l < h; l++)
+	  {
+	    #pragma omp ordered depend(sink: i - 1, j, k + 1, l - 2)
+	    baz (i, j, k, l);
+	    if (i > a && k < f - 1 && l > g + 1)
+	      {
+		int m;
+		#pragma omp atomic read
+		m = results[512 * *(i - 1) + 64 * *j + 8 * *(k + 1) + l - 2];
+		if (m == 0)
+		  abort ();
+	      }
+	    #pragma omp ordered depend(source)
+	  }
+  r1 = i;
+  r2 = j;
+  r3 = k;
+}
+
+void
+f2 (int a, int b, int c, int d, int e, int f, int g, int h, int &r1, int &r2, int &r3)
+{
+  int i, j, k, l;
+#pragma omp parallel for collapse (1) ordered(4) lastprivate (i, j, k) schedule(static, 2)
+  for (i = a; i <= b; i++)
+    for (j = c; j < d; j++)
+      for (k = e; k < f; k++)
+	for (l = g; l < h; l++)
+	  {
+	    #pragma omp ordered depend(sink: i - 1, j, k + 1, l - 2)
+	    baz (i, j, k, l);
+	    if (i > a && k < f - 1 && l > g + 1)
+	      {
+		int m;
+		#pragma omp atomic read
+		m = results[512 * (i - 1) + 64 * j + 8 * (k + 1) + l - 2];
+		if (m == 0)
+		  abort ();
+	      }
+	    #pragma omp ordered depend(source)
+	  }
+  r1 = i;
+  r2 = j;
+  r3 = k;
+}
+
+void
+f3 (const I<int> &a, const I<int> &b, const I<int> &c, const I<int> &d,
+    const I<int> &e, const I<int> &f, int g, int h,
+    I<int> &r1, I<int> &r2, I<int> &r3)
+{
+  I<int> i, j, k;
+  int l;
+#pragma omp parallel for collapse (2) ordered(4) lastprivate (i, j, k) schedule(static, 1)
+  for (i = a; i <= b; i++)
+    for (j = c; j < d; j++)
+      for (k = e; k < f; k++)
+	for (l = g; l < h; l++)
+	  {
+	    #pragma omp ordered depend(sink: i - 1, j, k + 1, l - 2)
+	    baz (i, j, k, l);
+	    if (i > a && k < f - 1 && l > g + 1)
+	      {
+		int m;
+		#pragma omp atomic read
+		m = results[512 * *(i - 1) + 64 * *j + 8 * *(k + 1) + l - 2];
+		if (m == 0)
+		  abort ();
+	      }
+	    #pragma omp ordered depend(source)
+	  }
+  r1 = i;
+  r2 = j;
+  r3 = k;
+}
+
+void
+f4 (int a, int b, int c, int d, int e, int f, int g, int h, int &r1, int &r2, int &r3)
+{
+  int i, j, k, l;
+#pragma omp parallel for collapse (2) ordered(4) lastprivate (i, j, k) schedule(static, 2)
+  for (i = a; i <= b; i++)
+    for (j = c; j < d; j++)
+      for (k = e; k < f; k++)
+	for (l = g; l < h; l++)
+	  {
+	    #pragma omp ordered depend(sink: i - 1, j, k + 1, l - 2)
+	    baz (i, j, k, l);
+	    if (i > a && k < f - 1 && l > g + 1)
+	      {
+		int m;
+		#pragma omp atomic read
+		m = results[512 * (i - 1) + 64 * j + 8 * (k + 1) + l - 2];
+		if (m == 0)
+		  abort ();
+	      }
+	    #pragma omp ordered depend(source)
+	  }
+  r1 = i;
+  r2 = j;
+  r3 = k;
+}
+
+#define check(expr) \
+  for (int i = 0; i < 2048; i++)			\
+    if (expr)						\
+      {							\
+	if (results[i] != 1)				\
+	  abort ();					\
+	results[i] = 0;					\
+      }							\
+    else if (results[i])				\
+      abort ()
+
+int
+main ()
+{
+  int a[16], s1, s2, s3;
+  I<int> r1, r2, r3;
+  for (int i = 0; i < 16; i++)
+    a[i] = i;
+  r1 = &a[15]; r2 = &a[15]; r3 = &a[15];
+  f1 (&a[1], &a[3], &a[2], &a[5], &a[1], &a[3], 0, 5, r1, r2, r3);
+  if (*r1 != 4 || *r2 != 5 || *r3 != 3)
+    abort ();
+  check ((i / 512) - 1U < 3U && ((i / 64) & 7) - 2U < 3U && ((i / 8) & 7) - 1U < 2U && (i & 7) < 5);
+  r1 = &a[15]; r2 = &a[15]; r3 = &a[15];
+  f1 (&a[1], &a[3], &a[1], &a[4], &a[1], &a[5], 1, 0, r1, r2, r3);
+  if (*r1 != 4 || *r2 != 4 || *r3 != 5)
+    abort ();
+  r1 = &a[15]; r2 = &a[15]; r3 = &a[15];
+  f1 (&a[1], &a[3], &a[1], &a[9], &a[7], &a[2], 0, 7, r1, r2, r3);
+  if (*r1 != 4 || *r2 != 9 || *r3 != 7)
+    abort ();
+  s1 = 15; s2 = 15; s3 = 15;
+  f2 (1, 3, 2, 5, 1, 3, 0, 5, s1, s2, s3);
+  if (s1 != 4 || s2 != 5 || s3 != 3)
+    abort ();
+  check ((i / 512) - 1U < 3U && ((i / 64) & 7) - 2U < 3U && ((i / 8) & 7) - 1U < 2U && (i & 7) < 5);
+  s1 = 15; s2 = 15; s3 = 15;
+  f2 (1, 3, 1, 4, 1, 5, 1, 0, s1, s2, s3);
+  if (s1 != 4 || s2 != 4 || s3 != 5)
+    abort ();
+  s1 = 15; s2 = 15; s3 = 15;
+  f2 (1, 3, 1, 9, 7, 2, 0, 7, s1, s2, s3);
+  if (s1 != 4 || s2 != 9 || s3 != 7)
+    abort ();
+  r1 = &a[15]; r2 = &a[15]; r3 = &a[15];
+  f3 (&a[1], &a[3], &a[2], &a[5], &a[1], &a[3], 0, 5, r1, r2, r3);
+  if (*r1 != 4 || *r2 != 5 || *r3 != 3)
+    abort ();
+  check ((i / 512) - 1U < 3U && ((i / 64) & 7) - 2U < 3U && ((i / 8) & 7) - 1U < 2U && (i & 7) < 5);
+  r1 = &a[15]; r2 = &a[15]; r3 = &a[15];
+  f3 (&a[1], &a[3], &a[1], &a[4], &a[1], &a[5], 1, 0, r1, r2, r3);
+  if (*r1 != 4 || *r2 != 4 || *r3 != 5)
+    abort ();
+  r1 = &a[15]; r2 = &a[15]; r3 = &a[15];
+  f3 (&a[1], &a[3], &a[1], &a[9], &a[7], &a[2], 0, 7, r1, r2, r3);
+  if (*r1 != 4 || *r2 != 9 || *r3 != 7)
+    abort ();
+  s1 = 15; s2 = 15; s3 = 15;
+  f4 (1, 3, 2, 5, 1, 3, 0, 5, s1, s2, s3);
+  if (s1 != 4 || s2 != 5 || s3 != 3)
+    abort ();
+  check ((i / 512) - 1U < 3U && ((i / 64) & 7) - 2U < 3U && ((i / 8) & 7) - 1U < 2U && (i & 7) < 5);
+  s1 = 15; s2 = 15; s3 = 15;
+  f4 (1, 3, 1, 4, 1, 5, 1, 0, s1, s2, s3);
+  if (s1 != 4 || s2 != 4 || s3 != 5)
+    abort ();
+  s1 = 15; s2 = 15; s3 = 15;
+  f4 (1, 3, 1, 9, 7, 2, 0, 7, s1, s2, s3);
+  if (s1 != 4 || s2 != 9 || s3 != 7)
+    abort ();
+  return 0;
+}


	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]