On Mon, 29 Apr 2013, Richard Biener wrote:

> 
> I've tried to follow where the scalar loop appears in
> expand_omp_for_static_nochunk but got lost quickly.  So the following
> papers over the lack of OMP expansion populating the loop tree
> as I've done in the original patch introducing loops to it.
> 
> If the OMP expansion code knows at some point "here is a new loop
> and this is the header block and this is the latch block" I can
> write a helper that properly updates the loop tree with that
> information (call alloc_loop, init ->header and ->latch and
> call add_loop).  But at the moment I have no idea where to call
> that function ...

After discussion on IRC I am now testing the following (only
the degenerate case still uses fixup, I'm not sure how to
reliably get at loops here - eventually we want to revisit
that loops-with-abnormal-entries issue again).

Richard.

2013-04-29  Richard Biener  <rguent...@suse.de>

        PR middle-end/57089
        * omp-low.c (expand_omp_taskreg): If the parent function had
        a broken loop tree make sure to schedule a fixup for the child
        as well.
        (expand_omp_for_generic): Properly add loops.
        (expand_omp_for_static_nochunk): Likewise.
        (expand_omp_for_static_chunk): Likewise.
        (expand_omp_for): For the degenerate case fixup loops.
        (expand_omp_sections): Fix default bb placement in loops.
        (expand_omp_atomic_pipeline): Properly add loops.

        * gfortran.dg/gomp/pr57089.f90: New testcase.

Index: gcc/omp-low.c
===================================================================
*** gcc/omp-low.c       (revision 198389)
--- gcc/omp-low.c       (working copy)
*************** expand_omp_taskreg (struct omp_region *r
*** 3571,3581 ****
        new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
        if (exit_bb)
        single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
!       /* ???  As the OMP expansion process does not update the loop
!          tree of the original function before outlining the region to
!        the new child function we need to discover loops in the child.
!        Arrange for that.  */
!       child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
  
        /* Remove non-local VAR_DECLs from child_cfun->local_decls list.  */
        num = vec_safe_length (child_cfun->local_decls);
--- 3571,3580 ----
        new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
        if (exit_bb)
        single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
!       /* When the OMP expansion process cannot guarantee an up-to-date
!          loop tree arrange for the child function to fixup loops.  */
!       if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
!       child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
  
        /* Remove non-local VAR_DECLs from child_cfun->local_decls list.  */
        num = vec_safe_length (child_cfun->local_decls);
*************** expand_omp_for_generic (struct omp_regio
*** 4148,4153 ****
--- 4147,4162 ----
                               recompute_dominator (CDI_DOMINATORS, l0_bb));
        set_immediate_dominator (CDI_DOMINATORS, l1_bb,
                               recompute_dominator (CDI_DOMINATORS, l1_bb));
+ 
+       struct loop *outer_loop = alloc_loop ();
+       outer_loop->header = l0_bb;
+       outer_loop->latch = l2_bb;
+       add_loop (outer_loop, l0_bb->loop_father);
+ 
+       struct loop *loop = alloc_loop ();
+       loop->header = l1_bb;
+       /* The loop may have multiple latches.  */
+       add_loop (loop, outer_loop);
      }
  }
  
*************** expand_omp_for_static_nochunk (struct om
*** 4370,4375 ****
--- 4379,4389 ----
                           recompute_dominator (CDI_DOMINATORS, body_bb));
    set_immediate_dominator (CDI_DOMINATORS, fin_bb,
                           recompute_dominator (CDI_DOMINATORS, fin_bb));
+ 
+   struct loop *loop = alloc_loop ();
+   loop->header = body_bb;
+   loop->latch = cont_bb;
+   add_loop (loop, body_bb->loop_father);
  }
  
  
*************** expand_omp_for_static_chunk (struct omp_
*** 4671,4676 ****
--- 4685,4700 ----
                           recompute_dominator (CDI_DOMINATORS, seq_start_bb));
    set_immediate_dominator (CDI_DOMINATORS, body_bb,
                           recompute_dominator (CDI_DOMINATORS, body_bb));
+ 
+   struct loop *trip_loop = alloc_loop ();
+   trip_loop->header = iter_part_bb;
+   trip_loop->latch = trip_update_bb;
+   add_loop (trip_loop, iter_part_bb->loop_father);
+ 
+   struct loop *loop = alloc_loop ();
+   loop->header = body_bb;
+   loop->latch = cont_bb;
+   add_loop (loop, trip_loop);
  }
  
  
*************** expand_omp_for (struct omp_region *regio
*** 4698,4703 ****
--- 4722,4732 ----
        BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
        FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
      }
+   else
+     /* If there isnt a continue then this is a degerate case where
+        the introduction of abnormal edges during lowering will prevent
+        original loops from being detected.  Fix that up.  */
+     loops_state_set (LOOPS_NEED_FIXUP);
  
    if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
        && !fd.have_ordered
*************** expand_omp_sections (struct omp_region *
*** 4914,4920 ****
    u = build_case_label (NULL, NULL, t);
    make_edge (l0_bb, default_bb, 0);
    if (current_loops)
!     add_bb_to_loop (default_bb, l0_bb->loop_father);
  
    stmt = gimple_build_switch (vmain, u, label_vec);
    gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
--- 4943,4949 ----
    u = build_case_label (NULL, NULL, t);
    make_edge (l0_bb, default_bb, 0);
    if (current_loops)
!     add_bb_to_loop (default_bb, current_loops->tree_root);
  
    stmt = gimple_build_switch (vmain, u, label_vec);
    gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
*************** expand_omp_atomic_pipeline (basic_block
*** 5448,5460 ****
    /* Remove GIMPLE_OMP_ATOMIC_STORE.  */
    gsi_remove (&si, true);
  
    if (gimple_in_ssa_p (cfun))
      update_ssa (TODO_update_ssa_no_phi);
  
-   /* ???  The above could use loop construction primitives.  */
-   if (current_loops)
-     loops_state_set (LOOPS_NEED_FIXUP);
- 
    return true;
  }
  
--- 5477,5490 ----
    /* Remove GIMPLE_OMP_ATOMIC_STORE.  */
    gsi_remove (&si, true);
  
+   struct loop *loop = alloc_loop ();
+   loop->header = loop_header;
+   loop->latch = loop_header;
+   add_loop (loop, loop_header->loop_father);
+ 
    if (gimple_in_ssa_p (cfun))
      update_ssa (TODO_update_ssa_no_phi);
  
    return true;
  }
  
Index: gcc/testsuite/gfortran.dg/gomp/pr57089.f90
===================================================================
*** gcc/testsuite/gfortran.dg/gomp/pr57089.f90  (revision 0)
--- gcc/testsuite/gfortran.dg/gomp/pr57089.f90  (working copy)
***************
*** 0 ****
--- 1,12 ----
+ ! PR middle-end/57089
+ ! { dg-do compile }
+ ! { dg-options "-O -fopenmp" }
+   SUBROUTINE T()
+     INTEGER            :: npoints, grad_deriv
+     SELECT CASE(grad_deriv)
+     CASE (0)
+        !$omp do
+        DO ii=1,npoints
+        END DO
+     END SELECT
+   END SUBROUTINE 

Reply via email to