2013-04-26 Richard Biener <rguenther@suse.de>
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 26 Apr 2013 12:56:36 +0000 (12:56 +0000)
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 26 Apr 2013 12:56:36 +0000 (12:56 +0000)
* 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
gcc/omp-low.c
gcc/tree-cfg.c

index a6b7ba7..dd49037 100644 (file)
@@ -1,3 +1,12 @@
+2013-04-26  Richard Biener  <rguenther@suse.de>
+
+       * 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  <ubizjak@gmail.com>
 
        * config/i386/i386.md (type, unit): Fix long lines.
index eaeeaa5..81ae5b4 100644 (file)
@@ -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
index cbbc5c7..a8e9f5c 100644 (file)
@@ -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)
     {