From 82b40354915f37aaccce4736ec48cd2e4acfb6a2 Mon Sep 17 00:00:00 2001 From: rguenth Date: Fri, 26 Apr 2013 12:56:36 +0000 Subject: [PATCH] 2013-04-26 Richard Biener * omp-low.c (finalize_task_copyfn): Do not drop PROP_loops. (expand_omp_taskreg): Likewise. Mark loops for fixup. * tree-cfg.c (move_block_to_fn): Remap loop fathers. (fixup_loop_arrays_after_move): New function. (move_sese_region_to_fn): Properly outline the loop tree parts of the SESE region. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@198338 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 9 +++++++ gcc/omp-low.c | 14 +++++----- gcc/tree-cfg.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++---------- 3 files changed, 86 insertions(+), 19 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a6b7ba77665..dd490374f52 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2013-04-26 Richard Biener + + * omp-low.c (finalize_task_copyfn): Do not drop PROP_loops. + (expand_omp_taskreg): Likewise. Mark loops for fixup. + * tree-cfg.c (move_block_to_fn): Remap loop fathers. + (fixup_loop_arrays_after_move): New function. + (move_sese_region_to_fn): Properly outline the loop tree parts + of the SESE region. + 2013-04-26 Uros Bizjak * config/i386/i386.md (type, unit): Fix long lines. diff --git a/gcc/omp-low.c b/gcc/omp-low.c index eaeeaa5fe39..81ae5b4e5c1 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -1258,10 +1258,7 @@ finalize_task_copyfn (gimple task_stmt) return; child_cfun = DECL_STRUCT_FUNCTION (child_fn); - - /* Inform the callgraph about the new function. */ - DECL_STRUCT_FUNCTION (child_fn)->curr_properties - = cfun->curr_properties & ~PROP_loops; + DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties; push_cfun (child_cfun); bind = gimplify_body (child_fn, false); @@ -1276,6 +1273,7 @@ finalize_task_copyfn (gimple task_stmt) gimple_set_body (child_fn, seq); pop_cfun (); + /* Inform the callgraph about the new function. */ cgraph_add_new_function (child_fn, false); } @@ -3573,6 +3571,11 @@ expand_omp_taskreg (struct omp_region *region) 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); @@ -3589,8 +3592,7 @@ expand_omp_taskreg (struct omp_region *region) vec_safe_truncate (child_cfun->local_decls, dstidx); /* Inform the callgraph about the new function. */ - DECL_STRUCT_FUNCTION (child_fn)->curr_properties - = cfun->curr_properties & ~PROP_loops; + DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties; cgraph_add_new_function (child_fn, true); /* Fix the callgraph edges for child_cfun. Those for cfun will be diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index cbbc5c76bae..a8e9f5cbab6 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -6346,8 +6346,14 @@ move_block_to_fn (struct function *dest_cfun, basic_block bb, /* Remove BB from dominance structures. */ delete_from_dominance_info (CDI_DOMINATORS, bb); + + /* Move BB from its current loop to the copy in the new function. */ if (current_loops) - remove_bb_from_loops (bb); + { + struct loop *new_loop = (struct loop *)bb->loop_father->aux; + if (new_loop) + bb->loop_father = new_loop; + } /* Link BB to the new linked list. */ move_block_after (bb, after); @@ -6579,6 +6585,25 @@ replace_block_vars_by_duplicates (tree block, struct pointer_map_t *vars_map, replace_block_vars_by_duplicates (block, vars_map, to_context); } +/* Fixup the loop arrays and numbers after moving LOOP and its subloops + from FN1 to FN2. */ + +static void +fixup_loop_arrays_after_move (struct function *fn1, struct function *fn2, + struct loop *loop) +{ + /* Discard it from the old loop array. */ + (*fn1->x_current_loops->larray)[loop->num] = NULL; + + /* Place it in the new loop array, assigning it a new number. */ + loop->num = vec_safe_length (fn2->x_current_loops->larray); + vec_safe_push (fn2->x_current_loops->larray, loop); + + /* Recurse to children. */ + for (loop = loop->inner; loop; loop = loop->next) + fixup_loop_arrays_after_move (fn1, fn2, loop); +} + /* Move a single-entry, single-exit region delimited by ENTRY_BB and EXIT_BB to function DEST_CFUN. The whole region is replaced by a single basic block in the original CFG and the new basic block is @@ -6698,6 +6723,42 @@ move_sese_region_to_fn (struct function *dest_cfun, basic_block entry_bb, } } + /* Initialize an empty loop tree. */ + dest_cfun->x_current_loops = ggc_alloc_cleared_loops (); + init_loops_structure (dest_cfun, dest_cfun->x_current_loops, 1); + dest_cfun->x_current_loops->state = LOOPS_MAY_HAVE_MULTIPLE_LATCHES; + + /* Move the outlined loop tree part. */ + FOR_EACH_VEC_ELT (bbs, i, bb) + { + if (bb->loop_father->header == bb + && loop_outer (bb->loop_father) == loop) + { + struct loop *loop = bb->loop_father; + flow_loop_tree_node_remove (bb->loop_father); + flow_loop_tree_node_add (dest_cfun->x_current_loops->tree_root, loop); + fixup_loop_arrays_after_move (saved_cfun, cfun, loop); + } + + /* Remove loop exits from the outlined region. */ + if (saved_cfun->x_current_loops->exits) + FOR_EACH_EDGE (e, ei, bb->succs) + { + void **slot = htab_find_slot_with_hash + (saved_cfun->x_current_loops->exits, e, + htab_hash_pointer (e), NO_INSERT); + if (slot) + htab_clear_slot (saved_cfun->x_current_loops->exits, slot); + } + } + + + /* Adjust the number of blocks in the tree root of the outlined part. */ + dest_cfun->x_current_loops->tree_root->num_nodes = bbs.length () + 2; + + /* Setup a mapping to be used by move_block_to_fn. */ + loop->aux = current_loops->tree_root; + pop_cfun (); /* Move blocks from BBS into DEST_CFUN. */ @@ -6715,18 +6776,6 @@ move_sese_region_to_fn (struct function *dest_cfun, basic_block entry_bb, d.eh_map = eh_map; d.remap_decls_p = true; - /* Cancel all loops inside the SESE region. - ??? We rely on loop fixup because loop structure is not 100% - up-to-date when called from OMP lowering and thus cancel_loop_tree - will not work. - ??? Properly move loops to the outlined function. */ - FOR_EACH_VEC_ELT (bbs, i, bb) - if (bb->loop_father->header == bb) - { - bb->loop_father->header = NULL; - bb->loop_father->latch = NULL; - loops_state_set (LOOPS_NEED_FIXUP); - } FOR_EACH_VEC_ELT (bbs, i, bb) { /* No need to update edge counts on the last block. It has @@ -6736,6 +6785,13 @@ move_sese_region_to_fn (struct function *dest_cfun, basic_block entry_bb, after = bb; } + loop->aux = NULL; + /* Loop sizes are no longer correct, fix them up. */ + loop->num_nodes -= bbs.length (); + for (struct loop *outer = loop_outer (loop); + outer; outer = loop_outer (outer)) + outer->num_nodes -= bbs.length (); + /* Rewire BLOCK_SUBBLOCKS of orig_block. */ if (orig_block) { -- 2.11.4.GIT