[committed] openmp: Don't reject some valid initializers or conditions of non-rectangular loops [PR102854]

Message ID 20211027074645.GA4027102@tucnak
State Committed
Headers
Series [committed] openmp: Don't reject some valid initializers or conditions of non-rectangular loops [PR102854] |

Commit Message

Jakub Jelinek Oct. 27, 2021, 7:46 a.m. UTC
  Hi!

In C++, if an iterator has or might have (e.g. dependent type) class type we
remember the original init expressions and check those separately for presence
of iterators, because for class iterators we turn those into expressions that
always do contain reference to the current iterator.  But this resulted in
rejecting valid non-rectangular loop where the dependent type is later instantiated
to an integral type.

Non-rectangular loops with class random access iterators remain broken, that is something
to be fixed incrementally.

Bootstrapped/regtested on x86_64-linux and i686-linux, committed to trunk.

2021-10-27  Jakub Jelinek  <jakub@redhat.com>

	PR c++/102854
gcc/c-family/
	* c-common.h (c_omp_check_loop_iv_exprs): Add enum tree_code argument.
	* c-omp.c (c_omp_check_loop_iv_r): For trees other than decls,
	TREE_VEC, PLUS_EXPR, MINUS_EXPR, MULT_EXPR, POINTER_PLUS_EXPR or
	conversions temporarily clear the 3rd bit from d->kind while walking
	subtrees.
	(c_omp_check_loop_iv_exprs): Add CODE argument.  Or in 4 into data.kind
	if possibly non-rectangular.
gcc/cp/
	* semantics.c (handle_omp_for_class_iterator,
	finish_omp_for): Adjust c_omp_check_loop_iv_exprs caller.
gcc/testsuite/
	* g++.dg/gomp/loop-3.C: Don't expect some errors.
	* g++.dg/gomp/loop-7.C: New test.


	Jakub
  

Patch

