diff mbox

omp-low.h

Message ID 525DFE13.6050608@redhat.com
State New
Headers show

Commit Message

Andrew MacLeod Oct. 16, 2013, 2:46 a.m. UTC
On 10/11/2013 04:12 AM, Richard Biener wrote:
> On Fri, Oct 11, 2013 at 5:31 AM, Andrew MacLeod <amacleod@redhat.com> wrote:
>> Missed a bit in tree-flow.h..  I mistakenly assumed omp_region belonged
>> there :-P
>>
>> Anyway by moving struct omp_region into omp_low.h, along with the prototypes
>> from tree-flow.h, gimple.h and tree.h.  Everything works great with just a
>> few files actually requiring omp-low.h.
>>
>> AS an extra bonus, omp-low.c was *exporting*  "struct omp_region
>> *root_omp_region".   tree-cfg.c was checking it for non-null and calling
>> free_omp_regions().   Well,  free_omp_regions works just fine will a NULL
>> root_omp_region (basically does nothing and returns), so exporting it just
>> for that one check seems nonsensical.  Its now static.
>>
>> Bootstraps (will really-all languages) on x86_64-unknown-linux-gnu with no
>> new regressions.  also stage 1 cross builds on rs6000 and mips.  No more of
>> that crap :-)
>>
>> OK?
>
Here's the new reworked version after Jakub's merge.

Couple of extra things.  well, 3 :-)

1 - The entire omp_region structure was being exported for tree-cfg to 
use, and it was used in a  single routine.. make_edges.  I split out the 
GIMPLE_OMP clauses from that switch, and put them into a function in 
omp-low.c for make_edges to call.  Now the structure contents are 
private to omp-low.c which I think is better.
2 - A few extra front end files are now using find_omp_clause() and thus 
need omp-low.h.  A couple of them do not understand gimple (nor should 
they).  They didn't even know what "enum gimple_code" was and failed to 
compile both struct omp_region (which has an enum gimple_code), as well 
as one or two of the prototypes.  Item 1) solved the struct issue, but I 
still needed to avoid 'enum gimple_code' in the prototypes, which is why 
make_gimple_omp_edges doesn't pass in the code, rather it picks it up 
from the last gimple_stmt of the basic block. pretty easy.  I folowed 
the naming convention used for make_gimple_asm_edges().
3 - omp-low was also exporting copy_var_decl with tree-cfg.c as the only 
current consumer.   It is actually a very generic tree routine,  but 
since its only used in these gimple contexts, I moved it to gimple.c so 
I wont have to duplicate it later when I do the wrappers. It will likely 
become a method within the gimple_var_decl object, so it seemed 
reasonable to put it in gimple.c for now. omp-low.c doesn't seem like 
the right place to leave it.

Bootstraps on 86_64-unknown-linux-gnu and no new regressions.  OK?

Andrew

Comments

Jakub Jelinek Oct. 17, 2013, 3:15 p.m. UTC | #1
On Tue, Oct 15, 2013 at 10:46:43PM -0400, Andrew MacLeod wrote:
> Bootstraps on 86_64-unknown-linux-gnu and no new regressions.  OK?
> 
> Andrew

> 
> 	* tree-flow.h (struct omp_region): Move to omp-low.c

Missing dot at the end of line.

> 	Remove omp_ prototypes and variables.
> 	* gimple.h (omp_reduction_init): Move prototype to omp-low.h.
> 	(copy_var_decl): Relocate prototype from tree-flow.h.
> 	* gimple.c (copy_var_decl): Relocate from omp-low.c.
> 	* tree.h: Move prototype to omp-low.h.
> 	* omp-low.h: New File. Relocate prototypes here.

Missing space after .
> 	* omp-low.c (struct omp_region): Make local here.
> 	(root_omp_region): Make static.
> 	(copy_var_decl) Move to gimple.c.
> 	(new_omp_region): Make static.
> 	(make_gimple_omp_edges): New.  Refactored from tree-cfg.c make_edges.
> 	* tree-cfg.c: Include omp-low.h.
> 	(make_edges): Factor out OMP specific bits to make_gimple_omp_edges.
> 	* gimplify.c: Include omp-low.h.
> 	* tree-parloops.c: Include omp-low.h.

