This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Autoparallelization


Hello,

> > in the IL, there is nothing really missing.  Only a massive rewrite 
> > of omp-low.c would be necessary, to make it all work on SSA and 
> > probably also preserve loop structures.
> > 
> I doubt that you will need a *massive* rewrite.  OTOH, Richard and I
> overhauled it at least 3 or 4 times during development, so it's not as
> bad as it seems.  Yes, there will be work to be done to support SSA, and
> I am not sure how much painful will that be.  That's the one thing I
> specifically set aside to be dealt with when the autoparallelizer was
> implemented.

here is patch that makes omp expansion work on SSA.  Things get pretty
ugly at some places, but overall, it's not as disasterous as I expected
it to be :-)

It is not really well tested (I just made it pass libgomp.c testsuite);
are there some applications using OpenMP you would recommend for
debugging and testing it?

The most important changes:
-- omp_expand functions now work both on ssa form and non-ssa gimple
   (this is necessary so that omp works even with -O0); by using
   force_gimple_operand_bsi, this turned out to be much simpler
   than I feared.
-- to make ssa form updating possible, I had to add operand (control
   variable) to OMP_SECTIONS, def and use of the control variable
   to OMP_CONTINUE, and create new code OMP_SECTIONS_SWITCH;
   also, some changes to make cfg more precise for OMP constructs
   were necessary.
-- move_sese_region_to_fn duplicates all the var_decls in the moved
   region.  The original var_decls may be referenced from points-to
   information and virtual operands, and removing them from there
   would be quite nontrivial (basically equivalent to running alias
   analysis pass -- given that we would have to do this after every
   omp_parallel construct is expanded, this would not be practical).
-- the code moved by move_sese_region_to_fn must be rewritten out of
   ssa form; to avoid problems with variables and other data structures
   getting shared between the two functions, I had to modify the
   out-of-ssa pass so that it does not use variable annotations.

Zdenek

	* tree-pretty-print.c (dump_generic_node): Handle OMP_SECTIONS_SWITCH
	and extra arguments of OMP_SECTIONS and OMP_CONTINUE.
	* tree.h (OMP_DIRECTIVE_P): Add OMP_SECTIONS_SWITCH.
	(OMP_SECTIONS_CONTROL): New macro.
	* tree-pass.h (pass_expand_omp_O0): Declare.
	* omp-low.c (find_omp_clause): Export.
	(copy_var_decl): New function.
	(omp_copy_decl_2): Use copy_var_decl.
	(build_omp_barrier): Do not gimplify the result.
	(lower_rec_input_clauses): Gimplify result of build_omp_barrier.
	(extract_omp_for_data, expand_parallel_call, expand_omp_parallel,
	expand_omp_for_generic, expand_omp_for_static_nochunk,
	expand_omp_for_static_chunk, expand_omp_for, expand_omp_sections,
	expand_omp_single): Work on ssa form.
	(build_omp_regions_1): Handle OMP_SECTIONS_SWITCH.
	(gate_expand_omp_O0, pass_expand_omp_O0): New pass structure.
	(lower_omp_sections): Emit OMP_SECTIONS_SWITCH.  Add arguments to
	OMP_CONTINUE and OMP_SECTIONS.
	(lower_omp_for): Regimplify OMP_CLAUSE_SCHEDULE_CHUNK_EXPR.
	Add arguments to OMP_CONTINUE.
	* tree-gimple.c (is_gimple_stmt): Add OMP_SECTIONS_SWITCH.
	* tree-ssa-alias.c (is_escape_site): Handle OMP_PARALLEL.
	* gimple-low.c (lower_stmt): Handle OMP_SECTIONS_SWITCH.
	* tree-parloops.c (mark_virtual_ops_for_renaming): Moved to tree-cfg.c.
	(mark_call_virtual_operands): Exported.
	(extract_loop_to_function): Move some parts to go_out_of_ssa.
	* tree.def (OMP_SECTIONS): Change number of operands to 3.
	(OMP_SECTIONS_SWITCH): New code.
	(OMP_CONTINUE): Change number of operands to 2.
	* tree-inline.c (estimate_num_insns_1): Handle OMP_SECTIONS_SWITCH.
	* tree-outof-ssa.c (go_out_of_ssa): Take new function as an argument.
	Remove references to variables from the old function, and clear
	their annotations.
	(create_temp): Do not record the variable as referenced.
	* tree-flow.h (copy_var_decl, find_omp_clause,
	mark_virtual_ops_for_renaming, mark_call_virtual_operands): Declare.
	(go_out_of_ssa, force_gimple_operand_bsi): Declaration changed.
	* tree-cfg.c (make_edges): Generate more precise cfg for OMP
	constructs.
	(tree_redirect_edge_and_branch): Handle OMP codes.
	(replace_by_duplicate_decl, mark_virtual_ops_in_region): New functions.
	(new_label_mapper): Use XNEW.
	(move_stmt_r, move_block_to_fn, move_sese_region_to_fn): Copy the
	region to clear decls.
	(mark_virtual_ops_for_renaming): Moved from tree-parloops.c.
	* passes.c (init_optimization_passes): Move pass_expand_omp to
	pass_all_optimizations.  Use pass_expand_omp_O0 instead of it.
	* tree-ssa-operands.c (get_expr_operands): Record operands of
	OMP constructs.

	* gimplify.c (force_gimple_operand_bsi):  Add arguments to specify
	direction of insertion.
	* tree-scalar-evolution.c (scev_const_prop): Change arguments to
	force_gimple_operand_bsi.
	* tree-ssa-address.c (gimplify_mem_ref_parts, create_mem_ref): Ditto.
	* tree-ssa-loop-prefetch.c (issue_prefetch_ref): Ditto.
	* tree-profile.c (prepare_instrumented_value,
	tree_gen_interval_profiler, tree_gen_pow2_profiler,
	tree_gen_one_value_profiler): Ditto.
	* tree-ssa-reassoc.c (negate_value): Ditto.

	* tree-flow-inline.h (set_is_used): Removed.
	* tree-ssa-live.c (var_partition_map, out_of_ssa): New variables.
	(int_int_map_eq, int_int_map_hash, delete_var_partition_map,
	init_var_partition_map, int_int_map_find_or_insert): New functions.
	(change_partition_var, mark_all_vars_used, mark_all_vars_used_1,
	remove_unused_locals, create_ssa_var_map, root_var_init): Do not
	use variable annotations.
	* tree-ssa-live.h (VAR_ANN_PARTITION, VAR_ANN_ROOT_INDEX): Removed.
	(struct int_int_map, var_partition_map, out_of_ssa,
	int_int_map_find_or_insert, init_var_partition_map,
	delete_var_partition_map): Declare.
	(var_to_partition): Do not use variable annotations.
	* tree-outof-ssa.c (insert_copy_on_edge, coalesce_ssa_name,
	assign_vars, replace_use_variable, replace_def_variable,
	rewrite_out_of_ssa): Do not use variable annotations.
	* tree-flow.h (struct var_ann_d): Removed out_of_ssa_tag,
	root_var_processed, partition and root_index.
	(set_is_used): Declaration removed.

