On Thu, Sep 24, 2015 at 08:32:10PM +0200, Jakub Jelinek wrote:
> then there is a bug with ordered loops that have noreturn body (need to add
> some edge for that case and condition checking),

This patch fixes the above issue, if we have any of the ordered > collapse
loops that might have zero iterations, we need to deal with the !cont_bb
(aka broken_loop) case, for lastprivate reasons not just as simple checking
of the conditions and falling through into the cont_bb case, but have to
emit all the loops, and just for the innermost handle the case that there is
no fallthru from the body to the cont_bb block; the innermost could have
zero iterations and some of the outer ones could have all non-zero
iterations, at which point we want lastprivate to contain the initial value
of the innermost iterator and last iteration's values of the outer ones.

2015-09-29  Jakub Jelinek  <ja...@redhat.com>

        * omp-low.c (expand_omp_for_ordered_loops): Handle the case
        when cont_bb has no predecessors.
        (expand_omp_for_generic): If any of the ordered loops above
        collapsed loops could have zero iterations for broken_loop,
        create a cont_bb and continue as if the loop is not broken.

        * testsuite/libgomp.c/doacross-1.c (main): Adjust, so that one
        of the doacross loops has noreturn loop body.

--- gcc/omp-low.c.jj    2015-09-25 18:17:13.000000000 +0200
+++ gcc/omp-low.c       2015-09-29 19:07:25.366494422 +0200
@@ -7345,36 +7345,44 @@ expand_omp_for_ordered_loops (struct omp
       basic_block new_body = e1->dest;
       if (body_bb == cont_bb)
        cont_bb = new_body;
-      gsi = gsi_last_bb (cont_bb);
-      if (POINTER_TYPE_P (type))
-       t = fold_build_pointer_plus (fd->loops[i].v,
-                                    fold_convert (sizetype,
-                                                  fd->loops[i].step));
-      else
-       t = fold_build2 (PLUS_EXPR, type, fd->loops[i].v,
-                        fold_convert (type, fd->loops[i].step));
-      expand_omp_build_assign (&gsi, fd->loops[i].v, t);
-      if (counts[i])
-       {
-         t = fold_build2 (PLUS_EXPR, fd->iter_type, counts[i],
-                          build_int_cst (fd->iter_type, 1));
-         expand_omp_build_assign (&gsi, counts[i], t);
-         t = counts[i];
-       }
-      else
+      edge e2 = NULL;
+      basic_block new_header;
+      if (EDGE_COUNT (cont_bb->preds) > 0)
        {
-         t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
-                          fd->loops[i].v, fd->loops[i].n1);
-         t = fold_convert (fd->iter_type, t);
-         t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
-                                       true, GSI_SAME_STMT);
+         gsi = gsi_last_bb (cont_bb);
+         if (POINTER_TYPE_P (type))
+           t = fold_build_pointer_plus (fd->loops[i].v,
+                                        fold_convert (sizetype,
+                                                      fd->loops[i].step));
+         else
+           t = fold_build2 (PLUS_EXPR, type, fd->loops[i].v,
+                            fold_convert (type, fd->loops[i].step));
+         expand_omp_build_assign (&gsi, fd->loops[i].v, t);
+         if (counts[i])
+           {
+             t = fold_build2 (PLUS_EXPR, fd->iter_type, counts[i],
+                              build_int_cst (fd->iter_type, 1));
+             expand_omp_build_assign (&gsi, counts[i], t);
+             t = counts[i];
+           }
+         else
+           {
+             t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
+                              fd->loops[i].v, fd->loops[i].n1);
+             t = fold_convert (fd->iter_type, t);
+             t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
+                                           true, GSI_SAME_STMT);
+           }
+         aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
+                        size_int (i - fd->collapse + 1),
+                        NULL_TREE, NULL_TREE);
+         expand_omp_build_assign (&gsi, aref, t);
+         gsi_prev (&gsi);
+         e2 = split_block (cont_bb, gsi_stmt (gsi));
+         new_header = e2->dest;
        }
-      aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
-                    size_int (i - fd->collapse + 1), NULL_TREE, NULL_TREE);
-      expand_omp_build_assign (&gsi, aref, t);
-      gsi_prev (&gsi);
-      edge e2 = split_block (cont_bb, gsi_stmt (gsi));
-      basic_block new_header = e2->dest;
+      else
+       new_header = cont_bb;
       gsi = gsi_after_labels (new_header);
       tree v = force_gimple_operand_gsi (&gsi, fd->loops[i].v, true, NULL_TREE,
                                         true, GSI_SAME_STMT);
@@ -7395,10 +7403,13 @@ expand_omp_for_ordered_loops (struct omp
       set_immediate_dominator (CDI_DOMINATORS, new_header, body_bb);
       set_immediate_dominator (CDI_DOMINATORS, new_body, new_header);
 
-      struct loop *loop = alloc_loop ();
-      loop->header = new_header;
-      loop->latch = e2->src;
-      add_loop (loop, body_bb->loop_father);
+      if (e2)
+       {
+         struct loop *loop = alloc_loop ();
+         loop->header = new_header;
+         loop->latch = e2->src;
+         add_loop (loop, body_bb->loop_father);
+       }
     }
   return cont_bb;
 }
@@ -7943,6 +7954,33 @@ expand_omp_for_generic (struct omp_regio
         depend(source).  */
       if (fd->collapse > 1)
        memmove (counts, counts + 1, (fd->collapse - 1) * sizeof (counts[0]));
+      if (broken_loop)
+       {
+         int i;
+         for (i = fd->collapse; i < fd->ordered; i++)
+           {
+             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))
+               break;
+           }
+         if (i < fd->ordered)
+           {
+             cont_bb
+               = create_empty_bb (EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb);
+             add_bb_to_loop (cont_bb, l1_bb->loop_father);
+             gimple_stmt_iterator gsi = gsi_after_labels (cont_bb);
+             gimple g = gimple_build_omp_continue (fd->loop.v, fd->loop.v);
+             gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+             make_edge (cont_bb, l3_bb, EDGE_FALLTHRU);
+             make_edge (cont_bb, l1_bb, 0);
+             l2_bb = create_empty_bb (cont_bb);
+             broken_loop = false;
+           }
+       }
       expand_omp_ordered_source_sink (region, fd, counts, cont_bb);
       cont_bb = expand_omp_for_ordered_loops (fd, counts, cont_bb, l1_bb);
       if (counts[fd->collapse - 1])
--- libgomp/testsuite/libgomp.c/doacross-1.c.jj 2015-09-25 16:54:47.000000000 
+0200
+++ libgomp/testsuite/libgomp.c/doacross-1.c    2015-09-29 16:36:26.131321339 
+0200
@@ -144,8 +144,7 @@ main ()
            {
              #pragma omp ordered depend (source)
              #pragma omp ordered depend (sink:i - 2, j + 2, k - 2, m)
-             if (!e)
-               abort ();
+             abort ();
            }
     #pragma omp single
     if (i != 1 || j != -1 || k != 2 || m != 0)


        Jakub

Reply via email to