Use Likewise. for the second.

> 
> 	c
> 	* c-parser.c: Include omp-low.h.
> 	* c-typeck.c: Include omp-low.h.

Likewise.
> 
> 	cp
> 	* parser.c: Include omp-low.h.
> 	* semantics.c: Include omp-low.h.

Likewise.
> 
> 	fortran
> 	* trans-openmp.c: Include omp-low.h.

> *************** struct omp_for_data
> *** 135,141 ****
>   static splay_tree all_contexts;
>   static int taskreg_nesting_level;
>   static int target_nesting_level;
> ! struct omp_region *root_omp_region;
>   static bitmap task_shared_vars;
>   
>   static void scan_omp (gimple_seq *, omp_context *);
> --- 175,181 ----
>   static splay_tree all_contexts;
>   static int taskreg_nesting_level;
>   static int target_nesting_level;
> ! static struct omp_region *root_omp_region;
>   static bitmap task_shared_vars;
>   
>   static void scan_omp (gimple_seq *, omp_context *);

Why?

> --- 912,917 ----
> *************** debug_all_omp_regions (void)
> *** 1219,1225 ****
>   
>   /* Create a new parallel region starting at STMT inside region PARENT.  */
>   
> ! struct omp_region *
>   new_omp_region (basic_block bb, enum gimple_code type,
>   		struct omp_region *parent)
>   {
> --- 1238,1244 ----
>   
>   /* Create a new parallel region starting at STMT inside region PARENT.  */
>   
> ! static struct omp_region *
>   new_omp_region (basic_block bb, enum gimple_code type,
>   		struct omp_region *parent)
>   {

Likewise.

> +     case GIMPLE_OMP_CONTINUE:
...
> + 
> +       default:
> + 	gcc_unreachable ();

Bad indentation here, default: should be indented just by 4
spaces and gcc_unreachable () by 6.

Otherwise LGTM.

	Jakub
Andrew MacLeod Oct. 17, 2013, 3:52 p.m. UTC | #2
On 10/17/2013 11:15 AM, Jakub Jelinek wrote:
>> *************** struct omp_for_data
>> *** 135,141 ****
>>    static splay_tree all_contexts;
>>    static int taskreg_nesting_level;
>>    static int target_nesting_level;
>> ! struct omp_region *root_omp_region;
>>    static bitmap task_shared_vars;
>>    
>>    static void scan_omp (gimple_seq *, omp_context *);
>> --- 175,181 ----
>>    static splay_tree all_contexts;
>>    static int taskreg_nesting_level;
>>    static int target_nesting_level;
>> ! static struct omp_region *root_omp_region;
>>    static bitmap task_shared_vars;
>>    
>>    static void scan_omp (gimple_seq *, omp_context *);
> Why?
It should be static now since it is no longer exported outside the 
file... and can't be now that struct omp_region is declared in omp-low.c

>> --- 912,917 ----
>> *************** debug_all_omp_regions (void)
>> *** 1219,1225 ****
>>    
>>    /* Create a new parallel region starting at STMT inside region PARENT.  */
>>    
>> ! struct omp_region *
>>    new_omp_region (basic_block bb, enum gimple_code type,
>>    		struct omp_region *parent)
>>    {
>> --- 1238,1244 ----
>>    
>>    /* Create a new parallel region starting at STMT inside region PARENT.  */
>>    
>> ! static struct omp_region *
>>    new_omp_region (basic_block bb, enum gimple_code type,
>>    		struct omp_region *parent)
>>    {
> Likewise.
again, because it is no longer an exported function...  only 
tree-cfg.c::make_edges needed it, and it no longer does.

Thanks.

Andrew
Jakub Jelinek Oct. 17, 2013, 3:54 p.m. UTC | #3
On Thu, Oct 17, 2013 at 11:52:21AM -0400, Andrew MacLeod wrote:
> On 10/17/2013 11:15 AM, Jakub Jelinek wrote:
> >>*************** struct omp_for_data
> >>*** 135,141 ****
> >>   static splay_tree all_contexts;
> >>   static int taskreg_nesting_level;
> >>   static int target_nesting_level;
> >>! struct omp_region *root_omp_region;
> >>   static bitmap task_shared_vars;
> >>   static void scan_omp (gimple_seq *, omp_context *);
> >>--- 175,181 ----
> >>   static splay_tree all_contexts;
> >>   static int taskreg_nesting_level;
> >>   static int target_nesting_level;
> >>! static struct omp_region *root_omp_region;
> >>   static bitmap task_shared_vars;
> >>   static void scan_omp (gimple_seq *, omp_context *);
> >Why?
> It should be static now since it is no longer exported outside the
> file... and can't be now that struct omp_region is declared in
> omp-low.c

Ah, just misread your change, thought you are adding struct keyword
while you are actually adding static.  Sorry.

	Jakub
diff mbox

Patch


	* tree-flow.h (struct omp_region): Move to omp-low.c
	Remove omp_ prototypes and variables.
	* gimple.h (omp_reduction_init): Move prototype to omp-low.h.
	(copy_var_decl): Relocate prototype from tree-flow.h.
	* gimple.c (copy_var_decl): Relocate from omp-low.c.
	* tree.h: Move prototype to omp-low.h.
	* omp-low.h: New File. Relocate prototypes here.
	* omp-low.c (struct omp_region): Make local here.
	(root_omp_region): Make static.
	(copy_var_decl) Move to gimple.c.
	(new_omp_region): Make static.
	(make_gimple_omp_edges): New.  Refactored from tree-cfg.c make_edges.
	* tree-cfg.c: Include omp-low.h.
	(make_edges): Factor out OMP specific bits to make_gimple_omp_edges.
	* gimplify.c: Include omp-low.h.
	* tree-parloops.c: Include omp-low.h.

	c
	* c-parser.c: Include omp-low.h.
	* c-typeck.c: Include omp-low.h.

	cp
	* parser.c: Include omp-low.h.
	* semantics.c: Include omp-low.h.

	fortran
	* trans-openmp.c: Include omp-low.h.

Index: tree-flow.h
===================================================================
*** tree-flow.h	(revision 203625)
--- tree-flow.h	(working copy)
*************** along with GCC; see the file COPYING3.
*** 37,92 ****
  #include "tree-into-ssa.h"
  #include "tree-ssa-loop.h"
  
- /*---------------------------------------------------------------------------
- 			      OpenMP Region Tree
- ---------------------------------------------------------------------------*/
- 
- /* Parallel region information.  Every parallel and workshare
-    directive is enclosed between two markers, the OMP_* directive
-    and a corresponding OMP_RETURN statement.  */
- 
- struct omp_region
- {
-   /* The enclosing region.  */
-   struct omp_region *outer;
- 
-   /* First child region.  */
-   struct omp_region *inner;
- 
-   /* Next peer region.  */
-   struct omp_region *next;
- 
-   /* Block containing the omp directive as its last stmt.  */
-   basic_block entry;
- 
-   /* Block containing the OMP_RETURN as its last stmt.  */
-   basic_block exit;
- 
-   /* Block containing the OMP_CONTINUE as its last stmt.  */
-   basic_block cont;
- 
-   /* If this is a combined parallel+workshare region, this is a list
-      of additional arguments needed by the combined parallel+workshare
-      library call.  */
-   vec<tree, va_gc> *ws_args;
- 
-   /* The code for the omp directive of this region.  */
-   enum gimple_code type;
- 
-   /* Schedule kind, only used for OMP_FOR type regions.  */
-   enum omp_clause_schedule_kind sched_kind;
- 
-   /* True if this is a combined parallel+workshare region.  */
-   bool is_combined_parallel;
- };
- 
- extern struct omp_region *root_omp_region;
- extern struct omp_region *new_omp_region (basic_block, enum gimple_code,
- 					  struct omp_region *);
- extern void free_omp_regions (void);
- void omp_expand_local (basic_block);
- tree copy_var_decl (tree, tree, tree);
- 
  /* Location to track pending stmt for edge insertion.  */
  #define PENDING_STMT(e)	((e)->insns.g)
  
--- 37,42 ----
Index: gimple.h
===================================================================
*** gimple.h	(revision 203625)
--- gimple.h	(working copy)
*************** extern tree canonicalize_cond_expr_cond
*** 1086,1094 ****
  extern void dump_decl_set (FILE *, bitmap);
  extern bool gimple_can_coalesce_p (tree, tree);
  extern bool nonfreeing_call_p (gimple);
! 
! /* In omp-low.c.  */
! extern tree omp_reduction_init (tree, tree);
  
  /* In trans-mem.c.  */
  extern void diagnose_tm_safe_errors (tree);
--- 1086,1092 ----
  extern void dump_decl_set (FILE *, bitmap);
  extern bool gimple_can_coalesce_p (tree, tree);
  extern bool nonfreeing_call_p (gimple);
! extern tree copy_var_decl (tree, tree, tree);
  
  /* In trans-mem.c.  */
  extern void diagnose_tm_safe_errors (tree);
Index: gimple.c
===================================================================
*** gimple.c	(revision 203625)
--- gimple.c	(working copy)
*************** nonfreeing_call_p (gimple call)
*** 4063,4065 ****
--- 4063,4086 ----
  
    return false;
  }
+ 
+ /* Create a new VAR_DECL and copy information from VAR to it.  */
+ 
+ tree
+ copy_var_decl (tree var, tree name, tree type)
+ {
+   tree copy = build_decl (DECL_SOURCE_LOCATION (var), VAR_DECL, name, type);
+ 
+   TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (var);
+   TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (var);
+   DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (var);
+   DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (var);
+   DECL_IGNORED_P (copy) = DECL_IGNORED_P (var);
+   DECL_CONTEXT (copy) = DECL_CONTEXT (var);
+   TREE_NO_WARNING (copy) = TREE_NO_WARNING (var);
+   TREE_USED (copy) = 1;
+   DECL_SEEN_IN_BIND_EXPR_P (copy) = 1;
+   DECL_ATTRIBUTES (copy) = DECL_ATTRIBUTES (var);
+ 
+   return copy;
+ }
Index: tree.h
===================================================================
*** tree.h	(revision 203625)
--- tree.h	(working copy)
*************** extern tree build_translation_unit_decl
*** 3553,3559 ****
  extern tree build_block (tree, tree, tree, tree);
  extern tree build_empty_stmt (location_t);
  extern tree build_omp_clause (location_t, enum omp_clause_code);
- extern tree find_omp_clause (tree, enum omp_clause_code);
  
  extern tree build_vl_exp_stat (enum tree_code, int MEM_STAT_DECL);
  #define build_vl_exp(c, n) build_vl_exp_stat (c, n MEM_STAT_INFO)
--- 3553,3558 ----
Index: omp-low.h
===================================================================
*** omp-low.h	(revision 0)
--- omp-low.h	(working copy)
***************
*** 0 ****
--- 1,31 ----
+ /* Header file for openMP lowering directives.
+    Copyright (C) 2013 Free Software Foundation, Inc.
+ 
+ This file is part of GCC.
+ 
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+ 
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+  for more details.
+ 
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3.  If not see
+ <http://www.gnu.org/licenses/>.  */
+ 
+ #ifndef GCC_OMP_LOW_H
+ #define GCC_OMP_LOW_H
+ 
+ struct omp_region;
+ 
+ extern tree find_omp_clause (tree, enum omp_clause_code);
+ extern void omp_expand_local (basic_block);
+ extern void free_omp_regions (void);
+ extern tree omp_reduction_init (tree, tree);
+ extern bool make_gimple_omp_edges (basic_block bb, struct omp_region **region);
+ 
+ #endif /* GCC_OMP_LOW_H */
Index: omp-low.c
===================================================================
*** omp-low.c	(revision 203625)
--- omp-low.c	(working copy)
*************** along with GCC; see the file COPYING3.
*** 43,48 ****
--- 43,49 ----
  #include "optabs.h"
  #include "cfgloop.h"
  #include "target.h"
+ #include "omp-low.h"
  
  
  /* Lowering of OpenMP parallel and workshare constructs proceeds in two
*************** along with GCC; see the file COPYING3.
*** 56,61 ****
--- 57,101 ----
     scanned for parallel regions which are then moved to a new
     function, to be invoked by the thread library.  */
  
+ /* Parallel region information.  Every parallel and workshare
+    directive is enclosed between two markers, the OMP_* directive
+    and a corresponding OMP_RETURN statement.  */
+ 
+ struct omp_region
+ {
+   /* The enclosing region.  */
+   struct omp_region *outer;
+ 
+   /* First child region.  */
+   struct omp_region *inner;
+ 
+   /* Next peer region.  */
+   struct omp_region *next;
+ 
+   /* Block containing the omp directive as its last stmt.  */
+   basic_block entry;
+ 
+   /* Block containing the OMP_RETURN as its last stmt.  */
+   basic_block exit;
+ 
+   /* Block containing the OMP_CONTINUE as its last stmt.  */
+   basic_block cont;
+ 
+   /* If this is a combined parallel+workshare region, this is a list
+      of additional arguments needed by the combined parallel+workshare
+      library call.  */
+   vec<tree, va_gc> *ws_args;
+ 
+   /* The code for the omp directive of this region.  */
+   enum gimple_code type;
+ 
+   /* Schedule kind, only used for OMP_FOR type regions.  */
+   enum omp_clause_schedule_kind sched_kind;
+ 
+   /* True if this is a combined parallel+workshare region.  */
+   bool is_combined_parallel;
+ };
+ 
  /* Context structure.  Used to store information about each parallel
     directive in the code.  */
  
*************** struct omp_for_data
*** 135,141 ****
  static splay_tree all_contexts;
  static int taskreg_nesting_level;
  static int target_nesting_level;
! struct omp_region *root_omp_region;
  static bitmap task_shared_vars;
  
  static void scan_omp (gimple_seq *, omp_context *);
--- 175,181 ----
  static splay_tree all_contexts;
  static int taskreg_nesting_level;
  static int target_nesting_level;
! static struct omp_region *root_omp_region;
  static bitmap task_shared_vars;
  
  static void scan_omp (gimple_seq *, omp_context *);
*************** use_pointer_for_field (tree decl, omp_co
*** 872,898 ****
    return false;
  }
  
- /* Create a new VAR_DECL and copy information from VAR to it.  */
- 
- tree
- copy_var_decl (tree var, tree name, tree type)
- {
-   tree copy = build_decl (DECL_SOURCE_LOCATION (var), VAR_DECL, name, type);
- 
-   TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (var);
-   TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (var);
-   DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (var);
-   DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (var);
-   DECL_IGNORED_P (copy) = DECL_IGNORED_P (var);
-   DECL_CONTEXT (copy) = DECL_CONTEXT (var);
-   TREE_NO_WARNING (copy) = TREE_NO_WARNING (var);
-   TREE_USED (copy) = 1;
-   DECL_SEEN_IN_BIND_EXPR_P (copy) = 1;
-   DECL_ATTRIBUTES (copy) = DECL_ATTRIBUTES (var);
- 
-   return copy;
- }
- 
  /* Construct a new automatic decl similar to VAR.  */
  
  static tree
--- 912,917 ----
*************** debug_all_omp_regions (void)
*** 1219,1225 ****
  
  /* Create a new parallel region starting at STMT inside region PARENT.  */
  
! struct omp_region *
  new_omp_region (basic_block bb, enum gimple_code type,
  		struct omp_region *parent)
  {
--- 1238,1244 ----
  
  /* Create a new parallel region starting at STMT inside region PARENT.  */
  
! static struct omp_region *
  new_omp_region (basic_block bb, enum gimple_code type,
  		struct omp_region *parent)
  {
*************** diagnose_sb_2 (gimple_stmt_iterator *gsi
*** 10312,10317 ****
--- 10331,10451 ----
    return NULL_TREE;
  }
  
+ /* Called from tree-cfg.c::make_edges to create cfg edges for all GIMPLE_OMP
+    codes.  */
+ bool
+ make_gimple_omp_edges (basic_block bb, struct omp_region **region)
+ {
+   gimple last = last_stmt (bb);
+   enum gimple_code code = gimple_code (last);
+   struct omp_region *cur_region = *region;
+   bool fallthru = false;
+ 
+   switch (code)
+     {
+     case GIMPLE_OMP_PARALLEL:
+     case GIMPLE_OMP_TASK:
+     case GIMPLE_OMP_FOR:
+     case GIMPLE_OMP_SINGLE:
+     case GIMPLE_OMP_TEAMS:
+     case GIMPLE_OMP_MASTER:
+     case GIMPLE_OMP_TASKGROUP:
+     case GIMPLE_OMP_ORDERED:
+     case GIMPLE_OMP_CRITICAL:
+     case GIMPLE_OMP_SECTION:
+       cur_region = new_omp_region (bb, code, cur_region);
+       fallthru = true;
+       break;
+ 
+     case GIMPLE_OMP_TARGET:
+       cur_region = new_omp_region (bb, code, cur_region);
+       fallthru = true;
+       if (gimple_omp_target_kind (last) == GF_OMP_TARGET_KIND_UPDATE)
+ 	cur_region = cur_region->outer;
+       break;
+ 
+     case GIMPLE_OMP_SECTIONS:
+       cur_region = new_omp_region (bb, code, cur_region);
+       fallthru = true;
+       break;
+ 
+     case GIMPLE_OMP_SECTIONS_SWITCH:
+       fallthru = false;
+       break;
+ 
+     case GIMPLE_OMP_ATOMIC_LOAD:
+     case GIMPLE_OMP_ATOMIC_STORE:
+        fallthru = true;
+        break;
+ 
+     case GIMPLE_OMP_RETURN:
+       /* In the case of a GIMPLE_OMP_SECTION, the edge will go
+ 	 somewhere other than the next block.  This will be
+ 	 created later.  */
+       cur_region->exit = bb;
+       fallthru = cur_region->type != GIMPLE_OMP_SECTION;
+       cur_region = cur_region->outer;
+       break;
+ 
+     case GIMPLE_OMP_CONTINUE:
+       cur_region->cont = bb;
+       switch (cur_region->type)
+ 	{
+ 	case GIMPLE_OMP_FOR:
+ 	  /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
+ 	     succs edges as abnormal to prevent splitting
+ 	     them.  */
+ 	  single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
+ 	  /* Make the loopback edge.  */
+ 	  make_edge (bb, single_succ (cur_region->entry),
+ 		     EDGE_ABNORMAL);
+ 
+ 	  /* Create an edge from GIMPLE_OMP_FOR to exit, which
+ 	     corresponds to the case that the body of the loop
+ 	     is not executed at all.  */
+ 	  make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
+ 	  make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
+ 	  fallthru = false;
+ 	  break;
+ 
+ 	case GIMPLE_OMP_SECTIONS:
+ 	  /* Wire up the edges into and out of the nested sections.  */
+ 	  {
+ 	    basic_block switch_bb = single_succ (cur_region->entry);
+ 
+ 	    struct omp_region *i;
+ 	    for (i = cur_region->inner; i ; i = i->next)
+ 	      {
+ 		gcc_assert (i->type == GIMPLE_OMP_SECTION);
+ 		make_edge (switch_bb, i->entry, 0);
+ 		make_edge (i->exit, bb, EDGE_FALLTHRU);
+ 	      }
+ 
+ 	    /* Make the loopback edge to the block with
+ 	       GIMPLE_OMP_SECTIONS_SWITCH.  */
+ 	    make_edge (bb, switch_bb, 0);
+ 
+ 	    /* Make the edge from the switch to exit.  */
+ 	    make_edge (switch_bb, bb->next_bb, 0);
+ 	    fallthru = false;
+ 	  }
+ 	  break;
+ 
+ 	default:
+ 	  gcc_unreachable ();
+ 	}
+       break;
+ 
+       default:
+ 	gcc_unreachable ();
+     }
+ 
+   if (*region != cur_region)
+     *region = cur_region;
+ 
+   return fallthru;
+ }
+ 
  static unsigned int
  diagnose_omp_structured_block_errors (void)
  {
Index: tree-cfg.c
===================================================================
*** tree-cfg.c	(revision 203625)
--- tree-cfg.c	(working copy)
*************** along with GCC; see the file COPYING3.
*** 42,47 ****
--- 42,48 ----
  #include "tree-inline.h"
  #include "target.h"
  #include "tree-ssa-live.h"
+ #include "omp-low.h"
  
  /* This file contains functions for building the Control Flow Graph (CFG)
     for a function tree.  */
*************** make_edges (void)
*** 607,703 ****
  	      fallthru = true;
  	      break;
  
! 	    case GIMPLE_OMP_PARALLEL:
! 	    case GIMPLE_OMP_TASK:
! 	    case GIMPLE_OMP_FOR:
! 	    case GIMPLE_OMP_SINGLE:
! 	    case GIMPLE_OMP_TEAMS:
! 	    case GIMPLE_OMP_MASTER:
! 	    case GIMPLE_OMP_TASKGROUP:
! 	    case GIMPLE_OMP_ORDERED:
! 	    case GIMPLE_OMP_CRITICAL:
! 	    case GIMPLE_OMP_SECTION:
! 	      cur_region = new_omp_region (bb, code, cur_region);
! 	      fallthru = true;
! 	      break;
! 
! 	    case GIMPLE_OMP_TARGET:
! 	      cur_region = new_omp_region (bb, code, cur_region);
! 	      fallthru = true;
! 	      if (gimple_omp_target_kind (last) == GF_OMP_TARGET_KIND_UPDATE)
! 		cur_region = cur_region->outer;
! 	      break;
! 
! 	    case GIMPLE_OMP_SECTIONS:
! 	      cur_region = new_omp_region (bb, code, cur_region);
! 	      fallthru = true;
! 	      break;
! 
! 	    case GIMPLE_OMP_SECTIONS_SWITCH:
! 	      fallthru = false;
! 	      break;
! 
!             case GIMPLE_OMP_ATOMIC_LOAD:
!             case GIMPLE_OMP_ATOMIC_STORE:
!                fallthru = true;
!                break;
! 
! 	    case GIMPLE_OMP_RETURN:
! 	      /* In the case of a GIMPLE_OMP_SECTION, the edge will go
! 		 somewhere other than the next block.  This will be
! 		 created later.  */
! 	      cur_region->exit = bb;
! 	      fallthru = cur_region->type != GIMPLE_OMP_SECTION;
! 	      cur_region = cur_region->outer;
! 	      break;
! 
! 	    case GIMPLE_OMP_CONTINUE:
! 	      cur_region->cont = bb;
! 	      switch (cur_region->type)
! 		{
! 		case GIMPLE_OMP_FOR:
! 		  /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
! 		     succs edges as abnormal to prevent splitting
! 		     them.  */
! 		  single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
! 		  /* Make the loopback edge.  */
! 		  make_edge (bb, single_succ (cur_region->entry),
! 			     EDGE_ABNORMAL);
! 
! 		  /* Create an edge from GIMPLE_OMP_FOR to exit, which
! 		     corresponds to the case that the body of the loop
! 		     is not executed at all.  */
! 		  make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
! 		  make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
! 		  fallthru = false;
! 		  break;
! 
! 		case GIMPLE_OMP_SECTIONS:
! 		  /* Wire up the edges into and out of the nested sections.  */
! 		  {
! 		    basic_block switch_bb = single_succ (cur_region->entry);
! 
! 		    struct omp_region *i;
! 		    for (i = cur_region->inner; i ; i = i->next)
! 		      {
! 			gcc_assert (i->type == GIMPLE_OMP_SECTION);
! 			make_edge (switch_bb, i->entry, 0);
! 			make_edge (i->exit, bb, EDGE_FALLTHRU);
! 		      }
! 
! 		    /* Make the loopback edge to the block with
! 		       GIMPLE_OMP_SECTIONS_SWITCH.  */
! 		    make_edge (bb, switch_bb, 0);
! 
! 		    /* Make the edge from the switch to exit.  */
! 		    make_edge (switch_bb, bb->next_bb, 0);
! 		    fallthru = false;
! 		  }
! 		  break;
! 
! 		default:
! 		  gcc_unreachable ();
! 		}
  	      break;
  
  	    case GIMPLE_TRANSACTION:
--- 608,615 ----
  	      fallthru = true;
  	      break;
  
! 	    CASE_GIMPLE_OMP:
! 	      fallthru = make_gimple_omp_edges (bb, &cur_region);
  	      break;
  
  	    case GIMPLE_TRANSACTION:
*************** make_edges (void)
*** 721,728 ****
  	make_edge (bb, bb->next_bb, EDGE_FALLTHRU);
      }
  
!   if (root_omp_region)
!     free_omp_regions ();
  
    /* Fold COND_EXPR_COND of each COND_EXPR.  */
    fold_cond_expr_cond ();
--- 633,639 ----
  	make_edge (bb, bb->next_bb, EDGE_FALLTHRU);
      }
  
!   free_omp_regions ();
  
    /* Fold COND_EXPR_COND of each COND_EXPR.  */
    fold_cond_expr_cond ();
Index: gimplify.c
===================================================================
*** gimplify.c	(revision 203625)
--- gimplify.c	(working copy)
*************** along with GCC; see the file COPYING3.
*** 42,47 ****
--- 42,48 ----
  #include "pointer-set.h"
  #include "splay-tree.h"
  #include "vec.h"
+ #include "omp-low.h"
  
  #include "langhooks-def.h"	/* FIXME: for lhd_set_decl_assembler_name */
  #include "tree-pass.h"		/* FIXME: only for PROP_gimple_any */
Index: tree-parloops.c
===================================================================
*** tree-parloops.c	(revision 203625)
--- tree-parloops.c	(working copy)
*************** along with GCC; see the file COPYING3.
*** 32,37 ****
--- 32,38 ----
  #include "tree-vectorizer.h"
  #include "tree-hasher.h"
  #include "tree-parloops.h"
+ #include "omp-low.h"
  
  /* This pass tries to distribute iterations of loops into several threads.
     The implementation is straightforward -- for each loop we test whether its
Index: c/c-parser.c
===================================================================
*** c/c-parser.c	(revision 203625)
--- c/c-parser.c	(working copy)
*************** along with GCC; see the file COPYING3.
*** 55,60 ****
--- 55,61 ----
  #include "target.h"
  #include "cgraph.h"
  #include "plugin.h"
+ #include "omp-low.h"
  
  
  /* Initialization routine for this file.  */
Index: c/c-typeck.c
===================================================================
*** c/c-typeck.c	(revision 203625)
--- c/c-typeck.c	(working copy)
*************** along with GCC; see the file COPYING3.
*** 38,43 ****
--- 38,44 ----
  #include "bitmap.h"
  #include "gimple.h"
  #include "tree-inline.h"
+ #include "omp-low.h"
  #include "c-family/c-objc.h"
  #include "c-family/c-common.h"
  #include "c-family/c-ubsan.h"
Index: cp/parser.c
===================================================================
*** cp/parser.c	(revision 203625)
--- cp/parser.c	(working copy)
*************** along with GCC; see the file COPYING3.
*** 39,44 ****
--- 39,45 ----
  #include "tree-pretty-print.h"
  #include "parser.h"
  #include "type-utils.h"
+ #include "omp-low.h"
  
  
  /* The lexer.  */
Index: cp/semantics.c
===================================================================
*** cp/semantics.c	(revision 203625)
--- cp/semantics.c	(working copy)
*************** along with GCC; see the file COPYING3.
*** 44,49 ****
--- 44,50 ----
  #include "gimple.h"
  #include "bitmap.h"
  #include "hash-table.h"
+ #include "omp-low.h"
  
  static bool verify_constant (tree, bool, bool *, bool *);
  #define VERIFY_CONSTANT(X)						\
Index: fortran/trans-openmp.c
===================================================================
*** fortran/trans-openmp.c	(revision 203625)
--- fortran/trans-openmp.c	(working copy)
*************** along with GCC; see the file COPYING3.
*** 32,37 ****
--- 32,38 ----
  #include "trans-array.h"
  #include "trans-const.h"
  #include "arith.h"
+ #include "omp-low.h"
  
  int ompws_flags;