Index: tree-pretty-print.c
===================================================================
*** tree-pretty-print.c	(revision 117561)
--- tree-pretty-print.c	(working copy)
*************** dump_generic_node (pretty_printer *buffe
*** 1780,1788 ****
--- 1780,1800 ----
  
      case OMP_SECTIONS:
        pp_string (buffer, "#pragma omp sections");
+       if (OMP_SECTIONS_CONTROL (node))
+ 	{
+ 	  pp_string (buffer, " (");
+ 	  dump_generic_node (buffer, OMP_SECTIONS_CONTROL (node), spc,
+ 			     flags, false);
+ 	  pp_string (buffer, ")");
+ 	}
        dump_omp_clauses (buffer, OMP_SECTIONS_CLAUSES (node), spc, flags);
        goto dump_omp_body;
  
+     case OMP_SECTIONS_SWITCH:
+       pp_string (buffer, "OMP_SECTIONS_SWITCH");
+       is_expr = false;
+       break;
+  
      case OMP_SECTION:
        pp_string (buffer, "#pragma omp section");
        goto dump_omp_body;
*************** dump_generic_node (pretty_printer *buffe
*** 1830,1836 ****
        break;
  
      case OMP_CONTINUE:
!       pp_string (buffer, "OMP_CONTINUE");
        is_expr = false;
        break;
  
--- 1842,1852 ----
        break;
  
      case OMP_CONTINUE:
!       pp_string (buffer, "OMP_CONTINUE (");
!       dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
!       pp_string (buffer, " <- ");
!       dump_generic_node (buffer, TREE_OPERAND (node, 1), spc, flags, false);
!       pp_string (buffer, ")");
        is_expr = false;
        break;
  
Index: tree.h
===================================================================
*** tree.h	(revision 117561)
--- tree.h	(working copy)
*************** extern const enum tree_code_class tree_c
*** 173,178 ****
--- 173,179 ----
      (TREE_CODE (NODE) == OMP_PARALLEL			\
       || TREE_CODE (NODE) == OMP_FOR			\
       || TREE_CODE (NODE) == OMP_SECTIONS		\
+      || TREE_CODE (NODE) == OMP_SECTIONS_SWITCH		\
       || TREE_CODE (NODE) == OMP_SINGLE			\
       || TREE_CODE (NODE) == OMP_SECTION			\
       || TREE_CODE (NODE) == OMP_MASTER			\
*************** struct tree_constructor GTY(())
*** 1571,1576 ****
--- 1572,1578 ----
  
  #define OMP_SECTIONS_BODY(NODE)    TREE_OPERAND (OMP_SECTIONS_CHECK (NODE), 0)
  #define OMP_SECTIONS_CLAUSES(NODE) TREE_OPERAND (OMP_SECTIONS_CHECK (NODE), 1)
+ #define OMP_SECTIONS_CONTROL(NODE) TREE_OPERAND (OMP_SECTIONS_CHECK (NODE), 2)
  
  #define OMP_SECTION_BODY(NODE)	   TREE_OPERAND (OMP_SECTION_CHECK (NODE), 0)
  
Index: tree-pass.h
===================================================================
*** tree-pass.h	(revision 117561)
--- tree-pass.h	(working copy)
*************** extern struct tree_opt_pass pass_lower_v
*** 275,280 ****
--- 275,281 ----
  extern struct tree_opt_pass pass_lower_vector_ssa;
  extern struct tree_opt_pass pass_lower_omp;
  extern struct tree_opt_pass pass_expand_omp;
+ extern struct tree_opt_pass pass_expand_omp_O0;
  extern struct tree_opt_pass pass_object_sizes;
  extern struct tree_opt_pass pass_fold_builtins;
  extern struct tree_opt_pass pass_stdarg;
Index: tree-scalar-evolution.c
===================================================================
*** tree-scalar-evolution.c	(revision 117561)
--- tree-scalar-evolution.c	(working copy)
*************** scev_const_prop (void)
*** 3013,3019 ****
  	  {
  	    block_stmt_iterator dest = bsi;
  	    bsi_insert_before (&dest, ass, BSI_NEW_STMT);
! 	    def = force_gimple_operand_bsi (&dest, def, false, NULL_TREE);
  	  }
  	  TREE_OPERAND (ass, 1) = def;
  	  update_stmt (ass);
--- 3013,3020 ----
  	  {
  	    block_stmt_iterator dest = bsi;
  	    bsi_insert_before (&dest, ass, BSI_NEW_STMT);
! 	    def = force_gimple_operand_bsi (&dest, def, false, NULL_TREE,
! 					    true, BSI_SAME_STMT);
  	  }
  	  TREE_OPERAND (ass, 1) = def;
  	  update_stmt (ass);
Index: omp-low.c
===================================================================
*** omp-low.c	(revision 117561)
--- omp-low.c	(working copy)
*************** static tree maybe_lookup_decl_in_outer_c
*** 117,123 ****
  
  /* Find an OpenMP clause of type KIND within CLAUSES.  */
  
! static tree
  find_omp_clause (tree clauses, enum tree_code kind)
  {
    for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
--- 117,123 ----
  
  /* Find an OpenMP clause of type KIND within CLAUSES.  */
  
! tree
  find_omp_clause (tree clauses, enum tree_code kind)
  {
    for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
*************** is_combined_parallel (struct omp_region 
*** 151,157 ****
  static void
  extract_omp_for_data (tree for_stmt, struct omp_for_data *fd)
  {
!   tree t;
  
    fd->for_stmt = for_stmt;
    fd->pre = NULL;
--- 151,157 ----
  static void
  extract_omp_for_data (tree for_stmt, struct omp_for_data *fd)
  {
!   tree t, var;
  
    fd->for_stmt = for_stmt;
    fd->pre = NULL;
*************** extract_omp_for_data (tree for_stmt, str
*** 159,171 ****
    t = OMP_FOR_INIT (for_stmt);
    gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
    fd->v = TREE_OPERAND (t, 0);
!   gcc_assert (DECL_P (fd->v));
    gcc_assert (TREE_CODE (TREE_TYPE (fd->v)) == INTEGER_TYPE);
    fd->n1 = TREE_OPERAND (t, 1);
  
    t = OMP_FOR_COND (for_stmt);
    fd->cond_code = TREE_CODE (t);
!   gcc_assert (TREE_OPERAND (t, 0) == fd->v);
    fd->n2 = TREE_OPERAND (t, 1);
    switch (fd->cond_code)
      {
--- 159,172 ----
    t = OMP_FOR_INIT (for_stmt);
    gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
    fd->v = TREE_OPERAND (t, 0);
!   gcc_assert (SSA_VAR_P (fd->v));
!   var = TREE_CODE (fd->v) == SSA_NAME ? SSA_NAME_VAR (fd->v) : fd->v;
    gcc_assert (TREE_CODE (TREE_TYPE (fd->v)) == INTEGER_TYPE);
    fd->n1 = TREE_OPERAND (t, 1);
  
    t = OMP_FOR_COND (for_stmt);
    fd->cond_code = TREE_CODE (t);
!   gcc_assert (TREE_OPERAND (t, 0) == var);
    fd->n2 = TREE_OPERAND (t, 1);
    switch (fd->cond_code)
      {
*************** extract_omp_for_data (tree for_stmt, str
*** 188,196 ****
  
    t = OMP_FOR_INCR (fd->for_stmt);
    gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
!   gcc_assert (TREE_OPERAND (t, 0) == fd->v);
    t = TREE_OPERAND (t, 1);
!   gcc_assert (TREE_OPERAND (t, 0) == fd->v);
    switch (TREE_CODE (t))
      {
      case PLUS_EXPR:
--- 189,197 ----
  
    t = OMP_FOR_INCR (fd->for_stmt);
    gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
!   gcc_assert (TREE_OPERAND (t, 0) == var);
    t = TREE_OPERAND (t, 1);
!   gcc_assert (TREE_OPERAND (t, 0) == var);
    switch (TREE_CODE (t))
      {
      case PLUS_EXPR:
*************** use_pointer_for_field (tree decl, bool s
*** 505,514 ****
    return false;
  }
  
! /* Construct a new automatic decl similar to VAR.  */
  
! static tree
! omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
  {
    tree copy = build_decl (VAR_DECL, name, type);
  
--- 506,515 ----
    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 (VAR_DECL, name, type);
  
*************** omp_copy_decl_2 (tree var, tree name, tr
*** 516,525 ****
    DECL_COMPLEX_GIMPLE_REG_P (copy) = DECL_COMPLEX_GIMPLE_REG_P (var);
    DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (var);
    DECL_IGNORED_P (copy) = DECL_IGNORED_P (var);
    TREE_USED (copy) = 1;
-   DECL_CONTEXT (copy) = current_function_decl;
    DECL_SEEN_IN_BIND_EXPR_P (copy) = 1;
  
    TREE_CHAIN (copy) = ctx->block_vars;
    ctx->block_vars = copy;
  
--- 517,537 ----
    DECL_COMPLEX_GIMPLE_REG_P (copy) = DECL_COMPLEX_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_USED (copy) = 1;
    DECL_SEEN_IN_BIND_EXPR_P (copy) = 1;
  
+   return copy;
+ }
+ 
+ /* Construct a new automatic decl similar to VAR.  */
+ 
+ static tree
+ omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
+ {
+   tree copy = copy_var_decl (var, name, type);
+ 
+   DECL_CONTEXT (copy) = current_function_decl;
    TREE_CHAIN (copy) = ctx->block_vars;
    ctx->block_vars = copy;
  
*************** scan_omp (tree *stmt_p, omp_context *ctx
*** 1423,1436 ****
  
  /* Build a call to GOMP_barrier.  */
  
! static void
! build_omp_barrier (tree *stmt_list)
  {
    tree t;
  
    t = built_in_decls[BUILT_IN_GOMP_BARRIER];
    t = build_function_call_expr (t, NULL);
!   gimplify_and_add (t, stmt_list);
  }
  
  /* If a context was created for STMT when it was scanned, return it.  */
--- 1435,1448 ----
  
  /* Build a call to GOMP_barrier.  */
  
! static tree
! build_omp_barrier (void)
  {
    tree t;
  
    t = built_in_decls[BUILT_IN_GOMP_BARRIER];
    t = build_function_call_expr (t, NULL);
!   return t;
  }
  
  /* If a context was created for STMT when it was scanned, return it.  */
*************** lower_rec_input_clauses (tree clauses, t
*** 1828,1834 ****
       lastprivate clauses we need to ensure the lastprivate copying
       happens after firstprivate copying in all threads.  */
    if (copyin_by_ref || lastprivate_firstprivate)
!     build_omp_barrier (ilist);
  }
  
  
--- 1840,1846 ----
       lastprivate clauses we need to ensure the lastprivate copying
       happens after firstprivate copying in all threads.  */
    if (copyin_by_ref || lastprivate_firstprivate)
!     gimplify_and_add (build_omp_barrier (), ilist);
  }
  
  
*************** static void
*** 2154,2165 ****
  expand_parallel_call (struct omp_region *region, basic_block bb,
  		      tree entry_stmt, tree ws_args)
  {
!   tree t, args, val, cond, c, list, clauses;
    block_stmt_iterator si;
    int start_ix;
  
    clauses = OMP_PARALLEL_CLAUSES (entry_stmt);
-   push_gimplify_context ();
  
    /* Determine what flavor of GOMP_parallel_start we will be
       emitting.  */
--- 2166,2176 ----
  expand_parallel_call (struct omp_region *region, basic_block bb,
  		      tree entry_stmt, tree ws_args)
  {
!   tree t, args, val, cond, c, clauses;
    block_stmt_iterator si;
    int start_ix;
  
    clauses = OMP_PARALLEL_CLAUSES (entry_stmt);
  
    /* Determine what flavor of GOMP_parallel_start we will be
       emitting.  */
*************** expand_parallel_call (struct omp_region 
*** 2205,2219 ****
        cond = gimple_boolify (cond);
  
        if (integer_zerop (val))
! 	val = build2 (EQ_EXPR, unsigned_type_node, cond,
! 		      build_int_cst (TREE_TYPE (cond), 0));
        else
  	{
  	  basic_block cond_bb, then_bb, else_bb;
! 	  edge e;
! 	  tree t, then_lab, else_lab, tmp;
  
- 	  tmp = create_tmp_var (TREE_TYPE (val), NULL);
  	  e = split_block (bb, NULL);
  	  cond_bb = e->src;
  	  bb = e->dest;
--- 2216,2243 ----
        cond = gimple_boolify (cond);
  
        if (integer_zerop (val))
! 	val = fold_build2 (EQ_EXPR, unsigned_type_node, cond,
! 			   build_int_cst (TREE_TYPE (cond), 0));
        else
  	{
  	  basic_block cond_bb, then_bb, else_bb;
! 	  edge e, e_then, e_else;
! 	  tree t, then_lab, else_lab, tmp_then, tmp_else, tmp_join, tmp_var;
! 
! 	  tmp_var = create_tmp_var (TREE_TYPE (val), NULL);
! 	  if (in_ssa_p)
! 	    {
! 	      tmp_then = make_ssa_name (tmp_var, NULL_TREE);
! 	      tmp_else = make_ssa_name (tmp_var, NULL_TREE);
! 	      tmp_join = make_ssa_name (tmp_var, NULL_TREE);
! 	    }
! 	  else
! 	    {
! 	      tmp_then = tmp_var;
! 	      tmp_else = tmp_var;
! 	      tmp_join = tmp_var;
! 	    }
  
  	  e = split_block (bb, NULL);
  	  cond_bb = e->src;
  	  bb = e->dest;
*************** expand_parallel_call (struct omp_region 
*** 2237,2267 ****
  	  si = bsi_start (then_bb);
  	  t = build1 (LABEL_EXPR, void_type_node, then_lab);
  	  bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
! 	  t = build2 (MODIFY_EXPR, void_type_node, tmp, val);
  	  bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
  
  	  si = bsi_start (else_bb);
  	  t = build1 (LABEL_EXPR, void_type_node, else_lab);
  	  bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
! 	  t = build2 (MODIFY_EXPR, void_type_node, tmp, 
  	              build_int_cst (unsigned_type_node, 1));
  	  bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
  
  	  make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
  	  make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
! 	  make_edge (then_bb, bb, EDGE_FALLTHRU);
! 	  make_edge (else_bb, bb, EDGE_FALLTHRU);
  
! 	  val = tmp;
  	}
  
-       list = NULL_TREE;
-       val = get_formal_tmp_var (val, &list);
        si = bsi_start (bb);
!       bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
      }
  
!   list = NULL_TREE;
    args = tree_cons (NULL, val, NULL);
    t = OMP_PARALLEL_DATA_ARG (entry_stmt);
    if (t == NULL)
--- 2261,2303 ----
  	  si = bsi_start (then_bb);
  	  t = build1 (LABEL_EXPR, void_type_node, then_lab);
  	  bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
! 	  t = build2 (MODIFY_EXPR, void_type_node, tmp_then, val);
  	  bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
+ 	  if (in_ssa_p)
+ 	    SSA_NAME_DEF_STMT (tmp_then) = t;
  
  	  si = bsi_start (else_bb);
  	  t = build1 (LABEL_EXPR, void_type_node, else_lab);
  	  bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
! 	  t = build2 (MODIFY_EXPR, void_type_node, tmp_else, 
  	              build_int_cst (unsigned_type_node, 1));
  	  bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
+ 	  if (in_ssa_p)
+ 	    SSA_NAME_DEF_STMT (tmp_else) = t;
  
  	  make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
  	  make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
! 	  e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
! 	  e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
! 
! 	  if (in_ssa_p)
! 	    {
! 	      tree phi = create_phi_node (tmp_join, bb);
! 	      SSA_NAME_DEF_STMT (tmp_join) = phi;
! 	      add_phi_arg (phi, tmp_then, e_then);
! 	      add_phi_arg (phi, tmp_else, e_else);
! 	    }
  
! 	  val = tmp_join;
  	}
  
        si = bsi_start (bb);
!       val = force_gimple_operand_bsi (&si, val, true, NULL_TREE,
! 				      false, BSI_CONTINUE_LINKING);
      }
  
!   si = bsi_last (bb);
! 
    args = tree_cons (NULL, val, NULL);
    t = OMP_PARALLEL_DATA_ARG (entry_stmt);
    if (t == NULL)
*************** expand_parallel_call (struct omp_region 
*** 2277,2301 ****
  
    t = built_in_decls[start_ix];
    t = build_function_call_expr (t, args);
!   gimplify_and_add (t, &list);
  
    t = OMP_PARALLEL_DATA_ARG (entry_stmt);
    if (t == NULL)
      t = null_pointer_node;
    else
      t = build_fold_addr_expr (t);
    args = tree_cons (NULL, t, NULL);
    t = build_function_call_expr (OMP_PARALLEL_FN (entry_stmt), args);
!   gimplify_and_add (t, &list);
  
    t = built_in_decls[BUILT_IN_GOMP_PARALLEL_END];
    t = build_function_call_expr (t, NULL);
!   gimplify_and_add (t, &list);
! 
!   si = bsi_last (bb);
!   bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
! 
!   pop_gimplify_context (NULL_TREE);
  }
  
  
--- 2313,2336 ----
  
    t = built_in_decls[start_ix];
    t = build_function_call_expr (t, args);
!   force_gimple_operand_bsi (&si, t, true, NULL_TREE,
! 			    false, BSI_CONTINUE_LINKING);
  
    t = OMP_PARALLEL_DATA_ARG (entry_stmt);
    if (t == NULL)
      t = null_pointer_node;
    else
      t = build_fold_addr_expr (t);
+ 
    args = tree_cons (NULL, t, NULL);
    t = build_function_call_expr (OMP_PARALLEL_FN (entry_stmt), args);
!   force_gimple_operand_bsi (&si, t, true, NULL_TREE,
! 			    false, BSI_CONTINUE_LINKING);
  
    t = built_in_decls[BUILT_IN_GOMP_PARALLEL_END];
    t = build_function_call_expr (t, NULL);
!   force_gimple_operand_bsi (&si, t, true, NULL_TREE,
! 			    false, BSI_CONTINUE_LINKING);
  }
  
  
*************** expand_omp_parallel (struct omp_region *
*** 2474,2479 ****
--- 2509,2515 ----
  	{
  	  basic_block entry_succ_bb = single_succ (entry_bb);
  	  block_stmt_iterator si;
+ 	  tree parcopy_stmt = NULL_TREE, arg, narg;
  
  	  for (si = bsi_start (entry_succ_bb); ; bsi_next (&si))
  	    {
*************** expand_omp_parallel (struct omp_region *
*** 2490,2502 ****
  		  && TREE_OPERAND (arg, 0)
  		     == OMP_PARALLEL_DATA_ARG (entry_stmt))
  		{
! 		  if (TREE_OPERAND (stmt, 0) == DECL_ARGUMENTS (child_fn))
! 		    bsi_remove (&si, true);
! 		  else
! 		    TREE_OPERAND (stmt, 1) = DECL_ARGUMENTS (child_fn);
  		  break;
  		}
  	    }
  	}
  
        /* Declare local variables needed in CHILD_CFUN.  */
--- 2526,2557 ----
  		  && TREE_OPERAND (arg, 0)
  		     == OMP_PARALLEL_DATA_ARG (entry_stmt))
  		{
! 		  parcopy_stmt = stmt;
  		  break;
  		}
  	    }
+ 
+ 	  gcc_assert (parcopy_stmt != NULL_TREE);
+ 	  arg = DECL_ARGUMENTS (child_fn);
+ 
+ 	  if (!in_ssa_p)
+ 	    {
+ 	      if (TREE_OPERAND (parcopy_stmt, 0) == arg)
+ 		bsi_remove (&si, true);
+ 	      else
+ 		TREE_OPERAND (parcopy_stmt, 1) = arg;
+ 	    }
+ 	  else
+ 	    {
+ 	      /* If we are in ssa form, we must load the value from the default
+ 		 definition of the argument.  That should not be defined now,
+ 		 since the argument is not used uninitialized.  */
+ 	      gcc_assert (default_def (arg) == NULL);
+ 	      narg = make_ssa_name (arg, build_empty_stmt ());
+ 	      set_default_def (arg, narg);
+ 	      TREE_OPERAND (parcopy_stmt, 1) = narg;
+ 	      update_stmt (parcopy_stmt);
+ 	    }
  	}
  
        /* Declare local variables needed in CHILD_CFUN.  */
*************** expand_omp_parallel (struct omp_region *
*** 2504,2513 ****
        BLOCK_VARS (block) = list2chain (child_cfun->unexpanded_var_list);
        DECL_SAVED_TREE (child_fn) = single_succ (entry_bb)->stmt_list;
  
!       /* Reset DECL_CONTEXT on locals and function arguments.  */
!       for (t = BLOCK_VARS (block); t; t = TREE_CHAIN (t))
! 	DECL_CONTEXT (t) = child_fn;
! 
        for (t = DECL_ARGUMENTS (child_fn); t; t = TREE_CHAIN (t))
  	DECL_CONTEXT (t) = child_fn;
  
--- 2559,2565 ----
        BLOCK_VARS (block) = list2chain (child_cfun->unexpanded_var_list);
        DECL_SAVED_TREE (child_fn) = single_succ (entry_bb)->stmt_list;
  
!       /* Reset DECL_CONTEXT on function arguments.  */
        for (t = DECL_ARGUMENTS (child_fn); t; t = TREE_CHAIN (t))
  	DECL_CONTEXT (t) = child_fn;
  
*************** expand_omp_parallel (struct omp_region *
*** 2521,2532 ****
        entry_bb = e->dest;
        single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
  
-       /* Move the parallel region into CHILD_CFUN.  */
-       new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb);
-       if (exit_bb)
- 	single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
-       cgraph_add_new_function (child_fn);
- 
        /* Convert OMP_RETURN into a RETURN_EXPR.  */
        if (exit_bb)
  	{
--- 2573,2578 ----
*************** expand_omp_parallel (struct omp_region *
*** 2537,2548 ****
  	  bsi_insert_after (&si, t, TSI_SAME_STMT);
  	  bsi_remove (&si, true);
  	}
      }
  
    /* Emit a library call to launch the children threads.  */
    expand_parallel_call (region, new_bb, entry_stmt, ws_args);
- }
  
  
  /* A subroutine of expand_omp_for.  Generate code for a parallel
     loop with any schedule.  Given parameters:
--- 2583,2607 ----
  	  bsi_insert_after (&si, t, TSI_SAME_STMT);
  	  bsi_remove (&si, true);
  	}
+ 
+       /* Move the parallel region into CHILD_CFUN.  */
+       new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb);
+       if (exit_bb)
+ 	single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
+ 
+       /* Rewrite the child function out of ssa, and inform the callgraph about
+ 	 the new function.  */
+       if (in_ssa_p)
+ 	go_out_of_ssa (child_fn);
+       cgraph_add_new_function (child_fn);
      }
  
    /* Emit a library call to launch the children threads.  */
    expand_parallel_call (region, new_bb, entry_stmt, ws_args);
  
+   /* Fix up the ssa form.  */
+   update_ssa (TODO_update_ssa_only_virtuals);
+ }
  
  /* A subroutine of expand_omp_for.  Generate code for a parallel
     loop with any schedule.  Given parameters:
*************** expand_omp_parallel (struct omp_region *
*** 2565,2571 ****
      L3:
  
      If this is a combined omp parallel loop, instead of the call to
!     GOMP_loop_foo_start, we emit 'goto L3'.  */
  
  static void
  expand_omp_for_generic (struct omp_region *region,
--- 2624,2630 ----
      L3:
  
      If this is a combined omp parallel loop, instead of the call to
!     GOMP_loop_foo_start, we emit 'goto L2'.  */
  
  static void
  expand_omp_for_generic (struct omp_region *region,
*************** expand_omp_for_generic (struct omp_regio
*** 2575,2582 ****
  {
    tree l0, l1, l2, l3;
    tree type, istart0, iend0, iend;
!   tree t, args, list;
!   basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l3_bb;
    block_stmt_iterator si;
    bool in_combined_parallel = is_combined_parallel (region);
  
--- 2634,2641 ----
  {
    tree l0, l1, l2, l3;
    tree type, istart0, iend0, iend;
!   tree t, args, vmain, vback;
!   basic_block entry_bb, cont_bb, l0_bb, l1_bb, l2_bb, l3_bb, exit_bb;
    block_stmt_iterator si;
    bool in_combined_parallel = is_combined_parallel (region);
  
*************** expand_omp_for_generic (struct omp_regio
*** 2584,2599 ****
  
    istart0 = create_tmp_var (long_integer_type_node, ".istart0");
    iend0 = create_tmp_var (long_integer_type_node, ".iend0");
-   iend = create_tmp_var (type, NULL);
    TREE_ADDRESSABLE (istart0) = 1;
    TREE_ADDRESSABLE (iend0) = 1;
  
    entry_bb = region->entry;
-   l0_bb = create_empty_bb (entry_bb);
-   l1_bb = single_succ (entry_bb);
    cont_bb = region->cont;
    l2_bb = create_empty_bb (cont_bb);
!   l3_bb = single_succ (cont_bb);
    exit_bb = region->exit;
  
    l0 = tree_block_label (l0_bb);
--- 2643,2668 ----
  
    istart0 = create_tmp_var (long_integer_type_node, ".istart0");
    iend0 = create_tmp_var (long_integer_type_node, ".iend0");
    TREE_ADDRESSABLE (istart0) = 1;
    TREE_ADDRESSABLE (iend0) = 1;
+   if (in_ssa_p)
+     {
+       add_referenced_var (istart0);
+       add_referenced_var (iend0);
+       mark_call_clobbered (istart0, ESCAPE_TO_CALL);
+       mark_call_clobbered (iend0, ESCAPE_TO_CALL);
+     }
  
    entry_bb = region->entry;
    cont_bb = region->cont;
+   gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
+   gcc_assert (BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
+   l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
+   l1_bb = single_succ (l0_bb);
    l2_bb = create_empty_bb (cont_bb);
!   gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb);
!   gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
!   l3_bb = FALLTHRU_EDGE (cont_bb)->dest;
    exit_bb = region->exit;
  
    l0 = tree_block_label (l0_bb);
*************** expand_omp_for_generic (struct omp_regio
*** 2607,2613 ****
      {
        /* If this is not a combined parallel loop, emit a call to
  	 GOMP_loop_foo_start in ENTRY_BB.  */
!       list = alloc_stmt_list ();
        t = build_fold_addr_expr (iend0);
        args = tree_cons (NULL, t, NULL);
        t = build_fold_addr_expr (istart0);
--- 2676,2682 ----
      {
        /* If this is not a combined parallel loop, emit a call to
  	 GOMP_loop_foo_start in ENTRY_BB.  */
! 
        t = build_fold_addr_expr (iend0);
        args = tree_cons (NULL, t, NULL);
        t = build_fold_addr_expr (istart0);
*************** expand_omp_for_generic (struct omp_regio
*** 2624,2686 ****
        t = fold_convert (long_integer_type_node, fd->n1);
        args = tree_cons (NULL, t, args);
        t = build_function_call_expr (built_in_decls[start_fn], args);
!       t = get_formal_tmp_var (t, &list);
        t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l0),
  		  build_and_jump (&l3));
!       append_to_statement_list (t, &list);
!       bsi_insert_after (&si, list, BSI_SAME_STMT);
      }
    bsi_remove (&si, true);
  
    /* Iteration setup for sequential loop goes in L0_BB.  */
!   list = alloc_stmt_list ();
    t = fold_convert (type, istart0);
    t = build2 (MODIFY_EXPR, void_type_node, fd->v, t);
!   gimplify_and_add (t, &list);
  
    t = fold_convert (type, iend0);
!   t = build2 (MODIFY_EXPR, void_type_node, iend, t);
!   gimplify_and_add (t, &list);
! 
!   si = bsi_start (l0_bb);
!   bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
  
    /* Code to control the increment and predicate for the sequential
       loop goes in the first half of EXIT_BB (we split EXIT_BB so
       that we can inherit all the edges going out of the loop
       body).  */
!   list = alloc_stmt_list ();
  
!   t = build2 (PLUS_EXPR, type, fd->v, fd->step);
!   t = build2 (MODIFY_EXPR, void_type_node, fd->v, t);
!   gimplify_and_add (t, &list);
!   
!   t = build2 (fd->cond_code, boolean_type_node, fd->v, iend);
!   t = get_formal_tmp_var (t, &list);
    t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l1),
  	      build_and_jump (&l2));
!   append_to_statement_list (t, &list);
  
!   si = bsi_last (cont_bb);
!   bsi_insert_after (&si, list, BSI_SAME_STMT);
!   gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_CONTINUE);
    bsi_remove (&si, true);
  
    /* Emit code to get the next parallel iteration in L2_BB.  */
!   list = alloc_stmt_list ();
! 
    t = build_fold_addr_expr (iend0);
    args = tree_cons (NULL, t, NULL);
    t = build_fold_addr_expr (istart0);
    args = tree_cons (NULL, t, args);
    t = build_function_call_expr (built_in_decls[next_fn], args);
!   t = get_formal_tmp_var (t, &list);
    t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l0),
  	      build_and_jump (&l3));
!   append_to_statement_list (t, &list);
!   
!   si = bsi_start (l2_bb);
!   bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
  
    /* Add the loop cleanup function.  */
    si = bsi_last (exit_bb);
--- 2693,2762 ----
        t = fold_convert (long_integer_type_node, fd->n1);
        args = tree_cons (NULL, t, args);
        t = build_function_call_expr (built_in_decls[start_fn], args);
!       t = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
! 				    true, BSI_SAME_STMT);
! 
        t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l0),
  		  build_and_jump (&l3));
!       bsi_insert_after (&si, t, BSI_SAME_STMT);
      }
    bsi_remove (&si, true);
  
    /* Iteration setup for sequential loop goes in L0_BB.  */
!   si = bsi_start (l0_bb);
    t = fold_convert (type, istart0);
+   t = force_gimple_operand_bsi (&si, t, false, NULL_TREE,
+ 				false, BSI_CONTINUE_LINKING);
    t = build2 (MODIFY_EXPR, void_type_node, fd->v, t);
!   bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
!   if (in_ssa_p)
!     {
!       SSA_NAME_DEF_STMT (fd->v) = t;
!       mark_new_vars_to_rename (t);
!     }
  
    t = fold_convert (type, iend0);
!   iend = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
! 				   false, BSI_CONTINUE_LINKING);
  
    /* Code to control the increment and predicate for the sequential
       loop goes in the first half of EXIT_BB (we split EXIT_BB so
       that we can inherit all the edges going out of the loop
       body).  */
!   si = bsi_last (cont_bb);
!   t = bsi_stmt (si);
!   gcc_assert (TREE_CODE (t) == OMP_CONTINUE);
!   vmain = TREE_OPERAND (t, 1);
!   vback = TREE_OPERAND (t, 0);
! 
!   t = fold_build2 (PLUS_EXPR, type, vmain, fd->step);
!   t = force_gimple_operand_bsi (&si, t, false, NULL_TREE,
! 				true, BSI_SAME_STMT);
!   t = build2 (MODIFY_EXPR, void_type_node, vback, t);
!   bsi_insert_before (&si, t, BSI_SAME_STMT);
!   if (in_ssa_p)
!     SSA_NAME_DEF_STMT (vback) = t;
  
!   t = build2 (fd->cond_code, boolean_type_node, vback, iend);
    t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l1),
  	      build_and_jump (&l2));
!   bsi_insert_before (&si, t, BSI_SAME_STMT);
  
!   /* Remove OMP_CONTINUE.  */
    bsi_remove (&si, true);
  
    /* Emit code to get the next parallel iteration in L2_BB.  */
!   si = bsi_start (l2_bb);
    t = build_fold_addr_expr (iend0);
    args = tree_cons (NULL, t, NULL);
    t = build_fold_addr_expr (istart0);
    args = tree_cons (NULL, t, args);
    t = build_function_call_expr (built_in_decls[next_fn], args);
!   t = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
! 				false, BSI_CONTINUE_LINKING);
    t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l0),
  	      build_and_jump (&l3));
!   bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
  
    /* Add the loop cleanup function.  */
    si = bsi_last (exit_bb);
*************** expand_omp_for_generic (struct omp_regio
*** 2690,2711 ****
      t = built_in_decls[BUILT_IN_GOMP_LOOP_END];
    t = build_function_call_expr (t, NULL);
    bsi_insert_after (&si, t, BSI_SAME_STMT);
    bsi_remove (&si, true);
  
    /* Connect the new blocks.  */
-   remove_edge (single_succ_edge (entry_bb));
    if (in_combined_parallel)
!     make_edge (entry_bb, l2_bb, EDGE_FALLTHRU);
    else
      {
!       make_edge (entry_bb, l0_bb, EDGE_TRUE_VALUE);
!       make_edge (entry_bb, l3_bb, EDGE_FALSE_VALUE);
      }
  
!   make_edge (l0_bb, l1_bb, EDGE_FALLTHRU);
! 
!   remove_edge (single_succ_edge (cont_bb));
!   make_edge (cont_bb, l1_bb, EDGE_TRUE_VALUE);
    make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
  
    make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
--- 2766,2789 ----
      t = built_in_decls[BUILT_IN_GOMP_LOOP_END];
    t = build_function_call_expr (t, NULL);
    bsi_insert_after (&si, t, BSI_SAME_STMT);
+   if (in_ssa_p)
+     mark_new_vars_to_rename (t);
    bsi_remove (&si, true);
  
    /* Connect the new blocks.  */
    if (in_combined_parallel)
!     {
!       remove_edge (BRANCH_EDGE (entry_bb));
!       redirect_edge_and_branch (single_succ_edge (entry_bb), l2_bb);
!     }
    else
      {
!       find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
!       find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
      }
  
!   find_edge (cont_bb, l1_bb)->flags = EDGE_TRUE_VALUE;
!   remove_edge (find_edge (cont_bb, l3_bb));
    make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
  
    make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
*************** expand_omp_for_generic (struct omp_regio
*** 2719,2724 ****
--- 2797,2813 ----
  			   recount_dominator (CDI_DOMINATORS, l0_bb));
    set_immediate_dominator (CDI_DOMINATORS, l1_bb,
  			   recount_dominator (CDI_DOMINATORS, l1_bb));
+ 
+   /* FIXME: We marked ISTART0 and IEND0 as call clobbered.  The problem
+      is that this causes them to appear appear on each call, making it
+      impossible to get virtual ssa form correct for them without calling
+      mark_new_vars_to_rename for each call in the function.  This is annoying
+      and potentially slow.  Also, in case OMP_PARALLEL is in this function
+      around the OMP_FOR construct, the references to ISTART0 and IEND0
+      will remain in the virtual operands even after the body of the
+      OMP_PARALLEL construct is split into new function.  This does not
+      seem to cause any problem at the moment, but it looks dangerous.  */
+   mark_call_virtual_operands ();
  }
  
  
*************** expand_omp_for_generic (struct omp_regio
*** 2739,2747 ****
  	q += (q * nthreads != n);
  	s0 = q * threadid;
  	e0 = min(s0 + q, n);
  	if (s0 >= e0) goto L2; else goto L0;
      L0:
- 	V = s0 * STEP + N1;
  	e = e0 * STEP + N1;
      L1:
  	BODY;
--- 2828,2836 ----
  	q += (q * nthreads != n);
  	s0 = q * threadid;
  	e0 = min(s0 + q, n);
+ 	V = s0 * STEP + N1;
  	if (s0 >= e0) goto L2; else goto L0;
      L0:
  	e = e0 * STEP + N1;
      L1:
  	BODY;
*************** expand_omp_for_static_nochunk (struct om
*** 2755,2773 ****
  			       struct omp_for_data *fd)
  {
    tree l0, l1, l2, n, q, s0, e0, e, t, nthreads, threadid;
!   tree type, utype, list;
!   basic_block entry_bb, exit_bb, seq_start_bb, body_bb, cont_bb;
    basic_block fin_bb;
    block_stmt_iterator si;
  
    type = TREE_TYPE (fd->v);
    utype = lang_hooks.types.unsigned_type (type);
  
    entry_bb = region->entry;
-   seq_start_bb = create_empty_bb (entry_bb);
-   body_bb = single_succ (entry_bb);
    cont_bb = region->cont;
!   fin_bb = single_succ (cont_bb);
    exit_bb = region->exit;
  
    l0 = tree_block_label (seq_start_bb);
--- 2844,2867 ----
  			       struct omp_for_data *fd)
  {
    tree l0, l1, l2, n, q, s0, e0, e, t, nthreads, threadid;
!   tree type, utype;
!   basic_block entry_bb, seq_start_bb, body_bb, cont_bb, exit_bb;
    basic_block fin_bb;
    block_stmt_iterator si;
+   tree vmain, vback;
  
    type = TREE_TYPE (fd->v);
    utype = lang_hooks.types.unsigned_type (type);
  
    entry_bb = region->entry;
    cont_bb = region->cont;
!   gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
!   gcc_assert (BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
!   seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
!   body_bb = single_succ (seq_start_bb);
!   gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
!   gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
!   fin_bb = FALLTHRU_EDGE (cont_bb)->dest;
    exit_bb = region->exit;
  
    l0 = tree_block_label (seq_start_bb);
*************** expand_omp_for_static_nochunk (struct om
*** 2775,2803 ****
    l2 = tree_block_label (fin_bb);
  
    /* Iteration space partitioning goes in ENTRY_BB.  */
!   list = alloc_stmt_list ();
  
    t = built_in_decls[BUILT_IN_OMP_GET_NUM_THREADS];
    t = build_function_call_expr (t, NULL);
    t = fold_convert (utype, t);
!   nthreads = get_formal_tmp_var (t, &list);
    
    t = built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM];
    t = build_function_call_expr (t, NULL);
    t = fold_convert (utype, t);
!   threadid = get_formal_tmp_var (t, &list);
  
!   fd->n1 = fold_convert (type, fd->n1);
!   if (!is_gimple_val (fd->n1))
!     fd->n1 = get_formal_tmp_var (fd->n1, &list);
! 
!   fd->n2 = fold_convert (type, fd->n2);
!   if (!is_gimple_val (fd->n2))
!     fd->n2 = get_formal_tmp_var (fd->n2, &list);
! 
!   fd->step = fold_convert (type, fd->step);
!   if (!is_gimple_val (fd->step))
!     fd->step = get_formal_tmp_var (fd->step, &list);
  
    t = build_int_cst (type, (fd->cond_code == LT_EXPR ? -1 : 1));
    t = fold_build2 (PLUS_EXPR, type, fd->step, t);
--- 2869,2903 ----
    l2 = tree_block_label (fin_bb);
  
    /* Iteration space partitioning goes in ENTRY_BB.  */
!   si = bsi_last (entry_bb);
!   gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_FOR);
  
    t = built_in_decls[BUILT_IN_OMP_GET_NUM_THREADS];
    t = build_function_call_expr (t, NULL);
    t = fold_convert (utype, t);
!   nthreads = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
! 				       true, BSI_SAME_STMT);
    
    t = built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM];
    t = build_function_call_expr (t, NULL);
    t = fold_convert (utype, t);
!   threadid = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
! 				       true, BSI_SAME_STMT);
  
!   fd->n1 = force_gimple_operand_bsi (&si,
! 				     fold_convert (type, fd->n1),
! 				     true, NULL_TREE,
! 				     true, BSI_SAME_STMT);
! 
!   fd->n2 = force_gimple_operand_bsi (&si,
! 				    fold_convert (type, fd->n2),
! 				    true, NULL_TREE,
! 				    true, BSI_SAME_STMT);
! 
!   fd->step = force_gimple_operand_bsi (&si,
! 				       fold_convert (type, fd->step),
! 				       true, NULL_TREE,
! 				       true, BSI_SAME_STMT);
  
    t = build_int_cst (type, (fd->cond_code == LT_EXPR ? -1 : 1));
    t = fold_build2 (PLUS_EXPR, type, fd->step, t);
*************** expand_omp_for_static_nochunk (struct om
*** 2805,2893 ****
    t = fold_build2 (MINUS_EXPR, type, t, fd->n1);
    t = fold_build2 (TRUNC_DIV_EXPR, type, t, fd->step);
    t = fold_convert (utype, t);
!   if (is_gimple_val (t))
!     n = t;
!   else
!     n = get_formal_tmp_var (t, &list);
  
!   t = build2 (TRUNC_DIV_EXPR, utype, n, nthreads);
!   q = get_formal_tmp_var (t, &list);
  
!   t = build2 (MULT_EXPR, utype, q, nthreads);
!   t = build2 (NE_EXPR, utype, t, n);
!   t = build2 (PLUS_EXPR, utype, q, t);
!   q = get_formal_tmp_var (t, &list);
  
    t = build2 (MULT_EXPR, utype, q, threadid);
!   s0 = get_formal_tmp_var (t, &list);
  
!   t = build2 (PLUS_EXPR, utype, s0, q);
!   t = build2 (MIN_EXPR, utype, t, n);
!   e0 = get_formal_tmp_var (t, &list);
  
    t = build2 (GE_EXPR, boolean_type_node, s0, e0);
    t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l2),
  	      build_and_jump (&l0));
!   append_to_statement_list (t, &list);
  
!   si = bsi_last (entry_bb);
!   gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_FOR);
!   bsi_insert_after (&si, list, BSI_SAME_STMT);
    bsi_remove (&si, true);
  
    /* Setup code for sequential iteration goes in SEQ_START_BB.  */
!   list = alloc_stmt_list ();
! 
!   t = fold_convert (type, s0);
!   t = build2 (MULT_EXPR, type, t, fd->step);
!   t = build2 (PLUS_EXPR, type, t, fd->n1);
!   t = build2 (MODIFY_EXPR, void_type_node, fd->v, t);
!   gimplify_and_add (t, &list);
  
    t = fold_convert (type, e0);
!   t = build2 (MULT_EXPR, type, t, fd->step);
!   t = build2 (PLUS_EXPR, type, t, fd->n1);
!   e = get_formal_tmp_var (t, &list);
! 
!   si = bsi_start (seq_start_bb);
!   bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
  
    /* The code controlling the sequential loop replaces the OMP_CONTINUE.  */
!   list = alloc_stmt_list ();
! 
!   t = build2 (PLUS_EXPR, type, fd->v, fd->step);
!   t = build2 (MODIFY_EXPR, void_type_node, fd->v, t);
!   gimplify_and_add (t, &list);
  
!   t = build2 (fd->cond_code, boolean_type_node, fd->v, e);
!   t = get_formal_tmp_var (t, &list);
    t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l1),
  	      build_and_jump (&l2));
