openmp: Diagnose non-rectangular loops with invalid steps
authorJakub Jelinek <jakub@redhat.com>
Thu, 2 Jul 2020 09:03:33 +0000 (11:03 +0200)
committerJakub Jelinek <jakub@redhat.com>
Thu, 2 Jul 2020 09:03:33 +0000 (11:03 +0200)
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.

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.

gcc/omp-expand.c
gcc/testsuite/c-c++-common/gomp/loop-7.c [new file with mode: 0644]

index 0f07e51f7e8141ea6944ad1bc609cfd940fed5df..b1349d8f0887c7d6529c612c583f8d1b4a604b84 100644 (file)
@@ -7122,15 +7122,55 @@ expand_omp_for (struct omp_region *region, gimple *inner_stmt)
   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;
diff --git a/gcc/testsuite/c-c++-common/gomp/loop-7.c b/gcc/testsuite/c-c++-common/gomp/loop-7.c
new file mode 100644 (file)
index 0000000..4c8f27e
--- /dev/null
@@ -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)
+      ;
+}