[committed] openmp: Diagnose non-rectangular loops with invalid steps

Message ID 20200702090834.GO8462@tucnak
State New
Headers show
Series
  • [committed] openmp: Diagnose non-rectangular loops with invalid steps
Related show

Commit Message

Jakub Jelinek via Gcc-patches July 2, 2020, 9:08 a.m.
Hi!

The OpenMP 5 standard requires that if some loop in OpenMP loop nest refers
to some outer loop's iterator variable, then the subtraction of the multiplication
factors for the outer iterator multiplied by the outer increment modulo the
inner increment is 0.  For loops with non-constants in any of these we can't
diagnose it, it would be a task for something like -fsanitize=openmp,
but if all these are constant, we can diagnose it.

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

2020-07-02  Jakub Jelinek  <jakub@redhat.com>

	* omp-expand.c (expand_omp_for): Diagnose non-rectangular loops with
	invalid steps - ((m2 - m1) * incr_outer) % incr must be 0 in valid
	OpenMP non-rectangular loops.  Use XALLOCAVEC.

	* c-c++-common/gomp/loop-7.c: New test.



	Jakub

Patch

--- gcc/omp-expand.c.jj	2020-06-29 14:51:54.855085915 +0200
+++ gcc/omp-expand.c	2020-06-30 15:45:00.531813174 +0200
@@ -7122,15 +7122,55 @@  expand_omp_for (struct omp_region *regio
   struct omp_for_data fd;
   struct omp_for_data_loop *loops;
 
-  loops
-    = (struct omp_for_data_loop *)
-      alloca (gimple_omp_for_collapse (last_stmt (region->entry))
-	      * sizeof (struct omp_for_data_loop));
+  loops = XALLOCAVEC (struct omp_for_data_loop,
+		      gimple_omp_for_collapse (last_stmt (region->entry)));
   omp_extract_for_data (as_a <gomp_for *> (last_stmt (region->entry)),
 			&fd, loops);
   region->sched_kind = fd.sched_kind;
   region->sched_modifiers = fd.sched_modifiers;
   region->has_lastprivate_conditional = fd.lastprivate_conditional != 0;
+  if (fd.non_rect && !gimple_omp_for_combined_into_p (fd.for_stmt))
+    {
+      for (int i = fd.first_nonrect; i <= fd.last_nonrect; i++)
+	if ((loops[i].m1 || loops[i].m2)
+	    && (loops[i].m1 == NULL_TREE
+		|| TREE_CODE (loops[i].m1) == INTEGER_CST)
+	    && (loops[i].m2 == NULL_TREE
+		|| TREE_CODE (loops[i].m2) == INTEGER_CST)
+	    && TREE_CODE (loops[i].step) == INTEGER_CST
+	    && TREE_CODE (loops[i - loops[i].outer].step) == INTEGER_CST)
+	  {
+	    tree t;
+	    tree itype = TREE_TYPE (loops[i].v);
+	    if (loops[i].m1 && loops[i].m2)
+	      t = fold_build2 (MINUS_EXPR, itype, loops[i].m2, loops[i].m1);
+	    else if (loops[i].m1)
+	      t = fold_build1 (NEGATE_EXPR, itype, loops[i].m1);
+	    else
+	      t = loops[i].m2;
+	    t = fold_build2 (MULT_EXPR, itype, t,
+			     fold_convert (itype,
+					   loops[i - loops[i].outer].step));
+	    if (TYPE_UNSIGNED (itype) && loops[i].cond_code == GT_EXPR)
+	      t = fold_build2 (TRUNC_MOD_EXPR, itype,
+			       fold_build1 (NEGATE_EXPR, itype, t),
+			       fold_build1 (NEGATE_EXPR, itype,
+					    fold_convert (itype,
+							  loops[i].step)));
+	    else
+	      t = fold_build2 (TRUNC_MOD_EXPR, itype, t,
+			       fold_convert (itype, loops[i].step));
+	    if (integer_nonzerop (t))
+	      error_at (gimple_location (fd.for_stmt),
+			"invalid OpenMP non-rectangular loop step; "
+			"%<(%E - %E) * %E%> is not a multiple of loop %d "
+			"step %qE",
+			loops[i].m2 ? loops[i].m2 : integer_zero_node,
+			loops[i].m1 ? loops[i].m1 : integer_zero_node,
+			loops[i - loops[i].outer].step, i + 1,
+			loops[i].step);
+	  }
+    }
 
   gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
   BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
--- gcc/testsuite/c-c++-common/gomp/loop-7.c.jj	2020-06-30 16:29:38.969728972 +0200
+++ gcc/testsuite/c-c++-common/gomp/loop-7.c	2020-06-30 15:49:17.788152186 +0200
@@ -0,0 +1,24 @@ 
+void
+foo (void)
+{
+  #pragma omp for collapse(2)	/* { dg-error "invalid OpenMP non-rectangular loop step" } */
+  for (int i = 0; i < 6; i++)
+    for (int j = 4 * i; j < 7 * i; j += 2)
+      ;
+  #pragma omp for collapse(2)	/* { dg-error "invalid OpenMP non-rectangular loop step" } */
+  for (int i = 0; i < 32; i += 7)
+    for (int j = 3 * i; j < 7 * i; j += 30)
+      ;
+  #pragma omp for collapse(2)
+  for (int i = 0; i < 6; i++)
+    for (int j = 4 * i; j < 6 * i; j += 2)
+      ;
+  #pragma omp for collapse(2)
+  for (int i = 0; i < 6; i += 2)
+    for (int j = 4 * i; j < 7 * i; j += 2)
+      ;
+  #pragma omp for collapse(2)
+  for (int i = 0; i < 6; i += 5)
+    for (int j = 4 * i; j < 7 * i; j += 15)
+      ;
+}