!   append_to_statement_list (t, &list);
  
!   si = bsi_last (cont_bb);
!   gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_CONTINUE);
!   bsi_insert_after (&si, list, BSI_SAME_STMT);
    bsi_remove (&si, true);
  
    /* Replace the OMP_RETURN with a barrier, or nothing.  */
    si = bsi_last (exit_bb);
    if (!OMP_RETURN_NOWAIT (bsi_stmt (si)))
!     {
!       list = alloc_stmt_list ();
!       build_omp_barrier (&list);
!       bsi_insert_after (&si, list, BSI_SAME_STMT);
!     }
    bsi_remove (&si, true);
  
    /* Connect all the blocks.  */
!   make_edge (seq_start_bb, body_bb, EDGE_FALLTHRU);
! 
!   remove_edge (single_succ_edge (entry_bb));
!   make_edge (entry_bb, fin_bb, EDGE_TRUE_VALUE);
!   make_edge (entry_bb, seq_start_bb, EDGE_FALSE_VALUE);
  
!   make_edge (cont_bb, body_bb, EDGE_TRUE_VALUE);
    find_edge (cont_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
  
    set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, entry_bb);
--- 2905,2989 ----
    t = fold_build2 (MINUS_EXPR, type, t, fd->n1);
    t = fold_build2 (TRUNC_DIV_EXPR, type, t, fd->step);
    t = fold_convert (utype, t);
!   n = force_gimple_operand_bsi (&si, t, true, NULL_TREE, true, BSI_SAME_STMT);
  
!   t = fold_build2 (TRUNC_DIV_EXPR, utype, n, nthreads);
!   q = force_gimple_operand_bsi (&si, t, true, NULL_TREE, true, BSI_SAME_STMT);
  
!   t = fold_build2 (MULT_EXPR, utype, q, nthreads);
!   t = fold_build2 (NE_EXPR, utype, t, n);
!   t = fold_build2 (PLUS_EXPR, utype, q, t);
!   q = force_gimple_operand_bsi (&si, t, true, NULL_TREE, true, BSI_SAME_STMT);
  
    t = build2 (MULT_EXPR, utype, q, threadid);
!   s0 = force_gimple_operand_bsi (&si, t, true, NULL_TREE, true, BSI_SAME_STMT);
! 
!   t = fold_build2 (PLUS_EXPR, utype, s0, q);
!   t = fold_build2 (MIN_EXPR, utype, t, n);
!   e0 = force_gimple_operand_bsi (&si, t, true, NULL_TREE, true, BSI_SAME_STMT);
  
!   t = fold_convert (type, s0);
!   t = fold_build2 (MULT_EXPR, type, t, fd->step);
!   t = fold_build2 (PLUS_EXPR, type, t, fd->n1);
!   t = force_gimple_operand_bsi (&si, t, false, NULL_TREE,
! 				true, BSI_SAME_STMT);
!   t = build2 (MODIFY_EXPR, void_type_node, fd->v, t);
!   bsi_insert_before (&si, t, BSI_SAME_STMT);
!   if (in_ssa_p)
!     SSA_NAME_DEF_STMT (fd->v) = t;
  
    t = build2 (GE_EXPR, boolean_type_node, s0, e0);
    t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l2),
  	      build_and_jump (&l0));
!   bsi_insert_before (&si, t, BSI_SAME_STMT);
  
!   /* Remove the OMP_FOR statement.  */
    bsi_remove (&si, true);
  
    /* Setup code for sequential iteration goes in SEQ_START_BB.  */
!   si = bsi_start (seq_start_bb);
  
    t = fold_convert (type, e0);
!   t = fold_build2 (MULT_EXPR, type, t, fd->step);
!   t = fold_build2 (PLUS_EXPR, type, t, fd->n1);
!   e = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
! 				false, BSI_CONTINUE_LINKING);
  
    /* The code controlling the sequential loop replaces the OMP_CONTINUE.  */
!   si = bsi_last (cont_bb);
!   t = bsi_stmt (si);
!   gcc_assert (TREE_CODE (t) == OMP_CONTINUE);
!   vmain = TREE_OPERAND (t, 1);
!   vback = TREE_OPERAND (t, 0);
! 
!   t = fold_build2 (PLUS_EXPR, type, vmain, fd->step);
!   t = force_gimple_operand_bsi (&si, t, false, NULL_TREE,
! 				true, BSI_SAME_STMT);
!   t = build2 (MODIFY_EXPR, void_type_node, vback, t);
!   bsi_insert_before (&si, t, BSI_SAME_STMT);
!   if (in_ssa_p)
!     SSA_NAME_DEF_STMT (vback) = t;
  
!   t = build2 (fd->cond_code, boolean_type_node, vback, e);
    t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&l1),
  	      build_and_jump (&l2));
!   bsi_insert_before (&si, t, BSI_SAME_STMT);
  
!   /* Remove the OMP_CONTINUE statement.  */
    bsi_remove (&si, true);
  
    /* Replace the OMP_RETURN with a barrier, or nothing.  */
    si = bsi_last (exit_bb);
    if (!OMP_RETURN_NOWAIT (bsi_stmt (si)))
!     force_gimple_operand_bsi (&si, build_omp_barrier (), false, NULL_TREE,
! 			      false, BSI_SAME_STMT);
    bsi_remove (&si, true);
  
    /* Connect all the blocks.  */
!   find_edge (entry_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
!   find_edge (entry_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
  
!   find_edge (cont_bb, body_bb)->flags = EDGE_TRUE_VALUE;
    find_edge (cont_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
  
    set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, entry_bb);
*************** expand_omp_for_static_nochunk (struct om
*** 2912,2917 ****
--- 3008,3016 ----
  	  adj = STEP + 1;
  	n = (adj + N2 - N1) / STEP;
  	trip = 0;
+ 	V = threadid * CHUNK * STEP + N1;  -- this extra definition of V is
+ 					      here so that V is defined
+ 					      if the loop is not entered
      L0:
  	s0 = (trip * nthreads + threadid) * CHUNK;
  	e0 = min(s0 + CHUNK, n);
*************** expand_omp_for_static_nochunk (struct om
*** 2932,2957 ****
  static void
  expand_omp_for_static_chunk (struct omp_region *region, struct omp_for_data *fd)
  {
!   tree l0, l1, l2, l3, l4, n, s0, e0, e, t;
!   tree trip, nthreads, threadid;
!   tree type, utype;
!   basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
!   basic_block trip_update_bb, cont_bb, fin_bb;
!   tree list;
    block_stmt_iterator si;
  
    type = TREE_TYPE (fd->v);
    utype = lang_hooks.types.unsigned_type (type);
  
    entry_bb = region->entry;
!   iter_part_bb = create_empty_bb (entry_bb);
!   seq_start_bb = create_empty_bb (iter_part_bb);
!   body_bb = single_succ (entry_bb);
    cont_bb = region->cont;
!   trip_update_bb = create_empty_bb (cont_bb);
!   fin_bb = single_succ (cont_bb);
    exit_bb = region->exit;
  
    l0 = tree_block_label (iter_part_bb);
    l1 = tree_block_label (seq_start_bb);
    l2 = tree_block_label (body_bb);
--- 3031,3064 ----
  static void
  expand_omp_for_static_chunk (struct omp_region *region, struct omp_for_data *fd)
  {
!   tree l0, l1, l2, l3, l4, n, s0, e0, e, t, phi, nphi, args;
!   tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
!   tree type, utype, cont, v_main, v_back, v_extra;
!   basic_block entry_bb, body_bb, seq_start_bb, iter_part_bb;
!   basic_block trip_update_bb, cont_bb, fin_bb, exit_bb;
    block_stmt_iterator si;
+   edge se, re, ene;
  
    type = TREE_TYPE (fd->v);
    utype = lang_hooks.types.unsigned_type (type);
  
    entry_bb = region->entry;
!   se = split_block (entry_bb, last_stmt (entry_bb));
!   entry_bb = se->src;
!   iter_part_bb = se->dest;
    cont_bb = region->cont;
!   gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
!   gcc_assert (BRANCH_EDGE (iter_part_bb)->dest
! 	      == FALLTHRU_EDGE (cont_bb)->dest);
!   seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
!   body_bb = single_succ (seq_start_bb);
!   gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
!   gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
!   fin_bb = FALLTHRU_EDGE (cont_bb)->dest;
!   trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
    exit_bb = region->exit;
  
+   tree_block_label (entry_bb);
    l0 = tree_block_label (iter_part_bb);
    l1 = tree_block_label (seq_start_bb);
    l2 = tree_block_label (body_bb);
*************** expand_omp_for_static_chunk (struct omp_
*** 2959,2991 ****
    l4 = tree_block_label (fin_bb);
  
    /* Trip and adjustment setup goes in ENTRY_BB.  */
!   list = alloc_stmt_list ();
  
    t = built_in_decls[BUILT_IN_OMP_GET_NUM_THREADS];
    t = build_function_call_expr (t, NULL);
    t = fold_convert (utype, t);
!   nthreads = get_formal_tmp_var (t, &list);
    
    t = built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM];
    t = build_function_call_expr (t, NULL);
    t = fold_convert (utype, t);
!   threadid = get_formal_tmp_var (t, &list);
  
!   fd->n1 = fold_convert (type, fd->n1);
!   if (!is_gimple_val (fd->n1))
!     fd->n1 = get_formal_tmp_var (fd->n1, &list);
! 
!   fd->n2 = fold_convert (type, fd->n2);
!   if (!is_gimple_val (fd->n2))
!     fd->n2 = get_formal_tmp_var (fd->n2, &list);
! 
!   fd->step = fold_convert (type, fd->step);
!   if (!is_gimple_val (fd->step))
!     fd->step = get_formal_tmp_var (fd->step, &list);
! 
!   fd->chunk_size = fold_convert (utype, fd->chunk_size);
!   if (!is_gimple_val (fd->chunk_size))
!     fd->chunk_size = get_formal_tmp_var (fd->chunk_size, &list);
  
    t = build_int_cst (type, (fd->cond_code == LT_EXPR ? -1 : 1));
    t = fold_build2 (PLUS_EXPR, type, fd->step, t);
--- 3066,3100 ----
    l4 = tree_block_label (fin_bb);
  
    /* Trip and adjustment setup goes in ENTRY_BB.  */
!   si = bsi_last (entry_bb);
!   gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_FOR);
  
    t = built_in_decls[BUILT_IN_OMP_GET_NUM_THREADS];
    t = build_function_call_expr (t, NULL);
    t = fold_convert (utype, t);
!   nthreads = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
! 				       true, BSI_SAME_STMT);
    
    t = built_in_decls[BUILT_IN_OMP_GET_THREAD_NUM];
    t = build_function_call_expr (t, NULL);
    t = fold_convert (utype, t);
!   threadid = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
! 				       true, BSI_SAME_STMT);
  
!   fd->n1 = force_gimple_operand_bsi (&si, fold_convert (type, fd->n1),
! 				     true, NULL_TREE,
! 				     true, BSI_SAME_STMT);
!   fd->n2 = force_gimple_operand_bsi (&si, fold_convert (type, fd->n2),
! 				     true, NULL_TREE,
! 				     true, BSI_SAME_STMT);
!   fd->step = force_gimple_operand_bsi (&si, fold_convert (type, fd->step),
! 				       true, NULL_TREE,
! 				       true, BSI_SAME_STMT);
!   fd->chunk_size
! 	  = force_gimple_operand_bsi (&si, fold_convert (utype,
! 							 fd->chunk_size),
! 				      true, NULL_TREE,
! 				      true, BSI_SAME_STMT);
  
    t = build_int_cst (type, (fd->cond_code == LT_EXPR ? -1 : 1));
    t = fold_build2 (PLUS_EXPR, type, fd->step, t);
*************** expand_omp_for_static_chunk (struct omp_
*** 2993,3102 ****
    t = fold_build2 (MINUS_EXPR, type, t, fd->n1);
    t = fold_build2 (TRUNC_DIV_EXPR, type, t, fd->step);
    t = fold_convert (utype, t);
!   if (is_gimple_val (t))
!     n = t;
!   else
!     n = get_formal_tmp_var (t, &list);
  
!   t = build_int_cst (utype, 0);
!   trip = get_initialized_tmp_var (t, &list, NULL);
  
!   si = bsi_last (entry_bb);
!   gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_FOR);
!   bsi_insert_after (&si, list, BSI_SAME_STMT);
    bsi_remove (&si, true);
  
    /* Iteration space partitioning goes in ITER_PART_BB.  */
!   list = alloc_stmt_list ();
  
!   t = build2 (MULT_EXPR, utype, trip, nthreads);
!   t = build2 (PLUS_EXPR, utype, t, threadid);
!   t = build2 (MULT_EXPR, utype, t, fd->chunk_size);
!   s0 = get_formal_tmp_var (t, &list);
! 
!   t = build2 (PLUS_EXPR, utype, s0, fd->chunk_size);
!   t = build2 (MIN_EXPR, utype, t, n);
!   e0 = get_formal_tmp_var (t, &list);
  
    t = build2 (LT_EXPR, boolean_type_node, s0, n);
    t = build3 (COND_EXPR, void_type_node, t,
  	      build_and_jump (&l1), build_and_jump (&l4));
!   append_to_statement_list (t, &list);
! 
!   si = bsi_start (iter_part_bb);
!   bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
  
    /* Setup code for sequential iteration goes in SEQ_START_BB.  */
!   list = alloc_stmt_list ();
  
    t = fold_convert (type, s0);
!   t = build2 (MULT_EXPR, type, t, fd->step);
!   t = build2 (PLUS_EXPR, type, t, fd->n1);
    t = build2 (MODIFY_EXPR, void_type_node, fd->v, t);
!   gimplify_and_add (t, &list);
  
    t = fold_convert (type, e0);
!   t = build2 (MULT_EXPR, type, t, fd->step);
!   t = build2 (PLUS_EXPR, type, t, fd->n1);
!   e = get_formal_tmp_var (t, &list);
! 
!   si = bsi_start (seq_start_bb);
!   bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
  
    /* The code controlling the sequential loop goes in CONT_BB,
       replacing the OMP_CONTINUE.  */
!   list = alloc_stmt_list ();
! 
!   t = build2 (PLUS_EXPR, type, fd->v, fd->step);
!   t = build2 (MODIFY_EXPR, void_type_node, fd->v, t);
!   gimplify_and_add (t, &list);
  
!   t = build2 (fd->cond_code, boolean_type_node, fd->v, e);
!   t = get_formal_tmp_var (t, &list);
    t = build3 (COND_EXPR, void_type_node, t,
  	      build_and_jump (&l2), build_and_jump (&l3));
!   append_to_statement_list (t, &list);
!   
!   si = bsi_last (cont_bb);
!   gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_CONTINUE);
!   bsi_insert_after (&si, list, BSI_SAME_STMT);
    bsi_remove (&si, true);
  
    /* Trip update code goes into TRIP_UPDATE_BB.  */
!   list = alloc_stmt_list ();
  
    t = build_int_cst (utype, 1);
!   t = build2 (PLUS_EXPR, utype, trip, t);
!   t = build2 (MODIFY_EXPR, void_type_node, trip, t);
!   gimplify_and_add (t, &list);
! 
!   si = bsi_start (trip_update_bb);
!   bsi_insert_after (&si, list, BSI_CONTINUE_LINKING);
  
    /* Replace the OMP_RETURN with a barrier, or nothing.  */
    si = bsi_last (exit_bb);
    if (!OMP_RETURN_NOWAIT (bsi_stmt (si)))
!     {
!       list = alloc_stmt_list ();
!       build_omp_barrier (&list);
!       bsi_insert_after (&si, list, BSI_SAME_STMT);
!     }
    bsi_remove (&si, true);
  
    /* Connect the new blocks.  */
!   remove_edge (single_succ_edge (entry_bb));
!   make_edge (entry_bb, iter_part_bb, EDGE_FALLTHRU);
  
!   make_edge (iter_part_bb, seq_start_bb, EDGE_TRUE_VALUE);
!   make_edge (iter_part_bb, fin_bb, EDGE_FALSE_VALUE);
  
!   make_edge (seq_start_bb, body_bb, EDGE_FALLTHRU);
  
!   remove_edge (single_succ_edge (cont_bb));
!   make_edge (cont_bb, body_bb, EDGE_TRUE_VALUE);
!   make_edge (cont_bb, trip_update_bb, EDGE_FALSE_VALUE);
  
!   make_edge (trip_update_bb, iter_part_bb, EDGE_FALLTHRU);
  
    set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
    set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
--- 3102,3267 ----
    t = fold_build2 (MINUS_EXPR, type, t, fd->n1);
    t = fold_build2 (TRUNC_DIV_EXPR, type, t, fd->step);
    t = fold_convert (utype, t);
!   n = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
! 				true, BSI_SAME_STMT);
  
!   trip_var = create_tmp_var (utype, ".trip");
!   add_referenced_var (trip_var);
!   if (in_ssa_p)
!     {
!       trip_init = make_ssa_name (trip_var, NULL_TREE);
!       trip_main = make_ssa_name (trip_var, NULL_TREE);
!       trip_back = make_ssa_name (trip_var, NULL_TREE);
!     }
!   else
!     {
!       trip_init = trip_var;
!       trip_main = trip_var;
!       trip_back = trip_var;
!     }
!   t = build2 (MODIFY_EXPR, void_type_node, trip_init,
! 	      build_int_cst (utype, 0));
!   bsi_insert_before (&si, t, BSI_SAME_STMT);
!   if (in_ssa_p)
!     SSA_NAME_DEF_STMT (trip_init) = t;
! 
!   t = fold_build2 (MULT_EXPR, utype, threadid, fd->chunk_size);
!   t = fold_convert (type, t);
!   t = fold_build2 (MULT_EXPR, type, t, fd->step);
!   t = fold_build2 (PLUS_EXPR, type, t, fd->n1);
!   v_extra = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
! 				      true, BSI_SAME_STMT);
  
