xref: /dflybsd-src/contrib/gcc-8.0/gcc/omp-expand.c (revision 95059079af47f9a66a175f374f2da1a5020e3255)
138fd1498Szrj /* Expansion pass for OMP directives.  Outlines regions of certain OMP
238fd1498Szrj    directives to separate functions, converts others into explicit calls to the
338fd1498Szrj    runtime library (libgomp) and so forth
438fd1498Szrj 
538fd1498Szrj Copyright (C) 2005-2018 Free Software Foundation, Inc.
638fd1498Szrj 
738fd1498Szrj This file is part of GCC.
838fd1498Szrj 
938fd1498Szrj GCC is free software; you can redistribute it and/or modify it under
1038fd1498Szrj the terms of the GNU General Public License as published by the Free
1138fd1498Szrj Software Foundation; either version 3, or (at your option) any later
1238fd1498Szrj version.
1338fd1498Szrj 
1438fd1498Szrj GCC is distributed in the hope that it will be useful, but WITHOUT ANY
1538fd1498Szrj WARRANTY; without even the implied warranty of MERCHANTABILITY or
1638fd1498Szrj FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1738fd1498Szrj for more details.
1838fd1498Szrj 
1938fd1498Szrj You should have received a copy of the GNU General Public License
2038fd1498Szrj along with GCC; see the file COPYING3.  If not see
2138fd1498Szrj <http://www.gnu.org/licenses/>.  */
2238fd1498Szrj 
2338fd1498Szrj #include "config.h"
2438fd1498Szrj #include "system.h"
2538fd1498Szrj #include "coretypes.h"
2638fd1498Szrj #include "memmodel.h"
2738fd1498Szrj #include "backend.h"
2838fd1498Szrj #include "target.h"
2938fd1498Szrj #include "rtl.h"
3038fd1498Szrj #include "tree.h"
3138fd1498Szrj #include "gimple.h"
3238fd1498Szrj #include "cfghooks.h"
3338fd1498Szrj #include "tree-pass.h"
3438fd1498Szrj #include "ssa.h"
3538fd1498Szrj #include "optabs.h"
3638fd1498Szrj #include "cgraph.h"
3738fd1498Szrj #include "pretty-print.h"
3838fd1498Szrj #include "diagnostic-core.h"
3938fd1498Szrj #include "fold-const.h"
4038fd1498Szrj #include "stor-layout.h"
4138fd1498Szrj #include "cfganal.h"
4238fd1498Szrj #include "internal-fn.h"
4338fd1498Szrj #include "gimplify.h"
4438fd1498Szrj #include "gimple-iterator.h"
4538fd1498Szrj #include "gimplify-me.h"
4638fd1498Szrj #include "gimple-walk.h"
4738fd1498Szrj #include "tree-cfg.h"
4838fd1498Szrj #include "tree-into-ssa.h"
4938fd1498Szrj #include "tree-ssa.h"
5038fd1498Szrj #include "splay-tree.h"
5138fd1498Szrj #include "cfgloop.h"
5238fd1498Szrj #include "omp-general.h"
5338fd1498Szrj #include "omp-offload.h"
5438fd1498Szrj #include "tree-cfgcleanup.h"
5538fd1498Szrj #include "symbol-summary.h"
5638fd1498Szrj #include "gomp-constants.h"
5738fd1498Szrj #include "gimple-pretty-print.h"
5838fd1498Szrj #include "hsa-common.h"
5938fd1498Szrj #include "stringpool.h"
6038fd1498Szrj #include "attribs.h"
6138fd1498Szrj 
6238fd1498Szrj /* OMP region information.  Every parallel and workshare
6338fd1498Szrj    directive is enclosed between two markers, the OMP_* directive
6438fd1498Szrj    and a corresponding GIMPLE_OMP_RETURN statement.  */
6538fd1498Szrj 
6638fd1498Szrj struct omp_region
6738fd1498Szrj {
6838fd1498Szrj   /* The enclosing region.  */
6938fd1498Szrj   struct omp_region *outer;
7038fd1498Szrj 
7138fd1498Szrj   /* First child region.  */
7238fd1498Szrj   struct omp_region *inner;
7338fd1498Szrj 
7438fd1498Szrj   /* Next peer region.  */
7538fd1498Szrj   struct omp_region *next;
7638fd1498Szrj 
7738fd1498Szrj   /* Block containing the omp directive as its last stmt.  */
7838fd1498Szrj   basic_block entry;
7938fd1498Szrj 
8038fd1498Szrj   /* Block containing the GIMPLE_OMP_RETURN as its last stmt.  */
8138fd1498Szrj   basic_block exit;
8238fd1498Szrj 
8338fd1498Szrj   /* Block containing the GIMPLE_OMP_CONTINUE as its last stmt.  */
8438fd1498Szrj   basic_block cont;
8538fd1498Szrj 
8638fd1498Szrj   /* If this is a combined parallel+workshare region, this is a list
8738fd1498Szrj      of additional arguments needed by the combined parallel+workshare
8838fd1498Szrj      library call.  */
8938fd1498Szrj   vec<tree, va_gc> *ws_args;
9038fd1498Szrj 
9138fd1498Szrj   /* The code for the omp directive of this region.  */
9238fd1498Szrj   enum gimple_code type;
9338fd1498Szrj 
9438fd1498Szrj   /* Schedule kind, only used for GIMPLE_OMP_FOR type regions.  */
9538fd1498Szrj   enum omp_clause_schedule_kind sched_kind;
9638fd1498Szrj 
9738fd1498Szrj   /* Schedule modifiers.  */
9838fd1498Szrj   unsigned char sched_modifiers;
9938fd1498Szrj 
10038fd1498Szrj   /* True if this is a combined parallel+workshare region.  */
10138fd1498Szrj   bool is_combined_parallel;
10238fd1498Szrj 
10338fd1498Szrj   /* The ordered stmt if type is GIMPLE_OMP_ORDERED and it has
10438fd1498Szrj      a depend clause.  */
10538fd1498Szrj   gomp_ordered *ord_stmt;
10638fd1498Szrj };
10738fd1498Szrj 
10838fd1498Szrj static struct omp_region *root_omp_region;
10938fd1498Szrj static bool omp_any_child_fn_dumped;
11038fd1498Szrj 
11138fd1498Szrj static void expand_omp_build_assign (gimple_stmt_iterator *, tree, tree,
11238fd1498Szrj 				     bool = false);
11338fd1498Szrj static gphi *find_phi_with_arg_on_edge (tree, edge);
11438fd1498Szrj static void expand_omp (struct omp_region *region);
11538fd1498Szrj 
11638fd1498Szrj /* Return true if REGION is a combined parallel+workshare region.  */
11738fd1498Szrj 
11838fd1498Szrj static inline bool
is_combined_parallel(struct omp_region * region)11938fd1498Szrj is_combined_parallel (struct omp_region *region)
12038fd1498Szrj {
12138fd1498Szrj   return region->is_combined_parallel;
12238fd1498Szrj }
12338fd1498Szrj 
12438fd1498Szrj /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
12538fd1498Szrj    is the immediate dominator of PAR_ENTRY_BB, return true if there
12638fd1498Szrj    are no data dependencies that would prevent expanding the parallel
12738fd1498Szrj    directive at PAR_ENTRY_BB as a combined parallel+workshare region.
12838fd1498Szrj 
12938fd1498Szrj    When expanding a combined parallel+workshare region, the call to
13038fd1498Szrj    the child function may need additional arguments in the case of
13138fd1498Szrj    GIMPLE_OMP_FOR regions.  In some cases, these arguments are
13238fd1498Szrj    computed out of variables passed in from the parent to the child
13338fd1498Szrj    via 'struct .omp_data_s'.  For instance:
13438fd1498Szrj 
13538fd1498Szrj 	#pragma omp parallel for schedule (guided, i * 4)
13638fd1498Szrj 	for (j ...)
13738fd1498Szrj 
13838fd1498Szrj    Is lowered into:
13938fd1498Szrj 
14038fd1498Szrj 	# BLOCK 2 (PAR_ENTRY_BB)
14138fd1498Szrj 	.omp_data_o.i = i;
14238fd1498Szrj 	#pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
14338fd1498Szrj 
14438fd1498Szrj 	# BLOCK 3 (WS_ENTRY_BB)
14538fd1498Szrj 	.omp_data_i = &.omp_data_o;
14638fd1498Szrj 	D.1667 = .omp_data_i->i;
14738fd1498Szrj 	D.1598 = D.1667 * 4;
14838fd1498Szrj 	#pragma omp for schedule (guided, D.1598)
14938fd1498Szrj 
15038fd1498Szrj    When we outline the parallel region, the call to the child function
15138fd1498Szrj    'bar.omp_fn.0' will need the value D.1598 in its argument list, but
15238fd1498Szrj    that value is computed *after* the call site.  So, in principle we
15338fd1498Szrj    cannot do the transformation.
15438fd1498Szrj 
15538fd1498Szrj    To see whether the code in WS_ENTRY_BB blocks the combined
15638fd1498Szrj    parallel+workshare call, we collect all the variables used in the
15738fd1498Szrj    GIMPLE_OMP_FOR header check whether they appear on the LHS of any
15838fd1498Szrj    statement in WS_ENTRY_BB.  If so, then we cannot emit the combined
15938fd1498Szrj    call.
16038fd1498Szrj 
16138fd1498Szrj    FIXME.  If we had the SSA form built at this point, we could merely
16238fd1498Szrj    hoist the code in block 3 into block 2 and be done with it.  But at
16338fd1498Szrj    this point we don't have dataflow information and though we could
16438fd1498Szrj    hack something up here, it is really not worth the aggravation.  */
16538fd1498Szrj 
16638fd1498Szrj static bool
workshare_safe_to_combine_p(basic_block ws_entry_bb)16738fd1498Szrj workshare_safe_to_combine_p (basic_block ws_entry_bb)
16838fd1498Szrj {
16938fd1498Szrj   struct omp_for_data fd;
17038fd1498Szrj   gimple *ws_stmt = last_stmt (ws_entry_bb);
17138fd1498Szrj 
17238fd1498Szrj   if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
17338fd1498Szrj     return true;
17438fd1498Szrj 
17538fd1498Szrj   gcc_assert (gimple_code (ws_stmt) == GIMPLE_OMP_FOR);
17638fd1498Szrj 
17738fd1498Szrj   omp_extract_for_data (as_a <gomp_for *> (ws_stmt), &fd, NULL);
17838fd1498Szrj 
17938fd1498Szrj   if (fd.collapse > 1 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
18038fd1498Szrj     return false;
18138fd1498Szrj   if (fd.iter_type != long_integer_type_node)
18238fd1498Szrj     return false;
18338fd1498Szrj 
18438fd1498Szrj   /* FIXME.  We give up too easily here.  If any of these arguments
18538fd1498Szrj      are not constants, they will likely involve variables that have
18638fd1498Szrj      been mapped into fields of .omp_data_s for sharing with the child
18738fd1498Szrj      function.  With appropriate data flow, it would be possible to
18838fd1498Szrj      see through this.  */
18938fd1498Szrj   if (!is_gimple_min_invariant (fd.loop.n1)
19038fd1498Szrj       || !is_gimple_min_invariant (fd.loop.n2)
19138fd1498Szrj       || !is_gimple_min_invariant (fd.loop.step)
19238fd1498Szrj       || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
19338fd1498Szrj     return false;
19438fd1498Szrj 
19538fd1498Szrj   return true;
19638fd1498Szrj }
19738fd1498Szrj 
19838fd1498Szrj /* Adjust CHUNK_SIZE from SCHEDULE clause, depending on simd modifier
19938fd1498Szrj    presence (SIMD_SCHEDULE).  */
20038fd1498Szrj 
20138fd1498Szrj static tree
omp_adjust_chunk_size(tree chunk_size,bool simd_schedule)20238fd1498Szrj omp_adjust_chunk_size (tree chunk_size, bool simd_schedule)
20338fd1498Szrj {
20438fd1498Szrj   if (!simd_schedule)
20538fd1498Szrj     return chunk_size;
20638fd1498Szrj 
20738fd1498Szrj   poly_uint64 vf = omp_max_vf ();
20838fd1498Szrj   if (known_eq (vf, 1U))
20938fd1498Szrj     return chunk_size;
21038fd1498Szrj 
21138fd1498Szrj   tree type = TREE_TYPE (chunk_size);
21238fd1498Szrj   chunk_size = fold_build2 (PLUS_EXPR, type, chunk_size,
21338fd1498Szrj 			    build_int_cst (type, vf - 1));
21438fd1498Szrj   return fold_build2 (BIT_AND_EXPR, type, chunk_size,
21538fd1498Szrj 		      build_int_cst (type, -vf));
21638fd1498Szrj }
21738fd1498Szrj 
21838fd1498Szrj /* Collect additional arguments needed to emit a combined
21938fd1498Szrj    parallel+workshare call.  WS_STMT is the workshare directive being
22038fd1498Szrj    expanded.  */
22138fd1498Szrj 
22238fd1498Szrj static vec<tree, va_gc> *
get_ws_args_for(gimple * par_stmt,gimple * ws_stmt)22338fd1498Szrj get_ws_args_for (gimple *par_stmt, gimple *ws_stmt)
22438fd1498Szrj {
22538fd1498Szrj   tree t;
22638fd1498Szrj   location_t loc = gimple_location (ws_stmt);
22738fd1498Szrj   vec<tree, va_gc> *ws_args;
22838fd1498Szrj 
22938fd1498Szrj   if (gomp_for *for_stmt = dyn_cast <gomp_for *> (ws_stmt))
23038fd1498Szrj     {
23138fd1498Szrj       struct omp_for_data fd;
23238fd1498Szrj       tree n1, n2;
23338fd1498Szrj 
23438fd1498Szrj       omp_extract_for_data (for_stmt, &fd, NULL);
23538fd1498Szrj       n1 = fd.loop.n1;
23638fd1498Szrj       n2 = fd.loop.n2;
23738fd1498Szrj 
23838fd1498Szrj       if (gimple_omp_for_combined_into_p (for_stmt))
23938fd1498Szrj 	{
24038fd1498Szrj 	  tree innerc
24138fd1498Szrj 	    = omp_find_clause (gimple_omp_parallel_clauses (par_stmt),
24238fd1498Szrj 			       OMP_CLAUSE__LOOPTEMP_);
24338fd1498Szrj 	  gcc_assert (innerc);
24438fd1498Szrj 	  n1 = OMP_CLAUSE_DECL (innerc);
24538fd1498Szrj 	  innerc = omp_find_clause (OMP_CLAUSE_CHAIN (innerc),
24638fd1498Szrj 				    OMP_CLAUSE__LOOPTEMP_);
24738fd1498Szrj 	  gcc_assert (innerc);
24838fd1498Szrj 	  n2 = OMP_CLAUSE_DECL (innerc);
24938fd1498Szrj 	}
25038fd1498Szrj 
25138fd1498Szrj       vec_alloc (ws_args, 3 + (fd.chunk_size != 0));
25238fd1498Szrj 
25338fd1498Szrj       t = fold_convert_loc (loc, long_integer_type_node, n1);
25438fd1498Szrj       ws_args->quick_push (t);
25538fd1498Szrj 
25638fd1498Szrj       t = fold_convert_loc (loc, long_integer_type_node, n2);
25738fd1498Szrj       ws_args->quick_push (t);
25838fd1498Szrj 
25938fd1498Szrj       t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
26038fd1498Szrj       ws_args->quick_push (t);
26138fd1498Szrj 
26238fd1498Szrj       if (fd.chunk_size)
26338fd1498Szrj 	{
26438fd1498Szrj 	  t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
26538fd1498Szrj 	  t = omp_adjust_chunk_size (t, fd.simd_schedule);
26638fd1498Szrj 	  ws_args->quick_push (t);
26738fd1498Szrj 	}
26838fd1498Szrj 
26938fd1498Szrj       return ws_args;
27038fd1498Szrj     }
27138fd1498Szrj   else if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
27238fd1498Szrj     {
27338fd1498Szrj       /* Number of sections is equal to the number of edges from the
27438fd1498Szrj 	 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
27538fd1498Szrj 	 the exit of the sections region.  */
27638fd1498Szrj       basic_block bb = single_succ (gimple_bb (ws_stmt));
27738fd1498Szrj       t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
27838fd1498Szrj       vec_alloc (ws_args, 1);
27938fd1498Szrj       ws_args->quick_push (t);
28038fd1498Szrj       return ws_args;
28138fd1498Szrj     }
28238fd1498Szrj 
28338fd1498Szrj   gcc_unreachable ();
28438fd1498Szrj }
28538fd1498Szrj 
28638fd1498Szrj /* Discover whether REGION is a combined parallel+workshare region.  */
28738fd1498Szrj 
28838fd1498Szrj static void
determine_parallel_type(struct omp_region * region)28938fd1498Szrj determine_parallel_type (struct omp_region *region)
29038fd1498Szrj {
29138fd1498Szrj   basic_block par_entry_bb, par_exit_bb;
29238fd1498Szrj   basic_block ws_entry_bb, ws_exit_bb;
29338fd1498Szrj 
29438fd1498Szrj   if (region == NULL || region->inner == NULL
29538fd1498Szrj       || region->exit == NULL || region->inner->exit == NULL
29638fd1498Szrj       || region->inner->cont == NULL)
29738fd1498Szrj     return;
29838fd1498Szrj 
29938fd1498Szrj   /* We only support parallel+for and parallel+sections.  */
30038fd1498Szrj   if (region->type != GIMPLE_OMP_PARALLEL
30138fd1498Szrj       || (region->inner->type != GIMPLE_OMP_FOR
30238fd1498Szrj 	  && region->inner->type != GIMPLE_OMP_SECTIONS))
30338fd1498Szrj     return;
30438fd1498Szrj 
30538fd1498Szrj   /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
30638fd1498Szrj      WS_EXIT_BB -> PAR_EXIT_BB.  */
30738fd1498Szrj   par_entry_bb = region->entry;
30838fd1498Szrj   par_exit_bb = region->exit;
30938fd1498Szrj   ws_entry_bb = region->inner->entry;
31038fd1498Szrj   ws_exit_bb = region->inner->exit;
31138fd1498Szrj 
31238fd1498Szrj   if (single_succ (par_entry_bb) == ws_entry_bb
31338fd1498Szrj       && single_succ (ws_exit_bb) == par_exit_bb
31438fd1498Szrj       && workshare_safe_to_combine_p (ws_entry_bb)
31538fd1498Szrj       && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
31638fd1498Szrj 	  || (last_and_only_stmt (ws_entry_bb)
31738fd1498Szrj 	      && last_and_only_stmt (par_exit_bb))))
31838fd1498Szrj     {
31938fd1498Szrj       gimple *par_stmt = last_stmt (par_entry_bb);
32038fd1498Szrj       gimple *ws_stmt = last_stmt (ws_entry_bb);
32138fd1498Szrj 
32238fd1498Szrj       if (region->inner->type == GIMPLE_OMP_FOR)
32338fd1498Szrj 	{
32438fd1498Szrj 	  /* If this is a combined parallel loop, we need to determine
32538fd1498Szrj 	     whether or not to use the combined library calls.  There
32638fd1498Szrj 	     are two cases where we do not apply the transformation:
32738fd1498Szrj 	     static loops and any kind of ordered loop.  In the first
32838fd1498Szrj 	     case, we already open code the loop so there is no need
32938fd1498Szrj 	     to do anything else.  In the latter case, the combined
33038fd1498Szrj 	     parallel loop call would still need extra synchronization
33138fd1498Szrj 	     to implement ordered semantics, so there would not be any
33238fd1498Szrj 	     gain in using the combined call.  */
33338fd1498Szrj 	  tree clauses = gimple_omp_for_clauses (ws_stmt);
33438fd1498Szrj 	  tree c = omp_find_clause (clauses, OMP_CLAUSE_SCHEDULE);
33538fd1498Szrj 	  if (c == NULL
33638fd1498Szrj 	      || ((OMP_CLAUSE_SCHEDULE_KIND (c) & OMP_CLAUSE_SCHEDULE_MASK)
33738fd1498Szrj 		  == OMP_CLAUSE_SCHEDULE_STATIC)
33838fd1498Szrj 	      || omp_find_clause (clauses, OMP_CLAUSE_ORDERED))
33938fd1498Szrj 	    {
34038fd1498Szrj 	      region->is_combined_parallel = false;
34138fd1498Szrj 	      region->inner->is_combined_parallel = false;
34238fd1498Szrj 	      return;
34338fd1498Szrj 	    }
34438fd1498Szrj 	}
34538fd1498Szrj 
34638fd1498Szrj       region->is_combined_parallel = true;
34738fd1498Szrj       region->inner->is_combined_parallel = true;
34838fd1498Szrj       region->ws_args = get_ws_args_for (par_stmt, ws_stmt);
34938fd1498Szrj     }
35038fd1498Szrj }
35138fd1498Szrj 
35238fd1498Szrj /* Debugging dumps for parallel regions.  */
35338fd1498Szrj void dump_omp_region (FILE *, struct omp_region *, int);
35438fd1498Szrj void debug_omp_region (struct omp_region *);
35538fd1498Szrj void debug_all_omp_regions (void);
35638fd1498Szrj 
35738fd1498Szrj /* Dump the parallel region tree rooted at REGION.  */
35838fd1498Szrj 
35938fd1498Szrj void
dump_omp_region(FILE * file,struct omp_region * region,int indent)36038fd1498Szrj dump_omp_region (FILE *file, struct omp_region *region, int indent)
36138fd1498Szrj {
36238fd1498Szrj   fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
36338fd1498Szrj 	   gimple_code_name[region->type]);
36438fd1498Szrj 
36538fd1498Szrj   if (region->inner)
36638fd1498Szrj     dump_omp_region (file, region->inner, indent + 4);
36738fd1498Szrj 
36838fd1498Szrj   if (region->cont)
36938fd1498Szrj     {
37038fd1498Szrj       fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
37138fd1498Szrj 	       region->cont->index);
37238fd1498Szrj     }
37338fd1498Szrj 
37438fd1498Szrj   if (region->exit)
37538fd1498Szrj     fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
37638fd1498Szrj 	     region->exit->index);
37738fd1498Szrj   else
37838fd1498Szrj     fprintf (file, "%*s[no exit marker]\n", indent, "");
37938fd1498Szrj 
38038fd1498Szrj   if (region->next)
38138fd1498Szrj     dump_omp_region (file, region->next, indent);
38238fd1498Szrj }
38338fd1498Szrj 
38438fd1498Szrj DEBUG_FUNCTION void
debug_omp_region(struct omp_region * region)38538fd1498Szrj debug_omp_region (struct omp_region *region)
38638fd1498Szrj {
38738fd1498Szrj   dump_omp_region (stderr, region, 0);
38838fd1498Szrj }
38938fd1498Szrj 
39038fd1498Szrj DEBUG_FUNCTION void
debug_all_omp_regions(void)39138fd1498Szrj debug_all_omp_regions (void)
39238fd1498Szrj {
39338fd1498Szrj   dump_omp_region (stderr, root_omp_region, 0);
39438fd1498Szrj }
39538fd1498Szrj 
39638fd1498Szrj /* Create a new parallel region starting at STMT inside region PARENT.  */
39738fd1498Szrj 
39838fd1498Szrj static struct omp_region *
new_omp_region(basic_block bb,enum gimple_code type,struct omp_region * parent)39938fd1498Szrj new_omp_region (basic_block bb, enum gimple_code type,
40038fd1498Szrj 		struct omp_region *parent)
40138fd1498Szrj {
40238fd1498Szrj   struct omp_region *region = XCNEW (struct omp_region);
40338fd1498Szrj 
40438fd1498Szrj   region->outer = parent;
40538fd1498Szrj   region->entry = bb;
40638fd1498Szrj   region->type = type;
40738fd1498Szrj 
40838fd1498Szrj   if (parent)
40938fd1498Szrj     {
41038fd1498Szrj       /* This is a nested region.  Add it to the list of inner
41138fd1498Szrj 	 regions in PARENT.  */
41238fd1498Szrj       region->next = parent->inner;
41338fd1498Szrj       parent->inner = region;
41438fd1498Szrj     }
41538fd1498Szrj   else
41638fd1498Szrj     {
41738fd1498Szrj       /* This is a toplevel region.  Add it to the list of toplevel
41838fd1498Szrj 	 regions in ROOT_OMP_REGION.  */
41938fd1498Szrj       region->next = root_omp_region;
42038fd1498Szrj       root_omp_region = region;
42138fd1498Szrj     }
42238fd1498Szrj 
42338fd1498Szrj   return region;
42438fd1498Szrj }
42538fd1498Szrj 
42638fd1498Szrj /* Release the memory associated with the region tree rooted at REGION.  */
42738fd1498Szrj 
42838fd1498Szrj static void
free_omp_region_1(struct omp_region * region)42938fd1498Szrj free_omp_region_1 (struct omp_region *region)
43038fd1498Szrj {
43138fd1498Szrj   struct omp_region *i, *n;
43238fd1498Szrj 
43338fd1498Szrj   for (i = region->inner; i ; i = n)
43438fd1498Szrj     {
43538fd1498Szrj       n = i->next;
43638fd1498Szrj       free_omp_region_1 (i);
43738fd1498Szrj     }
43838fd1498Szrj 
43938fd1498Szrj   free (region);
44038fd1498Szrj }
44138fd1498Szrj 
44238fd1498Szrj /* Release the memory for the entire omp region tree.  */
44338fd1498Szrj 
44438fd1498Szrj void
omp_free_regions(void)44538fd1498Szrj omp_free_regions (void)
44638fd1498Szrj {
44738fd1498Szrj   struct omp_region *r, *n;
44838fd1498Szrj   for (r = root_omp_region; r ; r = n)
44938fd1498Szrj     {
45038fd1498Szrj       n = r->next;
45138fd1498Szrj       free_omp_region_1 (r);
45238fd1498Szrj     }
45338fd1498Szrj   root_omp_region = NULL;
45438fd1498Szrj }
45538fd1498Szrj 
45638fd1498Szrj /* A convenience function to build an empty GIMPLE_COND with just the
45738fd1498Szrj    condition.  */
45838fd1498Szrj 
45938fd1498Szrj static gcond *
gimple_build_cond_empty(tree cond)46038fd1498Szrj gimple_build_cond_empty (tree cond)
46138fd1498Szrj {
46238fd1498Szrj   enum tree_code pred_code;
46338fd1498Szrj   tree lhs, rhs;
46438fd1498Szrj 
46538fd1498Szrj   gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
46638fd1498Szrj   return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
46738fd1498Szrj }
46838fd1498Szrj 
46938fd1498Szrj /* Return true if a parallel REGION is within a declare target function or
47038fd1498Szrj    within a target region and is not a part of a gridified target.  */
47138fd1498Szrj 
47238fd1498Szrj static bool
parallel_needs_hsa_kernel_p(struct omp_region * region)47338fd1498Szrj parallel_needs_hsa_kernel_p (struct omp_region *region)
47438fd1498Szrj {
47538fd1498Szrj   bool indirect = false;
47638fd1498Szrj   for (region = region->outer; region; region = region->outer)
47738fd1498Szrj     {
47838fd1498Szrj       if (region->type == GIMPLE_OMP_PARALLEL)
47938fd1498Szrj 	indirect = true;
48038fd1498Szrj       else if (region->type == GIMPLE_OMP_TARGET)
48138fd1498Szrj 	{
48238fd1498Szrj 	  gomp_target *tgt_stmt
48338fd1498Szrj 	    = as_a <gomp_target *> (last_stmt (region->entry));
48438fd1498Szrj 
48538fd1498Szrj 	  if (omp_find_clause (gimple_omp_target_clauses (tgt_stmt),
48638fd1498Szrj 			       OMP_CLAUSE__GRIDDIM_))
48738fd1498Szrj 	    return indirect;
48838fd1498Szrj 	  else
48938fd1498Szrj 	    return true;
49038fd1498Szrj 	}
49138fd1498Szrj     }
49238fd1498Szrj 
49338fd1498Szrj   if (lookup_attribute ("omp declare target",
49438fd1498Szrj 			DECL_ATTRIBUTES (current_function_decl)))
49538fd1498Szrj     return true;
49638fd1498Szrj 
49738fd1498Szrj   return false;
49838fd1498Szrj }
49938fd1498Szrj 
50038fd1498Szrj /* Change DECL_CONTEXT of CHILD_FNDECL to that of the parent function.
50138fd1498Szrj    Add CHILD_FNDECL to decl chain of the supercontext of the block
50238fd1498Szrj    ENTRY_BLOCK - this is the block which originally contained the
50338fd1498Szrj    code from which CHILD_FNDECL was created.
50438fd1498Szrj 
50538fd1498Szrj    Together, these actions ensure that the debug info for the outlined
50638fd1498Szrj    function will be emitted with the correct lexical scope.  */
50738fd1498Szrj 
50838fd1498Szrj static void
adjust_context_and_scope(struct omp_region * region,tree entry_block,tree child_fndecl)509*58e805e6Szrj adjust_context_and_scope (struct omp_region *region, tree entry_block,
510*58e805e6Szrj 			  tree child_fndecl)
51138fd1498Szrj {
512*58e805e6Szrj   tree parent_fndecl = NULL_TREE;
513*58e805e6Szrj   gimple *entry_stmt;
514*58e805e6Szrj   /* OMP expansion expands inner regions before outer ones, so if
515*58e805e6Szrj      we e.g. have explicit task region nested in parallel region, when
516*58e805e6Szrj      expanding the task region current_function_decl will be the original
517*58e805e6Szrj      source function, but we actually want to use as context the child
518*58e805e6Szrj      function of the parallel.  */
519*58e805e6Szrj   for (region = region->outer;
520*58e805e6Szrj        region && parent_fndecl == NULL_TREE; region = region->outer)
521*58e805e6Szrj     switch (region->type)
522*58e805e6Szrj       {
523*58e805e6Szrj       case GIMPLE_OMP_PARALLEL:
524*58e805e6Szrj       case GIMPLE_OMP_TASK:
525*58e805e6Szrj 	entry_stmt = last_stmt (region->entry);
526*58e805e6Szrj 	parent_fndecl = gimple_omp_taskreg_child_fn (entry_stmt);
527*58e805e6Szrj 	break;
528*58e805e6Szrj       case GIMPLE_OMP_TARGET:
529*58e805e6Szrj 	entry_stmt = last_stmt (region->entry);
530*58e805e6Szrj 	parent_fndecl
531*58e805e6Szrj 	  = gimple_omp_target_child_fn (as_a <gomp_target *> (entry_stmt));
532*58e805e6Szrj 	break;
533*58e805e6Szrj       default:
534*58e805e6Szrj 	break;
535*58e805e6Szrj       }
536*58e805e6Szrj 
537*58e805e6Szrj   if (parent_fndecl == NULL_TREE)
538*58e805e6Szrj     parent_fndecl = current_function_decl;
539*58e805e6Szrj   DECL_CONTEXT (child_fndecl) = parent_fndecl;
540*58e805e6Szrj 
54138fd1498Szrj   if (entry_block != NULL_TREE && TREE_CODE (entry_block) == BLOCK)
54238fd1498Szrj     {
54338fd1498Szrj       tree b = BLOCK_SUPERCONTEXT (entry_block);
54438fd1498Szrj       if (TREE_CODE (b) == BLOCK)
54538fd1498Szrj         {
54638fd1498Szrj 	  DECL_CHAIN (child_fndecl) = BLOCK_VARS (b);
54738fd1498Szrj 	  BLOCK_VARS (b) = child_fndecl;
54838fd1498Szrj 	}
54938fd1498Szrj     }
55038fd1498Szrj }
55138fd1498Szrj 
55238fd1498Szrj /* Build the function calls to GOMP_parallel_start etc to actually
55338fd1498Szrj    generate the parallel operation.  REGION is the parallel region
55438fd1498Szrj    being expanded.  BB is the block where to insert the code.  WS_ARGS
55538fd1498Szrj    will be set if this is a call to a combined parallel+workshare
55638fd1498Szrj    construct, it contains the list of additional arguments needed by
55738fd1498Szrj    the workshare construct.  */
55838fd1498Szrj 
55938fd1498Szrj static void
expand_parallel_call(struct omp_region * region,basic_block bb,gomp_parallel * entry_stmt,vec<tree,va_gc> * ws_args)56038fd1498Szrj expand_parallel_call (struct omp_region *region, basic_block bb,
56138fd1498Szrj 		      gomp_parallel *entry_stmt,
56238fd1498Szrj 		      vec<tree, va_gc> *ws_args)
56338fd1498Szrj {
56438fd1498Szrj   tree t, t1, t2, val, cond, c, clauses, flags;
56538fd1498Szrj   gimple_stmt_iterator gsi;
56638fd1498Szrj   gimple *stmt;
56738fd1498Szrj   enum built_in_function start_ix;
56838fd1498Szrj   int start_ix2;
56938fd1498Szrj   location_t clause_loc;
57038fd1498Szrj   vec<tree, va_gc> *args;
57138fd1498Szrj 
57238fd1498Szrj   clauses = gimple_omp_parallel_clauses (entry_stmt);
57338fd1498Szrj 
57438fd1498Szrj   /* Determine what flavor of GOMP_parallel we will be
57538fd1498Szrj      emitting.  */
57638fd1498Szrj   start_ix = BUILT_IN_GOMP_PARALLEL;
57738fd1498Szrj   if (is_combined_parallel (region))
57838fd1498Szrj     {
57938fd1498Szrj       switch (region->inner->type)
58038fd1498Szrj 	{
58138fd1498Szrj 	case GIMPLE_OMP_FOR:
58238fd1498Szrj 	  gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
58338fd1498Szrj 	  switch (region->inner->sched_kind)
58438fd1498Szrj 	    {
58538fd1498Szrj 	    case OMP_CLAUSE_SCHEDULE_RUNTIME:
58638fd1498Szrj 	      start_ix2 = 3;
58738fd1498Szrj 	      break;
58838fd1498Szrj 	    case OMP_CLAUSE_SCHEDULE_DYNAMIC:
58938fd1498Szrj 	    case OMP_CLAUSE_SCHEDULE_GUIDED:
59038fd1498Szrj 	      if (region->inner->sched_modifiers
59138fd1498Szrj 		  & OMP_CLAUSE_SCHEDULE_NONMONOTONIC)
59238fd1498Szrj 		{
59338fd1498Szrj 		  start_ix2 = 3 + region->inner->sched_kind;
59438fd1498Szrj 		  break;
59538fd1498Szrj 		}
59638fd1498Szrj 	      /* FALLTHRU */
59738fd1498Szrj 	    default:
59838fd1498Szrj 	      start_ix2 = region->inner->sched_kind;
59938fd1498Szrj 	      break;
60038fd1498Szrj 	    }
60138fd1498Szrj 	  start_ix2 += (int) BUILT_IN_GOMP_PARALLEL_LOOP_STATIC;
60238fd1498Szrj 	  start_ix = (enum built_in_function) start_ix2;
60338fd1498Szrj 	  break;
60438fd1498Szrj 	case GIMPLE_OMP_SECTIONS:
60538fd1498Szrj 	  start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
60638fd1498Szrj 	  break;
60738fd1498Szrj 	default:
60838fd1498Szrj 	  gcc_unreachable ();
60938fd1498Szrj 	}
61038fd1498Szrj     }
61138fd1498Szrj 
61238fd1498Szrj   /* By default, the value of NUM_THREADS is zero (selected at run time)
61338fd1498Szrj      and there is no conditional.  */
61438fd1498Szrj   cond = NULL_TREE;
61538fd1498Szrj   val = build_int_cst (unsigned_type_node, 0);
61638fd1498Szrj   flags = build_int_cst (unsigned_type_node, 0);
61738fd1498Szrj 
61838fd1498Szrj   c = omp_find_clause (clauses, OMP_CLAUSE_IF);
61938fd1498Szrj   if (c)
62038fd1498Szrj     cond = OMP_CLAUSE_IF_EXPR (c);
62138fd1498Szrj 
62238fd1498Szrj   c = omp_find_clause (clauses, OMP_CLAUSE_NUM_THREADS);
62338fd1498Szrj   if (c)
62438fd1498Szrj     {
62538fd1498Szrj       val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
62638fd1498Szrj       clause_loc = OMP_CLAUSE_LOCATION (c);
62738fd1498Szrj     }
62838fd1498Szrj   else
62938fd1498Szrj     clause_loc = gimple_location (entry_stmt);
63038fd1498Szrj 
63138fd1498Szrj   c = omp_find_clause (clauses, OMP_CLAUSE_PROC_BIND);
63238fd1498Szrj   if (c)
63338fd1498Szrj     flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
63438fd1498Szrj 
63538fd1498Szrj   /* Ensure 'val' is of the correct type.  */
63638fd1498Szrj   val = fold_convert_loc (clause_loc, unsigned_type_node, val);
63738fd1498Szrj 
63838fd1498Szrj   /* If we found the clause 'if (cond)', build either
63938fd1498Szrj      (cond != 0) or (cond ? val : 1u).  */
64038fd1498Szrj   if (cond)
64138fd1498Szrj     {
64238fd1498Szrj       cond = gimple_boolify (cond);
64338fd1498Szrj 
64438fd1498Szrj       if (integer_zerop (val))
64538fd1498Szrj 	val = fold_build2_loc (clause_loc,
64638fd1498Szrj 			   EQ_EXPR, unsigned_type_node, cond,
64738fd1498Szrj 			   build_int_cst (TREE_TYPE (cond), 0));
64838fd1498Szrj       else
64938fd1498Szrj 	{
65038fd1498Szrj 	  basic_block cond_bb, then_bb, else_bb;
65138fd1498Szrj 	  edge e, e_then, e_else;
65238fd1498Szrj 	  tree tmp_then, tmp_else, tmp_join, tmp_var;
65338fd1498Szrj 
65438fd1498Szrj 	  tmp_var = create_tmp_var (TREE_TYPE (val));
65538fd1498Szrj 	  if (gimple_in_ssa_p (cfun))
65638fd1498Szrj 	    {
65738fd1498Szrj 	      tmp_then = make_ssa_name (tmp_var);
65838fd1498Szrj 	      tmp_else = make_ssa_name (tmp_var);
65938fd1498Szrj 	      tmp_join = make_ssa_name (tmp_var);
66038fd1498Szrj 	    }
66138fd1498Szrj 	  else
66238fd1498Szrj 	    {
66338fd1498Szrj 	      tmp_then = tmp_var;
66438fd1498Szrj 	      tmp_else = tmp_var;
66538fd1498Szrj 	      tmp_join = tmp_var;
66638fd1498Szrj 	    }
66738fd1498Szrj 
66838fd1498Szrj 	  e = split_block_after_labels (bb);
66938fd1498Szrj 	  cond_bb = e->src;
67038fd1498Szrj 	  bb = e->dest;
67138fd1498Szrj 	  remove_edge (e);
67238fd1498Szrj 
67338fd1498Szrj 	  then_bb = create_empty_bb (cond_bb);
67438fd1498Szrj 	  else_bb = create_empty_bb (then_bb);
67538fd1498Szrj 	  set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
67638fd1498Szrj 	  set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
67738fd1498Szrj 
67838fd1498Szrj 	  stmt = gimple_build_cond_empty (cond);
67938fd1498Szrj 	  gsi = gsi_start_bb (cond_bb);
68038fd1498Szrj 	  gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
68138fd1498Szrj 
68238fd1498Szrj 	  gsi = gsi_start_bb (then_bb);
68338fd1498Szrj 	  expand_omp_build_assign (&gsi, tmp_then, val, true);
68438fd1498Szrj 
68538fd1498Szrj 	  gsi = gsi_start_bb (else_bb);
68638fd1498Szrj 	  expand_omp_build_assign (&gsi, tmp_else,
68738fd1498Szrj 				   build_int_cst (unsigned_type_node, 1),
68838fd1498Szrj 				   true);
68938fd1498Szrj 
69038fd1498Szrj 	  make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
69138fd1498Szrj 	  make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
69238fd1498Szrj 	  add_bb_to_loop (then_bb, cond_bb->loop_father);
69338fd1498Szrj 	  add_bb_to_loop (else_bb, cond_bb->loop_father);
69438fd1498Szrj 	  e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
69538fd1498Szrj 	  e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
69638fd1498Szrj 
69738fd1498Szrj 	  if (gimple_in_ssa_p (cfun))
69838fd1498Szrj 	    {
69938fd1498Szrj 	      gphi *phi = create_phi_node (tmp_join, bb);
70038fd1498Szrj 	      add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
70138fd1498Szrj 	      add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
70238fd1498Szrj 	    }
70338fd1498Szrj 
70438fd1498Szrj 	  val = tmp_join;
70538fd1498Szrj 	}
70638fd1498Szrj 
70738fd1498Szrj       gsi = gsi_start_bb (bb);
70838fd1498Szrj       val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
70938fd1498Szrj 				      false, GSI_CONTINUE_LINKING);
71038fd1498Szrj     }
71138fd1498Szrj 
71238fd1498Szrj   gsi = gsi_last_nondebug_bb (bb);
71338fd1498Szrj   t = gimple_omp_parallel_data_arg (entry_stmt);
71438fd1498Szrj   if (t == NULL)
71538fd1498Szrj     t1 = null_pointer_node;
71638fd1498Szrj   else
71738fd1498Szrj     t1 = build_fold_addr_expr (t);
71838fd1498Szrj   tree child_fndecl = gimple_omp_parallel_child_fn (entry_stmt);
71938fd1498Szrj   t2 = build_fold_addr_expr (child_fndecl);
72038fd1498Szrj 
72138fd1498Szrj   vec_alloc (args, 4 + vec_safe_length (ws_args));
72238fd1498Szrj   args->quick_push (t2);
72338fd1498Szrj   args->quick_push (t1);
72438fd1498Szrj   args->quick_push (val);
72538fd1498Szrj   if (ws_args)
72638fd1498Szrj     args->splice (*ws_args);
72738fd1498Szrj   args->quick_push (flags);
72838fd1498Szrj 
72938fd1498Szrj   t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
73038fd1498Szrj 			       builtin_decl_explicit (start_ix), args);
73138fd1498Szrj 
73238fd1498Szrj   force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
73338fd1498Szrj 			    false, GSI_CONTINUE_LINKING);
73438fd1498Szrj 
73538fd1498Szrj   if (hsa_gen_requested_p ()
73638fd1498Szrj       && parallel_needs_hsa_kernel_p (region))
73738fd1498Szrj     {
73838fd1498Szrj       cgraph_node *child_cnode = cgraph_node::get (child_fndecl);
73938fd1498Szrj       hsa_register_kernel (child_cnode);
74038fd1498Szrj     }
74138fd1498Szrj }
74238fd1498Szrj 
74338fd1498Szrj /* Build the function call to GOMP_task to actually
74438fd1498Szrj    generate the task operation.  BB is the block where to insert the code.  */
74538fd1498Szrj 
74638fd1498Szrj static void
expand_task_call(struct omp_region * region,basic_block bb,gomp_task * entry_stmt)74738fd1498Szrj expand_task_call (struct omp_region *region, basic_block bb,
74838fd1498Szrj 		  gomp_task *entry_stmt)
74938fd1498Szrj {
75038fd1498Szrj   tree t1, t2, t3;
75138fd1498Szrj   gimple_stmt_iterator gsi;
75238fd1498Szrj   location_t loc = gimple_location (entry_stmt);
75338fd1498Szrj 
75438fd1498Szrj   tree clauses = gimple_omp_task_clauses (entry_stmt);
75538fd1498Szrj 
75638fd1498Szrj   tree ifc = omp_find_clause (clauses, OMP_CLAUSE_IF);
75738fd1498Szrj   tree untied = omp_find_clause (clauses, OMP_CLAUSE_UNTIED);
75838fd1498Szrj   tree mergeable = omp_find_clause (clauses, OMP_CLAUSE_MERGEABLE);
75938fd1498Szrj   tree depend = omp_find_clause (clauses, OMP_CLAUSE_DEPEND);
76038fd1498Szrj   tree finalc = omp_find_clause (clauses, OMP_CLAUSE_FINAL);
76138fd1498Szrj   tree priority = omp_find_clause (clauses, OMP_CLAUSE_PRIORITY);
76238fd1498Szrj 
76338fd1498Szrj   unsigned int iflags
76438fd1498Szrj     = (untied ? GOMP_TASK_FLAG_UNTIED : 0)
76538fd1498Szrj       | (mergeable ? GOMP_TASK_FLAG_MERGEABLE : 0)
76638fd1498Szrj       | (depend ? GOMP_TASK_FLAG_DEPEND : 0);
76738fd1498Szrj 
76838fd1498Szrj   bool taskloop_p = gimple_omp_task_taskloop_p (entry_stmt);
76938fd1498Szrj   tree startvar = NULL_TREE, endvar = NULL_TREE, step = NULL_TREE;
77038fd1498Szrj   tree num_tasks = NULL_TREE;
77138fd1498Szrj   bool ull = false;
77238fd1498Szrj   if (taskloop_p)
77338fd1498Szrj     {
77438fd1498Szrj       gimple *g = last_stmt (region->outer->entry);
77538fd1498Szrj       gcc_assert (gimple_code (g) == GIMPLE_OMP_FOR
77638fd1498Szrj 		  && gimple_omp_for_kind (g) == GF_OMP_FOR_KIND_TASKLOOP);
77738fd1498Szrj       struct omp_for_data fd;
77838fd1498Szrj       omp_extract_for_data (as_a <gomp_for *> (g), &fd, NULL);
77938fd1498Szrj       startvar = omp_find_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
78038fd1498Szrj       endvar = omp_find_clause (OMP_CLAUSE_CHAIN (startvar),
78138fd1498Szrj 				OMP_CLAUSE__LOOPTEMP_);
78238fd1498Szrj       startvar = OMP_CLAUSE_DECL (startvar);
78338fd1498Szrj       endvar = OMP_CLAUSE_DECL (endvar);
78438fd1498Szrj       step = fold_convert_loc (loc, fd.iter_type, fd.loop.step);
78538fd1498Szrj       if (fd.loop.cond_code == LT_EXPR)
78638fd1498Szrj 	iflags |= GOMP_TASK_FLAG_UP;
78738fd1498Szrj       tree tclauses = gimple_omp_for_clauses (g);
78838fd1498Szrj       num_tasks = omp_find_clause (tclauses, OMP_CLAUSE_NUM_TASKS);
78938fd1498Szrj       if (num_tasks)
79038fd1498Szrj 	num_tasks = OMP_CLAUSE_NUM_TASKS_EXPR (num_tasks);
79138fd1498Szrj       else
79238fd1498Szrj 	{
79338fd1498Szrj 	  num_tasks = omp_find_clause (tclauses, OMP_CLAUSE_GRAINSIZE);
79438fd1498Szrj 	  if (num_tasks)
79538fd1498Szrj 	    {
79638fd1498Szrj 	      iflags |= GOMP_TASK_FLAG_GRAINSIZE;
79738fd1498Szrj 	      num_tasks = OMP_CLAUSE_GRAINSIZE_EXPR (num_tasks);
79838fd1498Szrj 	    }
79938fd1498Szrj 	  else
80038fd1498Szrj 	    num_tasks = integer_zero_node;
80138fd1498Szrj 	}
80238fd1498Szrj       num_tasks = fold_convert_loc (loc, long_integer_type_node, num_tasks);
80338fd1498Szrj       if (ifc == NULL_TREE)
80438fd1498Szrj 	iflags |= GOMP_TASK_FLAG_IF;
80538fd1498Szrj       if (omp_find_clause (tclauses, OMP_CLAUSE_NOGROUP))
80638fd1498Szrj 	iflags |= GOMP_TASK_FLAG_NOGROUP;
80738fd1498Szrj       ull = fd.iter_type == long_long_unsigned_type_node;
80838fd1498Szrj     }
80938fd1498Szrj   else if (priority)
81038fd1498Szrj     iflags |= GOMP_TASK_FLAG_PRIORITY;
81138fd1498Szrj 
81238fd1498Szrj   tree flags = build_int_cst (unsigned_type_node, iflags);
81338fd1498Szrj 
81438fd1498Szrj   tree cond = boolean_true_node;
81538fd1498Szrj   if (ifc)
81638fd1498Szrj     {
81738fd1498Szrj       if (taskloop_p)
81838fd1498Szrj 	{
81938fd1498Szrj 	  tree t = gimple_boolify (OMP_CLAUSE_IF_EXPR (ifc));
82038fd1498Szrj 	  t = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, t,
82138fd1498Szrj 			       build_int_cst (unsigned_type_node,
82238fd1498Szrj 					      GOMP_TASK_FLAG_IF),
82338fd1498Szrj 			       build_int_cst (unsigned_type_node, 0));
82438fd1498Szrj 	  flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node,
82538fd1498Szrj 				   flags, t);
82638fd1498Szrj 	}
82738fd1498Szrj       else
82838fd1498Szrj 	cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (ifc));
82938fd1498Szrj     }
83038fd1498Szrj 
83138fd1498Szrj   if (finalc)
83238fd1498Szrj     {
83338fd1498Szrj       tree t = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (finalc));
83438fd1498Szrj       t = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, t,
83538fd1498Szrj 			   build_int_cst (unsigned_type_node,
83638fd1498Szrj 					  GOMP_TASK_FLAG_FINAL),
83738fd1498Szrj 			   build_int_cst (unsigned_type_node, 0));
83838fd1498Szrj       flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, t);
83938fd1498Szrj     }
84038fd1498Szrj   if (depend)
84138fd1498Szrj     depend = OMP_CLAUSE_DECL (depend);
84238fd1498Szrj   else
84338fd1498Szrj     depend = build_int_cst (ptr_type_node, 0);
84438fd1498Szrj   if (priority)
84538fd1498Szrj     priority = fold_convert (integer_type_node,
84638fd1498Szrj 			     OMP_CLAUSE_PRIORITY_EXPR (priority));
84738fd1498Szrj   else
84838fd1498Szrj     priority = integer_zero_node;
84938fd1498Szrj 
85038fd1498Szrj   gsi = gsi_last_nondebug_bb (bb);
85138fd1498Szrj   tree t = gimple_omp_task_data_arg (entry_stmt);
85238fd1498Szrj   if (t == NULL)
85338fd1498Szrj     t2 = null_pointer_node;
85438fd1498Szrj   else
85538fd1498Szrj     t2 = build_fold_addr_expr_loc (loc, t);
85638fd1498Szrj   t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
85738fd1498Szrj   t = gimple_omp_task_copy_fn (entry_stmt);
85838fd1498Szrj   if (t == NULL)
85938fd1498Szrj     t3 = null_pointer_node;
86038fd1498Szrj   else
86138fd1498Szrj     t3 = build_fold_addr_expr_loc (loc, t);
86238fd1498Szrj 
86338fd1498Szrj   if (taskloop_p)
86438fd1498Szrj     t = build_call_expr (ull
86538fd1498Szrj 			 ? builtin_decl_explicit (BUILT_IN_GOMP_TASKLOOP_ULL)
86638fd1498Szrj 			 : builtin_decl_explicit (BUILT_IN_GOMP_TASKLOOP),
86738fd1498Szrj 			 11, t1, t2, t3,
86838fd1498Szrj 			 gimple_omp_task_arg_size (entry_stmt),
86938fd1498Szrj 			 gimple_omp_task_arg_align (entry_stmt), flags,
87038fd1498Szrj 			 num_tasks, priority, startvar, endvar, step);
87138fd1498Szrj   else
87238fd1498Szrj     t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
87338fd1498Szrj 			 9, t1, t2, t3,
87438fd1498Szrj 			 gimple_omp_task_arg_size (entry_stmt),
87538fd1498Szrj 			 gimple_omp_task_arg_align (entry_stmt), cond, flags,
87638fd1498Szrj 			 depend, priority);
87738fd1498Szrj 
87838fd1498Szrj   force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
87938fd1498Szrj 			    false, GSI_CONTINUE_LINKING);
88038fd1498Szrj }
88138fd1498Szrj 
88238fd1498Szrj /* Chain all the DECLs in LIST by their TREE_CHAIN fields.  */
88338fd1498Szrj 
88438fd1498Szrj static tree
vec2chain(vec<tree,va_gc> * v)88538fd1498Szrj vec2chain (vec<tree, va_gc> *v)
88638fd1498Szrj {
88738fd1498Szrj   tree chain = NULL_TREE, t;
88838fd1498Szrj   unsigned ix;
88938fd1498Szrj 
89038fd1498Szrj   FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
89138fd1498Szrj     {
89238fd1498Szrj       DECL_CHAIN (t) = chain;
89338fd1498Szrj       chain = t;
89438fd1498Szrj     }
89538fd1498Szrj 
89638fd1498Szrj   return chain;
89738fd1498Szrj }
89838fd1498Szrj 
89938fd1498Szrj /* Remove barriers in REGION->EXIT's block.  Note that this is only
90038fd1498Szrj    valid for GIMPLE_OMP_PARALLEL regions.  Since the end of a parallel region
90138fd1498Szrj    is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
90238fd1498Szrj    left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
90338fd1498Szrj    removed.  */
90438fd1498Szrj 
90538fd1498Szrj static void
remove_exit_barrier(struct omp_region * region)90638fd1498Szrj remove_exit_barrier (struct omp_region *region)
90738fd1498Szrj {
90838fd1498Szrj   gimple_stmt_iterator gsi;
90938fd1498Szrj   basic_block exit_bb;
91038fd1498Szrj   edge_iterator ei;
91138fd1498Szrj   edge e;
91238fd1498Szrj   gimple *stmt;
91338fd1498Szrj   int any_addressable_vars = -1;
91438fd1498Szrj 
91538fd1498Szrj   exit_bb = region->exit;
91638fd1498Szrj 
91738fd1498Szrj   /* If the parallel region doesn't return, we don't have REGION->EXIT
91838fd1498Szrj      block at all.  */
91938fd1498Szrj   if (! exit_bb)
92038fd1498Szrj     return;
92138fd1498Szrj 
92238fd1498Szrj   /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN.  The
92338fd1498Szrj      workshare's GIMPLE_OMP_RETURN will be in a preceding block.  The kinds of
92438fd1498Szrj      statements that can appear in between are extremely limited -- no
92538fd1498Szrj      memory operations at all.  Here, we allow nothing at all, so the
92638fd1498Szrj      only thing we allow to precede this GIMPLE_OMP_RETURN is a label.  */
92738fd1498Szrj   gsi = gsi_last_nondebug_bb (exit_bb);
92838fd1498Szrj   gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
92938fd1498Szrj   gsi_prev_nondebug (&gsi);
93038fd1498Szrj   if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
93138fd1498Szrj     return;
93238fd1498Szrj 
93338fd1498Szrj   FOR_EACH_EDGE (e, ei, exit_bb->preds)
93438fd1498Szrj     {
93538fd1498Szrj       gsi = gsi_last_nondebug_bb (e->src);
93638fd1498Szrj       if (gsi_end_p (gsi))
93738fd1498Szrj 	continue;
93838fd1498Szrj       stmt = gsi_stmt (gsi);
93938fd1498Szrj       if (gimple_code (stmt) == GIMPLE_OMP_RETURN
94038fd1498Szrj 	  && !gimple_omp_return_nowait_p (stmt))
94138fd1498Szrj 	{
94238fd1498Szrj 	  /* OpenMP 3.0 tasks unfortunately prevent this optimization
94338fd1498Szrj 	     in many cases.  If there could be tasks queued, the barrier
94438fd1498Szrj 	     might be needed to let the tasks run before some local
94538fd1498Szrj 	     variable of the parallel that the task uses as shared
94638fd1498Szrj 	     runs out of scope.  The task can be spawned either
94738fd1498Szrj 	     from within current function (this would be easy to check)
94838fd1498Szrj 	     or from some function it calls and gets passed an address
94938fd1498Szrj 	     of such a variable.  */
95038fd1498Szrj 	  if (any_addressable_vars < 0)
95138fd1498Szrj 	    {
95238fd1498Szrj 	      gomp_parallel *parallel_stmt
95338fd1498Szrj 		= as_a <gomp_parallel *> (last_stmt (region->entry));
95438fd1498Szrj 	      tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
95538fd1498Szrj 	      tree local_decls, block, decl;
95638fd1498Szrj 	      unsigned ix;
95738fd1498Szrj 
95838fd1498Szrj 	      any_addressable_vars = 0;
95938fd1498Szrj 	      FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
96038fd1498Szrj 		if (TREE_ADDRESSABLE (decl))
96138fd1498Szrj 		  {
96238fd1498Szrj 		    any_addressable_vars = 1;
96338fd1498Szrj 		    break;
96438fd1498Szrj 		  }
96538fd1498Szrj 	      for (block = gimple_block (stmt);
96638fd1498Szrj 		   !any_addressable_vars
96738fd1498Szrj 		   && block
96838fd1498Szrj 		   && TREE_CODE (block) == BLOCK;
96938fd1498Szrj 		   block = BLOCK_SUPERCONTEXT (block))
97038fd1498Szrj 		{
97138fd1498Szrj 		  for (local_decls = BLOCK_VARS (block);
97238fd1498Szrj 		       local_decls;
97338fd1498Szrj 		       local_decls = DECL_CHAIN (local_decls))
97438fd1498Szrj 		    if (TREE_ADDRESSABLE (local_decls))
97538fd1498Szrj 		      {
97638fd1498Szrj 			any_addressable_vars = 1;
97738fd1498Szrj 			break;
97838fd1498Szrj 		      }
97938fd1498Szrj 		  if (block == gimple_block (parallel_stmt))
98038fd1498Szrj 		    break;
98138fd1498Szrj 		}
98238fd1498Szrj 	    }
98338fd1498Szrj 	  if (!any_addressable_vars)
98438fd1498Szrj 	    gimple_omp_return_set_nowait (stmt);
98538fd1498Szrj 	}
98638fd1498Szrj     }
98738fd1498Szrj }
98838fd1498Szrj 
98938fd1498Szrj static void
remove_exit_barriers(struct omp_region * region)99038fd1498Szrj remove_exit_barriers (struct omp_region *region)
99138fd1498Szrj {
99238fd1498Szrj   if (region->type == GIMPLE_OMP_PARALLEL)
99338fd1498Szrj     remove_exit_barrier (region);
99438fd1498Szrj 
99538fd1498Szrj   if (region->inner)
99638fd1498Szrj     {
99738fd1498Szrj       region = region->inner;
99838fd1498Szrj       remove_exit_barriers (region);
99938fd1498Szrj       while (region->next)
100038fd1498Szrj 	{
100138fd1498Szrj 	  region = region->next;
100238fd1498Szrj 	  remove_exit_barriers (region);
100338fd1498Szrj 	}
100438fd1498Szrj     }
100538fd1498Szrj }
100638fd1498Szrj 
100738fd1498Szrj /* Optimize omp_get_thread_num () and omp_get_num_threads ()
100838fd1498Szrj    calls.  These can't be declared as const functions, but
100938fd1498Szrj    within one parallel body they are constant, so they can be
101038fd1498Szrj    transformed there into __builtin_omp_get_{thread_num,num_threads} ()
101138fd1498Szrj    which are declared const.  Similarly for task body, except
101238fd1498Szrj    that in untied task omp_get_thread_num () can change at any task
101338fd1498Szrj    scheduling point.  */
101438fd1498Szrj 
101538fd1498Szrj static void
optimize_omp_library_calls(gimple * entry_stmt)101638fd1498Szrj optimize_omp_library_calls (gimple *entry_stmt)
101738fd1498Szrj {
101838fd1498Szrj   basic_block bb;
101938fd1498Szrj   gimple_stmt_iterator gsi;
102038fd1498Szrj   tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
102138fd1498Szrj   tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
102238fd1498Szrj   tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
102338fd1498Szrj   tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
102438fd1498Szrj   bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
102538fd1498Szrj 		      && omp_find_clause (gimple_omp_task_clauses (entry_stmt),
102638fd1498Szrj 					  OMP_CLAUSE_UNTIED) != NULL);
102738fd1498Szrj 
102838fd1498Szrj   FOR_EACH_BB_FN (bb, cfun)
102938fd1498Szrj     for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
103038fd1498Szrj       {
103138fd1498Szrj 	gimple *call = gsi_stmt (gsi);
103238fd1498Szrj 	tree decl;
103338fd1498Szrj 
103438fd1498Szrj 	if (is_gimple_call (call)
103538fd1498Szrj 	    && (decl = gimple_call_fndecl (call))
103638fd1498Szrj 	    && DECL_EXTERNAL (decl)
103738fd1498Szrj 	    && TREE_PUBLIC (decl)
103838fd1498Szrj 	    && DECL_INITIAL (decl) == NULL)
103938fd1498Szrj 	  {
104038fd1498Szrj 	    tree built_in;
104138fd1498Szrj 
104238fd1498Szrj 	    if (DECL_NAME (decl) == thr_num_id)
104338fd1498Szrj 	      {
104438fd1498Szrj 		/* In #pragma omp task untied omp_get_thread_num () can change
104538fd1498Szrj 		   during the execution of the task region.  */
104638fd1498Szrj 		if (untied_task)
104738fd1498Szrj 		  continue;
104838fd1498Szrj 		built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
104938fd1498Szrj 	      }
105038fd1498Szrj 	    else if (DECL_NAME (decl) == num_thr_id)
105138fd1498Szrj 	      built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
105238fd1498Szrj 	    else
105338fd1498Szrj 	      continue;
105438fd1498Szrj 
105538fd1498Szrj 	    if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
105638fd1498Szrj 		|| gimple_call_num_args (call) != 0)
105738fd1498Szrj 	      continue;
105838fd1498Szrj 
105938fd1498Szrj 	    if (flag_exceptions && !TREE_NOTHROW (decl))
106038fd1498Szrj 	      continue;
106138fd1498Szrj 
106238fd1498Szrj 	    if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
106338fd1498Szrj 		|| !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
106438fd1498Szrj 					TREE_TYPE (TREE_TYPE (built_in))))
106538fd1498Szrj 	      continue;
106638fd1498Szrj 
106738fd1498Szrj 	    gimple_call_set_fndecl (call, built_in);
106838fd1498Szrj 	  }
106938fd1498Szrj       }
107038fd1498Szrj }
107138fd1498Szrj 
107238fd1498Szrj /* Callback for expand_omp_build_assign.  Return non-NULL if *tp needs to be
107338fd1498Szrj    regimplified.  */
107438fd1498Szrj 
107538fd1498Szrj static tree
expand_omp_regimplify_p(tree * tp,int * walk_subtrees,void *)107638fd1498Szrj expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
107738fd1498Szrj {
107838fd1498Szrj   tree t = *tp;
107938fd1498Szrj 
108038fd1498Szrj   /* Any variable with DECL_VALUE_EXPR needs to be regimplified.  */
108138fd1498Szrj   if (VAR_P (t) && DECL_HAS_VALUE_EXPR_P (t))
108238fd1498Szrj     return t;
108338fd1498Szrj 
108438fd1498Szrj   if (TREE_CODE (t) == ADDR_EXPR)
108538fd1498Szrj     recompute_tree_invariant_for_addr_expr (t);
108638fd1498Szrj 
108738fd1498Szrj   *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
108838fd1498Szrj   return NULL_TREE;
108938fd1498Szrj }
109038fd1498Szrj 
109138fd1498Szrj /* Prepend or append TO = FROM assignment before or after *GSI_P.  */
109238fd1498Szrj 
109338fd1498Szrj static void
expand_omp_build_assign(gimple_stmt_iterator * gsi_p,tree to,tree from,bool after)109438fd1498Szrj expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from,
109538fd1498Szrj 			 bool after)
109638fd1498Szrj {
109738fd1498Szrj   bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
109838fd1498Szrj   from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
109938fd1498Szrj 				   !after, after ? GSI_CONTINUE_LINKING
110038fd1498Szrj 						 : GSI_SAME_STMT);
110138fd1498Szrj   gimple *stmt = gimple_build_assign (to, from);
110238fd1498Szrj   if (after)
110338fd1498Szrj     gsi_insert_after (gsi_p, stmt, GSI_CONTINUE_LINKING);
110438fd1498Szrj   else
110538fd1498Szrj     gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
110638fd1498Szrj   if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
110738fd1498Szrj       || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
110838fd1498Szrj     {
110938fd1498Szrj       gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
111038fd1498Szrj       gimple_regimplify_operands (stmt, &gsi);
111138fd1498Szrj     }
111238fd1498Szrj }
111338fd1498Szrj 
111438fd1498Szrj /* Expand the OpenMP parallel or task directive starting at REGION.  */
111538fd1498Szrj 
111638fd1498Szrj static void
expand_omp_taskreg(struct omp_region * region)111738fd1498Szrj expand_omp_taskreg (struct omp_region *region)
111838fd1498Szrj {
111938fd1498Szrj   basic_block entry_bb, exit_bb, new_bb;
112038fd1498Szrj   struct function *child_cfun;
112138fd1498Szrj   tree child_fn, block, t;
112238fd1498Szrj   gimple_stmt_iterator gsi;
112338fd1498Szrj   gimple *entry_stmt, *stmt;
112438fd1498Szrj   edge e;
112538fd1498Szrj   vec<tree, va_gc> *ws_args;
112638fd1498Szrj 
112738fd1498Szrj   entry_stmt = last_stmt (region->entry);
112838fd1498Szrj   child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
112938fd1498Szrj   child_cfun = DECL_STRUCT_FUNCTION (child_fn);
113038fd1498Szrj 
113138fd1498Szrj   entry_bb = region->entry;
113238fd1498Szrj   if (gimple_code (entry_stmt) == GIMPLE_OMP_TASK)
113338fd1498Szrj     exit_bb = region->cont;
113438fd1498Szrj   else
113538fd1498Szrj     exit_bb = region->exit;
113638fd1498Szrj 
113738fd1498Szrj   if (is_combined_parallel (region))
113838fd1498Szrj     ws_args = region->ws_args;
113938fd1498Szrj   else
114038fd1498Szrj     ws_args = NULL;
114138fd1498Szrj 
114238fd1498Szrj   if (child_cfun->cfg)
114338fd1498Szrj     {
114438fd1498Szrj       /* Due to inlining, it may happen that we have already outlined
114538fd1498Szrj 	 the region, in which case all we need to do is make the
114638fd1498Szrj 	 sub-graph unreachable and emit the parallel call.  */
114738fd1498Szrj       edge entry_succ_e, exit_succ_e;
114838fd1498Szrj 
114938fd1498Szrj       entry_succ_e = single_succ_edge (entry_bb);
115038fd1498Szrj 
115138fd1498Szrj       gsi = gsi_last_nondebug_bb (entry_bb);
115238fd1498Szrj       gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
115338fd1498Szrj 		  || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
115438fd1498Szrj       gsi_remove (&gsi, true);
115538fd1498Szrj 
115638fd1498Szrj       new_bb = entry_bb;
115738fd1498Szrj       if (exit_bb)
115838fd1498Szrj 	{
115938fd1498Szrj 	  exit_succ_e = single_succ_edge (exit_bb);
116038fd1498Szrj 	  make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
116138fd1498Szrj 	}
116238fd1498Szrj       remove_edge_and_dominated_blocks (entry_succ_e);
116338fd1498Szrj     }
116438fd1498Szrj   else
116538fd1498Szrj     {
116638fd1498Szrj       unsigned srcidx, dstidx, num;
116738fd1498Szrj 
116838fd1498Szrj       /* If the parallel region needs data sent from the parent
116938fd1498Szrj 	 function, then the very first statement (except possible
117038fd1498Szrj 	 tree profile counter updates) of the parallel body
117138fd1498Szrj 	 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O.  Since
117238fd1498Szrj 	 &.OMP_DATA_O is passed as an argument to the child function,
117338fd1498Szrj 	 we need to replace it with the argument as seen by the child
117438fd1498Szrj 	 function.
117538fd1498Szrj 
117638fd1498Szrj 	 In most cases, this will end up being the identity assignment
117738fd1498Szrj 	 .OMP_DATA_I = .OMP_DATA_I.  However, if the parallel body had
117838fd1498Szrj 	 a function call that has been inlined, the original PARM_DECL
117938fd1498Szrj 	 .OMP_DATA_I may have been converted into a different local
118038fd1498Szrj 	 variable.  In which case, we need to keep the assignment.  */
118138fd1498Szrj       if (gimple_omp_taskreg_data_arg (entry_stmt))
118238fd1498Szrj 	{
118338fd1498Szrj 	  basic_block entry_succ_bb
118438fd1498Szrj 	    = single_succ_p (entry_bb) ? single_succ (entry_bb)
118538fd1498Szrj 				       : FALLTHRU_EDGE (entry_bb)->dest;
118638fd1498Szrj 	  tree arg;
118738fd1498Szrj 	  gimple *parcopy_stmt = NULL;
118838fd1498Szrj 
118938fd1498Szrj 	  for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
119038fd1498Szrj 	    {
119138fd1498Szrj 	      gimple *stmt;
119238fd1498Szrj 
119338fd1498Szrj 	      gcc_assert (!gsi_end_p (gsi));
119438fd1498Szrj 	      stmt = gsi_stmt (gsi);
119538fd1498Szrj 	      if (gimple_code (stmt) != GIMPLE_ASSIGN)
119638fd1498Szrj 		continue;
119738fd1498Szrj 
119838fd1498Szrj 	      if (gimple_num_ops (stmt) == 2)
119938fd1498Szrj 		{
120038fd1498Szrj 		  tree arg = gimple_assign_rhs1 (stmt);
120138fd1498Szrj 
120238fd1498Szrj 		  /* We're ignore the subcode because we're
120338fd1498Szrj 		     effectively doing a STRIP_NOPS.  */
120438fd1498Szrj 
120538fd1498Szrj 		  if (TREE_CODE (arg) == ADDR_EXPR
120638fd1498Szrj 		      && TREE_OPERAND (arg, 0)
120738fd1498Szrj 			== gimple_omp_taskreg_data_arg (entry_stmt))
120838fd1498Szrj 		    {
120938fd1498Szrj 		      parcopy_stmt = stmt;
121038fd1498Szrj 		      break;
121138fd1498Szrj 		    }
121238fd1498Szrj 		}
121338fd1498Szrj 	    }
121438fd1498Szrj 
121538fd1498Szrj 	  gcc_assert (parcopy_stmt != NULL);
121638fd1498Szrj 	  arg = DECL_ARGUMENTS (child_fn);
121738fd1498Szrj 
121838fd1498Szrj 	  if (!gimple_in_ssa_p (cfun))
121938fd1498Szrj 	    {
122038fd1498Szrj 	      if (gimple_assign_lhs (parcopy_stmt) == arg)
122138fd1498Szrj 		gsi_remove (&gsi, true);
122238fd1498Szrj 	      else
122338fd1498Szrj 		{
122438fd1498Szrj 		  /* ?? Is setting the subcode really necessary ??  */
122538fd1498Szrj 		  gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
122638fd1498Szrj 		  gimple_assign_set_rhs1 (parcopy_stmt, arg);
122738fd1498Szrj 		}
122838fd1498Szrj 	    }
122938fd1498Szrj 	  else
123038fd1498Szrj 	    {
123138fd1498Szrj 	      tree lhs = gimple_assign_lhs (parcopy_stmt);
123238fd1498Szrj 	      gcc_assert (SSA_NAME_VAR (lhs) == arg);
123338fd1498Szrj 	      /* We'd like to set the rhs to the default def in the child_fn,
123438fd1498Szrj 		 but it's too early to create ssa names in the child_fn.
123538fd1498Szrj 		 Instead, we set the rhs to the parm.  In
123638fd1498Szrj 		 move_sese_region_to_fn, we introduce a default def for the
123738fd1498Szrj 		 parm, map the parm to it's default def, and once we encounter
123838fd1498Szrj 		 this stmt, replace the parm with the default def.  */
123938fd1498Szrj 	      gimple_assign_set_rhs1 (parcopy_stmt, arg);
124038fd1498Szrj 	      update_stmt (parcopy_stmt);
124138fd1498Szrj 	    }
124238fd1498Szrj 	}
124338fd1498Szrj 
124438fd1498Szrj       /* Declare local variables needed in CHILD_CFUN.  */
124538fd1498Szrj       block = DECL_INITIAL (child_fn);
124638fd1498Szrj       BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
124738fd1498Szrj       /* The gimplifier could record temporaries in parallel/task block
124838fd1498Szrj 	 rather than in containing function's local_decls chain,
124938fd1498Szrj 	 which would mean cgraph missed finalizing them.  Do it now.  */
125038fd1498Szrj       for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
125138fd1498Szrj 	if (VAR_P (t) && TREE_STATIC (t) && !DECL_EXTERNAL (t))
125238fd1498Szrj 	  varpool_node::finalize_decl (t);
125338fd1498Szrj       DECL_SAVED_TREE (child_fn) = NULL;
125438fd1498Szrj       /* We'll create a CFG for child_fn, so no gimple body is needed.  */
125538fd1498Szrj       gimple_set_body (child_fn, NULL);
125638fd1498Szrj       TREE_USED (block) = 1;
125738fd1498Szrj 
125838fd1498Szrj       /* Reset DECL_CONTEXT on function arguments.  */
125938fd1498Szrj       for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
126038fd1498Szrj 	DECL_CONTEXT (t) = child_fn;
126138fd1498Szrj 
126238fd1498Szrj       /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
126338fd1498Szrj 	 so that it can be moved to the child function.  */
126438fd1498Szrj       gsi = gsi_last_nondebug_bb (entry_bb);
126538fd1498Szrj       stmt = gsi_stmt (gsi);
126638fd1498Szrj       gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
126738fd1498Szrj 			   || gimple_code (stmt) == GIMPLE_OMP_TASK));
126838fd1498Szrj       e = split_block (entry_bb, stmt);
126938fd1498Szrj       gsi_remove (&gsi, true);
127038fd1498Szrj       entry_bb = e->dest;
127138fd1498Szrj       edge e2 = NULL;
127238fd1498Szrj       if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
127338fd1498Szrj 	single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
127438fd1498Szrj       else
127538fd1498Szrj 	{
127638fd1498Szrj 	  e2 = make_edge (e->src, BRANCH_EDGE (entry_bb)->dest, EDGE_ABNORMAL);
127738fd1498Szrj 	  gcc_assert (e2->dest == region->exit);
127838fd1498Szrj 	  remove_edge (BRANCH_EDGE (entry_bb));
127938fd1498Szrj 	  set_immediate_dominator (CDI_DOMINATORS, e2->dest, e->src);
128038fd1498Szrj 	  gsi = gsi_last_nondebug_bb (region->exit);
128138fd1498Szrj 	  gcc_assert (!gsi_end_p (gsi)
128238fd1498Szrj 		      && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
128338fd1498Szrj 	  gsi_remove (&gsi, true);
128438fd1498Szrj 	}
128538fd1498Szrj 
128638fd1498Szrj       /* Convert GIMPLE_OMP_{RETURN,CONTINUE} into a RETURN_EXPR.  */
128738fd1498Szrj       if (exit_bb)
128838fd1498Szrj 	{
128938fd1498Szrj 	  gsi = gsi_last_nondebug_bb (exit_bb);
129038fd1498Szrj 	  gcc_assert (!gsi_end_p (gsi)
129138fd1498Szrj 		      && (gimple_code (gsi_stmt (gsi))
129238fd1498Szrj 			  == (e2 ? GIMPLE_OMP_CONTINUE : GIMPLE_OMP_RETURN)));
129338fd1498Szrj 	  stmt = gimple_build_return (NULL);
129438fd1498Szrj 	  gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
129538fd1498Szrj 	  gsi_remove (&gsi, true);
129638fd1498Szrj 	}
129738fd1498Szrj 
129838fd1498Szrj       /* Move the parallel region into CHILD_CFUN.  */
129938fd1498Szrj 
130038fd1498Szrj       if (gimple_in_ssa_p (cfun))
130138fd1498Szrj 	{
130238fd1498Szrj 	  init_tree_ssa (child_cfun);
130338fd1498Szrj 	  init_ssa_operands (child_cfun);
130438fd1498Szrj 	  child_cfun->gimple_df->in_ssa_p = true;
130538fd1498Szrj 	  block = NULL_TREE;
130638fd1498Szrj 	}
130738fd1498Szrj       else
130838fd1498Szrj 	block = gimple_block (entry_stmt);
130938fd1498Szrj 
131038fd1498Szrj       new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
131138fd1498Szrj       if (exit_bb)
131238fd1498Szrj 	single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
131338fd1498Szrj       if (e2)
131438fd1498Szrj 	{
131538fd1498Szrj 	  basic_block dest_bb = e2->dest;
131638fd1498Szrj 	  if (!exit_bb)
131738fd1498Szrj 	    make_edge (new_bb, dest_bb, EDGE_FALLTHRU);
131838fd1498Szrj 	  remove_edge (e2);
131938fd1498Szrj 	  set_immediate_dominator (CDI_DOMINATORS, dest_bb, new_bb);
132038fd1498Szrj 	}
132138fd1498Szrj       /* When the OMP expansion process cannot guarantee an up-to-date
132238fd1498Szrj 	 loop tree arrange for the child function to fixup loops.  */
132338fd1498Szrj       if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
132438fd1498Szrj 	child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
132538fd1498Szrj 
132638fd1498Szrj       /* Remove non-local VAR_DECLs from child_cfun->local_decls list.  */
132738fd1498Szrj       num = vec_safe_length (child_cfun->local_decls);
132838fd1498Szrj       for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
132938fd1498Szrj 	{
133038fd1498Szrj 	  t = (*child_cfun->local_decls)[srcidx];
133138fd1498Szrj 	  if (DECL_CONTEXT (t) == cfun->decl)
133238fd1498Szrj 	    continue;
133338fd1498Szrj 	  if (srcidx != dstidx)
133438fd1498Szrj 	    (*child_cfun->local_decls)[dstidx] = t;
133538fd1498Szrj 	  dstidx++;
133638fd1498Szrj 	}
133738fd1498Szrj       if (dstidx != num)
133838fd1498Szrj 	vec_safe_truncate (child_cfun->local_decls, dstidx);
133938fd1498Szrj 
134038fd1498Szrj       /* Inform the callgraph about the new function.  */
134138fd1498Szrj       child_cfun->curr_properties = cfun->curr_properties;
134238fd1498Szrj       child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
134338fd1498Szrj       child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
134438fd1498Szrj       cgraph_node *node = cgraph_node::get_create (child_fn);
134538fd1498Szrj       node->parallelized_function = 1;
134638fd1498Szrj       cgraph_node::add_new_function (child_fn, true);
134738fd1498Szrj 
134838fd1498Szrj       bool need_asm = DECL_ASSEMBLER_NAME_SET_P (current_function_decl)
134938fd1498Szrj 		      && !DECL_ASSEMBLER_NAME_SET_P (child_fn);
135038fd1498Szrj 
135138fd1498Szrj       /* Fix the callgraph edges for child_cfun.  Those for cfun will be
135238fd1498Szrj 	 fixed in a following pass.  */
135338fd1498Szrj       push_cfun (child_cfun);
135438fd1498Szrj       if (need_asm)
135538fd1498Szrj 	assign_assembler_name_if_needed (child_fn);
135638fd1498Szrj 
135738fd1498Szrj       if (optimize)
135838fd1498Szrj 	optimize_omp_library_calls (entry_stmt);
135938fd1498Szrj       update_max_bb_count ();
136038fd1498Szrj       cgraph_edge::rebuild_edges ();
136138fd1498Szrj 
136238fd1498Szrj       /* Some EH regions might become dead, see PR34608.  If
136338fd1498Szrj 	 pass_cleanup_cfg isn't the first pass to happen with the
136438fd1498Szrj 	 new child, these dead EH edges might cause problems.
136538fd1498Szrj 	 Clean them up now.  */
136638fd1498Szrj       if (flag_exceptions)
136738fd1498Szrj 	{
136838fd1498Szrj 	  basic_block bb;
136938fd1498Szrj 	  bool changed = false;
137038fd1498Szrj 
137138fd1498Szrj 	  FOR_EACH_BB_FN (bb, cfun)
137238fd1498Szrj 	    changed |= gimple_purge_dead_eh_edges (bb);
137338fd1498Szrj 	  if (changed)
137438fd1498Szrj 	    cleanup_tree_cfg ();
137538fd1498Szrj 	}
137638fd1498Szrj       if (gimple_in_ssa_p (cfun))
137738fd1498Szrj 	update_ssa (TODO_update_ssa);
137838fd1498Szrj       if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
137938fd1498Szrj 	verify_loop_structure ();
138038fd1498Szrj       pop_cfun ();
138138fd1498Szrj 
138238fd1498Szrj       if (dump_file && !gimple_in_ssa_p (cfun))
138338fd1498Szrj 	{
138438fd1498Szrj 	  omp_any_child_fn_dumped = true;
138538fd1498Szrj 	  dump_function_header (dump_file, child_fn, dump_flags);
138638fd1498Szrj 	  dump_function_to_file (child_fn, dump_file, dump_flags);
138738fd1498Szrj 	}
138838fd1498Szrj     }
138938fd1498Szrj 
1390*58e805e6Szrj   adjust_context_and_scope (region, gimple_block (entry_stmt), child_fn);
1391*58e805e6Szrj 
139238fd1498Szrj   if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
139338fd1498Szrj     expand_parallel_call (region, new_bb,
139438fd1498Szrj 			  as_a <gomp_parallel *> (entry_stmt), ws_args);
139538fd1498Szrj   else
139638fd1498Szrj     expand_task_call (region, new_bb, as_a <gomp_task *> (entry_stmt));
139738fd1498Szrj   if (gimple_in_ssa_p (cfun))
139838fd1498Szrj     update_ssa (TODO_update_ssa_only_virtuals);
139938fd1498Szrj }
140038fd1498Szrj 
140138fd1498Szrj /* Information about members of an OpenACC collapsed loop nest.  */
140238fd1498Szrj 
140338fd1498Szrj struct oacc_collapse
140438fd1498Szrj {
140538fd1498Szrj   tree base;  /* Base value.  */
140638fd1498Szrj   tree iters; /* Number of steps.  */
140738fd1498Szrj   tree step;  /* Step size.  */
140838fd1498Szrj   tree tile;  /* Tile increment (if tiled).  */
140938fd1498Szrj   tree outer; /* Tile iterator var. */
141038fd1498Szrj };
141138fd1498Szrj 
141238fd1498Szrj /* Helper for expand_oacc_for.  Determine collapsed loop information.
141338fd1498Szrj    Fill in COUNTS array.  Emit any initialization code before GSI.
141438fd1498Szrj    Return the calculated outer loop bound of BOUND_TYPE.  */
141538fd1498Szrj 
141638fd1498Szrj static tree
expand_oacc_collapse_init(const struct omp_for_data * fd,gimple_stmt_iterator * gsi,oacc_collapse * counts,tree bound_type,location_t loc)141738fd1498Szrj expand_oacc_collapse_init (const struct omp_for_data *fd,
141838fd1498Szrj 			   gimple_stmt_iterator *gsi,
141938fd1498Szrj 			   oacc_collapse *counts, tree bound_type,
142038fd1498Szrj 			   location_t loc)
142138fd1498Szrj {
142238fd1498Szrj   tree tiling = fd->tiling;
142338fd1498Szrj   tree total = build_int_cst (bound_type, 1);
142438fd1498Szrj   int ix;
142538fd1498Szrj 
142638fd1498Szrj   gcc_assert (integer_onep (fd->loop.step));
142738fd1498Szrj   gcc_assert (integer_zerop (fd->loop.n1));
142838fd1498Szrj 
142938fd1498Szrj   /* When tiling, the first operand of the tile clause applies to the
143038fd1498Szrj      innermost loop, and we work outwards from there.  Seems
143138fd1498Szrj      backwards, but whatever.  */
143238fd1498Szrj   for (ix = fd->collapse; ix--;)
143338fd1498Szrj     {
143438fd1498Szrj       const omp_for_data_loop *loop = &fd->loops[ix];
143538fd1498Szrj 
143638fd1498Szrj       tree iter_type = TREE_TYPE (loop->v);
143738fd1498Szrj       tree diff_type = iter_type;
143838fd1498Szrj       tree plus_type = iter_type;
143938fd1498Szrj 
144038fd1498Szrj       gcc_assert (loop->cond_code == fd->loop.cond_code);
144138fd1498Szrj 
144238fd1498Szrj       if (POINTER_TYPE_P (iter_type))
144338fd1498Szrj 	plus_type = sizetype;
144438fd1498Szrj       if (POINTER_TYPE_P (diff_type) || TYPE_UNSIGNED (diff_type))
144538fd1498Szrj 	diff_type = signed_type_for (diff_type);
144638fd1498Szrj       if (TYPE_PRECISION (diff_type) < TYPE_PRECISION (integer_type_node))
144738fd1498Szrj 	diff_type = integer_type_node;
144838fd1498Szrj 
144938fd1498Szrj       if (tiling)
145038fd1498Szrj 	{
145138fd1498Szrj 	  tree num = build_int_cst (integer_type_node, fd->collapse);
145238fd1498Szrj 	  tree loop_no = build_int_cst (integer_type_node, ix);
145338fd1498Szrj 	  tree tile = TREE_VALUE (tiling);
145438fd1498Szrj 	  gcall *call
145538fd1498Szrj 	    = gimple_build_call_internal (IFN_GOACC_TILE, 5, num, loop_no, tile,
145638fd1498Szrj 					  /* gwv-outer=*/integer_zero_node,
145738fd1498Szrj 					  /* gwv-inner=*/integer_zero_node);
145838fd1498Szrj 
145938fd1498Szrj 	  counts[ix].outer = create_tmp_var (iter_type, ".outer");
146038fd1498Szrj 	  counts[ix].tile = create_tmp_var (diff_type, ".tile");
146138fd1498Szrj 	  gimple_call_set_lhs (call, counts[ix].tile);
146238fd1498Szrj 	  gimple_set_location (call, loc);
146338fd1498Szrj 	  gsi_insert_before (gsi, call, GSI_SAME_STMT);
146438fd1498Szrj 
146538fd1498Szrj 	  tiling = TREE_CHAIN (tiling);
146638fd1498Szrj 	}
146738fd1498Szrj       else
146838fd1498Szrj 	{
146938fd1498Szrj 	  counts[ix].tile = NULL;
147038fd1498Szrj 	  counts[ix].outer = loop->v;
147138fd1498Szrj 	}
147238fd1498Szrj 
147338fd1498Szrj       tree b = loop->n1;
147438fd1498Szrj       tree e = loop->n2;
147538fd1498Szrj       tree s = loop->step;
147638fd1498Szrj       bool up = loop->cond_code == LT_EXPR;
147738fd1498Szrj       tree dir = build_int_cst (diff_type, up ? +1 : -1);
147838fd1498Szrj       bool negating;
147938fd1498Szrj       tree expr;
148038fd1498Szrj 
148138fd1498Szrj       b = force_gimple_operand_gsi (gsi, b, true, NULL_TREE,
148238fd1498Szrj 				    true, GSI_SAME_STMT);
148338fd1498Szrj       e = force_gimple_operand_gsi (gsi, e, true, NULL_TREE,
148438fd1498Szrj 				    true, GSI_SAME_STMT);
148538fd1498Szrj 
148638fd1498Szrj       /* Convert the step, avoiding possible unsigned->signed overflow.  */
148738fd1498Szrj       negating = !up && TYPE_UNSIGNED (TREE_TYPE (s));
148838fd1498Szrj       if (negating)
148938fd1498Szrj 	s = fold_build1 (NEGATE_EXPR, TREE_TYPE (s), s);
149038fd1498Szrj       s = fold_convert (diff_type, s);
149138fd1498Szrj       if (negating)
149238fd1498Szrj 	s = fold_build1 (NEGATE_EXPR, diff_type, s);
149338fd1498Szrj       s = force_gimple_operand_gsi (gsi, s, true, NULL_TREE,
149438fd1498Szrj 				    true, GSI_SAME_STMT);
149538fd1498Szrj 
149638fd1498Szrj       /* Determine the range, avoiding possible unsigned->signed overflow.  */
149738fd1498Szrj       negating = !up && TYPE_UNSIGNED (iter_type);
149838fd1498Szrj       expr = fold_build2 (MINUS_EXPR, plus_type,
149938fd1498Szrj 			  fold_convert (plus_type, negating ? b : e),
150038fd1498Szrj 			  fold_convert (plus_type, negating ? e : b));
150138fd1498Szrj       expr = fold_convert (diff_type, expr);
150238fd1498Szrj       if (negating)
150338fd1498Szrj 	expr = fold_build1 (NEGATE_EXPR, diff_type, expr);
150438fd1498Szrj       tree range = force_gimple_operand_gsi
150538fd1498Szrj 	(gsi, expr, true, NULL_TREE, true, GSI_SAME_STMT);
150638fd1498Szrj 
150738fd1498Szrj       /* Determine number of iterations.  */
150838fd1498Szrj       expr = fold_build2 (MINUS_EXPR, diff_type, range, dir);
150938fd1498Szrj       expr = fold_build2 (PLUS_EXPR, diff_type, expr, s);
151038fd1498Szrj       expr = fold_build2 (TRUNC_DIV_EXPR, diff_type, expr, s);
151138fd1498Szrj 
151238fd1498Szrj       tree iters = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE,
151338fd1498Szrj 					     true, GSI_SAME_STMT);
151438fd1498Szrj 
151538fd1498Szrj       counts[ix].base = b;
151638fd1498Szrj       counts[ix].iters = iters;
151738fd1498Szrj       counts[ix].step = s;
151838fd1498Szrj 
151938fd1498Szrj       total = fold_build2 (MULT_EXPR, bound_type, total,
152038fd1498Szrj 			   fold_convert (bound_type, iters));
152138fd1498Szrj     }
152238fd1498Szrj 
152338fd1498Szrj   return total;
152438fd1498Szrj }
152538fd1498Szrj 
152638fd1498Szrj /* Emit initializers for collapsed loop members.  INNER is true if
152738fd1498Szrj    this is for the element loop of a TILE.  IVAR is the outer
152838fd1498Szrj    loop iteration variable, from which collapsed loop iteration values
152938fd1498Szrj    are  calculated.  COUNTS array has been initialized by
153038fd1498Szrj    expand_oacc_collapse_inits.  */
153138fd1498Szrj 
153238fd1498Szrj static void
expand_oacc_collapse_vars(const struct omp_for_data * fd,bool inner,gimple_stmt_iterator * gsi,const oacc_collapse * counts,tree ivar)153338fd1498Szrj expand_oacc_collapse_vars (const struct omp_for_data *fd, bool inner,
153438fd1498Szrj 			   gimple_stmt_iterator *gsi,
153538fd1498Szrj 			   const oacc_collapse *counts, tree ivar)
153638fd1498Szrj {
153738fd1498Szrj   tree ivar_type = TREE_TYPE (ivar);
153838fd1498Szrj 
153938fd1498Szrj   /*  The most rapidly changing iteration variable is the innermost
154038fd1498Szrj       one.  */
154138fd1498Szrj   for (int ix = fd->collapse; ix--;)
154238fd1498Szrj     {
154338fd1498Szrj       const omp_for_data_loop *loop = &fd->loops[ix];
154438fd1498Szrj       const oacc_collapse *collapse = &counts[ix];
154538fd1498Szrj       tree v = inner ? loop->v : collapse->outer;
154638fd1498Szrj       tree iter_type = TREE_TYPE (v);
154738fd1498Szrj       tree diff_type = TREE_TYPE (collapse->step);
154838fd1498Szrj       tree plus_type = iter_type;
154938fd1498Szrj       enum tree_code plus_code = PLUS_EXPR;
155038fd1498Szrj       tree expr;
155138fd1498Szrj 
155238fd1498Szrj       if (POINTER_TYPE_P (iter_type))
155338fd1498Szrj 	{
155438fd1498Szrj 	  plus_code = POINTER_PLUS_EXPR;
155538fd1498Szrj 	  plus_type = sizetype;
155638fd1498Szrj 	}
155738fd1498Szrj 
155838fd1498Szrj       expr = ivar;
155938fd1498Szrj       if (ix)
156038fd1498Szrj 	{
156138fd1498Szrj 	  tree mod = fold_convert (ivar_type, collapse->iters);
156238fd1498Szrj 	  ivar = fold_build2 (TRUNC_DIV_EXPR, ivar_type, expr, mod);
156338fd1498Szrj 	  expr = fold_build2 (TRUNC_MOD_EXPR, ivar_type, expr, mod);
156438fd1498Szrj 	  ivar = force_gimple_operand_gsi (gsi, ivar, true, NULL_TREE,
156538fd1498Szrj 					   true, GSI_SAME_STMT);
156638fd1498Szrj 	}
156738fd1498Szrj 
156838fd1498Szrj       expr = fold_build2 (MULT_EXPR, diff_type, fold_convert (diff_type, expr),
156938fd1498Szrj 			  collapse->step);
157038fd1498Szrj       expr = fold_build2 (plus_code, iter_type,
157138fd1498Szrj 			  inner ? collapse->outer : collapse->base,
157238fd1498Szrj 			  fold_convert (plus_type, expr));
157338fd1498Szrj       expr = force_gimple_operand_gsi (gsi, expr, false, NULL_TREE,
157438fd1498Szrj 				       true, GSI_SAME_STMT);
157538fd1498Szrj       gassign *ass = gimple_build_assign (v, expr);
157638fd1498Szrj       gsi_insert_before (gsi, ass, GSI_SAME_STMT);
157738fd1498Szrj     }
157838fd1498Szrj }
157938fd1498Szrj 
158038fd1498Szrj /* Helper function for expand_omp_{for_*,simd}.  If this is the outermost
158138fd1498Szrj    of the combined collapse > 1 loop constructs, generate code like:
158238fd1498Szrj 	if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
158338fd1498Szrj 	if (cond3 is <)
158438fd1498Szrj 	  adj = STEP3 - 1;
158538fd1498Szrj 	else
158638fd1498Szrj 	  adj = STEP3 + 1;
158738fd1498Szrj 	count3 = (adj + N32 - N31) / STEP3;
158838fd1498Szrj 	if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
158938fd1498Szrj 	if (cond2 is <)
159038fd1498Szrj 	  adj = STEP2 - 1;
159138fd1498Szrj 	else
159238fd1498Szrj 	  adj = STEP2 + 1;
159338fd1498Szrj 	count2 = (adj + N22 - N21) / STEP2;
159438fd1498Szrj 	if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
159538fd1498Szrj 	if (cond1 is <)
159638fd1498Szrj 	  adj = STEP1 - 1;
159738fd1498Szrj 	else
159838fd1498Szrj 	  adj = STEP1 + 1;
159938fd1498Szrj 	count1 = (adj + N12 - N11) / STEP1;
160038fd1498Szrj 	count = count1 * count2 * count3;
160138fd1498Szrj    Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
160238fd1498Szrj 	count = 0;
160338fd1498Szrj    and set ZERO_ITER_BB to that bb.  If this isn't the outermost
160438fd1498Szrj    of the combined loop constructs, just initialize COUNTS array
160538fd1498Szrj    from the _looptemp_ clauses.  */
160638fd1498Szrj 
160738fd1498Szrj /* NOTE: It *could* be better to moosh all of the BBs together,
160838fd1498Szrj    creating one larger BB with all the computation and the unexpected
160938fd1498Szrj    jump at the end.  I.e.
161038fd1498Szrj 
161138fd1498Szrj    bool zero3, zero2, zero1, zero;
161238fd1498Szrj 
161338fd1498Szrj    zero3 = N32 c3 N31;
161438fd1498Szrj    count3 = (N32 - N31) /[cl] STEP3;
161538fd1498Szrj    zero2 = N22 c2 N21;
161638fd1498Szrj    count2 = (N22 - N21) /[cl] STEP2;
161738fd1498Szrj    zero1 = N12 c1 N11;
161838fd1498Szrj    count1 = (N12 - N11) /[cl] STEP1;
161938fd1498Szrj    zero = zero3 || zero2 || zero1;
162038fd1498Szrj    count = count1 * count2 * count3;
162138fd1498Szrj    if (__builtin_expect(zero, false)) goto zero_iter_bb;
162238fd1498Szrj 
162338fd1498Szrj    After all, we expect the zero=false, and thus we expect to have to
162438fd1498Szrj    evaluate all of the comparison expressions, so short-circuiting
162538fd1498Szrj    oughtn't be a win.  Since the condition isn't protecting a
162638fd1498Szrj    denominator, we're not concerned about divide-by-zero, so we can
162738fd1498Szrj    fully evaluate count even if a numerator turned out to be wrong.
162838fd1498Szrj 
162938fd1498Szrj    It seems like putting this all together would create much better
163038fd1498Szrj    scheduling opportunities, and less pressure on the chip's branch
163138fd1498Szrj    predictor.  */
163238fd1498Szrj 
163338fd1498Szrj static void
expand_omp_for_init_counts(struct omp_for_data * fd,gimple_stmt_iterator * gsi,basic_block & entry_bb,tree * counts,basic_block & zero_iter1_bb,int & first_zero_iter1,basic_block & zero_iter2_bb,int & first_zero_iter2,basic_block & l2_dom_bb)163438fd1498Szrj expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
163538fd1498Szrj 			    basic_block &entry_bb, tree *counts,
163638fd1498Szrj 			    basic_block &zero_iter1_bb, int &first_zero_iter1,
163738fd1498Szrj 			    basic_block &zero_iter2_bb, int &first_zero_iter2,
163838fd1498Szrj 			    basic_block &l2_dom_bb)
163938fd1498Szrj {
164038fd1498Szrj   tree t, type = TREE_TYPE (fd->loop.v);
164138fd1498Szrj   edge e, ne;
164238fd1498Szrj   int i;
164338fd1498Szrj 
164438fd1498Szrj   /* Collapsed loops need work for expansion into SSA form.  */
164538fd1498Szrj   gcc_assert (!gimple_in_ssa_p (cfun));
164638fd1498Szrj 
164738fd1498Szrj   if (gimple_omp_for_combined_into_p (fd->for_stmt)
164838fd1498Szrj       && TREE_CODE (fd->loop.n2) != INTEGER_CST)
164938fd1498Szrj     {
165038fd1498Szrj       gcc_assert (fd->ordered == 0);
165138fd1498Szrj       /* First two _looptemp_ clauses are for istart/iend, counts[0]
165238fd1498Szrj 	 isn't supposed to be handled, as the inner loop doesn't
165338fd1498Szrj 	 use it.  */
165438fd1498Szrj       tree innerc = omp_find_clause (gimple_omp_for_clauses (fd->for_stmt),
165538fd1498Szrj 				     OMP_CLAUSE__LOOPTEMP_);
165638fd1498Szrj       gcc_assert (innerc);
165738fd1498Szrj       for (i = 0; i < fd->collapse; i++)
165838fd1498Szrj 	{
165938fd1498Szrj 	  innerc = omp_find_clause (OMP_CLAUSE_CHAIN (innerc),
166038fd1498Szrj 				    OMP_CLAUSE__LOOPTEMP_);
166138fd1498Szrj 	  gcc_assert (innerc);
166238fd1498Szrj 	  if (i)
166338fd1498Szrj 	    counts[i] = OMP_CLAUSE_DECL (innerc);
166438fd1498Szrj 	  else
166538fd1498Szrj 	    counts[0] = NULL_TREE;
166638fd1498Szrj 	}
166738fd1498Szrj       return;
166838fd1498Szrj     }
166938fd1498Szrj 
167038fd1498Szrj   for (i = fd->collapse; i < fd->ordered; i++)
167138fd1498Szrj     {
167238fd1498Szrj       tree itype = TREE_TYPE (fd->loops[i].v);
167338fd1498Szrj       counts[i] = NULL_TREE;
167438fd1498Szrj       t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
167538fd1498Szrj 		       fold_convert (itype, fd->loops[i].n1),
167638fd1498Szrj 		       fold_convert (itype, fd->loops[i].n2));
167738fd1498Szrj       if (t && integer_zerop (t))
167838fd1498Szrj 	{
167938fd1498Szrj 	  for (i = fd->collapse; i < fd->ordered; i++)
168038fd1498Szrj 	    counts[i] = build_int_cst (type, 0);
168138fd1498Szrj 	  break;
168238fd1498Szrj 	}
168338fd1498Szrj     }
168438fd1498Szrj   for (i = 0; i < (fd->ordered ? fd->ordered : fd->collapse); i++)
168538fd1498Szrj     {
168638fd1498Szrj       tree itype = TREE_TYPE (fd->loops[i].v);
168738fd1498Szrj 
168838fd1498Szrj       if (i >= fd->collapse && counts[i])
168938fd1498Szrj 	continue;
169038fd1498Szrj       if ((SSA_VAR_P (fd->loop.n2) || i >= fd->collapse)
169138fd1498Szrj 	  && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
169238fd1498Szrj 				fold_convert (itype, fd->loops[i].n1),
169338fd1498Szrj 				fold_convert (itype, fd->loops[i].n2)))
169438fd1498Szrj 	      == NULL_TREE || !integer_onep (t)))
169538fd1498Szrj 	{
169638fd1498Szrj 	  gcond *cond_stmt;
169738fd1498Szrj 	  tree n1, n2;
169838fd1498Szrj 	  n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
169938fd1498Szrj 	  n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
170038fd1498Szrj 					 true, GSI_SAME_STMT);
170138fd1498Szrj 	  n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
170238fd1498Szrj 	  n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
170338fd1498Szrj 					 true, GSI_SAME_STMT);
170438fd1498Szrj 	  cond_stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
170538fd1498Szrj 					 NULL_TREE, NULL_TREE);
170638fd1498Szrj 	  gsi_insert_before (gsi, cond_stmt, GSI_SAME_STMT);
170738fd1498Szrj 	  if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
170838fd1498Szrj 			 expand_omp_regimplify_p, NULL, NULL)
170938fd1498Szrj 	      || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
171038fd1498Szrj 			    expand_omp_regimplify_p, NULL, NULL))
171138fd1498Szrj 	    {
171238fd1498Szrj 	      *gsi = gsi_for_stmt (cond_stmt);
171338fd1498Szrj 	      gimple_regimplify_operands (cond_stmt, gsi);
171438fd1498Szrj 	    }
171538fd1498Szrj 	  e = split_block (entry_bb, cond_stmt);
171638fd1498Szrj 	  basic_block &zero_iter_bb
171738fd1498Szrj 	    = i < fd->collapse ? zero_iter1_bb : zero_iter2_bb;
171838fd1498Szrj 	  int &first_zero_iter
171938fd1498Szrj 	    = i < fd->collapse ? first_zero_iter1 : first_zero_iter2;
172038fd1498Szrj 	  if (zero_iter_bb == NULL)
172138fd1498Szrj 	    {
172238fd1498Szrj 	      gassign *assign_stmt;
172338fd1498Szrj 	      first_zero_iter = i;
172438fd1498Szrj 	      zero_iter_bb = create_empty_bb (entry_bb);
172538fd1498Szrj 	      add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
172638fd1498Szrj 	      *gsi = gsi_after_labels (zero_iter_bb);
172738fd1498Szrj 	      if (i < fd->collapse)
172838fd1498Szrj 		assign_stmt = gimple_build_assign (fd->loop.n2,
172938fd1498Szrj 						   build_zero_cst (type));
173038fd1498Szrj 	      else
173138fd1498Szrj 		{
173238fd1498Szrj 		  counts[i] = create_tmp_reg (type, ".count");
173338fd1498Szrj 		  assign_stmt
173438fd1498Szrj 		    = gimple_build_assign (counts[i], build_zero_cst (type));
173538fd1498Szrj 		}
173638fd1498Szrj 	      gsi_insert_before (gsi, assign_stmt, GSI_SAME_STMT);
173738fd1498Szrj 	      set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
173838fd1498Szrj 				       entry_bb);
173938fd1498Szrj 	    }
174038fd1498Szrj 	  ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
174138fd1498Szrj 	  ne->probability = profile_probability::very_unlikely ();
174238fd1498Szrj 	  e->flags = EDGE_TRUE_VALUE;
174338fd1498Szrj 	  e->probability = ne->probability.invert ();
174438fd1498Szrj 	  if (l2_dom_bb == NULL)
174538fd1498Szrj 	    l2_dom_bb = entry_bb;
174638fd1498Szrj 	  entry_bb = e->dest;
174738fd1498Szrj 	  *gsi = gsi_last_nondebug_bb (entry_bb);
174838fd1498Szrj 	}
174938fd1498Szrj 
175038fd1498Szrj       if (POINTER_TYPE_P (itype))
175138fd1498Szrj 	itype = signed_type_for (itype);
175238fd1498Szrj       t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
175338fd1498Szrj 				 ? -1 : 1));
175438fd1498Szrj       t = fold_build2 (PLUS_EXPR, itype,
175538fd1498Szrj 		       fold_convert (itype, fd->loops[i].step), t);
175638fd1498Szrj       t = fold_build2 (PLUS_EXPR, itype, t,
175738fd1498Szrj 		       fold_convert (itype, fd->loops[i].n2));
175838fd1498Szrj       t = fold_build2 (MINUS_EXPR, itype, t,
175938fd1498Szrj 		       fold_convert (itype, fd->loops[i].n1));
176038fd1498Szrj       /* ?? We could probably use CEIL_DIV_EXPR instead of
176138fd1498Szrj 	 TRUNC_DIV_EXPR and adjusting by hand.  Unless we can't
176238fd1498Szrj 	 generate the same code in the end because generically we
176338fd1498Szrj 	 don't know that the values involved must be negative for
176438fd1498Szrj 	 GT??  */
176538fd1498Szrj       if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
176638fd1498Szrj 	t = fold_build2 (TRUNC_DIV_EXPR, itype,
176738fd1498Szrj 			 fold_build1 (NEGATE_EXPR, itype, t),
176838fd1498Szrj 			 fold_build1 (NEGATE_EXPR, itype,
176938fd1498Szrj 				      fold_convert (itype,
177038fd1498Szrj 						    fd->loops[i].step)));
177138fd1498Szrj       else
177238fd1498Szrj 	t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
177338fd1498Szrj 			 fold_convert (itype, fd->loops[i].step));
177438fd1498Szrj       t = fold_convert (type, t);
177538fd1498Szrj       if (TREE_CODE (t) == INTEGER_CST)
177638fd1498Szrj 	counts[i] = t;
177738fd1498Szrj       else
177838fd1498Szrj 	{
177938fd1498Szrj 	  if (i < fd->collapse || i != first_zero_iter2)
178038fd1498Szrj 	    counts[i] = create_tmp_reg (type, ".count");
178138fd1498Szrj 	  expand_omp_build_assign (gsi, counts[i], t);
178238fd1498Szrj 	}
178338fd1498Szrj       if (SSA_VAR_P (fd->loop.n2) && i < fd->collapse)
178438fd1498Szrj 	{
178538fd1498Szrj 	  if (i == 0)
178638fd1498Szrj 	    t = counts[0];
178738fd1498Szrj 	  else
178838fd1498Szrj 	    t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
178938fd1498Szrj 	  expand_omp_build_assign (gsi, fd->loop.n2, t);
179038fd1498Szrj 	}
179138fd1498Szrj     }
179238fd1498Szrj }
179338fd1498Szrj 
179438fd1498Szrj /* Helper function for expand_omp_{for_*,simd}.  Generate code like:
179538fd1498Szrj 	T = V;
179638fd1498Szrj 	V3 = N31 + (T % count3) * STEP3;
179738fd1498Szrj 	T = T / count3;
179838fd1498Szrj 	V2 = N21 + (T % count2) * STEP2;
179938fd1498Szrj 	T = T / count2;
180038fd1498Szrj 	V1 = N11 + T * STEP1;
180138fd1498Szrj    if this loop doesn't have an inner loop construct combined with it.
180238fd1498Szrj    If it does have an inner loop construct combined with it and the
180338fd1498Szrj    iteration count isn't known constant, store values from counts array
180438fd1498Szrj    into its _looptemp_ temporaries instead.  */
180538fd1498Szrj 
180638fd1498Szrj static void
expand_omp_for_init_vars(struct omp_for_data * fd,gimple_stmt_iterator * gsi,tree * counts,gimple * inner_stmt,tree startvar)180738fd1498Szrj expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
180838fd1498Szrj 			  tree *counts, gimple *inner_stmt, tree startvar)
180938fd1498Szrj {
181038fd1498Szrj   int i;
181138fd1498Szrj   if (gimple_omp_for_combined_p (fd->for_stmt))
181238fd1498Szrj     {
181338fd1498Szrj       /* If fd->loop.n2 is constant, then no propagation of the counts
181438fd1498Szrj 	 is needed, they are constant.  */
181538fd1498Szrj       if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
181638fd1498Szrj 	return;
181738fd1498Szrj 
181838fd1498Szrj       tree clauses = gimple_code (inner_stmt) != GIMPLE_OMP_FOR
181938fd1498Szrj 		     ? gimple_omp_taskreg_clauses (inner_stmt)
182038fd1498Szrj 		     : gimple_omp_for_clauses (inner_stmt);
182138fd1498Szrj       /* First two _looptemp_ clauses are for istart/iend, counts[0]
182238fd1498Szrj 	 isn't supposed to be handled, as the inner loop doesn't
182338fd1498Szrj 	 use it.  */
182438fd1498Szrj       tree innerc = omp_find_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
182538fd1498Szrj       gcc_assert (innerc);
182638fd1498Szrj       for (i = 0; i < fd->collapse; i++)
182738fd1498Szrj 	{
182838fd1498Szrj 	  innerc = omp_find_clause (OMP_CLAUSE_CHAIN (innerc),
182938fd1498Szrj 				    OMP_CLAUSE__LOOPTEMP_);
183038fd1498Szrj 	  gcc_assert (innerc);
183138fd1498Szrj 	  if (i)
183238fd1498Szrj 	    {
183338fd1498Szrj 	      tree tem = OMP_CLAUSE_DECL (innerc);
183438fd1498Szrj 	      tree t = fold_convert (TREE_TYPE (tem), counts[i]);
183538fd1498Szrj 	      t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
183638fd1498Szrj 					    false, GSI_CONTINUE_LINKING);
183738fd1498Szrj 	      gassign *stmt = gimple_build_assign (tem, t);
183838fd1498Szrj 	      gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
183938fd1498Szrj 	    }
184038fd1498Szrj 	}
184138fd1498Szrj       return;
184238fd1498Szrj     }
184338fd1498Szrj 
184438fd1498Szrj   tree type = TREE_TYPE (fd->loop.v);
184538fd1498Szrj   tree tem = create_tmp_reg (type, ".tem");
184638fd1498Szrj   gassign *stmt = gimple_build_assign (tem, startvar);
184738fd1498Szrj   gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
184838fd1498Szrj 
184938fd1498Szrj   for (i = fd->collapse - 1; i >= 0; i--)
185038fd1498Szrj     {
185138fd1498Szrj       tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
185238fd1498Szrj       itype = vtype;
185338fd1498Szrj       if (POINTER_TYPE_P (vtype))
185438fd1498Szrj 	itype = signed_type_for (vtype);
185538fd1498Szrj       if (i != 0)
185638fd1498Szrj 	t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
185738fd1498Szrj       else
185838fd1498Szrj 	t = tem;
185938fd1498Szrj       t = fold_convert (itype, t);
186038fd1498Szrj       t = fold_build2 (MULT_EXPR, itype, t,
186138fd1498Szrj 		       fold_convert (itype, fd->loops[i].step));
186238fd1498Szrj       if (POINTER_TYPE_P (vtype))
186338fd1498Szrj 	t = fold_build_pointer_plus (fd->loops[i].n1, t);
186438fd1498Szrj       else
186538fd1498Szrj 	t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
186638fd1498Szrj       t = force_gimple_operand_gsi (gsi, t,
186738fd1498Szrj 				    DECL_P (fd->loops[i].v)
186838fd1498Szrj 				    && TREE_ADDRESSABLE (fd->loops[i].v),
186938fd1498Szrj 				    NULL_TREE, false,
187038fd1498Szrj 				    GSI_CONTINUE_LINKING);
187138fd1498Szrj       stmt = gimple_build_assign (fd->loops[i].v, t);
187238fd1498Szrj       gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
187338fd1498Szrj       if (i != 0)
187438fd1498Szrj 	{
187538fd1498Szrj 	  t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
187638fd1498Szrj 	  t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
187738fd1498Szrj 					false, GSI_CONTINUE_LINKING);
187838fd1498Szrj 	  stmt = gimple_build_assign (tem, t);
187938fd1498Szrj 	  gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
188038fd1498Szrj 	}
188138fd1498Szrj     }
188238fd1498Szrj }
188338fd1498Szrj 
188438fd1498Szrj /* Helper function for expand_omp_for_*.  Generate code like:
188538fd1498Szrj     L10:
188638fd1498Szrj 	V3 += STEP3;
188738fd1498Szrj 	if (V3 cond3 N32) goto BODY_BB; else goto L11;
188838fd1498Szrj     L11:
188938fd1498Szrj 	V3 = N31;
189038fd1498Szrj 	V2 += STEP2;
189138fd1498Szrj 	if (V2 cond2 N22) goto BODY_BB; else goto L12;
189238fd1498Szrj     L12:
189338fd1498Szrj 	V2 = N21;
189438fd1498Szrj 	V1 += STEP1;
189538fd1498Szrj 	goto BODY_BB;  */
189638fd1498Szrj 
189738fd1498Szrj static basic_block
extract_omp_for_update_vars(struct omp_for_data * fd,basic_block cont_bb,basic_block body_bb)189838fd1498Szrj extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
189938fd1498Szrj 			     basic_block body_bb)
190038fd1498Szrj {
190138fd1498Szrj   basic_block last_bb, bb, collapse_bb = NULL;
190238fd1498Szrj   int i;
190338fd1498Szrj   gimple_stmt_iterator gsi;
190438fd1498Szrj   edge e;
190538fd1498Szrj   tree t;
190638fd1498Szrj   gimple *stmt;
190738fd1498Szrj 
190838fd1498Szrj   last_bb = cont_bb;
190938fd1498Szrj   for (i = fd->collapse - 1; i >= 0; i--)
191038fd1498Szrj     {
191138fd1498Szrj       tree vtype = TREE_TYPE (fd->loops[i].v);
191238fd1498Szrj 
191338fd1498Szrj       bb = create_empty_bb (last_bb);
191438fd1498Szrj       add_bb_to_loop (bb, last_bb->loop_father);
191538fd1498Szrj       gsi = gsi_start_bb (bb);
191638fd1498Szrj 
191738fd1498Szrj       if (i < fd->collapse - 1)
191838fd1498Szrj 	{
191938fd1498Szrj 	  e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
192038fd1498Szrj 	  e->probability = profile_probability::guessed_always ().apply_scale (1, 8);
192138fd1498Szrj 
192238fd1498Szrj 	  t = fd->loops[i + 1].n1;
192338fd1498Szrj 	  t = force_gimple_operand_gsi (&gsi, t,
192438fd1498Szrj 					DECL_P (fd->loops[i + 1].v)
192538fd1498Szrj 					&& TREE_ADDRESSABLE (fd->loops[i
192638fd1498Szrj 								       + 1].v),
192738fd1498Szrj 					NULL_TREE, false,
192838fd1498Szrj 					GSI_CONTINUE_LINKING);
192938fd1498Szrj 	  stmt = gimple_build_assign (fd->loops[i + 1].v, t);
193038fd1498Szrj 	  gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
193138fd1498Szrj 	}
193238fd1498Szrj       else
193338fd1498Szrj 	collapse_bb = bb;
193438fd1498Szrj 
193538fd1498Szrj       set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
193638fd1498Szrj 
193738fd1498Szrj       if (POINTER_TYPE_P (vtype))
193838fd1498Szrj 	t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
193938fd1498Szrj       else
194038fd1498Szrj 	t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
194138fd1498Szrj       t = force_gimple_operand_gsi (&gsi, t,
194238fd1498Szrj 				    DECL_P (fd->loops[i].v)
194338fd1498Szrj 				    && TREE_ADDRESSABLE (fd->loops[i].v),
194438fd1498Szrj 				    NULL_TREE, false, GSI_CONTINUE_LINKING);
194538fd1498Szrj       stmt = gimple_build_assign (fd->loops[i].v, t);
194638fd1498Szrj       gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
194738fd1498Szrj 
194838fd1498Szrj       if (i > 0)
194938fd1498Szrj 	{
195038fd1498Szrj 	  t = fd->loops[i].n2;
195138fd1498Szrj 	  t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
195238fd1498Szrj 					false, GSI_CONTINUE_LINKING);
195338fd1498Szrj 	  tree v = fd->loops[i].v;
195438fd1498Szrj 	  if (DECL_P (v) && TREE_ADDRESSABLE (v))
195538fd1498Szrj 	    v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
195638fd1498Szrj 					  false, GSI_CONTINUE_LINKING);
195738fd1498Szrj 	  t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
195838fd1498Szrj 	  stmt = gimple_build_cond_empty (t);
195938fd1498Szrj 	  gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
1960*58e805e6Szrj 	  if (walk_tree (gimple_cond_lhs_ptr (as_a <gcond *> (stmt)),
1961*58e805e6Szrj 			 expand_omp_regimplify_p, NULL, NULL)
1962*58e805e6Szrj 	      || walk_tree (gimple_cond_rhs_ptr (as_a <gcond *> (stmt)),
1963*58e805e6Szrj 			    expand_omp_regimplify_p, NULL, NULL))
1964*58e805e6Szrj 	    gimple_regimplify_operands (stmt, &gsi);
196538fd1498Szrj 	  e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
196638fd1498Szrj 	  e->probability = profile_probability::guessed_always ().apply_scale (7, 8);
196738fd1498Szrj 	}
196838fd1498Szrj       else
196938fd1498Szrj 	make_edge (bb, body_bb, EDGE_FALLTHRU);
197038fd1498Szrj       last_bb = bb;
197138fd1498Szrj     }
197238fd1498Szrj 
197338fd1498Szrj   return collapse_bb;
197438fd1498Szrj }
197538fd1498Szrj 
197638fd1498Szrj /* Expand #pragma omp ordered depend(source).  */
197738fd1498Szrj 
197838fd1498Szrj static void
expand_omp_ordered_source(gimple_stmt_iterator * gsi,struct omp_for_data * fd,tree * counts,location_t loc)197938fd1498Szrj expand_omp_ordered_source (gimple_stmt_iterator *gsi, struct omp_for_data *fd,
198038fd1498Szrj 			   tree *counts, location_t loc)
198138fd1498Szrj {
198238fd1498Szrj   enum built_in_function source_ix
198338fd1498Szrj     = fd->iter_type == long_integer_type_node
198438fd1498Szrj       ? BUILT_IN_GOMP_DOACROSS_POST : BUILT_IN_GOMP_DOACROSS_ULL_POST;
198538fd1498Szrj   gimple *g
198638fd1498Szrj     = gimple_build_call (builtin_decl_explicit (source_ix), 1,
198738fd1498Szrj 			 build_fold_addr_expr (counts[fd->ordered]));
198838fd1498Szrj   gimple_set_location (g, loc);
198938fd1498Szrj   gsi_insert_before (gsi, g, GSI_SAME_STMT);
199038fd1498Szrj }
199138fd1498Szrj 
199238fd1498Szrj /* Expand a single depend from #pragma omp ordered depend(sink:...).  */
199338fd1498Szrj 
199438fd1498Szrj static void
expand_omp_ordered_sink(gimple_stmt_iterator * gsi,struct omp_for_data * fd,tree * counts,tree c,location_t loc)199538fd1498Szrj expand_omp_ordered_sink (gimple_stmt_iterator *gsi, struct omp_for_data *fd,
199638fd1498Szrj 			 tree *counts, tree c, location_t loc)
199738fd1498Szrj {
199838fd1498Szrj   auto_vec<tree, 10> args;
199938fd1498Szrj   enum built_in_function sink_ix
200038fd1498Szrj     = fd->iter_type == long_integer_type_node
200138fd1498Szrj       ? BUILT_IN_GOMP_DOACROSS_WAIT : BUILT_IN_GOMP_DOACROSS_ULL_WAIT;
200238fd1498Szrj   tree t, off, coff = NULL_TREE, deps = OMP_CLAUSE_DECL (c), cond = NULL_TREE;
200338fd1498Szrj   int i;
200438fd1498Szrj   gimple_stmt_iterator gsi2 = *gsi;
200538fd1498Szrj   bool warned_step = false;
200638fd1498Szrj 
200738fd1498Szrj   for (i = 0; i < fd->ordered; i++)
200838fd1498Szrj     {
200938fd1498Szrj       tree step = NULL_TREE;
201038fd1498Szrj       off = TREE_PURPOSE (deps);
201138fd1498Szrj       if (TREE_CODE (off) == TRUNC_DIV_EXPR)
201238fd1498Szrj 	{
201338fd1498Szrj 	  step = TREE_OPERAND (off, 1);
201438fd1498Szrj 	  off = TREE_OPERAND (off, 0);
201538fd1498Szrj 	}
201638fd1498Szrj       if (!integer_zerop (off))
201738fd1498Szrj 	{
201838fd1498Szrj 	  gcc_assert (fd->loops[i].cond_code == LT_EXPR
201938fd1498Szrj 		      || fd->loops[i].cond_code == GT_EXPR);
202038fd1498Szrj 	  bool forward = fd->loops[i].cond_code == LT_EXPR;
202138fd1498Szrj 	  if (step)
202238fd1498Szrj 	    {
202338fd1498Szrj 	      /* Non-simple Fortran DO loops.  If step is variable,
202438fd1498Szrj 		 we don't know at compile even the direction, so can't
202538fd1498Szrj 		 warn.  */
202638fd1498Szrj 	      if (TREE_CODE (step) != INTEGER_CST)
202738fd1498Szrj 		break;
202838fd1498Szrj 	      forward = tree_int_cst_sgn (step) != -1;
202938fd1498Szrj 	    }
203038fd1498Szrj 	  if (forward ^ OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
203138fd1498Szrj 	    warning_at (loc, 0, "%<depend(sink)%> clause waiting for "
203238fd1498Szrj 				"lexically later iteration");
203338fd1498Szrj 	  break;
203438fd1498Szrj 	}
203538fd1498Szrj       deps = TREE_CHAIN (deps);
203638fd1498Szrj     }
203738fd1498Szrj   /* If all offsets corresponding to the collapsed loops are zero,
203838fd1498Szrj      this depend clause can be ignored.  FIXME: but there is still a
203938fd1498Szrj      flush needed.  We need to emit one __sync_synchronize () for it
204038fd1498Szrj      though (perhaps conditionally)?  Solve this together with the
204138fd1498Szrj      conservative dependence folding optimization.
204238fd1498Szrj   if (i >= fd->collapse)
204338fd1498Szrj     return;  */
204438fd1498Szrj 
204538fd1498Szrj   deps = OMP_CLAUSE_DECL (c);
204638fd1498Szrj   gsi_prev (&gsi2);
204738fd1498Szrj   edge e1 = split_block (gsi_bb (gsi2), gsi_stmt (gsi2));
204838fd1498Szrj   edge e2 = split_block_after_labels (e1->dest);
204938fd1498Szrj 
205038fd1498Szrj   gsi2 = gsi_after_labels (e1->dest);
205138fd1498Szrj   *gsi = gsi_last_bb (e1->src);
205238fd1498Szrj   for (i = 0; i < fd->ordered; i++)
205338fd1498Szrj     {
205438fd1498Szrj       tree itype = TREE_TYPE (fd->loops[i].v);
205538fd1498Szrj       tree step = NULL_TREE;
205638fd1498Szrj       tree orig_off = NULL_TREE;
205738fd1498Szrj       if (POINTER_TYPE_P (itype))
205838fd1498Szrj 	itype = sizetype;
205938fd1498Szrj       if (i)
206038fd1498Szrj 	deps = TREE_CHAIN (deps);
206138fd1498Szrj       off = TREE_PURPOSE (deps);
206238fd1498Szrj       if (TREE_CODE (off) == TRUNC_DIV_EXPR)
206338fd1498Szrj 	{
206438fd1498Szrj 	  step = TREE_OPERAND (off, 1);
206538fd1498Szrj 	  off = TREE_OPERAND (off, 0);
206638fd1498Szrj 	  gcc_assert (fd->loops[i].cond_code == LT_EXPR
206738fd1498Szrj 		      && integer_onep (fd->loops[i].step)
206838fd1498Szrj 		      && !POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)));
206938fd1498Szrj 	}
207038fd1498Szrj       tree s = fold_convert_loc (loc, itype, step ? step : fd->loops[i].step);
207138fd1498Szrj       if (step)
207238fd1498Szrj 	{
207338fd1498Szrj 	  off = fold_convert_loc (loc, itype, off);
207438fd1498Szrj 	  orig_off = off;
207538fd1498Szrj 	  off = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, off, s);
207638fd1498Szrj 	}
207738fd1498Szrj 
207838fd1498Szrj       if (integer_zerop (off))
207938fd1498Szrj 	t = boolean_true_node;
208038fd1498Szrj       else
208138fd1498Szrj 	{
208238fd1498Szrj 	  tree a;
208338fd1498Szrj 	  tree co = fold_convert_loc (loc, itype, off);
208438fd1498Szrj 	  if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
208538fd1498Szrj 	    {
208638fd1498Szrj 	      if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
208738fd1498Szrj 		co = fold_build1_loc (loc, NEGATE_EXPR, itype, co);
208838fd1498Szrj 	      a = fold_build2_loc (loc, POINTER_PLUS_EXPR,
208938fd1498Szrj 				   TREE_TYPE (fd->loops[i].v), fd->loops[i].v,
209038fd1498Szrj 				   co);
209138fd1498Szrj 	    }
209238fd1498Szrj 	  else if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
209338fd1498Szrj 	    a = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
209438fd1498Szrj 				 fd->loops[i].v, co);
209538fd1498Szrj 	  else
209638fd1498Szrj 	    a = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
209738fd1498Szrj 				 fd->loops[i].v, co);
209838fd1498Szrj 	  if (step)
209938fd1498Szrj 	    {
210038fd1498Szrj 	      tree t1, t2;
210138fd1498Szrj 	      if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
210238fd1498Szrj 		t1 = fold_build2_loc (loc, GE_EXPR, boolean_type_node, a,
210338fd1498Szrj 				      fd->loops[i].n1);
210438fd1498Szrj 	      else
210538fd1498Szrj 		t1 = fold_build2_loc (loc, LT_EXPR, boolean_type_node, a,
210638fd1498Szrj 				      fd->loops[i].n2);
210738fd1498Szrj 	      if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
210838fd1498Szrj 		t2 = fold_build2_loc (loc, LT_EXPR, boolean_type_node, a,
210938fd1498Szrj 				      fd->loops[i].n2);
211038fd1498Szrj 	      else
211138fd1498Szrj 		t2 = fold_build2_loc (loc, GE_EXPR, boolean_type_node, a,
211238fd1498Szrj 				      fd->loops[i].n1);
211338fd1498Szrj 	      t = fold_build2_loc (loc, LT_EXPR, boolean_type_node,
211438fd1498Szrj 				   step, build_int_cst (TREE_TYPE (step), 0));
211538fd1498Szrj 	      if (TREE_CODE (step) != INTEGER_CST)
211638fd1498Szrj 		{
211738fd1498Szrj 		  t1 = unshare_expr (t1);
211838fd1498Szrj 		  t1 = force_gimple_operand_gsi (gsi, t1, true, NULL_TREE,
211938fd1498Szrj 						 false, GSI_CONTINUE_LINKING);
212038fd1498Szrj 		  t2 = unshare_expr (t2);
212138fd1498Szrj 		  t2 = force_gimple_operand_gsi (gsi, t2, true, NULL_TREE,
212238fd1498Szrj 						 false, GSI_CONTINUE_LINKING);
212338fd1498Szrj 		}
212438fd1498Szrj 	      t = fold_build3_loc (loc, COND_EXPR, boolean_type_node,
212538fd1498Szrj 				   t, t2, t1);
212638fd1498Szrj 	    }
212738fd1498Szrj 	  else if (fd->loops[i].cond_code == LT_EXPR)
212838fd1498Szrj 	    {
212938fd1498Szrj 	      if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
213038fd1498Szrj 		t = fold_build2_loc (loc, GE_EXPR, boolean_type_node, a,
213138fd1498Szrj 				     fd->loops[i].n1);
213238fd1498Szrj 	      else
213338fd1498Szrj 		t = fold_build2_loc (loc, LT_EXPR, boolean_type_node, a,
213438fd1498Szrj 				     fd->loops[i].n2);
213538fd1498Szrj 	    }
213638fd1498Szrj 	  else if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
213738fd1498Szrj 	    t = fold_build2_loc (loc, GT_EXPR, boolean_type_node, a,
213838fd1498Szrj 				 fd->loops[i].n2);
213938fd1498Szrj 	  else
214038fd1498Szrj 	    t = fold_build2_loc (loc, LE_EXPR, boolean_type_node, a,
214138fd1498Szrj 				 fd->loops[i].n1);
214238fd1498Szrj 	}
214338fd1498Szrj       if (cond)
214438fd1498Szrj 	cond = fold_build2_loc (loc, BIT_AND_EXPR, boolean_type_node, cond, t);
214538fd1498Szrj       else
214638fd1498Szrj 	cond = t;
214738fd1498Szrj 
214838fd1498Szrj       off = fold_convert_loc (loc, itype, off);
214938fd1498Szrj 
215038fd1498Szrj       if (step
215138fd1498Szrj 	  || (fd->loops[i].cond_code == LT_EXPR
215238fd1498Szrj 	      ? !integer_onep (fd->loops[i].step)
215338fd1498Szrj 	      : !integer_minus_onep (fd->loops[i].step)))
215438fd1498Szrj 	{
215538fd1498Szrj 	  if (step == NULL_TREE
215638fd1498Szrj 	      && TYPE_UNSIGNED (itype)
215738fd1498Szrj 	      && fd->loops[i].cond_code == GT_EXPR)
215838fd1498Szrj 	    t = fold_build2_loc (loc, TRUNC_MOD_EXPR, itype, off,
215938fd1498Szrj 				 fold_build1_loc (loc, NEGATE_EXPR, itype,
216038fd1498Szrj 						  s));
216138fd1498Szrj 	  else
216238fd1498Szrj 	    t = fold_build2_loc (loc, TRUNC_MOD_EXPR, itype,
216338fd1498Szrj 				 orig_off ? orig_off : off, s);
216438fd1498Szrj 	  t = fold_build2_loc (loc, EQ_EXPR, boolean_type_node, t,
216538fd1498Szrj 			       build_int_cst (itype, 0));
216638fd1498Szrj 	  if (integer_zerop (t) && !warned_step)
216738fd1498Szrj 	    {
216838fd1498Szrj 	      warning_at (loc, 0, "%<depend(sink)%> refers to iteration never "
216938fd1498Szrj 				  "in the iteration space");
217038fd1498Szrj 	      warned_step = true;
217138fd1498Szrj 	    }
217238fd1498Szrj 	  cond = fold_build2_loc (loc, BIT_AND_EXPR, boolean_type_node,
217338fd1498Szrj 				  cond, t);
217438fd1498Szrj 	}
217538fd1498Szrj 
217638fd1498Szrj       if (i <= fd->collapse - 1 && fd->collapse > 1)
217738fd1498Szrj 	t = fd->loop.v;
217838fd1498Szrj       else if (counts[i])
217938fd1498Szrj 	t = counts[i];
218038fd1498Szrj       else
218138fd1498Szrj 	{
218238fd1498Szrj 	  t = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
218338fd1498Szrj 			       fd->loops[i].v, fd->loops[i].n1);
218438fd1498Szrj 	  t = fold_convert_loc (loc, fd->iter_type, t);
218538fd1498Szrj 	}
218638fd1498Szrj       if (step)
218738fd1498Szrj 	/* We have divided off by step already earlier.  */;
218838fd1498Szrj       else if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
218938fd1498Szrj 	off = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, off,
219038fd1498Szrj 			       fold_build1_loc (loc, NEGATE_EXPR, itype,
219138fd1498Szrj 						s));
219238fd1498Szrj       else
219338fd1498Szrj 	off = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, off, s);
219438fd1498Szrj       if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
219538fd1498Szrj 	off = fold_build1_loc (loc, NEGATE_EXPR, itype, off);
219638fd1498Szrj       off = fold_convert_loc (loc, fd->iter_type, off);
219738fd1498Szrj       if (i <= fd->collapse - 1 && fd->collapse > 1)
219838fd1498Szrj 	{
219938fd1498Szrj 	  if (i)
220038fd1498Szrj 	    off = fold_build2_loc (loc, PLUS_EXPR, fd->iter_type, coff,
220138fd1498Szrj 				   off);
220238fd1498Szrj 	  if (i < fd->collapse - 1)
220338fd1498Szrj 	    {
220438fd1498Szrj 	      coff = fold_build2_loc (loc, MULT_EXPR, fd->iter_type, off,
220538fd1498Szrj 				      counts[i]);
220638fd1498Szrj 	      continue;
220738fd1498Szrj 	    }
220838fd1498Szrj 	}
220938fd1498Szrj       off = unshare_expr (off);
221038fd1498Szrj       t = fold_build2_loc (loc, PLUS_EXPR, fd->iter_type, t, off);
221138fd1498Szrj       t = force_gimple_operand_gsi (&gsi2, t, true, NULL_TREE,
221238fd1498Szrj 				    true, GSI_SAME_STMT);
221338fd1498Szrj       args.safe_push (t);
221438fd1498Szrj     }
221538fd1498Szrj   gimple *g = gimple_build_call_vec (builtin_decl_explicit (sink_ix), args);
221638fd1498Szrj   gimple_set_location (g, loc);
221738fd1498Szrj   gsi_insert_before (&gsi2, g, GSI_SAME_STMT);
221838fd1498Szrj 
221938fd1498Szrj   cond = unshare_expr (cond);
222038fd1498Szrj   cond = force_gimple_operand_gsi (gsi, cond, true, NULL_TREE, false,
222138fd1498Szrj 				   GSI_CONTINUE_LINKING);
222238fd1498Szrj   gsi_insert_after (gsi, gimple_build_cond_empty (cond), GSI_NEW_STMT);
222338fd1498Szrj   edge e3 = make_edge (e1->src, e2->dest, EDGE_FALSE_VALUE);
222438fd1498Szrj   e3->probability = profile_probability::guessed_always ().apply_scale (1, 8);
222538fd1498Szrj   e1->probability = e3->probability.invert ();
222638fd1498Szrj   e1->flags = EDGE_TRUE_VALUE;
222738fd1498Szrj   set_immediate_dominator (CDI_DOMINATORS, e2->dest, e1->src);
222838fd1498Szrj 
222938fd1498Szrj   *gsi = gsi_after_labels (e2->dest);
223038fd1498Szrj }
223138fd1498Szrj 
223238fd1498Szrj /* Expand all #pragma omp ordered depend(source) and
223338fd1498Szrj    #pragma omp ordered depend(sink:...) constructs in the current
223438fd1498Szrj    #pragma omp for ordered(n) region.  */
223538fd1498Szrj 
223638fd1498Szrj static void
expand_omp_ordered_source_sink(struct omp_region * region,struct omp_for_data * fd,tree * counts,basic_block cont_bb)223738fd1498Szrj expand_omp_ordered_source_sink (struct omp_region *region,
223838fd1498Szrj 				struct omp_for_data *fd, tree *counts,
223938fd1498Szrj 				basic_block cont_bb)
224038fd1498Szrj {
224138fd1498Szrj   struct omp_region *inner;
224238fd1498Szrj   int i;
224338fd1498Szrj   for (i = fd->collapse - 1; i < fd->ordered; i++)
224438fd1498Szrj     if (i == fd->collapse - 1 && fd->collapse > 1)
224538fd1498Szrj       counts[i] = NULL_TREE;
224638fd1498Szrj     else if (i >= fd->collapse && !cont_bb)
224738fd1498Szrj       counts[i] = build_zero_cst (fd->iter_type);
224838fd1498Szrj     else if (!POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v))
224938fd1498Szrj 	     && integer_onep (fd->loops[i].step))
225038fd1498Szrj       counts[i] = NULL_TREE;
225138fd1498Szrj     else
225238fd1498Szrj       counts[i] = create_tmp_var (fd->iter_type, ".orditer");
225338fd1498Szrj   tree atype
225438fd1498Szrj     = build_array_type_nelts (fd->iter_type, fd->ordered - fd->collapse + 1);
225538fd1498Szrj   counts[fd->ordered] = create_tmp_var (atype, ".orditera");
225638fd1498Szrj   TREE_ADDRESSABLE (counts[fd->ordered]) = 1;
225738fd1498Szrj 
225838fd1498Szrj   for (inner = region->inner; inner; inner = inner->next)
225938fd1498Szrj     if (inner->type == GIMPLE_OMP_ORDERED)
226038fd1498Szrj       {
226138fd1498Szrj 	gomp_ordered *ord_stmt = inner->ord_stmt;
226238fd1498Szrj 	gimple_stmt_iterator gsi = gsi_for_stmt (ord_stmt);
226338fd1498Szrj 	location_t loc = gimple_location (ord_stmt);
226438fd1498Szrj 	tree c;
226538fd1498Szrj 	for (c = gimple_omp_ordered_clauses (ord_stmt);
226638fd1498Szrj 	     c; c = OMP_CLAUSE_CHAIN (c))
226738fd1498Szrj 	  if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE)
226838fd1498Szrj 	    break;
226938fd1498Szrj 	if (c)
227038fd1498Szrj 	  expand_omp_ordered_source (&gsi, fd, counts, loc);
227138fd1498Szrj 	for (c = gimple_omp_ordered_clauses (ord_stmt);
227238fd1498Szrj 	     c; c = OMP_CLAUSE_CHAIN (c))
227338fd1498Szrj 	  if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)
227438fd1498Szrj 	    expand_omp_ordered_sink (&gsi, fd, counts, c, loc);
227538fd1498Szrj 	gsi_remove (&gsi, true);
227638fd1498Szrj       }
227738fd1498Szrj }
227838fd1498Szrj 
227938fd1498Szrj /* Wrap the body into fd->ordered - fd->collapse loops that aren't
228038fd1498Szrj    collapsed.  */
228138fd1498Szrj 
228238fd1498Szrj static basic_block
expand_omp_for_ordered_loops(struct omp_for_data * fd,tree * counts,basic_block cont_bb,basic_block body_bb,bool ordered_lastprivate)228338fd1498Szrj expand_omp_for_ordered_loops (struct omp_for_data *fd, tree *counts,
228438fd1498Szrj 			      basic_block cont_bb, basic_block body_bb,
228538fd1498Szrj 			      bool ordered_lastprivate)
228638fd1498Szrj {
228738fd1498Szrj   if (fd->ordered == fd->collapse)
228838fd1498Szrj     return cont_bb;
228938fd1498Szrj 
229038fd1498Szrj   if (!cont_bb)
229138fd1498Szrj     {
229238fd1498Szrj       gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
229338fd1498Szrj       for (int i = fd->collapse; i < fd->ordered; i++)
229438fd1498Szrj 	{
229538fd1498Szrj 	  tree type = TREE_TYPE (fd->loops[i].v);
229638fd1498Szrj 	  tree n1 = fold_convert (type, fd->loops[i].n1);
229738fd1498Szrj 	  expand_omp_build_assign (&gsi, fd->loops[i].v, n1);
229838fd1498Szrj 	  tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
229938fd1498Szrj 			      size_int (i - fd->collapse + 1),
230038fd1498Szrj 			      NULL_TREE, NULL_TREE);
230138fd1498Szrj 	  expand_omp_build_assign (&gsi, aref, build_zero_cst (fd->iter_type));
230238fd1498Szrj 	}
230338fd1498Szrj       return NULL;
230438fd1498Szrj     }
230538fd1498Szrj 
230638fd1498Szrj   for (int i = fd->ordered - 1; i >= fd->collapse; i--)
230738fd1498Szrj     {
230838fd1498Szrj       tree t, type = TREE_TYPE (fd->loops[i].v);
230938fd1498Szrj       gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
231038fd1498Szrj       expand_omp_build_assign (&gsi, fd->loops[i].v,
231138fd1498Szrj 			       fold_convert (type, fd->loops[i].n1));
231238fd1498Szrj       if (counts[i])
231338fd1498Szrj 	expand_omp_build_assign (&gsi, counts[i],
231438fd1498Szrj 				 build_zero_cst (fd->iter_type));
231538fd1498Szrj       tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
231638fd1498Szrj 			  size_int (i - fd->collapse + 1),
231738fd1498Szrj 			  NULL_TREE, NULL_TREE);
231838fd1498Szrj       expand_omp_build_assign (&gsi, aref, build_zero_cst (fd->iter_type));
231938fd1498Szrj       if (!gsi_end_p (gsi))
232038fd1498Szrj 	gsi_prev (&gsi);
232138fd1498Szrj       else
232238fd1498Szrj 	gsi = gsi_last_bb (body_bb);
232338fd1498Szrj       edge e1 = split_block (body_bb, gsi_stmt (gsi));
232438fd1498Szrj       basic_block new_body = e1->dest;
232538fd1498Szrj       if (body_bb == cont_bb)
232638fd1498Szrj 	cont_bb = new_body;
232738fd1498Szrj       edge e2 = NULL;
232838fd1498Szrj       basic_block new_header;
232938fd1498Szrj       if (EDGE_COUNT (cont_bb->preds) > 0)
233038fd1498Szrj 	{
233138fd1498Szrj 	  gsi = gsi_last_bb (cont_bb);
233238fd1498Szrj 	  if (POINTER_TYPE_P (type))
233338fd1498Szrj 	    t = fold_build_pointer_plus (fd->loops[i].v,
233438fd1498Szrj 					 fold_convert (sizetype,
233538fd1498Szrj 						       fd->loops[i].step));
233638fd1498Szrj 	  else
233738fd1498Szrj 	    t = fold_build2 (PLUS_EXPR, type, fd->loops[i].v,
233838fd1498Szrj 			     fold_convert (type, fd->loops[i].step));
233938fd1498Szrj 	  expand_omp_build_assign (&gsi, fd->loops[i].v, t);
234038fd1498Szrj 	  if (counts[i])
234138fd1498Szrj 	    {
234238fd1498Szrj 	      t = fold_build2 (PLUS_EXPR, fd->iter_type, counts[i],
234338fd1498Szrj 			       build_int_cst (fd->iter_type, 1));
234438fd1498Szrj 	      expand_omp_build_assign (&gsi, counts[i], t);
234538fd1498Szrj 	      t = counts[i];
234638fd1498Szrj 	    }
234738fd1498Szrj 	  else
234838fd1498Szrj 	    {
234938fd1498Szrj 	      t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
235038fd1498Szrj 			       fd->loops[i].v, fd->loops[i].n1);
235138fd1498Szrj 	      t = fold_convert (fd->iter_type, t);
235238fd1498Szrj 	      t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
235338fd1498Szrj 					    true, GSI_SAME_STMT);
235438fd1498Szrj 	    }
235538fd1498Szrj 	  aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
235638fd1498Szrj 			 size_int (i - fd->collapse + 1),
235738fd1498Szrj 			 NULL_TREE, NULL_TREE);
235838fd1498Szrj 	  expand_omp_build_assign (&gsi, aref, t);
235938fd1498Szrj 	  gsi_prev (&gsi);
236038fd1498Szrj 	  e2 = split_block (cont_bb, gsi_stmt (gsi));
236138fd1498Szrj 	  new_header = e2->dest;
236238fd1498Szrj 	}
236338fd1498Szrj       else
236438fd1498Szrj 	new_header = cont_bb;
236538fd1498Szrj       gsi = gsi_after_labels (new_header);
236638fd1498Szrj       tree v = force_gimple_operand_gsi (&gsi, fd->loops[i].v, true, NULL_TREE,
236738fd1498Szrj 					 true, GSI_SAME_STMT);
236838fd1498Szrj       tree n2
236938fd1498Szrj 	= force_gimple_operand_gsi (&gsi, fold_convert (type, fd->loops[i].n2),
237038fd1498Szrj 				    true, NULL_TREE, true, GSI_SAME_STMT);
237138fd1498Szrj       t = build2 (fd->loops[i].cond_code, boolean_type_node, v, n2);
237238fd1498Szrj       gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_NEW_STMT);
237338fd1498Szrj       edge e3 = split_block (new_header, gsi_stmt (gsi));
237438fd1498Szrj       cont_bb = e3->dest;
237538fd1498Szrj       remove_edge (e1);
237638fd1498Szrj       make_edge (body_bb, new_header, EDGE_FALLTHRU);
237738fd1498Szrj       e3->flags = EDGE_FALSE_VALUE;
237838fd1498Szrj       e3->probability = profile_probability::guessed_always ().apply_scale (1, 8);
237938fd1498Szrj       e1 = make_edge (new_header, new_body, EDGE_TRUE_VALUE);
238038fd1498Szrj       e1->probability = e3->probability.invert ();
238138fd1498Szrj 
238238fd1498Szrj       set_immediate_dominator (CDI_DOMINATORS, new_header, body_bb);
238338fd1498Szrj       set_immediate_dominator (CDI_DOMINATORS, new_body, new_header);
238438fd1498Szrj 
238538fd1498Szrj       if (e2)
238638fd1498Szrj 	{
238738fd1498Szrj 	  struct loop *loop = alloc_loop ();
238838fd1498Szrj 	  loop->header = new_header;
238938fd1498Szrj 	  loop->latch = e2->src;
239038fd1498Szrj 	  add_loop (loop, body_bb->loop_father);
239138fd1498Szrj 	}
239238fd1498Szrj     }
239338fd1498Szrj 
239438fd1498Szrj   /* If there are any lastprivate clauses and it is possible some loops
239538fd1498Szrj      might have zero iterations, ensure all the decls are initialized,
239638fd1498Szrj      otherwise we could crash evaluating C++ class iterators with lastprivate
239738fd1498Szrj      clauses.  */
239838fd1498Szrj   bool need_inits = false;
239938fd1498Szrj   for (int i = fd->collapse; ordered_lastprivate && i < fd->ordered; i++)
240038fd1498Szrj     if (need_inits)
240138fd1498Szrj       {
240238fd1498Szrj 	tree type = TREE_TYPE (fd->loops[i].v);
240338fd1498Szrj 	gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
240438fd1498Szrj 	expand_omp_build_assign (&gsi, fd->loops[i].v,
240538fd1498Szrj 				 fold_convert (type, fd->loops[i].n1));
240638fd1498Szrj       }
240738fd1498Szrj     else
240838fd1498Szrj       {
240938fd1498Szrj 	tree type = TREE_TYPE (fd->loops[i].v);
241038fd1498Szrj 	tree this_cond = fold_build2 (fd->loops[i].cond_code,
241138fd1498Szrj 				      boolean_type_node,
241238fd1498Szrj 				      fold_convert (type, fd->loops[i].n1),
241338fd1498Szrj 				      fold_convert (type, fd->loops[i].n2));
241438fd1498Szrj 	if (!integer_onep (this_cond))
241538fd1498Szrj 	  need_inits = true;
241638fd1498Szrj       }
241738fd1498Szrj 
241838fd1498Szrj   return cont_bb;
241938fd1498Szrj }
242038fd1498Szrj 
242138fd1498Szrj /* A subroutine of expand_omp_for.  Generate code for a parallel
242238fd1498Szrj    loop with any schedule.  Given parameters:
242338fd1498Szrj 
242438fd1498Szrj 	for (V = N1; V cond N2; V += STEP) BODY;
242538fd1498Szrj 
242638fd1498Szrj    where COND is "<" or ">", we generate pseudocode
242738fd1498Szrj 
242838fd1498Szrj 	more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
242938fd1498Szrj 	if (more) goto L0; else goto L3;
243038fd1498Szrj     L0:
243138fd1498Szrj 	V = istart0;
243238fd1498Szrj 	iend = iend0;
243338fd1498Szrj     L1:
243438fd1498Szrj 	BODY;
243538fd1498Szrj 	V += STEP;
243638fd1498Szrj 	if (V cond iend) goto L1; else goto L2;
243738fd1498Szrj     L2:
243838fd1498Szrj 	if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
243938fd1498Szrj     L3:
244038fd1498Szrj 
244138fd1498Szrj     If this is a combined omp parallel loop, instead of the call to
244238fd1498Szrj     GOMP_loop_foo_start, we call GOMP_loop_foo_next.
244338fd1498Szrj     If this is gimple_omp_for_combined_p loop, then instead of assigning
244438fd1498Szrj     V and iend in L0 we assign the first two _looptemp_ clause decls of the
244538fd1498Szrj     inner GIMPLE_OMP_FOR and V += STEP; and
244638fd1498Szrj     if (V cond iend) goto L1; else goto L2; are removed.
244738fd1498Szrj 
244838fd1498Szrj     For collapsed loops, given parameters:
244938fd1498Szrj       collapse(3)
245038fd1498Szrj       for (V1 = N11; V1 cond1 N12; V1 += STEP1)
245138fd1498Szrj 	for (V2 = N21; V2 cond2 N22; V2 += STEP2)
245238fd1498Szrj 	  for (V3 = N31; V3 cond3 N32; V3 += STEP3)
245338fd1498Szrj 	    BODY;
245438fd1498Szrj 
245538fd1498Szrj     we generate pseudocode
245638fd1498Szrj 
245738fd1498Szrj 	if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
245838fd1498Szrj 	if (cond3 is <)
245938fd1498Szrj 	  adj = STEP3 - 1;
246038fd1498Szrj 	else
246138fd1498Szrj 	  adj = STEP3 + 1;
246238fd1498Szrj 	count3 = (adj + N32 - N31) / STEP3;
246338fd1498Szrj 	if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
246438fd1498Szrj 	if (cond2 is <)
246538fd1498Szrj 	  adj = STEP2 - 1;
246638fd1498Szrj 	else
246738fd1498Szrj 	  adj = STEP2 + 1;
246838fd1498Szrj 	count2 = (adj + N22 - N21) / STEP2;
246938fd1498Szrj 	if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
247038fd1498Szrj 	if (cond1 is <)
247138fd1498Szrj 	  adj = STEP1 - 1;
247238fd1498Szrj 	else
247338fd1498Szrj 	  adj = STEP1 + 1;
247438fd1498Szrj 	count1 = (adj + N12 - N11) / STEP1;
247538fd1498Szrj 	count = count1 * count2 * count3;
247638fd1498Szrj 	goto Z1;
247738fd1498Szrj     Z0:
247838fd1498Szrj 	count = 0;
247938fd1498Szrj     Z1:
248038fd1498Szrj 	more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
248138fd1498Szrj 	if (more) goto L0; else goto L3;
248238fd1498Szrj     L0:
248338fd1498Szrj 	V = istart0;
248438fd1498Szrj 	T = V;
248538fd1498Szrj 	V3 = N31 + (T % count3) * STEP3;
248638fd1498Szrj 	T = T / count3;
248738fd1498Szrj 	V2 = N21 + (T % count2) * STEP2;
248838fd1498Szrj 	T = T / count2;
248938fd1498Szrj 	V1 = N11 + T * STEP1;
249038fd1498Szrj 	iend = iend0;
249138fd1498Szrj     L1:
249238fd1498Szrj 	BODY;
249338fd1498Szrj 	V += 1;
249438fd1498Szrj 	if (V < iend) goto L10; else goto L2;
249538fd1498Szrj     L10:
249638fd1498Szrj 	V3 += STEP3;
249738fd1498Szrj 	if (V3 cond3 N32) goto L1; else goto L11;
249838fd1498Szrj     L11:
249938fd1498Szrj 	V3 = N31;
250038fd1498Szrj 	V2 += STEP2;
250138fd1498Szrj 	if (V2 cond2 N22) goto L1; else goto L12;
250238fd1498Szrj     L12:
250338fd1498Szrj 	V2 = N21;
250438fd1498Szrj 	V1 += STEP1;
250538fd1498Szrj 	goto L1;
250638fd1498Szrj     L2:
250738fd1498Szrj 	if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
250838fd1498Szrj     L3:
250938fd1498Szrj 
251038fd1498Szrj       */
251138fd1498Szrj 
251238fd1498Szrj static void
expand_omp_for_generic(struct omp_region * region,struct omp_for_data * fd,enum built_in_function start_fn,enum built_in_function next_fn,gimple * inner_stmt)251338fd1498Szrj expand_omp_for_generic (struct omp_region *region,
251438fd1498Szrj 			struct omp_for_data *fd,
251538fd1498Szrj 			enum built_in_function start_fn,
251638fd1498Szrj 			enum built_in_function next_fn,
251738fd1498Szrj 			gimple *inner_stmt)
251838fd1498Szrj {
251938fd1498Szrj   tree type, istart0, iend0, iend;
252038fd1498Szrj   tree t, vmain, vback, bias = NULL_TREE;
252138fd1498Szrj   basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
252238fd1498Szrj   basic_block l2_bb = NULL, l3_bb = NULL;
252338fd1498Szrj   gimple_stmt_iterator gsi;
252438fd1498Szrj   gassign *assign_stmt;
252538fd1498Szrj   bool in_combined_parallel = is_combined_parallel (region);
252638fd1498Szrj   bool broken_loop = region->cont == NULL;
252738fd1498Szrj   edge e, ne;
252838fd1498Szrj   tree *counts = NULL;
252938fd1498Szrj   int i;
253038fd1498Szrj   bool ordered_lastprivate = false;
253138fd1498Szrj 
253238fd1498Szrj   gcc_assert (!broken_loop || !in_combined_parallel);
253338fd1498Szrj   gcc_assert (fd->iter_type == long_integer_type_node
253438fd1498Szrj 	      || !in_combined_parallel);
253538fd1498Szrj 
253638fd1498Szrj   entry_bb = region->entry;
253738fd1498Szrj   cont_bb = region->cont;
253838fd1498Szrj   collapse_bb = NULL;
253938fd1498Szrj   gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
254038fd1498Szrj   gcc_assert (broken_loop
254138fd1498Szrj 	      || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
254238fd1498Szrj   l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
254338fd1498Szrj   l1_bb = single_succ (l0_bb);
254438fd1498Szrj   if (!broken_loop)
254538fd1498Szrj     {
254638fd1498Szrj       l2_bb = create_empty_bb (cont_bb);
254738fd1498Szrj       gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb
254838fd1498Szrj 		  || (single_succ_edge (BRANCH_EDGE (cont_bb)->dest)->dest
254938fd1498Szrj 		      == l1_bb));
255038fd1498Szrj       gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
255138fd1498Szrj     }
255238fd1498Szrj   else
255338fd1498Szrj     l2_bb = NULL;
255438fd1498Szrj   l3_bb = BRANCH_EDGE (entry_bb)->dest;
255538fd1498Szrj   exit_bb = region->exit;
255638fd1498Szrj 
255738fd1498Szrj   gsi = gsi_last_nondebug_bb (entry_bb);
255838fd1498Szrj 
255938fd1498Szrj   gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
256038fd1498Szrj   if (fd->ordered
256138fd1498Szrj       && omp_find_clause (gimple_omp_for_clauses (gsi_stmt (gsi)),
256238fd1498Szrj 			  OMP_CLAUSE_LASTPRIVATE))
256338fd1498Szrj     ordered_lastprivate = false;
256438fd1498Szrj   if (fd->collapse > 1 || fd->ordered)
256538fd1498Szrj     {
256638fd1498Szrj       int first_zero_iter1 = -1, first_zero_iter2 = -1;
256738fd1498Szrj       basic_block zero_iter1_bb = NULL, zero_iter2_bb = NULL, l2_dom_bb = NULL;
256838fd1498Szrj 
256938fd1498Szrj       counts = XALLOCAVEC (tree, fd->ordered ? fd->ordered + 1 : fd->collapse);
257038fd1498Szrj       expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
257138fd1498Szrj 				  zero_iter1_bb, first_zero_iter1,
257238fd1498Szrj 				  zero_iter2_bb, first_zero_iter2, l2_dom_bb);
257338fd1498Szrj 
257438fd1498Szrj       if (zero_iter1_bb)
257538fd1498Szrj 	{
257638fd1498Szrj 	  /* Some counts[i] vars might be uninitialized if
257738fd1498Szrj 	     some loop has zero iterations.  But the body shouldn't
257838fd1498Szrj 	     be executed in that case, so just avoid uninit warnings.  */
257938fd1498Szrj 	  for (i = first_zero_iter1;
258038fd1498Szrj 	       i < (fd->ordered ? fd->ordered : fd->collapse); i++)
258138fd1498Szrj 	    if (SSA_VAR_P (counts[i]))
258238fd1498Szrj 	      TREE_NO_WARNING (counts[i]) = 1;
258338fd1498Szrj 	  gsi_prev (&gsi);
258438fd1498Szrj 	  e = split_block (entry_bb, gsi_stmt (gsi));
258538fd1498Szrj 	  entry_bb = e->dest;
258638fd1498Szrj 	  make_edge (zero_iter1_bb, entry_bb, EDGE_FALLTHRU);
258738fd1498Szrj 	  gsi = gsi_last_nondebug_bb (entry_bb);
258838fd1498Szrj 	  set_immediate_dominator (CDI_DOMINATORS, entry_bb,
258938fd1498Szrj 				   get_immediate_dominator (CDI_DOMINATORS,
259038fd1498Szrj 							    zero_iter1_bb));
259138fd1498Szrj 	}
259238fd1498Szrj       if (zero_iter2_bb)
259338fd1498Szrj 	{
259438fd1498Szrj 	  /* Some counts[i] vars might be uninitialized if
259538fd1498Szrj 	     some loop has zero iterations.  But the body shouldn't
259638fd1498Szrj 	     be executed in that case, so just avoid uninit warnings.  */
259738fd1498Szrj 	  for (i = first_zero_iter2; i < fd->ordered; i++)
259838fd1498Szrj 	    if (SSA_VAR_P (counts[i]))
259938fd1498Szrj 	      TREE_NO_WARNING (counts[i]) = 1;
260038fd1498Szrj 	  if (zero_iter1_bb)
260138fd1498Szrj 	    make_edge (zero_iter2_bb, entry_bb, EDGE_FALLTHRU);
260238fd1498Szrj 	  else
260338fd1498Szrj 	    {
260438fd1498Szrj 	      gsi_prev (&gsi);
260538fd1498Szrj 	      e = split_block (entry_bb, gsi_stmt (gsi));
260638fd1498Szrj 	      entry_bb = e->dest;
260738fd1498Szrj 	      make_edge (zero_iter2_bb, entry_bb, EDGE_FALLTHRU);
260838fd1498Szrj 	      gsi = gsi_last_nondebug_bb (entry_bb);
260938fd1498Szrj 	      set_immediate_dominator (CDI_DOMINATORS, entry_bb,
261038fd1498Szrj 				       get_immediate_dominator
261138fd1498Szrj 					 (CDI_DOMINATORS, zero_iter2_bb));
261238fd1498Szrj 	    }
261338fd1498Szrj 	}
261438fd1498Szrj       if (fd->collapse == 1)
261538fd1498Szrj 	{
261638fd1498Szrj 	  counts[0] = fd->loop.n2;
261738fd1498Szrj 	  fd->loop = fd->loops[0];
261838fd1498Szrj 	}
261938fd1498Szrj     }
262038fd1498Szrj 
262138fd1498Szrj   type = TREE_TYPE (fd->loop.v);
262238fd1498Szrj   istart0 = create_tmp_var (fd->iter_type, ".istart0");
262338fd1498Szrj   iend0 = create_tmp_var (fd->iter_type, ".iend0");
262438fd1498Szrj   TREE_ADDRESSABLE (istart0) = 1;
262538fd1498Szrj   TREE_ADDRESSABLE (iend0) = 1;
262638fd1498Szrj 
262738fd1498Szrj   /* See if we need to bias by LLONG_MIN.  */
262838fd1498Szrj   if (fd->iter_type == long_long_unsigned_type_node
262938fd1498Szrj       && TREE_CODE (type) == INTEGER_TYPE
263038fd1498Szrj       && !TYPE_UNSIGNED (type)
263138fd1498Szrj       && fd->ordered == 0)
263238fd1498Szrj     {
263338fd1498Szrj       tree n1, n2;
263438fd1498Szrj 
263538fd1498Szrj       if (fd->loop.cond_code == LT_EXPR)
263638fd1498Szrj 	{
263738fd1498Szrj 	  n1 = fd->loop.n1;
263838fd1498Szrj 	  n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
263938fd1498Szrj 	}
264038fd1498Szrj       else
264138fd1498Szrj 	{
264238fd1498Szrj 	  n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
264338fd1498Szrj 	  n2 = fd->loop.n1;
264438fd1498Szrj 	}
264538fd1498Szrj       if (TREE_CODE (n1) != INTEGER_CST
264638fd1498Szrj 	  || TREE_CODE (n2) != INTEGER_CST
264738fd1498Szrj 	  || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
264838fd1498Szrj 	bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
264938fd1498Szrj     }
265038fd1498Szrj 
265138fd1498Szrj   gimple_stmt_iterator gsif = gsi;
265238fd1498Szrj   gsi_prev (&gsif);
265338fd1498Szrj 
265438fd1498Szrj   tree arr = NULL_TREE;
265538fd1498Szrj   if (in_combined_parallel)
265638fd1498Szrj     {
265738fd1498Szrj       gcc_assert (fd->ordered == 0);
265838fd1498Szrj       /* In a combined parallel loop, emit a call to
265938fd1498Szrj 	 GOMP_loop_foo_next.  */
266038fd1498Szrj       t = build_call_expr (builtin_decl_explicit (next_fn), 2,
266138fd1498Szrj 			   build_fold_addr_expr (istart0),
266238fd1498Szrj 			   build_fold_addr_expr (iend0));
266338fd1498Szrj     }
266438fd1498Szrj   else
266538fd1498Szrj     {
266638fd1498Szrj       tree t0, t1, t2, t3, t4;
266738fd1498Szrj       /* If this is not a combined parallel loop, emit a call to
266838fd1498Szrj 	 GOMP_loop_foo_start in ENTRY_BB.  */
266938fd1498Szrj       t4 = build_fold_addr_expr (iend0);
267038fd1498Szrj       t3 = build_fold_addr_expr (istart0);
267138fd1498Szrj       if (fd->ordered)
267238fd1498Szrj 	{
267338fd1498Szrj 	  t0 = build_int_cst (unsigned_type_node,
267438fd1498Szrj 			      fd->ordered - fd->collapse + 1);
267538fd1498Szrj 	  arr = create_tmp_var (build_array_type_nelts (fd->iter_type,
267638fd1498Szrj 							fd->ordered
267738fd1498Szrj 							- fd->collapse + 1),
267838fd1498Szrj 				".omp_counts");
267938fd1498Szrj 	  DECL_NAMELESS (arr) = 1;
268038fd1498Szrj 	  TREE_ADDRESSABLE (arr) = 1;
268138fd1498Szrj 	  TREE_STATIC (arr) = 1;
268238fd1498Szrj 	  vec<constructor_elt, va_gc> *v;
268338fd1498Szrj 	  vec_alloc (v, fd->ordered - fd->collapse + 1);
268438fd1498Szrj 	  int idx;
268538fd1498Szrj 
268638fd1498Szrj 	  for (idx = 0; idx < fd->ordered - fd->collapse + 1; idx++)
268738fd1498Szrj 	    {
268838fd1498Szrj 	      tree c;
268938fd1498Szrj 	      if (idx == 0 && fd->collapse > 1)
269038fd1498Szrj 		c = fd->loop.n2;
269138fd1498Szrj 	      else
269238fd1498Szrj 		c = counts[idx + fd->collapse - 1];
269338fd1498Szrj 	      tree purpose = size_int (idx);
269438fd1498Szrj 	      CONSTRUCTOR_APPEND_ELT (v, purpose, c);
269538fd1498Szrj 	      if (TREE_CODE (c) != INTEGER_CST)
269638fd1498Szrj 		TREE_STATIC (arr) = 0;
269738fd1498Szrj 	    }
269838fd1498Szrj 
269938fd1498Szrj 	  DECL_INITIAL (arr) = build_constructor (TREE_TYPE (arr), v);
270038fd1498Szrj 	  if (!TREE_STATIC (arr))
270138fd1498Szrj 	    force_gimple_operand_gsi (&gsi, build1 (DECL_EXPR,
270238fd1498Szrj 						    void_type_node, arr),
270338fd1498Szrj 				      true, NULL_TREE, true, GSI_SAME_STMT);
270438fd1498Szrj 	  t1 = build_fold_addr_expr (arr);
270538fd1498Szrj 	  t2 = NULL_TREE;
270638fd1498Szrj 	}
270738fd1498Szrj       else
270838fd1498Szrj 	{
270938fd1498Szrj 	  t2 = fold_convert (fd->iter_type, fd->loop.step);
271038fd1498Szrj 	  t1 = fd->loop.n2;
271138fd1498Szrj 	  t0 = fd->loop.n1;
271238fd1498Szrj 	  if (gimple_omp_for_combined_into_p (fd->for_stmt))
271338fd1498Szrj 	    {
271438fd1498Szrj 	      tree innerc
271538fd1498Szrj 		= omp_find_clause (gimple_omp_for_clauses (fd->for_stmt),
271638fd1498Szrj 				   OMP_CLAUSE__LOOPTEMP_);
271738fd1498Szrj 	      gcc_assert (innerc);
271838fd1498Szrj 	      t0 = OMP_CLAUSE_DECL (innerc);
271938fd1498Szrj 	      innerc = omp_find_clause (OMP_CLAUSE_CHAIN (innerc),
272038fd1498Szrj 					OMP_CLAUSE__LOOPTEMP_);
272138fd1498Szrj 	      gcc_assert (innerc);
272238fd1498Szrj 	      t1 = OMP_CLAUSE_DECL (innerc);
272338fd1498Szrj 	    }
272438fd1498Szrj 	  if (POINTER_TYPE_P (TREE_TYPE (t0))
272538fd1498Szrj 	      && TYPE_PRECISION (TREE_TYPE (t0))
272638fd1498Szrj 		 != TYPE_PRECISION (fd->iter_type))
272738fd1498Szrj 	    {
272838fd1498Szrj 	      /* Avoid casting pointers to integer of a different size.  */
272938fd1498Szrj 	      tree itype = signed_type_for (type);
273038fd1498Szrj 	      t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
273138fd1498Szrj 	      t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
273238fd1498Szrj 	    }
273338fd1498Szrj 	  else
273438fd1498Szrj 	    {
273538fd1498Szrj 	      t1 = fold_convert (fd->iter_type, t1);
273638fd1498Szrj 	      t0 = fold_convert (fd->iter_type, t0);
273738fd1498Szrj 	    }
273838fd1498Szrj 	  if (bias)
273938fd1498Szrj 	    {
274038fd1498Szrj 	      t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
274138fd1498Szrj 	      t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
274238fd1498Szrj 	    }
274338fd1498Szrj 	}
274438fd1498Szrj       if (fd->iter_type == long_integer_type_node || fd->ordered)
274538fd1498Szrj 	{
274638fd1498Szrj 	  if (fd->chunk_size)
274738fd1498Szrj 	    {
274838fd1498Szrj 	      t = fold_convert (fd->iter_type, fd->chunk_size);
274938fd1498Szrj 	      t = omp_adjust_chunk_size (t, fd->simd_schedule);
275038fd1498Szrj 	      if (fd->ordered)
275138fd1498Szrj 		t = build_call_expr (builtin_decl_explicit (start_fn),
275238fd1498Szrj 				     5, t0, t1, t, t3, t4);
275338fd1498Szrj 	      else
275438fd1498Szrj 		t = build_call_expr (builtin_decl_explicit (start_fn),
275538fd1498Szrj 				     6, t0, t1, t2, t, t3, t4);
275638fd1498Szrj 	    }
275738fd1498Szrj 	  else if (fd->ordered)
275838fd1498Szrj 	    t = build_call_expr (builtin_decl_explicit (start_fn),
275938fd1498Szrj 				 4, t0, t1, t3, t4);
276038fd1498Szrj 	  else
276138fd1498Szrj 	    t = build_call_expr (builtin_decl_explicit (start_fn),
276238fd1498Szrj 				 5, t0, t1, t2, t3, t4);
276338fd1498Szrj 	}
276438fd1498Szrj       else
276538fd1498Szrj 	{
276638fd1498Szrj 	  tree t5;
276738fd1498Szrj 	  tree c_bool_type;
276838fd1498Szrj 	  tree bfn_decl;
276938fd1498Szrj 
277038fd1498Szrj 	  /* The GOMP_loop_ull_*start functions have additional boolean
277138fd1498Szrj 	     argument, true for < loops and false for > loops.
277238fd1498Szrj 	     In Fortran, the C bool type can be different from
277338fd1498Szrj 	     boolean_type_node.  */
277438fd1498Szrj 	  bfn_decl = builtin_decl_explicit (start_fn);
277538fd1498Szrj 	  c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
277638fd1498Szrj 	  t5 = build_int_cst (c_bool_type,
277738fd1498Szrj 			      fd->loop.cond_code == LT_EXPR ? 1 : 0);
277838fd1498Szrj 	  if (fd->chunk_size)
277938fd1498Szrj 	    {
278038fd1498Szrj 	      tree bfn_decl = builtin_decl_explicit (start_fn);
278138fd1498Szrj 	      t = fold_convert (fd->iter_type, fd->chunk_size);
278238fd1498Szrj 	      t = omp_adjust_chunk_size (t, fd->simd_schedule);
278338fd1498Szrj 	      t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
278438fd1498Szrj 	    }
278538fd1498Szrj 	  else
278638fd1498Szrj 	    t = build_call_expr (builtin_decl_explicit (start_fn),
278738fd1498Szrj 				 6, t5, t0, t1, t2, t3, t4);
278838fd1498Szrj 	}
278938fd1498Szrj     }
279038fd1498Szrj   if (TREE_TYPE (t) != boolean_type_node)
279138fd1498Szrj     t = fold_build2 (NE_EXPR, boolean_type_node,
279238fd1498Szrj 		     t, build_int_cst (TREE_TYPE (t), 0));
279338fd1498Szrj   t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
279438fd1498Szrj 				true, GSI_SAME_STMT);
279538fd1498Szrj   if (arr && !TREE_STATIC (arr))
279638fd1498Szrj     {
279738fd1498Szrj       tree clobber = build_constructor (TREE_TYPE (arr), NULL);
279838fd1498Szrj       TREE_THIS_VOLATILE (clobber) = 1;
279938fd1498Szrj       gsi_insert_before (&gsi, gimple_build_assign (arr, clobber),
280038fd1498Szrj 			 GSI_SAME_STMT);
280138fd1498Szrj     }
280238fd1498Szrj   gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
280338fd1498Szrj 
280438fd1498Szrj   /* Remove the GIMPLE_OMP_FOR statement.  */
280538fd1498Szrj   gsi_remove (&gsi, true);
280638fd1498Szrj 
280738fd1498Szrj   if (gsi_end_p (gsif))
280838fd1498Szrj     gsif = gsi_after_labels (gsi_bb (gsif));
280938fd1498Szrj   gsi_next (&gsif);
281038fd1498Szrj 
281138fd1498Szrj   /* Iteration setup for sequential loop goes in L0_BB.  */
281238fd1498Szrj   tree startvar = fd->loop.v;
281338fd1498Szrj   tree endvar = NULL_TREE;
281438fd1498Szrj 
281538fd1498Szrj   if (gimple_omp_for_combined_p (fd->for_stmt))
281638fd1498Szrj     {
281738fd1498Szrj       gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
281838fd1498Szrj 		  && gimple_omp_for_kind (inner_stmt)
281938fd1498Szrj 		     == GF_OMP_FOR_KIND_SIMD);
282038fd1498Szrj       tree innerc = omp_find_clause (gimple_omp_for_clauses (inner_stmt),
282138fd1498Szrj 				     OMP_CLAUSE__LOOPTEMP_);
282238fd1498Szrj       gcc_assert (innerc);
282338fd1498Szrj       startvar = OMP_CLAUSE_DECL (innerc);
282438fd1498Szrj       innerc = omp_find_clause (OMP_CLAUSE_CHAIN (innerc),
282538fd1498Szrj 				OMP_CLAUSE__LOOPTEMP_);
282638fd1498Szrj       gcc_assert (innerc);
282738fd1498Szrj       endvar = OMP_CLAUSE_DECL (innerc);
282838fd1498Szrj     }
282938fd1498Szrj 
283038fd1498Szrj   gsi = gsi_start_bb (l0_bb);
283138fd1498Szrj   t = istart0;
283238fd1498Szrj   if (fd->ordered && fd->collapse == 1)
283338fd1498Szrj     t = fold_build2 (MULT_EXPR, fd->iter_type, t,
283438fd1498Szrj 		     fold_convert (fd->iter_type, fd->loop.step));
283538fd1498Szrj   else if (bias)
283638fd1498Szrj     t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
283738fd1498Szrj   if (fd->ordered && fd->collapse == 1)
283838fd1498Szrj     {
283938fd1498Szrj       if (POINTER_TYPE_P (TREE_TYPE (startvar)))
284038fd1498Szrj 	t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (startvar),
284138fd1498Szrj 			 fd->loop.n1, fold_convert (sizetype, t));
284238fd1498Szrj       else
284338fd1498Szrj 	{
284438fd1498Szrj 	  t = fold_convert (TREE_TYPE (startvar), t);
284538fd1498Szrj 	  t = fold_build2 (PLUS_EXPR, TREE_TYPE (startvar),
284638fd1498Szrj 			   fd->loop.n1, t);
284738fd1498Szrj 	}
284838fd1498Szrj     }
284938fd1498Szrj   else
285038fd1498Szrj     {
285138fd1498Szrj       if (POINTER_TYPE_P (TREE_TYPE (startvar)))
285238fd1498Szrj 	t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
285338fd1498Szrj       t = fold_convert (TREE_TYPE (startvar), t);
285438fd1498Szrj     }
285538fd1498Szrj   t = force_gimple_operand_gsi (&gsi, t,
285638fd1498Szrj 				DECL_P (startvar)
285738fd1498Szrj 				&& TREE_ADDRESSABLE (startvar),
285838fd1498Szrj 				NULL_TREE, false, GSI_CONTINUE_LINKING);
285938fd1498Szrj   assign_stmt = gimple_build_assign (startvar, t);
286038fd1498Szrj   gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
286138fd1498Szrj 
286238fd1498Szrj   t = iend0;
286338fd1498Szrj   if (fd->ordered && fd->collapse == 1)
286438fd1498Szrj     t = fold_build2 (MULT_EXPR, fd->iter_type, t,
286538fd1498Szrj 		     fold_convert (fd->iter_type, fd->loop.step));
286638fd1498Szrj   else if (bias)
286738fd1498Szrj     t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
286838fd1498Szrj   if (fd->ordered && fd->collapse == 1)
286938fd1498Szrj     {
287038fd1498Szrj       if (POINTER_TYPE_P (TREE_TYPE (startvar)))
287138fd1498Szrj 	t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (startvar),
287238fd1498Szrj 			 fd->loop.n1, fold_convert (sizetype, t));
287338fd1498Szrj       else
287438fd1498Szrj 	{
287538fd1498Szrj 	  t = fold_convert (TREE_TYPE (startvar), t);
287638fd1498Szrj 	  t = fold_build2 (PLUS_EXPR, TREE_TYPE (startvar),
287738fd1498Szrj 			   fd->loop.n1, t);
287838fd1498Szrj 	}
287938fd1498Szrj     }
288038fd1498Szrj   else
288138fd1498Szrj     {
288238fd1498Szrj       if (POINTER_TYPE_P (TREE_TYPE (startvar)))
288338fd1498Szrj 	t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
288438fd1498Szrj       t = fold_convert (TREE_TYPE (startvar), t);
288538fd1498Szrj     }
288638fd1498Szrj   iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
288738fd1498Szrj 				   false, GSI_CONTINUE_LINKING);
288838fd1498Szrj   if (endvar)
288938fd1498Szrj     {
289038fd1498Szrj       assign_stmt = gimple_build_assign (endvar, iend);
289138fd1498Szrj       gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
289238fd1498Szrj       if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (iend)))
289338fd1498Szrj 	assign_stmt = gimple_build_assign (fd->loop.v, iend);
289438fd1498Szrj       else
289538fd1498Szrj 	assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, iend);
289638fd1498Szrj       gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
289738fd1498Szrj     }
289838fd1498Szrj   /* Handle linear clause adjustments.  */
289938fd1498Szrj   tree itercnt = NULL_TREE;
290038fd1498Szrj   if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
290138fd1498Szrj     for (tree c = gimple_omp_for_clauses (fd->for_stmt);
290238fd1498Szrj 	 c; c = OMP_CLAUSE_CHAIN (c))
290338fd1498Szrj       if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
290438fd1498Szrj 	  && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
290538fd1498Szrj 	{
290638fd1498Szrj 	  tree d = OMP_CLAUSE_DECL (c);
290738fd1498Szrj 	  bool is_ref = omp_is_reference (d);
290838fd1498Szrj 	  tree t = d, a, dest;
290938fd1498Szrj 	  if (is_ref)
291038fd1498Szrj 	    t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
291138fd1498Szrj 	  tree type = TREE_TYPE (t);
291238fd1498Szrj 	  if (POINTER_TYPE_P (type))
291338fd1498Szrj 	    type = sizetype;
291438fd1498Szrj 	  dest = unshare_expr (t);
291538fd1498Szrj 	  tree v = create_tmp_var (TREE_TYPE (t), NULL);
291638fd1498Szrj 	  expand_omp_build_assign (&gsif, v, t);
291738fd1498Szrj 	  if (itercnt == NULL_TREE)
291838fd1498Szrj 	    {
291938fd1498Szrj 	      itercnt = startvar;
292038fd1498Szrj 	      tree n1 = fd->loop.n1;
292138fd1498Szrj 	      if (POINTER_TYPE_P (TREE_TYPE (itercnt)))
292238fd1498Szrj 		{
292338fd1498Szrj 		  itercnt
292438fd1498Szrj 		    = fold_convert (signed_type_for (TREE_TYPE (itercnt)),
292538fd1498Szrj 				    itercnt);
292638fd1498Szrj 		  n1 = fold_convert (TREE_TYPE (itercnt), n1);
292738fd1498Szrj 		}
292838fd1498Szrj 	      itercnt = fold_build2 (MINUS_EXPR, TREE_TYPE (itercnt),
292938fd1498Szrj 				     itercnt, n1);
293038fd1498Szrj 	      itercnt = fold_build2 (EXACT_DIV_EXPR, TREE_TYPE (itercnt),
293138fd1498Szrj 				     itercnt, fd->loop.step);
293238fd1498Szrj 	      itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
293338fd1498Szrj 						  NULL_TREE, false,
293438fd1498Szrj 						  GSI_CONTINUE_LINKING);
293538fd1498Szrj 	    }
293638fd1498Szrj 	  a = fold_build2 (MULT_EXPR, type,
293738fd1498Szrj 			   fold_convert (type, itercnt),
293838fd1498Szrj 			   fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
293938fd1498Szrj 	  t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
294038fd1498Szrj 			   : POINTER_PLUS_EXPR, TREE_TYPE (t), v, a);
294138fd1498Szrj 	  t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
294238fd1498Szrj 					false, GSI_CONTINUE_LINKING);
294338fd1498Szrj 	  assign_stmt = gimple_build_assign (dest, t);
294438fd1498Szrj 	  gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
294538fd1498Szrj 	}
294638fd1498Szrj   if (fd->collapse > 1)
294738fd1498Szrj     expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
294838fd1498Szrj 
294938fd1498Szrj   if (fd->ordered)
295038fd1498Szrj     {
295138fd1498Szrj       /* Until now, counts array contained number of iterations or
295238fd1498Szrj 	 variable containing it for ith loop.  From now on, we need
295338fd1498Szrj 	 those counts only for collapsed loops, and only for the 2nd
295438fd1498Szrj 	 till the last collapsed one.  Move those one element earlier,
295538fd1498Szrj 	 we'll use counts[fd->collapse - 1] for the first source/sink
295638fd1498Szrj 	 iteration counter and so on and counts[fd->ordered]
295738fd1498Szrj 	 as the array holding the current counter values for
295838fd1498Szrj 	 depend(source).  */
295938fd1498Szrj       if (fd->collapse > 1)
296038fd1498Szrj 	memmove (counts, counts + 1, (fd->collapse - 1) * sizeof (counts[0]));
296138fd1498Szrj       if (broken_loop)
296238fd1498Szrj 	{
296338fd1498Szrj 	  int i;
296438fd1498Szrj 	  for (i = fd->collapse; i < fd->ordered; i++)
296538fd1498Szrj 	    {
296638fd1498Szrj 	      tree type = TREE_TYPE (fd->loops[i].v);
296738fd1498Szrj 	      tree this_cond
296838fd1498Szrj 		= fold_build2 (fd->loops[i].cond_code, boolean_type_node,
296938fd1498Szrj 			       fold_convert (type, fd->loops[i].n1),
297038fd1498Szrj 			       fold_convert (type, fd->loops[i].n2));
297138fd1498Szrj 	      if (!integer_onep (this_cond))
297238fd1498Szrj 		break;
297338fd1498Szrj 	    }
297438fd1498Szrj 	  if (i < fd->ordered)
297538fd1498Szrj 	    {
297638fd1498Szrj 	      cont_bb
297738fd1498Szrj 		= create_empty_bb (EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb);
297838fd1498Szrj 	      add_bb_to_loop (cont_bb, l1_bb->loop_father);
297938fd1498Szrj 	      gimple_stmt_iterator gsi = gsi_after_labels (cont_bb);
298038fd1498Szrj 	      gimple *g = gimple_build_omp_continue (fd->loop.v, fd->loop.v);
298138fd1498Szrj 	      gsi_insert_before (&gsi, g, GSI_SAME_STMT);
298238fd1498Szrj 	      make_edge (cont_bb, l3_bb, EDGE_FALLTHRU);
298338fd1498Szrj 	      make_edge (cont_bb, l1_bb, 0);
298438fd1498Szrj 	      l2_bb = create_empty_bb (cont_bb);
298538fd1498Szrj 	      broken_loop = false;
298638fd1498Szrj 	    }
298738fd1498Szrj 	}
298838fd1498Szrj       expand_omp_ordered_source_sink (region, fd, counts, cont_bb);
298938fd1498Szrj       cont_bb = expand_omp_for_ordered_loops (fd, counts, cont_bb, l1_bb,
299038fd1498Szrj 					      ordered_lastprivate);
299138fd1498Szrj       if (counts[fd->collapse - 1])
299238fd1498Szrj 	{
299338fd1498Szrj 	  gcc_assert (fd->collapse == 1);
299438fd1498Szrj 	  gsi = gsi_last_bb (l0_bb);
299538fd1498Szrj 	  expand_omp_build_assign (&gsi, counts[fd->collapse - 1],
299638fd1498Szrj 				   istart0, true);
299738fd1498Szrj 	  gsi = gsi_last_bb (cont_bb);
299838fd1498Szrj 	  t = fold_build2 (PLUS_EXPR, fd->iter_type, counts[fd->collapse - 1],
299938fd1498Szrj 			   build_int_cst (fd->iter_type, 1));
300038fd1498Szrj 	  expand_omp_build_assign (&gsi, counts[fd->collapse - 1], t);
300138fd1498Szrj 	  tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
300238fd1498Szrj 			      size_zero_node, NULL_TREE, NULL_TREE);
300338fd1498Szrj 	  expand_omp_build_assign (&gsi, aref, counts[fd->collapse - 1]);
300438fd1498Szrj 	  t = counts[fd->collapse - 1];
300538fd1498Szrj 	}
300638fd1498Szrj       else if (fd->collapse > 1)
300738fd1498Szrj 	t = fd->loop.v;
300838fd1498Szrj       else
300938fd1498Szrj 	{
301038fd1498Szrj 	  t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[0].v),
301138fd1498Szrj 			   fd->loops[0].v, fd->loops[0].n1);
301238fd1498Szrj 	  t = fold_convert (fd->iter_type, t);
301338fd1498Szrj 	}
301438fd1498Szrj       gsi = gsi_last_bb (l0_bb);
301538fd1498Szrj       tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
301638fd1498Szrj 			  size_zero_node, NULL_TREE, NULL_TREE);
301738fd1498Szrj       t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
301838fd1498Szrj 				    false, GSI_CONTINUE_LINKING);
301938fd1498Szrj       expand_omp_build_assign (&gsi, aref, t, true);
302038fd1498Szrj     }
302138fd1498Szrj 
302238fd1498Szrj   if (!broken_loop)
302338fd1498Szrj     {
302438fd1498Szrj       /* Code to control the increment and predicate for the sequential
302538fd1498Szrj 	 loop goes in the CONT_BB.  */
302638fd1498Szrj       gsi = gsi_last_nondebug_bb (cont_bb);
302738fd1498Szrj       gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
302838fd1498Szrj       gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
302938fd1498Szrj       vmain = gimple_omp_continue_control_use (cont_stmt);
303038fd1498Szrj       vback = gimple_omp_continue_control_def (cont_stmt);
303138fd1498Szrj 
303238fd1498Szrj       if (!gimple_omp_for_combined_p (fd->for_stmt))
303338fd1498Szrj 	{
303438fd1498Szrj 	  if (POINTER_TYPE_P (type))
303538fd1498Szrj 	    t = fold_build_pointer_plus (vmain, fd->loop.step);
303638fd1498Szrj 	  else
303738fd1498Szrj 	    t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
303838fd1498Szrj 	  t = force_gimple_operand_gsi (&gsi, t,
303938fd1498Szrj 					DECL_P (vback)
304038fd1498Szrj 					&& TREE_ADDRESSABLE (vback),
304138fd1498Szrj 					NULL_TREE, true, GSI_SAME_STMT);
304238fd1498Szrj 	  assign_stmt = gimple_build_assign (vback, t);
304338fd1498Szrj 	  gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
304438fd1498Szrj 
304538fd1498Szrj 	  if (fd->ordered && counts[fd->collapse - 1] == NULL_TREE)
304638fd1498Szrj 	    {
3047*58e805e6Szrj 	      tree tem;
304838fd1498Szrj 	      if (fd->collapse > 1)
3049*58e805e6Szrj 		tem = fd->loop.v;
305038fd1498Szrj 	      else
305138fd1498Szrj 		{
3052*58e805e6Szrj 		  tem = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[0].v),
305338fd1498Szrj 				     fd->loops[0].v, fd->loops[0].n1);
3054*58e805e6Szrj 		  tem = fold_convert (fd->iter_type, tem);
305538fd1498Szrj 		}
305638fd1498Szrj 	      tree aref = build4 (ARRAY_REF, fd->iter_type,
305738fd1498Szrj 				  counts[fd->ordered], size_zero_node,
305838fd1498Szrj 				  NULL_TREE, NULL_TREE);
3059*58e805e6Szrj 	      tem = force_gimple_operand_gsi (&gsi, tem, true, NULL_TREE,
306038fd1498Szrj 					      true, GSI_SAME_STMT);
3061*58e805e6Szrj 	      expand_omp_build_assign (&gsi, aref, tem);
306238fd1498Szrj 	    }
306338fd1498Szrj 
306438fd1498Szrj 	  t = build2 (fd->loop.cond_code, boolean_type_node,
306538fd1498Szrj 		      DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
306638fd1498Szrj 		      iend);
306738fd1498Szrj 	  gcond *cond_stmt = gimple_build_cond_empty (t);
306838fd1498Szrj 	  gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
306938fd1498Szrj 	}
307038fd1498Szrj 
307138fd1498Szrj       /* Remove GIMPLE_OMP_CONTINUE.  */
307238fd1498Szrj       gsi_remove (&gsi, true);
307338fd1498Szrj 
307438fd1498Szrj       if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
307538fd1498Szrj 	collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
307638fd1498Szrj 
307738fd1498Szrj       /* Emit code to get the next parallel iteration in L2_BB.  */
307838fd1498Szrj       gsi = gsi_start_bb (l2_bb);
307938fd1498Szrj 
308038fd1498Szrj       t = build_call_expr (builtin_decl_explicit (next_fn), 2,
308138fd1498Szrj 			   build_fold_addr_expr (istart0),
308238fd1498Szrj 			   build_fold_addr_expr (iend0));
308338fd1498Szrj       t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
308438fd1498Szrj 				    false, GSI_CONTINUE_LINKING);
308538fd1498Szrj       if (TREE_TYPE (t) != boolean_type_node)
308638fd1498Szrj 	t = fold_build2 (NE_EXPR, boolean_type_node,
308738fd1498Szrj 			 t, build_int_cst (TREE_TYPE (t), 0));
308838fd1498Szrj       gcond *cond_stmt = gimple_build_cond_empty (t);
308938fd1498Szrj       gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
309038fd1498Szrj     }
309138fd1498Szrj 
309238fd1498Szrj   /* Add the loop cleanup function.  */
309338fd1498Szrj   gsi = gsi_last_nondebug_bb (exit_bb);
309438fd1498Szrj   if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
309538fd1498Szrj     t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
309638fd1498Szrj   else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
309738fd1498Szrj     t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
309838fd1498Szrj   else
309938fd1498Szrj     t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
310038fd1498Szrj   gcall *call_stmt = gimple_build_call (t, 0);
310138fd1498Szrj   if (gimple_omp_return_lhs (gsi_stmt (gsi)))
310238fd1498Szrj     gimple_call_set_lhs (call_stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
310338fd1498Szrj   gsi_insert_after (&gsi, call_stmt, GSI_SAME_STMT);
310438fd1498Szrj   if (fd->ordered)
310538fd1498Szrj     {
310638fd1498Szrj       tree arr = counts[fd->ordered];
310738fd1498Szrj       tree clobber = build_constructor (TREE_TYPE (arr), NULL);
310838fd1498Szrj       TREE_THIS_VOLATILE (clobber) = 1;
310938fd1498Szrj       gsi_insert_after (&gsi, gimple_build_assign (arr, clobber),
311038fd1498Szrj 			GSI_SAME_STMT);
311138fd1498Szrj     }
311238fd1498Szrj   gsi_remove (&gsi, true);
311338fd1498Szrj 
311438fd1498Szrj   /* Connect the new blocks.  */
311538fd1498Szrj   find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
311638fd1498Szrj   find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
311738fd1498Szrj 
311838fd1498Szrj   if (!broken_loop)
311938fd1498Szrj     {
312038fd1498Szrj       gimple_seq phis;
312138fd1498Szrj 
312238fd1498Szrj       e = find_edge (cont_bb, l3_bb);
312338fd1498Szrj       ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
312438fd1498Szrj 
312538fd1498Szrj       phis = phi_nodes (l3_bb);
312638fd1498Szrj       for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
312738fd1498Szrj 	{
312838fd1498Szrj 	  gimple *phi = gsi_stmt (gsi);
312938fd1498Szrj 	  SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
313038fd1498Szrj 		   PHI_ARG_DEF_FROM_EDGE (phi, e));
313138fd1498Szrj 	}
313238fd1498Szrj       remove_edge (e);
313338fd1498Szrj 
313438fd1498Szrj       make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
313538fd1498Szrj       e = find_edge (cont_bb, l1_bb);
313638fd1498Szrj       if (e == NULL)
313738fd1498Szrj 	{
313838fd1498Szrj 	  e = BRANCH_EDGE (cont_bb);
313938fd1498Szrj 	  gcc_assert (single_succ (e->dest) == l1_bb);
314038fd1498Szrj 	}
314138fd1498Szrj       if (gimple_omp_for_combined_p (fd->for_stmt))
314238fd1498Szrj 	{
314338fd1498Szrj 	  remove_edge (e);
314438fd1498Szrj 	  e = NULL;
314538fd1498Szrj 	}
314638fd1498Szrj       else if (fd->collapse > 1)
314738fd1498Szrj 	{
314838fd1498Szrj 	  remove_edge (e);
314938fd1498Szrj 	  e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
315038fd1498Szrj 	}
315138fd1498Szrj       else
315238fd1498Szrj 	e->flags = EDGE_TRUE_VALUE;
315338fd1498Szrj       if (e)
315438fd1498Szrj 	{
315538fd1498Szrj 	  e->probability = profile_probability::guessed_always ().apply_scale (7, 8);
315638fd1498Szrj 	  find_edge (cont_bb, l2_bb)->probability = e->probability.invert ();
315738fd1498Szrj 	}
315838fd1498Szrj       else
315938fd1498Szrj 	{
316038fd1498Szrj 	  e = find_edge (cont_bb, l2_bb);
316138fd1498Szrj 	  e->flags = EDGE_FALLTHRU;
316238fd1498Szrj 	}
316338fd1498Szrj       make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
316438fd1498Szrj 
316538fd1498Szrj       if (gimple_in_ssa_p (cfun))
316638fd1498Szrj 	{
316738fd1498Szrj 	  /* Add phis to the outer loop that connect to the phis in the inner,
316838fd1498Szrj 	     original loop, and move the loop entry value of the inner phi to
316938fd1498Szrj 	     the loop entry value of the outer phi.  */
317038fd1498Szrj 	  gphi_iterator psi;
317138fd1498Szrj 	  for (psi = gsi_start_phis (l3_bb); !gsi_end_p (psi); gsi_next (&psi))
317238fd1498Szrj 	    {
317338fd1498Szrj 	      source_location locus;
317438fd1498Szrj 	      gphi *nphi;
317538fd1498Szrj 	      gphi *exit_phi = psi.phi ();
317638fd1498Szrj 
317738fd1498Szrj 	      if (virtual_operand_p (gimple_phi_result (exit_phi)))
317838fd1498Szrj 		continue;
317938fd1498Szrj 
318038fd1498Szrj 	      edge l2_to_l3 = find_edge (l2_bb, l3_bb);
318138fd1498Szrj 	      tree exit_res = PHI_ARG_DEF_FROM_EDGE (exit_phi, l2_to_l3);
318238fd1498Szrj 
318338fd1498Szrj 	      basic_block latch = BRANCH_EDGE (cont_bb)->dest;
318438fd1498Szrj 	      edge latch_to_l1 = find_edge (latch, l1_bb);
318538fd1498Szrj 	      gphi *inner_phi
318638fd1498Szrj 		= find_phi_with_arg_on_edge (exit_res, latch_to_l1);
318738fd1498Szrj 
318838fd1498Szrj 	      tree t = gimple_phi_result (exit_phi);
318938fd1498Szrj 	      tree new_res = copy_ssa_name (t, NULL);
319038fd1498Szrj 	      nphi = create_phi_node (new_res, l0_bb);
319138fd1498Szrj 
319238fd1498Szrj 	      edge l0_to_l1 = find_edge (l0_bb, l1_bb);
319338fd1498Szrj 	      t = PHI_ARG_DEF_FROM_EDGE (inner_phi, l0_to_l1);
319438fd1498Szrj 	      locus = gimple_phi_arg_location_from_edge (inner_phi, l0_to_l1);
319538fd1498Szrj 	      edge entry_to_l0 = find_edge (entry_bb, l0_bb);
319638fd1498Szrj 	      add_phi_arg (nphi, t, entry_to_l0, locus);
319738fd1498Szrj 
319838fd1498Szrj 	      edge l2_to_l0 = find_edge (l2_bb, l0_bb);
319938fd1498Szrj 	      add_phi_arg (nphi, exit_res, l2_to_l0, UNKNOWN_LOCATION);
320038fd1498Szrj 
320138fd1498Szrj 	      add_phi_arg (inner_phi, new_res, l0_to_l1, UNKNOWN_LOCATION);
320238fd1498Szrj 	    }
320338fd1498Szrj 	}
320438fd1498Szrj 
320538fd1498Szrj       set_immediate_dominator (CDI_DOMINATORS, l2_bb,
320638fd1498Szrj 			       recompute_dominator (CDI_DOMINATORS, l2_bb));
320738fd1498Szrj       set_immediate_dominator (CDI_DOMINATORS, l3_bb,
320838fd1498Szrj 			       recompute_dominator (CDI_DOMINATORS, l3_bb));
320938fd1498Szrj       set_immediate_dominator (CDI_DOMINATORS, l0_bb,
321038fd1498Szrj 			       recompute_dominator (CDI_DOMINATORS, l0_bb));
321138fd1498Szrj       set_immediate_dominator (CDI_DOMINATORS, l1_bb,
321238fd1498Szrj 			       recompute_dominator (CDI_DOMINATORS, l1_bb));
321338fd1498Szrj 
321438fd1498Szrj       /* We enter expand_omp_for_generic with a loop.  This original loop may
321538fd1498Szrj 	 have its own loop struct, or it may be part of an outer loop struct
321638fd1498Szrj 	 (which may be the fake loop).  */
321738fd1498Szrj       struct loop *outer_loop = entry_bb->loop_father;
321838fd1498Szrj       bool orig_loop_has_loop_struct = l1_bb->loop_father != outer_loop;
321938fd1498Szrj 
322038fd1498Szrj       add_bb_to_loop (l2_bb, outer_loop);
322138fd1498Szrj 
322238fd1498Szrj       /* We've added a new loop around the original loop.  Allocate the
322338fd1498Szrj 	 corresponding loop struct.  */
322438fd1498Szrj       struct loop *new_loop = alloc_loop ();
322538fd1498Szrj       new_loop->header = l0_bb;
322638fd1498Szrj       new_loop->latch = l2_bb;
322738fd1498Szrj       add_loop (new_loop, outer_loop);
322838fd1498Szrj 
322938fd1498Szrj       /* Allocate a loop structure for the original loop unless we already
323038fd1498Szrj 	 had one.  */
323138fd1498Szrj       if (!orig_loop_has_loop_struct
323238fd1498Szrj 	  && !gimple_omp_for_combined_p (fd->for_stmt))
323338fd1498Szrj 	{
323438fd1498Szrj 	  struct loop *orig_loop = alloc_loop ();
323538fd1498Szrj 	  orig_loop->header = l1_bb;
323638fd1498Szrj 	  /* The loop may have multiple latches.  */
323738fd1498Szrj 	  add_loop (orig_loop, new_loop);
323838fd1498Szrj 	}
323938fd1498Szrj     }
324038fd1498Szrj }
324138fd1498Szrj 
324238fd1498Szrj /* A subroutine of expand_omp_for.  Generate code for a parallel
324338fd1498Szrj    loop with static schedule and no specified chunk size.  Given
324438fd1498Szrj    parameters:
324538fd1498Szrj 
324638fd1498Szrj 	for (V = N1; V cond N2; V += STEP) BODY;
324738fd1498Szrj 
324838fd1498Szrj    where COND is "<" or ">", we generate pseudocode
324938fd1498Szrj 
325038fd1498Szrj 	if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
325138fd1498Szrj 	if (cond is <)
325238fd1498Szrj 	  adj = STEP - 1;
325338fd1498Szrj 	else
325438fd1498Szrj 	  adj = STEP + 1;
325538fd1498Szrj 	if ((__typeof (V)) -1 > 0 && cond is >)
325638fd1498Szrj 	  n = -(adj + N2 - N1) / -STEP;
325738fd1498Szrj 	else
325838fd1498Szrj 	  n = (adj + N2 - N1) / STEP;
325938fd1498Szrj 	q = n / nthreads;
326038fd1498Szrj 	tt = n % nthreads;
326138fd1498Szrj 	if (threadid < tt) goto L3; else goto L4;
326238fd1498Szrj     L3:
326338fd1498Szrj 	tt = 0;
326438fd1498Szrj 	q = q + 1;
326538fd1498Szrj     L4:
326638fd1498Szrj 	s0 = q * threadid + tt;
326738fd1498Szrj 	e0 = s0 + q;
326838fd1498Szrj 	V = s0 * STEP + N1;
326938fd1498Szrj 	if (s0 >= e0) goto L2; else goto L0;
327038fd1498Szrj     L0:
327138fd1498Szrj 	e = e0 * STEP + N1;
327238fd1498Szrj     L1:
327338fd1498Szrj 	BODY;
327438fd1498Szrj 	V += STEP;
327538fd1498Szrj 	if (V cond e) goto L1;
327638fd1498Szrj     L2:
327738fd1498Szrj */
327838fd1498Szrj 
327938fd1498Szrj static void
expand_omp_for_static_nochunk(struct omp_region * region,struct omp_for_data * fd,gimple * inner_stmt)328038fd1498Szrj expand_omp_for_static_nochunk (struct omp_region *region,
328138fd1498Szrj 			       struct omp_for_data *fd,
328238fd1498Szrj 			       gimple *inner_stmt)
328338fd1498Szrj {
328438fd1498Szrj   tree n, q, s0, e0, e, t, tt, nthreads, threadid;
328538fd1498Szrj   tree type, itype, vmain, vback;
328638fd1498Szrj   basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
328738fd1498Szrj   basic_block body_bb, cont_bb, collapse_bb = NULL;
328838fd1498Szrj   basic_block fin_bb;
328938fd1498Szrj   gimple_stmt_iterator gsi;
329038fd1498Szrj   edge ep;
329138fd1498Szrj   bool broken_loop = region->cont == NULL;
329238fd1498Szrj   tree *counts = NULL;
329338fd1498Szrj   tree n1, n2, step;
329438fd1498Szrj 
329538fd1498Szrj   itype = type = TREE_TYPE (fd->loop.v);
329638fd1498Szrj   if (POINTER_TYPE_P (type))
329738fd1498Szrj     itype = signed_type_for (type);
329838fd1498Szrj 
329938fd1498Szrj   entry_bb = region->entry;
330038fd1498Szrj   cont_bb = region->cont;
330138fd1498Szrj   gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
330238fd1498Szrj   fin_bb = BRANCH_EDGE (entry_bb)->dest;
330338fd1498Szrj   gcc_assert (broken_loop
330438fd1498Szrj 	      || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
330538fd1498Szrj   seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
330638fd1498Szrj   body_bb = single_succ (seq_start_bb);
330738fd1498Szrj   if (!broken_loop)
330838fd1498Szrj     {
330938fd1498Szrj       gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb
331038fd1498Szrj 		  || single_succ (BRANCH_EDGE (cont_bb)->dest) == body_bb);
331138fd1498Szrj       gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
331238fd1498Szrj     }
331338fd1498Szrj   exit_bb = region->exit;
331438fd1498Szrj 
331538fd1498Szrj   /* Iteration space partitioning goes in ENTRY_BB.  */
331638fd1498Szrj   gsi = gsi_last_nondebug_bb (entry_bb);
331738fd1498Szrj   gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
331838fd1498Szrj 
331938fd1498Szrj   if (fd->collapse > 1)
332038fd1498Szrj     {
332138fd1498Szrj       int first_zero_iter = -1, dummy = -1;
332238fd1498Szrj       basic_block l2_dom_bb = NULL, dummy_bb = NULL;
332338fd1498Szrj 
332438fd1498Szrj       counts = XALLOCAVEC (tree, fd->collapse);
332538fd1498Szrj       expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
332638fd1498Szrj 				  fin_bb, first_zero_iter,
332738fd1498Szrj 				  dummy_bb, dummy, l2_dom_bb);
332838fd1498Szrj       t = NULL_TREE;
332938fd1498Szrj     }
333038fd1498Szrj   else if (gimple_omp_for_combined_into_p (fd->for_stmt))
333138fd1498Szrj     t = integer_one_node;
333238fd1498Szrj   else
333338fd1498Szrj     t = fold_binary (fd->loop.cond_code, boolean_type_node,
333438fd1498Szrj 		     fold_convert (type, fd->loop.n1),
333538fd1498Szrj 		     fold_convert (type, fd->loop.n2));
333638fd1498Szrj   if (fd->collapse == 1
333738fd1498Szrj       && TYPE_UNSIGNED (type)
333838fd1498Szrj       && (t == NULL_TREE || !integer_onep (t)))
333938fd1498Szrj     {
334038fd1498Szrj       n1 = fold_convert (type, unshare_expr (fd->loop.n1));
334138fd1498Szrj       n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
334238fd1498Szrj 				     true, GSI_SAME_STMT);
334338fd1498Szrj       n2 = fold_convert (type, unshare_expr (fd->loop.n2));
334438fd1498Szrj       n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
334538fd1498Szrj 				     true, GSI_SAME_STMT);
334638fd1498Szrj       gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
334738fd1498Szrj 						 NULL_TREE, NULL_TREE);
334838fd1498Szrj       gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
334938fd1498Szrj       if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
335038fd1498Szrj 		     expand_omp_regimplify_p, NULL, NULL)
335138fd1498Szrj 	  || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
335238fd1498Szrj 			expand_omp_regimplify_p, NULL, NULL))
335338fd1498Szrj 	{
335438fd1498Szrj 	  gsi = gsi_for_stmt (cond_stmt);
335538fd1498Szrj 	  gimple_regimplify_operands (cond_stmt, &gsi);
335638fd1498Szrj 	}
335738fd1498Szrj       ep = split_block (entry_bb, cond_stmt);
335838fd1498Szrj       ep->flags = EDGE_TRUE_VALUE;
335938fd1498Szrj       entry_bb = ep->dest;
336038fd1498Szrj       ep->probability = profile_probability::very_likely ();
336138fd1498Szrj       ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
336238fd1498Szrj       ep->probability = profile_probability::very_unlikely ();
336338fd1498Szrj       if (gimple_in_ssa_p (cfun))
336438fd1498Szrj 	{
336538fd1498Szrj 	  int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
336638fd1498Szrj 	  for (gphi_iterator gpi = gsi_start_phis (fin_bb);
336738fd1498Szrj 	       !gsi_end_p (gpi); gsi_next (&gpi))
336838fd1498Szrj 	    {
336938fd1498Szrj 	      gphi *phi = gpi.phi ();
337038fd1498Szrj 	      add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
337138fd1498Szrj 			   ep, UNKNOWN_LOCATION);
337238fd1498Szrj 	    }
337338fd1498Szrj 	}
337438fd1498Szrj       gsi = gsi_last_bb (entry_bb);
337538fd1498Szrj     }
337638fd1498Szrj 
337738fd1498Szrj   switch (gimple_omp_for_kind (fd->for_stmt))
337838fd1498Szrj     {
337938fd1498Szrj     case GF_OMP_FOR_KIND_FOR:
338038fd1498Szrj       nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
338138fd1498Szrj       threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
338238fd1498Szrj       break;
338338fd1498Szrj     case GF_OMP_FOR_KIND_DISTRIBUTE:
338438fd1498Szrj       nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
338538fd1498Szrj       threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
338638fd1498Szrj       break;
338738fd1498Szrj     default:
338838fd1498Szrj       gcc_unreachable ();
338938fd1498Szrj     }
339038fd1498Szrj   nthreads = build_call_expr (nthreads, 0);
339138fd1498Szrj   nthreads = fold_convert (itype, nthreads);
339238fd1498Szrj   nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
339338fd1498Szrj 				       true, GSI_SAME_STMT);
339438fd1498Szrj   threadid = build_call_expr (threadid, 0);
339538fd1498Szrj   threadid = fold_convert (itype, threadid);
339638fd1498Szrj   threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
339738fd1498Szrj 				       true, GSI_SAME_STMT);
339838fd1498Szrj 
339938fd1498Szrj   n1 = fd->loop.n1;
340038fd1498Szrj   n2 = fd->loop.n2;
340138fd1498Szrj   step = fd->loop.step;
340238fd1498Szrj   if (gimple_omp_for_combined_into_p (fd->for_stmt))
340338fd1498Szrj     {
340438fd1498Szrj       tree innerc = omp_find_clause (gimple_omp_for_clauses (fd->for_stmt),
340538fd1498Szrj 				     OMP_CLAUSE__LOOPTEMP_);
340638fd1498Szrj       gcc_assert (innerc);
340738fd1498Szrj       n1 = OMP_CLAUSE_DECL (innerc);
340838fd1498Szrj       innerc = omp_find_clause (OMP_CLAUSE_CHAIN (innerc),
340938fd1498Szrj 				OMP_CLAUSE__LOOPTEMP_);
341038fd1498Szrj       gcc_assert (innerc);
341138fd1498Szrj       n2 = OMP_CLAUSE_DECL (innerc);
341238fd1498Szrj     }
341338fd1498Szrj   n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
341438fd1498Szrj 				 true, NULL_TREE, true, GSI_SAME_STMT);
341538fd1498Szrj   n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
341638fd1498Szrj 				 true, NULL_TREE, true, GSI_SAME_STMT);
341738fd1498Szrj   step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
341838fd1498Szrj 				   true, NULL_TREE, true, GSI_SAME_STMT);
341938fd1498Szrj 
342038fd1498Szrj   t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
342138fd1498Szrj   t = fold_build2 (PLUS_EXPR, itype, step, t);
342238fd1498Szrj   t = fold_build2 (PLUS_EXPR, itype, t, n2);
342338fd1498Szrj   t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
342438fd1498Szrj   if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
342538fd1498Szrj     t = fold_build2 (TRUNC_DIV_EXPR, itype,
342638fd1498Szrj 		     fold_build1 (NEGATE_EXPR, itype, t),
342738fd1498Szrj 		     fold_build1 (NEGATE_EXPR, itype, step));
342838fd1498Szrj   else
342938fd1498Szrj     t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
343038fd1498Szrj   t = fold_convert (itype, t);
343138fd1498Szrj   n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
343238fd1498Szrj 
343338fd1498Szrj   q = create_tmp_reg (itype, "q");
343438fd1498Szrj   t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
343538fd1498Szrj   t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
343638fd1498Szrj   gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
343738fd1498Szrj 
343838fd1498Szrj   tt = create_tmp_reg (itype, "tt");
343938fd1498Szrj   t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
344038fd1498Szrj   t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
344138fd1498Szrj   gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
344238fd1498Szrj 
344338fd1498Szrj   t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
344438fd1498Szrj   gcond *cond_stmt = gimple_build_cond_empty (t);
344538fd1498Szrj   gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
344638fd1498Szrj 
344738fd1498Szrj   second_bb = split_block (entry_bb, cond_stmt)->dest;
344838fd1498Szrj   gsi = gsi_last_nondebug_bb (second_bb);
344938fd1498Szrj   gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
345038fd1498Szrj 
345138fd1498Szrj   gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
345238fd1498Szrj 		     GSI_SAME_STMT);
345338fd1498Szrj   gassign *assign_stmt
345438fd1498Szrj     = gimple_build_assign (q, PLUS_EXPR, q, build_int_cst (itype, 1));
345538fd1498Szrj   gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
345638fd1498Szrj 
345738fd1498Szrj   third_bb = split_block (second_bb, assign_stmt)->dest;
345838fd1498Szrj   gsi = gsi_last_nondebug_bb (third_bb);
345938fd1498Szrj   gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
346038fd1498Szrj 
346138fd1498Szrj   t = build2 (MULT_EXPR, itype, q, threadid);
346238fd1498Szrj   t = build2 (PLUS_EXPR, itype, t, tt);
346338fd1498Szrj   s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
346438fd1498Szrj 
346538fd1498Szrj   t = fold_build2 (PLUS_EXPR, itype, s0, q);
346638fd1498Szrj   e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
346738fd1498Szrj 
346838fd1498Szrj   t = build2 (GE_EXPR, boolean_type_node, s0, e0);
346938fd1498Szrj   gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
347038fd1498Szrj 
347138fd1498Szrj   /* Remove the GIMPLE_OMP_FOR statement.  */
347238fd1498Szrj   gsi_remove (&gsi, true);
347338fd1498Szrj 
347438fd1498Szrj   /* Setup code for sequential iteration goes in SEQ_START_BB.  */
347538fd1498Szrj   gsi = gsi_start_bb (seq_start_bb);
347638fd1498Szrj 
347738fd1498Szrj   tree startvar = fd->loop.v;
347838fd1498Szrj   tree endvar = NULL_TREE;
347938fd1498Szrj 
348038fd1498Szrj   if (gimple_omp_for_combined_p (fd->for_stmt))
348138fd1498Szrj     {
348238fd1498Szrj       tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
348338fd1498Szrj 		     ? gimple_omp_parallel_clauses (inner_stmt)
348438fd1498Szrj 		     : gimple_omp_for_clauses (inner_stmt);
348538fd1498Szrj       tree innerc = omp_find_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
348638fd1498Szrj       gcc_assert (innerc);
348738fd1498Szrj       startvar = OMP_CLAUSE_DECL (innerc);
348838fd1498Szrj       innerc = omp_find_clause (OMP_CLAUSE_CHAIN (innerc),
348938fd1498Szrj 				OMP_CLAUSE__LOOPTEMP_);
349038fd1498Szrj       gcc_assert (innerc);
349138fd1498Szrj       endvar = OMP_CLAUSE_DECL (innerc);
349238fd1498Szrj       if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST
349338fd1498Szrj 	  && gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
349438fd1498Szrj 	{
349538fd1498Szrj 	  int i;
349638fd1498Szrj 	  for (i = 1; i < fd->collapse; i++)
349738fd1498Szrj 	    {
349838fd1498Szrj 	      innerc = omp_find_clause (OMP_CLAUSE_CHAIN (innerc),
349938fd1498Szrj 					OMP_CLAUSE__LOOPTEMP_);
350038fd1498Szrj 	      gcc_assert (innerc);
350138fd1498Szrj 	    }
350238fd1498Szrj 	  innerc = omp_find_clause (OMP_CLAUSE_CHAIN (innerc),
350338fd1498Szrj 				    OMP_CLAUSE__LOOPTEMP_);
350438fd1498Szrj 	  if (innerc)
350538fd1498Szrj 	    {
350638fd1498Szrj 	      /* If needed (distribute parallel for with lastprivate),
350738fd1498Szrj 		 propagate down the total number of iterations.  */
350838fd1498Szrj 	      tree t = fold_convert (TREE_TYPE (OMP_CLAUSE_DECL (innerc)),
350938fd1498Szrj 				     fd->loop.n2);
351038fd1498Szrj 	      t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, false,
351138fd1498Szrj 					    GSI_CONTINUE_LINKING);
351238fd1498Szrj 	      assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
351338fd1498Szrj 	      gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
351438fd1498Szrj 	    }
351538fd1498Szrj 	}
351638fd1498Szrj     }
351738fd1498Szrj   t = fold_convert (itype, s0);
351838fd1498Szrj   t = fold_build2 (MULT_EXPR, itype, t, step);
351938fd1498Szrj   if (POINTER_TYPE_P (type))
352038fd1498Szrj     t = fold_build_pointer_plus (n1, t);
352138fd1498Szrj   else
352238fd1498Szrj     t = fold_build2 (PLUS_EXPR, type, t, n1);
352338fd1498Szrj   t = fold_convert (TREE_TYPE (startvar), t);
352438fd1498Szrj   t = force_gimple_operand_gsi (&gsi, t,
352538fd1498Szrj 				DECL_P (startvar)
352638fd1498Szrj 				&& TREE_ADDRESSABLE (startvar),
352738fd1498Szrj 				NULL_TREE, false, GSI_CONTINUE_LINKING);
352838fd1498Szrj   assign_stmt = gimple_build_assign (startvar, t);
352938fd1498Szrj   gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
353038fd1498Szrj 
353138fd1498Szrj   t = fold_convert (itype, e0);
353238fd1498Szrj   t = fold_build2 (MULT_EXPR, itype, t, step);
353338fd1498Szrj   if (POINTER_TYPE_P (type))
353438fd1498Szrj     t = fold_build_pointer_plus (n1, t);
353538fd1498Szrj   else
353638fd1498Szrj     t = fold_build2 (PLUS_EXPR, type, t, n1);
353738fd1498Szrj   t = fold_convert (TREE_TYPE (startvar), t);
353838fd1498Szrj   e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
353938fd1498Szrj 				false, GSI_CONTINUE_LINKING);
354038fd1498Szrj   if (endvar)
354138fd1498Szrj     {
354238fd1498Szrj       assign_stmt = gimple_build_assign (endvar, e);
354338fd1498Szrj       gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
354438fd1498Szrj       if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
354538fd1498Szrj 	assign_stmt = gimple_build_assign (fd->loop.v, e);
354638fd1498Szrj       else
354738fd1498Szrj 	assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
354838fd1498Szrj       gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
354938fd1498Szrj     }
355038fd1498Szrj   /* Handle linear clause adjustments.  */
355138fd1498Szrj   tree itercnt = NULL_TREE;
355238fd1498Szrj   if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
355338fd1498Szrj     for (tree c = gimple_omp_for_clauses (fd->for_stmt);
355438fd1498Szrj 	 c; c = OMP_CLAUSE_CHAIN (c))
355538fd1498Szrj       if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
355638fd1498Szrj 	  && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
355738fd1498Szrj 	{
355838fd1498Szrj 	  tree d = OMP_CLAUSE_DECL (c);
355938fd1498Szrj 	  bool is_ref = omp_is_reference (d);
356038fd1498Szrj 	  tree t = d, a, dest;
356138fd1498Szrj 	  if (is_ref)
356238fd1498Szrj 	    t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
356338fd1498Szrj 	  if (itercnt == NULL_TREE)
356438fd1498Szrj 	    {
356538fd1498Szrj 	      if (gimple_omp_for_combined_into_p (fd->for_stmt))
356638fd1498Szrj 		{
356738fd1498Szrj 		  itercnt = fold_build2 (MINUS_EXPR, itype,
356838fd1498Szrj 					 fold_convert (itype, n1),
356938fd1498Szrj 					 fold_convert (itype, fd->loop.n1));
357038fd1498Szrj 		  itercnt = fold_build2 (EXACT_DIV_EXPR, itype, itercnt, step);
357138fd1498Szrj 		  itercnt = fold_build2 (PLUS_EXPR, itype, itercnt, s0);
357238fd1498Szrj 		  itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
357338fd1498Szrj 						      NULL_TREE, false,
357438fd1498Szrj 						      GSI_CONTINUE_LINKING);
357538fd1498Szrj 		}
357638fd1498Szrj 	      else
357738fd1498Szrj 		itercnt = s0;
357838fd1498Szrj 	    }
357938fd1498Szrj 	  tree type = TREE_TYPE (t);
358038fd1498Szrj 	  if (POINTER_TYPE_P (type))
358138fd1498Szrj 	    type = sizetype;
358238fd1498Szrj 	  a = fold_build2 (MULT_EXPR, type,
358338fd1498Szrj 			   fold_convert (type, itercnt),
358438fd1498Szrj 			   fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
358538fd1498Szrj 	  dest = unshare_expr (t);
358638fd1498Szrj 	  t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
358738fd1498Szrj 			   : POINTER_PLUS_EXPR, TREE_TYPE (t), t, a);
358838fd1498Szrj 	  t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
358938fd1498Szrj 					false, GSI_CONTINUE_LINKING);
359038fd1498Szrj 	  assign_stmt = gimple_build_assign (dest, t);
359138fd1498Szrj 	  gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
359238fd1498Szrj 	}
359338fd1498Szrj   if (fd->collapse > 1)
359438fd1498Szrj     expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
359538fd1498Szrj 
359638fd1498Szrj   if (!broken_loop)
359738fd1498Szrj     {
359838fd1498Szrj       /* The code controlling the sequential loop replaces the
359938fd1498Szrj 	 GIMPLE_OMP_CONTINUE.  */
360038fd1498Szrj       gsi = gsi_last_nondebug_bb (cont_bb);
360138fd1498Szrj       gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
360238fd1498Szrj       gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
360338fd1498Szrj       vmain = gimple_omp_continue_control_use (cont_stmt);
360438fd1498Szrj       vback = gimple_omp_continue_control_def (cont_stmt);
360538fd1498Szrj 
360638fd1498Szrj       if (!gimple_omp_for_combined_p (fd->for_stmt))
360738fd1498Szrj 	{
360838fd1498Szrj 	  if (POINTER_TYPE_P (type))
360938fd1498Szrj 	    t = fold_build_pointer_plus (vmain, step);
361038fd1498Szrj 	  else
361138fd1498Szrj 	    t = fold_build2 (PLUS_EXPR, type, vmain, step);
361238fd1498Szrj 	  t = force_gimple_operand_gsi (&gsi, t,
361338fd1498Szrj 					DECL_P (vback)
361438fd1498Szrj 					&& TREE_ADDRESSABLE (vback),
361538fd1498Szrj 					NULL_TREE, true, GSI_SAME_STMT);
361638fd1498Szrj 	  assign_stmt = gimple_build_assign (vback, t);
361738fd1498Szrj 	  gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
361838fd1498Szrj 
361938fd1498Szrj 	  t = build2 (fd->loop.cond_code, boolean_type_node,
362038fd1498Szrj 		      DECL_P (vback) && TREE_ADDRESSABLE (vback)
362138fd1498Szrj 		      ? t : vback, e);
362238fd1498Szrj 	  gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
362338fd1498Szrj 	}
362438fd1498Szrj 
362538fd1498Szrj       /* Remove the GIMPLE_OMP_CONTINUE statement.  */
362638fd1498Szrj       gsi_remove (&gsi, true);
362738fd1498Szrj 
362838fd1498Szrj       if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
362938fd1498Szrj 	collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
363038fd1498Szrj     }
363138fd1498Szrj 
363238fd1498Szrj   /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing.  */
363338fd1498Szrj   gsi = gsi_last_nondebug_bb (exit_bb);
363438fd1498Szrj   if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
363538fd1498Szrj     {
363638fd1498Szrj       t = gimple_omp_return_lhs (gsi_stmt (gsi));
363738fd1498Szrj       gsi_insert_after (&gsi, omp_build_barrier (t), GSI_SAME_STMT);
363838fd1498Szrj     }
363938fd1498Szrj   gsi_remove (&gsi, true);
364038fd1498Szrj 
364138fd1498Szrj   /* Connect all the blocks.  */
364238fd1498Szrj   ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
364338fd1498Szrj   ep->probability = profile_probability::guessed_always ().apply_scale (3, 4);
364438fd1498Szrj   ep = find_edge (entry_bb, second_bb);
364538fd1498Szrj   ep->flags = EDGE_TRUE_VALUE;
364638fd1498Szrj   ep->probability = profile_probability::guessed_always ().apply_scale (1, 4);
364738fd1498Szrj   find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
364838fd1498Szrj   find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
364938fd1498Szrj 
365038fd1498Szrj   if (!broken_loop)
365138fd1498Szrj     {
365238fd1498Szrj       ep = find_edge (cont_bb, body_bb);
365338fd1498Szrj       if (ep == NULL)
365438fd1498Szrj 	{
365538fd1498Szrj 	  ep = BRANCH_EDGE (cont_bb);
365638fd1498Szrj 	  gcc_assert (single_succ (ep->dest) == body_bb);
365738fd1498Szrj 	}
365838fd1498Szrj       if (gimple_omp_for_combined_p (fd->for_stmt))
365938fd1498Szrj 	{
366038fd1498Szrj 	  remove_edge (ep);
366138fd1498Szrj 	  ep = NULL;
366238fd1498Szrj 	}
366338fd1498Szrj       else if (fd->collapse > 1)
366438fd1498Szrj 	{
366538fd1498Szrj 	  remove_edge (ep);
366638fd1498Szrj 	  ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
366738fd1498Szrj 	}
366838fd1498Szrj       else
366938fd1498Szrj 	ep->flags = EDGE_TRUE_VALUE;
367038fd1498Szrj       find_edge (cont_bb, fin_bb)->flags
367138fd1498Szrj 	= ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
367238fd1498Szrj     }
367338fd1498Szrj 
367438fd1498Szrj   set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
367538fd1498Szrj   set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
367638fd1498Szrj   set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
367738fd1498Szrj 
367838fd1498Szrj   set_immediate_dominator (CDI_DOMINATORS, body_bb,
367938fd1498Szrj 			   recompute_dominator (CDI_DOMINATORS, body_bb));
368038fd1498Szrj   set_immediate_dominator (CDI_DOMINATORS, fin_bb,
368138fd1498Szrj 			   recompute_dominator (CDI_DOMINATORS, fin_bb));
368238fd1498Szrj 
368338fd1498Szrj   struct loop *loop = body_bb->loop_father;
368438fd1498Szrj   if (loop != entry_bb->loop_father)
368538fd1498Szrj     {
368638fd1498Szrj       gcc_assert (broken_loop || loop->header == body_bb);
368738fd1498Szrj       gcc_assert (broken_loop
368838fd1498Szrj 		  || loop->latch == region->cont
368938fd1498Szrj 		  || single_pred (loop->latch) == region->cont);
369038fd1498Szrj       return;
369138fd1498Szrj     }
369238fd1498Szrj 
369338fd1498Szrj   if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
369438fd1498Szrj     {
369538fd1498Szrj       loop = alloc_loop ();
369638fd1498Szrj       loop->header = body_bb;
369738fd1498Szrj       if (collapse_bb == NULL)
369838fd1498Szrj 	loop->latch = cont_bb;
369938fd1498Szrj       add_loop (loop, body_bb->loop_father);
370038fd1498Szrj     }
370138fd1498Szrj }
370238fd1498Szrj 
370338fd1498Szrj /* Return phi in E->DEST with ARG on edge E.  */
370438fd1498Szrj 
370538fd1498Szrj static gphi *
find_phi_with_arg_on_edge(tree arg,edge e)370638fd1498Szrj find_phi_with_arg_on_edge (tree arg, edge e)
370738fd1498Szrj {
370838fd1498Szrj   basic_block bb = e->dest;
370938fd1498Szrj 
371038fd1498Szrj   for (gphi_iterator gpi = gsi_start_phis (bb);
371138fd1498Szrj        !gsi_end_p (gpi);
371238fd1498Szrj        gsi_next (&gpi))
371338fd1498Szrj     {
371438fd1498Szrj       gphi *phi = gpi.phi ();
371538fd1498Szrj       if (PHI_ARG_DEF_FROM_EDGE (phi, e) == arg)
371638fd1498Szrj 	return phi;
371738fd1498Szrj     }
371838fd1498Szrj 
371938fd1498Szrj   return NULL;
372038fd1498Szrj }
372138fd1498Szrj 
372238fd1498Szrj /* A subroutine of expand_omp_for.  Generate code for a parallel
372338fd1498Szrj    loop with static schedule and a specified chunk size.  Given
372438fd1498Szrj    parameters:
372538fd1498Szrj 
372638fd1498Szrj 	for (V = N1; V cond N2; V += STEP) BODY;
372738fd1498Szrj 
372838fd1498Szrj    where COND is "<" or ">", we generate pseudocode
372938fd1498Szrj 
373038fd1498Szrj 	if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
373138fd1498Szrj 	if (cond is <)
373238fd1498Szrj 	  adj = STEP - 1;
373338fd1498Szrj 	else
373438fd1498Szrj 	  adj = STEP + 1;
373538fd1498Szrj 	if ((__typeof (V)) -1 > 0 && cond is >)
373638fd1498Szrj 	  n = -(adj + N2 - N1) / -STEP;
373738fd1498Szrj 	else
373838fd1498Szrj 	  n = (adj + N2 - N1) / STEP;
373938fd1498Szrj 	trip = 0;
374038fd1498Szrj 	V = threadid * CHUNK * STEP + N1;  -- this extra definition of V is
374138fd1498Szrj 					      here so that V is defined
374238fd1498Szrj 					      if the loop is not entered
374338fd1498Szrj     L0:
374438fd1498Szrj 	s0 = (trip * nthreads + threadid) * CHUNK;
374538fd1498Szrj 	e0 = min (s0 + CHUNK, n);
374638fd1498Szrj 	if (s0 < n) goto L1; else goto L4;
374738fd1498Szrj     L1:
374838fd1498Szrj 	V = s0 * STEP + N1;
374938fd1498Szrj 	e = e0 * STEP + N1;
375038fd1498Szrj     L2:
375138fd1498Szrj 	BODY;
375238fd1498Szrj 	V += STEP;
375338fd1498Szrj 	if (V cond e) goto L2; else goto L3;
375438fd1498Szrj     L3:
375538fd1498Szrj 	trip += 1;
375638fd1498Szrj 	goto L0;
375738fd1498Szrj     L4:
375838fd1498Szrj */
375938fd1498Szrj 
376038fd1498Szrj static void
expand_omp_for_static_chunk(struct omp_region * region,struct omp_for_data * fd,gimple * inner_stmt)376138fd1498Szrj expand_omp_for_static_chunk (struct omp_region *region,
376238fd1498Szrj 			     struct omp_for_data *fd, gimple *inner_stmt)
376338fd1498Szrj {
376438fd1498Szrj   tree n, s0, e0, e, t;
376538fd1498Szrj   tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
376638fd1498Szrj   tree type, itype, vmain, vback, vextra;
376738fd1498Szrj   basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
376838fd1498Szrj   basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
376938fd1498Szrj   gimple_stmt_iterator gsi;
377038fd1498Szrj   edge se;
377138fd1498Szrj   bool broken_loop = region->cont == NULL;
377238fd1498Szrj   tree *counts = NULL;
377338fd1498Szrj   tree n1, n2, step;
377438fd1498Szrj 
377538fd1498Szrj   itype = type = TREE_TYPE (fd->loop.v);
377638fd1498Szrj   if (POINTER_TYPE_P (type))
377738fd1498Szrj     itype = signed_type_for (type);
377838fd1498Szrj 
377938fd1498Szrj   entry_bb = region->entry;
378038fd1498Szrj   se = split_block (entry_bb, last_stmt (entry_bb));
378138fd1498Szrj   entry_bb = se->src;
378238fd1498Szrj   iter_part_bb = se->dest;
378338fd1498Szrj   cont_bb = region->cont;
378438fd1498Szrj   gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
378538fd1498Szrj   fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
378638fd1498Szrj   gcc_assert (broken_loop
378738fd1498Szrj 	      || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
378838fd1498Szrj   seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
378938fd1498Szrj   body_bb = single_succ (seq_start_bb);
379038fd1498Szrj   if (!broken_loop)
379138fd1498Szrj     {
379238fd1498Szrj       gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb
379338fd1498Szrj 		  || single_succ (BRANCH_EDGE (cont_bb)->dest) == body_bb);
379438fd1498Szrj       gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
379538fd1498Szrj       trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
379638fd1498Szrj     }
379738fd1498Szrj   exit_bb = region->exit;
379838fd1498Szrj 
379938fd1498Szrj   /* Trip and adjustment setup goes in ENTRY_BB.  */
380038fd1498Szrj   gsi = gsi_last_nondebug_bb (entry_bb);
380138fd1498Szrj   gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
380238fd1498Szrj 
380338fd1498Szrj   if (fd->collapse > 1)
380438fd1498Szrj     {
380538fd1498Szrj       int first_zero_iter = -1, dummy = -1;
380638fd1498Szrj       basic_block l2_dom_bb = NULL, dummy_bb = NULL;
380738fd1498Szrj 
380838fd1498Szrj       counts = XALLOCAVEC (tree, fd->collapse);
380938fd1498Szrj       expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
381038fd1498Szrj 				  fin_bb, first_zero_iter,
381138fd1498Szrj 				  dummy_bb, dummy, l2_dom_bb);
381238fd1498Szrj       t = NULL_TREE;
381338fd1498Szrj     }
381438fd1498Szrj   else if (gimple_omp_for_combined_into_p (fd->for_stmt))
381538fd1498Szrj     t = integer_one_node;
381638fd1498Szrj   else
381738fd1498Szrj     t = fold_binary (fd->loop.cond_code, boolean_type_node,
381838fd1498Szrj 		     fold_convert (type, fd->loop.n1),
381938fd1498Szrj 		     fold_convert (type, fd->loop.n2));
382038fd1498Szrj   if (fd->collapse == 1
382138fd1498Szrj       && TYPE_UNSIGNED (type)
382238fd1498Szrj       && (t == NULL_TREE || !integer_onep (t)))
382338fd1498Szrj     {
382438fd1498Szrj       n1 = fold_convert (type, unshare_expr (fd->loop.n1));
382538fd1498Szrj       n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
382638fd1498Szrj 				     true, GSI_SAME_STMT);
382738fd1498Szrj       n2 = fold_convert (type, unshare_expr (fd->loop.n2));
382838fd1498Szrj       n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
382938fd1498Szrj 				     true, GSI_SAME_STMT);
383038fd1498Szrj       gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
383138fd1498Szrj 						 NULL_TREE, NULL_TREE);
383238fd1498Szrj       gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
383338fd1498Szrj       if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
383438fd1498Szrj 		     expand_omp_regimplify_p, NULL, NULL)
383538fd1498Szrj 	  || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
383638fd1498Szrj 			expand_omp_regimplify_p, NULL, NULL))
383738fd1498Szrj 	{
383838fd1498Szrj 	  gsi = gsi_for_stmt (cond_stmt);
383938fd1498Szrj 	  gimple_regimplify_operands (cond_stmt, &gsi);
384038fd1498Szrj 	}
384138fd1498Szrj       se = split_block (entry_bb, cond_stmt);
384238fd1498Szrj       se->flags = EDGE_TRUE_VALUE;
384338fd1498Szrj       entry_bb = se->dest;
384438fd1498Szrj       se->probability = profile_probability::very_likely ();
384538fd1498Szrj       se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
384638fd1498Szrj       se->probability = profile_probability::very_unlikely ();
384738fd1498Szrj       if (gimple_in_ssa_p (cfun))
384838fd1498Szrj 	{
384938fd1498Szrj 	  int dest_idx = find_edge (iter_part_bb, fin_bb)->dest_idx;
385038fd1498Szrj 	  for (gphi_iterator gpi = gsi_start_phis (fin_bb);
385138fd1498Szrj 	       !gsi_end_p (gpi); gsi_next (&gpi))
385238fd1498Szrj 	    {
385338fd1498Szrj 	      gphi *phi = gpi.phi ();
385438fd1498Szrj 	      add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
385538fd1498Szrj 			   se, UNKNOWN_LOCATION);
385638fd1498Szrj 	    }
385738fd1498Szrj 	}
385838fd1498Szrj       gsi = gsi_last_bb (entry_bb);
385938fd1498Szrj     }
386038fd1498Szrj 
386138fd1498Szrj   switch (gimple_omp_for_kind (fd->for_stmt))
386238fd1498Szrj     {
386338fd1498Szrj     case GF_OMP_FOR_KIND_FOR:
386438fd1498Szrj       nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
386538fd1498Szrj       threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
386638fd1498Szrj       break;
386738fd1498Szrj     case GF_OMP_FOR_KIND_DISTRIBUTE:
386838fd1498Szrj       nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
386938fd1498Szrj       threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
387038fd1498Szrj       break;
387138fd1498Szrj     default:
387238fd1498Szrj       gcc_unreachable ();
387338fd1498Szrj     }
387438fd1498Szrj   nthreads = build_call_expr (nthreads, 0);
387538fd1498Szrj   nthreads = fold_convert (itype, nthreads);
387638fd1498Szrj   nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
387738fd1498Szrj 				       true, GSI_SAME_STMT);
387838fd1498Szrj   threadid = build_call_expr (threadid, 0);
387938fd1498Szrj   threadid = fold_convert (itype, threadid);
388038fd1498Szrj   threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
388138fd1498Szrj 				       true, GSI_SAME_STMT);
388238fd1498Szrj 
388338fd1498Szrj   n1 = fd->loop.n1;
388438fd1498Szrj   n2 = fd->loop.n2;
388538fd1498Szrj   step = fd->loop.step;
388638fd1498Szrj   if (gimple_omp_for_combined_into_p (fd->for_stmt))
388738fd1498Szrj     {
388838fd1498Szrj       tree innerc = omp_find_clause (gimple_omp_for_clauses (fd->for_stmt),
388938fd1498Szrj 				     OMP_CLAUSE__LOOPTEMP_);
389038fd1498Szrj       gcc_assert (innerc);
389138fd1498Szrj       n1 = OMP_CLAUSE_DECL (innerc);
389238fd1498Szrj       innerc = omp_find_clause (OMP_CLAUSE_CHAIN (innerc),
389338fd1498Szrj 				OMP_CLAUSE__LOOPTEMP_);
389438fd1498Szrj       gcc_assert (innerc);
389538fd1498Szrj       n2 = OMP_CLAUSE_DECL (innerc);
389638fd1498Szrj     }
389738fd1498Szrj   n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
389838fd1498Szrj 				 true, NULL_TREE, true, GSI_SAME_STMT);
389938fd1498Szrj   n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
390038fd1498Szrj 				 true, NULL_TREE, true, GSI_SAME_STMT);
390138fd1498Szrj   step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
390238fd1498Szrj 				   true, NULL_TREE, true, GSI_SAME_STMT);
390338fd1498Szrj   tree chunk_size = fold_convert (itype, fd->chunk_size);
390438fd1498Szrj   chunk_size = omp_adjust_chunk_size (chunk_size, fd->simd_schedule);
390538fd1498Szrj   chunk_size
390638fd1498Szrj     = force_gimple_operand_gsi (&gsi, chunk_size, true, NULL_TREE, true,
390738fd1498Szrj 				GSI_SAME_STMT);
390838fd1498Szrj 
390938fd1498Szrj   t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
391038fd1498Szrj   t = fold_build2 (PLUS_EXPR, itype, step, t);
391138fd1498Szrj   t = fold_build2 (PLUS_EXPR, itype, t, n2);
391238fd1498Szrj   t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
391338fd1498Szrj   if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
391438fd1498Szrj     t = fold_build2 (TRUNC_DIV_EXPR, itype,
391538fd1498Szrj 		     fold_build1 (NEGATE_EXPR, itype, t),
391638fd1498Szrj 		     fold_build1 (NEGATE_EXPR, itype, step));
391738fd1498Szrj   else
391838fd1498Szrj     t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
391938fd1498Szrj   t = fold_convert (itype, t);
392038fd1498Szrj   n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
392138fd1498Szrj 				true, GSI_SAME_STMT);
392238fd1498Szrj 
392338fd1498Szrj   trip_var = create_tmp_reg (itype, ".trip");
392438fd1498Szrj   if (gimple_in_ssa_p (cfun))
392538fd1498Szrj     {
392638fd1498Szrj       trip_init = make_ssa_name (trip_var);
392738fd1498Szrj       trip_main = make_ssa_name (trip_var);
392838fd1498Szrj       trip_back = make_ssa_name (trip_var);
392938fd1498Szrj     }
393038fd1498Szrj   else
393138fd1498Szrj     {
393238fd1498Szrj       trip_init = trip_var;
393338fd1498Szrj       trip_main = trip_var;
393438fd1498Szrj       trip_back = trip_var;
393538fd1498Szrj     }
393638fd1498Szrj 
393738fd1498Szrj   gassign *assign_stmt
393838fd1498Szrj     = gimple_build_assign (trip_init, build_int_cst (itype, 0));
393938fd1498Szrj   gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
394038fd1498Szrj 
394138fd1498Szrj   t = fold_build2 (MULT_EXPR, itype, threadid, chunk_size);
394238fd1498Szrj   t = fold_build2 (MULT_EXPR, itype, t, step);
394338fd1498Szrj   if (POINTER_TYPE_P (type))
394438fd1498Szrj     t = fold_build_pointer_plus (n1, t);
394538fd1498Szrj   else
394638fd1498Szrj     t = fold_build2 (PLUS_EXPR, type, t, n1);
394738fd1498Szrj   vextra = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
394838fd1498Szrj 				     true, GSI_SAME_STMT);
394938fd1498Szrj 
395038fd1498Szrj   /* Remove the GIMPLE_OMP_FOR.  */
395138fd1498Szrj   gsi_remove (&gsi, true);
395238fd1498Szrj 
395338fd1498Szrj   gimple_stmt_iterator gsif = gsi;
395438fd1498Szrj 
395538fd1498Szrj   /* Iteration space partitioning goes in ITER_PART_BB.  */
395638fd1498Szrj   gsi = gsi_last_bb (iter_part_bb);
395738fd1498Szrj 
395838fd1498Szrj   t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
395938fd1498Szrj   t = fold_build2 (PLUS_EXPR, itype, t, threadid);
396038fd1498Szrj   t = fold_build2 (MULT_EXPR, itype, t, chunk_size);
396138fd1498Szrj   s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
396238fd1498Szrj 				 false, GSI_CONTINUE_LINKING);
396338fd1498Szrj 
396438fd1498Szrj   t = fold_build2 (PLUS_EXPR, itype, s0, chunk_size);
396538fd1498Szrj   t = fold_build2 (MIN_EXPR, itype, t, n);
396638fd1498Szrj   e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
396738fd1498Szrj 				 false, GSI_CONTINUE_LINKING);
396838fd1498Szrj 
396938fd1498Szrj   t = build2 (LT_EXPR, boolean_type_node, s0, n);
397038fd1498Szrj   gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
397138fd1498Szrj 
397238fd1498Szrj   /* Setup code for sequential iteration goes in SEQ_START_BB.  */
397338fd1498Szrj   gsi = gsi_start_bb (seq_start_bb);
397438fd1498Szrj 
397538fd1498Szrj   tree startvar = fd->loop.v;
397638fd1498Szrj   tree endvar = NULL_TREE;
397738fd1498Szrj 
397838fd1498Szrj   if (gimple_omp_for_combined_p (fd->for_stmt))
397938fd1498Szrj     {
398038fd1498Szrj       tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
398138fd1498Szrj 		     ? gimple_omp_parallel_clauses (inner_stmt)
398238fd1498Szrj 		     : gimple_omp_for_clauses (inner_stmt);
398338fd1498Szrj       tree innerc = omp_find_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
398438fd1498Szrj       gcc_assert (innerc);
398538fd1498Szrj       startvar = OMP_CLAUSE_DECL (innerc);
398638fd1498Szrj       innerc = omp_find_clause (OMP_CLAUSE_CHAIN (innerc),
398738fd1498Szrj 				OMP_CLAUSE__LOOPTEMP_);
398838fd1498Szrj       gcc_assert (innerc);
398938fd1498Szrj       endvar = OMP_CLAUSE_DECL (innerc);
399038fd1498Szrj       if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST
399138fd1498Szrj 	  && gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
399238fd1498Szrj 	{
399338fd1498Szrj 	  int i;
399438fd1498Szrj 	  for (i = 1; i < fd->collapse; i++)
399538fd1498Szrj 	    {
399638fd1498Szrj 	      innerc = omp_find_clause (OMP_CLAUSE_CHAIN (innerc),
399738fd1498Szrj 					OMP_CLAUSE__LOOPTEMP_);
399838fd1498Szrj 	      gcc_assert (innerc);
399938fd1498Szrj 	    }
400038fd1498Szrj 	  innerc = omp_find_clause (OMP_CLAUSE_CHAIN (innerc),
400138fd1498Szrj 				    OMP_CLAUSE__LOOPTEMP_);
400238fd1498Szrj 	  if (innerc)
400338fd1498Szrj 	    {
400438fd1498Szrj 	      /* If needed (distribute parallel for with lastprivate),
400538fd1498Szrj 		 propagate down the total number of iterations.  */
400638fd1498Szrj 	      tree t = fold_convert (TREE_TYPE (OMP_CLAUSE_DECL (innerc)),
400738fd1498Szrj 				     fd->loop.n2);
400838fd1498Szrj 	      t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, false,
400938fd1498Szrj 					    GSI_CONTINUE_LINKING);
401038fd1498Szrj 	      assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
401138fd1498Szrj 	      gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
401238fd1498Szrj 	    }
401338fd1498Szrj 	}
401438fd1498Szrj     }
401538fd1498Szrj 
401638fd1498Szrj   t = fold_convert (itype, s0);
401738fd1498Szrj   t = fold_build2 (MULT_EXPR, itype, t, step);
401838fd1498Szrj   if (POINTER_TYPE_P (type))
401938fd1498Szrj     t = fold_build_pointer_plus (n1, t);
402038fd1498Szrj   else
402138fd1498Szrj     t = fold_build2 (PLUS_EXPR, type, t, n1);
402238fd1498Szrj   t = fold_convert (TREE_TYPE (startvar), t);
402338fd1498Szrj   t = force_gimple_operand_gsi (&gsi, t,
402438fd1498Szrj 				DECL_P (startvar)
402538fd1498Szrj 				&& TREE_ADDRESSABLE (startvar),
402638fd1498Szrj 				NULL_TREE, false, GSI_CONTINUE_LINKING);
402738fd1498Szrj   assign_stmt = gimple_build_assign (startvar, t);
402838fd1498Szrj   gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
402938fd1498Szrj 
403038fd1498Szrj   t = fold_convert (itype, e0);
403138fd1498Szrj   t = fold_build2 (MULT_EXPR, itype, t, step);
403238fd1498Szrj   if (POINTER_TYPE_P (type))
403338fd1498Szrj     t = fold_build_pointer_plus (n1, t);
403438fd1498Szrj   else
403538fd1498Szrj     t = fold_build2 (PLUS_EXPR, type, t, n1);
403638fd1498Szrj   t = fold_convert (TREE_TYPE (startvar), t);
403738fd1498Szrj   e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
403838fd1498Szrj 				false, GSI_CONTINUE_LINKING);
403938fd1498Szrj   if (endvar)
404038fd1498Szrj     {
404138fd1498Szrj       assign_stmt = gimple_build_assign (endvar, e);
404238fd1498Szrj       gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
404338fd1498Szrj       if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
404438fd1498Szrj 	assign_stmt = gimple_build_assign (fd->loop.v, e);
404538fd1498Szrj       else
404638fd1498Szrj 	assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
404738fd1498Szrj       gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
404838fd1498Szrj     }
404938fd1498Szrj   /* Handle linear clause adjustments.  */
405038fd1498Szrj   tree itercnt = NULL_TREE, itercntbias = NULL_TREE;
405138fd1498Szrj   if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
405238fd1498Szrj     for (tree c = gimple_omp_for_clauses (fd->for_stmt);
405338fd1498Szrj 	 c; c = OMP_CLAUSE_CHAIN (c))
405438fd1498Szrj       if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
405538fd1498Szrj 	  && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
405638fd1498Szrj 	{
405738fd1498Szrj 	  tree d = OMP_CLAUSE_DECL (c);
405838fd1498Szrj 	  bool is_ref = omp_is_reference (d);
405938fd1498Szrj 	  tree t = d, a, dest;
406038fd1498Szrj 	  if (is_ref)
406138fd1498Szrj 	    t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
406238fd1498Szrj 	  tree type = TREE_TYPE (t);
406338fd1498Szrj 	  if (POINTER_TYPE_P (type))
406438fd1498Szrj 	    type = sizetype;
406538fd1498Szrj 	  dest = unshare_expr (t);
406638fd1498Szrj 	  tree v = create_tmp_var (TREE_TYPE (t), NULL);
406738fd1498Szrj 	  expand_omp_build_assign (&gsif, v, t);
406838fd1498Szrj 	  if (itercnt == NULL_TREE)
406938fd1498Szrj 	    {
407038fd1498Szrj 	      if (gimple_omp_for_combined_into_p (fd->for_stmt))
407138fd1498Szrj 		{
407238fd1498Szrj 		  itercntbias
407338fd1498Szrj 		    = fold_build2 (MINUS_EXPR, itype, fold_convert (itype, n1),
407438fd1498Szrj 				   fold_convert (itype, fd->loop.n1));
407538fd1498Szrj 		  itercntbias = fold_build2 (EXACT_DIV_EXPR, itype,
407638fd1498Szrj 					     itercntbias, step);
407738fd1498Szrj 		  itercntbias
407838fd1498Szrj 		    = force_gimple_operand_gsi (&gsif, itercntbias, true,
407938fd1498Szrj 						NULL_TREE, true,
408038fd1498Szrj 						GSI_SAME_STMT);
408138fd1498Szrj 		  itercnt = fold_build2 (PLUS_EXPR, itype, itercntbias, s0);
408238fd1498Szrj 		  itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
408338fd1498Szrj 						      NULL_TREE, false,
408438fd1498Szrj 						      GSI_CONTINUE_LINKING);
408538fd1498Szrj 		}
408638fd1498Szrj 	      else
408738fd1498Szrj 		itercnt = s0;
408838fd1498Szrj 	    }
408938fd1498Szrj 	  a = fold_build2 (MULT_EXPR, type,
409038fd1498Szrj 			   fold_convert (type, itercnt),
409138fd1498Szrj 			   fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
409238fd1498Szrj 	  t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
409338fd1498Szrj 			   : POINTER_PLUS_EXPR, TREE_TYPE (t), v, a);
409438fd1498Szrj 	  t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
409538fd1498Szrj 					false, GSI_CONTINUE_LINKING);
409638fd1498Szrj 	  assign_stmt = gimple_build_assign (dest, t);
409738fd1498Szrj 	  gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
409838fd1498Szrj 	}
409938fd1498Szrj   if (fd->collapse > 1)
410038fd1498Szrj     expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
410138fd1498Szrj 
410238fd1498Szrj   if (!broken_loop)
410338fd1498Szrj     {
410438fd1498Szrj       /* The code controlling the sequential loop goes in CONT_BB,
410538fd1498Szrj 	 replacing the GIMPLE_OMP_CONTINUE.  */
410638fd1498Szrj       gsi = gsi_last_nondebug_bb (cont_bb);
410738fd1498Szrj       gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
410838fd1498Szrj       vmain = gimple_omp_continue_control_use (cont_stmt);
410938fd1498Szrj       vback = gimple_omp_continue_control_def (cont_stmt);
411038fd1498Szrj 
411138fd1498Szrj       if (!gimple_omp_for_combined_p (fd->for_stmt))
411238fd1498Szrj 	{
411338fd1498Szrj 	  if (POINTER_TYPE_P (type))
411438fd1498Szrj 	    t = fold_build_pointer_plus (vmain, step);
411538fd1498Szrj 	  else
411638fd1498Szrj 	    t = fold_build2 (PLUS_EXPR, type, vmain, step);
411738fd1498Szrj 	  if (DECL_P (vback) && TREE_ADDRESSABLE (vback))
411838fd1498Szrj 	    t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
411938fd1498Szrj 					  true, GSI_SAME_STMT);
412038fd1498Szrj 	  assign_stmt = gimple_build_assign (vback, t);
412138fd1498Szrj 	  gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
412238fd1498Szrj 
412338fd1498Szrj 	  if (tree_int_cst_equal (fd->chunk_size, integer_one_node))
412438fd1498Szrj 	    t = build2 (EQ_EXPR, boolean_type_node,
412538fd1498Szrj 			build_int_cst (itype, 0),
412638fd1498Szrj 			build_int_cst (itype, 1));
412738fd1498Szrj 	  else
412838fd1498Szrj 	    t = build2 (fd->loop.cond_code, boolean_type_node,
412938fd1498Szrj 			DECL_P (vback) && TREE_ADDRESSABLE (vback)
413038fd1498Szrj 			? t : vback, e);
413138fd1498Szrj 	  gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
413238fd1498Szrj 	}
413338fd1498Szrj 
413438fd1498Szrj       /* Remove GIMPLE_OMP_CONTINUE.  */
413538fd1498Szrj       gsi_remove (&gsi, true);
413638fd1498Szrj 
413738fd1498Szrj       if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
413838fd1498Szrj 	collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
413938fd1498Szrj 
414038fd1498Szrj       /* Trip update code goes into TRIP_UPDATE_BB.  */
414138fd1498Szrj       gsi = gsi_start_bb (trip_update_bb);
414238fd1498Szrj 
414338fd1498Szrj       t = build_int_cst (itype, 1);
414438fd1498Szrj       t = build2 (PLUS_EXPR, itype, trip_main, t);
414538fd1498Szrj       assign_stmt = gimple_build_assign (trip_back, t);
414638fd1498Szrj       gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
414738fd1498Szrj     }
414838fd1498Szrj 
414938fd1498Szrj   /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing.  */
415038fd1498Szrj   gsi = gsi_last_nondebug_bb (exit_bb);
415138fd1498Szrj   if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
415238fd1498Szrj     {
415338fd1498Szrj       t = gimple_omp_return_lhs (gsi_stmt (gsi));
415438fd1498Szrj       gsi_insert_after (&gsi, omp_build_barrier (t), GSI_SAME_STMT);
415538fd1498Szrj     }
415638fd1498Szrj   gsi_remove (&gsi, true);
415738fd1498Szrj 
415838fd1498Szrj   /* Connect the new blocks.  */
415938fd1498Szrj   find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
416038fd1498Szrj   find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
416138fd1498Szrj 
416238fd1498Szrj   if (!broken_loop)
416338fd1498Szrj     {
416438fd1498Szrj       se = find_edge (cont_bb, body_bb);
416538fd1498Szrj       if (se == NULL)
416638fd1498Szrj 	{
416738fd1498Szrj 	  se = BRANCH_EDGE (cont_bb);
416838fd1498Szrj 	  gcc_assert (single_succ (se->dest) == body_bb);
416938fd1498Szrj 	}
417038fd1498Szrj       if (gimple_omp_for_combined_p (fd->for_stmt))
417138fd1498Szrj 	{
417238fd1498Szrj 	  remove_edge (se);
417338fd1498Szrj 	  se = NULL;
417438fd1498Szrj 	}
417538fd1498Szrj       else if (fd->collapse > 1)
417638fd1498Szrj 	{
417738fd1498Szrj 	  remove_edge (se);
417838fd1498Szrj 	  se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
417938fd1498Szrj 	}
418038fd1498Szrj       else
418138fd1498Szrj 	se->flags = EDGE_TRUE_VALUE;
418238fd1498Szrj       find_edge (cont_bb, trip_update_bb)->flags
418338fd1498Szrj 	= se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
418438fd1498Szrj 
418538fd1498Szrj       redirect_edge_and_branch (single_succ_edge (trip_update_bb),
418638fd1498Szrj 				iter_part_bb);
418738fd1498Szrj     }
418838fd1498Szrj 
418938fd1498Szrj   if (gimple_in_ssa_p (cfun))
419038fd1498Szrj     {
419138fd1498Szrj       gphi_iterator psi;
419238fd1498Szrj       gphi *phi;
419338fd1498Szrj       edge re, ene;
419438fd1498Szrj       edge_var_map *vm;
419538fd1498Szrj       size_t i;
419638fd1498Szrj 
419738fd1498Szrj       gcc_assert (fd->collapse == 1 && !broken_loop);
419838fd1498Szrj 
419938fd1498Szrj       /* When we redirect the edge from trip_update_bb to iter_part_bb, we
420038fd1498Szrj 	 remove arguments of the phi nodes in fin_bb.  We need to create
420138fd1498Szrj 	 appropriate phi nodes in iter_part_bb instead.  */
420238fd1498Szrj       se = find_edge (iter_part_bb, fin_bb);
420338fd1498Szrj       re = single_succ_edge (trip_update_bb);
420438fd1498Szrj       vec<edge_var_map> *head = redirect_edge_var_map_vector (re);
420538fd1498Szrj       ene = single_succ_edge (entry_bb);
420638fd1498Szrj 
420738fd1498Szrj       psi = gsi_start_phis (fin_bb);
420838fd1498Szrj       for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
420938fd1498Szrj 	   gsi_next (&psi), ++i)
421038fd1498Szrj 	{
421138fd1498Szrj 	  gphi *nphi;
421238fd1498Szrj 	  source_location locus;
421338fd1498Szrj 
421438fd1498Szrj 	  phi = psi.phi ();
421538fd1498Szrj 	  if (operand_equal_p (gimple_phi_arg_def (phi, 0),
421638fd1498Szrj 			       redirect_edge_var_map_def (vm), 0))
421738fd1498Szrj 	    continue;
421838fd1498Szrj 
421938fd1498Szrj 	  t = gimple_phi_result (phi);
422038fd1498Szrj 	  gcc_assert (t == redirect_edge_var_map_result (vm));
422138fd1498Szrj 
422238fd1498Szrj 	  if (!single_pred_p (fin_bb))
422338fd1498Szrj 	    t = copy_ssa_name (t, phi);
422438fd1498Szrj 
422538fd1498Szrj 	  nphi = create_phi_node (t, iter_part_bb);
422638fd1498Szrj 
422738fd1498Szrj 	  t = PHI_ARG_DEF_FROM_EDGE (phi, se);
422838fd1498Szrj 	  locus = gimple_phi_arg_location_from_edge (phi, se);
422938fd1498Szrj 
423038fd1498Szrj 	  /* A special case -- fd->loop.v is not yet computed in
423138fd1498Szrj 	     iter_part_bb, we need to use vextra instead.  */
423238fd1498Szrj 	  if (t == fd->loop.v)
423338fd1498Szrj 	    t = vextra;
423438fd1498Szrj 	  add_phi_arg (nphi, t, ene, locus);
423538fd1498Szrj 	  locus = redirect_edge_var_map_location (vm);
423638fd1498Szrj 	  tree back_arg = redirect_edge_var_map_def (vm);
423738fd1498Szrj 	  add_phi_arg (nphi, back_arg, re, locus);
423838fd1498Szrj 	  edge ce = find_edge (cont_bb, body_bb);
423938fd1498Szrj 	  if (ce == NULL)
424038fd1498Szrj 	    {
424138fd1498Szrj 	      ce = BRANCH_EDGE (cont_bb);
424238fd1498Szrj 	      gcc_assert (single_succ (ce->dest) == body_bb);
424338fd1498Szrj 	      ce = single_succ_edge (ce->dest);
424438fd1498Szrj 	    }
424538fd1498Szrj 	  gphi *inner_loop_phi = find_phi_with_arg_on_edge (back_arg, ce);
424638fd1498Szrj 	  gcc_assert (inner_loop_phi != NULL);
424738fd1498Szrj 	  add_phi_arg (inner_loop_phi, gimple_phi_result (nphi),
424838fd1498Szrj 		       find_edge (seq_start_bb, body_bb), locus);
424938fd1498Szrj 
425038fd1498Szrj 	  if (!single_pred_p (fin_bb))
425138fd1498Szrj 	    add_phi_arg (phi, gimple_phi_result (nphi), se, locus);
425238fd1498Szrj 	}
425338fd1498Szrj       gcc_assert (gsi_end_p (psi) && (head == NULL || i == head->length ()));
425438fd1498Szrj       redirect_edge_var_map_clear (re);
425538fd1498Szrj       if (single_pred_p (fin_bb))
425638fd1498Szrj 	while (1)
425738fd1498Szrj 	  {
425838fd1498Szrj 	    psi = gsi_start_phis (fin_bb);
425938fd1498Szrj 	    if (gsi_end_p (psi))
426038fd1498Szrj 	      break;
426138fd1498Szrj 	    remove_phi_node (&psi, false);
426238fd1498Szrj 	  }
426338fd1498Szrj 
426438fd1498Szrj       /* Make phi node for trip.  */
426538fd1498Szrj       phi = create_phi_node (trip_main, iter_part_bb);
426638fd1498Szrj       add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
426738fd1498Szrj 		   UNKNOWN_LOCATION);
426838fd1498Szrj       add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
426938fd1498Szrj 		   UNKNOWN_LOCATION);
427038fd1498Szrj     }
427138fd1498Szrj 
427238fd1498Szrj   if (!broken_loop)
427338fd1498Szrj     set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
427438fd1498Szrj   set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
427538fd1498Szrj 			   recompute_dominator (CDI_DOMINATORS, iter_part_bb));
427638fd1498Szrj   set_immediate_dominator (CDI_DOMINATORS, fin_bb,
427738fd1498Szrj 			   recompute_dominator (CDI_DOMINATORS, fin_bb));
427838fd1498Szrj   set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
427938fd1498Szrj 			   recompute_dominator (CDI_DOMINATORS, seq_start_bb));
428038fd1498Szrj   set_immediate_dominator (CDI_DOMINATORS, body_bb,
428138fd1498Szrj 			   recompute_dominator (CDI_DOMINATORS, body_bb));
428238fd1498Szrj 
428338fd1498Szrj   if (!broken_loop)
428438fd1498Szrj     {
428538fd1498Szrj       struct loop *loop = body_bb->loop_father;
428638fd1498Szrj       struct loop *trip_loop = alloc_loop ();
428738fd1498Szrj       trip_loop->header = iter_part_bb;
428838fd1498Szrj       trip_loop->latch = trip_update_bb;
428938fd1498Szrj       add_loop (trip_loop, iter_part_bb->loop_father);
429038fd1498Szrj 
429138fd1498Szrj       if (loop != entry_bb->loop_father)
429238fd1498Szrj 	{
429338fd1498Szrj 	  gcc_assert (loop->header == body_bb);
429438fd1498Szrj 	  gcc_assert (loop->latch == region->cont
429538fd1498Szrj 		      || single_pred (loop->latch) == region->cont);
429638fd1498Szrj 	  trip_loop->inner = loop;
429738fd1498Szrj 	  return;
429838fd1498Szrj 	}
429938fd1498Szrj 
430038fd1498Szrj       if (!gimple_omp_for_combined_p (fd->for_stmt))
430138fd1498Szrj 	{
430238fd1498Szrj 	  loop = alloc_loop ();
430338fd1498Szrj 	  loop->header = body_bb;
430438fd1498Szrj 	  if (collapse_bb == NULL)
430538fd1498Szrj 	    loop->latch = cont_bb;
430638fd1498Szrj 	  add_loop (loop, trip_loop);
430738fd1498Szrj 	}
430838fd1498Szrj     }
430938fd1498Szrj }
431038fd1498Szrj 
431138fd1498Szrj /* A subroutine of expand_omp_for.  Generate code for a simd non-worksharing
431238fd1498Szrj    loop.  Given parameters:
431338fd1498Szrj 
431438fd1498Szrj 	for (V = N1; V cond N2; V += STEP) BODY;
431538fd1498Szrj 
431638fd1498Szrj    where COND is "<" or ">", we generate pseudocode
431738fd1498Szrj 
431838fd1498Szrj 	V = N1;
431938fd1498Szrj 	goto L1;
432038fd1498Szrj     L0:
432138fd1498Szrj 	BODY;
432238fd1498Szrj 	V += STEP;
432338fd1498Szrj     L1:
432438fd1498Szrj 	if (V cond N2) goto L0; else goto L2;
432538fd1498Szrj     L2:
432638fd1498Szrj 
432738fd1498Szrj     For collapsed loops, given parameters:
432838fd1498Szrj       collapse(3)
432938fd1498Szrj       for (V1 = N11; V1 cond1 N12; V1 += STEP1)
433038fd1498Szrj 	for (V2 = N21; V2 cond2 N22; V2 += STEP2)
433138fd1498Szrj 	  for (V3 = N31; V3 cond3 N32; V3 += STEP3)
433238fd1498Szrj 	    BODY;
433338fd1498Szrj 
433438fd1498Szrj     we generate pseudocode
433538fd1498Szrj 
433638fd1498Szrj 	if (cond3 is <)
433738fd1498Szrj 	  adj = STEP3 - 1;
433838fd1498Szrj 	else
433938fd1498Szrj 	  adj = STEP3 + 1;
434038fd1498Szrj 	count3 = (adj + N32 - N31) / STEP3;
434138fd1498Szrj 	if (cond2 is <)
434238fd1498Szrj 	  adj = STEP2 - 1;
434338fd1498Szrj 	else
434438fd1498Szrj 	  adj = STEP2 + 1;
434538fd1498Szrj 	count2 = (adj + N22 - N21) / STEP2;
434638fd1498Szrj 	if (cond1 is <)
434738fd1498Szrj 	  adj = STEP1 - 1;
434838fd1498Szrj 	else
434938fd1498Szrj 	  adj = STEP1 + 1;
435038fd1498Szrj 	count1 = (adj + N12 - N11) / STEP1;
435138fd1498Szrj 	count = count1 * count2 * count3;
435238fd1498Szrj 	V = 0;
435338fd1498Szrj 	V1 = N11;
435438fd1498Szrj 	V2 = N21;
435538fd1498Szrj 	V3 = N31;
435638fd1498Szrj 	goto L1;
435738fd1498Szrj     L0:
435838fd1498Szrj 	BODY;
435938fd1498Szrj 	V += 1;
436038fd1498Szrj 	V3 += STEP3;
436138fd1498Szrj 	V2 += (V3 cond3 N32) ? 0 : STEP2;
436238fd1498Szrj 	V3 = (V3 cond3 N32) ? V3 : N31;
436338fd1498Szrj 	V1 += (V2 cond2 N22) ? 0 : STEP1;
436438fd1498Szrj 	V2 = (V2 cond2 N22) ? V2 : N21;
436538fd1498Szrj     L1:
436638fd1498Szrj 	if (V < count) goto L0; else goto L2;
436738fd1498Szrj     L2:
436838fd1498Szrj 
436938fd1498Szrj       */
437038fd1498Szrj 
437138fd1498Szrj static void
expand_omp_simd(struct omp_region * region,struct omp_for_data * fd)437238fd1498Szrj expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
437338fd1498Szrj {
437438fd1498Szrj   tree type, t;
437538fd1498Szrj   basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
437638fd1498Szrj   gimple_stmt_iterator gsi;
437738fd1498Szrj   gimple *stmt;
437838fd1498Szrj   gcond *cond_stmt;
437938fd1498Szrj   bool broken_loop = region->cont == NULL;
438038fd1498Szrj   edge e, ne;
438138fd1498Szrj   tree *counts = NULL;
438238fd1498Szrj   int i;
438338fd1498Szrj   int safelen_int = INT_MAX;
438438fd1498Szrj   tree safelen = omp_find_clause (gimple_omp_for_clauses (fd->for_stmt),
438538fd1498Szrj 				  OMP_CLAUSE_SAFELEN);
438638fd1498Szrj   tree simduid = omp_find_clause (gimple_omp_for_clauses (fd->for_stmt),
438738fd1498Szrj 				  OMP_CLAUSE__SIMDUID_);
438838fd1498Szrj   tree n1, n2;
438938fd1498Szrj 
439038fd1498Szrj   if (safelen)
439138fd1498Szrj     {
439238fd1498Szrj       poly_uint64 val;
439338fd1498Szrj       safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
439438fd1498Szrj       if (!poly_int_tree_p (safelen, &val))
439538fd1498Szrj 	safelen_int = 0;
439638fd1498Szrj       else
439738fd1498Szrj 	safelen_int = MIN (constant_lower_bound (val), INT_MAX);
439838fd1498Szrj       if (safelen_int == 1)
439938fd1498Szrj 	safelen_int = 0;
440038fd1498Szrj     }
440138fd1498Szrj   type = TREE_TYPE (fd->loop.v);
440238fd1498Szrj   entry_bb = region->entry;
440338fd1498Szrj   cont_bb = region->cont;
440438fd1498Szrj   gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
440538fd1498Szrj   gcc_assert (broken_loop
440638fd1498Szrj 	      || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
440738fd1498Szrj   l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
440838fd1498Szrj   if (!broken_loop)
440938fd1498Szrj     {
441038fd1498Szrj       gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
441138fd1498Szrj       gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
441238fd1498Szrj       l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
441338fd1498Szrj       l2_bb = BRANCH_EDGE (entry_bb)->dest;
441438fd1498Szrj     }
441538fd1498Szrj   else
441638fd1498Szrj     {
441738fd1498Szrj       BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
441838fd1498Szrj       l1_bb = split_edge (BRANCH_EDGE (entry_bb));
441938fd1498Szrj       l2_bb = single_succ (l1_bb);
442038fd1498Szrj     }
442138fd1498Szrj   exit_bb = region->exit;
442238fd1498Szrj   l2_dom_bb = NULL;
442338fd1498Szrj 
442438fd1498Szrj   gsi = gsi_last_nondebug_bb (entry_bb);
442538fd1498Szrj 
442638fd1498Szrj   gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
442738fd1498Szrj   /* Not needed in SSA form right now.  */
442838fd1498Szrj   gcc_assert (!gimple_in_ssa_p (cfun));
442938fd1498Szrj   if (fd->collapse > 1)
443038fd1498Szrj     {
443138fd1498Szrj       int first_zero_iter = -1, dummy = -1;
443238fd1498Szrj       basic_block zero_iter_bb = l2_bb, dummy_bb = NULL;
443338fd1498Szrj 
443438fd1498Szrj       counts = XALLOCAVEC (tree, fd->collapse);
443538fd1498Szrj       expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
443638fd1498Szrj 				  zero_iter_bb, first_zero_iter,
443738fd1498Szrj 				  dummy_bb, dummy, l2_dom_bb);
443838fd1498Szrj     }
443938fd1498Szrj   if (l2_dom_bb == NULL)
444038fd1498Szrj     l2_dom_bb = l1_bb;
444138fd1498Szrj 
444238fd1498Szrj   n1 = fd->loop.n1;
444338fd1498Szrj   n2 = fd->loop.n2;
444438fd1498Szrj   if (gimple_omp_for_combined_into_p (fd->for_stmt))
444538fd1498Szrj     {
444638fd1498Szrj       tree innerc = omp_find_clause (gimple_omp_for_clauses (fd->for_stmt),
444738fd1498Szrj 				     OMP_CLAUSE__LOOPTEMP_);
444838fd1498Szrj       gcc_assert (innerc);
444938fd1498Szrj       n1 = OMP_CLAUSE_DECL (innerc);
445038fd1498Szrj       innerc = omp_find_clause (OMP_CLAUSE_CHAIN (innerc),
445138fd1498Szrj 				OMP_CLAUSE__LOOPTEMP_);
445238fd1498Szrj       gcc_assert (innerc);
445338fd1498Szrj       n2 = OMP_CLAUSE_DECL (innerc);
445438fd1498Szrj     }
445538fd1498Szrj   tree step = fd->loop.step;
445638fd1498Szrj 
445738fd1498Szrj   bool is_simt = omp_find_clause (gimple_omp_for_clauses (fd->for_stmt),
445838fd1498Szrj 				  OMP_CLAUSE__SIMT_);
445938fd1498Szrj   if (is_simt)
446038fd1498Szrj     {
446138fd1498Szrj       cfun->curr_properties &= ~PROP_gimple_lomp_dev;
446238fd1498Szrj       is_simt = safelen_int > 1;
446338fd1498Szrj     }
446438fd1498Szrj   tree simt_lane = NULL_TREE, simt_maxlane = NULL_TREE;
446538fd1498Szrj   if (is_simt)
446638fd1498Szrj     {
446738fd1498Szrj       simt_lane = create_tmp_var (unsigned_type_node);
446838fd1498Szrj       gimple *g = gimple_build_call_internal (IFN_GOMP_SIMT_LANE, 0);
446938fd1498Szrj       gimple_call_set_lhs (g, simt_lane);
447038fd1498Szrj       gsi_insert_before (&gsi, g, GSI_SAME_STMT);
447138fd1498Szrj       tree offset = fold_build2 (MULT_EXPR, TREE_TYPE (step), step,
447238fd1498Szrj 				 fold_convert (TREE_TYPE (step), simt_lane));
447338fd1498Szrj       n1 = fold_convert (type, n1);
447438fd1498Szrj       if (POINTER_TYPE_P (type))
447538fd1498Szrj 	n1 = fold_build_pointer_plus (n1, offset);
447638fd1498Szrj       else
447738fd1498Szrj 	n1 = fold_build2 (PLUS_EXPR, type, n1, fold_convert (type, offset));
447838fd1498Szrj 
447938fd1498Szrj       /* Collapsed loops not handled for SIMT yet: limit to one lane only.  */
448038fd1498Szrj       if (fd->collapse > 1)
448138fd1498Szrj 	simt_maxlane = build_one_cst (unsigned_type_node);
448238fd1498Szrj       else if (safelen_int < omp_max_simt_vf ())
448338fd1498Szrj 	simt_maxlane = build_int_cst (unsigned_type_node, safelen_int);
448438fd1498Szrj       tree vf
448538fd1498Szrj 	= build_call_expr_internal_loc (UNKNOWN_LOCATION, IFN_GOMP_SIMT_VF,
448638fd1498Szrj 					unsigned_type_node, 0);
448738fd1498Szrj       if (simt_maxlane)
448838fd1498Szrj 	vf = fold_build2 (MIN_EXPR, unsigned_type_node, vf, simt_maxlane);
448938fd1498Szrj       vf = fold_convert (TREE_TYPE (step), vf);
449038fd1498Szrj       step = fold_build2 (MULT_EXPR, TREE_TYPE (step), step, vf);
449138fd1498Szrj     }
449238fd1498Szrj 
449338fd1498Szrj   expand_omp_build_assign (&gsi, fd->loop.v, fold_convert (type, n1));
449438fd1498Szrj   if (fd->collapse > 1)
449538fd1498Szrj     {
449638fd1498Szrj       if (gimple_omp_for_combined_into_p (fd->for_stmt))
449738fd1498Szrj 	{
449838fd1498Szrj 	  gsi_prev (&gsi);
449938fd1498Szrj 	  expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
450038fd1498Szrj 	  gsi_next (&gsi);
450138fd1498Szrj 	}
450238fd1498Szrj       else
450338fd1498Szrj 	for (i = 0; i < fd->collapse; i++)
450438fd1498Szrj 	  {
450538fd1498Szrj 	    tree itype = TREE_TYPE (fd->loops[i].v);
450638fd1498Szrj 	    if (POINTER_TYPE_P (itype))
450738fd1498Szrj 	      itype = signed_type_for (itype);
450838fd1498Szrj 	    t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
450938fd1498Szrj 	    expand_omp_build_assign (&gsi, fd->loops[i].v, t);
451038fd1498Szrj 	  }
451138fd1498Szrj     }
451238fd1498Szrj 
451338fd1498Szrj   /* Remove the GIMPLE_OMP_FOR statement.  */
451438fd1498Szrj   gsi_remove (&gsi, true);
451538fd1498Szrj 
451638fd1498Szrj   if (!broken_loop)
451738fd1498Szrj     {
451838fd1498Szrj       /* Code to control the increment goes in the CONT_BB.  */
451938fd1498Szrj       gsi = gsi_last_nondebug_bb (cont_bb);
452038fd1498Szrj       stmt = gsi_stmt (gsi);
452138fd1498Szrj       gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
452238fd1498Szrj 
452338fd1498Szrj       if (POINTER_TYPE_P (type))
452438fd1498Szrj 	t = fold_build_pointer_plus (fd->loop.v, step);
452538fd1498Szrj       else
452638fd1498Szrj 	t = fold_build2 (PLUS_EXPR, type, fd->loop.v, step);
452738fd1498Szrj       expand_omp_build_assign (&gsi, fd->loop.v, t);
452838fd1498Szrj 
452938fd1498Szrj       if (fd->collapse > 1)
453038fd1498Szrj 	{
453138fd1498Szrj 	  i = fd->collapse - 1;
453238fd1498Szrj 	  if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
453338fd1498Szrj 	    {
453438fd1498Szrj 	      t = fold_convert (sizetype, fd->loops[i].step);
453538fd1498Szrj 	      t = fold_build_pointer_plus (fd->loops[i].v, t);
453638fd1498Szrj 	    }
453738fd1498Szrj 	  else
453838fd1498Szrj 	    {
453938fd1498Szrj 	      t = fold_convert (TREE_TYPE (fd->loops[i].v),
454038fd1498Szrj 				fd->loops[i].step);
454138fd1498Szrj 	      t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
454238fd1498Szrj 			       fd->loops[i].v, t);
454338fd1498Szrj 	    }
454438fd1498Szrj 	  expand_omp_build_assign (&gsi, fd->loops[i].v, t);
454538fd1498Szrj 
454638fd1498Szrj 	  for (i = fd->collapse - 1; i > 0; i--)
454738fd1498Szrj 	    {
454838fd1498Szrj 	      tree itype = TREE_TYPE (fd->loops[i].v);
454938fd1498Szrj 	      tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
455038fd1498Szrj 	      if (POINTER_TYPE_P (itype2))
455138fd1498Szrj 		itype2 = signed_type_for (itype2);
455238fd1498Szrj 	      t = fold_convert (itype2, fd->loops[i - 1].step);
455338fd1498Szrj 	      t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true,
455438fd1498Szrj 					    GSI_SAME_STMT);
455538fd1498Szrj 	      t = build3 (COND_EXPR, itype2,
455638fd1498Szrj 			  build2 (fd->loops[i].cond_code, boolean_type_node,
455738fd1498Szrj 				  fd->loops[i].v,
455838fd1498Szrj 				  fold_convert (itype, fd->loops[i].n2)),
455938fd1498Szrj 			  build_int_cst (itype2, 0), t);
456038fd1498Szrj 	      if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
456138fd1498Szrj 		t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
456238fd1498Szrj 	      else
456338fd1498Szrj 		t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
456438fd1498Szrj 	      expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
456538fd1498Szrj 
456638fd1498Szrj 	      t = fold_convert (itype, fd->loops[i].n1);
456738fd1498Szrj 	      t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true,
456838fd1498Szrj 					    GSI_SAME_STMT);
456938fd1498Szrj 	      t = build3 (COND_EXPR, itype,
457038fd1498Szrj 			  build2 (fd->loops[i].cond_code, boolean_type_node,
457138fd1498Szrj 				  fd->loops[i].v,
457238fd1498Szrj 				  fold_convert (itype, fd->loops[i].n2)),
457338fd1498Szrj 			  fd->loops[i].v, t);
457438fd1498Szrj 	      expand_omp_build_assign (&gsi, fd->loops[i].v, t);
457538fd1498Szrj 	    }
457638fd1498Szrj 	}
457738fd1498Szrj 
457838fd1498Szrj       /* Remove GIMPLE_OMP_CONTINUE.  */
457938fd1498Szrj       gsi_remove (&gsi, true);
458038fd1498Szrj     }
458138fd1498Szrj 
458238fd1498Szrj   /* Emit the condition in L1_BB.  */
458338fd1498Szrj   gsi = gsi_start_bb (l1_bb);
458438fd1498Szrj 
458538fd1498Szrj   t = fold_convert (type, n2);
458638fd1498Szrj   t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
458738fd1498Szrj 				false, GSI_CONTINUE_LINKING);
458838fd1498Szrj   tree v = fd->loop.v;
458938fd1498Szrj   if (DECL_P (v) && TREE_ADDRESSABLE (v))
459038fd1498Szrj     v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
459138fd1498Szrj 				  false, GSI_CONTINUE_LINKING);
459238fd1498Szrj   t = build2 (fd->loop.cond_code, boolean_type_node, v, t);
459338fd1498Szrj   cond_stmt = gimple_build_cond_empty (t);
459438fd1498Szrj   gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
459538fd1498Szrj   if (walk_tree (gimple_cond_lhs_ptr (cond_stmt), expand_omp_regimplify_p,
459638fd1498Szrj 		 NULL, NULL)
459738fd1498Szrj       || walk_tree (gimple_cond_rhs_ptr (cond_stmt), expand_omp_regimplify_p,
459838fd1498Szrj 		    NULL, NULL))
459938fd1498Szrj     {
460038fd1498Szrj       gsi = gsi_for_stmt (cond_stmt);
460138fd1498Szrj       gimple_regimplify_operands (cond_stmt, &gsi);
460238fd1498Szrj     }
460338fd1498Szrj 
460438fd1498Szrj   /* Add 'V -= STEP * (SIMT_VF - 1)' after the loop.  */
460538fd1498Szrj   if (is_simt)
460638fd1498Szrj     {
460738fd1498Szrj       gsi = gsi_start_bb (l2_bb);
460838fd1498Szrj       step = fold_build2 (MINUS_EXPR, TREE_TYPE (step), fd->loop.step, step);
460938fd1498Szrj       if (POINTER_TYPE_P (type))
461038fd1498Szrj 	t = fold_build_pointer_plus (fd->loop.v, step);
461138fd1498Szrj       else
461238fd1498Szrj 	t = fold_build2 (PLUS_EXPR, type, fd->loop.v, step);
461338fd1498Szrj       expand_omp_build_assign (&gsi, fd->loop.v, t);
461438fd1498Szrj     }
461538fd1498Szrj 
461638fd1498Szrj   /* Remove GIMPLE_OMP_RETURN.  */
461738fd1498Szrj   gsi = gsi_last_nondebug_bb (exit_bb);
461838fd1498Szrj   gsi_remove (&gsi, true);
461938fd1498Szrj 
462038fd1498Szrj   /* Connect the new blocks.  */
462138fd1498Szrj   remove_edge (FALLTHRU_EDGE (entry_bb));
462238fd1498Szrj 
462338fd1498Szrj   if (!broken_loop)
462438fd1498Szrj     {
462538fd1498Szrj       remove_edge (BRANCH_EDGE (entry_bb));
462638fd1498Szrj       make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
462738fd1498Szrj 
462838fd1498Szrj       e = BRANCH_EDGE (l1_bb);
462938fd1498Szrj       ne = FALLTHRU_EDGE (l1_bb);
463038fd1498Szrj       e->flags = EDGE_TRUE_VALUE;
463138fd1498Szrj     }
463238fd1498Szrj   else
463338fd1498Szrj     {
463438fd1498Szrj       single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
463538fd1498Szrj 
463638fd1498Szrj       ne = single_succ_edge (l1_bb);
463738fd1498Szrj       e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
463838fd1498Szrj 
463938fd1498Szrj     }
464038fd1498Szrj   ne->flags = EDGE_FALSE_VALUE;
464138fd1498Szrj   e->probability = profile_probability::guessed_always ().apply_scale (7, 8);
464238fd1498Szrj   ne->probability = e->probability.invert ();
464338fd1498Szrj 
464438fd1498Szrj   set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
464538fd1498Szrj   set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
464638fd1498Szrj 
464738fd1498Szrj   if (simt_maxlane)
464838fd1498Szrj     {
464938fd1498Szrj       cond_stmt = gimple_build_cond (LT_EXPR, simt_lane, simt_maxlane,
465038fd1498Szrj 				     NULL_TREE, NULL_TREE);
465138fd1498Szrj       gsi = gsi_last_bb (entry_bb);
465238fd1498Szrj       gsi_insert_after (&gsi, cond_stmt, GSI_NEW_STMT);
465338fd1498Szrj       make_edge (entry_bb, l2_bb, EDGE_FALSE_VALUE);
465438fd1498Szrj       FALLTHRU_EDGE (entry_bb)->flags = EDGE_TRUE_VALUE;
465538fd1498Szrj       FALLTHRU_EDGE (entry_bb)->probability
465638fd1498Szrj 	 = profile_probability::guessed_always ().apply_scale (7, 8);
465738fd1498Szrj       BRANCH_EDGE (entry_bb)->probability
465838fd1498Szrj 	 = FALLTHRU_EDGE (entry_bb)->probability.invert ();
465938fd1498Szrj       l2_dom_bb = entry_bb;
466038fd1498Szrj     }
466138fd1498Szrj   set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
466238fd1498Szrj 
466338fd1498Szrj   if (!broken_loop)
466438fd1498Szrj     {
466538fd1498Szrj       struct loop *loop = alloc_loop ();
466638fd1498Szrj       loop->header = l1_bb;
466738fd1498Szrj       loop->latch = cont_bb;
466838fd1498Szrj       add_loop (loop, l1_bb->loop_father);
466938fd1498Szrj       loop->safelen = safelen_int;
467038fd1498Szrj       if (simduid)
467138fd1498Szrj 	{
467238fd1498Szrj 	  loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
467338fd1498Szrj 	  cfun->has_simduid_loops = true;
467438fd1498Szrj 	}
467538fd1498Szrj       /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
467638fd1498Szrj 	 the loop.  */
467738fd1498Szrj       if ((flag_tree_loop_vectorize
467838fd1498Szrj 	   || !global_options_set.x_flag_tree_loop_vectorize)
467938fd1498Szrj 	  && flag_tree_loop_optimize
468038fd1498Szrj 	  && loop->safelen > 1)
468138fd1498Szrj 	{
468238fd1498Szrj 	  loop->force_vectorize = true;
468338fd1498Szrj 	  cfun->has_force_vectorize_loops = true;
468438fd1498Szrj 	}
468538fd1498Szrj     }
468638fd1498Szrj   else if (simduid)
468738fd1498Szrj     cfun->has_simduid_loops = true;
468838fd1498Szrj }
468938fd1498Szrj 
469038fd1498Szrj /* Taskloop construct is represented after gimplification with
469138fd1498Szrj    two GIMPLE_OMP_FOR constructs with GIMPLE_OMP_TASK sandwiched
469238fd1498Szrj    in between them.  This routine expands the outer GIMPLE_OMP_FOR,
469338fd1498Szrj    which should just compute all the needed loop temporaries
469438fd1498Szrj    for GIMPLE_OMP_TASK.  */
469538fd1498Szrj 
469638fd1498Szrj static void
expand_omp_taskloop_for_outer(struct omp_region * region,struct omp_for_data * fd,gimple * inner_stmt)469738fd1498Szrj expand_omp_taskloop_for_outer (struct omp_region *region,
469838fd1498Szrj 			       struct omp_for_data *fd,
469938fd1498Szrj 			       gimple *inner_stmt)
470038fd1498Szrj {
470138fd1498Szrj   tree type, bias = NULL_TREE;
470238fd1498Szrj   basic_block entry_bb, cont_bb, exit_bb;
470338fd1498Szrj   gimple_stmt_iterator gsi;
470438fd1498Szrj   gassign *assign_stmt;
470538fd1498Szrj   tree *counts = NULL;
470638fd1498Szrj   int i;
470738fd1498Szrj 
470838fd1498Szrj   gcc_assert (inner_stmt);
470938fd1498Szrj   gcc_assert (region->cont);
471038fd1498Szrj   gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_TASK
471138fd1498Szrj 	      && gimple_omp_task_taskloop_p (inner_stmt));
471238fd1498Szrj   type = TREE_TYPE (fd->loop.v);
471338fd1498Szrj 
471438fd1498Szrj   /* See if we need to bias by LLONG_MIN.  */
471538fd1498Szrj   if (fd->iter_type == long_long_unsigned_type_node
471638fd1498Szrj       && TREE_CODE (type) == INTEGER_TYPE
471738fd1498Szrj       && !TYPE_UNSIGNED (type))
471838fd1498Szrj     {
471938fd1498Szrj       tree n1, n2;
472038fd1498Szrj 
472138fd1498Szrj       if (fd->loop.cond_code == LT_EXPR)
472238fd1498Szrj 	{
472338fd1498Szrj 	  n1 = fd->loop.n1;
472438fd1498Szrj 	  n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
472538fd1498Szrj 	}
472638fd1498Szrj       else
472738fd1498Szrj 	{
472838fd1498Szrj 	  n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
472938fd1498Szrj 	  n2 = fd->loop.n1;
473038fd1498Szrj 	}
473138fd1498Szrj       if (TREE_CODE (n1) != INTEGER_CST
473238fd1498Szrj 	  || TREE_CODE (n2) != INTEGER_CST
473338fd1498Szrj 	  || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
473438fd1498Szrj 	bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
473538fd1498Szrj     }
473638fd1498Szrj 
473738fd1498Szrj   entry_bb = region->entry;
473838fd1498Szrj   cont_bb = region->cont;
473938fd1498Szrj   gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
474038fd1498Szrj   gcc_assert (BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
474138fd1498Szrj   exit_bb = region->exit;
474238fd1498Szrj 
474338fd1498Szrj   gsi = gsi_last_nondebug_bb (entry_bb);
474438fd1498Szrj   gimple *for_stmt = gsi_stmt (gsi);
474538fd1498Szrj   gcc_assert (gimple_code (for_stmt) == GIMPLE_OMP_FOR);
474638fd1498Szrj   if (fd->collapse > 1)
474738fd1498Szrj     {
474838fd1498Szrj       int first_zero_iter = -1, dummy = -1;
474938fd1498Szrj       basic_block zero_iter_bb = NULL, dummy_bb = NULL, l2_dom_bb = NULL;
475038fd1498Szrj 
475138fd1498Szrj       counts = XALLOCAVEC (tree, fd->collapse);
475238fd1498Szrj       expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
475338fd1498Szrj 				  zero_iter_bb, first_zero_iter,
475438fd1498Szrj 				  dummy_bb, dummy, l2_dom_bb);
475538fd1498Szrj 
475638fd1498Szrj       if (zero_iter_bb)
475738fd1498Szrj 	{
475838fd1498Szrj 	  /* Some counts[i] vars might be uninitialized if
475938fd1498Szrj 	     some loop has zero iterations.  But the body shouldn't
476038fd1498Szrj 	     be executed in that case, so just avoid uninit warnings.  */
476138fd1498Szrj 	  for (i = first_zero_iter; i < fd->collapse; i++)
476238fd1498Szrj 	    if (SSA_VAR_P (counts[i]))
476338fd1498Szrj 	      TREE_NO_WARNING (counts[i]) = 1;
476438fd1498Szrj 	  gsi_prev (&gsi);
476538fd1498Szrj 	  edge e = split_block (entry_bb, gsi_stmt (gsi));
476638fd1498Szrj 	  entry_bb = e->dest;
476738fd1498Szrj 	  make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
476838fd1498Szrj 	  gsi = gsi_last_bb (entry_bb);
476938fd1498Szrj 	  set_immediate_dominator (CDI_DOMINATORS, entry_bb,
477038fd1498Szrj 				   get_immediate_dominator (CDI_DOMINATORS,
477138fd1498Szrj 							    zero_iter_bb));
477238fd1498Szrj 	}
477338fd1498Szrj     }
477438fd1498Szrj 
477538fd1498Szrj   tree t0, t1;
477638fd1498Szrj   t1 = fd->loop.n2;
477738fd1498Szrj   t0 = fd->loop.n1;
477838fd1498Szrj   if (POINTER_TYPE_P (TREE_TYPE (t0))
477938fd1498Szrj       && TYPE_PRECISION (TREE_TYPE (t0))
478038fd1498Szrj 	 != TYPE_PRECISION (fd->iter_type))
478138fd1498Szrj     {
478238fd1498Szrj       /* Avoid casting pointers to integer of a different size.  */
478338fd1498Szrj       tree itype = signed_type_for (type);
478438fd1498Szrj       t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
478538fd1498Szrj       t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
478638fd1498Szrj     }
478738fd1498Szrj   else
478838fd1498Szrj     {
478938fd1498Szrj       t1 = fold_convert (fd->iter_type, t1);
479038fd1498Szrj       t0 = fold_convert (fd->iter_type, t0);
479138fd1498Szrj     }
479238fd1498Szrj   if (bias)
479338fd1498Szrj     {
479438fd1498Szrj       t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
479538fd1498Szrj       t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
479638fd1498Szrj     }
479738fd1498Szrj 
479838fd1498Szrj   tree innerc = omp_find_clause (gimple_omp_task_clauses (inner_stmt),
479938fd1498Szrj 				 OMP_CLAUSE__LOOPTEMP_);
480038fd1498Szrj   gcc_assert (innerc);
480138fd1498Szrj   tree startvar = OMP_CLAUSE_DECL (innerc);
480238fd1498Szrj   innerc = omp_find_clause (OMP_CLAUSE_CHAIN (innerc), OMP_CLAUSE__LOOPTEMP_);
480338fd1498Szrj   gcc_assert (innerc);
480438fd1498Szrj   tree endvar = OMP_CLAUSE_DECL (innerc);
480538fd1498Szrj   if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
480638fd1498Szrj     {
480738fd1498Szrj       gcc_assert (innerc);
480838fd1498Szrj       for (i = 1; i < fd->collapse; i++)
480938fd1498Szrj 	{
481038fd1498Szrj 	  innerc = omp_find_clause (OMP_CLAUSE_CHAIN (innerc),
481138fd1498Szrj 				    OMP_CLAUSE__LOOPTEMP_);
481238fd1498Szrj 	  gcc_assert (innerc);
481338fd1498Szrj 	}
481438fd1498Szrj       innerc = omp_find_clause (OMP_CLAUSE_CHAIN (innerc),
481538fd1498Szrj 				OMP_CLAUSE__LOOPTEMP_);
481638fd1498Szrj       if (innerc)
481738fd1498Szrj 	{
481838fd1498Szrj 	  /* If needed (inner taskloop has lastprivate clause), propagate
481938fd1498Szrj 	     down the total number of iterations.  */
482038fd1498Szrj 	  tree t = force_gimple_operand_gsi (&gsi, fd->loop.n2, false,
482138fd1498Szrj 					     NULL_TREE, false,
482238fd1498Szrj 					     GSI_CONTINUE_LINKING);
482338fd1498Szrj 	  assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
482438fd1498Szrj 	  gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
482538fd1498Szrj 	}
482638fd1498Szrj     }
482738fd1498Szrj 
482838fd1498Szrj   t0 = force_gimple_operand_gsi (&gsi, t0, false, NULL_TREE, false,
482938fd1498Szrj 				 GSI_CONTINUE_LINKING);
483038fd1498Szrj   assign_stmt = gimple_build_assign (startvar, t0);
483138fd1498Szrj   gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
483238fd1498Szrj 
483338fd1498Szrj   t1 = force_gimple_operand_gsi (&gsi, t1, false, NULL_TREE, false,
483438fd1498Szrj 				 GSI_CONTINUE_LINKING);
483538fd1498Szrj   assign_stmt = gimple_build_assign (endvar, t1);
483638fd1498Szrj   gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
483738fd1498Szrj   if (fd->collapse > 1)
483838fd1498Szrj     expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
483938fd1498Szrj 
484038fd1498Szrj   /* Remove the GIMPLE_OMP_FOR statement.  */
484138fd1498Szrj   gsi = gsi_for_stmt (for_stmt);
484238fd1498Szrj   gsi_remove (&gsi, true);
484338fd1498Szrj 
484438fd1498Szrj   gsi = gsi_last_nondebug_bb (cont_bb);
484538fd1498Szrj   gsi_remove (&gsi, true);
484638fd1498Szrj 
484738fd1498Szrj   gsi = gsi_last_nondebug_bb (exit_bb);
484838fd1498Szrj   gsi_remove (&gsi, true);
484938fd1498Szrj 
485038fd1498Szrj   FALLTHRU_EDGE (entry_bb)->probability = profile_probability::always ();
485138fd1498Szrj   remove_edge (BRANCH_EDGE (entry_bb));
485238fd1498Szrj   FALLTHRU_EDGE (cont_bb)->probability = profile_probability::always ();
485338fd1498Szrj   remove_edge (BRANCH_EDGE (cont_bb));
485438fd1498Szrj   set_immediate_dominator (CDI_DOMINATORS, exit_bb, cont_bb);
485538fd1498Szrj   set_immediate_dominator (CDI_DOMINATORS, region->entry,
485638fd1498Szrj 			   recompute_dominator (CDI_DOMINATORS, region->entry));
485738fd1498Szrj }
485838fd1498Szrj 
485938fd1498Szrj /* Taskloop construct is represented after gimplification with
486038fd1498Szrj    two GIMPLE_OMP_FOR constructs with GIMPLE_OMP_TASK sandwiched
486138fd1498Szrj    in between them.  This routine expands the inner GIMPLE_OMP_FOR.
486238fd1498Szrj    GOMP_taskloop{,_ull} function arranges for each task to be given just
486338fd1498Szrj    a single range of iterations.  */
486438fd1498Szrj 
486538fd1498Szrj static void
expand_omp_taskloop_for_inner(struct omp_region * region,struct omp_for_data * fd,gimple * inner_stmt)486638fd1498Szrj expand_omp_taskloop_for_inner (struct omp_region *region,
486738fd1498Szrj 			       struct omp_for_data *fd,
486838fd1498Szrj 			       gimple *inner_stmt)
486938fd1498Szrj {
487038fd1498Szrj   tree e, t, type, itype, vmain, vback, bias = NULL_TREE;
487138fd1498Szrj   basic_block entry_bb, exit_bb, body_bb, cont_bb, collapse_bb = NULL;
487238fd1498Szrj   basic_block fin_bb;
487338fd1498Szrj   gimple_stmt_iterator gsi;
487438fd1498Szrj   edge ep;
487538fd1498Szrj   bool broken_loop = region->cont == NULL;
487638fd1498Szrj   tree *counts = NULL;
487738fd1498Szrj   tree n1, n2, step;
487838fd1498Szrj 
487938fd1498Szrj   itype = type = TREE_TYPE (fd->loop.v);
488038fd1498Szrj   if (POINTER_TYPE_P (type))
488138fd1498Szrj     itype = signed_type_for (type);
488238fd1498Szrj 
488338fd1498Szrj   /* See if we need to bias by LLONG_MIN.  */
488438fd1498Szrj   if (fd->iter_type == long_long_unsigned_type_node
488538fd1498Szrj       && TREE_CODE (type) == INTEGER_TYPE
488638fd1498Szrj       && !TYPE_UNSIGNED (type))
488738fd1498Szrj     {
488838fd1498Szrj       tree n1, n2;
488938fd1498Szrj 
489038fd1498Szrj       if (fd->loop.cond_code == LT_EXPR)
489138fd1498Szrj 	{
489238fd1498Szrj 	  n1 = fd->loop.n1;
489338fd1498Szrj 	  n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
489438fd1498Szrj 	}
489538fd1498Szrj       else
489638fd1498Szrj 	{
489738fd1498Szrj 	  n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
489838fd1498Szrj 	  n2 = fd->loop.n1;
489938fd1498Szrj 	}
490038fd1498Szrj       if (TREE_CODE (n1) != INTEGER_CST
490138fd1498Szrj 	  || TREE_CODE (n2) != INTEGER_CST
490238fd1498Szrj 	  || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
490338fd1498Szrj 	bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
490438fd1498Szrj     }
490538fd1498Szrj 
490638fd1498Szrj   entry_bb = region->entry;
490738fd1498Szrj   cont_bb = region->cont;
490838fd1498Szrj   gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
490938fd1498Szrj   fin_bb = BRANCH_EDGE (entry_bb)->dest;
491038fd1498Szrj   gcc_assert (broken_loop
491138fd1498Szrj 	      || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
491238fd1498Szrj   body_bb = FALLTHRU_EDGE (entry_bb)->dest;
491338fd1498Szrj   if (!broken_loop)
491438fd1498Szrj     {
491538fd1498Szrj       gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
491638fd1498Szrj       gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
491738fd1498Szrj     }
491838fd1498Szrj   exit_bb = region->exit;
491938fd1498Szrj 
492038fd1498Szrj   /* Iteration space partitioning goes in ENTRY_BB.  */
492138fd1498Szrj   gsi = gsi_last_nondebug_bb (entry_bb);
492238fd1498Szrj   gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
492338fd1498Szrj 
492438fd1498Szrj   if (fd->collapse > 1)
492538fd1498Szrj     {
492638fd1498Szrj       int first_zero_iter = -1, dummy = -1;
492738fd1498Szrj       basic_block l2_dom_bb = NULL, dummy_bb = NULL;
492838fd1498Szrj 
492938fd1498Szrj       counts = XALLOCAVEC (tree, fd->collapse);
493038fd1498Szrj       expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
493138fd1498Szrj 				  fin_bb, first_zero_iter,
493238fd1498Szrj 				  dummy_bb, dummy, l2_dom_bb);
493338fd1498Szrj       t = NULL_TREE;
493438fd1498Szrj     }
493538fd1498Szrj   else
493638fd1498Szrj     t = integer_one_node;
493738fd1498Szrj 
493838fd1498Szrj   step = fd->loop.step;
493938fd1498Szrj   tree innerc = omp_find_clause (gimple_omp_for_clauses (fd->for_stmt),
494038fd1498Szrj 				 OMP_CLAUSE__LOOPTEMP_);
494138fd1498Szrj   gcc_assert (innerc);
494238fd1498Szrj   n1 = OMP_CLAUSE_DECL (innerc);
494338fd1498Szrj   innerc = omp_find_clause (OMP_CLAUSE_CHAIN (innerc), OMP_CLAUSE__LOOPTEMP_);
494438fd1498Szrj   gcc_assert (innerc);
494538fd1498Szrj   n2 = OMP_CLAUSE_DECL (innerc);
494638fd1498Szrj   if (bias)
494738fd1498Szrj     {
494838fd1498Szrj       n1 = fold_build2 (PLUS_EXPR, fd->iter_type, n1, bias);
494938fd1498Szrj       n2 = fold_build2 (PLUS_EXPR, fd->iter_type, n2, bias);
495038fd1498Szrj     }
495138fd1498Szrj   n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
495238fd1498Szrj 				 true, NULL_TREE, true, GSI_SAME_STMT);
495338fd1498Szrj   n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
495438fd1498Szrj 				 true, NULL_TREE, true, GSI_SAME_STMT);
495538fd1498Szrj   step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
495638fd1498Szrj 				   true, NULL_TREE, true, GSI_SAME_STMT);
495738fd1498Szrj 
495838fd1498Szrj   tree startvar = fd->loop.v;
495938fd1498Szrj   tree endvar = NULL_TREE;
496038fd1498Szrj 
496138fd1498Szrj   if (gimple_omp_for_combined_p (fd->for_stmt))
496238fd1498Szrj     {
496338fd1498Szrj       tree clauses = gimple_omp_for_clauses (inner_stmt);
496438fd1498Szrj       tree innerc = omp_find_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
496538fd1498Szrj       gcc_assert (innerc);
496638fd1498Szrj       startvar = OMP_CLAUSE_DECL (innerc);
496738fd1498Szrj       innerc = omp_find_clause (OMP_CLAUSE_CHAIN (innerc),
496838fd1498Szrj 				OMP_CLAUSE__LOOPTEMP_);
496938fd1498Szrj       gcc_assert (innerc);
497038fd1498Szrj       endvar = OMP_CLAUSE_DECL (innerc);
497138fd1498Szrj     }
497238fd1498Szrj   t = fold_convert (TREE_TYPE (startvar), n1);
497338fd1498Szrj   t = force_gimple_operand_gsi (&gsi, t,
497438fd1498Szrj 				DECL_P (startvar)
497538fd1498Szrj 				&& TREE_ADDRESSABLE (startvar),
497638fd1498Szrj 				NULL_TREE, false, GSI_CONTINUE_LINKING);
497738fd1498Szrj   gimple *assign_stmt = gimple_build_assign (startvar, t);
497838fd1498Szrj   gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
497938fd1498Szrj 
498038fd1498Szrj   t = fold_convert (TREE_TYPE (startvar), n2);
498138fd1498Szrj   e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
498238fd1498Szrj 				false, GSI_CONTINUE_LINKING);
498338fd1498Szrj   if (endvar)
498438fd1498Szrj     {
498538fd1498Szrj       assign_stmt = gimple_build_assign (endvar, e);
498638fd1498Szrj       gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
498738fd1498Szrj       if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
498838fd1498Szrj 	assign_stmt = gimple_build_assign (fd->loop.v, e);
498938fd1498Szrj       else
499038fd1498Szrj 	assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
499138fd1498Szrj       gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
499238fd1498Szrj     }
499338fd1498Szrj   if (fd->collapse > 1)
499438fd1498Szrj     expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
499538fd1498Szrj 
499638fd1498Szrj   if (!broken_loop)
499738fd1498Szrj     {
499838fd1498Szrj       /* The code controlling the sequential loop replaces the
499938fd1498Szrj 	 GIMPLE_OMP_CONTINUE.  */
500038fd1498Szrj       gsi = gsi_last_nondebug_bb (cont_bb);
500138fd1498Szrj       gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
500238fd1498Szrj       gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
500338fd1498Szrj       vmain = gimple_omp_continue_control_use (cont_stmt);
500438fd1498Szrj       vback = gimple_omp_continue_control_def (cont_stmt);
500538fd1498Szrj 
500638fd1498Szrj       if (!gimple_omp_for_combined_p (fd->for_stmt))
500738fd1498Szrj 	{
500838fd1498Szrj 	  if (POINTER_TYPE_P (type))
500938fd1498Szrj 	    t = fold_build_pointer_plus (vmain, step);
501038fd1498Szrj 	  else
501138fd1498Szrj 	    t = fold_build2 (PLUS_EXPR, type, vmain, step);
501238fd1498Szrj 	  t = force_gimple_operand_gsi (&gsi, t,
501338fd1498Szrj 					DECL_P (vback)
501438fd1498Szrj 					&& TREE_ADDRESSABLE (vback),
501538fd1498Szrj 					NULL_TREE, true, GSI_SAME_STMT);
501638fd1498Szrj 	  assign_stmt = gimple_build_assign (vback, t);
501738fd1498Szrj 	  gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
501838fd1498Szrj 
501938fd1498Szrj 	  t = build2 (fd->loop.cond_code, boolean_type_node,
502038fd1498Szrj 		      DECL_P (vback) && TREE_ADDRESSABLE (vback)
502138fd1498Szrj 		      ? t : vback, e);
502238fd1498Szrj 	  gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
502338fd1498Szrj 	}
502438fd1498Szrj 
502538fd1498Szrj       /* Remove the GIMPLE_OMP_CONTINUE statement.  */
502638fd1498Szrj       gsi_remove (&gsi, true);
502738fd1498Szrj 
502838fd1498Szrj       if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
502938fd1498Szrj 	collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
503038fd1498Szrj     }
503138fd1498Szrj 
503238fd1498Szrj   /* Remove the GIMPLE_OMP_FOR statement.  */
503338fd1498Szrj   gsi = gsi_for_stmt (fd->for_stmt);
503438fd1498Szrj   gsi_remove (&gsi, true);
503538fd1498Szrj 
503638fd1498Szrj   /* Remove the GIMPLE_OMP_RETURN statement.  */
503738fd1498Szrj   gsi = gsi_last_nondebug_bb (exit_bb);
503838fd1498Szrj   gsi_remove (&gsi, true);
503938fd1498Szrj 
504038fd1498Szrj   FALLTHRU_EDGE (entry_bb)->probability = profile_probability::always ();
504138fd1498Szrj   if (!broken_loop)
504238fd1498Szrj     remove_edge (BRANCH_EDGE (entry_bb));
504338fd1498Szrj   else
504438fd1498Szrj     {
504538fd1498Szrj       remove_edge_and_dominated_blocks (BRANCH_EDGE (entry_bb));
504638fd1498Szrj       region->outer->cont = NULL;
504738fd1498Szrj     }
504838fd1498Szrj 
504938fd1498Szrj   /* Connect all the blocks.  */
505038fd1498Szrj   if (!broken_loop)
505138fd1498Szrj     {
505238fd1498Szrj       ep = find_edge (cont_bb, body_bb);
505338fd1498Szrj       if (gimple_omp_for_combined_p (fd->for_stmt))
505438fd1498Szrj 	{
505538fd1498Szrj 	  remove_edge (ep);
505638fd1498Szrj 	  ep = NULL;
505738fd1498Szrj 	}
505838fd1498Szrj       else if (fd->collapse > 1)
505938fd1498Szrj 	{
506038fd1498Szrj 	  remove_edge (ep);
506138fd1498Szrj 	  ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
506238fd1498Szrj 	}
506338fd1498Szrj       else
506438fd1498Szrj 	ep->flags = EDGE_TRUE_VALUE;
506538fd1498Szrj       find_edge (cont_bb, fin_bb)->flags
506638fd1498Szrj 	= ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
506738fd1498Szrj     }
506838fd1498Szrj 
506938fd1498Szrj   set_immediate_dominator (CDI_DOMINATORS, body_bb,
507038fd1498Szrj 			   recompute_dominator (CDI_DOMINATORS, body_bb));
507138fd1498Szrj   if (!broken_loop)
507238fd1498Szrj     set_immediate_dominator (CDI_DOMINATORS, fin_bb,
507338fd1498Szrj 			     recompute_dominator (CDI_DOMINATORS, fin_bb));
507438fd1498Szrj 
507538fd1498Szrj   if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
507638fd1498Szrj     {
507738fd1498Szrj       struct loop *loop = alloc_loop ();
507838fd1498Szrj       loop->header = body_bb;
507938fd1498Szrj       if (collapse_bb == NULL)
508038fd1498Szrj 	loop->latch = cont_bb;
508138fd1498Szrj       add_loop (loop, body_bb->loop_father);
508238fd1498Szrj     }
508338fd1498Szrj }
508438fd1498Szrj 
508538fd1498Szrj /* A subroutine of expand_omp_for.  Generate code for an OpenACC
508638fd1498Szrj    partitioned loop.  The lowering here is abstracted, in that the
508738fd1498Szrj    loop parameters are passed through internal functions, which are
508838fd1498Szrj    further lowered by oacc_device_lower, once we get to the target
508938fd1498Szrj    compiler.  The loop is of the form:
509038fd1498Szrj 
509138fd1498Szrj    for (V = B; V LTGT E; V += S) {BODY}
509238fd1498Szrj 
509338fd1498Szrj    where LTGT is < or >.  We may have a specified chunking size, CHUNKING
509438fd1498Szrj    (constant 0 for no chunking) and we will have a GWV partitioning
509538fd1498Szrj    mask, specifying dimensions over which the loop is to be
509638fd1498Szrj    partitioned (see note below).  We generate code that looks like
509738fd1498Szrj    (this ignores tiling):
509838fd1498Szrj 
509938fd1498Szrj    <entry_bb> [incoming FALL->body, BRANCH->exit]
510038fd1498Szrj      typedef signedintify (typeof (V)) T;  // underlying signed integral type
510138fd1498Szrj      T range = E - B;
510238fd1498Szrj      T chunk_no = 0;
510338fd1498Szrj      T DIR = LTGT == '<' ? +1 : -1;
510438fd1498Szrj      T chunk_max = GOACC_LOOP_CHUNK (dir, range, S, CHUNK_SIZE, GWV);
510538fd1498Szrj      T step = GOACC_LOOP_STEP (dir, range, S, CHUNK_SIZE, GWV);
510638fd1498Szrj 
510738fd1498Szrj    <head_bb> [created by splitting end of entry_bb]
510838fd1498Szrj      T offset = GOACC_LOOP_OFFSET (dir, range, S, CHUNK_SIZE, GWV, chunk_no);
510938fd1498Szrj      T bound = GOACC_LOOP_BOUND (dir, range, S, CHUNK_SIZE, GWV, offset);
511038fd1498Szrj      if (!(offset LTGT bound)) goto bottom_bb;
511138fd1498Szrj 
511238fd1498Szrj    <body_bb> [incoming]
511338fd1498Szrj      V = B + offset;
511438fd1498Szrj      {BODY}
511538fd1498Szrj 
511638fd1498Szrj    <cont_bb> [incoming, may == body_bb FALL->exit_bb, BRANCH->body_bb]
511738fd1498Szrj      offset += step;
511838fd1498Szrj      if (offset LTGT bound) goto body_bb; [*]
511938fd1498Szrj 
512038fd1498Szrj    <bottom_bb> [created by splitting start of exit_bb] insert BRANCH->head_bb
512138fd1498Szrj      chunk_no++;
512238fd1498Szrj      if (chunk < chunk_max) goto head_bb;
512338fd1498Szrj 
512438fd1498Szrj    <exit_bb> [incoming]
512538fd1498Szrj      V = B + ((range -/+ 1) / S +/- 1) * S [*]
512638fd1498Szrj 
512738fd1498Szrj    [*] Needed if V live at end of loop.  */
512838fd1498Szrj 
512938fd1498Szrj static void
expand_oacc_for(struct omp_region * region,struct omp_for_data * fd)513038fd1498Szrj expand_oacc_for (struct omp_region *region, struct omp_for_data *fd)
513138fd1498Szrj {
513238fd1498Szrj   tree v = fd->loop.v;
513338fd1498Szrj   enum tree_code cond_code = fd->loop.cond_code;
513438fd1498Szrj   enum tree_code plus_code = PLUS_EXPR;
513538fd1498Szrj 
513638fd1498Szrj   tree chunk_size = integer_minus_one_node;
513738fd1498Szrj   tree gwv = integer_zero_node;
513838fd1498Szrj   tree iter_type = TREE_TYPE (v);
513938fd1498Szrj   tree diff_type = iter_type;
514038fd1498Szrj   tree plus_type = iter_type;
514138fd1498Szrj   struct oacc_collapse *counts = NULL;
514238fd1498Szrj 
514338fd1498Szrj   gcc_checking_assert (gimple_omp_for_kind (fd->for_stmt)
514438fd1498Szrj 		       == GF_OMP_FOR_KIND_OACC_LOOP);
514538fd1498Szrj   gcc_assert (!gimple_omp_for_combined_into_p (fd->for_stmt));
514638fd1498Szrj   gcc_assert (cond_code == LT_EXPR || cond_code == GT_EXPR);
514738fd1498Szrj 
514838fd1498Szrj   if (POINTER_TYPE_P (iter_type))
514938fd1498Szrj     {
515038fd1498Szrj       plus_code = POINTER_PLUS_EXPR;
515138fd1498Szrj       plus_type = sizetype;
515238fd1498Szrj     }
515338fd1498Szrj   if (POINTER_TYPE_P (diff_type) || TYPE_UNSIGNED (diff_type))
515438fd1498Szrj     diff_type = signed_type_for (diff_type);
515538fd1498Szrj   if (TYPE_PRECISION (diff_type) < TYPE_PRECISION (integer_type_node))
515638fd1498Szrj     diff_type = integer_type_node;
515738fd1498Szrj 
515838fd1498Szrj   basic_block entry_bb = region->entry; /* BB ending in OMP_FOR */
515938fd1498Szrj   basic_block exit_bb = region->exit; /* BB ending in OMP_RETURN */
516038fd1498Szrj   basic_block cont_bb = region->cont; /* BB ending in OMP_CONTINUE  */
516138fd1498Szrj   basic_block bottom_bb = NULL;
516238fd1498Szrj 
516338fd1498Szrj   /* entry_bb has two sucessors; the branch edge is to the exit
516438fd1498Szrj      block,  fallthrough edge to body.  */
516538fd1498Szrj   gcc_assert (EDGE_COUNT (entry_bb->succs) == 2
516638fd1498Szrj 	      && BRANCH_EDGE (entry_bb)->dest == exit_bb);
516738fd1498Szrj 
516838fd1498Szrj   /* If cont_bb non-NULL, it has 2 successors.  The branch successor is
516938fd1498Szrj      body_bb, or to a block whose only successor is the body_bb.  Its
517038fd1498Szrj      fallthrough successor is the final block (same as the branch
517138fd1498Szrj      successor of the entry_bb).  */
517238fd1498Szrj   if (cont_bb)
517338fd1498Szrj     {
517438fd1498Szrj       basic_block body_bb = FALLTHRU_EDGE (entry_bb)->dest;
517538fd1498Szrj       basic_block bed = BRANCH_EDGE (cont_bb)->dest;
517638fd1498Szrj 
517738fd1498Szrj       gcc_assert (FALLTHRU_EDGE (cont_bb)->dest == exit_bb);
517838fd1498Szrj       gcc_assert (bed == body_bb || single_succ_edge (bed)->dest == body_bb);
517938fd1498Szrj     }
518038fd1498Szrj   else
518138fd1498Szrj     gcc_assert (!gimple_in_ssa_p (cfun));
518238fd1498Szrj 
518338fd1498Szrj   /* The exit block only has entry_bb and cont_bb as predecessors.  */
518438fd1498Szrj   gcc_assert (EDGE_COUNT (exit_bb->preds) == 1 + (cont_bb != NULL));
518538fd1498Szrj 
518638fd1498Szrj   tree chunk_no;
518738fd1498Szrj   tree chunk_max = NULL_TREE;
518838fd1498Szrj   tree bound, offset;
518938fd1498Szrj   tree step = create_tmp_var (diff_type, ".step");
519038fd1498Szrj   bool up = cond_code == LT_EXPR;
519138fd1498Szrj   tree dir = build_int_cst (diff_type, up ? +1 : -1);
519238fd1498Szrj   bool chunking = !gimple_in_ssa_p (cfun);
519338fd1498Szrj   bool negating;
519438fd1498Szrj 
519538fd1498Szrj   /* Tiling vars.  */
519638fd1498Szrj   tree tile_size = NULL_TREE;
519738fd1498Szrj   tree element_s = NULL_TREE;
519838fd1498Szrj   tree e_bound = NULL_TREE, e_offset = NULL_TREE, e_step = NULL_TREE;
519938fd1498Szrj   basic_block elem_body_bb = NULL;
520038fd1498Szrj   basic_block elem_cont_bb = NULL;
520138fd1498Szrj 
520238fd1498Szrj   /* SSA instances.  */
520338fd1498Szrj   tree offset_incr = NULL_TREE;
520438fd1498Szrj   tree offset_init = NULL_TREE;
520538fd1498Szrj 
520638fd1498Szrj   gimple_stmt_iterator gsi;
520738fd1498Szrj   gassign *ass;
520838fd1498Szrj   gcall *call;
520938fd1498Szrj   gimple *stmt;
521038fd1498Szrj   tree expr;
521138fd1498Szrj   location_t loc;
521238fd1498Szrj   edge split, be, fte;
521338fd1498Szrj 
521438fd1498Szrj   /* Split the end of entry_bb to create head_bb.  */
521538fd1498Szrj   split = split_block (entry_bb, last_stmt (entry_bb));
521638fd1498Szrj   basic_block head_bb = split->dest;
521738fd1498Szrj   entry_bb = split->src;
521838fd1498Szrj 
521938fd1498Szrj   /* Chunk setup goes at end of entry_bb, replacing the omp_for.  */
522038fd1498Szrj   gsi = gsi_last_nondebug_bb (entry_bb);
522138fd1498Szrj   gomp_for *for_stmt = as_a <gomp_for *> (gsi_stmt (gsi));
522238fd1498Szrj   loc = gimple_location (for_stmt);
522338fd1498Szrj 
522438fd1498Szrj   if (gimple_in_ssa_p (cfun))
522538fd1498Szrj     {
522638fd1498Szrj       offset_init = gimple_omp_for_index (for_stmt, 0);
522738fd1498Szrj       gcc_assert (integer_zerop (fd->loop.n1));
522838fd1498Szrj       /* The SSA parallelizer does gang parallelism.  */
522938fd1498Szrj       gwv = build_int_cst (integer_type_node, GOMP_DIM_MASK (GOMP_DIM_GANG));
523038fd1498Szrj     }
523138fd1498Szrj 
523238fd1498Szrj   if (fd->collapse > 1 || fd->tiling)
523338fd1498Szrj     {
523438fd1498Szrj       gcc_assert (!gimple_in_ssa_p (cfun) && up);
523538fd1498Szrj       counts = XALLOCAVEC (struct oacc_collapse, fd->collapse);
523638fd1498Szrj       tree total = expand_oacc_collapse_init (fd, &gsi, counts,
523738fd1498Szrj 					      TREE_TYPE (fd->loop.n2), loc);
523838fd1498Szrj 
523938fd1498Szrj       if (SSA_VAR_P (fd->loop.n2))
524038fd1498Szrj 	{
524138fd1498Szrj 	  total = force_gimple_operand_gsi (&gsi, total, false, NULL_TREE,
524238fd1498Szrj 					    true, GSI_SAME_STMT);
524338fd1498Szrj 	  ass = gimple_build_assign (fd->loop.n2, total);
524438fd1498Szrj 	  gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
524538fd1498Szrj 	}
524638fd1498Szrj     }
524738fd1498Szrj 
524838fd1498Szrj   tree b = fd->loop.n1;
524938fd1498Szrj   tree e = fd->loop.n2;
525038fd1498Szrj   tree s = fd->loop.step;
525138fd1498Szrj 
525238fd1498Szrj   b = force_gimple_operand_gsi (&gsi, b, true, NULL_TREE, true, GSI_SAME_STMT);
525338fd1498Szrj   e = force_gimple_operand_gsi (&gsi, e, true, NULL_TREE, true, GSI_SAME_STMT);
525438fd1498Szrj 
525538fd1498Szrj   /* Convert the step, avoiding possible unsigned->signed overflow.  */
525638fd1498Szrj   negating = !up && TYPE_UNSIGNED (TREE_TYPE (s));
525738fd1498Szrj   if (negating)
525838fd1498Szrj     s = fold_build1 (NEGATE_EXPR, TREE_TYPE (s), s);
525938fd1498Szrj   s = fold_convert (diff_type, s);
526038fd1498Szrj   if (negating)
526138fd1498Szrj     s = fold_build1 (NEGATE_EXPR, diff_type, s);
526238fd1498Szrj   s = force_gimple_operand_gsi (&gsi, s, true, NULL_TREE, true, GSI_SAME_STMT);
526338fd1498Szrj 
526438fd1498Szrj   if (!chunking)
526538fd1498Szrj     chunk_size = integer_zero_node;
526638fd1498Szrj   expr = fold_convert (diff_type, chunk_size);
526738fd1498Szrj   chunk_size = force_gimple_operand_gsi (&gsi, expr, true,
526838fd1498Szrj 					 NULL_TREE, true, GSI_SAME_STMT);
526938fd1498Szrj 
527038fd1498Szrj   if (fd->tiling)
527138fd1498Szrj     {
527238fd1498Szrj       /* Determine the tile size and element step,
527338fd1498Szrj 	 modify the outer loop step size.  */
527438fd1498Szrj       tile_size = create_tmp_var (diff_type, ".tile_size");
527538fd1498Szrj       expr = build_int_cst (diff_type, 1);
527638fd1498Szrj       for (int ix = 0; ix < fd->collapse; ix++)
527738fd1498Szrj 	expr = fold_build2 (MULT_EXPR, diff_type, counts[ix].tile, expr);
527838fd1498Szrj       expr = force_gimple_operand_gsi (&gsi, expr, true,
527938fd1498Szrj 				       NULL_TREE, true, GSI_SAME_STMT);
528038fd1498Szrj       ass = gimple_build_assign (tile_size, expr);
528138fd1498Szrj       gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
528238fd1498Szrj 
528338fd1498Szrj       element_s = create_tmp_var (diff_type, ".element_s");
528438fd1498Szrj       ass = gimple_build_assign (element_s, s);
528538fd1498Szrj       gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
528638fd1498Szrj 
528738fd1498Szrj       expr = fold_build2 (MULT_EXPR, diff_type, s, tile_size);
528838fd1498Szrj       s = force_gimple_operand_gsi (&gsi, expr, true,
528938fd1498Szrj 				    NULL_TREE, true, GSI_SAME_STMT);
529038fd1498Szrj     }
529138fd1498Szrj 
529238fd1498Szrj   /* Determine the range, avoiding possible unsigned->signed overflow.  */
529338fd1498Szrj   negating = !up && TYPE_UNSIGNED (iter_type);
529438fd1498Szrj   expr = fold_build2 (MINUS_EXPR, plus_type,
529538fd1498Szrj 		      fold_convert (plus_type, negating ? b : e),
529638fd1498Szrj 		      fold_convert (plus_type, negating ? e : b));
529738fd1498Szrj   expr = fold_convert (diff_type, expr);
529838fd1498Szrj   if (negating)
529938fd1498Szrj     expr = fold_build1 (NEGATE_EXPR, diff_type, expr);
530038fd1498Szrj   tree range = force_gimple_operand_gsi (&gsi, expr, true,
530138fd1498Szrj 					 NULL_TREE, true, GSI_SAME_STMT);
530238fd1498Szrj 
530338fd1498Szrj   chunk_no = build_int_cst (diff_type, 0);
530438fd1498Szrj   if (chunking)
530538fd1498Szrj     {
530638fd1498Szrj       gcc_assert (!gimple_in_ssa_p (cfun));
530738fd1498Szrj 
530838fd1498Szrj       expr = chunk_no;
530938fd1498Szrj       chunk_max = create_tmp_var (diff_type, ".chunk_max");
531038fd1498Szrj       chunk_no = create_tmp_var (diff_type, ".chunk_no");
531138fd1498Szrj 
531238fd1498Szrj       ass = gimple_build_assign (chunk_no, expr);
531338fd1498Szrj       gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
531438fd1498Szrj 
531538fd1498Szrj       call = gimple_build_call_internal (IFN_GOACC_LOOP, 6,
531638fd1498Szrj 					 build_int_cst (integer_type_node,
531738fd1498Szrj 							IFN_GOACC_LOOP_CHUNKS),
531838fd1498Szrj 					 dir, range, s, chunk_size, gwv);
531938fd1498Szrj       gimple_call_set_lhs (call, chunk_max);
532038fd1498Szrj       gimple_set_location (call, loc);
532138fd1498Szrj       gsi_insert_before (&gsi, call, GSI_SAME_STMT);
532238fd1498Szrj     }
532338fd1498Szrj   else
532438fd1498Szrj     chunk_size = chunk_no;
532538fd1498Szrj 
532638fd1498Szrj   call = gimple_build_call_internal (IFN_GOACC_LOOP, 6,
532738fd1498Szrj 				     build_int_cst (integer_type_node,
532838fd1498Szrj 						    IFN_GOACC_LOOP_STEP),
532938fd1498Szrj 				     dir, range, s, chunk_size, gwv);
533038fd1498Szrj   gimple_call_set_lhs (call, step);
533138fd1498Szrj   gimple_set_location (call, loc);
533238fd1498Szrj   gsi_insert_before (&gsi, call, GSI_SAME_STMT);
533338fd1498Szrj 
533438fd1498Szrj   /* Remove the GIMPLE_OMP_FOR.  */
533538fd1498Szrj   gsi_remove (&gsi, true);
533638fd1498Szrj 
533738fd1498Szrj   /* Fixup edges from head_bb.  */
533838fd1498Szrj   be = BRANCH_EDGE (head_bb);
533938fd1498Szrj   fte = FALLTHRU_EDGE (head_bb);
534038fd1498Szrj   be->flags |= EDGE_FALSE_VALUE;
534138fd1498Szrj   fte->flags ^= EDGE_FALLTHRU | EDGE_TRUE_VALUE;
534238fd1498Szrj 
534338fd1498Szrj   basic_block body_bb = fte->dest;
534438fd1498Szrj 
534538fd1498Szrj   if (gimple_in_ssa_p (cfun))
534638fd1498Szrj     {
534738fd1498Szrj       gsi = gsi_last_nondebug_bb (cont_bb);
534838fd1498Szrj       gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
534938fd1498Szrj 
535038fd1498Szrj       offset = gimple_omp_continue_control_use (cont_stmt);
535138fd1498Szrj       offset_incr = gimple_omp_continue_control_def (cont_stmt);
535238fd1498Szrj     }
535338fd1498Szrj   else
535438fd1498Szrj     {
535538fd1498Szrj       offset = create_tmp_var (diff_type, ".offset");
535638fd1498Szrj       offset_init = offset_incr = offset;
535738fd1498Szrj     }
535838fd1498Szrj   bound = create_tmp_var (TREE_TYPE (offset), ".bound");
535938fd1498Szrj 
536038fd1498Szrj   /* Loop offset & bound go into head_bb.  */
536138fd1498Szrj   gsi = gsi_start_bb (head_bb);
536238fd1498Szrj 
536338fd1498Szrj   call = gimple_build_call_internal (IFN_GOACC_LOOP, 7,
536438fd1498Szrj 				     build_int_cst (integer_type_node,
536538fd1498Szrj 						    IFN_GOACC_LOOP_OFFSET),
536638fd1498Szrj 				     dir, range, s,
536738fd1498Szrj 				     chunk_size, gwv, chunk_no);
536838fd1498Szrj   gimple_call_set_lhs (call, offset_init);
536938fd1498Szrj   gimple_set_location (call, loc);
537038fd1498Szrj   gsi_insert_after (&gsi, call, GSI_CONTINUE_LINKING);
537138fd1498Szrj 
537238fd1498Szrj   call = gimple_build_call_internal (IFN_GOACC_LOOP, 7,
537338fd1498Szrj 				     build_int_cst (integer_type_node,
537438fd1498Szrj 						    IFN_GOACC_LOOP_BOUND),
537538fd1498Szrj 				     dir, range, s,
537638fd1498Szrj 				     chunk_size, gwv, offset_init);
537738fd1498Szrj   gimple_call_set_lhs (call, bound);
537838fd1498Szrj   gimple_set_location (call, loc);
537938fd1498Szrj   gsi_insert_after (&gsi, call, GSI_CONTINUE_LINKING);
538038fd1498Szrj 
538138fd1498Szrj   expr = build2 (cond_code, boolean_type_node, offset_init, bound);
538238fd1498Szrj   gsi_insert_after (&gsi, gimple_build_cond_empty (expr),
538338fd1498Szrj 		    GSI_CONTINUE_LINKING);
538438fd1498Szrj 
538538fd1498Szrj   /* V assignment goes into body_bb.  */
538638fd1498Szrj   if (!gimple_in_ssa_p (cfun))
538738fd1498Szrj     {
538838fd1498Szrj       gsi = gsi_start_bb (body_bb);
538938fd1498Szrj 
539038fd1498Szrj       expr = build2 (plus_code, iter_type, b,
539138fd1498Szrj 		     fold_convert (plus_type, offset));
539238fd1498Szrj       expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
539338fd1498Szrj 				       true, GSI_SAME_STMT);
539438fd1498Szrj       ass = gimple_build_assign (v, expr);
539538fd1498Szrj       gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
539638fd1498Szrj 
539738fd1498Szrj       if (fd->collapse > 1 || fd->tiling)
539838fd1498Szrj 	expand_oacc_collapse_vars (fd, false, &gsi, counts, v);
539938fd1498Szrj 
540038fd1498Szrj       if (fd->tiling)
540138fd1498Szrj 	{
540238fd1498Szrj 	  /* Determine the range of the element loop -- usually simply
540338fd1498Szrj 	     the tile_size, but could be smaller if the final
540438fd1498Szrj 	     iteration of the outer loop is a partial tile.  */
540538fd1498Szrj 	  tree e_range = create_tmp_var (diff_type, ".e_range");
540638fd1498Szrj 
540738fd1498Szrj 	  expr = build2 (MIN_EXPR, diff_type,
540838fd1498Szrj 			 build2 (MINUS_EXPR, diff_type, bound, offset),
540938fd1498Szrj 			 build2 (MULT_EXPR, diff_type, tile_size,
541038fd1498Szrj 				 element_s));
541138fd1498Szrj 	  expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
541238fd1498Szrj 					   true, GSI_SAME_STMT);
541338fd1498Szrj 	  ass = gimple_build_assign (e_range, expr);
541438fd1498Szrj 	  gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
541538fd1498Szrj 
541638fd1498Szrj 	  /* Determine bound, offset & step of inner loop. */
541738fd1498Szrj 	  e_bound = create_tmp_var (diff_type, ".e_bound");
541838fd1498Szrj 	  e_offset = create_tmp_var (diff_type, ".e_offset");
541938fd1498Szrj 	  e_step = create_tmp_var (diff_type, ".e_step");
542038fd1498Szrj 
542138fd1498Szrj 	  /* Mark these as element loops.  */
542238fd1498Szrj 	  tree t, e_gwv = integer_minus_one_node;
542338fd1498Szrj 	  tree chunk = build_int_cst (diff_type, 0); /* Never chunked.  */
542438fd1498Szrj 
542538fd1498Szrj 	  t = build_int_cst (integer_type_node, IFN_GOACC_LOOP_OFFSET);
542638fd1498Szrj 	  call = gimple_build_call_internal (IFN_GOACC_LOOP, 7, t, dir, e_range,
542738fd1498Szrj 					     element_s, chunk, e_gwv, chunk);
542838fd1498Szrj 	  gimple_call_set_lhs (call, e_offset);
542938fd1498Szrj 	  gimple_set_location (call, loc);
543038fd1498Szrj 	  gsi_insert_before (&gsi, call, GSI_SAME_STMT);
543138fd1498Szrj 
543238fd1498Szrj 	  t = build_int_cst (integer_type_node, IFN_GOACC_LOOP_BOUND);
543338fd1498Szrj 	  call = gimple_build_call_internal (IFN_GOACC_LOOP, 7, t, dir, e_range,
543438fd1498Szrj 					     element_s, chunk, e_gwv, e_offset);
543538fd1498Szrj 	  gimple_call_set_lhs (call, e_bound);
543638fd1498Szrj 	  gimple_set_location (call, loc);
543738fd1498Szrj 	  gsi_insert_before (&gsi, call, GSI_SAME_STMT);
543838fd1498Szrj 
543938fd1498Szrj 	  t = build_int_cst (integer_type_node, IFN_GOACC_LOOP_STEP);
544038fd1498Szrj 	  call = gimple_build_call_internal (IFN_GOACC_LOOP, 6, t, dir, e_range,
544138fd1498Szrj 					     element_s, chunk, e_gwv);
544238fd1498Szrj 	  gimple_call_set_lhs (call, e_step);
544338fd1498Szrj 	  gimple_set_location (call, loc);
544438fd1498Szrj 	  gsi_insert_before (&gsi, call, GSI_SAME_STMT);
544538fd1498Szrj 
544638fd1498Szrj 	  /* Add test and split block.  */
544738fd1498Szrj 	  expr = build2 (cond_code, boolean_type_node, e_offset, e_bound);
544838fd1498Szrj 	  stmt = gimple_build_cond_empty (expr);
544938fd1498Szrj 	  gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
545038fd1498Szrj 	  split = split_block (body_bb, stmt);
545138fd1498Szrj 	  elem_body_bb = split->dest;
545238fd1498Szrj 	  if (cont_bb == body_bb)
545338fd1498Szrj 	    cont_bb = elem_body_bb;
545438fd1498Szrj 	  body_bb = split->src;
545538fd1498Szrj 
545638fd1498Szrj 	  split->flags ^= EDGE_FALLTHRU | EDGE_TRUE_VALUE;
545738fd1498Szrj 
545838fd1498Szrj 	  /* Add a dummy exit for the tiled block when cont_bb is missing.  */
545938fd1498Szrj 	  if (cont_bb == NULL)
546038fd1498Szrj 	    {
546138fd1498Szrj 	      edge e = make_edge (body_bb, exit_bb, EDGE_FALSE_VALUE);
546238fd1498Szrj 	      e->probability = profile_probability::even ();
546338fd1498Szrj 	      split->probability = profile_probability::even ();
546438fd1498Szrj 	    }
546538fd1498Szrj 
546638fd1498Szrj 	  /* Initialize the user's loop vars.  */
546738fd1498Szrj 	  gsi = gsi_start_bb (elem_body_bb);
546838fd1498Szrj 	  expand_oacc_collapse_vars (fd, true, &gsi, counts, e_offset);
546938fd1498Szrj 	}
547038fd1498Szrj     }
547138fd1498Szrj 
547238fd1498Szrj   /* Loop increment goes into cont_bb.  If this is not a loop, we
547338fd1498Szrj      will have spawned threads as if it was, and each one will
547438fd1498Szrj      execute one iteration.  The specification is not explicit about
547538fd1498Szrj      whether such constructs are ill-formed or not, and they can
547638fd1498Szrj      occur, especially when noreturn routines are involved.  */
547738fd1498Szrj   if (cont_bb)
547838fd1498Szrj     {
547938fd1498Szrj       gsi = gsi_last_nondebug_bb (cont_bb);
548038fd1498Szrj       gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
548138fd1498Szrj       loc = gimple_location (cont_stmt);
548238fd1498Szrj 
548338fd1498Szrj       if (fd->tiling)
548438fd1498Szrj 	{
548538fd1498Szrj 	  /* Insert element loop increment and test.  */
548638fd1498Szrj 	  expr = build2 (PLUS_EXPR, diff_type, e_offset, e_step);
548738fd1498Szrj 	  expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
548838fd1498Szrj 					   true, GSI_SAME_STMT);
548938fd1498Szrj 	  ass = gimple_build_assign (e_offset, expr);
549038fd1498Szrj 	  gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
549138fd1498Szrj 	  expr = build2 (cond_code, boolean_type_node, e_offset, e_bound);
549238fd1498Szrj 
549338fd1498Szrj 	  stmt = gimple_build_cond_empty (expr);
549438fd1498Szrj 	  gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
549538fd1498Szrj 	  split = split_block (cont_bb, stmt);
549638fd1498Szrj 	  elem_cont_bb = split->src;
549738fd1498Szrj 	  cont_bb = split->dest;
549838fd1498Szrj 
549938fd1498Szrj 	  split->flags ^= EDGE_FALLTHRU | EDGE_FALSE_VALUE;
550038fd1498Szrj 	  split->probability = profile_probability::unlikely ().guessed ();
550138fd1498Szrj 	  edge latch_edge
550238fd1498Szrj 	    = make_edge (elem_cont_bb, elem_body_bb, EDGE_TRUE_VALUE);
550338fd1498Szrj 	  latch_edge->probability = profile_probability::likely ().guessed ();
550438fd1498Szrj 
550538fd1498Szrj 	  edge skip_edge = make_edge (body_bb, cont_bb, EDGE_FALSE_VALUE);
550638fd1498Szrj 	  skip_edge->probability = profile_probability::unlikely ().guessed ();
550738fd1498Szrj 	  edge loop_entry_edge = EDGE_SUCC (body_bb, 1 - skip_edge->dest_idx);
550838fd1498Szrj 	  loop_entry_edge->probability
550938fd1498Szrj 	    = profile_probability::likely ().guessed ();
551038fd1498Szrj 
551138fd1498Szrj 	  gsi = gsi_for_stmt (cont_stmt);
551238fd1498Szrj 	}
551338fd1498Szrj 
551438fd1498Szrj       /* Increment offset.  */
551538fd1498Szrj       if (gimple_in_ssa_p (cfun))
551638fd1498Szrj 	expr = build2 (plus_code, iter_type, offset,
551738fd1498Szrj 		       fold_convert (plus_type, step));
551838fd1498Szrj       else
551938fd1498Szrj 	expr = build2 (PLUS_EXPR, diff_type, offset, step);
552038fd1498Szrj       expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
552138fd1498Szrj 				       true, GSI_SAME_STMT);
552238fd1498Szrj       ass = gimple_build_assign (offset_incr, expr);
552338fd1498Szrj       gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
552438fd1498Szrj       expr = build2 (cond_code, boolean_type_node, offset_incr, bound);
552538fd1498Szrj       gsi_insert_before (&gsi, gimple_build_cond_empty (expr), GSI_SAME_STMT);
552638fd1498Szrj 
552738fd1498Szrj       /*  Remove the GIMPLE_OMP_CONTINUE.  */
552838fd1498Szrj       gsi_remove (&gsi, true);
552938fd1498Szrj 
553038fd1498Szrj       /* Fixup edges from cont_bb.  */
553138fd1498Szrj       be = BRANCH_EDGE (cont_bb);
553238fd1498Szrj       fte = FALLTHRU_EDGE (cont_bb);
553338fd1498Szrj       be->flags |= EDGE_TRUE_VALUE;
553438fd1498Szrj       fte->flags ^= EDGE_FALLTHRU | EDGE_FALSE_VALUE;
553538fd1498Szrj 
553638fd1498Szrj       if (chunking)
553738fd1498Szrj 	{
553838fd1498Szrj 	  /* Split the beginning of exit_bb to make bottom_bb.  We
553938fd1498Szrj 	     need to insert a nop at the start, because splitting is
554038fd1498Szrj 	     after a stmt, not before.  */
554138fd1498Szrj 	  gsi = gsi_start_bb (exit_bb);
554238fd1498Szrj 	  stmt = gimple_build_nop ();
554338fd1498Szrj 	  gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
554438fd1498Szrj 	  split = split_block (exit_bb, stmt);
554538fd1498Szrj 	  bottom_bb = split->src;
554638fd1498Szrj 	  exit_bb = split->dest;
554738fd1498Szrj 	  gsi = gsi_last_bb (bottom_bb);
554838fd1498Szrj 
554938fd1498Szrj 	  /* Chunk increment and test goes into bottom_bb.  */
555038fd1498Szrj 	  expr = build2 (PLUS_EXPR, diff_type, chunk_no,
555138fd1498Szrj 			 build_int_cst (diff_type, 1));
555238fd1498Szrj 	  ass = gimple_build_assign (chunk_no, expr);
555338fd1498Szrj 	  gsi_insert_after (&gsi, ass, GSI_CONTINUE_LINKING);
555438fd1498Szrj 
555538fd1498Szrj 	  /* Chunk test at end of bottom_bb.  */
555638fd1498Szrj 	  expr = build2 (LT_EXPR, boolean_type_node, chunk_no, chunk_max);
555738fd1498Szrj 	  gsi_insert_after (&gsi, gimple_build_cond_empty (expr),
555838fd1498Szrj 			    GSI_CONTINUE_LINKING);
555938fd1498Szrj 
556038fd1498Szrj 	  /* Fixup edges from bottom_bb.  */
556138fd1498Szrj 	  split->flags ^= EDGE_FALLTHRU | EDGE_FALSE_VALUE;
556238fd1498Szrj 	  split->probability = profile_probability::unlikely ().guessed ();
556338fd1498Szrj 	  edge latch_edge = make_edge (bottom_bb, head_bb, EDGE_TRUE_VALUE);
556438fd1498Szrj 	  latch_edge->probability = profile_probability::likely ().guessed ();
556538fd1498Szrj 	}
556638fd1498Szrj     }
556738fd1498Szrj 
556838fd1498Szrj   gsi = gsi_last_nondebug_bb (exit_bb);
556938fd1498Szrj   gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
557038fd1498Szrj   loc = gimple_location (gsi_stmt (gsi));
557138fd1498Szrj 
557238fd1498Szrj   if (!gimple_in_ssa_p (cfun))
557338fd1498Szrj     {
557438fd1498Szrj       /* Insert the final value of V, in case it is live.  This is the
557538fd1498Szrj 	 value for the only thread that survives past the join.  */
557638fd1498Szrj       expr = fold_build2 (MINUS_EXPR, diff_type, range, dir);
557738fd1498Szrj       expr = fold_build2 (PLUS_EXPR, diff_type, expr, s);
557838fd1498Szrj       expr = fold_build2 (TRUNC_DIV_EXPR, diff_type, expr, s);
557938fd1498Szrj       expr = fold_build2 (MULT_EXPR, diff_type, expr, s);
558038fd1498Szrj       expr = build2 (plus_code, iter_type, b, fold_convert (plus_type, expr));
558138fd1498Szrj       expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
558238fd1498Szrj 				       true, GSI_SAME_STMT);
558338fd1498Szrj       ass = gimple_build_assign (v, expr);
558438fd1498Szrj       gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
558538fd1498Szrj     }
558638fd1498Szrj 
558738fd1498Szrj   /* Remove the OMP_RETURN.  */
558838fd1498Szrj   gsi_remove (&gsi, true);
558938fd1498Szrj 
559038fd1498Szrj   if (cont_bb)
559138fd1498Szrj     {
559238fd1498Szrj       /* We now have one, two or three nested loops.  Update the loop
559338fd1498Szrj 	 structures.  */
559438fd1498Szrj       struct loop *parent = entry_bb->loop_father;
559538fd1498Szrj       struct loop *body = body_bb->loop_father;
559638fd1498Szrj 
559738fd1498Szrj       if (chunking)
559838fd1498Szrj 	{
559938fd1498Szrj 	  struct loop *chunk_loop = alloc_loop ();
560038fd1498Szrj 	  chunk_loop->header = head_bb;
560138fd1498Szrj 	  chunk_loop->latch = bottom_bb;
560238fd1498Szrj 	  add_loop (chunk_loop, parent);
560338fd1498Szrj 	  parent = chunk_loop;
560438fd1498Szrj 	}
560538fd1498Szrj       else if (parent != body)
560638fd1498Szrj 	{
560738fd1498Szrj 	  gcc_assert (body->header == body_bb);
560838fd1498Szrj 	  gcc_assert (body->latch == cont_bb
560938fd1498Szrj 		      || single_pred (body->latch) == cont_bb);
561038fd1498Szrj 	  parent = NULL;
561138fd1498Szrj 	}
561238fd1498Szrj 
561338fd1498Szrj       if (parent)
561438fd1498Szrj 	{
561538fd1498Szrj 	  struct loop *body_loop = alloc_loop ();
561638fd1498Szrj 	  body_loop->header = body_bb;
561738fd1498Szrj 	  body_loop->latch = cont_bb;
561838fd1498Szrj 	  add_loop (body_loop, parent);
561938fd1498Szrj 
562038fd1498Szrj 	  if (fd->tiling)
562138fd1498Szrj 	    {
562238fd1498Szrj 	      /* Insert tiling's element loop.  */
562338fd1498Szrj 	      struct loop *inner_loop = alloc_loop ();
562438fd1498Szrj 	      inner_loop->header = elem_body_bb;
562538fd1498Szrj 	      inner_loop->latch = elem_cont_bb;
562638fd1498Szrj 	      add_loop (inner_loop, body_loop);
562738fd1498Szrj 	    }
562838fd1498Szrj 	}
562938fd1498Szrj     }
563038fd1498Szrj }
563138fd1498Szrj 
563238fd1498Szrj /* Expand the OMP loop defined by REGION.  */
563338fd1498Szrj 
563438fd1498Szrj static void
expand_omp_for(struct omp_region * region,gimple * inner_stmt)563538fd1498Szrj expand_omp_for (struct omp_region *region, gimple *inner_stmt)
563638fd1498Szrj {
563738fd1498Szrj   struct omp_for_data fd;
563838fd1498Szrj   struct omp_for_data_loop *loops;
563938fd1498Szrj 
564038fd1498Szrj   loops
564138fd1498Szrj     = (struct omp_for_data_loop *)
564238fd1498Szrj       alloca (gimple_omp_for_collapse (last_stmt (region->entry))
564338fd1498Szrj 	      * sizeof (struct omp_for_data_loop));
564438fd1498Szrj   omp_extract_for_data (as_a <gomp_for *> (last_stmt (region->entry)),
564538fd1498Szrj 			&fd, loops);
564638fd1498Szrj   region->sched_kind = fd.sched_kind;
564738fd1498Szrj   region->sched_modifiers = fd.sched_modifiers;
564838fd1498Szrj 
564938fd1498Szrj   gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
565038fd1498Szrj   BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
565138fd1498Szrj   FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
565238fd1498Szrj   if (region->cont)
565338fd1498Szrj     {
565438fd1498Szrj       gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
565538fd1498Szrj       BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
565638fd1498Szrj       FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
565738fd1498Szrj     }
565838fd1498Szrj   else
565938fd1498Szrj     /* If there isn't a continue then this is a degerate case where
566038fd1498Szrj        the introduction of abnormal edges during lowering will prevent
566138fd1498Szrj        original loops from being detected.  Fix that up.  */
566238fd1498Szrj     loops_state_set (LOOPS_NEED_FIXUP);
566338fd1498Szrj 
566438fd1498Szrj   if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_SIMD)
566538fd1498Szrj     expand_omp_simd (region, &fd);
566638fd1498Szrj   else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
566738fd1498Szrj     {
566838fd1498Szrj       gcc_assert (!inner_stmt);
566938fd1498Szrj       expand_oacc_for (region, &fd);
567038fd1498Szrj     }
567138fd1498Szrj   else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_TASKLOOP)
567238fd1498Szrj     {
567338fd1498Szrj       if (gimple_omp_for_combined_into_p (fd.for_stmt))
567438fd1498Szrj 	expand_omp_taskloop_for_inner (region, &fd, inner_stmt);
567538fd1498Szrj       else
567638fd1498Szrj 	expand_omp_taskloop_for_outer (region, &fd, inner_stmt);
567738fd1498Szrj     }
567838fd1498Szrj   else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
567938fd1498Szrj 	   && !fd.have_ordered)
568038fd1498Szrj     {
568138fd1498Szrj       if (fd.chunk_size == NULL)
568238fd1498Szrj 	expand_omp_for_static_nochunk (region, &fd, inner_stmt);
568338fd1498Szrj       else
568438fd1498Szrj 	expand_omp_for_static_chunk (region, &fd, inner_stmt);
568538fd1498Szrj     }
568638fd1498Szrj   else
568738fd1498Szrj     {
568838fd1498Szrj       int fn_index, start_ix, next_ix;
568938fd1498Szrj 
569038fd1498Szrj       gcc_assert (gimple_omp_for_kind (fd.for_stmt)
569138fd1498Szrj 		  == GF_OMP_FOR_KIND_FOR);
569238fd1498Szrj       if (fd.chunk_size == NULL
569338fd1498Szrj 	  && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
569438fd1498Szrj 	fd.chunk_size = integer_zero_node;
569538fd1498Szrj       gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
569638fd1498Szrj       switch (fd.sched_kind)
569738fd1498Szrj 	{
569838fd1498Szrj 	case OMP_CLAUSE_SCHEDULE_RUNTIME:
569938fd1498Szrj 	  fn_index = 3;
570038fd1498Szrj 	  break;
570138fd1498Szrj 	case OMP_CLAUSE_SCHEDULE_DYNAMIC:
570238fd1498Szrj 	case OMP_CLAUSE_SCHEDULE_GUIDED:
570338fd1498Szrj 	  if ((fd.sched_modifiers & OMP_CLAUSE_SCHEDULE_NONMONOTONIC)
570438fd1498Szrj 	      && !fd.ordered
570538fd1498Szrj 	      && !fd.have_ordered)
570638fd1498Szrj 	    {
570738fd1498Szrj 	      fn_index = 3 + fd.sched_kind;
570838fd1498Szrj 	      break;
570938fd1498Szrj 	    }
571038fd1498Szrj 	  /* FALLTHRU */
571138fd1498Szrj 	default:
571238fd1498Szrj 	  fn_index = fd.sched_kind;
571338fd1498Szrj 	  break;
571438fd1498Szrj 	}
571538fd1498Szrj       if (!fd.ordered)
571638fd1498Szrj 	fn_index += fd.have_ordered * 6;
571738fd1498Szrj       if (fd.ordered)
571838fd1498Szrj 	start_ix = ((int)BUILT_IN_GOMP_LOOP_DOACROSS_STATIC_START) + fn_index;
571938fd1498Szrj       else
572038fd1498Szrj 	start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
572138fd1498Szrj       next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
572238fd1498Szrj       if (fd.iter_type == long_long_unsigned_type_node)
572338fd1498Szrj 	{
572438fd1498Szrj 	  start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
572538fd1498Szrj 			- (int)BUILT_IN_GOMP_LOOP_STATIC_START);
572638fd1498Szrj 	  next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
572738fd1498Szrj 		      - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
572838fd1498Szrj 	}
572938fd1498Szrj       expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
573038fd1498Szrj 			      (enum built_in_function) next_ix, inner_stmt);
573138fd1498Szrj     }
573238fd1498Szrj 
573338fd1498Szrj   if (gimple_in_ssa_p (cfun))
573438fd1498Szrj     update_ssa (TODO_update_ssa_only_virtuals);
573538fd1498Szrj }
573638fd1498Szrj 
573738fd1498Szrj /* Expand code for an OpenMP sections directive.  In pseudo code, we generate
573838fd1498Szrj 
573938fd1498Szrj 	v = GOMP_sections_start (n);
574038fd1498Szrj     L0:
574138fd1498Szrj 	switch (v)
574238fd1498Szrj 	  {
574338fd1498Szrj 	  case 0:
574438fd1498Szrj 	    goto L2;
574538fd1498Szrj 	  case 1:
574638fd1498Szrj 	    section 1;
574738fd1498Szrj 	    goto L1;
574838fd1498Szrj 	  case 2:
574938fd1498Szrj 	    ...
575038fd1498Szrj 	  case n:
575138fd1498Szrj 	    ...
575238fd1498Szrj 	  default:
575338fd1498Szrj 	    abort ();
575438fd1498Szrj 	  }
575538fd1498Szrj     L1:
575638fd1498Szrj 	v = GOMP_sections_next ();
575738fd1498Szrj 	goto L0;
575838fd1498Szrj     L2:
575938fd1498Szrj 	reduction;
576038fd1498Szrj 
576138fd1498Szrj     If this is a combined parallel sections, replace the call to
576238fd1498Szrj     GOMP_sections_start with call to GOMP_sections_next.  */
576338fd1498Szrj 
576438fd1498Szrj static void
expand_omp_sections(struct omp_region * region)576538fd1498Szrj expand_omp_sections (struct omp_region *region)
576638fd1498Szrj {
576738fd1498Szrj   tree t, u, vin = NULL, vmain, vnext, l2;
576838fd1498Szrj   unsigned len;
576938fd1498Szrj   basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
577038fd1498Szrj   gimple_stmt_iterator si, switch_si;
577138fd1498Szrj   gomp_sections *sections_stmt;
577238fd1498Szrj   gimple *stmt;
577338fd1498Szrj   gomp_continue *cont;
577438fd1498Szrj   edge_iterator ei;
577538fd1498Szrj   edge e;
577638fd1498Szrj   struct omp_region *inner;
577738fd1498Szrj   unsigned i, casei;
577838fd1498Szrj   bool exit_reachable = region->cont != NULL;
577938fd1498Szrj 
578038fd1498Szrj   gcc_assert (region->exit != NULL);
578138fd1498Szrj   entry_bb = region->entry;
578238fd1498Szrj   l0_bb = single_succ (entry_bb);
578338fd1498Szrj   l1_bb = region->cont;
578438fd1498Szrj   l2_bb = region->exit;
578538fd1498Szrj   if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
578638fd1498Szrj     l2 = gimple_block_label (l2_bb);
578738fd1498Szrj   else
578838fd1498Szrj     {
578938fd1498Szrj       /* This can happen if there are reductions.  */
579038fd1498Szrj       len = EDGE_COUNT (l0_bb->succs);
579138fd1498Szrj       gcc_assert (len > 0);
579238fd1498Szrj       e = EDGE_SUCC (l0_bb, len - 1);
579338fd1498Szrj       si = gsi_last_nondebug_bb (e->dest);
579438fd1498Szrj       l2 = NULL_TREE;
579538fd1498Szrj       if (gsi_end_p (si)
579638fd1498Szrj 	  || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
579738fd1498Szrj 	l2 = gimple_block_label (e->dest);
579838fd1498Szrj       else
579938fd1498Szrj 	FOR_EACH_EDGE (e, ei, l0_bb->succs)
580038fd1498Szrj 	  {
580138fd1498Szrj 	    si = gsi_last_nondebug_bb (e->dest);
580238fd1498Szrj 	    if (gsi_end_p (si)
580338fd1498Szrj 		|| gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
580438fd1498Szrj 	      {
580538fd1498Szrj 		l2 = gimple_block_label (e->dest);
580638fd1498Szrj 		break;
580738fd1498Szrj 	      }
580838fd1498Szrj 	  }
580938fd1498Szrj     }
581038fd1498Szrj   if (exit_reachable)
581138fd1498Szrj     default_bb = create_empty_bb (l1_bb->prev_bb);
581238fd1498Szrj   else
581338fd1498Szrj     default_bb = create_empty_bb (l0_bb);
581438fd1498Szrj 
581538fd1498Szrj   /* We will build a switch() with enough cases for all the
581638fd1498Szrj      GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
581738fd1498Szrj      and a default case to abort if something goes wrong.  */
581838fd1498Szrj   len = EDGE_COUNT (l0_bb->succs);
581938fd1498Szrj 
582038fd1498Szrj   /* Use vec::quick_push on label_vec throughout, since we know the size
582138fd1498Szrj      in advance.  */
582238fd1498Szrj   auto_vec<tree> label_vec (len);
582338fd1498Szrj 
582438fd1498Szrj   /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
582538fd1498Szrj      GIMPLE_OMP_SECTIONS statement.  */
582638fd1498Szrj   si = gsi_last_nondebug_bb (entry_bb);
582738fd1498Szrj   sections_stmt = as_a <gomp_sections *> (gsi_stmt (si));
582838fd1498Szrj   gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
582938fd1498Szrj   vin = gimple_omp_sections_control (sections_stmt);
583038fd1498Szrj   if (!is_combined_parallel (region))
583138fd1498Szrj     {
583238fd1498Szrj       /* If we are not inside a combined parallel+sections region,
583338fd1498Szrj 	 call GOMP_sections_start.  */
583438fd1498Szrj       t = build_int_cst (unsigned_type_node, len - 1);
583538fd1498Szrj       u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
583638fd1498Szrj       stmt = gimple_build_call (u, 1, t);
583738fd1498Szrj     }
583838fd1498Szrj   else
583938fd1498Szrj     {
584038fd1498Szrj       /* Otherwise, call GOMP_sections_next.  */
584138fd1498Szrj       u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
584238fd1498Szrj       stmt = gimple_build_call (u, 0);
584338fd1498Szrj     }
584438fd1498Szrj   gimple_call_set_lhs (stmt, vin);
584538fd1498Szrj   gsi_insert_after (&si, stmt, GSI_SAME_STMT);
584638fd1498Szrj   gsi_remove (&si, true);
584738fd1498Szrj 
584838fd1498Szrj   /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
584938fd1498Szrj      L0_BB.  */
585038fd1498Szrj   switch_si = gsi_last_nondebug_bb (l0_bb);
585138fd1498Szrj   gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
585238fd1498Szrj   if (exit_reachable)
585338fd1498Szrj     {
585438fd1498Szrj       cont = as_a <gomp_continue *> (last_stmt (l1_bb));
585538fd1498Szrj       gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
585638fd1498Szrj       vmain = gimple_omp_continue_control_use (cont);
585738fd1498Szrj       vnext = gimple_omp_continue_control_def (cont);
585838fd1498Szrj     }
585938fd1498Szrj   else
586038fd1498Szrj     {
586138fd1498Szrj       vmain = vin;
586238fd1498Szrj       vnext = NULL_TREE;
586338fd1498Szrj     }
586438fd1498Szrj 
586538fd1498Szrj   t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
586638fd1498Szrj   label_vec.quick_push (t);
586738fd1498Szrj   i = 1;
586838fd1498Szrj 
586938fd1498Szrj   /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR.  */
587038fd1498Szrj   for (inner = region->inner, casei = 1;
587138fd1498Szrj        inner;
587238fd1498Szrj        inner = inner->next, i++, casei++)
587338fd1498Szrj     {
587438fd1498Szrj       basic_block s_entry_bb, s_exit_bb;
587538fd1498Szrj 
587638fd1498Szrj       /* Skip optional reduction region.  */
587738fd1498Szrj       if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
587838fd1498Szrj 	{
587938fd1498Szrj 	  --i;
588038fd1498Szrj 	  --casei;
588138fd1498Szrj 	  continue;
588238fd1498Szrj 	}
588338fd1498Szrj 
588438fd1498Szrj       s_entry_bb = inner->entry;
588538fd1498Szrj       s_exit_bb = inner->exit;
588638fd1498Szrj 
588738fd1498Szrj       t = gimple_block_label (s_entry_bb);
588838fd1498Szrj       u = build_int_cst (unsigned_type_node, casei);
588938fd1498Szrj       u = build_case_label (u, NULL, t);
589038fd1498Szrj       label_vec.quick_push (u);
589138fd1498Szrj 
589238fd1498Szrj       si = gsi_last_nondebug_bb (s_entry_bb);
589338fd1498Szrj       gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
589438fd1498Szrj       gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
589538fd1498Szrj       gsi_remove (&si, true);
589638fd1498Szrj       single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
589738fd1498Szrj 
589838fd1498Szrj       if (s_exit_bb == NULL)
589938fd1498Szrj 	continue;
590038fd1498Szrj 
590138fd1498Szrj       si = gsi_last_nondebug_bb (s_exit_bb);
590238fd1498Szrj       gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
590338fd1498Szrj       gsi_remove (&si, true);
590438fd1498Szrj 
590538fd1498Szrj       single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
590638fd1498Szrj     }
590738fd1498Szrj 
590838fd1498Szrj   /* Error handling code goes in DEFAULT_BB.  */
590938fd1498Szrj   t = gimple_block_label (default_bb);
591038fd1498Szrj   u = build_case_label (NULL, NULL, t);
591138fd1498Szrj   make_edge (l0_bb, default_bb, 0);
591238fd1498Szrj   add_bb_to_loop (default_bb, current_loops->tree_root);
591338fd1498Szrj 
591438fd1498Szrj   stmt = gimple_build_switch (vmain, u, label_vec);
591538fd1498Szrj   gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
591638fd1498Szrj   gsi_remove (&switch_si, true);
591738fd1498Szrj 
591838fd1498Szrj   si = gsi_start_bb (default_bb);
591938fd1498Szrj   stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
592038fd1498Szrj   gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
592138fd1498Szrj 
592238fd1498Szrj   if (exit_reachable)
592338fd1498Szrj     {
592438fd1498Szrj       tree bfn_decl;
592538fd1498Szrj 
592638fd1498Szrj       /* Code to get the next section goes in L1_BB.  */
592738fd1498Szrj       si = gsi_last_nondebug_bb (l1_bb);
592838fd1498Szrj       gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
592938fd1498Szrj 
593038fd1498Szrj       bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
593138fd1498Szrj       stmt = gimple_build_call (bfn_decl, 0);
593238fd1498Szrj       gimple_call_set_lhs (stmt, vnext);
593338fd1498Szrj       gsi_insert_after (&si, stmt, GSI_SAME_STMT);
593438fd1498Szrj       gsi_remove (&si, true);
593538fd1498Szrj 
593638fd1498Szrj       single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
593738fd1498Szrj     }
593838fd1498Szrj 
593938fd1498Szrj   /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB.  */
594038fd1498Szrj   si = gsi_last_nondebug_bb (l2_bb);
594138fd1498Szrj   if (gimple_omp_return_nowait_p (gsi_stmt (si)))
594238fd1498Szrj     t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
594338fd1498Szrj   else if (gimple_omp_return_lhs (gsi_stmt (si)))
594438fd1498Szrj     t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
594538fd1498Szrj   else
594638fd1498Szrj     t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
594738fd1498Szrj   stmt = gimple_build_call (t, 0);
594838fd1498Szrj   if (gimple_omp_return_lhs (gsi_stmt (si)))
594938fd1498Szrj     gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
595038fd1498Szrj   gsi_insert_after (&si, stmt, GSI_SAME_STMT);
595138fd1498Szrj   gsi_remove (&si, true);
595238fd1498Szrj 
595338fd1498Szrj   set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
595438fd1498Szrj }
595538fd1498Szrj 
595638fd1498Szrj /* Expand code for an OpenMP single directive.  We've already expanded
595738fd1498Szrj    much of the code, here we simply place the GOMP_barrier call.  */
595838fd1498Szrj 
595938fd1498Szrj static void
expand_omp_single(struct omp_region * region)596038fd1498Szrj expand_omp_single (struct omp_region *region)
596138fd1498Szrj {
596238fd1498Szrj   basic_block entry_bb, exit_bb;
596338fd1498Szrj   gimple_stmt_iterator si;
596438fd1498Szrj 
596538fd1498Szrj   entry_bb = region->entry;
596638fd1498Szrj   exit_bb = region->exit;
596738fd1498Szrj 
596838fd1498Szrj   si = gsi_last_nondebug_bb (entry_bb);
596938fd1498Szrj   gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
597038fd1498Szrj   gsi_remove (&si, true);
597138fd1498Szrj   single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
597238fd1498Szrj 
597338fd1498Szrj   si = gsi_last_nondebug_bb (exit_bb);
597438fd1498Szrj   if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
597538fd1498Szrj     {
597638fd1498Szrj       tree t = gimple_omp_return_lhs (gsi_stmt (si));
597738fd1498Szrj       gsi_insert_after (&si, omp_build_barrier (t), GSI_SAME_STMT);
597838fd1498Szrj     }
597938fd1498Szrj   gsi_remove (&si, true);
598038fd1498Szrj   single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
598138fd1498Szrj }
598238fd1498Szrj 
598338fd1498Szrj /* Generic expansion for OpenMP synchronization directives: master,
598438fd1498Szrj    ordered and critical.  All we need to do here is remove the entry
598538fd1498Szrj    and exit markers for REGION.  */
598638fd1498Szrj 
598738fd1498Szrj static void
expand_omp_synch(struct omp_region * region)598838fd1498Szrj expand_omp_synch (struct omp_region *region)
598938fd1498Szrj {
599038fd1498Szrj   basic_block entry_bb, exit_bb;
599138fd1498Szrj   gimple_stmt_iterator si;
599238fd1498Szrj 
599338fd1498Szrj   entry_bb = region->entry;
599438fd1498Szrj   exit_bb = region->exit;
599538fd1498Szrj 
599638fd1498Szrj   si = gsi_last_nondebug_bb (entry_bb);
599738fd1498Szrj   gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
599838fd1498Szrj 	      || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
599938fd1498Szrj 	      || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
600038fd1498Szrj 	      || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
600138fd1498Szrj 	      || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
600238fd1498Szrj 	      || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
600338fd1498Szrj   gsi_remove (&si, true);
600438fd1498Szrj   single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
600538fd1498Szrj 
600638fd1498Szrj   if (exit_bb)
600738fd1498Szrj     {
600838fd1498Szrj       si = gsi_last_nondebug_bb (exit_bb);
600938fd1498Szrj       gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
601038fd1498Szrj       gsi_remove (&si, true);
601138fd1498Szrj       single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
601238fd1498Szrj     }
601338fd1498Szrj }
601438fd1498Szrj 
601538fd1498Szrj /* A subroutine of expand_omp_atomic.  Attempt to implement the atomic
601638fd1498Szrj    operation as a normal volatile load.  */
601738fd1498Szrj 
601838fd1498Szrj static bool
expand_omp_atomic_load(basic_block load_bb,tree addr,tree loaded_val,int index)601938fd1498Szrj expand_omp_atomic_load (basic_block load_bb, tree addr,
602038fd1498Szrj 			tree loaded_val, int index)
602138fd1498Szrj {
602238fd1498Szrj   enum built_in_function tmpbase;
602338fd1498Szrj   gimple_stmt_iterator gsi;
602438fd1498Szrj   basic_block store_bb;
602538fd1498Szrj   location_t loc;
602638fd1498Szrj   gimple *stmt;
602738fd1498Szrj   tree decl, call, type, itype;
602838fd1498Szrj 
602938fd1498Szrj   gsi = gsi_last_nondebug_bb (load_bb);
603038fd1498Szrj   stmt = gsi_stmt (gsi);
603138fd1498Szrj   gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
603238fd1498Szrj   loc = gimple_location (stmt);
603338fd1498Szrj 
603438fd1498Szrj   /* ??? If the target does not implement atomic_load_optab[mode], and mode
603538fd1498Szrj      is smaller than word size, then expand_atomic_load assumes that the load
603638fd1498Szrj      is atomic.  We could avoid the builtin entirely in this case.  */
603738fd1498Szrj 
603838fd1498Szrj   tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
603938fd1498Szrj   decl = builtin_decl_explicit (tmpbase);
604038fd1498Szrj   if (decl == NULL_TREE)
604138fd1498Szrj     return false;
604238fd1498Szrj 
604338fd1498Szrj   type = TREE_TYPE (loaded_val);
604438fd1498Szrj   itype = TREE_TYPE (TREE_TYPE (decl));
604538fd1498Szrj 
604638fd1498Szrj   call = build_call_expr_loc (loc, decl, 2, addr,
604738fd1498Szrj 			      build_int_cst (NULL,
604838fd1498Szrj 					     gimple_omp_atomic_seq_cst_p (stmt)
604938fd1498Szrj 					     ? MEMMODEL_SEQ_CST
605038fd1498Szrj 					     : MEMMODEL_RELAXED));
605138fd1498Szrj   if (!useless_type_conversion_p (type, itype))
605238fd1498Szrj     call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
605338fd1498Szrj   call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
605438fd1498Szrj 
605538fd1498Szrj   force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
605638fd1498Szrj   gsi_remove (&gsi, true);
605738fd1498Szrj 
605838fd1498Szrj   store_bb = single_succ (load_bb);
605938fd1498Szrj   gsi = gsi_last_nondebug_bb (store_bb);
606038fd1498Szrj   gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
606138fd1498Szrj   gsi_remove (&gsi, true);
606238fd1498Szrj 
606338fd1498Szrj   if (gimple_in_ssa_p (cfun))
606438fd1498Szrj     update_ssa (TODO_update_ssa_no_phi);
606538fd1498Szrj 
606638fd1498Szrj   return true;
606738fd1498Szrj }
606838fd1498Szrj 
606938fd1498Szrj /* A subroutine of expand_omp_atomic.  Attempt to implement the atomic
607038fd1498Szrj    operation as a normal volatile store.  */
607138fd1498Szrj 
607238fd1498Szrj static bool
expand_omp_atomic_store(basic_block load_bb,tree addr,tree loaded_val,tree stored_val,int index)607338fd1498Szrj expand_omp_atomic_store (basic_block load_bb, tree addr,
607438fd1498Szrj 			 tree loaded_val, tree stored_val, int index)
607538fd1498Szrj {
607638fd1498Szrj   enum built_in_function tmpbase;
607738fd1498Szrj   gimple_stmt_iterator gsi;
607838fd1498Szrj   basic_block store_bb = single_succ (load_bb);
607938fd1498Szrj   location_t loc;
608038fd1498Szrj   gimple *stmt;
608138fd1498Szrj   tree decl, call, type, itype;
608238fd1498Szrj   machine_mode imode;
608338fd1498Szrj   bool exchange;
608438fd1498Szrj 
608538fd1498Szrj   gsi = gsi_last_nondebug_bb (load_bb);
608638fd1498Szrj   stmt = gsi_stmt (gsi);
608738fd1498Szrj   gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
608838fd1498Szrj 
608938fd1498Szrj   /* If the load value is needed, then this isn't a store but an exchange.  */
609038fd1498Szrj   exchange = gimple_omp_atomic_need_value_p (stmt);
609138fd1498Szrj 
609238fd1498Szrj   gsi = gsi_last_nondebug_bb (store_bb);
609338fd1498Szrj   stmt = gsi_stmt (gsi);
609438fd1498Szrj   gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
609538fd1498Szrj   loc = gimple_location (stmt);
609638fd1498Szrj 
609738fd1498Szrj   /* ??? If the target does not implement atomic_store_optab[mode], and mode
609838fd1498Szrj      is smaller than word size, then expand_atomic_store assumes that the store
609938fd1498Szrj      is atomic.  We could avoid the builtin entirely in this case.  */
610038fd1498Szrj 
610138fd1498Szrj   tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
610238fd1498Szrj   tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
610338fd1498Szrj   decl = builtin_decl_explicit (tmpbase);
610438fd1498Szrj   if (decl == NULL_TREE)
610538fd1498Szrj     return false;
610638fd1498Szrj 
610738fd1498Szrj   type = TREE_TYPE (stored_val);
610838fd1498Szrj 
610938fd1498Szrj   /* Dig out the type of the function's second argument.  */
611038fd1498Szrj   itype = TREE_TYPE (decl);
611138fd1498Szrj   itype = TYPE_ARG_TYPES (itype);
611238fd1498Szrj   itype = TREE_CHAIN (itype);
611338fd1498Szrj   itype = TREE_VALUE (itype);
611438fd1498Szrj   imode = TYPE_MODE (itype);
611538fd1498Szrj 
611638fd1498Szrj   if (exchange && !can_atomic_exchange_p (imode, true))
611738fd1498Szrj     return false;
611838fd1498Szrj 
611938fd1498Szrj   if (!useless_type_conversion_p (itype, type))
612038fd1498Szrj     stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
612138fd1498Szrj   call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
612238fd1498Szrj 			      build_int_cst (NULL,
612338fd1498Szrj 					     gimple_omp_atomic_seq_cst_p (stmt)
612438fd1498Szrj 					     ? MEMMODEL_SEQ_CST
612538fd1498Szrj 					     : MEMMODEL_RELAXED));
612638fd1498Szrj   if (exchange)
612738fd1498Szrj     {
612838fd1498Szrj       if (!useless_type_conversion_p (type, itype))
612938fd1498Szrj 	call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
613038fd1498Szrj       call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
613138fd1498Szrj     }
613238fd1498Szrj 
613338fd1498Szrj   force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
613438fd1498Szrj   gsi_remove (&gsi, true);
613538fd1498Szrj 
613638fd1498Szrj   /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above.  */
613738fd1498Szrj   gsi = gsi_last_nondebug_bb (load_bb);
613838fd1498Szrj   gsi_remove (&gsi, true);
613938fd1498Szrj 
614038fd1498Szrj   if (gimple_in_ssa_p (cfun))
614138fd1498Szrj     update_ssa (TODO_update_ssa_no_phi);
614238fd1498Szrj 
614338fd1498Szrj   return true;
614438fd1498Szrj }
614538fd1498Szrj 
614638fd1498Szrj /* A subroutine of expand_omp_atomic.  Attempt to implement the atomic
614738fd1498Szrj    operation as a __atomic_fetch_op builtin.  INDEX is log2 of the
614838fd1498Szrj    size of the data type, and thus usable to find the index of the builtin
614938fd1498Szrj    decl.  Returns false if the expression is not of the proper form.  */
615038fd1498Szrj 
615138fd1498Szrj static bool
expand_omp_atomic_fetch_op(basic_block load_bb,tree addr,tree loaded_val,tree stored_val,int index)615238fd1498Szrj expand_omp_atomic_fetch_op (basic_block load_bb,
615338fd1498Szrj 			    tree addr, tree loaded_val,
615438fd1498Szrj 			    tree stored_val, int index)
615538fd1498Szrj {
615638fd1498Szrj   enum built_in_function oldbase, newbase, tmpbase;
615738fd1498Szrj   tree decl, itype, call;
615838fd1498Szrj   tree lhs, rhs;
615938fd1498Szrj   basic_block store_bb = single_succ (load_bb);
616038fd1498Szrj   gimple_stmt_iterator gsi;
616138fd1498Szrj   gimple *stmt;
616238fd1498Szrj   location_t loc;
616338fd1498Szrj   enum tree_code code;
616438fd1498Szrj   bool need_old, need_new;
616538fd1498Szrj   machine_mode imode;
616638fd1498Szrj   bool seq_cst;
616738fd1498Szrj 
616838fd1498Szrj   /* We expect to find the following sequences:
616938fd1498Szrj 
617038fd1498Szrj    load_bb:
617138fd1498Szrj        GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
617238fd1498Szrj 
617338fd1498Szrj    store_bb:
617438fd1498Szrj        val = tmp OP something; (or: something OP tmp)
617538fd1498Szrj        GIMPLE_OMP_STORE (val)
617638fd1498Szrj 
617738fd1498Szrj   ???FIXME: Allow a more flexible sequence.
617838fd1498Szrj   Perhaps use data flow to pick the statements.
617938fd1498Szrj 
618038fd1498Szrj   */
618138fd1498Szrj 
618238fd1498Szrj   gsi = gsi_after_labels (store_bb);
618338fd1498Szrj   stmt = gsi_stmt (gsi);
618438fd1498Szrj   if (is_gimple_debug (stmt))
618538fd1498Szrj     {
618638fd1498Szrj       gsi_next_nondebug (&gsi);
618738fd1498Szrj       if (gsi_end_p (gsi))
618838fd1498Szrj 	return false;
618938fd1498Szrj       stmt = gsi_stmt (gsi);
619038fd1498Szrj     }
619138fd1498Szrj   loc = gimple_location (stmt);
619238fd1498Szrj   if (!is_gimple_assign (stmt))
619338fd1498Szrj     return false;
619438fd1498Szrj   gsi_next_nondebug (&gsi);
619538fd1498Szrj   if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
619638fd1498Szrj     return false;
619738fd1498Szrj   need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
619838fd1498Szrj   need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
619938fd1498Szrj   seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
620038fd1498Szrj   gcc_checking_assert (!need_old || !need_new);
620138fd1498Szrj 
620238fd1498Szrj   if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
620338fd1498Szrj     return false;
620438fd1498Szrj 
620538fd1498Szrj   /* Check for one of the supported fetch-op operations.  */
620638fd1498Szrj   code = gimple_assign_rhs_code (stmt);
620738fd1498Szrj   switch (code)
620838fd1498Szrj     {
620938fd1498Szrj     case PLUS_EXPR:
621038fd1498Szrj     case POINTER_PLUS_EXPR:
621138fd1498Szrj       oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
621238fd1498Szrj       newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
621338fd1498Szrj       break;
621438fd1498Szrj     case MINUS_EXPR:
621538fd1498Szrj       oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
621638fd1498Szrj       newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
621738fd1498Szrj       break;
621838fd1498Szrj     case BIT_AND_EXPR:
621938fd1498Szrj       oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
622038fd1498Szrj       newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
622138fd1498Szrj       break;
622238fd1498Szrj     case BIT_IOR_EXPR:
622338fd1498Szrj       oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
622438fd1498Szrj       newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
622538fd1498Szrj       break;
622638fd1498Szrj     case BIT_XOR_EXPR:
622738fd1498Szrj       oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
622838fd1498Szrj       newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
622938fd1498Szrj       break;
623038fd1498Szrj     default:
623138fd1498Szrj       return false;
623238fd1498Szrj     }
623338fd1498Szrj 
623438fd1498Szrj   /* Make sure the expression is of the proper form.  */
623538fd1498Szrj   if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
623638fd1498Szrj     rhs = gimple_assign_rhs2 (stmt);
623738fd1498Szrj   else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
623838fd1498Szrj 	   && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
623938fd1498Szrj     rhs = gimple_assign_rhs1 (stmt);
624038fd1498Szrj   else
624138fd1498Szrj     return false;
624238fd1498Szrj 
624338fd1498Szrj   tmpbase = ((enum built_in_function)
624438fd1498Szrj 	     ((need_new ? newbase : oldbase) + index + 1));
624538fd1498Szrj   decl = builtin_decl_explicit (tmpbase);
624638fd1498Szrj   if (decl == NULL_TREE)
624738fd1498Szrj     return false;
624838fd1498Szrj   itype = TREE_TYPE (TREE_TYPE (decl));
624938fd1498Szrj   imode = TYPE_MODE (itype);
625038fd1498Szrj 
625138fd1498Szrj   /* We could test all of the various optabs involved, but the fact of the
625238fd1498Szrj      matter is that (with the exception of i486 vs i586 and xadd) all targets
625338fd1498Szrj      that support any atomic operaton optab also implements compare-and-swap.
625438fd1498Szrj      Let optabs.c take care of expanding any compare-and-swap loop.  */
625538fd1498Szrj   if (!can_compare_and_swap_p (imode, true) || !can_atomic_load_p (imode))
625638fd1498Szrj     return false;
625738fd1498Szrj 
625838fd1498Szrj   gsi = gsi_last_nondebug_bb (load_bb);
625938fd1498Szrj   gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
626038fd1498Szrj 
626138fd1498Szrj   /* OpenMP does not imply any barrier-like semantics on its atomic ops.
626238fd1498Szrj      It only requires that the operation happen atomically.  Thus we can
626338fd1498Szrj      use the RELAXED memory model.  */
626438fd1498Szrj   call = build_call_expr_loc (loc, decl, 3, addr,
626538fd1498Szrj 			      fold_convert_loc (loc, itype, rhs),
626638fd1498Szrj 			      build_int_cst (NULL,
626738fd1498Szrj 					     seq_cst ? MEMMODEL_SEQ_CST
626838fd1498Szrj 						     : MEMMODEL_RELAXED));
626938fd1498Szrj 
627038fd1498Szrj   if (need_old || need_new)
627138fd1498Szrj     {
627238fd1498Szrj       lhs = need_old ? loaded_val : stored_val;
627338fd1498Szrj       call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
627438fd1498Szrj       call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
627538fd1498Szrj     }
627638fd1498Szrj   else
627738fd1498Szrj     call = fold_convert_loc (loc, void_type_node, call);
627838fd1498Szrj   force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
627938fd1498Szrj   gsi_remove (&gsi, true);
628038fd1498Szrj 
628138fd1498Szrj   gsi = gsi_last_nondebug_bb (store_bb);
628238fd1498Szrj   gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
628338fd1498Szrj   gsi_remove (&gsi, true);
628438fd1498Szrj   gsi = gsi_last_nondebug_bb (store_bb);
628538fd1498Szrj   stmt = gsi_stmt (gsi);
628638fd1498Szrj   gsi_remove (&gsi, true);
628738fd1498Szrj 
628838fd1498Szrj   if (gimple_in_ssa_p (cfun))
628938fd1498Szrj     {
629038fd1498Szrj       release_defs (stmt);
629138fd1498Szrj       update_ssa (TODO_update_ssa_no_phi);
629238fd1498Szrj     }
629338fd1498Szrj 
629438fd1498Szrj   return true;
629538fd1498Szrj }
629638fd1498Szrj 
629738fd1498Szrj /* A subroutine of expand_omp_atomic.  Implement the atomic operation as:
629838fd1498Szrj 
629938fd1498Szrj       oldval = *addr;
630038fd1498Szrj       repeat:
630138fd1498Szrj 	newval = rhs;	 // with oldval replacing *addr in rhs
630238fd1498Szrj 	oldval = __sync_val_compare_and_swap (addr, oldval, newval);
630338fd1498Szrj 	if (oldval != newval)
630438fd1498Szrj 	  goto repeat;
630538fd1498Szrj 
630638fd1498Szrj    INDEX is log2 of the size of the data type, and thus usable to find the
630738fd1498Szrj    index of the builtin decl.  */
630838fd1498Szrj 
630938fd1498Szrj static bool
expand_omp_atomic_pipeline(basic_block load_bb,basic_block store_bb,tree addr,tree loaded_val,tree stored_val,int index)631038fd1498Szrj expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
631138fd1498Szrj 			    tree addr, tree loaded_val, tree stored_val,
631238fd1498Szrj 			    int index)
631338fd1498Szrj {
631438fd1498Szrj   tree loadedi, storedi, initial, new_storedi, old_vali;
631538fd1498Szrj   tree type, itype, cmpxchg, iaddr, atype;
631638fd1498Szrj   gimple_stmt_iterator si;
631738fd1498Szrj   basic_block loop_header = single_succ (load_bb);
631838fd1498Szrj   gimple *phi, *stmt;
631938fd1498Szrj   edge e;
632038fd1498Szrj   enum built_in_function fncode;
632138fd1498Szrj 
632238fd1498Szrj   /* ??? We need a non-pointer interface to __atomic_compare_exchange in
632338fd1498Szrj      order to use the RELAXED memory model effectively.  */
632438fd1498Szrj   fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
632538fd1498Szrj 				    + index + 1);
632638fd1498Szrj   cmpxchg = builtin_decl_explicit (fncode);
632738fd1498Szrj   if (cmpxchg == NULL_TREE)
632838fd1498Szrj     return false;
632938fd1498Szrj   type = TYPE_MAIN_VARIANT (TREE_TYPE (loaded_val));
633038fd1498Szrj   atype = type;
633138fd1498Szrj   itype = TREE_TYPE (TREE_TYPE (cmpxchg));
633238fd1498Szrj 
633338fd1498Szrj   if (!can_compare_and_swap_p (TYPE_MODE (itype), true)
633438fd1498Szrj       || !can_atomic_load_p (TYPE_MODE (itype)))
633538fd1498Szrj     return false;
633638fd1498Szrj 
633738fd1498Szrj   /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD.  */
633838fd1498Szrj   si = gsi_last_nondebug_bb (load_bb);
633938fd1498Szrj   gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
634038fd1498Szrj 
634138fd1498Szrj   /* For floating-point values, we'll need to view-convert them to integers
634238fd1498Szrj      so that we can perform the atomic compare and swap.  Simplify the
634338fd1498Szrj      following code by always setting up the "i"ntegral variables.  */
634438fd1498Szrj   if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
634538fd1498Szrj     {
634638fd1498Szrj       tree iaddr_val;
634738fd1498Szrj 
634838fd1498Szrj       iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
634938fd1498Szrj 							   true));
635038fd1498Szrj       atype = itype;
635138fd1498Szrj       iaddr_val
635238fd1498Szrj 	= force_gimple_operand_gsi (&si,
635338fd1498Szrj 				    fold_convert (TREE_TYPE (iaddr), addr),
635438fd1498Szrj 				    false, NULL_TREE, true, GSI_SAME_STMT);
635538fd1498Szrj       stmt = gimple_build_assign (iaddr, iaddr_val);
635638fd1498Szrj       gsi_insert_before (&si, stmt, GSI_SAME_STMT);
635738fd1498Szrj       loadedi = create_tmp_var (itype);
635838fd1498Szrj       if (gimple_in_ssa_p (cfun))
635938fd1498Szrj 	loadedi = make_ssa_name (loadedi);
636038fd1498Szrj     }
636138fd1498Szrj   else
636238fd1498Szrj     {
636338fd1498Szrj       iaddr = addr;
636438fd1498Szrj       loadedi = loaded_val;
636538fd1498Szrj     }
636638fd1498Szrj 
636738fd1498Szrj   fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
636838fd1498Szrj   tree loaddecl = builtin_decl_explicit (fncode);
636938fd1498Szrj   if (loaddecl)
637038fd1498Szrj     initial
637138fd1498Szrj       = fold_convert (atype,
637238fd1498Szrj 		      build_call_expr (loaddecl, 2, iaddr,
637338fd1498Szrj 				       build_int_cst (NULL_TREE,
637438fd1498Szrj 						      MEMMODEL_RELAXED)));
637538fd1498Szrj   else
637638fd1498Szrj     {
637738fd1498Szrj       tree off
637838fd1498Szrj 	= build_int_cst (build_pointer_type_for_mode (atype, ptr_mode,
637938fd1498Szrj 						      true), 0);
638038fd1498Szrj       initial = build2 (MEM_REF, atype, iaddr, off);
638138fd1498Szrj     }
638238fd1498Szrj 
638338fd1498Szrj   initial
638438fd1498Szrj     = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
638538fd1498Szrj 				GSI_SAME_STMT);
638638fd1498Szrj 
638738fd1498Szrj   /* Move the value to the LOADEDI temporary.  */
638838fd1498Szrj   if (gimple_in_ssa_p (cfun))
638938fd1498Szrj     {
639038fd1498Szrj       gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
639138fd1498Szrj       phi = create_phi_node (loadedi, loop_header);
639238fd1498Szrj       SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
639338fd1498Szrj 	       initial);
639438fd1498Szrj     }
639538fd1498Szrj   else
639638fd1498Szrj     gsi_insert_before (&si,
639738fd1498Szrj 		       gimple_build_assign (loadedi, initial),
639838fd1498Szrj 		       GSI_SAME_STMT);
639938fd1498Szrj   if (loadedi != loaded_val)
640038fd1498Szrj     {
640138fd1498Szrj       gimple_stmt_iterator gsi2;
640238fd1498Szrj       tree x;
640338fd1498Szrj 
640438fd1498Szrj       x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
640538fd1498Szrj       gsi2 = gsi_start_bb (loop_header);
640638fd1498Szrj       if (gimple_in_ssa_p (cfun))
640738fd1498Szrj 	{
640838fd1498Szrj 	  gassign *stmt;
640938fd1498Szrj 	  x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
641038fd1498Szrj 					true, GSI_SAME_STMT);
641138fd1498Szrj 	  stmt = gimple_build_assign (loaded_val, x);
641238fd1498Szrj 	  gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
641338fd1498Szrj 	}
641438fd1498Szrj       else
641538fd1498Szrj 	{
641638fd1498Szrj 	  x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
641738fd1498Szrj 	  force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
641838fd1498Szrj 				    true, GSI_SAME_STMT);
641938fd1498Szrj 	}
642038fd1498Szrj     }
642138fd1498Szrj   gsi_remove (&si, true);
642238fd1498Szrj 
642338fd1498Szrj   si = gsi_last_nondebug_bb (store_bb);
642438fd1498Szrj   gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
642538fd1498Szrj 
642638fd1498Szrj   if (iaddr == addr)
642738fd1498Szrj     storedi = stored_val;
642838fd1498Szrj   else
642938fd1498Szrj     storedi
643038fd1498Szrj       = force_gimple_operand_gsi (&si,
643138fd1498Szrj 				  build1 (VIEW_CONVERT_EXPR, itype,
643238fd1498Szrj 					  stored_val), true, NULL_TREE, true,
643338fd1498Szrj 				  GSI_SAME_STMT);
643438fd1498Szrj 
643538fd1498Szrj   /* Build the compare&swap statement.  */
643638fd1498Szrj   new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
643738fd1498Szrj   new_storedi = force_gimple_operand_gsi (&si,
643838fd1498Szrj 					  fold_convert (TREE_TYPE (loadedi),
643938fd1498Szrj 							new_storedi),
644038fd1498Szrj 					  true, NULL_TREE,
644138fd1498Szrj 					  true, GSI_SAME_STMT);
644238fd1498Szrj 
644338fd1498Szrj   if (gimple_in_ssa_p (cfun))
644438fd1498Szrj     old_vali = loadedi;
644538fd1498Szrj   else
644638fd1498Szrj     {
644738fd1498Szrj       old_vali = create_tmp_var (TREE_TYPE (loadedi));
644838fd1498Szrj       stmt = gimple_build_assign (old_vali, loadedi);
644938fd1498Szrj       gsi_insert_before (&si, stmt, GSI_SAME_STMT);
645038fd1498Szrj 
645138fd1498Szrj       stmt = gimple_build_assign (loadedi, new_storedi);
645238fd1498Szrj       gsi_insert_before (&si, stmt, GSI_SAME_STMT);
645338fd1498Szrj     }
645438fd1498Szrj 
645538fd1498Szrj   /* Note that we always perform the comparison as an integer, even for
645638fd1498Szrj      floating point.  This allows the atomic operation to properly
645738fd1498Szrj      succeed even with NaNs and -0.0.  */
645838fd1498Szrj   tree ne = build2 (NE_EXPR, boolean_type_node, new_storedi, old_vali);
645938fd1498Szrj   stmt = gimple_build_cond_empty (ne);
646038fd1498Szrj   gsi_insert_before (&si, stmt, GSI_SAME_STMT);
646138fd1498Szrj 
646238fd1498Szrj   /* Update cfg.  */
646338fd1498Szrj   e = single_succ_edge (store_bb);
646438fd1498Szrj   e->flags &= ~EDGE_FALLTHRU;
646538fd1498Szrj   e->flags |= EDGE_FALSE_VALUE;
646638fd1498Szrj   /* Expect no looping.  */
646738fd1498Szrj   e->probability = profile_probability::guessed_always ();
646838fd1498Szrj 
646938fd1498Szrj   e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
647038fd1498Szrj   e->probability = profile_probability::guessed_never ();
647138fd1498Szrj 
647238fd1498Szrj   /* Copy the new value to loadedi (we already did that before the condition
647338fd1498Szrj      if we are not in SSA).  */
647438fd1498Szrj   if (gimple_in_ssa_p (cfun))
647538fd1498Szrj     {
647638fd1498Szrj       phi = gimple_seq_first_stmt (phi_nodes (loop_header));
647738fd1498Szrj       SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
647838fd1498Szrj     }
647938fd1498Szrj 
648038fd1498Szrj   /* Remove GIMPLE_OMP_ATOMIC_STORE.  */
648138fd1498Szrj   gsi_remove (&si, true);
648238fd1498Szrj 
648338fd1498Szrj   struct loop *loop = alloc_loop ();
648438fd1498Szrj   loop->header = loop_header;
648538fd1498Szrj   loop->latch = store_bb;
648638fd1498Szrj   add_loop (loop, loop_header->loop_father);
648738fd1498Szrj 
648838fd1498Szrj   if (gimple_in_ssa_p (cfun))
648938fd1498Szrj     update_ssa (TODO_update_ssa_no_phi);
649038fd1498Szrj 
649138fd1498Szrj   return true;
649238fd1498Szrj }
649338fd1498Szrj 
649438fd1498Szrj /* A subroutine of expand_omp_atomic.  Implement the atomic operation as:
649538fd1498Szrj 
649638fd1498Szrj 				  GOMP_atomic_start ();
649738fd1498Szrj 				  *addr = rhs;
649838fd1498Szrj 				  GOMP_atomic_end ();
649938fd1498Szrj 
650038fd1498Szrj    The result is not globally atomic, but works so long as all parallel
650138fd1498Szrj    references are within #pragma omp atomic directives.  According to
650238fd1498Szrj    responses received from omp@openmp.org, appears to be within spec.
650338fd1498Szrj    Which makes sense, since that's how several other compilers handle
650438fd1498Szrj    this situation as well.
650538fd1498Szrj    LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
650638fd1498Szrj    expanding.  STORED_VAL is the operand of the matching
650738fd1498Szrj    GIMPLE_OMP_ATOMIC_STORE.
650838fd1498Szrj 
650938fd1498Szrj    We replace
651038fd1498Szrj    GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
651138fd1498Szrj    loaded_val = *addr;
651238fd1498Szrj 
651338fd1498Szrj    and replace
651438fd1498Szrj    GIMPLE_OMP_ATOMIC_STORE (stored_val)  with
651538fd1498Szrj    *addr = stored_val;
651638fd1498Szrj */
651738fd1498Szrj 
651838fd1498Szrj static bool
expand_omp_atomic_mutex(basic_block load_bb,basic_block store_bb,tree addr,tree loaded_val,tree stored_val)651938fd1498Szrj expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
652038fd1498Szrj 			 tree addr, tree loaded_val, tree stored_val)
652138fd1498Szrj {
652238fd1498Szrj   gimple_stmt_iterator si;
652338fd1498Szrj   gassign *stmt;
652438fd1498Szrj   tree t;
652538fd1498Szrj 
652638fd1498Szrj   si = gsi_last_nondebug_bb (load_bb);
652738fd1498Szrj   gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
652838fd1498Szrj 
652938fd1498Szrj   t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
653038fd1498Szrj   t = build_call_expr (t, 0);
653138fd1498Szrj   force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
653238fd1498Szrj 
653338fd1498Szrj   tree mem = build_simple_mem_ref (addr);
653438fd1498Szrj   TREE_TYPE (mem) = TREE_TYPE (loaded_val);
653538fd1498Szrj   TREE_OPERAND (mem, 1)
653638fd1498Szrj     = fold_convert (build_pointer_type_for_mode (TREE_TYPE (mem), ptr_mode,
653738fd1498Szrj 						 true),
653838fd1498Szrj 		    TREE_OPERAND (mem, 1));
653938fd1498Szrj   stmt = gimple_build_assign (loaded_val, mem);
654038fd1498Szrj   gsi_insert_before (&si, stmt, GSI_SAME_STMT);
654138fd1498Szrj   gsi_remove (&si, true);
654238fd1498Szrj 
654338fd1498Szrj   si = gsi_last_nondebug_bb (store_bb);
654438fd1498Szrj   gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
654538fd1498Szrj 
654638fd1498Szrj   stmt = gimple_build_assign (unshare_expr (mem), stored_val);
654738fd1498Szrj   gsi_insert_before (&si, stmt, GSI_SAME_STMT);
654838fd1498Szrj 
654938fd1498Szrj   t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
655038fd1498Szrj   t = build_call_expr (t, 0);
655138fd1498Szrj   force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
655238fd1498Szrj   gsi_remove (&si, true);
655338fd1498Szrj 
655438fd1498Szrj   if (gimple_in_ssa_p (cfun))
655538fd1498Szrj     update_ssa (TODO_update_ssa_no_phi);
655638fd1498Szrj   return true;
655738fd1498Szrj }
655838fd1498Szrj 
655938fd1498Szrj /* Expand an GIMPLE_OMP_ATOMIC statement.  We try to expand
656038fd1498Szrj    using expand_omp_atomic_fetch_op.  If it failed, we try to
656138fd1498Szrj    call expand_omp_atomic_pipeline, and if it fails too, the
656238fd1498Szrj    ultimate fallback is wrapping the operation in a mutex
656338fd1498Szrj    (expand_omp_atomic_mutex).  REGION is the atomic region built
656438fd1498Szrj    by build_omp_regions_1().  */
656538fd1498Szrj 
656638fd1498Szrj static void
expand_omp_atomic(struct omp_region * region)656738fd1498Szrj expand_omp_atomic (struct omp_region *region)
656838fd1498Szrj {
656938fd1498Szrj   basic_block load_bb = region->entry, store_bb = region->exit;
657038fd1498Szrj   gomp_atomic_load *load = as_a <gomp_atomic_load *> (last_stmt (load_bb));
657138fd1498Szrj   gomp_atomic_store *store = as_a <gomp_atomic_store *> (last_stmt (store_bb));
657238fd1498Szrj   tree loaded_val = gimple_omp_atomic_load_lhs (load);
657338fd1498Szrj   tree addr = gimple_omp_atomic_load_rhs (load);
657438fd1498Szrj   tree stored_val = gimple_omp_atomic_store_val (store);
657538fd1498Szrj   tree type = TYPE_MAIN_VARIANT (TREE_TYPE (loaded_val));
657638fd1498Szrj   HOST_WIDE_INT index;
657738fd1498Szrj 
657838fd1498Szrj   /* Make sure the type is one of the supported sizes.  */
657938fd1498Szrj   index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
658038fd1498Szrj   index = exact_log2 (index);
658138fd1498Szrj   if (index >= 0 && index <= 4)
658238fd1498Szrj     {
658338fd1498Szrj       unsigned int align = TYPE_ALIGN_UNIT (type);
658438fd1498Szrj 
658538fd1498Szrj       /* __sync builtins require strict data alignment.  */
658638fd1498Szrj       if (exact_log2 (align) >= index)
658738fd1498Szrj 	{
658838fd1498Szrj 	  /* Atomic load.  */
658938fd1498Szrj 	  scalar_mode smode;
659038fd1498Szrj 	  if (loaded_val == stored_val
659138fd1498Szrj 	      && (is_int_mode (TYPE_MODE (type), &smode)
659238fd1498Szrj 		  || is_float_mode (TYPE_MODE (type), &smode))
659338fd1498Szrj 	      && GET_MODE_BITSIZE (smode) <= BITS_PER_WORD
659438fd1498Szrj 	      && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
659538fd1498Szrj 	    return;
659638fd1498Szrj 
659738fd1498Szrj 	  /* Atomic store.  */
659838fd1498Szrj 	  if ((is_int_mode (TYPE_MODE (type), &smode)
659938fd1498Szrj 	       || is_float_mode (TYPE_MODE (type), &smode))
660038fd1498Szrj 	      && GET_MODE_BITSIZE (smode) <= BITS_PER_WORD
660138fd1498Szrj 	      && store_bb == single_succ (load_bb)
660238fd1498Szrj 	      && first_stmt (store_bb) == store
660338fd1498Szrj 	      && expand_omp_atomic_store (load_bb, addr, loaded_val,
660438fd1498Szrj 					  stored_val, index))
660538fd1498Szrj 	    return;
660638fd1498Szrj 
660738fd1498Szrj 	  /* When possible, use specialized atomic update functions.  */
660838fd1498Szrj 	  if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
660938fd1498Szrj 	      && store_bb == single_succ (load_bb)
661038fd1498Szrj 	      && expand_omp_atomic_fetch_op (load_bb, addr,
661138fd1498Szrj 					     loaded_val, stored_val, index))
661238fd1498Szrj 	    return;
661338fd1498Szrj 
661438fd1498Szrj 	  /* If we don't have specialized __sync builtins, try and implement
661538fd1498Szrj 	     as a compare and swap loop.  */
661638fd1498Szrj 	  if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
661738fd1498Szrj 					  loaded_val, stored_val, index))
661838fd1498Szrj 	    return;
661938fd1498Szrj 	}
662038fd1498Szrj     }
662138fd1498Szrj 
662238fd1498Szrj   /* The ultimate fallback is wrapping the operation in a mutex.  */
662338fd1498Szrj   expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
662438fd1498Szrj }
662538fd1498Szrj 
662638fd1498Szrj /* Mark the loops inside the kernels region starting at REGION_ENTRY and ending
662738fd1498Szrj    at REGION_EXIT.  */
662838fd1498Szrj 
662938fd1498Szrj static void
mark_loops_in_oacc_kernels_region(basic_block region_entry,basic_block region_exit)663038fd1498Szrj mark_loops_in_oacc_kernels_region (basic_block region_entry,
663138fd1498Szrj 				   basic_block region_exit)
663238fd1498Szrj {
663338fd1498Szrj   struct loop *outer = region_entry->loop_father;
663438fd1498Szrj   gcc_assert (region_exit == NULL || outer == region_exit->loop_father);
663538fd1498Szrj 
663638fd1498Szrj   /* Don't parallelize the kernels region if it contains more than one outer
663738fd1498Szrj      loop.  */
663838fd1498Szrj   unsigned int nr_outer_loops = 0;
663938fd1498Szrj   struct loop *single_outer = NULL;
664038fd1498Szrj   for (struct loop *loop = outer->inner; loop != NULL; loop = loop->next)
664138fd1498Szrj     {
664238fd1498Szrj       gcc_assert (loop_outer (loop) == outer);
664338fd1498Szrj 
664438fd1498Szrj       if (!dominated_by_p (CDI_DOMINATORS, loop->header, region_entry))
664538fd1498Szrj 	continue;
664638fd1498Szrj 
664738fd1498Szrj       if (region_exit != NULL
664838fd1498Szrj 	  && dominated_by_p (CDI_DOMINATORS, loop->header, region_exit))
664938fd1498Szrj 	continue;
665038fd1498Szrj 
665138fd1498Szrj       nr_outer_loops++;
665238fd1498Szrj       single_outer = loop;
665338fd1498Szrj     }
665438fd1498Szrj   if (nr_outer_loops != 1)
665538fd1498Szrj     return;
665638fd1498Szrj 
665738fd1498Szrj   for (struct loop *loop = single_outer->inner;
665838fd1498Szrj        loop != NULL;
665938fd1498Szrj        loop = loop->inner)
666038fd1498Szrj     if (loop->next)
666138fd1498Szrj       return;
666238fd1498Szrj 
666338fd1498Szrj   /* Mark the loops in the region.  */
666438fd1498Szrj   for (struct loop *loop = single_outer; loop != NULL; loop = loop->inner)
666538fd1498Szrj     loop->in_oacc_kernels_region = true;
666638fd1498Szrj }
666738fd1498Szrj 
666838fd1498Szrj /* Types used to pass grid and wortkgroup sizes to kernel invocation.  */
666938fd1498Szrj 
667038fd1498Szrj struct GTY(()) grid_launch_attributes_trees
667138fd1498Szrj {
667238fd1498Szrj   tree kernel_dim_array_type;
667338fd1498Szrj   tree kernel_lattrs_dimnum_decl;
667438fd1498Szrj   tree kernel_lattrs_grid_decl;
667538fd1498Szrj   tree kernel_lattrs_group_decl;
667638fd1498Szrj   tree kernel_launch_attributes_type;
667738fd1498Szrj };
667838fd1498Szrj 
667938fd1498Szrj static GTY(()) struct grid_launch_attributes_trees *grid_attr_trees;
668038fd1498Szrj 
668138fd1498Szrj /* Create types used to pass kernel launch attributes to target.  */
668238fd1498Szrj 
668338fd1498Szrj static void
grid_create_kernel_launch_attr_types(void)668438fd1498Szrj grid_create_kernel_launch_attr_types (void)
668538fd1498Szrj {
668638fd1498Szrj   if (grid_attr_trees)
668738fd1498Szrj     return;
668838fd1498Szrj   grid_attr_trees = ggc_alloc <grid_launch_attributes_trees> ();
668938fd1498Szrj 
669038fd1498Szrj   tree dim_arr_index_type
669138fd1498Szrj     = build_index_type (build_int_cst (integer_type_node, 2));
669238fd1498Szrj   grid_attr_trees->kernel_dim_array_type
669338fd1498Szrj     = build_array_type (uint32_type_node, dim_arr_index_type);
669438fd1498Szrj 
669538fd1498Szrj   grid_attr_trees->kernel_launch_attributes_type = make_node (RECORD_TYPE);
669638fd1498Szrj   grid_attr_trees->kernel_lattrs_dimnum_decl
669738fd1498Szrj     = build_decl (BUILTINS_LOCATION, FIELD_DECL, get_identifier ("ndim"),
669838fd1498Szrj 		  uint32_type_node);
669938fd1498Szrj   DECL_CHAIN (grid_attr_trees->kernel_lattrs_dimnum_decl) = NULL_TREE;
670038fd1498Szrj 
670138fd1498Szrj   grid_attr_trees->kernel_lattrs_grid_decl
670238fd1498Szrj     = build_decl (BUILTINS_LOCATION, FIELD_DECL, get_identifier ("grid_size"),
670338fd1498Szrj 		  grid_attr_trees->kernel_dim_array_type);
670438fd1498Szrj   DECL_CHAIN (grid_attr_trees->kernel_lattrs_grid_decl)
670538fd1498Szrj     = grid_attr_trees->kernel_lattrs_dimnum_decl;
670638fd1498Szrj   grid_attr_trees->kernel_lattrs_group_decl
670738fd1498Szrj     = build_decl (BUILTINS_LOCATION, FIELD_DECL, get_identifier ("group_size"),
670838fd1498Szrj 		  grid_attr_trees->kernel_dim_array_type);
670938fd1498Szrj   DECL_CHAIN (grid_attr_trees->kernel_lattrs_group_decl)
671038fd1498Szrj     = grid_attr_trees->kernel_lattrs_grid_decl;
671138fd1498Szrj   finish_builtin_struct (grid_attr_trees->kernel_launch_attributes_type,
671238fd1498Szrj 			 "__gomp_kernel_launch_attributes",
671338fd1498Szrj 			 grid_attr_trees->kernel_lattrs_group_decl, NULL_TREE);
671438fd1498Szrj }
671538fd1498Szrj 
671638fd1498Szrj /* Insert before the current statement in GSI a store of VALUE to INDEX of
671738fd1498Szrj    array (of type kernel_dim_array_type) FLD_DECL of RANGE_VAR.  VALUE must be
671838fd1498Szrj    of type uint32_type_node.  */
671938fd1498Szrj 
672038fd1498Szrj static void
grid_insert_store_range_dim(gimple_stmt_iterator * gsi,tree range_var,tree fld_decl,int index,tree value)672138fd1498Szrj grid_insert_store_range_dim (gimple_stmt_iterator *gsi, tree range_var,
672238fd1498Szrj 			     tree fld_decl, int index, tree value)
672338fd1498Szrj {
672438fd1498Szrj   tree ref = build4 (ARRAY_REF, uint32_type_node,
672538fd1498Szrj 		     build3 (COMPONENT_REF,
672638fd1498Szrj 			     grid_attr_trees->kernel_dim_array_type,
672738fd1498Szrj 			     range_var, fld_decl, NULL_TREE),
672838fd1498Szrj 		     build_int_cst (integer_type_node, index),
672938fd1498Szrj 		     NULL_TREE, NULL_TREE);
673038fd1498Szrj   gsi_insert_before (gsi, gimple_build_assign (ref, value), GSI_SAME_STMT);
673138fd1498Szrj }
673238fd1498Szrj 
673338fd1498Szrj /* Return a tree representation of a pointer to a structure with grid and
673438fd1498Szrj    work-group size information.  Statements filling that information will be
673538fd1498Szrj    inserted before GSI, TGT_STMT is the target statement which has the
673638fd1498Szrj    necessary information in it.  */
673738fd1498Szrj 
673838fd1498Szrj static tree
grid_get_kernel_launch_attributes(gimple_stmt_iterator * gsi,gomp_target * tgt_stmt)673938fd1498Szrj grid_get_kernel_launch_attributes (gimple_stmt_iterator *gsi,
674038fd1498Szrj 				       gomp_target *tgt_stmt)
674138fd1498Szrj {
674238fd1498Szrj   grid_create_kernel_launch_attr_types ();
674338fd1498Szrj   tree lattrs = create_tmp_var (grid_attr_trees->kernel_launch_attributes_type,
674438fd1498Szrj 				"__kernel_launch_attrs");
674538fd1498Szrj 
674638fd1498Szrj   unsigned max_dim = 0;
674738fd1498Szrj   for (tree clause = gimple_omp_target_clauses (tgt_stmt);
674838fd1498Szrj        clause;
674938fd1498Szrj        clause = OMP_CLAUSE_CHAIN (clause))
675038fd1498Szrj     {
675138fd1498Szrj       if (OMP_CLAUSE_CODE (clause) != OMP_CLAUSE__GRIDDIM_)
675238fd1498Szrj 	continue;
675338fd1498Szrj 
675438fd1498Szrj       unsigned dim = OMP_CLAUSE__GRIDDIM__DIMENSION (clause);
675538fd1498Szrj       max_dim = MAX (dim, max_dim);
675638fd1498Szrj 
675738fd1498Szrj       grid_insert_store_range_dim (gsi, lattrs,
675838fd1498Szrj 				   grid_attr_trees->kernel_lattrs_grid_decl,
675938fd1498Szrj 				   dim, OMP_CLAUSE__GRIDDIM__SIZE (clause));
676038fd1498Szrj       grid_insert_store_range_dim (gsi, lattrs,
676138fd1498Szrj 				   grid_attr_trees->kernel_lattrs_group_decl,
676238fd1498Szrj 				   dim, OMP_CLAUSE__GRIDDIM__GROUP (clause));
676338fd1498Szrj     }
676438fd1498Szrj 
676538fd1498Szrj   tree dimref = build3 (COMPONENT_REF, uint32_type_node, lattrs,
676638fd1498Szrj 			grid_attr_trees->kernel_lattrs_dimnum_decl, NULL_TREE);
676738fd1498Szrj   gcc_checking_assert (max_dim <= 2);
676838fd1498Szrj   tree dimensions = build_int_cstu (uint32_type_node, max_dim + 1);
676938fd1498Szrj   gsi_insert_before (gsi, gimple_build_assign (dimref, dimensions),
677038fd1498Szrj 		     GSI_SAME_STMT);
677138fd1498Szrj   TREE_ADDRESSABLE (lattrs) = 1;
677238fd1498Szrj   return build_fold_addr_expr (lattrs);
677338fd1498Szrj }
677438fd1498Szrj 
677538fd1498Szrj /* Build target argument identifier from the DEVICE identifier, value
677638fd1498Szrj    identifier ID and whether the element also has a SUBSEQUENT_PARAM.  */
677738fd1498Szrj 
677838fd1498Szrj static tree
get_target_argument_identifier_1(int device,bool subseqent_param,int id)677938fd1498Szrj get_target_argument_identifier_1 (int device, bool subseqent_param, int id)
678038fd1498Szrj {
678138fd1498Szrj   tree t = build_int_cst (integer_type_node, device);
678238fd1498Szrj   if (subseqent_param)
678338fd1498Szrj     t = fold_build2 (BIT_IOR_EXPR, integer_type_node, t,
678438fd1498Szrj 		     build_int_cst (integer_type_node,
678538fd1498Szrj 				    GOMP_TARGET_ARG_SUBSEQUENT_PARAM));
678638fd1498Szrj   t = fold_build2 (BIT_IOR_EXPR, integer_type_node, t,
678738fd1498Szrj 		   build_int_cst (integer_type_node, id));
678838fd1498Szrj   return t;
678938fd1498Szrj }
679038fd1498Szrj 
679138fd1498Szrj /* Like above but return it in type that can be directly stored as an element
679238fd1498Szrj    of the argument array.  */
679338fd1498Szrj 
679438fd1498Szrj static tree
get_target_argument_identifier(int device,bool subseqent_param,int id)679538fd1498Szrj get_target_argument_identifier (int device, bool subseqent_param, int id)
679638fd1498Szrj {
679738fd1498Szrj   tree t = get_target_argument_identifier_1 (device, subseqent_param, id);
679838fd1498Szrj   return fold_convert (ptr_type_node, t);
679938fd1498Szrj }
680038fd1498Szrj 
680138fd1498Szrj /* Return a target argument consisting of DEVICE identifier, value identifier
680238fd1498Szrj    ID, and the actual VALUE.  */
680338fd1498Szrj 
680438fd1498Szrj static tree
get_target_argument_value(gimple_stmt_iterator * gsi,int device,int id,tree value)680538fd1498Szrj get_target_argument_value (gimple_stmt_iterator *gsi, int device, int id,
680638fd1498Szrj 			   tree value)
680738fd1498Szrj {
680838fd1498Szrj   tree t = fold_build2 (LSHIFT_EXPR, integer_type_node,
680938fd1498Szrj 			fold_convert (integer_type_node, value),
681038fd1498Szrj 			build_int_cst (unsigned_type_node,
681138fd1498Szrj 				       GOMP_TARGET_ARG_VALUE_SHIFT));
681238fd1498Szrj   t = fold_build2 (BIT_IOR_EXPR, integer_type_node, t,
681338fd1498Szrj 		   get_target_argument_identifier_1 (device, false, id));
681438fd1498Szrj   t = fold_convert (ptr_type_node, t);
681538fd1498Szrj   return force_gimple_operand_gsi (gsi, t, true, NULL, true, GSI_SAME_STMT);
681638fd1498Szrj }
681738fd1498Szrj 
681838fd1498Szrj /* If VALUE is an integer constant greater than -2^15 and smaller than 2^15,
681938fd1498Szrj    push one argument to ARGS with both the DEVICE, ID and VALUE embedded in it,
682038fd1498Szrj    otherwise push an identifier (with DEVICE and ID) and the VALUE in two
682138fd1498Szrj    arguments.  */
682238fd1498Szrj 
682338fd1498Szrj static void
push_target_argument_according_to_value(gimple_stmt_iterator * gsi,int device,int id,tree value,vec<tree> * args)682438fd1498Szrj push_target_argument_according_to_value (gimple_stmt_iterator *gsi, int device,
682538fd1498Szrj 					 int id, tree value, vec <tree> *args)
682638fd1498Szrj {
682738fd1498Szrj   if (tree_fits_shwi_p (value)
682838fd1498Szrj       && tree_to_shwi (value) > -(1 << 15)
682938fd1498Szrj       && tree_to_shwi (value) < (1 << 15))
683038fd1498Szrj     args->quick_push (get_target_argument_value (gsi, device, id, value));
683138fd1498Szrj   else
683238fd1498Szrj     {
683338fd1498Szrj       args->quick_push (get_target_argument_identifier (device, true, id));
683438fd1498Szrj       value = fold_convert (ptr_type_node, value);
683538fd1498Szrj       value = force_gimple_operand_gsi (gsi, value, true, NULL, true,
683638fd1498Szrj 					GSI_SAME_STMT);
683738fd1498Szrj       args->quick_push (value);
683838fd1498Szrj     }
683938fd1498Szrj }
684038fd1498Szrj 
684138fd1498Szrj /* Create an array of arguments that is then passed to GOMP_target.  */
684238fd1498Szrj 
684338fd1498Szrj static tree
get_target_arguments(gimple_stmt_iterator * gsi,gomp_target * tgt_stmt)684438fd1498Szrj get_target_arguments (gimple_stmt_iterator *gsi, gomp_target *tgt_stmt)
684538fd1498Szrj {
684638fd1498Szrj   auto_vec <tree, 6> args;
684738fd1498Szrj   tree clauses = gimple_omp_target_clauses (tgt_stmt);
684838fd1498Szrj   tree t, c = omp_find_clause (clauses, OMP_CLAUSE_NUM_TEAMS);
684938fd1498Szrj   if (c)
685038fd1498Szrj     t = OMP_CLAUSE_NUM_TEAMS_EXPR (c);
685138fd1498Szrj   else
685238fd1498Szrj     t = integer_minus_one_node;
685338fd1498Szrj   push_target_argument_according_to_value (gsi, GOMP_TARGET_ARG_DEVICE_ALL,
685438fd1498Szrj 					   GOMP_TARGET_ARG_NUM_TEAMS, t, &args);
685538fd1498Szrj 
685638fd1498Szrj   c = omp_find_clause (clauses, OMP_CLAUSE_THREAD_LIMIT);
685738fd1498Szrj   if (c)
685838fd1498Szrj     t = OMP_CLAUSE_THREAD_LIMIT_EXPR (c);
685938fd1498Szrj   else
686038fd1498Szrj     t = integer_minus_one_node;
686138fd1498Szrj   push_target_argument_according_to_value (gsi, GOMP_TARGET_ARG_DEVICE_ALL,
686238fd1498Szrj 					   GOMP_TARGET_ARG_THREAD_LIMIT, t,
686338fd1498Szrj 					   &args);
686438fd1498Szrj 
686538fd1498Szrj   /* Add HSA-specific grid sizes, if available.  */
686638fd1498Szrj   if (omp_find_clause (gimple_omp_target_clauses (tgt_stmt),
686738fd1498Szrj 		       OMP_CLAUSE__GRIDDIM_))
686838fd1498Szrj     {
686938fd1498Szrj       int id = GOMP_TARGET_ARG_HSA_KERNEL_ATTRIBUTES;
687038fd1498Szrj       t = get_target_argument_identifier (GOMP_DEVICE_HSA, true, id);
687138fd1498Szrj       args.quick_push (t);
687238fd1498Szrj       args.quick_push (grid_get_kernel_launch_attributes (gsi, tgt_stmt));
687338fd1498Szrj     }
687438fd1498Szrj 
687538fd1498Szrj   /* Produce more, perhaps device specific, arguments here.  */
687638fd1498Szrj 
687738fd1498Szrj   tree argarray = create_tmp_var (build_array_type_nelts (ptr_type_node,
687838fd1498Szrj 							  args.length () + 1),
687938fd1498Szrj 				  ".omp_target_args");
688038fd1498Szrj   for (unsigned i = 0; i < args.length (); i++)
688138fd1498Szrj     {
688238fd1498Szrj       tree ref = build4 (ARRAY_REF, ptr_type_node, argarray,
688338fd1498Szrj 			 build_int_cst (integer_type_node, i),
688438fd1498Szrj 			 NULL_TREE, NULL_TREE);
688538fd1498Szrj       gsi_insert_before (gsi, gimple_build_assign (ref, args[i]),
688638fd1498Szrj 			 GSI_SAME_STMT);
688738fd1498Szrj     }
688838fd1498Szrj   tree ref = build4 (ARRAY_REF, ptr_type_node, argarray,
688938fd1498Szrj 		     build_int_cst (integer_type_node, args.length ()),
689038fd1498Szrj 		     NULL_TREE, NULL_TREE);
689138fd1498Szrj   gsi_insert_before (gsi, gimple_build_assign (ref, null_pointer_node),
689238fd1498Szrj 		     GSI_SAME_STMT);
689338fd1498Szrj   TREE_ADDRESSABLE (argarray) = 1;
689438fd1498Szrj   return build_fold_addr_expr (argarray);
689538fd1498Szrj }
689638fd1498Szrj 
689738fd1498Szrj /* Expand the GIMPLE_OMP_TARGET starting at REGION.  */
689838fd1498Szrj 
689938fd1498Szrj static void
expand_omp_target(struct omp_region * region)690038fd1498Szrj expand_omp_target (struct omp_region *region)
690138fd1498Szrj {
690238fd1498Szrj   basic_block entry_bb, exit_bb, new_bb;
690338fd1498Szrj   struct function *child_cfun;
690438fd1498Szrj   tree child_fn, block, t;
690538fd1498Szrj   gimple_stmt_iterator gsi;
690638fd1498Szrj   gomp_target *entry_stmt;
690738fd1498Szrj   gimple *stmt;
690838fd1498Szrj   edge e;
690938fd1498Szrj   bool offloaded, data_region;
691038fd1498Szrj 
691138fd1498Szrj   entry_stmt = as_a <gomp_target *> (last_stmt (region->entry));
691238fd1498Szrj   new_bb = region->entry;
691338fd1498Szrj 
691438fd1498Szrj   offloaded = is_gimple_omp_offloaded (entry_stmt);
691538fd1498Szrj   switch (gimple_omp_target_kind (entry_stmt))
691638fd1498Szrj     {
691738fd1498Szrj     case GF_OMP_TARGET_KIND_REGION:
691838fd1498Szrj     case GF_OMP_TARGET_KIND_UPDATE:
691938fd1498Szrj     case GF_OMP_TARGET_KIND_ENTER_DATA:
692038fd1498Szrj     case GF_OMP_TARGET_KIND_EXIT_DATA:
692138fd1498Szrj     case GF_OMP_TARGET_KIND_OACC_PARALLEL:
692238fd1498Szrj     case GF_OMP_TARGET_KIND_OACC_KERNELS:
692338fd1498Szrj     case GF_OMP_TARGET_KIND_OACC_UPDATE:
692438fd1498Szrj     case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
692538fd1498Szrj     case GF_OMP_TARGET_KIND_OACC_DECLARE:
692638fd1498Szrj       data_region = false;
692738fd1498Szrj       break;
692838fd1498Szrj     case GF_OMP_TARGET_KIND_DATA:
692938fd1498Szrj     case GF_OMP_TARGET_KIND_OACC_DATA:
693038fd1498Szrj     case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
693138fd1498Szrj       data_region = true;
693238fd1498Szrj       break;
693338fd1498Szrj     default:
693438fd1498Szrj       gcc_unreachable ();
693538fd1498Szrj     }
693638fd1498Szrj 
693738fd1498Szrj   child_fn = NULL_TREE;
693838fd1498Szrj   child_cfun = NULL;
693938fd1498Szrj   if (offloaded)
694038fd1498Szrj     {
694138fd1498Szrj       child_fn = gimple_omp_target_child_fn (entry_stmt);
694238fd1498Szrj       child_cfun = DECL_STRUCT_FUNCTION (child_fn);
694338fd1498Szrj     }
694438fd1498Szrj 
694538fd1498Szrj   /* Supported by expand_omp_taskreg, but not here.  */
694638fd1498Szrj   if (child_cfun != NULL)
694738fd1498Szrj     gcc_checking_assert (!child_cfun->cfg);
694838fd1498Szrj   gcc_checking_assert (!gimple_in_ssa_p (cfun));
694938fd1498Szrj 
695038fd1498Szrj   entry_bb = region->entry;
695138fd1498Szrj   exit_bb = region->exit;
695238fd1498Szrj 
695338fd1498Szrj   if (gimple_omp_target_kind (entry_stmt) == GF_OMP_TARGET_KIND_OACC_KERNELS)
695438fd1498Szrj     {
695538fd1498Szrj       mark_loops_in_oacc_kernels_region (region->entry, region->exit);
695638fd1498Szrj 
695738fd1498Szrj       /* Further down, both OpenACC kernels and OpenACC parallel constructs
695838fd1498Szrj 	 will be mappted to BUILT_IN_GOACC_PARALLEL, and to distinguish the
695938fd1498Szrj 	 two, there is an "oacc kernels" attribute set for OpenACC kernels.  */
696038fd1498Szrj       DECL_ATTRIBUTES (child_fn)
696138fd1498Szrj 	= tree_cons (get_identifier ("oacc kernels"),
696238fd1498Szrj 		     NULL_TREE, DECL_ATTRIBUTES (child_fn));
696338fd1498Szrj     }
696438fd1498Szrj 
696538fd1498Szrj   if (offloaded)
696638fd1498Szrj     {
696738fd1498Szrj       unsigned srcidx, dstidx, num;
696838fd1498Szrj 
696938fd1498Szrj       /* If the offloading region needs data sent from the parent
697038fd1498Szrj 	 function, then the very first statement (except possible
697138fd1498Szrj 	 tree profile counter updates) of the offloading body
697238fd1498Szrj 	 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O.  Since
697338fd1498Szrj 	 &.OMP_DATA_O is passed as an argument to the child function,
697438fd1498Szrj 	 we need to replace it with the argument as seen by the child
697538fd1498Szrj 	 function.
697638fd1498Szrj 
697738fd1498Szrj 	 In most cases, this will end up being the identity assignment
697838fd1498Szrj 	 .OMP_DATA_I = .OMP_DATA_I.  However, if the offloading body had
697938fd1498Szrj 	 a function call that has been inlined, the original PARM_DECL
698038fd1498Szrj 	 .OMP_DATA_I may have been converted into a different local
698138fd1498Szrj 	 variable.  In which case, we need to keep the assignment.  */
698238fd1498Szrj       tree data_arg = gimple_omp_target_data_arg (entry_stmt);
698338fd1498Szrj       if (data_arg)
698438fd1498Szrj 	{
698538fd1498Szrj 	  basic_block entry_succ_bb = single_succ (entry_bb);
698638fd1498Szrj 	  gimple_stmt_iterator gsi;
698738fd1498Szrj 	  tree arg;
698838fd1498Szrj 	  gimple *tgtcopy_stmt = NULL;
698938fd1498Szrj 	  tree sender = TREE_VEC_ELT (data_arg, 0);
699038fd1498Szrj 
699138fd1498Szrj 	  for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
699238fd1498Szrj 	    {
699338fd1498Szrj 	      gcc_assert (!gsi_end_p (gsi));
699438fd1498Szrj 	      stmt = gsi_stmt (gsi);
699538fd1498Szrj 	      if (gimple_code (stmt) != GIMPLE_ASSIGN)
699638fd1498Szrj 		continue;
699738fd1498Szrj 
699838fd1498Szrj 	      if (gimple_num_ops (stmt) == 2)
699938fd1498Szrj 		{
700038fd1498Szrj 		  tree arg = gimple_assign_rhs1 (stmt);
700138fd1498Szrj 
700238fd1498Szrj 		  /* We're ignoring the subcode because we're
700338fd1498Szrj 		     effectively doing a STRIP_NOPS.  */
700438fd1498Szrj 
700538fd1498Szrj 		  if (TREE_CODE (arg) == ADDR_EXPR
700638fd1498Szrj 		      && TREE_OPERAND (arg, 0) == sender)
700738fd1498Szrj 		    {
700838fd1498Szrj 		      tgtcopy_stmt = stmt;
700938fd1498Szrj 		      break;
701038fd1498Szrj 		    }
701138fd1498Szrj 		}
701238fd1498Szrj 	    }
701338fd1498Szrj 
701438fd1498Szrj 	  gcc_assert (tgtcopy_stmt != NULL);
701538fd1498Szrj 	  arg = DECL_ARGUMENTS (child_fn);
701638fd1498Szrj 
701738fd1498Szrj 	  gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
701838fd1498Szrj 	  gsi_remove (&gsi, true);
701938fd1498Szrj 	}
702038fd1498Szrj 
702138fd1498Szrj       /* Declare local variables needed in CHILD_CFUN.  */
702238fd1498Szrj       block = DECL_INITIAL (child_fn);
702338fd1498Szrj       BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
702438fd1498Szrj       /* The gimplifier could record temporaries in the offloading block
702538fd1498Szrj 	 rather than in containing function's local_decls chain,
702638fd1498Szrj 	 which would mean cgraph missed finalizing them.  Do it now.  */
702738fd1498Szrj       for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
702838fd1498Szrj 	if (VAR_P (t) && TREE_STATIC (t) && !DECL_EXTERNAL (t))
702938fd1498Szrj 	  varpool_node::finalize_decl (t);
703038fd1498Szrj       DECL_SAVED_TREE (child_fn) = NULL;
703138fd1498Szrj       /* We'll create a CFG for child_fn, so no gimple body is needed.  */
703238fd1498Szrj       gimple_set_body (child_fn, NULL);
703338fd1498Szrj       TREE_USED (block) = 1;
703438fd1498Szrj 
703538fd1498Szrj       /* Reset DECL_CONTEXT on function arguments.  */
703638fd1498Szrj       for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
703738fd1498Szrj 	DECL_CONTEXT (t) = child_fn;
703838fd1498Szrj 
703938fd1498Szrj       /* Split ENTRY_BB at GIMPLE_*,
704038fd1498Szrj 	 so that it can be moved to the child function.  */
704138fd1498Szrj       gsi = gsi_last_nondebug_bb (entry_bb);
704238fd1498Szrj       stmt = gsi_stmt (gsi);
704338fd1498Szrj       gcc_assert (stmt
704438fd1498Szrj 		  && gimple_code (stmt) == gimple_code (entry_stmt));
704538fd1498Szrj       e = split_block (entry_bb, stmt);
704638fd1498Szrj       gsi_remove (&gsi, true);
704738fd1498Szrj       entry_bb = e->dest;
704838fd1498Szrj       single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
704938fd1498Szrj 
705038fd1498Szrj       /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR.  */
705138fd1498Szrj       if (exit_bb)
705238fd1498Szrj 	{
705338fd1498Szrj 	  gsi = gsi_last_nondebug_bb (exit_bb);
705438fd1498Szrj 	  gcc_assert (!gsi_end_p (gsi)
705538fd1498Szrj 		      && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
705638fd1498Szrj 	  stmt = gimple_build_return (NULL);
705738fd1498Szrj 	  gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
705838fd1498Szrj 	  gsi_remove (&gsi, true);
705938fd1498Szrj 	}
706038fd1498Szrj 
706138fd1498Szrj       /* Move the offloading region into CHILD_CFUN.  */
706238fd1498Szrj 
706338fd1498Szrj       block = gimple_block (entry_stmt);
706438fd1498Szrj 
706538fd1498Szrj       new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
706638fd1498Szrj       if (exit_bb)
706738fd1498Szrj 	single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
706838fd1498Szrj       /* When the OMP expansion process cannot guarantee an up-to-date
706938fd1498Szrj 	 loop tree arrange for the child function to fixup loops.  */
707038fd1498Szrj       if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
707138fd1498Szrj 	child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
707238fd1498Szrj 
707338fd1498Szrj       /* Remove non-local VAR_DECLs from child_cfun->local_decls list.  */
707438fd1498Szrj       num = vec_safe_length (child_cfun->local_decls);
707538fd1498Szrj       for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
707638fd1498Szrj 	{
707738fd1498Szrj 	  t = (*child_cfun->local_decls)[srcidx];
707838fd1498Szrj 	  if (DECL_CONTEXT (t) == cfun->decl)
707938fd1498Szrj 	    continue;
708038fd1498Szrj 	  if (srcidx != dstidx)
708138fd1498Szrj 	    (*child_cfun->local_decls)[dstidx] = t;
708238fd1498Szrj 	  dstidx++;
708338fd1498Szrj 	}
708438fd1498Szrj       if (dstidx != num)
708538fd1498Szrj 	vec_safe_truncate (child_cfun->local_decls, dstidx);
708638fd1498Szrj 
708738fd1498Szrj       /* Inform the callgraph about the new function.  */
708838fd1498Szrj       child_cfun->curr_properties = cfun->curr_properties;
708938fd1498Szrj       child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
709038fd1498Szrj       child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
709138fd1498Szrj       cgraph_node *node = cgraph_node::get_create (child_fn);
709238fd1498Szrj       node->parallelized_function = 1;
709338fd1498Szrj       cgraph_node::add_new_function (child_fn, true);
709438fd1498Szrj 
709538fd1498Szrj       /* Add the new function to the offload table.  */
709638fd1498Szrj       if (ENABLE_OFFLOADING)
709738fd1498Szrj 	{
709838fd1498Szrj 	  if (in_lto_p)
709938fd1498Szrj 	    DECL_PRESERVE_P (child_fn) = 1;
710038fd1498Szrj 	  vec_safe_push (offload_funcs, child_fn);
710138fd1498Szrj 	}
710238fd1498Szrj 
710338fd1498Szrj       bool need_asm = DECL_ASSEMBLER_NAME_SET_P (current_function_decl)
710438fd1498Szrj 		      && !DECL_ASSEMBLER_NAME_SET_P (child_fn);
710538fd1498Szrj 
710638fd1498Szrj       /* Fix the callgraph edges for child_cfun.  Those for cfun will be
710738fd1498Szrj 	 fixed in a following pass.  */
710838fd1498Szrj       push_cfun (child_cfun);
710938fd1498Szrj       if (need_asm)
711038fd1498Szrj 	assign_assembler_name_if_needed (child_fn);
711138fd1498Szrj       cgraph_edge::rebuild_edges ();
711238fd1498Szrj 
711338fd1498Szrj       /* Some EH regions might become dead, see PR34608.  If
711438fd1498Szrj 	 pass_cleanup_cfg isn't the first pass to happen with the
711538fd1498Szrj 	 new child, these dead EH edges might cause problems.
711638fd1498Szrj 	 Clean them up now.  */
711738fd1498Szrj       if (flag_exceptions)
711838fd1498Szrj 	{
711938fd1498Szrj 	  basic_block bb;
712038fd1498Szrj 	  bool changed = false;
712138fd1498Szrj 
712238fd1498Szrj 	  FOR_EACH_BB_FN (bb, cfun)
712338fd1498Szrj 	    changed |= gimple_purge_dead_eh_edges (bb);
712438fd1498Szrj 	  if (changed)
712538fd1498Szrj 	    cleanup_tree_cfg ();
712638fd1498Szrj 	}
712738fd1498Szrj       if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
712838fd1498Szrj 	verify_loop_structure ();
712938fd1498Szrj       pop_cfun ();
713038fd1498Szrj 
713138fd1498Szrj       if (dump_file && !gimple_in_ssa_p (cfun))
713238fd1498Szrj 	{
713338fd1498Szrj 	  omp_any_child_fn_dumped = true;
713438fd1498Szrj 	  dump_function_header (dump_file, child_fn, dump_flags);
713538fd1498Szrj 	  dump_function_to_file (child_fn, dump_file, dump_flags);
713638fd1498Szrj 	}
7137*58e805e6Szrj 
7138*58e805e6Szrj       adjust_context_and_scope (region, gimple_block (entry_stmt), child_fn);
713938fd1498Szrj     }
714038fd1498Szrj 
714138fd1498Szrj   /* Emit a library call to launch the offloading region, or do data
714238fd1498Szrj      transfers.  */
714338fd1498Szrj   tree t1, t2, t3, t4, device, cond, depend, c, clauses;
714438fd1498Szrj   enum built_in_function start_ix;
714538fd1498Szrj   location_t clause_loc;
714638fd1498Szrj   unsigned int flags_i = 0;
714738fd1498Szrj 
714838fd1498Szrj   switch (gimple_omp_target_kind (entry_stmt))
714938fd1498Szrj     {
715038fd1498Szrj     case GF_OMP_TARGET_KIND_REGION:
715138fd1498Szrj       start_ix = BUILT_IN_GOMP_TARGET;
715238fd1498Szrj       break;
715338fd1498Szrj     case GF_OMP_TARGET_KIND_DATA:
715438fd1498Szrj       start_ix = BUILT_IN_GOMP_TARGET_DATA;
715538fd1498Szrj       break;
715638fd1498Szrj     case GF_OMP_TARGET_KIND_UPDATE:
715738fd1498Szrj       start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
715838fd1498Szrj       break;
715938fd1498Szrj     case GF_OMP_TARGET_KIND_ENTER_DATA:
716038fd1498Szrj       start_ix = BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA;
716138fd1498Szrj       break;
716238fd1498Szrj     case GF_OMP_TARGET_KIND_EXIT_DATA:
716338fd1498Szrj       start_ix = BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA;
716438fd1498Szrj       flags_i |= GOMP_TARGET_FLAG_EXIT_DATA;
716538fd1498Szrj       break;
716638fd1498Szrj     case GF_OMP_TARGET_KIND_OACC_KERNELS:
716738fd1498Szrj     case GF_OMP_TARGET_KIND_OACC_PARALLEL:
716838fd1498Szrj       start_ix = BUILT_IN_GOACC_PARALLEL;
716938fd1498Szrj       break;
717038fd1498Szrj     case GF_OMP_TARGET_KIND_OACC_DATA:
717138fd1498Szrj     case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
717238fd1498Szrj       start_ix = BUILT_IN_GOACC_DATA_START;
717338fd1498Szrj       break;
717438fd1498Szrj     case GF_OMP_TARGET_KIND_OACC_UPDATE:
717538fd1498Szrj       start_ix = BUILT_IN_GOACC_UPDATE;
717638fd1498Szrj       break;
717738fd1498Szrj     case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
717838fd1498Szrj       start_ix = BUILT_IN_GOACC_ENTER_EXIT_DATA;
717938fd1498Szrj       break;
718038fd1498Szrj     case GF_OMP_TARGET_KIND_OACC_DECLARE:
718138fd1498Szrj       start_ix = BUILT_IN_GOACC_DECLARE;
718238fd1498Szrj       break;
718338fd1498Szrj     default:
718438fd1498Szrj       gcc_unreachable ();
718538fd1498Szrj     }
718638fd1498Szrj 
718738fd1498Szrj   clauses = gimple_omp_target_clauses (entry_stmt);
718838fd1498Szrj 
718938fd1498Szrj   /* By default, the value of DEVICE is GOMP_DEVICE_ICV (let runtime
719038fd1498Szrj      library choose) and there is no conditional.  */
719138fd1498Szrj   cond = NULL_TREE;
719238fd1498Szrj   device = build_int_cst (integer_type_node, GOMP_DEVICE_ICV);
719338fd1498Szrj 
719438fd1498Szrj   c = omp_find_clause (clauses, OMP_CLAUSE_IF);
719538fd1498Szrj   if (c)
719638fd1498Szrj     cond = OMP_CLAUSE_IF_EXPR (c);
719738fd1498Szrj 
719838fd1498Szrj   c = omp_find_clause (clauses, OMP_CLAUSE_DEVICE);
719938fd1498Szrj   if (c)
720038fd1498Szrj     {
720138fd1498Szrj       /* Even if we pass it to all library function calls, it is currently only
720238fd1498Szrj 	 defined/used for the OpenMP target ones.  */
720338fd1498Szrj       gcc_checking_assert (start_ix == BUILT_IN_GOMP_TARGET
720438fd1498Szrj 			   || start_ix == BUILT_IN_GOMP_TARGET_DATA
720538fd1498Szrj 			   || start_ix == BUILT_IN_GOMP_TARGET_UPDATE
720638fd1498Szrj 			   || start_ix == BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA);
720738fd1498Szrj 
720838fd1498Szrj       device = OMP_CLAUSE_DEVICE_ID (c);
720938fd1498Szrj       clause_loc = OMP_CLAUSE_LOCATION (c);
721038fd1498Szrj     }
721138fd1498Szrj   else
721238fd1498Szrj     clause_loc = gimple_location (entry_stmt);
721338fd1498Szrj 
721438fd1498Szrj   c = omp_find_clause (clauses, OMP_CLAUSE_NOWAIT);
721538fd1498Szrj   if (c)
721638fd1498Szrj     flags_i |= GOMP_TARGET_FLAG_NOWAIT;
721738fd1498Szrj 
721838fd1498Szrj   /* Ensure 'device' is of the correct type.  */
721938fd1498Szrj   device = fold_convert_loc (clause_loc, integer_type_node, device);
722038fd1498Szrj 
722138fd1498Szrj   /* If we found the clause 'if (cond)', build
722238fd1498Szrj      (cond ? device : GOMP_DEVICE_HOST_FALLBACK).  */
722338fd1498Szrj   if (cond)
722438fd1498Szrj     {
722538fd1498Szrj       cond = gimple_boolify (cond);
722638fd1498Szrj 
722738fd1498Szrj       basic_block cond_bb, then_bb, else_bb;
722838fd1498Szrj       edge e;
722938fd1498Szrj       tree tmp_var;
723038fd1498Szrj 
723138fd1498Szrj       tmp_var = create_tmp_var (TREE_TYPE (device));
723238fd1498Szrj       if (offloaded)
723338fd1498Szrj 	e = split_block_after_labels (new_bb);
723438fd1498Szrj       else
723538fd1498Szrj 	{
723638fd1498Szrj 	  gsi = gsi_last_nondebug_bb (new_bb);
723738fd1498Szrj 	  gsi_prev (&gsi);
723838fd1498Szrj 	  e = split_block (new_bb, gsi_stmt (gsi));
723938fd1498Szrj 	}
724038fd1498Szrj       cond_bb = e->src;
724138fd1498Szrj       new_bb = e->dest;
724238fd1498Szrj       remove_edge (e);
724338fd1498Szrj 
724438fd1498Szrj       then_bb = create_empty_bb (cond_bb);
724538fd1498Szrj       else_bb = create_empty_bb (then_bb);
724638fd1498Szrj       set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
724738fd1498Szrj       set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
724838fd1498Szrj 
724938fd1498Szrj       stmt = gimple_build_cond_empty (cond);
725038fd1498Szrj       gsi = gsi_last_bb (cond_bb);
725138fd1498Szrj       gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
725238fd1498Szrj 
725338fd1498Szrj       gsi = gsi_start_bb (then_bb);
725438fd1498Szrj       stmt = gimple_build_assign (tmp_var, device);
725538fd1498Szrj       gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
725638fd1498Szrj 
725738fd1498Szrj       gsi = gsi_start_bb (else_bb);
725838fd1498Szrj       stmt = gimple_build_assign (tmp_var,
725938fd1498Szrj 				  build_int_cst (integer_type_node,
726038fd1498Szrj 						 GOMP_DEVICE_HOST_FALLBACK));
726138fd1498Szrj       gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
726238fd1498Szrj 
726338fd1498Szrj       make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
726438fd1498Szrj       make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
726538fd1498Szrj       add_bb_to_loop (then_bb, cond_bb->loop_father);
726638fd1498Szrj       add_bb_to_loop (else_bb, cond_bb->loop_father);
726738fd1498Szrj       make_edge (then_bb, new_bb, EDGE_FALLTHRU);
726838fd1498Szrj       make_edge (else_bb, new_bb, EDGE_FALLTHRU);
726938fd1498Szrj 
727038fd1498Szrj       device = tmp_var;
727138fd1498Szrj       gsi = gsi_last_nondebug_bb (new_bb);
727238fd1498Szrj     }
727338fd1498Szrj   else
727438fd1498Szrj     {
727538fd1498Szrj       gsi = gsi_last_nondebug_bb (new_bb);
727638fd1498Szrj       device = force_gimple_operand_gsi (&gsi, device, true, NULL_TREE,
727738fd1498Szrj 					 true, GSI_SAME_STMT);
727838fd1498Szrj     }
727938fd1498Szrj 
728038fd1498Szrj   t = gimple_omp_target_data_arg (entry_stmt);
728138fd1498Szrj   if (t == NULL)
728238fd1498Szrj     {
728338fd1498Szrj       t1 = size_zero_node;
728438fd1498Szrj       t2 = build_zero_cst (ptr_type_node);
728538fd1498Szrj       t3 = t2;
728638fd1498Szrj       t4 = t2;
728738fd1498Szrj     }
728838fd1498Szrj   else
728938fd1498Szrj     {
729038fd1498Szrj       t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
729138fd1498Szrj       t1 = size_binop (PLUS_EXPR, t1, size_int (1));
729238fd1498Szrj       t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
729338fd1498Szrj       t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
729438fd1498Szrj       t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
729538fd1498Szrj     }
729638fd1498Szrj 
729738fd1498Szrj   gimple *g;
729838fd1498Szrj   bool tagging = false;
729938fd1498Szrj   /* The maximum number used by any start_ix, without varargs.  */
730038fd1498Szrj   auto_vec<tree, 11> args;
730138fd1498Szrj   args.quick_push (device);
730238fd1498Szrj   if (offloaded)
730338fd1498Szrj     args.quick_push (build_fold_addr_expr (child_fn));
730438fd1498Szrj   args.quick_push (t1);
730538fd1498Szrj   args.quick_push (t2);
730638fd1498Szrj   args.quick_push (t3);
730738fd1498Szrj   args.quick_push (t4);
730838fd1498Szrj   switch (start_ix)
730938fd1498Szrj     {
731038fd1498Szrj     case BUILT_IN_GOACC_DATA_START:
731138fd1498Szrj     case BUILT_IN_GOACC_DECLARE:
731238fd1498Szrj     case BUILT_IN_GOMP_TARGET_DATA:
731338fd1498Szrj       break;
731438fd1498Szrj     case BUILT_IN_GOMP_TARGET:
731538fd1498Szrj     case BUILT_IN_GOMP_TARGET_UPDATE:
731638fd1498Szrj     case BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA:
731738fd1498Szrj       args.quick_push (build_int_cst (unsigned_type_node, flags_i));
731838fd1498Szrj       c = omp_find_clause (clauses, OMP_CLAUSE_DEPEND);
731938fd1498Szrj       if (c)
732038fd1498Szrj 	depend = OMP_CLAUSE_DECL (c);
732138fd1498Szrj       else
732238fd1498Szrj 	depend = build_int_cst (ptr_type_node, 0);
732338fd1498Szrj       args.quick_push (depend);
732438fd1498Szrj       if (start_ix == BUILT_IN_GOMP_TARGET)
732538fd1498Szrj 	args.quick_push (get_target_arguments (&gsi, entry_stmt));
732638fd1498Szrj       break;
732738fd1498Szrj     case BUILT_IN_GOACC_PARALLEL:
732838fd1498Szrj       oacc_set_fn_attrib (child_fn, clauses, &args);
732938fd1498Szrj       tagging = true;
733038fd1498Szrj       /* FALLTHRU */
733138fd1498Szrj     case BUILT_IN_GOACC_ENTER_EXIT_DATA:
733238fd1498Szrj     case BUILT_IN_GOACC_UPDATE:
733338fd1498Szrj       {
733438fd1498Szrj 	tree t_async = NULL_TREE;
733538fd1498Szrj 
733638fd1498Szrj 	/* If present, use the value specified by the respective
733738fd1498Szrj 	   clause, making sure that is of the correct type.  */
733838fd1498Szrj 	c = omp_find_clause (clauses, OMP_CLAUSE_ASYNC);
733938fd1498Szrj 	if (c)
734038fd1498Szrj 	  t_async = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
734138fd1498Szrj 				      integer_type_node,
734238fd1498Szrj 				      OMP_CLAUSE_ASYNC_EXPR (c));
734338fd1498Szrj 	else if (!tagging)
734438fd1498Szrj 	  /* Default values for t_async.  */
734538fd1498Szrj 	  t_async = fold_convert_loc (gimple_location (entry_stmt),
734638fd1498Szrj 				      integer_type_node,
734738fd1498Szrj 				      build_int_cst (integer_type_node,
734838fd1498Szrj 						     GOMP_ASYNC_SYNC));
734938fd1498Szrj 	if (tagging && t_async)
735038fd1498Szrj 	  {
735138fd1498Szrj 	    unsigned HOST_WIDE_INT i_async = GOMP_LAUNCH_OP_MAX;
735238fd1498Szrj 
735338fd1498Szrj 	    if (TREE_CODE (t_async) == INTEGER_CST)
735438fd1498Szrj 	      {
735538fd1498Szrj 		/* See if we can pack the async arg in to the tag's
735638fd1498Szrj 		   operand.  */
735738fd1498Szrj 		i_async = TREE_INT_CST_LOW (t_async);
735838fd1498Szrj 		if (i_async < GOMP_LAUNCH_OP_MAX)
735938fd1498Szrj 		  t_async = NULL_TREE;
736038fd1498Szrj 		else
736138fd1498Szrj 		  i_async = GOMP_LAUNCH_OP_MAX;
736238fd1498Szrj 	      }
736338fd1498Szrj 	    args.safe_push (oacc_launch_pack (GOMP_LAUNCH_ASYNC, NULL_TREE,
736438fd1498Szrj 					      i_async));
736538fd1498Szrj 	  }
736638fd1498Szrj 	if (t_async)
736738fd1498Szrj 	  args.safe_push (t_async);
736838fd1498Szrj 
736938fd1498Szrj 	/* Save the argument index, and ... */
737038fd1498Szrj 	unsigned t_wait_idx = args.length ();
737138fd1498Szrj 	unsigned num_waits = 0;
737238fd1498Szrj 	c = omp_find_clause (clauses, OMP_CLAUSE_WAIT);
737338fd1498Szrj 	if (!tagging || c)
737438fd1498Szrj 	  /* ... push a placeholder.  */
737538fd1498Szrj 	  args.safe_push (integer_zero_node);
737638fd1498Szrj 
737738fd1498Szrj 	for (; c; c = OMP_CLAUSE_CHAIN (c))
737838fd1498Szrj 	  if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_WAIT)
737938fd1498Szrj 	    {
738038fd1498Szrj 	      args.safe_push (fold_convert_loc (OMP_CLAUSE_LOCATION (c),
738138fd1498Szrj 						integer_type_node,
738238fd1498Szrj 						OMP_CLAUSE_WAIT_EXPR (c)));
738338fd1498Szrj 	      num_waits++;
738438fd1498Szrj 	    }
738538fd1498Szrj 
738638fd1498Szrj 	if (!tagging || num_waits)
738738fd1498Szrj 	  {
738838fd1498Szrj 	    tree len;
738938fd1498Szrj 
739038fd1498Szrj 	    /* Now that we know the number, update the placeholder.  */
739138fd1498Szrj 	    if (tagging)
739238fd1498Szrj 	      len = oacc_launch_pack (GOMP_LAUNCH_WAIT, NULL_TREE, num_waits);
739338fd1498Szrj 	    else
739438fd1498Szrj 	      len = build_int_cst (integer_type_node, num_waits);
739538fd1498Szrj 	    len = fold_convert_loc (gimple_location (entry_stmt),
739638fd1498Szrj 				    unsigned_type_node, len);
739738fd1498Szrj 	    args[t_wait_idx] = len;
739838fd1498Szrj 	  }
739938fd1498Szrj       }
740038fd1498Szrj       break;
740138fd1498Szrj     default:
740238fd1498Szrj       gcc_unreachable ();
740338fd1498Szrj     }
740438fd1498Szrj   if (tagging)
740538fd1498Szrj     /*  Push terminal marker - zero.  */
740638fd1498Szrj     args.safe_push (oacc_launch_pack (0, NULL_TREE, 0));
740738fd1498Szrj 
740838fd1498Szrj   g = gimple_build_call_vec (builtin_decl_explicit (start_ix), args);
740938fd1498Szrj   gimple_set_location (g, gimple_location (entry_stmt));
741038fd1498Szrj   gsi_insert_before (&gsi, g, GSI_SAME_STMT);
741138fd1498Szrj   if (!offloaded)
741238fd1498Szrj     {
741338fd1498Szrj       g = gsi_stmt (gsi);
741438fd1498Szrj       gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
741538fd1498Szrj       gsi_remove (&gsi, true);
741638fd1498Szrj     }
741738fd1498Szrj   if (data_region && region->exit)
741838fd1498Szrj     {
741938fd1498Szrj       gsi = gsi_last_nondebug_bb (region->exit);
742038fd1498Szrj       g = gsi_stmt (gsi);
742138fd1498Szrj       gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
742238fd1498Szrj       gsi_remove (&gsi, true);
742338fd1498Szrj     }
742438fd1498Szrj }
742538fd1498Szrj 
742638fd1498Szrj /* Expand KFOR loop as a HSA grifidied kernel, i.e. as a body only with
742738fd1498Szrj    iteration variable derived from the thread number.  INTRA_GROUP means this
742838fd1498Szrj    is an expansion of a loop iterating over work-items within a separate
742938fd1498Szrj    iteration over groups.  */
743038fd1498Szrj 
743138fd1498Szrj static void
grid_expand_omp_for_loop(struct omp_region * kfor,bool intra_group)743238fd1498Szrj grid_expand_omp_for_loop (struct omp_region *kfor, bool intra_group)
743338fd1498Szrj {
743438fd1498Szrj   gimple_stmt_iterator gsi;
743538fd1498Szrj   gomp_for *for_stmt = as_a <gomp_for *> (last_stmt (kfor->entry));
743638fd1498Szrj   gcc_checking_assert (gimple_omp_for_kind (for_stmt)
743738fd1498Szrj 		       == GF_OMP_FOR_KIND_GRID_LOOP);
743838fd1498Szrj   size_t collapse = gimple_omp_for_collapse (for_stmt);
743938fd1498Szrj   struct omp_for_data_loop *loops
744038fd1498Szrj     = XALLOCAVEC (struct omp_for_data_loop,
744138fd1498Szrj 		  gimple_omp_for_collapse (for_stmt));
744238fd1498Szrj   struct omp_for_data fd;
744338fd1498Szrj 
744438fd1498Szrj   remove_edge (BRANCH_EDGE (kfor->entry));
744538fd1498Szrj   basic_block body_bb = FALLTHRU_EDGE (kfor->entry)->dest;
744638fd1498Szrj 
744738fd1498Szrj   gcc_assert (kfor->cont);
744838fd1498Szrj   omp_extract_for_data (for_stmt, &fd, loops);
744938fd1498Szrj 
745038fd1498Szrj   gsi = gsi_start_bb (body_bb);
745138fd1498Szrj 
745238fd1498Szrj   for (size_t dim = 0; dim < collapse; dim++)
745338fd1498Szrj     {
745438fd1498Szrj       tree type, itype;
745538fd1498Szrj       itype = type = TREE_TYPE (fd.loops[dim].v);
745638fd1498Szrj       if (POINTER_TYPE_P (type))
745738fd1498Szrj 	itype = signed_type_for (type);
745838fd1498Szrj 
745938fd1498Szrj       tree n1 = fd.loops[dim].n1;
746038fd1498Szrj       tree step = fd.loops[dim].step;
746138fd1498Szrj       n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
746238fd1498Szrj 				     true, NULL_TREE, true, GSI_SAME_STMT);
746338fd1498Szrj       step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
746438fd1498Szrj 				       true, NULL_TREE, true, GSI_SAME_STMT);
746538fd1498Szrj       tree threadid;
746638fd1498Szrj       if (gimple_omp_for_grid_group_iter (for_stmt))
746738fd1498Szrj 	{
746838fd1498Szrj 	  gcc_checking_assert (!intra_group);
746938fd1498Szrj 	  threadid = build_call_expr (builtin_decl_explicit
747038fd1498Szrj 				      (BUILT_IN_HSA_WORKGROUPID), 1,
747138fd1498Szrj 				      build_int_cstu (unsigned_type_node, dim));
747238fd1498Szrj 	}
747338fd1498Szrj       else if (intra_group)
747438fd1498Szrj 	threadid = build_call_expr (builtin_decl_explicit
747538fd1498Szrj 				    (BUILT_IN_HSA_WORKITEMID), 1,
747638fd1498Szrj 				    build_int_cstu (unsigned_type_node, dim));
747738fd1498Szrj       else
747838fd1498Szrj 	threadid = build_call_expr (builtin_decl_explicit
747938fd1498Szrj 				    (BUILT_IN_HSA_WORKITEMABSID), 1,
748038fd1498Szrj 				    build_int_cstu (unsigned_type_node, dim));
748138fd1498Szrj       threadid = fold_convert (itype, threadid);
748238fd1498Szrj       threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
748338fd1498Szrj 					   true, GSI_SAME_STMT);
748438fd1498Szrj 
748538fd1498Szrj       tree startvar = fd.loops[dim].v;
748638fd1498Szrj       tree t = fold_build2 (MULT_EXPR, itype, threadid, step);
748738fd1498Szrj       if (POINTER_TYPE_P (type))
748838fd1498Szrj 	t = fold_build_pointer_plus (n1, t);
748938fd1498Szrj       else
749038fd1498Szrj 	t = fold_build2 (PLUS_EXPR, type, t, n1);
749138fd1498Szrj       t = fold_convert (type, t);
749238fd1498Szrj       t = force_gimple_operand_gsi (&gsi, t,
749338fd1498Szrj 				    DECL_P (startvar)
749438fd1498Szrj 				    && TREE_ADDRESSABLE (startvar),
749538fd1498Szrj 				    NULL_TREE, true, GSI_SAME_STMT);
749638fd1498Szrj       gassign *assign_stmt = gimple_build_assign (startvar, t);
749738fd1498Szrj       gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
749838fd1498Szrj     }
749938fd1498Szrj   /* Remove the omp for statement.  */
750038fd1498Szrj   gsi = gsi_last_nondebug_bb (kfor->entry);
750138fd1498Szrj   gsi_remove (&gsi, true);
750238fd1498Szrj 
750338fd1498Szrj   /* Remove the GIMPLE_OMP_CONTINUE statement.  */
750438fd1498Szrj   gsi = gsi_last_nondebug_bb (kfor->cont);
750538fd1498Szrj   gcc_assert (!gsi_end_p (gsi)
750638fd1498Szrj 	      && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_CONTINUE);
750738fd1498Szrj   gsi_remove (&gsi, true);
750838fd1498Szrj 
750938fd1498Szrj   /* Replace the GIMPLE_OMP_RETURN with a barrier, if necessary.  */
751038fd1498Szrj   gsi = gsi_last_nondebug_bb (kfor->exit);
751138fd1498Szrj   gcc_assert (!gsi_end_p (gsi)
751238fd1498Szrj 	      && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
751338fd1498Szrj   if (intra_group)
751438fd1498Szrj     gsi_insert_before (&gsi, omp_build_barrier (NULL_TREE), GSI_SAME_STMT);
751538fd1498Szrj   gsi_remove (&gsi, true);
751638fd1498Szrj 
751738fd1498Szrj   /* Fixup the much simpler CFG.  */
751838fd1498Szrj   remove_edge (find_edge (kfor->cont, body_bb));
751938fd1498Szrj 
752038fd1498Szrj   if (kfor->cont != body_bb)
752138fd1498Szrj     set_immediate_dominator (CDI_DOMINATORS, kfor->cont, body_bb);
752238fd1498Szrj   set_immediate_dominator (CDI_DOMINATORS, kfor->exit, kfor->cont);
752338fd1498Szrj }
752438fd1498Szrj 
752538fd1498Szrj /* Structure passed to grid_remap_kernel_arg_accesses so that it can remap
752638fd1498Szrj    argument_decls.  */
752738fd1498Szrj 
752838fd1498Szrj struct grid_arg_decl_map
752938fd1498Szrj {
753038fd1498Szrj   tree old_arg;
753138fd1498Szrj   tree new_arg;
753238fd1498Szrj };
753338fd1498Szrj 
753438fd1498Szrj /* Invoked through walk_gimple_op, will remap all PARM_DECLs to the ones
753538fd1498Szrj    pertaining to kernel function.  */
753638fd1498Szrj 
753738fd1498Szrj static tree
grid_remap_kernel_arg_accesses(tree * tp,int * walk_subtrees,void * data)753838fd1498Szrj grid_remap_kernel_arg_accesses (tree *tp, int *walk_subtrees, void *data)
753938fd1498Szrj {
754038fd1498Szrj   struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
754138fd1498Szrj   struct grid_arg_decl_map *adm = (struct grid_arg_decl_map *) wi->info;
754238fd1498Szrj   tree t = *tp;
754338fd1498Szrj 
754438fd1498Szrj   if (t == adm->old_arg)
754538fd1498Szrj     *tp = adm->new_arg;
754638fd1498Szrj   *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
754738fd1498Szrj   return NULL_TREE;
754838fd1498Szrj }
754938fd1498Szrj 
755038fd1498Szrj /* If TARGET region contains a kernel body for loop, remove its region from the
755138fd1498Szrj    TARGET and expand it in HSA gridified kernel fashion.  */
755238fd1498Szrj 
755338fd1498Szrj static void
grid_expand_target_grid_body(struct omp_region * target)755438fd1498Szrj grid_expand_target_grid_body (struct omp_region *target)
755538fd1498Szrj {
755638fd1498Szrj   if (!hsa_gen_requested_p ())
755738fd1498Szrj     return;
755838fd1498Szrj 
755938fd1498Szrj   gomp_target *tgt_stmt = as_a <gomp_target *> (last_stmt (target->entry));
756038fd1498Szrj   struct omp_region **pp;
756138fd1498Szrj 
756238fd1498Szrj   for (pp = &target->inner; *pp; pp = &(*pp)->next)
756338fd1498Szrj     if ((*pp)->type == GIMPLE_OMP_GRID_BODY)
756438fd1498Szrj       break;
756538fd1498Szrj 
756638fd1498Szrj   struct omp_region *gpukernel = *pp;
756738fd1498Szrj 
756838fd1498Szrj   tree orig_child_fndecl = gimple_omp_target_child_fn (tgt_stmt);
756938fd1498Szrj   if (!gpukernel)
757038fd1498Szrj     {
757138fd1498Szrj       /* HSA cannot handle OACC stuff.  */
757238fd1498Szrj       if (gimple_omp_target_kind (tgt_stmt) != GF_OMP_TARGET_KIND_REGION)
757338fd1498Szrj 	return;
757438fd1498Szrj       gcc_checking_assert (orig_child_fndecl);
757538fd1498Szrj       gcc_assert (!omp_find_clause (gimple_omp_target_clauses (tgt_stmt),
757638fd1498Szrj 				    OMP_CLAUSE__GRIDDIM_));
757738fd1498Szrj       cgraph_node *n = cgraph_node::get (orig_child_fndecl);
757838fd1498Szrj 
757938fd1498Szrj       hsa_register_kernel (n);
758038fd1498Szrj       return;
758138fd1498Szrj     }
758238fd1498Szrj 
758338fd1498Szrj   gcc_assert (omp_find_clause (gimple_omp_target_clauses (tgt_stmt),
758438fd1498Szrj 			       OMP_CLAUSE__GRIDDIM_));
758538fd1498Szrj   tree inside_block
758638fd1498Szrj     = gimple_block (first_stmt (single_succ (gpukernel->entry)));
758738fd1498Szrj   *pp = gpukernel->next;
758838fd1498Szrj   for (pp = &gpukernel->inner; *pp; pp = &(*pp)->next)
758938fd1498Szrj     if ((*pp)->type == GIMPLE_OMP_FOR)
759038fd1498Szrj       break;
759138fd1498Szrj 
759238fd1498Szrj   struct omp_region *kfor = *pp;
759338fd1498Szrj   gcc_assert (kfor);
759438fd1498Szrj   gomp_for *for_stmt = as_a <gomp_for *> (last_stmt (kfor->entry));
759538fd1498Szrj   gcc_assert (gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_GRID_LOOP);
759638fd1498Szrj   *pp = kfor->next;
759738fd1498Szrj   if (kfor->inner)
759838fd1498Szrj     {
759938fd1498Szrj       if (gimple_omp_for_grid_group_iter (for_stmt))
760038fd1498Szrj 	{
760138fd1498Szrj 	  struct omp_region **next_pp;
760238fd1498Szrj 	  for (pp = &kfor->inner; *pp; pp = next_pp)
760338fd1498Szrj 	    {
760438fd1498Szrj 	      next_pp = &(*pp)->next;
760538fd1498Szrj 	      if ((*pp)->type != GIMPLE_OMP_FOR)
760638fd1498Szrj 		continue;
760738fd1498Szrj 	      gomp_for *inner = as_a <gomp_for *> (last_stmt ((*pp)->entry));
760838fd1498Szrj 	      gcc_assert (gimple_omp_for_kind (inner)
760938fd1498Szrj 			  == GF_OMP_FOR_KIND_GRID_LOOP);
761038fd1498Szrj 	      grid_expand_omp_for_loop (*pp, true);
761138fd1498Szrj 	      *pp = (*pp)->next;
761238fd1498Szrj 	      next_pp = pp;
761338fd1498Szrj 	    }
761438fd1498Szrj 	}
761538fd1498Szrj       expand_omp (kfor->inner);
761638fd1498Szrj     }
761738fd1498Szrj   if (gpukernel->inner)
761838fd1498Szrj     expand_omp (gpukernel->inner);
761938fd1498Szrj 
762038fd1498Szrj   tree kern_fndecl = copy_node (orig_child_fndecl);
762138fd1498Szrj   DECL_NAME (kern_fndecl) = clone_function_name (kern_fndecl, "kernel");
762238fd1498Szrj   SET_DECL_ASSEMBLER_NAME (kern_fndecl, DECL_NAME (kern_fndecl));
762338fd1498Szrj   tree tgtblock = gimple_block (tgt_stmt);
762438fd1498Szrj   tree fniniblock = make_node (BLOCK);
762538fd1498Szrj   BLOCK_ABSTRACT_ORIGIN (fniniblock) = tgtblock;
762638fd1498Szrj   BLOCK_SOURCE_LOCATION (fniniblock) = BLOCK_SOURCE_LOCATION (tgtblock);
762738fd1498Szrj   BLOCK_SOURCE_END_LOCATION (fniniblock) = BLOCK_SOURCE_END_LOCATION (tgtblock);
762838fd1498Szrj   BLOCK_SUPERCONTEXT (fniniblock) = kern_fndecl;
762938fd1498Szrj   DECL_INITIAL (kern_fndecl) = fniniblock;
763038fd1498Szrj   push_struct_function (kern_fndecl);
763138fd1498Szrj   cfun->function_end_locus = gimple_location (tgt_stmt);
763238fd1498Szrj   init_tree_ssa (cfun);
763338fd1498Szrj   pop_cfun ();
763438fd1498Szrj 
763538fd1498Szrj   tree old_parm_decl = DECL_ARGUMENTS (kern_fndecl);
763638fd1498Szrj   gcc_assert (!DECL_CHAIN (old_parm_decl));
763738fd1498Szrj   tree new_parm_decl = copy_node (DECL_ARGUMENTS (kern_fndecl));
763838fd1498Szrj   DECL_CONTEXT (new_parm_decl) = kern_fndecl;
763938fd1498Szrj   DECL_ARGUMENTS (kern_fndecl) = new_parm_decl;
764038fd1498Szrj   gcc_assert (VOID_TYPE_P (TREE_TYPE (DECL_RESULT (kern_fndecl))));
764138fd1498Szrj   DECL_RESULT (kern_fndecl) = copy_node (DECL_RESULT (kern_fndecl));
764238fd1498Szrj   DECL_CONTEXT (DECL_RESULT (kern_fndecl)) = kern_fndecl;
764338fd1498Szrj   struct function *kern_cfun = DECL_STRUCT_FUNCTION (kern_fndecl);
764438fd1498Szrj   kern_cfun->curr_properties = cfun->curr_properties;
764538fd1498Szrj 
764638fd1498Szrj   grid_expand_omp_for_loop (kfor, false);
764738fd1498Szrj 
764838fd1498Szrj   /* Remove the omp for statement.  */
764938fd1498Szrj   gimple_stmt_iterator gsi = gsi_last_nondebug_bb (gpukernel->entry);
765038fd1498Szrj   gsi_remove (&gsi, true);
765138fd1498Szrj   /* Replace the GIMPLE_OMP_RETURN at the end of the kernel region with a real
765238fd1498Szrj      return.  */
765338fd1498Szrj   gsi = gsi_last_nondebug_bb (gpukernel->exit);
765438fd1498Szrj   gcc_assert (!gsi_end_p (gsi)
765538fd1498Szrj 	      && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
765638fd1498Szrj   gimple *ret_stmt = gimple_build_return (NULL);
765738fd1498Szrj   gsi_insert_after (&gsi, ret_stmt, GSI_SAME_STMT);
765838fd1498Szrj   gsi_remove (&gsi, true);
765938fd1498Szrj 
766038fd1498Szrj   /* Statements in the first BB in the target construct have been produced by
766138fd1498Szrj      target lowering and must be copied inside the GPUKERNEL, with the two
766238fd1498Szrj      exceptions of the first OMP statement and the OMP_DATA assignment
766338fd1498Szrj      statement.  */
766438fd1498Szrj   gsi = gsi_start_bb (single_succ (gpukernel->entry));
766538fd1498Szrj   tree data_arg = gimple_omp_target_data_arg (tgt_stmt);
766638fd1498Szrj   tree sender = data_arg ? TREE_VEC_ELT (data_arg, 0) : NULL;
766738fd1498Szrj   for (gimple_stmt_iterator tsi = gsi_start_bb (single_succ (target->entry));
766838fd1498Szrj        !gsi_end_p (tsi); gsi_next (&tsi))
766938fd1498Szrj     {
767038fd1498Szrj       gimple *stmt = gsi_stmt (tsi);
767138fd1498Szrj       if (is_gimple_omp (stmt))
767238fd1498Szrj 	break;
767338fd1498Szrj       if (sender
767438fd1498Szrj 	  && is_gimple_assign (stmt)
767538fd1498Szrj 	  && TREE_CODE (gimple_assign_rhs1 (stmt)) == ADDR_EXPR
767638fd1498Szrj 	  && TREE_OPERAND (gimple_assign_rhs1 (stmt), 0) == sender)
767738fd1498Szrj 	continue;
767838fd1498Szrj       gimple *copy = gimple_copy (stmt);
767938fd1498Szrj       gsi_insert_before (&gsi, copy, GSI_SAME_STMT);
768038fd1498Szrj       gimple_set_block (copy, fniniblock);
768138fd1498Szrj     }
768238fd1498Szrj 
768338fd1498Szrj   move_sese_region_to_fn (kern_cfun, single_succ (gpukernel->entry),
768438fd1498Szrj 			  gpukernel->exit, inside_block);
768538fd1498Szrj 
768638fd1498Szrj   cgraph_node *kcn = cgraph_node::get_create (kern_fndecl);
768738fd1498Szrj   kcn->mark_force_output ();
768838fd1498Szrj   cgraph_node *orig_child = cgraph_node::get (orig_child_fndecl);
768938fd1498Szrj 
769038fd1498Szrj   hsa_register_kernel (kcn, orig_child);
769138fd1498Szrj 
769238fd1498Szrj   cgraph_node::add_new_function (kern_fndecl, true);
769338fd1498Szrj   push_cfun (kern_cfun);
769438fd1498Szrj   cgraph_edge::rebuild_edges ();
769538fd1498Szrj 
769638fd1498Szrj   /* Re-map any mention of the PARM_DECL of the original function to the
769738fd1498Szrj      PARM_DECL of the new one.
769838fd1498Szrj 
769938fd1498Szrj      TODO: It would be great if lowering produced references into the GPU
770038fd1498Szrj      kernel decl straight away and we did not have to do this.  */
770138fd1498Szrj   struct grid_arg_decl_map adm;
770238fd1498Szrj   adm.old_arg = old_parm_decl;
770338fd1498Szrj   adm.new_arg = new_parm_decl;
770438fd1498Szrj   basic_block bb;
770538fd1498Szrj   FOR_EACH_BB_FN (bb, kern_cfun)
770638fd1498Szrj     {
770738fd1498Szrj       for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
770838fd1498Szrj 	{
770938fd1498Szrj 	  gimple *stmt = gsi_stmt (gsi);
771038fd1498Szrj 	  struct walk_stmt_info wi;
771138fd1498Szrj 	  memset (&wi, 0, sizeof (wi));
771238fd1498Szrj 	  wi.info = &adm;
771338fd1498Szrj 	  walk_gimple_op (stmt, grid_remap_kernel_arg_accesses, &wi);
771438fd1498Szrj 	}
771538fd1498Szrj     }
771638fd1498Szrj   pop_cfun ();
771738fd1498Szrj 
771838fd1498Szrj   return;
771938fd1498Szrj }
772038fd1498Szrj 
772138fd1498Szrj /* Expand the parallel region tree rooted at REGION.  Expansion
772238fd1498Szrj    proceeds in depth-first order.  Innermost regions are expanded
772338fd1498Szrj    first.  This way, parallel regions that require a new function to
772438fd1498Szrj    be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
772538fd1498Szrj    internal dependencies in their body.  */
772638fd1498Szrj 
772738fd1498Szrj static void
expand_omp(struct omp_region * region)772838fd1498Szrj expand_omp (struct omp_region *region)
772938fd1498Szrj {
773038fd1498Szrj   omp_any_child_fn_dumped = false;
773138fd1498Szrj   while (region)
773238fd1498Szrj     {
773338fd1498Szrj       location_t saved_location;
773438fd1498Szrj       gimple *inner_stmt = NULL;
773538fd1498Szrj 
773638fd1498Szrj       /* First, determine whether this is a combined parallel+workshare
773738fd1498Szrj 	 region.  */
773838fd1498Szrj       if (region->type == GIMPLE_OMP_PARALLEL)
773938fd1498Szrj 	determine_parallel_type (region);
774038fd1498Szrj       else if (region->type == GIMPLE_OMP_TARGET)
774138fd1498Szrj 	grid_expand_target_grid_body (region);
774238fd1498Szrj 
774338fd1498Szrj       if (region->type == GIMPLE_OMP_FOR
774438fd1498Szrj 	  && gimple_omp_for_combined_p (last_stmt (region->entry)))
774538fd1498Szrj 	inner_stmt = last_stmt (region->inner->entry);
774638fd1498Szrj 
774738fd1498Szrj       if (region->inner)
774838fd1498Szrj 	expand_omp (region->inner);
774938fd1498Szrj 
775038fd1498Szrj       saved_location = input_location;
775138fd1498Szrj       if (gimple_has_location (last_stmt (region->entry)))
775238fd1498Szrj 	input_location = gimple_location (last_stmt (region->entry));
775338fd1498Szrj 
775438fd1498Szrj       switch (region->type)
775538fd1498Szrj 	{
775638fd1498Szrj 	case GIMPLE_OMP_PARALLEL:
775738fd1498Szrj 	case GIMPLE_OMP_TASK:
775838fd1498Szrj 	  expand_omp_taskreg (region);
775938fd1498Szrj 	  break;
776038fd1498Szrj 
776138fd1498Szrj 	case GIMPLE_OMP_FOR:
776238fd1498Szrj 	  expand_omp_for (region, inner_stmt);
776338fd1498Szrj 	  break;
776438fd1498Szrj 
776538fd1498Szrj 	case GIMPLE_OMP_SECTIONS:
776638fd1498Szrj 	  expand_omp_sections (region);
776738fd1498Szrj 	  break;
776838fd1498Szrj 
776938fd1498Szrj 	case GIMPLE_OMP_SECTION:
777038fd1498Szrj 	  /* Individual omp sections are handled together with their
777138fd1498Szrj 	     parent GIMPLE_OMP_SECTIONS region.  */
777238fd1498Szrj 	  break;
777338fd1498Szrj 
777438fd1498Szrj 	case GIMPLE_OMP_SINGLE:
777538fd1498Szrj 	  expand_omp_single (region);
777638fd1498Szrj 	  break;
777738fd1498Szrj 
777838fd1498Szrj 	case GIMPLE_OMP_ORDERED:
777938fd1498Szrj 	  {
778038fd1498Szrj 	    gomp_ordered *ord_stmt
778138fd1498Szrj 	      = as_a <gomp_ordered *> (last_stmt (region->entry));
778238fd1498Szrj 	    if (omp_find_clause (gimple_omp_ordered_clauses (ord_stmt),
778338fd1498Szrj 				 OMP_CLAUSE_DEPEND))
778438fd1498Szrj 	      {
778538fd1498Szrj 		/* We'll expand these when expanding corresponding
778638fd1498Szrj 		   worksharing region with ordered(n) clause.  */
778738fd1498Szrj 		gcc_assert (region->outer
778838fd1498Szrj 			    && region->outer->type == GIMPLE_OMP_FOR);
778938fd1498Szrj 		region->ord_stmt = ord_stmt;
779038fd1498Szrj 		break;
779138fd1498Szrj 	      }
779238fd1498Szrj 	  }
779338fd1498Szrj 	  /* FALLTHRU */
779438fd1498Szrj 	case GIMPLE_OMP_MASTER:
779538fd1498Szrj 	case GIMPLE_OMP_TASKGROUP:
779638fd1498Szrj 	case GIMPLE_OMP_CRITICAL:
779738fd1498Szrj 	case GIMPLE_OMP_TEAMS:
779838fd1498Szrj 	  expand_omp_synch (region);
779938fd1498Szrj 	  break;
780038fd1498Szrj 
780138fd1498Szrj 	case GIMPLE_OMP_ATOMIC_LOAD:
780238fd1498Szrj 	  expand_omp_atomic (region);
780338fd1498Szrj 	  break;
780438fd1498Szrj 
780538fd1498Szrj 	case GIMPLE_OMP_TARGET:
780638fd1498Szrj 	  expand_omp_target (region);
780738fd1498Szrj 	  break;
780838fd1498Szrj 
780938fd1498Szrj 	default:
781038fd1498Szrj 	  gcc_unreachable ();
781138fd1498Szrj 	}
781238fd1498Szrj 
781338fd1498Szrj       input_location = saved_location;
781438fd1498Szrj       region = region->next;
781538fd1498Szrj     }
781638fd1498Szrj   if (omp_any_child_fn_dumped)
781738fd1498Szrj     {
781838fd1498Szrj       if (dump_file)
781938fd1498Szrj 	dump_function_header (dump_file, current_function_decl, dump_flags);
782038fd1498Szrj       omp_any_child_fn_dumped = false;
782138fd1498Szrj     }
782238fd1498Szrj }
782338fd1498Szrj 
782438fd1498Szrj /* Helper for build_omp_regions.  Scan the dominator tree starting at
782538fd1498Szrj    block BB.  PARENT is the region that contains BB.  If SINGLE_TREE is
782638fd1498Szrj    true, the function ends once a single tree is built (otherwise, whole
782738fd1498Szrj    forest of OMP constructs may be built).  */
782838fd1498Szrj 
782938fd1498Szrj static void
build_omp_regions_1(basic_block bb,struct omp_region * parent,bool single_tree)783038fd1498Szrj build_omp_regions_1 (basic_block bb, struct omp_region *parent,
783138fd1498Szrj 		     bool single_tree)
783238fd1498Szrj {
783338fd1498Szrj   gimple_stmt_iterator gsi;
783438fd1498Szrj   gimple *stmt;
783538fd1498Szrj   basic_block son;
783638fd1498Szrj 
783738fd1498Szrj   gsi = gsi_last_nondebug_bb (bb);
783838fd1498Szrj   if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
783938fd1498Szrj     {
784038fd1498Szrj       struct omp_region *region;
784138fd1498Szrj       enum gimple_code code;
784238fd1498Szrj 
784338fd1498Szrj       stmt = gsi_stmt (gsi);
784438fd1498Szrj       code = gimple_code (stmt);
784538fd1498Szrj       if (code == GIMPLE_OMP_RETURN)
784638fd1498Szrj 	{
784738fd1498Szrj 	  /* STMT is the return point out of region PARENT.  Mark it
784838fd1498Szrj 	     as the exit point and make PARENT the immediately
784938fd1498Szrj 	     enclosing region.  */
785038fd1498Szrj 	  gcc_assert (parent);
785138fd1498Szrj 	  region = parent;
785238fd1498Szrj 	  region->exit = bb;
785338fd1498Szrj 	  parent = parent->outer;
785438fd1498Szrj 	}
785538fd1498Szrj       else if (code == GIMPLE_OMP_ATOMIC_STORE)
785638fd1498Szrj 	{
785738fd1498Szrj 	  /* GIMPLE_OMP_ATOMIC_STORE is analogous to
785838fd1498Szrj 	     GIMPLE_OMP_RETURN, but matches with
785938fd1498Szrj 	     GIMPLE_OMP_ATOMIC_LOAD.  */
786038fd1498Szrj 	  gcc_assert (parent);
786138fd1498Szrj 	  gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
786238fd1498Szrj 	  region = parent;
786338fd1498Szrj 	  region->exit = bb;
786438fd1498Szrj 	  parent = parent->outer;
786538fd1498Szrj 	}
786638fd1498Szrj       else if (code == GIMPLE_OMP_CONTINUE)
786738fd1498Szrj 	{
786838fd1498Szrj 	  gcc_assert (parent);
786938fd1498Szrj 	  parent->cont = bb;
787038fd1498Szrj 	}
787138fd1498Szrj       else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
787238fd1498Szrj 	{
787338fd1498Szrj 	  /* GIMPLE_OMP_SECTIONS_SWITCH is part of
787438fd1498Szrj 	     GIMPLE_OMP_SECTIONS, and we do nothing for it.  */
787538fd1498Szrj 	}
787638fd1498Szrj       else
787738fd1498Szrj 	{
787838fd1498Szrj 	  region = new_omp_region (bb, code, parent);
787938fd1498Szrj 	  /* Otherwise...  */
788038fd1498Szrj 	  if (code == GIMPLE_OMP_TARGET)
788138fd1498Szrj 	    {
788238fd1498Szrj 	      switch (gimple_omp_target_kind (stmt))
788338fd1498Szrj 		{
788438fd1498Szrj 		case GF_OMP_TARGET_KIND_REGION:
788538fd1498Szrj 		case GF_OMP_TARGET_KIND_DATA:
788638fd1498Szrj 		case GF_OMP_TARGET_KIND_OACC_PARALLEL:
788738fd1498Szrj 		case GF_OMP_TARGET_KIND_OACC_KERNELS:
788838fd1498Szrj 		case GF_OMP_TARGET_KIND_OACC_DATA:
788938fd1498Szrj 		case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
789038fd1498Szrj 		  break;
789138fd1498Szrj 		case GF_OMP_TARGET_KIND_UPDATE:
789238fd1498Szrj 		case GF_OMP_TARGET_KIND_ENTER_DATA:
789338fd1498Szrj 		case GF_OMP_TARGET_KIND_EXIT_DATA:
789438fd1498Szrj 		case GF_OMP_TARGET_KIND_OACC_UPDATE:
789538fd1498Szrj 		case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
789638fd1498Szrj 		case GF_OMP_TARGET_KIND_OACC_DECLARE:
789738fd1498Szrj 		  /* ..., other than for those stand-alone directives...  */
789838fd1498Szrj 		  region = NULL;
789938fd1498Szrj 		  break;
790038fd1498Szrj 		default:
790138fd1498Szrj 		  gcc_unreachable ();
790238fd1498Szrj 		}
790338fd1498Szrj 	    }
790438fd1498Szrj 	  else if (code == GIMPLE_OMP_ORDERED
790538fd1498Szrj 		   && omp_find_clause (gimple_omp_ordered_clauses
790638fd1498Szrj 					 (as_a <gomp_ordered *> (stmt)),
790738fd1498Szrj 				       OMP_CLAUSE_DEPEND))
790838fd1498Szrj 	    /* #pragma omp ordered depend is also just a stand-alone
790938fd1498Szrj 	       directive.  */
791038fd1498Szrj 	    region = NULL;
791138fd1498Szrj 	  /* ..., this directive becomes the parent for a new region.  */
791238fd1498Szrj 	  if (region)
791338fd1498Szrj 	    parent = region;
791438fd1498Szrj 	}
791538fd1498Szrj     }
791638fd1498Szrj 
791738fd1498Szrj   if (single_tree && !parent)
791838fd1498Szrj     return;
791938fd1498Szrj 
792038fd1498Szrj   for (son = first_dom_son (CDI_DOMINATORS, bb);
792138fd1498Szrj        son;
792238fd1498Szrj        son = next_dom_son (CDI_DOMINATORS, son))
792338fd1498Szrj     build_omp_regions_1 (son, parent, single_tree);
792438fd1498Szrj }
792538fd1498Szrj 
792638fd1498Szrj /* Builds the tree of OMP regions rooted at ROOT, storing it to
792738fd1498Szrj    root_omp_region.  */
792838fd1498Szrj 
792938fd1498Szrj static void
build_omp_regions_root(basic_block root)793038fd1498Szrj build_omp_regions_root (basic_block root)
793138fd1498Szrj {
793238fd1498Szrj   gcc_assert (root_omp_region == NULL);
793338fd1498Szrj   build_omp_regions_1 (root, NULL, true);
793438fd1498Szrj   gcc_assert (root_omp_region != NULL);
793538fd1498Szrj }
793638fd1498Szrj 
793738fd1498Szrj /* Expands omp construct (and its subconstructs) starting in HEAD.  */
793838fd1498Szrj 
793938fd1498Szrj void
omp_expand_local(basic_block head)794038fd1498Szrj omp_expand_local (basic_block head)
794138fd1498Szrj {
794238fd1498Szrj   build_omp_regions_root (head);
794338fd1498Szrj   if (dump_file && (dump_flags & TDF_DETAILS))
794438fd1498Szrj     {
794538fd1498Szrj       fprintf (dump_file, "\nOMP region tree\n\n");
794638fd1498Szrj       dump_omp_region (dump_file, root_omp_region, 0);
794738fd1498Szrj       fprintf (dump_file, "\n");
794838fd1498Szrj     }
794938fd1498Szrj 
795038fd1498Szrj   remove_exit_barriers (root_omp_region);
795138fd1498Szrj   expand_omp (root_omp_region);
795238fd1498Szrj 
795338fd1498Szrj   omp_free_regions ();
795438fd1498Szrj }
795538fd1498Szrj 
795638fd1498Szrj /* Scan the CFG and build a tree of OMP regions.  Return the root of
795738fd1498Szrj    the OMP region tree.  */
795838fd1498Szrj 
795938fd1498Szrj static void
build_omp_regions(void)796038fd1498Szrj build_omp_regions (void)
796138fd1498Szrj {
796238fd1498Szrj   gcc_assert (root_omp_region == NULL);
796338fd1498Szrj   calculate_dominance_info (CDI_DOMINATORS);
796438fd1498Szrj   build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
796538fd1498Szrj }
796638fd1498Szrj 
796738fd1498Szrj /* Main entry point for expanding OMP-GIMPLE into runtime calls.  */
796838fd1498Szrj 
796938fd1498Szrj static unsigned int
execute_expand_omp(void)797038fd1498Szrj execute_expand_omp (void)
797138fd1498Szrj {
797238fd1498Szrj   build_omp_regions ();
797338fd1498Szrj 
797438fd1498Szrj   if (!root_omp_region)
797538fd1498Szrj     return 0;
797638fd1498Szrj 
797738fd1498Szrj   if (dump_file)
797838fd1498Szrj     {
797938fd1498Szrj       fprintf (dump_file, "\nOMP region tree\n\n");
798038fd1498Szrj       dump_omp_region (dump_file, root_omp_region, 0);
798138fd1498Szrj       fprintf (dump_file, "\n");
798238fd1498Szrj     }
798338fd1498Szrj 
798438fd1498Szrj   remove_exit_barriers (root_omp_region);
798538fd1498Szrj 
798638fd1498Szrj   expand_omp (root_omp_region);
798738fd1498Szrj 
798838fd1498Szrj   if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
798938fd1498Szrj     verify_loop_structure ();
799038fd1498Szrj   cleanup_tree_cfg ();
799138fd1498Szrj 
799238fd1498Szrj   omp_free_regions ();
799338fd1498Szrj 
799438fd1498Szrj   return 0;
799538fd1498Szrj }
799638fd1498Szrj 
799738fd1498Szrj /* OMP expansion -- the default pass, run before creation of SSA form.  */
799838fd1498Szrj 
799938fd1498Szrj namespace {
800038fd1498Szrj 
800138fd1498Szrj const pass_data pass_data_expand_omp =
800238fd1498Szrj {
800338fd1498Szrj   GIMPLE_PASS, /* type */
800438fd1498Szrj   "ompexp", /* name */
800538fd1498Szrj   OPTGROUP_OMP, /* optinfo_flags */
800638fd1498Szrj   TV_NONE, /* tv_id */
800738fd1498Szrj   PROP_gimple_any, /* properties_required */
800838fd1498Szrj   PROP_gimple_eomp, /* properties_provided */
800938fd1498Szrj   0, /* properties_destroyed */
801038fd1498Szrj   0, /* todo_flags_start */
801138fd1498Szrj   0, /* todo_flags_finish */
801238fd1498Szrj };
801338fd1498Szrj 
801438fd1498Szrj class pass_expand_omp : public gimple_opt_pass
801538fd1498Szrj {
801638fd1498Szrj public:
pass_expand_omp(gcc::context * ctxt)801738fd1498Szrj   pass_expand_omp (gcc::context *ctxt)
801838fd1498Szrj     : gimple_opt_pass (pass_data_expand_omp, ctxt)
801938fd1498Szrj   {}
802038fd1498Szrj 
802138fd1498Szrj   /* opt_pass methods: */
execute(function *)802238fd1498Szrj   virtual unsigned int execute (function *)
802338fd1498Szrj     {
802438fd1498Szrj       bool gate = ((flag_openacc != 0 || flag_openmp != 0
802538fd1498Szrj 		    || flag_openmp_simd != 0)
802638fd1498Szrj 		   && !seen_error ());
802738fd1498Szrj 
802838fd1498Szrj       /* This pass always runs, to provide PROP_gimple_eomp.
802938fd1498Szrj 	 But often, there is nothing to do.  */
803038fd1498Szrj       if (!gate)
803138fd1498Szrj 	return 0;
803238fd1498Szrj 
803338fd1498Szrj       return execute_expand_omp ();
803438fd1498Szrj     }
803538fd1498Szrj 
803638fd1498Szrj }; // class pass_expand_omp
803738fd1498Szrj 
803838fd1498Szrj } // anon namespace
803938fd1498Szrj 
804038fd1498Szrj gimple_opt_pass *
make_pass_expand_omp(gcc::context * ctxt)804138fd1498Szrj make_pass_expand_omp (gcc::context *ctxt)
804238fd1498Szrj {
804338fd1498Szrj   return new pass_expand_omp (ctxt);
804438fd1498Szrj }
804538fd1498Szrj 
804638fd1498Szrj namespace {
804738fd1498Szrj 
804838fd1498Szrj const pass_data pass_data_expand_omp_ssa =
804938fd1498Szrj {
805038fd1498Szrj   GIMPLE_PASS, /* type */
805138fd1498Szrj   "ompexpssa", /* name */
805238fd1498Szrj   OPTGROUP_OMP, /* optinfo_flags */
805338fd1498Szrj   TV_NONE, /* tv_id */
805438fd1498Szrj   PROP_cfg | PROP_ssa, /* properties_required */
805538fd1498Szrj   PROP_gimple_eomp, /* properties_provided */
805638fd1498Szrj   0, /* properties_destroyed */
805738fd1498Szrj   0, /* todo_flags_start */
805838fd1498Szrj   TODO_cleanup_cfg | TODO_rebuild_alias, /* todo_flags_finish */
805938fd1498Szrj };
806038fd1498Szrj 
806138fd1498Szrj class pass_expand_omp_ssa : public gimple_opt_pass
806238fd1498Szrj {
806338fd1498Szrj public:
pass_expand_omp_ssa(gcc::context * ctxt)806438fd1498Szrj   pass_expand_omp_ssa (gcc::context *ctxt)
806538fd1498Szrj     : gimple_opt_pass (pass_data_expand_omp_ssa, ctxt)
806638fd1498Szrj   {}
806738fd1498Szrj 
806838fd1498Szrj   /* opt_pass methods: */
gate(function * fun)806938fd1498Szrj   virtual bool gate (function *fun)
807038fd1498Szrj     {
807138fd1498Szrj       return !(fun->curr_properties & PROP_gimple_eomp);
807238fd1498Szrj     }
execute(function *)807338fd1498Szrj   virtual unsigned int execute (function *) { return execute_expand_omp (); }
clone()807438fd1498Szrj   opt_pass * clone () { return new pass_expand_omp_ssa (m_ctxt); }
807538fd1498Szrj 
807638fd1498Szrj }; // class pass_expand_omp_ssa
807738fd1498Szrj 
807838fd1498Szrj } // anon namespace
807938fd1498Szrj 
808038fd1498Szrj gimple_opt_pass *
make_pass_expand_omp_ssa(gcc::context * ctxt)808138fd1498Szrj make_pass_expand_omp_ssa (gcc::context *ctxt)
808238fd1498Szrj {
808338fd1498Szrj   return new pass_expand_omp_ssa (ctxt);
808438fd1498Szrj }
808538fd1498Szrj 
808638fd1498Szrj /* Called from tree-cfg.c::make_edges to create cfg edges for all relevant
808738fd1498Szrj    GIMPLE_* codes.  */
808838fd1498Szrj 
808938fd1498Szrj bool
omp_make_gimple_edges(basic_block bb,struct omp_region ** region,int * region_idx)809038fd1498Szrj omp_make_gimple_edges (basic_block bb, struct omp_region **region,
809138fd1498Szrj 		       int *region_idx)
809238fd1498Szrj {
809338fd1498Szrj   gimple *last = last_stmt (bb);
809438fd1498Szrj   enum gimple_code code = gimple_code (last);
809538fd1498Szrj   struct omp_region *cur_region = *region;
809638fd1498Szrj   bool fallthru = false;
809738fd1498Szrj 
809838fd1498Szrj   switch (code)
809938fd1498Szrj     {
810038fd1498Szrj     case GIMPLE_OMP_PARALLEL:
810138fd1498Szrj     case GIMPLE_OMP_TASK:
810238fd1498Szrj     case GIMPLE_OMP_FOR:
810338fd1498Szrj     case GIMPLE_OMP_SINGLE:
810438fd1498Szrj     case GIMPLE_OMP_TEAMS:
810538fd1498Szrj     case GIMPLE_OMP_MASTER:
810638fd1498Szrj     case GIMPLE_OMP_TASKGROUP:
810738fd1498Szrj     case GIMPLE_OMP_CRITICAL:
810838fd1498Szrj     case GIMPLE_OMP_SECTION:
810938fd1498Szrj     case GIMPLE_OMP_GRID_BODY:
811038fd1498Szrj       cur_region = new_omp_region (bb, code, cur_region);
811138fd1498Szrj       fallthru = true;
811238fd1498Szrj       break;
811338fd1498Szrj 
811438fd1498Szrj     case GIMPLE_OMP_ORDERED:
811538fd1498Szrj       cur_region = new_omp_region (bb, code, cur_region);
811638fd1498Szrj       fallthru = true;
811738fd1498Szrj       if (omp_find_clause (gimple_omp_ordered_clauses
811838fd1498Szrj 			     (as_a <gomp_ordered *> (last)),
811938fd1498Szrj 			   OMP_CLAUSE_DEPEND))
812038fd1498Szrj 	cur_region = cur_region->outer;
812138fd1498Szrj       break;
812238fd1498Szrj 
812338fd1498Szrj     case GIMPLE_OMP_TARGET:
812438fd1498Szrj       cur_region = new_omp_region (bb, code, cur_region);
812538fd1498Szrj       fallthru = true;
812638fd1498Szrj       switch (gimple_omp_target_kind (last))
812738fd1498Szrj 	{
812838fd1498Szrj 	case GF_OMP_TARGET_KIND_REGION:
812938fd1498Szrj 	case GF_OMP_TARGET_KIND_DATA:
813038fd1498Szrj 	case GF_OMP_TARGET_KIND_OACC_PARALLEL:
813138fd1498Szrj 	case GF_OMP_TARGET_KIND_OACC_KERNELS:
813238fd1498Szrj 	case GF_OMP_TARGET_KIND_OACC_DATA:
813338fd1498Szrj 	case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
813438fd1498Szrj 	  break;
813538fd1498Szrj 	case GF_OMP_TARGET_KIND_UPDATE:
813638fd1498Szrj 	case GF_OMP_TARGET_KIND_ENTER_DATA:
813738fd1498Szrj 	case GF_OMP_TARGET_KIND_EXIT_DATA:
813838fd1498Szrj 	case GF_OMP_TARGET_KIND_OACC_UPDATE:
813938fd1498Szrj 	case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
814038fd1498Szrj 	case GF_OMP_TARGET_KIND_OACC_DECLARE:
814138fd1498Szrj 	  cur_region = cur_region->outer;
814238fd1498Szrj 	  break;
814338fd1498Szrj 	default:
814438fd1498Szrj 	  gcc_unreachable ();
814538fd1498Szrj 	}
814638fd1498Szrj       break;
814738fd1498Szrj 
814838fd1498Szrj     case GIMPLE_OMP_SECTIONS:
814938fd1498Szrj       cur_region = new_omp_region (bb, code, cur_region);
815038fd1498Szrj       fallthru = true;
815138fd1498Szrj       break;
815238fd1498Szrj 
815338fd1498Szrj     case GIMPLE_OMP_SECTIONS_SWITCH:
815438fd1498Szrj       fallthru = false;
815538fd1498Szrj       break;
815638fd1498Szrj 
815738fd1498Szrj     case GIMPLE_OMP_ATOMIC_LOAD:
815838fd1498Szrj     case GIMPLE_OMP_ATOMIC_STORE:
815938fd1498Szrj        fallthru = true;
816038fd1498Szrj        break;
816138fd1498Szrj 
816238fd1498Szrj     case GIMPLE_OMP_RETURN:
816338fd1498Szrj       /* In the case of a GIMPLE_OMP_SECTION, the edge will go
816438fd1498Szrj 	 somewhere other than the next block.  This will be
816538fd1498Szrj 	 created later.  */
816638fd1498Szrj       cur_region->exit = bb;
816738fd1498Szrj       if (cur_region->type == GIMPLE_OMP_TASK)
816838fd1498Szrj 	/* Add an edge corresponding to not scheduling the task
816938fd1498Szrj 	   immediately.  */
817038fd1498Szrj 	make_edge (cur_region->entry, bb, EDGE_ABNORMAL);
817138fd1498Szrj       fallthru = cur_region->type != GIMPLE_OMP_SECTION;
817238fd1498Szrj       cur_region = cur_region->outer;
817338fd1498Szrj       break;
817438fd1498Szrj 
817538fd1498Szrj     case GIMPLE_OMP_CONTINUE:
817638fd1498Szrj       cur_region->cont = bb;
817738fd1498Szrj       switch (cur_region->type)
817838fd1498Szrj 	{
817938fd1498Szrj 	case GIMPLE_OMP_FOR:
818038fd1498Szrj 	  /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
818138fd1498Szrj 	     succs edges as abnormal to prevent splitting
818238fd1498Szrj 	     them.  */
818338fd1498Szrj 	  single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
818438fd1498Szrj 	  /* Make the loopback edge.  */
818538fd1498Szrj 	  make_edge (bb, single_succ (cur_region->entry),
818638fd1498Szrj 		     EDGE_ABNORMAL);
818738fd1498Szrj 
818838fd1498Szrj 	  /* Create an edge from GIMPLE_OMP_FOR to exit, which
818938fd1498Szrj 	     corresponds to the case that the body of the loop
819038fd1498Szrj 	     is not executed at all.  */
819138fd1498Szrj 	  make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
819238fd1498Szrj 	  make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
819338fd1498Szrj 	  fallthru = false;
819438fd1498Szrj 	  break;
819538fd1498Szrj 
819638fd1498Szrj 	case GIMPLE_OMP_SECTIONS:
819738fd1498Szrj 	  /* Wire up the edges into and out of the nested sections.  */
819838fd1498Szrj 	  {
819938fd1498Szrj 	    basic_block switch_bb = single_succ (cur_region->entry);
820038fd1498Szrj 
820138fd1498Szrj 	    struct omp_region *i;
820238fd1498Szrj 	    for (i = cur_region->inner; i ; i = i->next)
820338fd1498Szrj 	      {
820438fd1498Szrj 		gcc_assert (i->type == GIMPLE_OMP_SECTION);
820538fd1498Szrj 		make_edge (switch_bb, i->entry, 0);
820638fd1498Szrj 		make_edge (i->exit, bb, EDGE_FALLTHRU);
820738fd1498Szrj 	      }
820838fd1498Szrj 
820938fd1498Szrj 	    /* Make the loopback edge to the block with
821038fd1498Szrj 	       GIMPLE_OMP_SECTIONS_SWITCH.  */
821138fd1498Szrj 	    make_edge (bb, switch_bb, 0);
821238fd1498Szrj 
821338fd1498Szrj 	    /* Make the edge from the switch to exit.  */
821438fd1498Szrj 	    make_edge (switch_bb, bb->next_bb, 0);
821538fd1498Szrj 	    fallthru = false;
821638fd1498Szrj 	  }
821738fd1498Szrj 	  break;
821838fd1498Szrj 
821938fd1498Szrj 	case GIMPLE_OMP_TASK:
822038fd1498Szrj 	  fallthru = true;
822138fd1498Szrj 	  break;
822238fd1498Szrj 
822338fd1498Szrj 	default:
822438fd1498Szrj 	  gcc_unreachable ();
822538fd1498Szrj 	}
822638fd1498Szrj       break;
822738fd1498Szrj 
822838fd1498Szrj     default:
822938fd1498Szrj       gcc_unreachable ();
823038fd1498Szrj     }
823138fd1498Szrj 
823238fd1498Szrj   if (*region != cur_region)
823338fd1498Szrj     {
823438fd1498Szrj       *region = cur_region;
823538fd1498Szrj       if (cur_region)
823638fd1498Szrj 	*region_idx = cur_region->entry->index;
823738fd1498Szrj       else
823838fd1498Szrj 	*region_idx = 0;
823938fd1498Szrj     }
824038fd1498Szrj 
824138fd1498Szrj   return fallthru;
824238fd1498Szrj }
824338fd1498Szrj 
824438fd1498Szrj #include "gt-omp-expand.h"
8245