--- gcc/c-family/c-common.h.jj	2021-10-05 09:53:55.377734121 +0200
+++ gcc/c-family/c-common.h	2021-10-21 16:09:20.397732877 +0200
@@ -1234,8 +1234,8 @@  extern void c_finish_omp_taskyield (loca
 extern tree c_finish_omp_for (location_t, enum tree_code, tree, tree, tree,
 			      tree, tree, tree, tree, bool);
 extern bool c_omp_check_loop_iv (tree, tree, walk_tree_lh);
-extern bool c_omp_check_loop_iv_exprs (location_t, tree, int, tree, tree, tree,
-				       walk_tree_lh);
+extern bool c_omp_check_loop_iv_exprs (location_t, enum tree_code, tree, int,
+				       tree, tree, tree, walk_tree_lh);
 extern tree c_finish_oacc_wait (location_t, tree, tree);
 extern tree c_oacc_split_loop_clauses (tree, tree *, bool);
 extern void c_omp_split_clauses (location_t, enum tree_code, omp_clause_mask,
--- gcc/c-family/c-omp.c.jj	2021-10-21 10:27:37.760331329 +0200
+++ gcc/c-family/c-omp.c	2021-10-21 18:31:29.967708593 +0200
@@ -1353,6 +1353,19 @@  c_omp_check_loop_iv_r (tree *tp, int *wa
 	}
       d->fail = true;
     }
+  else if ((d->kind & 4)
+	   && TREE_CODE (*tp) != TREE_VEC
+	   && TREE_CODE (*tp) != PLUS_EXPR
+	   && TREE_CODE (*tp) != MINUS_EXPR
+	   && TREE_CODE (*tp) != MULT_EXPR
+	   && !CONVERT_EXPR_P (*tp))
+    {
+      *walk_subtrees = 0;
+      d->kind &= 3;
+      walk_tree_1 (tp, c_omp_check_loop_iv_r, data, NULL, d->lh);
+      d->kind |= 4;
+      return NULL_TREE;
+    }
   else if (d->ppset->add (*tp))
     *walk_subtrees = 0;
   /* Don't walk dtors added by C++ wrap_cleanups_r.  */
@@ -1651,11 +1677,13 @@  c_omp_check_loop_iv (tree stmt, tree dec
 /* Similar, but allows to check the init or cond expressions individually.  */
 
 bool
-c_omp_check_loop_iv_exprs (location_t stmt_loc, tree declv, int i, tree decl,
-			   tree init, tree cond, walk_tree_lh lh)
+c_omp_check_loop_iv_exprs (location_t stmt_loc, enum tree_code code,
+			   tree declv, int i, tree decl, tree init, tree cond,
+			   walk_tree_lh lh)
 {
   hash_set<tree> pset;
   struct c_omp_check_loop_iv_data data;
+  int kind = (code != OACC_LOOP && i > 0) ? 4 : 0;
 
   data.declv = declv;
   data.fail = false;
@@ -1674,7 +1702,7 @@  c_omp_check_loop_iv_exprs (location_t st
   if (init)
     {
       data.expr_loc = EXPR_LOCATION (init);
-      data.kind = 0;
+      data.kind = kind;
       walk_tree_1 (&init,
 		   c_omp_check_loop_iv_r, &data, NULL, lh);
     }
@@ -1682,7 +1710,7 @@  c_omp_check_loop_iv_exprs (location_t st
     {
       gcc_assert (COMPARISON_CLASS_P (cond));
       data.expr_loc = EXPR_LOCATION (init);
-      data.kind = 1;
+      data.kind = kind | 1;
       if (TREE_OPERAND (cond, 0) == decl)
 	walk_tree_1 (&TREE_OPERAND (cond, 1),
 		     c_omp_check_loop_iv_r, &data, NULL, lh);
--- gcc/cp/semantics.c.jj	2021-10-21 10:23:12.014050655 +0200
+++ gcc/cp/semantics.c	2021-10-21 16:10:30.835749744 +0200
@@ -9211,7 +9211,7 @@  handle_omp_for_class_iterator (int i, lo
 		TREE_OPERAND (cond, 1), iter);
       return true;
     }
-  if (!c_omp_check_loop_iv_exprs (locus, orig_declv, i,
+  if (!c_omp_check_loop_iv_exprs (locus, code, orig_declv, i,
 				  TREE_VEC_ELT (declv, i), NULL_TREE,
 				  cond, cp_walk_subtrees))
     return true;
@@ -9597,7 +9597,7 @@  finish_omp_for (location_t locus, enum t
       tree orig_init;
       FOR_EACH_VEC_ELT (*orig_inits, i, orig_init)
 	if (orig_init
-	    && !c_omp_check_loop_iv_exprs (locus,
+	    && !c_omp_check_loop_iv_exprs (locus, code,
 					   orig_declv ? orig_declv : declv, i,
 					   TREE_VEC_ELT (declv, i), orig_init,
 					   NULL_TREE, cp_walk_subtrees))
--- gcc/testsuite/g++.dg/gomp/loop-3.C.jj	2020-01-12 11:54:37.178401867 +0100
+++ gcc/testsuite/g++.dg/gomp/loop-3.C	2021-10-21 18:35:13.032591017 +0200
@@ -116,7 +116,7 @@  f1 (I<int> &x, I<int> &y, I<int> &u, I<i
     for (j = x; j < y; j++)
       ;
   #pragma omp for collapse(2)
-  for (i = x; i < y; i = i + 2) /* { dg-error "initializer expression refers to iteration variable" } */
+  for (i = x; i < y; i = i + 2)
     for (j = i; j < v; j += 2)
       ;
   #pragma omp for collapse(2)
@@ -128,11 +128,11 @@  f1 (I<int> &x, I<int> &y, I<int> &u, I<i
     for (j = baz (&i); j < v; j += 2) /* { dg-error "initializer expression refers to iteration variable" } */
       ;
   #pragma omp for collapse(2)
-  for (i = x; i < y; i++) /* { dg-error "condition expression refers to iteration variable" } */
+  for (i = x; i < y; i++)
     for (j = v; j > i; j--)
       ;
   #pragma omp for collapse(2)
-  for (i = x; i < y; i++) /* { dg-error "condition expression refers to iteration variable" } */
+  for (i = x; i < y; i++)
     for (j = x; j < i; j++)
       ;
   #pragma omp for collapse(2)
@@ -234,7 +234,7 @@  f2 (I<int> &x, I<int> &y, I<int> &u, I<i
     for (I<int> j = u; j < y; j += 2)
       ;
   #pragma omp for collapse(2)
-  for (I<int> i = x; i < y; i = i + 2) /* { dg-error "initializer expression refers to iteration variable" } */
+  for (I<int> i = x; i < y; i = i + 2)
     for (I<int> j = i; j < v; j += 2)
       ;
   #pragma omp for collapse(2)
@@ -246,11 +246,11 @@  f2 (I<int> &x, I<int> &y, I<int> &u, I<i
     for (I<int> j = baz (&i); j < v; j += 2) /* { dg-error "initializer expression refers to iteration variable" } */
       ;
   #pragma omp for collapse(2)
-  for (I<int> i = x; i < y; i++) /* { dg-error "condition expression refers to iteration variable" } */
+  for (I<int> i = x; i < y; i++)
     for (I<int> j = v; j > i; j--)
       ;
   #pragma omp for collapse(2)
-  for (I<int> i = x; i < y; i++) /* { dg-error "condition expression refers to iteration variable" } */
+  for (I<int> i = x; i < y; i++)
     for (I<int> j = x; j < i; j++)
       ;
   #pragma omp for collapse(2)
--- gcc/testsuite/g++.dg/gomp/loop-7.C.jj	2021-10-21 18:35:47.690106638 +0200
+++ gcc/testsuite/g++.dg/gomp/loop-7.C	2021-10-21 17:30:12.963015526 +0200
@@ -0,0 +1,22 @@ 
+// PR c++/102854
+// { dg-do compile }
+
+template <typename T>
+void
+foo (T N, T M)
+{
+  #pragma omp parallel for collapse(2)
+  for (T i = 0; i < N; ++i)
+    for (T k = i; k < M; ++k)
+      ;
+  #pragma omp parallel for collapse(2)
+  for (T i = 0; i < N; ++i)
+    for (T k = i; k < 2 * i; ++k)
+      ;
+}
+
+void
+bar ()
+{
+  foo (5, 10);
+}