!   /* Remove the OMP_FOR.  */
    bsi_remove (&si, true);
  
    /* Iteration space partitioning goes in ITER_PART_BB.  */
!   si = bsi_last (iter_part_bb);
  
!   t = fold_build2 (MULT_EXPR, utype, trip_main, nthreads);
!   t = fold_build2 (PLUS_EXPR, utype, t, threadid);
!   t = fold_build2 (MULT_EXPR, utype, t, fd->chunk_size);
!   s0 = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
! 				 false, BSI_CONTINUE_LINKING);
! 
!   t = fold_build2 (PLUS_EXPR, utype, s0, fd->chunk_size);
!   t = fold_build2 (MIN_EXPR, utype, t, n);
!   e0 = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
! 				 false, BSI_CONTINUE_LINKING);
  
    t = build2 (LT_EXPR, boolean_type_node, s0, n);
    t = build3 (COND_EXPR, void_type_node, t,
  	      build_and_jump (&l1), build_and_jump (&l4));
!   bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
  
    /* Setup code for sequential iteration goes in SEQ_START_BB.  */
!   si = bsi_start (seq_start_bb);
  
    t = fold_convert (type, s0);
!   t = fold_build2 (MULT_EXPR, type, t, fd->step);
!   t = fold_build2 (PLUS_EXPR, type, t, fd->n1);
!   t = force_gimple_operand_bsi (&si, t, false, NULL_TREE,
! 				false, BSI_CONTINUE_LINKING);
    t = build2 (MODIFY_EXPR, void_type_node, fd->v, t);
!   bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
!   if (in_ssa_p)
!     SSA_NAME_DEF_STMT (fd->v) = t;
  
    t = fold_convert (type, e0);
!   t = fold_build2 (MULT_EXPR, type, t, fd->step);
!   t = fold_build2 (PLUS_EXPR, type, t, fd->n1);
!   e = force_gimple_operand_bsi (&si, t, true, NULL_TREE,
! 				false, BSI_CONTINUE_LINKING);
  
    /* The code controlling the sequential loop goes in CONT_BB,
       replacing the OMP_CONTINUE.  */
!   si = bsi_last (cont_bb);
!   cont = bsi_stmt (si);
!   gcc_assert (TREE_CODE (cont) == OMP_CONTINUE);
!   v_main = TREE_OPERAND (cont, 1);
!   v_back = TREE_OPERAND (cont, 0);
! 
!   t = build2 (PLUS_EXPR, type, v_main, fd->step);
!   t = build2 (MODIFY_EXPR, void_type_node, v_back, t);
!   bsi_insert_before (&si, t, BSI_SAME_STMT);
!   if (in_ssa_p)
!     SSA_NAME_DEF_STMT (v_back) = t;
  
!   t = build2 (fd->cond_code, boolean_type_node, v_back, e);
    t = build3 (COND_EXPR, void_type_node, t,
  	      build_and_jump (&l2), build_and_jump (&l3));
!   bsi_insert_before (&si, t, BSI_SAME_STMT);
!  
!   /* Remove OMP_CONTINUE.  */
    bsi_remove (&si, true);
  
    /* Trip update code goes into TRIP_UPDATE_BB.  */
!   si = bsi_start (trip_update_bb);
  
    t = build_int_cst (utype, 1);
!   t = build2 (PLUS_EXPR, utype, trip_main, t);
!   t = build2 (MODIFY_EXPR, void_type_node, trip_back, t);
!   bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
!   if (in_ssa_p)
!     SSA_NAME_DEF_STMT (trip_back) = t;
  
    /* Replace the OMP_RETURN with a barrier, or nothing.  */
    si = bsi_last (exit_bb);
    if (!OMP_RETURN_NOWAIT (bsi_stmt (si)))
!     force_gimple_operand_bsi (&si, build_omp_barrier (), false, NULL_TREE,
! 			      false, BSI_SAME_STMT);
    bsi_remove (&si, true);
  
    /* Connect the new blocks.  */
!   find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
!   find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
  
!   find_edge (cont_bb, body_bb)->flags = EDGE_TRUE_VALUE;
!   find_edge (cont_bb, trip_update_bb)->flags = EDGE_FALSE_VALUE;
  
!   redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
  
!   if (in_ssa_p)
!     {
!       /* When we redirect the edge from trip_update_bb to iter_part_bb, we
! 	 remove arguments of the phi nodes in fin_bb.  We need to create
! 	 appropriate phi nodes in iter_part_bb instead.  */
!       se = single_pred_edge (fin_bb);
!       re = single_succ_edge (trip_update_bb);
!       ene = single_succ_edge (entry_bb);
! 
!       args = PENDING_STMT (re);
!       PENDING_STMT (re) = NULL_TREE;
!       for (phi = phi_nodes (fin_bb);
! 	   phi && args;
! 	   phi = PHI_CHAIN (phi), args = TREE_CHAIN (args))
! 	{
! 	  t = PHI_RESULT (phi);
! 	  gcc_assert (t == TREE_PURPOSE (args));
! 	  nphi = create_phi_node (t, iter_part_bb);
! 	  SSA_NAME_DEF_STMT (t) = nphi;
! 
! 	  t = PHI_ARG_DEF_FROM_EDGE (phi, se);
! 	  /* A special case -- fd->v is not yet computed in iter_part_bb, we
! 	     need to use v_extra instead.  */
! 	  if (t == fd->v)
! 	    t = v_extra;
! 	  add_phi_arg (nphi, t, ene);
! 	  add_phi_arg (nphi, TREE_VALUE (args), re);
! 	}
!       gcc_assert (!phi && !args);
!       while ((phi = phi_nodes (fin_bb)) != NULL_TREE)
! 	{
! 	  SET_PHI_RESULT (phi, NULL_TREE);
! 	  remove_phi_node (phi, NULL_TREE);
! 	}
  
!       /* Make phi node for trip.  */
!       phi = create_phi_node (trip_main, iter_part_bb);
!       SSA_NAME_DEF_STMT (trip_main) = phi;
!       add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb));
!       add_phi_arg (phi, trip_init, single_succ_edge (entry_bb));
!     }
  
    set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
    set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
*************** expand_omp_for (struct omp_region *regio
*** 3117,3124 ****
  {
    struct omp_for_data fd;
  
-   push_gimplify_context ();
- 
    extract_omp_for_data (last_stmt (region->entry), &fd);
    region->sched_kind = fd.sched_kind;
  
--- 3282,3287 ----
*************** expand_omp_for (struct omp_region *regio
*** 3136,3143 ****
        int next_ix = BUILT_IN_GOMP_LOOP_STATIC_NEXT + fn_index;
        expand_omp_for_generic (region, &fd, start_ix, next_ix);
      }
! 
!   pop_gimplify_context (NULL);
  }
  
  
--- 3299,3306 ----
        int next_ix = BUILT_IN_GOMP_LOOP_STATIC_NEXT + fn_index;
        expand_omp_for_generic (region, &fd, start_ix, next_ix);
      }
!   
!   update_ssa (TODO_update_ssa_only_virtuals);
  }
  
  
