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