*************** expand_omp_for (struct omp_region *regio
*** 3166,3207 ****
  	reduction;
  
      If this is a combined parallel sections, replace the call to
!     GOMP_sections_start with 'goto L1'.  */
  
  static void
  expand_omp_sections (struct omp_region *region)
  {
!   tree label_vec, l0, l1, l2, t, u, v, sections_stmt;
    unsigned i, len;
!   basic_block entry_bb, exit_bb, l0_bb, l1_bb, l2_bb, default_bb;
    block_stmt_iterator si;
    struct omp_region *inner;
-   edge e;
  
    entry_bb = region->entry;
!   l0_bb = create_empty_bb (entry_bb);
    l1_bb = region->cont;
!   l2_bb = single_succ (l1_bb);
    default_bb = create_empty_bb (l1_bb->prev_bb);
-   exit_bb = region->exit;
  
    l0 = tree_block_label (l0_bb);
    l1 = tree_block_label (l1_bb);
    l2 = tree_block_label (l2_bb);
  
-   v = create_tmp_var (unsigned_type_node, ".section");
- 
    /* We will build a switch() with enough cases for all the
       OMP_SECTION regions, a '0' case to handle the end of more work
       and a default case to abort if something goes wrong.  */
!   len = EDGE_COUNT (entry_bb->succs);
    label_vec = make_tree_vec (len + 2);
  
    /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
       OMP_SECTIONS statement.  */
    si = bsi_last (entry_bb);
    sections_stmt = bsi_stmt (si);
!   gcc_assert (TREE_CODE (sections_stmt) == OMP_SECTIONS);
    if (!is_combined_parallel (region))
      {
        /* If we are not inside a combined parallel+sections region,
--- 3329,3367 ----
  	reduction;
  
      If this is a combined parallel sections, replace the call to
!     GOMP_sections_start with call to GOMP_sections_next.  */
  
  static void
  expand_omp_sections (struct omp_region *region)
  {
!   tree label_vec, l0, l1, l2, t, u, sections_stmt, vin, vmain, vnext, cont;
    unsigned i, len;
!   basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
    block_stmt_iterator si;
    struct omp_region *inner;
  
    entry_bb = region->entry;
!   l0_bb = single_succ (entry_bb);
    l1_bb = region->cont;
!   l2_bb = region->exit;
!   gcc_assert (single_pred (l2_bb) == l0_bb);
    default_bb = create_empty_bb (l1_bb->prev_bb);
  
    l0 = tree_block_label (l0_bb);
    l1 = tree_block_label (l1_bb);
    l2 = tree_block_label (l2_bb);
  
    /* We will build a switch() with enough cases for all the
       OMP_SECTION regions, a '0' case to handle the end of more work
       and a default case to abort if something goes wrong.  */
!   len = EDGE_COUNT (l0_bb->succs) - 1;
    label_vec = make_tree_vec (len + 2);
  
    /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
       OMP_SECTIONS statement.  */
    si = bsi_last (entry_bb);
    sections_stmt = bsi_stmt (si);
!   vin = OMP_SECTIONS_CONTROL (sections_stmt);
    if (!is_combined_parallel (region))
      {
        /* If we are not inside a combined parallel+sections region,
*************** expand_omp_sections (struct omp_region *
*** 3210,3230 ****
        t = tree_cons (NULL, t, NULL);
        u = built_in_decls[BUILT_IN_GOMP_SECTIONS_START];
        t = build_function_call_expr (u, t);
!       t = build2 (MODIFY_EXPR, void_type_node, v, t);
!       bsi_insert_after (&si, t, BSI_SAME_STMT);
      }
    bsi_remove (&si, true);
  
!   /* The switch() statement replacing OMP_SECTIONS goes in L0_BB.  */
!   si = bsi_start (l0_bb);
  
!   t = build3 (SWITCH_EXPR, void_type_node, v, NULL, label_vec);
!   bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
  
    t = build3 (CASE_LABEL_EXPR, void_type_node,
  	      build_int_cst (unsigned_type_node, 0), NULL, l2);
    TREE_VEC_ELT (label_vec, 0) = t;
!   make_edge (l0_bb, l2_bb, 0);
    
    /* Convert each OMP_SECTION into a CASE_LABEL_EXPR.  */
    for (inner = region->inner, i = 1; inner; inner = inner->next, ++i)
--- 3370,3411 ----
        t = tree_cons (NULL, t, NULL);
        u = built_in_decls[BUILT_IN_GOMP_SECTIONS_START];
        t = build_function_call_expr (u, t);
!       t = force_gimple_operand_bsi (&si, t, false, NULL_TREE,
! 				    true, BSI_SAME_STMT);
!       t = build2 (MODIFY_EXPR, void_type_node, vin, t);
      }
+   else
+     {
+       /* Otherwise, call GOMP_sections_next.  */
+       t = built_in_decls[BUILT_IN_GOMP_SECTIONS_NEXT];
+       t = build_function_call_expr (t, NULL);
+       t = build2 (MODIFY_EXPR, void_type_node, vin, t);
+     }
+   bsi_insert_after (&si, t, BSI_SAME_STMT);
+   if (in_ssa_p)
+     {
+       SSA_NAME_DEF_STMT (vin) = t;
+       mark_new_vars_to_rename (t);
+     }
+ 
    bsi_remove (&si, true);
  
!   /* The switch() statement replacing OMP_SECTIONS_SWITCH goes in L0_BB.  */
!   si = bsi_last (l0_bb);
!   gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_SECTIONS_SWITCH);
!   cont = last_stmt (l1_bb);
!   gcc_assert (TREE_CODE (cont) == OMP_CONTINUE);
!   vmain = TREE_OPERAND (cont, 1);
!   vnext = TREE_OPERAND (cont, 0);
  
!   t = build3 (SWITCH_EXPR, void_type_node, vmain, NULL, label_vec);
!   bsi_insert_after (&si, t, BSI_SAME_STMT);
  
    t = build3 (CASE_LABEL_EXPR, void_type_node,
  	      build_int_cst (unsigned_type_node, 0), NULL, l2);
    TREE_VEC_ELT (label_vec, 0) = t;
! 
!   bsi_remove (&si, true);
    
    /* Convert each OMP_SECTION into a CASE_LABEL_EXPR.  */
    for (inner = region->inner, i = 1; inner; inner = inner->next, ++i)
*************** expand_omp_sections (struct omp_region *
*** 3248,3257 ****
        gcc_assert (TREE_CODE (bsi_stmt (si)) == OMP_RETURN);
        bsi_remove (&si, true);
  
-       e = single_pred_edge (s_entry_bb);
-       e->flags = 0;
-       redirect_edge_pred (e, l0_bb);
- 
        single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
        single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
      }
--- 3429,3434 ----
*************** expand_omp_sections (struct omp_region *
*** 3265,3270 ****
--- 3442,3449 ----
    si = bsi_start (default_bb);
    t = built_in_decls[BUILT_IN_TRAP];
    t = build_function_call_expr (t, NULL);
+   if (in_ssa_p)
+     mark_new_vars_to_rename (t);
    bsi_insert_after (&si, t, BSI_CONTINUE_LINKING);
  
    /* Code to get the next section goes in L1_BB.  */
*************** expand_omp_sections (struct omp_region *
*** 3273,3318 ****
  
    t = built_in_decls[BUILT_IN_GOMP_SECTIONS_NEXT];
    t = build_function_call_expr (t, NULL);
!   t = build2 (MODIFY_EXPR, void_type_node, v, t);
    bsi_insert_after (&si, t, BSI_SAME_STMT);
    bsi_remove (&si, true);
  
    /* Cleanup function replaces OMP_RETURN in EXIT_BB.  */
!   si = bsi_last (exit_bb);
    if (OMP_RETURN_NOWAIT (bsi_stmt (si)))
      t = built_in_decls[BUILT_IN_GOMP_SECTIONS_END_NOWAIT];
    else
      t = built_in_decls[BUILT_IN_GOMP_SECTIONS_END];
    t = build_function_call_expr (t, NULL);
    bsi_insert_after (&si, t, BSI_SAME_STMT);
    bsi_remove (&si, true);
  
!   /* Connect the new blocks.  */
!   if (is_combined_parallel (region))
!     {
!       /* If this was a combined parallel+sections region, we did not
! 	 emit a GOMP_sections_start in the entry block, so we just
! 	 need to jump to L1_BB to get the next section.  */
!       make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
!     }
!   else
!     make_edge (entry_bb, l0_bb, EDGE_FALLTHRU);
! 
!   e = single_succ_edge (l1_bb);
!   redirect_edge_succ (e, l0_bb);
!   e->flags = EDGE_FALLTHRU;
  
!   set_immediate_dominator (CDI_DOMINATORS, l1_bb,
! 			   recount_dominator (CDI_DOMINATORS, l1_bb));
!   set_immediate_dominator (CDI_DOMINATORS, l0_bb,
! 			   recount_dominator (CDI_DOMINATORS, l0_bb));
!   set_immediate_dominator (CDI_DOMINATORS, default_bb,
! 			   recount_dominator (CDI_DOMINATORS, default_bb));
!   set_immediate_dominator (CDI_DOMINATORS, l2_bb,
! 			   recount_dominator (CDI_DOMINATORS, l2_bb));
!   for (inner = region->inner; inner; inner = inner->next)
!     set_immediate_dominator (CDI_DOMINATORS, inner->entry,
! 			     recount_dominator (CDI_DOMINATORS, inner->entry));
  }
  
  
--- 3452,3482 ----
  
    t = built_in_decls[BUILT_IN_GOMP_SECTIONS_NEXT];
    t = build_function_call_expr (t, NULL);
!   t = build2 (MODIFY_EXPR, void_type_node, vnext, t);
    bsi_insert_after (&si, t, BSI_SAME_STMT);
+   if (in_ssa_p)
+     {
+       SSA_NAME_DEF_STMT (vnext) = t;
+       mark_new_vars_to_rename (t);
+     }
    bsi_remove (&si, true);
  
    /* Cleanup function replaces OMP_RETURN in EXIT_BB.  */
!   si = bsi_last (l2_bb);
    if (OMP_RETURN_NOWAIT (bsi_stmt (si)))
      t = built_in_decls[BUILT_IN_GOMP_SECTIONS_END_NOWAIT];
    else
      t = built_in_decls[BUILT_IN_GOMP_SECTIONS_END];
    t = build_function_call_expr (t, NULL);
    bsi_insert_after (&si, t, BSI_SAME_STMT);
+   if (in_ssa_p)
+     mark_new_vars_to_rename (t);
    bsi_remove (&si, true);
  
!   single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
  
!   set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
!   update_ssa (TODO_update_ssa_only_virtuals);
  }
  
  
*************** expand_omp_single (struct omp_region *re
*** 3342,3354 ****
  
    si = bsi_last (exit_bb);
    if (!OMP_RETURN_NOWAIT (bsi_stmt (si)) || need_barrier)
!     {
!       tree t = alloc_stmt_list ();
!       build_omp_barrier (&t);
!       bsi_insert_after (&si, t, BSI_SAME_STMT);
!     }
    bsi_remove (&si, true);
    single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
  }
  
  
--- 3506,3516 ----
  
    si = bsi_last (exit_bb);
    if (!OMP_RETURN_NOWAIT (bsi_stmt (si)) || need_barrier)
!     force_gimple_operand_bsi (&si, build_omp_barrier (), false, NULL_TREE,
! 			      false, BSI_SAME_STMT);
    bsi_remove (&si, true);
    single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
+   update_ssa (TODO_update_ssa_only_virtuals);
  }
  
  
*************** build_omp_regions_1 (basic_block bb, str
*** 3471,3476 ****
--- 3633,3643 ----
  	  gcc_assert (parent);
  	  parent->cont = bb;
  	}
+       else if (code == OMP_SECTIONS_SWITCH)
+ 	{
+ 	  /* OMP_SECTIONS_SWITCH is part of OMP_SECTIONS, and we do nothing for
+ 	     it.  */
+ 	}
        else
  	{
  	  /* Otherwise, this directive becomes the parent for a new
*************** build_omp_regions (void)
*** 3498,3504 ****
    build_omp_regions_1 (ENTRY_BLOCK_PTR, NULL);
  }
  
- 
  /* Main entry point for expanding OMP-GIMPLE into runtime calls.  */
  
  static unsigned int
--- 3665,3670 ----
*************** struct tree_opt_pass pass_expand_omp = 
*** 3550,3555 ****
--- 3716,3747 ----
    TODO_dump_func,			/* todo_flags_finish */
    0					/* letter */
  };
+ 
+ /* This expansion pass is run when optimizations are disabled.
+    Execute_expand_omp detects this automatically by querying in_ssa_p.  */
+ 
+ static bool
+ gate_expand_omp_O0 (void)
+ {
+   return !optimize && flag_openmp != 0 && errorcount == 0;
+ }
+ 
+ struct tree_opt_pass pass_expand_omp_O0 = 
+ {
+   "ompexpO0",				/* name */
+   gate_expand_omp_O0,			/* gate */
+   execute_expand_omp,			/* execute */
+   NULL,					/* sub */
+   NULL,					/* next */
+   0,					/* static_pass_number */
+   0,					/* tv_id */
+   PROP_gimple_any,			/* properties_required */
+   PROP_gimple_lomp,			/* properties_provided */
+   0,					/* properties_destroyed */
+   0,					/* todo_flags_start */
+   TODO_dump_func,			/* todo_flags_finish */
+   0					/* letter */
+ };
  
  /* Routines to lower OpenMP directives into OMP-GIMPLE.  */
  
*************** lower_omp_sections (tree *stmt_p, omp_co
*** 3562,3567 ****
--- 3754,3760 ----
    tree t, dlist;
    tree_stmt_iterator tsi;
    unsigned i, len;
+   tree control;
  
    stmt = *stmt_p;
  
*************** lower_omp_sections (tree *stmt_p, omp_co
*** 3620,3628 ****
    new_body = alloc_stmt_list ();
    append_to_statement_list (ilist, &new_body);
    append_to_statement_list (stmt, &new_body);
    append_to_statement_list (bind, &new_body);
  
!   t = make_node (OMP_CONTINUE);
    append_to_statement_list (t, &new_body);
  
    append_to_statement_list (olist, &new_body);
--- 3813,3824 ----
    new_body = alloc_stmt_list ();
    append_to_statement_list (ilist, &new_body);
    append_to_statement_list (stmt, &new_body);
+   append_to_statement_list (make_node (OMP_SECTIONS_SWITCH), &new_body);
    append_to_statement_list (bind, &new_body);
  
!   control = create_tmp_var (unsigned_type_node, ".section");
!   t = build2 (OMP_CONTINUE, void_type_node, control, control);
!   OMP_SECTIONS_CONTROL (stmt) = control;
    append_to_statement_list (t, &new_body);
  
    append_to_statement_list (olist, &new_body);
*************** lower_omp_for_lastprivate (struct omp_fo
*** 3997,4010 ****
  static void
  lower_omp_for (tree *stmt_p, omp_context *ctx)
  {
!   tree t, stmt, ilist, dlist, new_stmt, *body_p, *rhs_p;
    struct omp_for_data fd;
  
    stmt = *stmt_p;
  
    push_gimplify_context ();
  
    lower_omp (&OMP_FOR_PRE_BODY (stmt), ctx);
    lower_omp (&OMP_FOR_BODY (stmt), ctx);
  
    /* Move declaration of temporaries in the loop body before we make
--- 4193,4214 ----
  static void
  lower_omp_for (tree *stmt_p, omp_context *ctx)
  {
!   tree t, stmt, ilist, clist = NULL, dlist, new_stmt, *body_p, *rhs_p, c, *tp;
    struct omp_for_data fd;
+   enum gimplify_status gs;
  
    stmt = *stmt_p;
  
    push_gimplify_context ();
  
    lower_omp (&OMP_FOR_PRE_BODY (stmt), ctx);
+   c = find_omp_clause (OMP_FOR_CLAUSES (stmt), OMP_CLAUSE_SCHEDULE);
+   if (c)
+     {
+       tp = &OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c);
+       gs = gimplify_expr (tp, &clist, NULL, is_gimple_val, fb_rvalue);
+       gcc_assert (gs == GS_ALL_DONE);
+     }
    lower_omp (&OMP_FOR_BODY (stmt), ctx);
  
    /* Move declaration of temporaries in the loop body before we make
*************** lower_omp_for (tree *stmt_p, omp_context
*** 4020,4025 ****
--- 4224,4230 ----
    ilist = NULL;
    dlist = NULL;
    append_to_statement_list (OMP_FOR_PRE_BODY (stmt), body_p);
+   append_to_statement_list (clist, body_p);
    lower_rec_input_clauses (OMP_FOR_CLAUSES (stmt), body_p, &dlist, ctx);
  
    /* Lower the header expressions.  At this point, we can assume that
*************** lower_omp_for (tree *stmt_p, omp_context
*** 4048,4054 ****
  
    append_to_statement_list (OMP_FOR_BODY (stmt), body_p);
  
!   t = make_node (OMP_CONTINUE);
    append_to_statement_list (t, body_p);
  
    /* After the loop, add exit clauses.  */
--- 4253,4259 ----
  
    append_to_statement_list (OMP_FOR_BODY (stmt), body_p);
  
!   t = build2 (OMP_CONTINUE, void_type_node, fd.v, fd.v);
    append_to_statement_list (t, body_p);
  
    /* After the loop, add exit clauses.  */
Index: tree-gimple.c
===================================================================
*** tree-gimple.c	(revision 117561)
--- tree-gimple.c	(working copy)
*************** is_gimple_stmt (tree t)
*** 222,227 ****
--- 222,228 ----
      case OMP_PARALLEL:
      case OMP_FOR:
      case OMP_SECTIONS:
+     case OMP_SECTIONS_SWITCH:
      case OMP_SECTION:
      case OMP_SINGLE:
      case OMP_MASTER:
Index: tree-ssa-alias.c
===================================================================
*** tree-ssa-alias.c	(revision 117561)
--- tree-ssa-alias.c	(working copy)
*************** is_escape_site (tree stmt, struct alias_
*** 2124,2129 ****
--- 2124,2135 ----
  
        return ESCAPE_TO_CALL;
      }
+   else if (TREE_CODE (stmt) == OMP_PARALLEL)
+     {
+       /* OMP_PARALLEL expands to a call whose argument is address of
+ 	 OMP_PARALLEL_DATA_ARG.  */
+       return ESCAPE_TO_CALL;
+     }
    else if (TREE_CODE (stmt) == ASM_EXPR)
      return ESCAPE_TO_ASM;
    else if (TREE_CODE (stmt) == MODIFY_EXPR)
Index: gimple-low.c
===================================================================
*** gimple-low.c	(revision 117561)
--- gimple-low.c	(working copy)
*************** lower_stmt (tree_stmt_iterator *tsi, str
*** 214,219 ****
--- 214,220 ----
      case SWITCH_EXPR:
      case OMP_FOR:
      case OMP_SECTIONS:
+     case OMP_SECTIONS_SWITCH:
      case OMP_SECTION:
      case OMP_SINGLE:
      case OMP_MASTER:
Index: tree-parloops.c
===================================================================
*** tree-parloops.c	(revision 117561)
--- tree-parloops.c	(working copy)
*************** loop_parallel_p (struct loop *loop, stru
*** 174,209 ****
    return ret;
  }
  
- /* Marks all virtual operands of statement STMT for renaming.  */
- 
- static void
- mark_virtual_ops_for_renaming (tree stmt)
- {
-   ssa_op_iter iter;
-   tree var;
- 
-   if (TREE_CODE (stmt) == PHI_NODE)
-     {
-       var = PHI_RESULT (stmt);
-       if (is_gimple_reg (var))
- 	return;
- 
-       if (TREE_CODE (var) == SSA_NAME)
- 	var = SSA_NAME_VAR (var);
-       mark_sym_for_renaming (var);
-       return;
-     }
- 
-   update_stmt (stmt);
- 
-   FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, SSA_OP_ALL_VIRTUALS)
-     {
-       if (TREE_CODE (var) == SSA_NAME)
- 	var = SSA_NAME_VAR (var);
-       mark_sym_for_renaming (var);
-     }
- }
- 
  /* Calls mark_virtual_ops_for_renaming for all members of LIST.  */
  
  static void
--- 174,179 ----
*************** mark_virtual_ops_for_renaming_list (tree
*** 217,223 ****
  
  /* Marks operands of calls for renaming.  */
  
! static void
  mark_call_virtual_operands (void)
  {
    basic_block bb;
--- 187,193 ----
  
  /* Marks operands of calls for renaming.  */
  
! void
  mark_call_virtual_operands (void)
  {
    basic_block bb;
*************** extract_loop_to_function (struct loop *l
*** 950,956 ****
  {
    basic_block bb_to = loop_split_edge_with (loop->single_exit, NULL);
    basic_block bb_from = loop_preheader_edge (loop)->src;
!   basic_block repl_bb, bb;
    tree arg, narg, stmt;
    struct function *act_cfun = cfun;
    tree act_decl = current_function_decl;
--- 920,926 ----
  {
    basic_block bb_to = loop_split_edge_with (loop->single_exit, NULL);
    basic_block bb_from = loop_preheader_edge (loop)->src;
!   basic_block repl_bb;
    tree arg, narg, stmt;
    struct function *act_cfun = cfun;
    tree act_decl = current_function_decl;
*************** extract_loop_to_function (struct loop *l
*** 958,964 ****
    basic_block *body = get_loop_body (loop);
    struct loop *outer = loop->outer;
    unsigned i, n = loop->num_nodes;
-   stmt_ann_t ann;
  
    cancel_loop_tree (current_loops, loop);
    for (i = 0; i < n; i++)
--- 928,933 ----
*************** extract_loop_to_function (struct loop *l
*** 993,1019 ****
        SSA_NAME_DEF_STMT (arg_struct) = stmt;
        bsi_insert_before (&bsi, stmt, BSI_NEW_STMT);
      }
- 
-   go_out_of_ssa ();
- 
-   /* Let us pretend that we have never seen the statements before.  The
-      operands of the statements are allocated from the local caches, so
-      we cannot preserve them.  */
-   FOR_EACH_BB (bb)
-     {
-       for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
- 	{
- 	  ann = stmt_ann (bsi_stmt (bsi));
- 	  memset (ann, 0, sizeof (struct stmt_ann_d));
- 	  ann->common.type = STMT_ANN;
- 	  ann->modified = 1;
- 	  ann->bb = bb;
- 	}
-     }
- 
    cfun = act_cfun;
    current_function_decl = act_decl;
  
    return repl_bb;
  }
  
--- 962,972 ----
        SSA_NAME_DEF_STMT (arg_struct) = stmt;
        bsi_insert_before (&bsi, stmt, BSI_NEW_STMT);
      }
    cfun = act_cfun;
    current_function_decl = act_decl;
  
+   go_out_of_ssa (*loop_fn);
+ 
    return repl_bb;
  }
  
Index: tree-ssa-address.c
===================================================================
*** tree-ssa-address.c	(revision 117561)
--- tree-ssa-address.c	(working copy)
*************** static void
*** 477,487 ****
  gimplify_mem_ref_parts (block_stmt_iterator *bsi, struct mem_address *parts)
  {
    if (parts->base)
!     parts->base = force_gimple_operand_bsi (bsi, parts->base,
! 					    true, NULL_TREE);
    if (parts->index)
      parts->index = force_gimple_operand_bsi (bsi, parts->index,
! 					     true, NULL_TREE);
  }
  
  /* Creates and returns a TARGET_MEM_REF for address ADDR.  If necessary
--- 477,488 ----
  gimplify_mem_ref_parts (block_stmt_iterator *bsi, struct mem_address *parts)
  {
    if (parts->base)
!     parts->base = force_gimple_operand_bsi (bsi, parts->base, true, NULL_TREE,
! 					    true, BSI_SAME_STMT);
    if (parts->index)
      parts->index = force_gimple_operand_bsi (bsi, parts->index,
! 					     true, NULL_TREE,
! 					     true, BSI_SAME_STMT);
  }
  
  /* Creates and returns a TARGET_MEM_REF for address ADDR.  If necessary
*************** create_mem_ref (block_stmt_iterator *bsi
*** 511,517 ****
        parts.index = force_gimple_operand_bsi (bsi,
  					      build2 (MULT_EXPR, addr_type,
  						      parts.index, parts.step),
! 					      true, NULL_TREE);
        parts.step = NULL_TREE;
    
        mem_ref = create_mem_ref_raw (type, &parts);
--- 512,519 ----
        parts.index = force_gimple_operand_bsi (bsi,
  					      build2 (MULT_EXPR, addr_type,
  						      parts.index, parts.step),
! 					      true, NULL_TREE,
! 					      true, BSI_SAME_STMT);
        parts.step = NULL_TREE;
    
        mem_ref = create_mem_ref_raw (type, &parts);
*************** create_mem_ref (block_stmt_iterator *bsi
*** 530,536 ****
  	    parts.base = force_gimple_operand_bsi (bsi,
  						   build2 (PLUS_EXPR, addr_type,
  							   parts.base, tmp),
! 						   true, NULL_TREE);
  	  else
  	    {
  	      parts.index = parts.base;
--- 532,539 ----
  	    parts.base = force_gimple_operand_bsi (bsi,
  						   build2 (PLUS_EXPR, addr_type,
  							   parts.base, tmp),
! 						   true, NULL_TREE,
! 						   true, BSI_SAME_STMT);
  	  else
  	    {
  	      parts.index = parts.base;
*************** create_mem_ref (block_stmt_iterator *bsi
*** 554,560 ****
  						build2 (PLUS_EXPR, addr_type,
  							parts.base,
  							parts.index),
! 						true, NULL_TREE);
        else
  	parts.index = parts.base;
        parts.base = NULL_TREE;
--- 557,564 ----
  						build2 (PLUS_EXPR, addr_type,
  							parts.base,
  							parts.index),
! 						true, NULL_TREE,
! 						true, BSI_SAME_STMT);
        else
  	parts.index = parts.base;
        parts.base = NULL_TREE;
*************** create_mem_ref (block_stmt_iterator *bsi
*** 572,578 ****
  						build2 (PLUS_EXPR, addr_type,
  							parts.index,
  							parts.offset),
! 						true, NULL_TREE);
        else
  	parts.index = parts.offset, bsi;
  
--- 576,583 ----
  						build2 (PLUS_EXPR, addr_type,
  							parts.index,
  							parts.offset),
! 						true, NULL_TREE,
! 						true, BSI_SAME_STMT);
        else
  	parts.index = parts.offset, bsi;
  
Index: tree-flow-inline.h
===================================================================
*** tree-flow-inline.h	(revision 117561)
--- tree-flow-inline.h	(working copy)
*************** phi_arg_index_from_use (use_operand_p us
*** 585,600 ****
   return index;
  }
  
- /* Mark VAR as used, so that it'll be preserved during rtl expansion.  */
- 
- static inline void
- set_is_used (tree var)
- {
-   var_ann_t ann = get_var_ann (var);
-   ann->used = 1;
- }
- 
- 
  /*  -----------------------------------------------------------------------  */
  
  /* Return true if T is an executable statement.  */
--- 585,590 ----
Index: gimplify.c
===================================================================
*** gimplify.c	(revision 117561)
--- gimplify.c	(working copy)
*************** force_gimple_operand (tree expr, tree *s
*** 6372,6388 ****
  }
  
  /* Invokes force_gimple_operand for EXPR with parameters SIMPLE_P and VAR.  If
!    some statements are produced, emits them before BSI.  */
  
  tree
  force_gimple_operand_bsi (block_stmt_iterator *bsi, tree expr,
! 			  bool simple_p, tree var)
  {
    tree stmts;
  
    expr = force_gimple_operand (expr, &stmts, simple_p, var);
    if (stmts)
!     bsi_insert_before (bsi, stmts, BSI_SAME_STMT);
  
    return expr;
  }
--- 6372,6405 ----
  }
  
  /* Invokes force_gimple_operand for EXPR with parameters SIMPLE_P and VAR.  If
!    some statements are produced, emits them before BSI.  If BEFORE is true.
!    the statements are appended before BSI, otherwise they are appended after
!    it.  M specifies the way BSI moves after insertion (BSI_SAME_STMT or
!    BSI_CONTINUE_LINKING are the usual values).  */
  
  tree
  force_gimple_operand_bsi (block_stmt_iterator *bsi, tree expr,
! 			  bool simple_p, tree var, bool before,
! 			  enum bsi_iterator_update m)
  {
    tree stmts;
  
    expr = force_gimple_operand (expr, &stmts, simple_p, var);
    if (stmts)
!     {
!       tree_stmt_iterator tsi;
! 
!       if (in_ssa_p)
! 	{
! 	  for (tsi = tsi_start (stmts); !tsi_end_p (tsi); tsi_next (&tsi))
! 	    mark_new_vars_to_rename (tsi_stmt (tsi));
! 	}
! 
!       if (before)
! 	bsi_insert_before (bsi, stmts, m);
!       else
! 	bsi_insert_after (bsi, stmts, m);
!     }
  
    return expr;
  }
Index: tree.def
===================================================================
*** tree.def	(revision 117561)
--- tree.def	(working copy)
*************** DEFTREECODE (OMP_FOR, "omp_for", tcc_sta
*** 987,994 ****
  
  /* OpenMP - #pragma omp sections [clause1 ... clauseN]
     Operand 0: OMP_SECTIONS_BODY: Sections body.
!    Operand 1: OMP_SECTIONS_CLAUSES: List of clauses.  */
! DEFTREECODE (OMP_SECTIONS, "omp_sections", tcc_statement, 2)
  
  /* OpenMP - #pragma omp single
     Operand 0: OMP_SINGLE_BODY: Single section body.
--- 987,1000 ----
  
  /* OpenMP - #pragma omp sections [clause1 ... clauseN]
     Operand 0: OMP_SECTIONS_BODY: Sections body.
!    Operand 1: OMP_SECTIONS_CLAUSES: List of clauses.
!    Operand 2: OMP_SECTIONS_CONTROL: The control variable used for deciding
! 	      which of the sections to execute.  */
! DEFTREECODE (OMP_SECTIONS, "omp_sections", tcc_statement, 3)
! 
! /* This tree immediatelly follows OMP_SECTIONS, and represents the switch
!    used to decide which branch is taken.  */
! DEFTREECODE (OMP_SECTIONS_SWITCH, "omp_sections_switch", tcc_statement, 0)
  
  /* OpenMP - #pragma omp single
     Operand 0: OMP_SINGLE_BODY: Single section body.
*************** DEFTREECODE (OMP_CRITICAL, "omp_critical
*** 1016,1023 ****
  DEFTREECODE (OMP_RETURN, "omp_return", tcc_statement, 0)
  
  /* OpenMP - An intermediate tree code to mark the location of the
!    loop or sections iteration in the partially lowered code.  */
! DEFTREECODE (OMP_CONTINUE, "omp_continue", tcc_statement, 0)
  
  /* OpenMP - #pragma omp atomic
     Operand 0: The address at which the atomic operation is to be performed.
--- 1022,1030 ----
  DEFTREECODE (OMP_RETURN, "omp_return", tcc_statement, 0)
  
  /* OpenMP - An intermediate tree code to mark the location of the
!    loop or sections iteration in the partially lowered code.
!    The arguments are definition and use of the control variable.  */
! DEFTREECODE (OMP_CONTINUE, "omp_continue", tcc_statement, 2)
  
  /* OpenMP - #pragma omp atomic
     Operand 0: The address at which the atomic operation is to be performed.
Index: tree-ssa-live.c
===================================================================
*** tree-ssa-live.c	(revision 117561)
--- tree-ssa-live.c	(working copy)
*************** Boston, MA 02110-1301, USA.  */
*** 40,45 ****
--- 40,51 ----
  #include "toplev.h"
  #include "vecprim.h"
  
+ /* Records partition for a variable.  */
+ htab_t var_partition_map;
+ 
+ /* Records variables seen by out of ssa pass.  */
+ bitmap out_of_ssa;
+ 
  static void live_worklist (tree_live_info_p, int *, int);
  static tree_live_info_p new_tree_live_info (var_map);
  static inline void set_if_valid (var_map, bitmap, tree);
*************** static inline void add_conflicts_if_vali
*** 50,55 ****
--- 56,81 ----
  					   var_map, bitmap, tree);
  static partition_pair_p find_partition_pair (coalesce_list_p, int, int, bool);
  
+ /* Hash table used by root_var_init and mapping from variables to
+    partitions.  */
+ 
+ static int
+ int_int_map_eq (const void *aa, const void *bb)
+ {
+   struct int_int_map *a = (struct int_int_map *) aa;
+   struct int_int_map *b = (struct int_int_map *) bb;
+ 
+   return a->from == b->from;
+ }
+ 
+ static hashval_t
+ int_int_map_hash (const void *aa)
+ {
+   struct int_int_map *a = (struct int_int_map *) aa;
+ 
+   return (hashval_t) a->from;
+ }
+ 
  /* This is where the mapping from SSA version number to real storage variable
     is tracked.  
  
*************** delete_var_map (var_map map)
*** 100,105 ****
--- 126,139 ----
    free (map);
  }
  
+ /* Free mapping from vars to partitions.  */
+ 
+ void
+ delete_var_partition_map (void)
+ {
+   htab_delete (var_partition_map);
+   BITMAP_FREE (out_of_ssa);
+ }
  
  /* This function will combine the partitions in MAP for VAR1 and VAR2.  It 
     Returns the partition which represents the new partition.  If the two 
*************** compact_var_map (var_map map, int flags)
*** 276,301 ****
  void 
  change_partition_var (var_map map, tree var, int part)
  {
!   var_ann_t ann;
  
    gcc_assert (TREE_CODE (var) != SSA_NAME);
  
!   ann = var_ann (var);
!   ann->out_of_ssa_tag = 1;
!   VAR_ANN_PARTITION (ann) = part;
    if (map->compact_to_partition)
      map->partition_to_var[map->compact_to_partition[part]] = var;
  }
  
! static inline void mark_all_vars_used (tree *);
  
  /* Helper function for mark_all_vars_used, called via walk_tree.  */
  
  static tree
  mark_all_vars_used_1 (tree *tp, int *walk_subtrees,
! 		      void *data ATTRIBUTE_UNUSED)
  {
    tree t = *tp;
  
    if (TREE_CODE (t) == SSA_NAME)
      t = SSA_NAME_VAR (t);
--- 310,336 ----
  void 
  change_partition_var (var_map map, tree var, int part)
  {
!   struct int_int_map *part_map;
  
    gcc_assert (TREE_CODE (var) != SSA_NAME);
  
!   part_map = int_int_map_find_or_insert (var_partition_map, DECL_UID (var));
!   bitmap_set_bit (out_of_ssa, DECL_UID (var));
!   part_map->to = part;
    if (map->compact_to_partition)
      map->partition_to_var[map->compact_to_partition[part]] = var;
  }
  
! static inline void mark_all_vars_used (tree *, bitmap);
  
  /* Helper function for mark_all_vars_used, called via walk_tree.  */
  
  static tree
  mark_all_vars_used_1 (tree *tp, int *walk_subtrees,
! 		      void *data)
  {
    tree t = *tp;
+   bitmap used = data;
  
    if (TREE_CODE (t) == SSA_NAME)
      t = SSA_NAME_VAR (t);
*************** mark_all_vars_used_1 (tree *tp, int *wal
*** 304,312 ****
       fields that do not contain vars.  */
    if (TREE_CODE (t) == TARGET_MEM_REF)
      {
!       mark_all_vars_used (&TMR_SYMBOL (t));
!       mark_all_vars_used (&TMR_BASE (t));
!       mark_all_vars_used (&TMR_INDEX (t));
        *walk_subtrees = 0;
        return NULL;
      }
--- 339,347 ----
       fields that do not contain vars.  */
    if (TREE_CODE (t) == TARGET_MEM_REF)
      {
!       mark_all_vars_used (&TMR_SYMBOL (t), used);
!       mark_all_vars_used (&TMR_BASE (t), used);
!       mark_all_vars_used (&TMR_INDEX (t), used);
        *walk_subtrees = 0;
        return NULL;
      }
*************** mark_all_vars_used_1 (tree *tp, int *wal
*** 314,320 ****
    /* Only need to mark VAR_DECLS; parameters and return results are not
       eliminated as unused.  */
    if (TREE_CODE (t) == VAR_DECL)
!     set_is_used (t);
  
    if (IS_TYPE_OR_DECL_P (t))
      *walk_subtrees = 0;
--- 349,355 ----
    /* Only need to mark VAR_DECLS; parameters and return results are not
       eliminated as unused.  */
    if (TREE_CODE (t) == VAR_DECL)
!     bitmap_set_bit (used, DECL_UID (t));
  
    if (IS_TYPE_OR_DECL_P (t))
      *walk_subtrees = 0;
*************** mark_all_vars_used_1 (tree *tp, int *wal
*** 326,334 ****
     eliminated during the tree->rtl conversion process.  */
  
  static inline void
! mark_all_vars_used (tree *expr_p)
  {
!   walk_tree (expr_p, mark_all_vars_used_1, NULL, NULL);
  }
  
  
--- 361,369 ----
     eliminated during the tree->rtl conversion process.  */
  
  static inline void
! mark_all_vars_used (tree *expr_p, bitmap used)
  {
!   walk_tree (expr_p, mark_all_vars_used_1, used, NULL);
  }
  
  
*************** void
*** 338,353 ****
  remove_unused_locals (void)
  {
    basic_block bb;
!   tree t, *cell;
! 
!   /* Assume all locals are unused.  */
!   for (t = cfun->unexpanded_var_list; t; t = TREE_CHAIN (t))
!     {
!       tree var = TREE_VALUE (t);
!       if (TREE_CODE (var) != FUNCTION_DECL
! 	  && var_ann (var))
! 	var_ann (var)->used = false;
!     }
  
    /* Walk the CFG marking all referenced symbols.  */
    FOR_EACH_BB (bb)
--- 373,380 ----
  remove_unused_locals (void)
  {
    basic_block bb;
!   tree *cell;
!   bitmap used_vars = BITMAP_ALLOC (NULL);
  
    /* Walk the CFG marking all referenced symbols.  */
    FOR_EACH_BB (bb)
*************** remove_unused_locals (void)
*** 357,363 ****
  
        /* Walk the statements.  */
        for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
! 	mark_all_vars_used (bsi_stmt_ptr (bsi));
  
        for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
          {
--- 384,390 ----
  
        /* Walk the statements.  */
        for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
! 	mark_all_vars_used (bsi_stmt_ptr (bsi), used_vars);
  
        for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
          {
*************** remove_unused_locals (void)
*** 369,380 ****
  	    continue;
  
            def = PHI_RESULT (phi);
!           mark_all_vars_used (&def);
  
            FOR_EACH_PHI_ARG (arg_p, phi, i, SSA_OP_ALL_USES)
              {
  	      tree arg = USE_FROM_PTR (arg_p);
! 	      mark_all_vars_used (&arg);
              }
          }
      }
--- 396,407 ----
  	    continue;
  
            def = PHI_RESULT (phi);
!           mark_all_vars_used (&def, used_vars);
  
            FOR_EACH_PHI_ARG (arg_p, phi, i, SSA_OP_ALL_USES)
              {
  	      tree arg = USE_FROM_PTR (arg_p);
! 	      mark_all_vars_used (&arg, used_vars);
              }
          }
      }
*************** remove_unused_locals (void)
*** 383,393 ****
    for (cell = &cfun->unexpanded_var_list; *cell; )
      {
        tree var = TREE_VALUE (*cell);
-       var_ann_t ann;
  
        if (TREE_CODE (var) != FUNCTION_DECL
! 	  && (!(ann = var_ann (var))
! 	      || !ann->used))
  	{
  	  *cell = TREE_CHAIN (*cell);
  	  continue;
--- 410,418 ----
    for (cell = &cfun->unexpanded_var_list; *cell; )
      {
        tree var = TREE_VALUE (*cell);
  
        if (TREE_CODE (var) != FUNCTION_DECL
! 	  && !bitmap_bit_p (used_vars, DECL_UID (var)))
  	{
  	  *cell = TREE_CHAIN (*cell);
  	  continue;
*************** remove_unused_locals (void)
*** 395,400 ****
--- 420,436 ----
  
        cell = &TREE_CHAIN (*cell);
      }
+ 
+   BITMAP_FREE (used_vars);
+ }
+ 
+ /* Initialize mapping from vars to partitions.  */
+ 
+ void
+ init_var_partition_map (void)
+ {
+   out_of_ssa = BITMAP_ALLOC (NULL);
+   var_partition_map = htab_create (10, int_int_map_hash, int_int_map_eq, free);
  }
  
  /* This function looks through the program and uses FLAGS to determine what 
*************** create_ssa_var_map (int flags)
*** 442,449 ****
  	      arg = PHI_ARG_DEF (phi, i);
  	      if (TREE_CODE (arg) == SSA_NAME)
  		register_ssa_partition (map, arg, true);
- 
- 	      mark_all_vars_used (&PHI_ARG_DEF_TREE (phi, i));
  	    }
  	}
  
--- 478,483 ----
*************** create_ssa_var_map (int flags)
*** 480,487 ****
  	    }
  
  #endif /* ENABLE_CHECKING */
- 
- 	  mark_all_vars_used (bsi_stmt_ptr (bsi));
  	}
      }
  
--- 514,519 ----
*************** tpa_compact (tpa_p tpa)
*** 999,1004 ****
--- 1031,1055 ----
    return last;
  }
  
+ /* Finds or creates element with key WHAT in WHERE.  */
+ 
+ struct int_int_map *
+ int_int_map_find_or_insert (htab_t where, int what)
+ {
+   void **loc;
+   struct int_int_map *nelt, temp;
+ 
+   temp.from = what;
+   loc = htab_find_slot_with_hash (where, &temp, what, INSERT);
+   if (*loc)
+     return *loc;
+ 
+   nelt = XNEW (struct int_int_map);
+   nelt->from = what;
+   nelt->to = 0;
+   *loc = nelt;
+   return nelt;
+ }
  
  /* Initialize a root_var object with SSA partitions from MAP which are based 
     on each root variable.  */
*************** root_var_init (var_map map)
*** 1010,1017 ****
    int num_partitions = num_var_partitions (map);
    int x, p;
    tree t;
-   var_ann_t ann;
    sbitmap seen;
  
    rv = tpa_init (map);
    if (!rv)
--- 1061,1070 ----
    int num_partitions = num_var_partitions (map);
    int x, p;
    tree t;
    sbitmap seen;
+   bitmap root_var_processed;
+   htab_t var_root_index;
+   struct int_int_map *root_index;
  
    rv = tpa_init (map);
    if (!rv)
*************** root_var_init (var_map map)
*** 1019,1024 ****
--- 1072,1079 ----
  
    seen = sbitmap_alloc (num_partitions);
    sbitmap_zero (seen);
+   root_var_processed = BITMAP_ALLOC (NULL);
+   var_root_index = htab_create (10, int_int_map_hash, int_int_map_eq, free);
  
    /* Start at the end and work towards the front. This will provide a list
       that is ordered from smallest to largest.  */
*************** root_var_init (var_map map)
*** 1040,1069 ****
        SET_BIT (seen, p);
        if (TREE_CODE (t) == SSA_NAME)
  	t = SSA_NAME_VAR (t);
!       ann = var_ann (t);
!       if (ann->root_var_processed)
!         {
  	  rv->next_partition[p] = VEC_index (int, rv->first_partition, 
! 					     VAR_ANN_ROOT_INDEX (ann));
! 	  VEC_replace (int, rv->first_partition, VAR_ANN_ROOT_INDEX (ann), p);
  	}
        else
          {
! 	  ann->root_var_processed = 1;
! 	  VAR_ANN_ROOT_INDEX (ann) = rv->num_trees++;
  	  VEC_safe_push (tree, heap, rv->trees, t);
  	  VEC_safe_push (int, heap, rv->first_partition, p);
  	}
!       rv->partition_to_tree_map[p] = VAR_ANN_ROOT_INDEX (ann);
!     }
! 
!   /* Reset the out_of_ssa_tag flag on each variable for later use.  */
!   for (x = 0; x < rv->num_trees; x++)
!     {
!       t = VEC_index (tree, rv->trees, x);
!       var_ann (t)->root_var_processed = 0;
      }
  
    sbitmap_free (seen);
    return rv;
  }
--- 1095,1119 ----
        SET_BIT (seen, p);
        if (TREE_CODE (t) == SSA_NAME)
  	t = SSA_NAME_VAR (t);
!       root_index = int_int_map_find_or_insert (var_root_index, DECL_UID (t));
!       if (bitmap_bit_p (root_var_processed, DECL_UID (t)))
! 	{
  	  rv->next_partition[p] = VEC_index (int, rv->first_partition, 
! 					     root_index->to);
! 	  VEC_replace (int, rv->first_partition, root_index->to, p);
  	}
        else
          {
! 	  bitmap_set_bit (root_var_processed, DECL_UID (t));
! 	  root_index->to = rv->num_trees++;
  	  VEC_safe_push (tree, heap, rv->trees, t);
  	  VEC_safe_push (int, heap, rv->first_partition, p);
  	}
!       rv->partition_to_tree_map[p] = root_index->to;
      }
  
+   BITMAP_FREE (root_var_processed);
+   htab_delete (var_root_index);
    sbitmap_free (seen);
    return rv;
  }
Index: tree-ssa-live.h
===================================================================
*** tree-ssa-live.h	(revision 117561)
--- tree-ssa-live.h	(working copy)
*************** typedef struct _var_map
*** 49,56 ****
    int *ref_count;
  } *var_map;
  
! #define VAR_ANN_PARTITION(ann) (ann->partition)
! #define VAR_ANN_ROOT_INDEX(ann) (ann->root_index)
  
  #define NO_PARTITION		-1
  
--- 49,65 ----
    int *ref_count;
  } *var_map;
  
! /* Hash table used by root_var_init and mapping from variables to
!    partitions.  */
! 
! struct int_int_map
! {
!   int from, to;
! };
! 
! extern htab_t var_partition_map;
! extern bitmap out_of_ssa;
! struct int_int_map *int_int_map_find_or_insert (htab_t, int);
  
  #define NO_PARTITION		-1
  
*************** static inline tree version_to_var (var_m
*** 135,141 ****
  static inline int
  var_to_partition (var_map map, tree var)
  {
!   var_ann_t ann;
    int part;
  
    if (TREE_CODE (var) == SSA_NAME)
--- 144,150 ----
  static inline int
  var_to_partition (var_map map, tree var)
  {
!   struct int_int_map *part_map;
    int part;
  
    if (TREE_CODE (var) == SSA_NAME)
*************** var_to_partition (var_map map, tree var)
*** 146,154 ****
      }
    else
      {
!       ann = var_ann (var);
!       if (ann->out_of_ssa_tag)
! 	part = VAR_ANN_PARTITION (ann);
        else
          part = NO_PARTITION;
      }
--- 155,166 ----
      }
    else
      {
!       if (bitmap_bit_p (out_of_ssa, DECL_UID (var)))
! 	{
! 	  part_map = int_int_map_find_or_insert (var_partition_map,
! 						 DECL_UID (var));
! 	  part = part_map->to;
! 	}
        else
          part = NO_PARTITION;
      }
*************** extern conflict_graph build_tree_conflic
*** 713,717 ****
--- 725,731 ----
  extern void coalesce_tpa_members (tpa_p tpa, conflict_graph graph, var_map map,
  				  coalesce_list_p cl, FILE *);
  
+ void init_var_partition_map (void);
+ void delete_var_partition_map (void);
  
  #endif /* _TREE_SSA_LIVE_H  */
Index: tree-ssa-loop-prefetch.c
===================================================================
*** tree-ssa-loop-prefetch.c	(revision 117561)
--- tree-ssa-loop-prefetch.c	(working copy)
*************** issue_prefetch_ref (struct mem_ref *ref,
*** 832,838 ****
    n_prefetches = ((unroll_factor + ref->prefetch_mod - 1)
  		  / ref->prefetch_mod);
    addr_base = build_fold_addr_expr_with_type (ref->mem, ptr_type_node);
!   addr_base = force_gimple_operand_bsi (&bsi, unshare_expr (addr_base), true, NULL);
  
    for (ap = 0; ap < n_prefetches; ap++)
      {
--- 832,839 ----
    n_prefetches = ((unroll_factor + ref->prefetch_mod - 1)
  		  / ref->prefetch_mod);
    addr_base = build_fold_addr_expr_with_type (ref->mem, ptr_type_node);
!   addr_base = force_gimple_operand_bsi (&bsi, unshare_expr (addr_base), true, NULL,
! 					true, BSI_SAME_STMT);
  
    for (ap = 0; ap < n_prefetches; ap++)
      {
*************** issue_prefetch_ref (struct mem_ref *ref,
*** 840,846 ****
        delta = (ahead + ap * ref->prefetch_mod) * ref->group->step;
        addr = fold_build2 (PLUS_EXPR, ptr_type_node,
  			  addr_base, build_int_cst (ptr_type_node, delta));
!       addr = force_gimple_operand_bsi (&bsi, unshare_expr (addr), true, NULL);
  
        /* Create the prefetch instruction.  */
        write_p = ref->write_p ? integer_one_node : integer_zero_node;
--- 841,848 ----
        delta = (ahead + ap * ref->prefetch_mod) * ref->group->step;
        addr = fold_build2 (PLUS_EXPR, ptr_type_node,
  			  addr_base, build_int_cst (ptr_type_node, delta));
!       addr = force_gimple_operand_bsi (&bsi, unshare_expr (addr), true, NULL,
! 				       true, BSI_SAME_STMT);
  
        /* Create the prefetch instruction.  */
        write_p = ref->write_p ? integer_one_node : integer_zero_node;
Index: tree-inline.c
===================================================================
*** tree-inline.c	(revision 117561)
--- tree-inline.c	(working copy)
*************** estimate_num_insns_1 (tree *tp, int *wal
*** 1633,1638 ****
--- 1633,1639 ----
      case OMP_CLAUSE:
      case OMP_RETURN:
      case OMP_CONTINUE:
+     case OMP_SECTIONS_SWITCH:
        break;
  
      /* We don't account constants for now.  Assume that the cost is amortized
Index: tree-outof-ssa.c
===================================================================
*** tree-outof-ssa.c	(revision 117561)
--- tree-outof-ssa.c	(working copy)
*************** create_temp (tree t)
*** 168,181 ****
      }
    DECL_ARTIFICIAL (tmp) = DECL_ARTIFICIAL (t);
    DECL_IGNORED_P (tmp) = DECL_IGNORED_P (t);
-   add_referenced_var (tmp);
- 
-   /* add_referenced_var will create the annotation and set up some
-      of the flags in the annotation.  However, some flags we need to
-      inherit from our original variable.  */
-   var_ann (tmp)->symbol_mem_tag = var_ann (t)->symbol_mem_tag;
-   if (is_call_clobbered (t))
-     mark_call_clobbered (tmp, var_ann (t)->escape_mask);
  
    return tmp;
  }
--- 168,173 ----
*************** insert_copy_on_edge (edge e, tree dest, 
*** 190,201 ****
    tree copy;
  
    copy = build2 (MODIFY_EXPR, TREE_TYPE (dest), dest, src);
-   set_is_used (dest);
  
    if (TREE_CODE (src) == ADDR_EXPR)
      src = TREE_OPERAND (src, 0);
-   if (TREE_CODE (src) == VAR_DECL || TREE_CODE (src) == PARM_DECL)
-     set_is_used (src);
  
    if (dump_file && (dump_flags & TDF_DETAILS))
      {
--- 182,190 ----
*************** coalesce_ssa_name (var_map map, int flag
*** 885,897 ****
    EXECUTE_IF_SET_IN_SBITMAP (live, 0, x, sbi)
      {
        tree var = root_var (rv, root_var_find (rv, x));
-       var_ann_t ann = var_ann (var);
        /* If these aren't already coalesced...  */
        if (partition_to_var (map, x) != var)
  	{
  	  /* This root variable should have not already been assigned
  	     to another partition which is not coalesced with this one.  */
! 	  gcc_assert (!ann->out_of_ssa_tag);
  
  	  if (dump_file && (dump_flags & TDF_DETAILS))
  	    {
--- 874,885 ----
    EXECUTE_IF_SET_IN_SBITMAP (live, 0, x, sbi)
      {
        tree var = root_var (rv, root_var_find (rv, x));
        /* If these aren't already coalesced...  */
        if (partition_to_var (map, x) != var)
  	{
  	  /* This root variable should have not already been assigned
  	     to another partition which is not coalesced with this one.  */
! 	  gcc_assert (!bitmap_bit_p (out_of_ssa, DECL_UID (var)));
  
  	  if (dump_file && (dump_flags & TDF_DETAILS))
  	    {
*************** assign_vars (var_map map)
*** 938,944 ****
  {
    int x, i, num, rep;
    tree t, var;
-   var_ann_t ann;
    root_var_p rv;
  
    rv = root_var_init (map);
--- 926,931 ----
*************** assign_vars (var_map map)
*** 957,964 ****
  	  /* Coalescing will already have verified that more than one
  	     partition doesn't have the same root variable. Simply marked
  	     the variable as assigned.  */
! 	  ann = var_ann (var);
! 	  ann->out_of_ssa_tag = 1;
  	  if (dump_file && (dump_flags & TDF_DETAILS))
  	    {
  	      fprintf (dump_file, "partition %d has variable ", x);
--- 944,950 ----
  	  /* Coalescing will already have verified that more than one
  	     partition doesn't have the same root variable. Simply marked
  	     the variable as assigned.  */
! 	  bitmap_set_bit (out_of_ssa, DECL_UID (var));
  	  if (dump_file && (dump_flags & TDF_DETAILS))
  	    {
  	      fprintf (dump_file, "partition %d has variable ", x);
*************** assign_vars (var_map map)
*** 973,979 ****
    for (x = 0; x < num; x++)
      {
        var = root_var (rv, x);
-       ann = var_ann (var);
        for (i = root_var_first_partition (rv, x);
  	   i != ROOT_VAR_NONE;
  	   i = root_var_next_partition (rv, i))
--- 959,964 ----
*************** assign_vars (var_map map)
*** 985,991 ****
  
  	  rep = var_to_partition (map, t);
  	  
! 	  if (!ann->out_of_ssa_tag)
  	    {
  	      if (dump_file && (dump_flags & TDF_DETAILS))
  		print_exprs (dump_file, "", t, "  --> ", var, "\n");
--- 970,976 ----
  
  	  rep = var_to_partition (map, t);
  	  
! 	  if (!bitmap_bit_p (out_of_ssa, DECL_UID (var)))
  	    {
  	      if (dump_file && (dump_flags & TDF_DETAILS))
  		print_exprs (dump_file, "", t, "  --> ", var, "\n");
*************** assign_vars (var_map map)
*** 999,1005 ****
  
  	  var = create_temp (t);
  	  change_partition_var (map, var, rep);
- 	  ann = var_ann (var);
  
  	  if (dump_file && (dump_flags & TDF_DETAILS))
  	    {
--- 984,989 ----
*************** replace_use_variable (var_map map, use_o
*** 1043,1049 ****
    if (new_var)
      {
        SET_USE (p, new_var);
-       set_is_used (new_var);
        return true;
      }
    return false;
--- 1027,1032 ----
*************** replace_def_variable (var_map map, def_o
*** 1079,1085 ****
    if (new_var)
      {
        SET_DEF (def_p, new_var);
-       set_is_used (new_var);
        return true;
      }
    return false;
--- 1062,1067 ----
*************** insert_backedge_copies (void)
*** 2497,2515 ****
      }
  }
  
! /* Rewrites the current function out of SSA form, leaving it in gimple
     and not freeing any structures.  */
  
  void
! go_out_of_ssa (void)
  {
    var_map map;
  
    insert_backedge_copies ();
    eliminate_virtual_phis ();
    map = create_ssa_var_map (0);
    remove_ssa_form (map, 0);
    delete_var_map (map);
  }
  
  /* Take the current function out of SSA form, as described in
--- 2479,2537 ----
      }
  }
  
! /* Rewrites the function FUN out of SSA form, leaving it in gimple
     and not freeing any structures.  */
  
  void
! go_out_of_ssa (tree fun)
  {
    var_map map;
+   struct function *act_cfun = cfun;
+   tree act_decl = current_function_decl;
+   basic_block bb;
+   block_stmt_iterator bsi;
+   stmt_ann_t ann;
+   use_operand_p use;
+   tree stmt;
+   ssa_op_iter oi;
  
+   cfun = DECL_STRUCT_FUNCTION (fun);
+   current_function_decl = fun;
+ 
+   init_var_partition_map ();
    insert_backedge_copies ();
    eliminate_virtual_phis ();
    map = create_ssa_var_map (0);
    remove_ssa_form (map, 0);
    delete_var_map (map);
+   delete_var_partition_map ();
+ 
+   /* Clean the annotations from the variables.  Go_out_of_ssa is called
+      on code split from the current function, operands of the statements are
+      allocated from the local caches, so we cannot preserve them.  Even if
+      we could, it probably would not be safe due to possible changes to the
+      information stored in the annotations.  */
+   FOR_EACH_BB (bb)
+     {
+       for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
+ 	{
+ 	  stmt = bsi_stmt (bsi);
+ 	  FOR_EACH_SSA_USE_OPERAND (use, stmt, oi,
+ 				    SSA_OP_ALL_USES | SSA_OP_ALL_KILLS)
+ 	    {
+ 	      delink_imm_use (use);
+ 	    }
+ 
+ 	  ann = stmt_ann (bsi_stmt (bsi));
+ 	  memset (ann, 0, sizeof (struct stmt_ann_d));
+ 	  ann->common.type = STMT_ANN;
+ 	  ann->modified = 1;
+ 	  ann->bb = bb;
+ 	}
+     }
+ 
+   cfun = act_cfun;
+   current_function_decl = act_decl;
  }
  
  /* Take the current function out of SSA form, as described in
*************** rewrite_out_of_ssa (void)
*** 2523,2528 ****
--- 2545,2552 ----
    int var_flags = 0;
    int ssa_flags = 0;
  
+   init_var_partition_map ();
+ 
    /* If elimination of a PHI requires inserting a copy on a backedge,
       then we will have to split the backedge which has numerous
       undesirable performance effects.
*************** rewrite_out_of_ssa (void)
*** 2561,2566 ****
--- 2585,2592 ----
    /* Flush out flow graph and SSA data.  */
    delete_var_map (map);
  
+   delete_var_partition_map ();
+ 
    in_ssa_p = false;
    return 0;
  }
Index: tree-profile.c
===================================================================
*** tree-profile.c	(revision 117561)
--- tree-profile.c	(working copy)
*************** prepare_instrumented_value (block_stmt_i
*** 125,131 ****
  {
    tree val = value->hvalue.value;
    return force_gimple_operand_bsi (bsi, fold_convert (gcov_type_node, val),
! 				   true, NULL_TREE);
  }
  
  /* Output instructions as GIMPLE trees to increment the interval histogram 
--- 125,131 ----
  {
    tree val = value->hvalue.value;
    return force_gimple_operand_bsi (bsi, fold_convert (gcov_type_node, val),
! 				   true, NULL_TREE, true, BSI_SAME_STMT);
  }
  
  /* Output instructions as GIMPLE trees to increment the interval histogram 
*************** tree_gen_interval_profiler (histogram_va
*** 144,150 ****
    
    ref_ptr = force_gimple_operand_bsi (&bsi,
  				      build_addr (ref, current_function_decl),
! 				      true, NULL_TREE);
    val = prepare_instrumented_value (&bsi, value);
    args = tree_cons (NULL_TREE, ref_ptr,
  		    tree_cons (NULL_TREE, val,
--- 144,150 ----
    
    ref_ptr = force_gimple_operand_bsi (&bsi,
  				      build_addr (ref, current_function_decl),
! 				      true, NULL_TREE, true, BSI_SAME_STMT);
    val = prepare_instrumented_value (&bsi, value);
    args = tree_cons (NULL_TREE, ref_ptr,
  		    tree_cons (NULL_TREE, val,
*************** tree_gen_pow2_profiler (histogram_value 
*** 169,175 ****
    
    ref_ptr = force_gimple_operand_bsi (&bsi,
  				      build_addr (ref, current_function_decl),
! 				      true, NULL_TREE);
    val = prepare_instrumented_value (&bsi, value);
    args = tree_cons (NULL_TREE, ref_ptr,
  		    tree_cons (NULL_TREE, val,
--- 169,175 ----
    
    ref_ptr = force_gimple_operand_bsi (&bsi,
  				      build_addr (ref, current_function_decl),
! 				      true, NULL_TREE, true, BSI_SAME_STMT);
    val = prepare_instrumented_value (&bsi, value);
    args = tree_cons (NULL_TREE, ref_ptr,
  		    tree_cons (NULL_TREE, val,
*************** tree_gen_one_value_profiler (histogram_v
*** 192,198 ****
    
    ref_ptr = force_gimple_operand_bsi (&bsi,
  				      build_addr (ref, current_function_decl),
! 				      true, NULL_TREE);
    val = prepare_instrumented_value (&bsi, value);
    args = tree_cons (NULL_TREE, ref_ptr,
  		    tree_cons (NULL_TREE, val,
--- 192,198 ----
    
    ref_ptr = force_gimple_operand_bsi (&bsi,
  				      build_addr (ref, current_function_decl),
! 				      true, NULL_TREE, true, BSI_SAME_STMT);
    val = prepare_instrumented_value (&bsi, value);
    args = tree_cons (NULL_TREE, ref_ptr,
  		    tree_cons (NULL_TREE, val,
Index: tree-flow.h
===================================================================
*** tree-flow.h	(revision 117561)
--- tree-flow.h	(working copy)
*************** struct var_ann_d GTY(())
*** 157,169 ****
  {
    struct tree_ann_common_d common;
  
-   /* Used by the out of SSA pass to determine whether this variable has
-      been seen yet or not.  */
-   unsigned out_of_ssa_tag : 1;
- 
-   /* Used when building root_var structures in tree_ssa_live.[ch].  */
-   unsigned root_var_processed : 1;
- 
    /* Nonzero if this variable is in the alias set of another variable.  */
    unsigned is_aliased : 1;
  
--- 157,162 ----
*************** struct var_ann_d GTY(())
*** 193,205 ****
    /* Variables that may alias this variable.  */
    VEC(tree, gc) *may_aliases;
  
-   /* Used when going out of SSA form to indicate which partition this
-      variable represents storage for.  */
-   unsigned partition;
- 
-   /* Used by the root-var object in tree-ssa-live.[ch].  */
-   unsigned root_index;
- 
    /* During into-ssa and the dominator optimizer, this field holds the
       current version of this variable (an SSA_NAME).  */
    tree current_def;
--- 186,191 ----
*************** extern struct omp_region *root_omp_regio
*** 548,553 ****
--- 534,541 ----
  extern struct omp_region *new_omp_region (basic_block, enum tree_code,
  					  struct omp_region *);
  extern void free_omp_regions (void);
+ tree copy_var_decl (tree, tree, tree);
+ tree find_omp_clause (tree, enum tree_code);
  
  /*---------------------------------------------------------------------------
  			      Function prototypes
*************** extern tree get_virtual_var (tree);
*** 637,642 ****
--- 625,632 ----
  extern void add_referenced_var (tree);
  extern void mark_new_vars_to_rename (tree);
  extern void find_new_referenced_vars (tree *);
+ void mark_virtual_ops_for_renaming (tree);
+ void mark_call_virtual_operands (void);
  
  extern tree make_rename_temp (tree, const char *);
  extern void set_default_def (tree, tree);
*************** void mark_sym_for_renaming (tree);
*** 713,719 ****
  void mark_set_for_renaming (bitmap);
  tree get_current_def (tree);
  void set_current_def (tree, tree);
! void go_out_of_ssa (void);
  
  /* In tree-ssa-ccp.c  */
  bool fold_stmt (tree *);
--- 703,709 ----
  void mark_set_for_renaming (bitmap);
  tree get_current_def (tree);
  void set_current_def (tree, tree);
! void go_out_of_ssa (tree);
  
  /* In tree-ssa-ccp.c  */
  bool fold_stmt (tree *);
*************** enum escape_type 
*** 889,895 ****
  /* In tree-flow-inline.h  */
  static inline bool is_call_clobbered (tree);
  static inline void mark_call_clobbered (tree, unsigned int);
- static inline void set_is_used (tree);
  static inline bool unmodifiable_var_p (tree);
  
  /* In tree-eh.c  */
--- 879,884 ----
*************** extern void register_jump_thread (edge, 
*** 947,953 ****
  
  /* In gimplify.c  */
  tree force_gimple_operand (tree, tree *, bool, tree);
! tree force_gimple_operand_bsi (block_stmt_iterator *, tree, bool, tree);
  
  /* In tree-ssa-structalias.c */
  bool find_what_p_points_to (tree);
--- 936,943 ----
  
  /* In gimplify.c  */
  tree force_gimple_operand (tree, tree *, bool, tree);
! tree force_gimple_operand_bsi (block_stmt_iterator *, tree, bool, tree,
! 			       bool, enum bsi_iterator_update);
  
  /* In tree-ssa-structalias.c */
  bool find_what_p_points_to (tree);
Index: tree-cfg.c
===================================================================
*** tree-cfg.c	(revision 117561)
--- tree-cfg.c	(working copy)
*************** make_edges (void)
*** 535,540 ****
--- 535,544 ----
  
  	    case OMP_SECTIONS:
  	      cur_region = new_omp_region (bb, code, cur_region);
+ 	      fallthru = true;
+ 	      break;
+ 
+ 	    case OMP_SECTIONS_SWITCH:
  	      fallthru = false;
  	      break;
  
*************** make_edges (void)
*** 551,581 ****
  	      switch (cur_region->type)
  		{
  		case OMP_FOR:
! 		  /* ??? Technically there should be a some sort of loopback
! 		     edge here, but it goes to a block that doesn't exist yet,
! 		     and without it, updating the ssa form would be a real
! 		     bear.  Fortunately, we don't yet do ssa before expanding
! 		     these nodes.  */
  		  break;
  
  		case OMP_SECTIONS:
  		  /* Wire up the edges into and out of the nested sections.  */
- 		  /* ??? Similarly wrt loopback.  */
  		  {
  		    struct omp_region *i;
  		    for (i = cur_region->inner; i ; i = i->next)
  		      {
  			gcc_assert (i->type == OMP_SECTION);
! 			make_edge (cur_region->entry, i->entry, 0);
  			make_edge (i->exit, bb, EDGE_FALLTHRU);
  		      }
  		  }
  		  break;
  
  		default:
  		  gcc_unreachable ();
  		}
- 	      fallthru = true;
  	      break;
  
  	    default:
--- 555,596 ----
  	      switch (cur_region->type)
  		{
  		case OMP_FOR:
! 		  /* Make the loopback edge.  */
! 		  make_edge (bb, single_succ (cur_region->entry), 0);
! 	      
! 		  /* Create an edge from 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, 0);
! 		  fallthru = true;
  		  break;
  
  		case 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 == OMP_SECTION);
! 			make_edge (switch_bb, i->entry, 0);
  			make_edge (i->exit, bb, EDGE_FALLTHRU);
  		      }
+ 
+ 		    /* Make the loopback edge to the block with
+ 		       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:
*************** tree_redirect_edge_and_branch (edge e, b
*** 4157,4162 ****
--- 4172,4183 ----
        e->flags |= EDGE_FALLTHRU;
        break;
  
+     case OMP_RETURN:
+     case OMP_CONTINUE:
+     case OMP_SECTIONS_SWITCH:
+       /* The edges from OMP constructs can be simply redirected.  */
+       break;
+ 
      default:
        /* Otherwise it must be a fallthru edge, and we don't need to
  	 do anything besides redirecting it.  */
*************** gather_blocks_in_sese_region (basic_bloc
*** 4561,4573 ****
      }
  }
  
  
  struct move_stmt_d
  {
    tree block;
    tree from_context;
    tree to_context;
!   bitmap vars_to_remove;
    htab_t new_label_map;
    bool remap_decls_p;
  };
--- 4582,4642 ----
      }
  }
  
+ /* Replaces *TP with a duplicate (belonging to function TO_CONTEXT).
+    The duplicates are recorded in VARS_MAP.  */
+ 
+ static void
+ replace_by_duplicate_decl (tree *tp, htab_t vars_map, tree to_context)
+ {
+   tree t = *tp, new_t, ddef;
+   struct function *f = DECL_STRUCT_FUNCTION (to_context);
+   struct tree_map in, *out;
+   void **loc;
+ 
+   in.from = t;
+   loc = htab_find_slot_with_hash (vars_map, &in, DECL_UID (t), INSERT);
+ 
+   if (!*loc)
+     {
+       new_t = copy_var_decl (t, DECL_NAME (t), TREE_TYPE (t));
+       DECL_CONTEXT (new_t) = to_context;
+       f->unexpanded_var_list
+ 	      = tree_cons (NULL_TREE, new_t, f->unexpanded_var_list);
+ 
+       out = XNEW (struct tree_map);
+       out->hash = DECL_UID (t);
+       out->from = t;
+       out->to = new_t;
+       *loc = out;
+ 
+       ddef = default_def (t);
+       if (ddef)
+ 	set_default_def (new_t, ddef);
+ 
+       /* Enter the duplicate as a key to the hashtable as well, since
+ 	 SSA names are shared, and we want to avoid replacing their
+ 	 variables repeatedly.  */
+       in.from = new_t;
+       loc = htab_find_slot_with_hash (vars_map, &in, DECL_UID (new_t), INSERT);
+       gcc_assert (!*loc);
+       out = XNEW (struct tree_map);
+       out->hash = DECL_UID (new_t);
+       out->from = new_t;
+       out->to = new_t;
+       *loc = out;
+     }
+   else
+     new_t = ((struct tree_map *) *loc)->to;
+ 
+   *tp = new_t;
+ }
  
  struct move_stmt_d
  {
    tree block;
    tree from_context;
    tree to_context;
!   htab_t vars_map;
    htab_t new_label_map;
    bool remap_decls_p;
  };
*************** static tree
*** 4580,4586 ****
  move_stmt_r (tree *tp, int *walk_subtrees, void *data)
  {
    struct move_stmt_d *p = (struct move_stmt_d *) data;
!   tree t = *tp;
  
    if (p->block && IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (t))))
      TREE_BLOCK (t) = p->block;
--- 4649,4655 ----
  move_stmt_r (tree *tp, int *walk_subtrees, void *data)
  {
    struct move_stmt_d *p = (struct move_stmt_d *) data;
!   tree t = *tp, *dp;
  
    if (p->block && IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (t))))
      TREE_BLOCK (t) = p->block;
*************** move_stmt_r (tree *tp, int *walk_subtree
*** 4605,4611 ****
  	   || TREE_CODE (t) == SSA_NAME)
      {
        if (TREE_CODE (t) == SSA_NAME)
! 	t = SSA_NAME_VAR (t);
  
        if (TREE_CODE (t) == LABEL_DECL)
  	{
--- 4674,4685 ----
  	   || TREE_CODE (t) == SSA_NAME)
      {
        if (TREE_CODE (t) == SSA_NAME)
! 	{
! 	  dp = &SSA_NAME_VAR (t);
! 	  t = SSA_NAME_VAR (t);
! 	}
!       else
! 	dp = tp;
  
        if (TREE_CODE (t) == LABEL_DECL)
  	{
*************** move_stmt_r (tree *tp, int *walk_subtree
*** 4622,4644 ****
  	}
        else if (p->remap_decls_p)
  	{
! 	  DECL_CONTEXT (t) = p->to_context;
! 
! 	  if (TREE_CODE (t) == VAR_DECL)
! 	    {
! 	      struct function *f = DECL_STRUCT_FUNCTION (p->to_context);
! 
! 	      if (!bitmap_bit_p (p->vars_to_remove, DECL_UID (t)))
! 		{
! 		  f->unexpanded_var_list
! 			  = tree_cons (0, t, f->unexpanded_var_list);
! 
! 		  /* Mark T to be removed from the original function,
! 		     otherwise it will be given a DECL_RTL when the
! 		     original function is expanded.  */
! 		  bitmap_set_bit (p->vars_to_remove, DECL_UID (t));
! 		}
! 	    }
  	}
      }
    else if (TYPE_P (t))
--- 4696,4710 ----
  	}
        else if (p->remap_decls_p)
  	{
! 	  /* Replace T with its duplicate.  T should no longer appear in the
! 	     parent function, so this looks wasteful; however, it may appear
! 	     in referenced_vars, and more importantly, as virtual operands of
! 	     statements, and in alias lists of other variables.  It would be
! 	     quite difficult to expunge it from all those places.  ??? It might
! 	     suffice to do this for addressable variables.  */
! 	  if (TREE_CODE (t) == VAR_DECL
! 	      && !is_global_var (t))
! 	    replace_by_duplicate_decl (dp, p->vars_map, p->to_context);
  	}
      }
    else if (TYPE_P (t))
*************** move_stmt_r (tree *tp, int *walk_subtree
*** 4647,4652 ****
--- 4713,4768 ----
    return NULL_TREE;
  }
  
+ /* Marks all virtual operands of statement STMT for renaming.  */
+ 
+ void
+ mark_virtual_ops_for_renaming (tree stmt)
+ {
+   ssa_op_iter iter;
+   tree var;
+ 
+   if (TREE_CODE (stmt) == PHI_NODE)
+     {
+       var = PHI_RESULT (stmt);
+       if (is_gimple_reg (var))
+ 	return;
+ 
+       if (TREE_CODE (var) == SSA_NAME)
+ 	var = SSA_NAME_VAR (var);
+       mark_sym_for_renaming (var);
+       return;
+     }
+ 
+   update_stmt (stmt);
+ 
+   FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, SSA_OP_ALL_VIRTUALS)
+     {
+       if (TREE_CODE (var) == SSA_NAME)
+ 	var = SSA_NAME_VAR (var);
+       mark_sym_for_renaming (var);
+     }
+ }
+ 
+ /* Marks virtual operands of all statements in basic blocks BBS for
+    renaming.  */
+ 
+ static void
+ mark_virtual_ops_in_region (VEC(basic_block,heap) *bbs)
+ {
+   tree phi;
+   block_stmt_iterator bsi;
+   basic_block bb;
+   unsigned i;
+ 
+   for (i = 0; VEC_iterate (basic_block, bbs, i, bb); i++)
+     {
+       for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
+ 	mark_virtual_ops_for_renaming (phi);
+ 
+       for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
+ 	mark_virtual_ops_for_renaming (bsi_stmt (bsi));
+     }
+ }
  
  /* Move basic block BB from function CFUN to function DEST_FN.  The
     block is moved out of the original linked list and placed after
*************** move_stmt_r (tree *tp, int *walk_subtree
*** 4655,4667 ****
     If UPDATE_EDGE_COUNT_P is true, the edge counts on both CFGs is
     updated to reflect the moved edges.
  
!    On exit, local variables that need to be removed from
!    CFUN->UNEXPANDED_VAR_LIST will have been added to VARS_TO_REMOVE.  */
  
  static void
  move_block_to_fn (struct function *dest_cfun, basic_block bb,
  		  basic_block after, bool update_edge_count_p,
! 		  bitmap vars_to_remove, htab_t new_label_map, int eh_offset)
  {
    struct control_flow_graph *cfg;
    edge_iterator ei;
--- 4771,4783 ----
     If UPDATE_EDGE_COUNT_P is true, the edge counts on both CFGs is
     updated to reflect the moved edges.
  
!    The local variables are remapped to new instances, VARS_MAP is used
!    to record the mapping.  */
  
  static void
  move_block_to_fn (struct function *dest_cfun, basic_block bb,
  		  basic_block after, bool update_edge_count_p,
! 		  htab_t vars_map, htab_t new_label_map, int eh_offset)
  {
    struct control_flow_graph *cfg;
    edge_iterator ei;
*************** move_block_to_fn (struct function *dest_
*** 4670,4675 ****
--- 4786,4792 ----
    struct move_stmt_d d;
    unsigned old_len, new_len;
    basic_block *addr;
+   tree phi;
  
    /* Remove BB from dominance structures.  */
    delete_from_dominance_info (CDI_DOMINATORS, bb);
*************** move_block_to_fn (struct function *dest_
*** 4707,4726 ****
    VEC_replace (basic_block, cfg->x_basic_block_info,
                 bb->index, bb);
  
    /* The statements in BB need to be associated with a new TREE_BLOCK.
       Labels need to be associated with a new label-to-block map.  */
    memset (&d, 0, sizeof (d));
!   d.vars_to_remove = vars_to_remove;
  
    for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si))
      {
        tree stmt = bsi_stmt (si);
        int region;
  
-       d.from_context = cfun->decl;
-       d.to_context = dest_cfun->decl;
        d.remap_decls_p = true;
-       d.new_label_map = new_label_map;
        if (TREE_BLOCK (stmt))
  	d.block = DECL_INITIAL (dest_cfun->decl);
  
--- 4824,4864 ----
    VEC_replace (basic_block, cfg->x_basic_block_info,
                 bb->index, bb);
  
+   /* Remap the variables in phi nodes.  */
+   for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
+     {
+       use_operand_p use;
+       tree op = PHI_RESULT (phi);
+       ssa_op_iter oi;
+ 
+       if (!is_gimple_reg (op))
+ 	continue;
+ 
+       replace_by_duplicate_decl (&SSA_NAME_VAR (op), vars_map,
+ 				 dest_cfun->decl);
+       FOR_EACH_PHI_ARG (use, phi, oi, SSA_OP_USE)
+ 	{
+ 	  op = USE_FROM_PTR (use);
+ 	  if (TREE_CODE (op) == SSA_NAME)
+ 	    replace_by_duplicate_decl (&SSA_NAME_VAR (op), vars_map,
+ 				       dest_cfun->decl);
+ 	}
+     }
+ 
    /* The statements in BB need to be associated with a new TREE_BLOCK.
       Labels need to be associated with a new label-to-block map.  */
    memset (&d, 0, sizeof (d));
!   d.vars_map = vars_map;
!   d.from_context = cfun->decl;
!   d.to_context = dest_cfun->decl;
!   d.new_label_map = new_label_map;
  
    for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si))
      {
        tree stmt = bsi_stmt (si);
        int region;
  
        d.remap_decls_p = true;
        if (TREE_BLOCK (stmt))
  	d.block = DECL_INITIAL (dest_cfun->decl);
  
*************** new_label_mapper (tree decl, void *data)
*** 4809,4815 ****
  
    gcc_assert (TREE_CODE (decl) == LABEL_DECL);
  
!   m = xmalloc (sizeof (struct tree_map));
    m->hash = DECL_UID (decl);
    m->from = decl;
    m->to = create_artificial_label ();
--- 4947,4953 ----
  
    gcc_assert (TREE_CODE (decl) == LABEL_DECL);
  
!   m = XNEW (struct tree_map);
    m->hash = DECL_UID (decl);
    m->from = decl;
    m->to = create_artificial_label ();
*************** move_sese_region_to_fn (struct function 
*** 4852,4859 ****
    unsigned i, num_entry_edges, num_exit_edges;
    edge e;
    edge_iterator ei;
!   bitmap vars_to_remove;
!   htab_t new_label_map;
  
    saved_cfun = cfun;
  
--- 4990,4996 ----
    unsigned i, num_entry_edges, num_exit_edges;
    edge e;
    edge_iterator ei;
!   htab_t new_label_map, vars_map;
  
    saved_cfun = cfun;
  
*************** move_sese_region_to_fn (struct function 
*** 4946,4989 ****
  
    cfun = saved_cfun;
  
    /* Move blocks from BBS into DEST_CFUN.  */
    gcc_assert (VEC_length (basic_block, bbs) >= 2);
    after = dest_cfun->cfg->x_entry_block_ptr;
!   vars_to_remove = BITMAP_ALLOC (NULL);
    for (i = 0; VEC_iterate (basic_block, bbs, i, bb); i++)
      {
        /* No need to update edge counts on the last block.  It has
  	 already been updated earlier when we detached the region from
  	 the original CFG.  */
!       move_block_to_fn (dest_cfun, bb, after, bb != exit_bb, vars_to_remove,
  	                new_label_map, eh_offset);
        after = bb;
      }
  
    if (new_label_map)
      htab_delete (new_label_map);
! 
!   /* Remove the variables marked in VARS_TO_REMOVE from
!      CFUN->UNEXPANDED_VAR_LIST.  Otherwise, they will be given a
!      DECL_RTL in the context of CFUN.  */
!   if (!bitmap_empty_p (vars_to_remove))
!     {
!       tree *p;
! 
!       for (p = &cfun->unexpanded_var_list; *p; )
! 	{
! 	  tree var = TREE_VALUE (*p);
! 	  if (bitmap_bit_p (vars_to_remove, DECL_UID (var)))
! 	    {
! 	      *p = TREE_CHAIN (*p);
! 	      continue;
! 	    }
! 
! 	  p = &TREE_CHAIN (*p);
! 	}
!     }
! 
!   BITMAP_FREE (vars_to_remove);
  
    /* Rewire the entry and exit blocks.  The successor to the entry
       block turns into the successor of DEST_FN's ENTRY_BLOCK_PTR in
--- 5083,5110 ----
  
    cfun = saved_cfun;
  
+   /* The ssa form for virtual operands in the source function will have to
+      be repaired.  We do not care for the real operands -- the sese region
+      must be closed with respect to those.  */
+   mark_virtual_ops_in_region (bbs);
+ 
    /* Move blocks from BBS into DEST_CFUN.  */
    gcc_assert (VEC_length (basic_block, bbs) >= 2);
    after = dest_cfun->cfg->x_entry_block_ptr;
!   vars_map = htab_create (17, tree_map_hash, tree_map_eq, free);
    for (i = 0; VEC_iterate (basic_block, bbs, i, bb); i++)
      {
        /* No need to update edge counts on the last block.  It has
  	 already been updated earlier when we detached the region from
  	 the original CFG.  */
!       move_block_to_fn (dest_cfun, bb, after, bb != exit_bb, vars_map,
  	                new_label_map, eh_offset);
        after = bb;
      }
  
    if (new_label_map)
      htab_delete (new_label_map);
!   htab_delete (vars_map);
  
    /* Rewire the entry and exit blocks.  The successor to the entry
       block turns into the successor of DEST_FN's ENTRY_BLOCK_PTR in
Index: passes.c
===================================================================
*** passes.c	(revision 117561)
--- passes.c	(working copy)
*************** init_optimization_passes (void)
*** 474,480 ****
    p = &all_passes;
    NEXT_PASS (pass_fixup_cfg);
    NEXT_PASS (pass_init_datastructures);
!   NEXT_PASS (pass_expand_omp);
    NEXT_PASS (pass_all_optimizations);
    NEXT_PASS (pass_warn_function_noreturn);
    NEXT_PASS (pass_mudflap_2);
--- 474,480 ----
    p = &all_passes;
    NEXT_PASS (pass_fixup_cfg);
    NEXT_PASS (pass_init_datastructures);
!   NEXT_PASS (pass_expand_omp_O0);
    NEXT_PASS (pass_all_optimizations);
    NEXT_PASS (pass_warn_function_noreturn);
    NEXT_PASS (pass_mudflap_2);
*************** init_optimization_passes (void)
*** 491,496 ****
--- 491,497 ----
    NEXT_PASS (pass_create_structure_vars);
    NEXT_PASS (pass_build_ssa);
    NEXT_PASS (pass_may_alias);
+   NEXT_PASS (pass_expand_omp);
    NEXT_PASS (pass_return_slot);
    NEXT_PASS (pass_rename_ssa_copies);
    NEXT_PASS (pass_early_warn_uninitialized);
Index: tree-ssa-reassoc.c
===================================================================
*** tree-ssa-reassoc.c	(revision 117561)
--- tree-ssa-reassoc.c	(working copy)
*************** negate_value (tree tonegate, block_stmt_
*** 1050,1056 ****
  
    tonegate = fold_build1 (NEGATE_EXPR, TREE_TYPE (tonegate), tonegate);
    resultofnegate = force_gimple_operand_bsi (bsi, tonegate, true,
! 					     NULL_TREE);
    VEC_safe_push (tree, heap, broken_up_subtracts, resultofnegate);
    return resultofnegate;
  
--- 1050,1056 ----
  
    tonegate = fold_build1 (NEGATE_EXPR, TREE_TYPE (tonegate), tonegate);
    resultofnegate = force_gimple_operand_bsi (bsi, tonegate, true,
! 					     NULL_TREE, true, BSI_SAME_STMT);
    VEC_safe_push (tree, heap, broken_up_subtracts, resultofnegate);
    return resultofnegate;
  
Index: tree-ssa-operands.c
===================================================================
*** tree-ssa-operands.c	(revision 117561)
--- tree-ssa-operands.c	(working copy)
*************** get_expr_operands (tree stmt, tree *expr
*** 2045,2065 ****
          return;
        }
  
      case BLOCK:
      case FUNCTION_DECL:
      case EXC_PTR_EXPR:
      case FILTER_EXPR:
      case LABEL_DECL:
      case CONST_DECL:
-     case OMP_PARALLEL:
-     case OMP_SECTIONS:
-     case OMP_FOR:
      case OMP_SINGLE:
      case OMP_MASTER:
      case OMP_ORDERED:
      case OMP_CRITICAL:
      case OMP_RETURN:
!     case OMP_CONTINUE:
        /* Expressions that make no memory references.  */
        return;
  
--- 2045,2116 ----
          return;
        }
  
+     case OMP_FOR:
+       {
+ 	tree init = OMP_FOR_INIT (expr);
+ 	tree cond = OMP_FOR_COND (expr);
+ 	tree incr = OMP_FOR_INCR (expr);
+ 	tree c, clauses = OMP_FOR_CLAUSES (stmt);
+ 
+ 	get_expr_operands (stmt, &TREE_OPERAND (init, 0), opf_is_def);
+ 	get_expr_operands (stmt, &TREE_OPERAND (init, 1), opf_none);
+ 	get_expr_operands (stmt, &TREE_OPERAND (cond, 1), opf_none);
+ 	get_expr_operands (stmt, &TREE_OPERAND (TREE_OPERAND (incr, 1), 1),
+ 			   opf_none);
+ 
+ 	c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
+ 	if (c)
+ 	  get_expr_operands (stmt, &OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c),
+ 			     opf_none);
+ 	return;
+       }
+ 
+     case OMP_CONTINUE:
+       {
+ 	get_expr_operands (stmt, &TREE_OPERAND (expr, 0), opf_is_def);
+ 	get_expr_operands (stmt, &TREE_OPERAND (expr, 1), opf_none);
+ 	return;
+       }
+ 
+     case OMP_PARALLEL:
+       {
+ 	tree c, clauses = OMP_PARALLEL_CLAUSES (stmt);
+ 
+ 	if (OMP_PARALLEL_DATA_ARG (stmt))
+ 	  {
+ 	    get_expr_operands (stmt, &OMP_PARALLEL_DATA_ARG (stmt), opf_none);
+ 	    add_to_addressable_set (OMP_PARALLEL_DATA_ARG (stmt),
+ 				    &s_ann->addresses_taken);
+ 	  }
+ 
+ 	c = find_omp_clause (clauses, OMP_CLAUSE_IF);
+ 	if (c)
+ 	  get_expr_operands (stmt, &OMP_CLAUSE_IF_EXPR (c), opf_none);
+ 	c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
+ 	if (c)
+ 	  get_expr_operands (stmt, &OMP_CLAUSE_NUM_THREADS_EXPR (c), opf_none);
+ 	return;
+       }
+ 
+     case OMP_SECTIONS:
+       {
+ 	get_expr_operands (stmt, &OMP_SECTIONS_CONTROL (expr), opf_is_def);
+ 	return;
+       }
+ 
      case BLOCK:
      case FUNCTION_DECL:
      case EXC_PTR_EXPR:
      case FILTER_EXPR:
      case LABEL_DECL:
      case CONST_DECL:
      case OMP_SINGLE:
      case OMP_MASTER:
      case OMP_ORDERED:
      case OMP_CRITICAL:
      case OMP_RETURN:
!     case OMP_SECTION:
!     case OMP_SECTIONS_SWITCH:
        /* Expressions that make no memory references.  */
        return;
  


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]