xref: /dflybsd-src/contrib/gcc-8.0/gcc/c-family/c-omp.c (revision 95059079af47f9a66a175f374f2da1a5020e3255)
138fd1498Szrj /* This file contains routines to construct OpenACC and OpenMP constructs,
238fd1498Szrj    called from parsing in the C and C++ front ends.
338fd1498Szrj 
438fd1498Szrj    Copyright (C) 2005-2018 Free Software Foundation, Inc.
538fd1498Szrj    Contributed by Richard Henderson <rth@redhat.com>,
638fd1498Szrj 		  Diego Novillo <dnovillo@redhat.com>.
738fd1498Szrj 
838fd1498Szrj This file is part of GCC.
938fd1498Szrj 
1038fd1498Szrj GCC is free software; you can redistribute it and/or modify it under
1138fd1498Szrj the terms of the GNU General Public License as published by the Free
1238fd1498Szrj Software Foundation; either version 3, or (at your option) any later
1338fd1498Szrj version.
1438fd1498Szrj 
1538fd1498Szrj GCC is distributed in the hope that it will be useful, but WITHOUT ANY
1638fd1498Szrj WARRANTY; without even the implied warranty of MERCHANTABILITY or
1738fd1498Szrj FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1838fd1498Szrj for more details.
1938fd1498Szrj 
2038fd1498Szrj You should have received a copy of the GNU General Public License
2138fd1498Szrj along with GCC; see the file COPYING3.  If not see
2238fd1498Szrj <http://www.gnu.org/licenses/>.  */
2338fd1498Szrj 
2438fd1498Szrj #include "config.h"
2538fd1498Szrj #include "system.h"
2638fd1498Szrj #include "coretypes.h"
2738fd1498Szrj #include "options.h"
2838fd1498Szrj #include "c-common.h"
2938fd1498Szrj #include "gimple-expr.h"
3038fd1498Szrj #include "c-pragma.h"
3138fd1498Szrj #include "omp-general.h"
3238fd1498Szrj #include "gomp-constants.h"
3338fd1498Szrj 
3438fd1498Szrj 
3538fd1498Szrj /* Complete a #pragma oacc wait construct.  LOC is the location of
3638fd1498Szrj    the #pragma.  */
3738fd1498Szrj 
3838fd1498Szrj tree
c_finish_oacc_wait(location_t loc,tree parms,tree clauses)3938fd1498Szrj c_finish_oacc_wait (location_t loc, tree parms, tree clauses)
4038fd1498Szrj {
4138fd1498Szrj   const int nparms = list_length (parms);
4238fd1498Szrj   tree stmt, t;
4338fd1498Szrj   vec<tree, va_gc> *args;
4438fd1498Szrj 
4538fd1498Szrj   vec_alloc (args, nparms + 2);
4638fd1498Szrj   stmt = builtin_decl_explicit (BUILT_IN_GOACC_WAIT);
4738fd1498Szrj 
4838fd1498Szrj   if (omp_find_clause (clauses, OMP_CLAUSE_ASYNC))
4938fd1498Szrj     t = OMP_CLAUSE_ASYNC_EXPR (clauses);
5038fd1498Szrj   else
5138fd1498Szrj     t = build_int_cst (integer_type_node, GOMP_ASYNC_SYNC);
5238fd1498Szrj 
5338fd1498Szrj   args->quick_push (t);
5438fd1498Szrj   args->quick_push (build_int_cst (integer_type_node, nparms));
5538fd1498Szrj 
5638fd1498Szrj   for (t = parms; t; t = TREE_CHAIN (t))
5738fd1498Szrj     {
5838fd1498Szrj       if (TREE_CODE (OMP_CLAUSE_WAIT_EXPR (t)) == INTEGER_CST)
5938fd1498Szrj 	args->quick_push (build_int_cst (integer_type_node,
6038fd1498Szrj 			TREE_INT_CST_LOW (OMP_CLAUSE_WAIT_EXPR (t))));
6138fd1498Szrj       else
6238fd1498Szrj 	args->quick_push (OMP_CLAUSE_WAIT_EXPR (t));
6338fd1498Szrj     }
6438fd1498Szrj 
6538fd1498Szrj   stmt = build_call_expr_loc_vec (loc, stmt, args);
6638fd1498Szrj 
6738fd1498Szrj   vec_free (args);
6838fd1498Szrj 
6938fd1498Szrj   return stmt;
7038fd1498Szrj }
7138fd1498Szrj 
7238fd1498Szrj /* Complete a #pragma omp master construct.  STMT is the structured-block
7338fd1498Szrj    that follows the pragma.  LOC is the l*/
7438fd1498Szrj 
7538fd1498Szrj tree
c_finish_omp_master(location_t loc,tree stmt)7638fd1498Szrj c_finish_omp_master (location_t loc, tree stmt)
7738fd1498Szrj {
7838fd1498Szrj   tree t = add_stmt (build1 (OMP_MASTER, void_type_node, stmt));
7938fd1498Szrj   SET_EXPR_LOCATION (t, loc);
8038fd1498Szrj   return t;
8138fd1498Szrj }
8238fd1498Szrj 
8338fd1498Szrj /* Complete a #pragma omp taskgroup construct.  STMT is the structured-block
8438fd1498Szrj    that follows the pragma.  LOC is the l*/
8538fd1498Szrj 
8638fd1498Szrj tree
c_finish_omp_taskgroup(location_t loc,tree stmt)8738fd1498Szrj c_finish_omp_taskgroup (location_t loc, tree stmt)
8838fd1498Szrj {
8938fd1498Szrj   tree t = add_stmt (build1 (OMP_TASKGROUP, void_type_node, stmt));
9038fd1498Szrj   SET_EXPR_LOCATION (t, loc);
9138fd1498Szrj   return t;
9238fd1498Szrj }
9338fd1498Szrj 
9438fd1498Szrj /* Complete a #pragma omp critical construct.  STMT is the structured-block
9538fd1498Szrj    that follows the pragma, NAME is the identifier in the pragma, or null
9638fd1498Szrj    if it was omitted.  LOC is the location of the #pragma.  */
9738fd1498Szrj 
9838fd1498Szrj tree
c_finish_omp_critical(location_t loc,tree body,tree name,tree clauses)9938fd1498Szrj c_finish_omp_critical (location_t loc, tree body, tree name, tree clauses)
10038fd1498Szrj {
10138fd1498Szrj   tree stmt = make_node (OMP_CRITICAL);
10238fd1498Szrj   TREE_TYPE (stmt) = void_type_node;
10338fd1498Szrj   OMP_CRITICAL_BODY (stmt) = body;
10438fd1498Szrj   OMP_CRITICAL_NAME (stmt) = name;
10538fd1498Szrj   OMP_CRITICAL_CLAUSES (stmt) = clauses;
10638fd1498Szrj   SET_EXPR_LOCATION (stmt, loc);
10738fd1498Szrj   return add_stmt (stmt);
10838fd1498Szrj }
10938fd1498Szrj 
11038fd1498Szrj /* Complete a #pragma omp ordered construct.  STMT is the structured-block
11138fd1498Szrj    that follows the pragma.  LOC is the location of the #pragma.  */
11238fd1498Szrj 
11338fd1498Szrj tree
c_finish_omp_ordered(location_t loc,tree clauses,tree stmt)11438fd1498Szrj c_finish_omp_ordered (location_t loc, tree clauses, tree stmt)
11538fd1498Szrj {
11638fd1498Szrj   tree t = make_node (OMP_ORDERED);
11738fd1498Szrj   TREE_TYPE (t) = void_type_node;
11838fd1498Szrj   OMP_ORDERED_BODY (t) = stmt;
11938fd1498Szrj   if (!flag_openmp	/* flag_openmp_simd */
12038fd1498Szrj       && (OMP_CLAUSE_CODE (clauses) != OMP_CLAUSE_SIMD
12138fd1498Szrj 	  || OMP_CLAUSE_CHAIN (clauses)))
12238fd1498Szrj     clauses = build_omp_clause (loc, OMP_CLAUSE_SIMD);
12338fd1498Szrj   OMP_ORDERED_CLAUSES (t) = clauses;
12438fd1498Szrj   SET_EXPR_LOCATION (t, loc);
12538fd1498Szrj   return add_stmt (t);
12638fd1498Szrj }
12738fd1498Szrj 
12838fd1498Szrj 
12938fd1498Szrj /* Complete a #pragma omp barrier construct.  LOC is the location of
13038fd1498Szrj    the #pragma.  */
13138fd1498Szrj 
13238fd1498Szrj void
c_finish_omp_barrier(location_t loc)13338fd1498Szrj c_finish_omp_barrier (location_t loc)
13438fd1498Szrj {
13538fd1498Szrj   tree x;
13638fd1498Szrj 
13738fd1498Szrj   x = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER);
13838fd1498Szrj   x = build_call_expr_loc (loc, x, 0);
13938fd1498Szrj   add_stmt (x);
14038fd1498Szrj }
14138fd1498Szrj 
14238fd1498Szrj 
14338fd1498Szrj /* Complete a #pragma omp taskwait construct.  LOC is the location of the
14438fd1498Szrj    pragma.  */
14538fd1498Szrj 
14638fd1498Szrj void
c_finish_omp_taskwait(location_t loc)14738fd1498Szrj c_finish_omp_taskwait (location_t loc)
14838fd1498Szrj {
14938fd1498Szrj   tree x;
15038fd1498Szrj 
15138fd1498Szrj   x = builtin_decl_explicit (BUILT_IN_GOMP_TASKWAIT);
15238fd1498Szrj   x = build_call_expr_loc (loc, x, 0);
15338fd1498Szrj   add_stmt (x);
15438fd1498Szrj }
15538fd1498Szrj 
15638fd1498Szrj 
15738fd1498Szrj /* Complete a #pragma omp taskyield construct.  LOC is the location of the
15838fd1498Szrj    pragma.  */
15938fd1498Szrj 
16038fd1498Szrj void
c_finish_omp_taskyield(location_t loc)16138fd1498Szrj c_finish_omp_taskyield (location_t loc)
16238fd1498Szrj {
16338fd1498Szrj   tree x;
16438fd1498Szrj 
16538fd1498Szrj   x = builtin_decl_explicit (BUILT_IN_GOMP_TASKYIELD);
16638fd1498Szrj   x = build_call_expr_loc (loc, x, 0);
16738fd1498Szrj   add_stmt (x);
16838fd1498Szrj }
16938fd1498Szrj 
17038fd1498Szrj 
17138fd1498Szrj /* Complete a #pragma omp atomic construct.  For CODE OMP_ATOMIC
17238fd1498Szrj    the expression to be implemented atomically is LHS opcode= RHS.
17338fd1498Szrj    For OMP_ATOMIC_READ V = LHS, for OMP_ATOMIC_CAPTURE_{NEW,OLD} LHS
17438fd1498Szrj    opcode= RHS with the new or old content of LHS returned.
17538fd1498Szrj    LOC is the location of the atomic statement.  The value returned
17638fd1498Szrj    is either error_mark_node (if the construct was erroneous) or an
17738fd1498Szrj    OMP_ATOMIC* node which should be added to the current statement
17838fd1498Szrj    tree with add_stmt.  If TEST is set, avoid calling save_expr
17938fd1498Szrj    or create_tmp_var*.  */
18038fd1498Szrj 
18138fd1498Szrj tree
c_finish_omp_atomic(location_t loc,enum tree_code code,enum tree_code opcode,tree lhs,tree rhs,tree v,tree lhs1,tree rhs1,bool swapped,bool seq_cst,bool test)18238fd1498Szrj c_finish_omp_atomic (location_t loc, enum tree_code code,
18338fd1498Szrj 		     enum tree_code opcode, tree lhs, tree rhs,
18438fd1498Szrj 		     tree v, tree lhs1, tree rhs1, bool swapped, bool seq_cst,
18538fd1498Szrj 		     bool test)
18638fd1498Szrj {
18738fd1498Szrj   tree x, type, addr, pre = NULL_TREE;
18838fd1498Szrj   HOST_WIDE_INT bitpos = 0, bitsize = 0;
18938fd1498Szrj 
19038fd1498Szrj   if (lhs == error_mark_node || rhs == error_mark_node
19138fd1498Szrj       || v == error_mark_node || lhs1 == error_mark_node
19238fd1498Szrj       || rhs1 == error_mark_node)
19338fd1498Szrj     return error_mark_node;
19438fd1498Szrj 
19538fd1498Szrj   /* ??? According to one reading of the OpenMP spec, complex type are
19638fd1498Szrj      supported, but there are no atomic stores for any architecture.
19738fd1498Szrj      But at least icc 9.0 doesn't support complex types here either.
19838fd1498Szrj      And lets not even talk about vector types...  */
19938fd1498Szrj   type = TREE_TYPE (lhs);
20038fd1498Szrj   if (!INTEGRAL_TYPE_P (type)
20138fd1498Szrj       && !POINTER_TYPE_P (type)
20238fd1498Szrj       && !SCALAR_FLOAT_TYPE_P (type))
20338fd1498Szrj     {
20438fd1498Szrj       error_at (loc, "invalid expression type for %<#pragma omp atomic%>");
20538fd1498Szrj       return error_mark_node;
20638fd1498Szrj     }
20738fd1498Szrj   if (TYPE_ATOMIC (type))
20838fd1498Szrj     {
20938fd1498Szrj       error_at (loc, "%<_Atomic%> expression in %<#pragma omp atomic%>");
21038fd1498Szrj       return error_mark_node;
21138fd1498Szrj     }
21238fd1498Szrj 
21338fd1498Szrj   if (opcode == RDIV_EXPR)
21438fd1498Szrj     opcode = TRUNC_DIV_EXPR;
21538fd1498Szrj 
21638fd1498Szrj   /* ??? Validate that rhs does not overlap lhs.  */
21738fd1498Szrj   tree blhs = NULL;
21838fd1498Szrj   if (TREE_CODE (lhs) == COMPONENT_REF
21938fd1498Szrj       && TREE_CODE (TREE_OPERAND (lhs, 1)) == FIELD_DECL
22038fd1498Szrj       && DECL_C_BIT_FIELD (TREE_OPERAND (lhs, 1))
22138fd1498Szrj       && DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (lhs, 1)))
22238fd1498Szrj     {
22338fd1498Szrj       tree field = TREE_OPERAND (lhs, 1);
22438fd1498Szrj       tree repr = DECL_BIT_FIELD_REPRESENTATIVE (field);
22538fd1498Szrj       if (tree_fits_uhwi_p (DECL_FIELD_OFFSET (field))
22638fd1498Szrj 	  && tree_fits_uhwi_p (DECL_FIELD_OFFSET (repr)))
22738fd1498Szrj 	bitpos = (tree_to_uhwi (DECL_FIELD_OFFSET (field))
22838fd1498Szrj 		  - tree_to_uhwi (DECL_FIELD_OFFSET (repr))) * BITS_PER_UNIT;
22938fd1498Szrj       else
23038fd1498Szrj 	bitpos = 0;
23138fd1498Szrj       bitpos += (tree_to_uhwi (DECL_FIELD_BIT_OFFSET (field))
23238fd1498Szrj 		 - tree_to_uhwi (DECL_FIELD_BIT_OFFSET (repr)));
23338fd1498Szrj       gcc_assert (tree_fits_shwi_p (DECL_SIZE (field)));
23438fd1498Szrj       bitsize = tree_to_shwi (DECL_SIZE (field));
23538fd1498Szrj       blhs = lhs;
23638fd1498Szrj       type = TREE_TYPE (repr);
23738fd1498Szrj       lhs = build3 (COMPONENT_REF, TREE_TYPE (repr), TREE_OPERAND (lhs, 0),
23838fd1498Szrj 		    repr, TREE_OPERAND (lhs, 2));
23938fd1498Szrj     }
24038fd1498Szrj 
24138fd1498Szrj   /* Take and save the address of the lhs.  From then on we'll reference it
24238fd1498Szrj      via indirection.  */
24338fd1498Szrj   addr = build_unary_op (loc, ADDR_EXPR, lhs, false);
24438fd1498Szrj   if (addr == error_mark_node)
24538fd1498Szrj     return error_mark_node;
24638fd1498Szrj   if (!test)
24738fd1498Szrj     addr = save_expr (addr);
24838fd1498Szrj   if (!test
24938fd1498Szrj       && TREE_CODE (addr) != SAVE_EXPR
25038fd1498Szrj       && (TREE_CODE (addr) != ADDR_EXPR
25138fd1498Szrj 	  || !VAR_P (TREE_OPERAND (addr, 0))))
25238fd1498Szrj     {
25338fd1498Szrj       /* Make sure LHS is simple enough so that goa_lhs_expr_p can recognize
25438fd1498Szrj 	 it even after unsharing function body.  */
25538fd1498Szrj       tree var = create_tmp_var_raw (TREE_TYPE (addr));
25638fd1498Szrj       DECL_CONTEXT (var) = current_function_decl;
25738fd1498Szrj       addr = build4 (TARGET_EXPR, TREE_TYPE (addr), var, addr, NULL, NULL);
25838fd1498Szrj     }
25938fd1498Szrj   tree orig_lhs = lhs;
26038fd1498Szrj   lhs = build_indirect_ref (loc, addr, RO_NULL);
26138fd1498Szrj   tree new_lhs = lhs;
26238fd1498Szrj 
26338fd1498Szrj   if (code == OMP_ATOMIC_READ)
26438fd1498Szrj     {
26538fd1498Szrj       x = build1 (OMP_ATOMIC_READ, type, addr);
26638fd1498Szrj       SET_EXPR_LOCATION (x, loc);
26738fd1498Szrj       OMP_ATOMIC_SEQ_CST (x) = seq_cst;
26838fd1498Szrj       if (blhs)
26938fd1498Szrj 	x = build3_loc (loc, BIT_FIELD_REF, TREE_TYPE (blhs), x,
27038fd1498Szrj 			bitsize_int (bitsize), bitsize_int (bitpos));
27138fd1498Szrj       return build_modify_expr (loc, v, NULL_TREE, NOP_EXPR,
27238fd1498Szrj 				loc, x, NULL_TREE);
27338fd1498Szrj     }
27438fd1498Szrj 
27538fd1498Szrj   /* There are lots of warnings, errors, and conversions that need to happen
27638fd1498Szrj      in the course of interpreting a statement.  Use the normal mechanisms
27738fd1498Szrj      to do this, and then take it apart again.  */
27838fd1498Szrj   if (blhs)
27938fd1498Szrj     {
28038fd1498Szrj       lhs = build3_loc (loc, BIT_FIELD_REF, TREE_TYPE (blhs), lhs,
28138fd1498Szrj 			bitsize_int (bitsize), bitsize_int (bitpos));
28238fd1498Szrj       if (swapped)
28338fd1498Szrj 	rhs = build_binary_op (loc, opcode, rhs, lhs, true);
28438fd1498Szrj       else if (opcode != NOP_EXPR)
28538fd1498Szrj 	rhs = build_binary_op (loc, opcode, lhs, rhs, true);
28638fd1498Szrj       opcode = NOP_EXPR;
28738fd1498Szrj     }
28838fd1498Szrj   else if (swapped)
28938fd1498Szrj     {
29038fd1498Szrj       rhs = build_binary_op (loc, opcode, rhs, lhs, true);
29138fd1498Szrj       opcode = NOP_EXPR;
29238fd1498Szrj     }
29338fd1498Szrj   bool save = in_late_binary_op;
29438fd1498Szrj   in_late_binary_op = true;
29538fd1498Szrj   x = build_modify_expr (loc, blhs ? blhs : lhs, NULL_TREE, opcode,
29638fd1498Szrj 			 loc, rhs, NULL_TREE);
29738fd1498Szrj   in_late_binary_op = save;
29838fd1498Szrj   if (x == error_mark_node)
29938fd1498Szrj     return error_mark_node;
30038fd1498Szrj   if (TREE_CODE (x) == COMPOUND_EXPR)
30138fd1498Szrj     {
30238fd1498Szrj       pre = TREE_OPERAND (x, 0);
30338fd1498Szrj       gcc_assert (TREE_CODE (pre) == SAVE_EXPR);
30438fd1498Szrj       x = TREE_OPERAND (x, 1);
30538fd1498Szrj     }
30638fd1498Szrj   gcc_assert (TREE_CODE (x) == MODIFY_EXPR);
30738fd1498Szrj   rhs = TREE_OPERAND (x, 1);
30838fd1498Szrj 
30938fd1498Szrj   if (blhs)
31038fd1498Szrj     rhs = build3_loc (loc, BIT_INSERT_EXPR, type, new_lhs,
31138fd1498Szrj 		      rhs, bitsize_int (bitpos));
31238fd1498Szrj 
31338fd1498Szrj   /* Punt the actual generation of atomic operations to common code.  */
31438fd1498Szrj   if (code == OMP_ATOMIC)
31538fd1498Szrj     type = void_type_node;
31638fd1498Szrj   x = build2 (code, type, addr, rhs);
31738fd1498Szrj   SET_EXPR_LOCATION (x, loc);
31838fd1498Szrj   OMP_ATOMIC_SEQ_CST (x) = seq_cst;
31938fd1498Szrj 
32038fd1498Szrj   /* Generally it is hard to prove lhs1 and lhs are the same memory
32138fd1498Szrj      location, just diagnose different variables.  */
32238fd1498Szrj   if (rhs1
32338fd1498Szrj       && VAR_P (rhs1)
32438fd1498Szrj       && VAR_P (orig_lhs)
32538fd1498Szrj       && rhs1 != orig_lhs
32638fd1498Szrj       && !test)
32738fd1498Szrj     {
32838fd1498Szrj       if (code == OMP_ATOMIC)
32938fd1498Szrj 	error_at (loc, "%<#pragma omp atomic update%> uses two different "
33038fd1498Szrj 		       "variables for memory");
33138fd1498Szrj       else
33238fd1498Szrj 	error_at (loc, "%<#pragma omp atomic capture%> uses two different "
33338fd1498Szrj 		       "variables for memory");
33438fd1498Szrj       return error_mark_node;
33538fd1498Szrj     }
33638fd1498Szrj 
33738fd1498Szrj   if (lhs1
33838fd1498Szrj       && lhs1 != orig_lhs
33938fd1498Szrj       && TREE_CODE (lhs1) == COMPONENT_REF
34038fd1498Szrj       && TREE_CODE (TREE_OPERAND (lhs1, 1)) == FIELD_DECL
34138fd1498Szrj       && DECL_C_BIT_FIELD (TREE_OPERAND (lhs1, 1))
34238fd1498Szrj       && DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (lhs1, 1)))
34338fd1498Szrj     {
34438fd1498Szrj       tree field = TREE_OPERAND (lhs1, 1);
34538fd1498Szrj       tree repr = DECL_BIT_FIELD_REPRESENTATIVE (field);
34638fd1498Szrj       lhs1 = build3 (COMPONENT_REF, TREE_TYPE (repr), TREE_OPERAND (lhs1, 0),
34738fd1498Szrj 		     repr, TREE_OPERAND (lhs1, 2));
34838fd1498Szrj     }
34938fd1498Szrj   if (rhs1
35038fd1498Szrj       && rhs1 != orig_lhs
35138fd1498Szrj       && TREE_CODE (rhs1) == COMPONENT_REF
35238fd1498Szrj       && TREE_CODE (TREE_OPERAND (rhs1, 1)) == FIELD_DECL
35338fd1498Szrj       && DECL_C_BIT_FIELD (TREE_OPERAND (rhs1, 1))
35438fd1498Szrj       && DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (rhs1, 1)))
35538fd1498Szrj     {
35638fd1498Szrj       tree field = TREE_OPERAND (rhs1, 1);
35738fd1498Szrj       tree repr = DECL_BIT_FIELD_REPRESENTATIVE (field);
35838fd1498Szrj       rhs1 = build3 (COMPONENT_REF, TREE_TYPE (repr), TREE_OPERAND (rhs1, 0),
35938fd1498Szrj 		     repr, TREE_OPERAND (rhs1, 2));
36038fd1498Szrj     }
36138fd1498Szrj 
36238fd1498Szrj   if (code != OMP_ATOMIC)
36338fd1498Szrj     {
36438fd1498Szrj       /* Generally it is hard to prove lhs1 and lhs are the same memory
36538fd1498Szrj 	 location, just diagnose different variables.  */
36638fd1498Szrj       if (lhs1 && VAR_P (lhs1) && VAR_P (orig_lhs))
36738fd1498Szrj 	{
36838fd1498Szrj 	  if (lhs1 != orig_lhs && !test)
36938fd1498Szrj 	    {
37038fd1498Szrj 	      error_at (loc, "%<#pragma omp atomic capture%> uses two "
37138fd1498Szrj 			     "different variables for memory");
37238fd1498Szrj 	      return error_mark_node;
37338fd1498Szrj 	    }
37438fd1498Szrj 	}
37538fd1498Szrj       if (blhs)
376*58e805e6Szrj 	{
37738fd1498Szrj 	  x = build3_loc (loc, BIT_FIELD_REF, TREE_TYPE (blhs), x,
37838fd1498Szrj 			  bitsize_int (bitsize), bitsize_int (bitpos));
379*58e805e6Szrj 	  type = TREE_TYPE (blhs);
380*58e805e6Szrj 	}
38138fd1498Szrj       x = build_modify_expr (loc, v, NULL_TREE, NOP_EXPR,
38238fd1498Szrj 			     loc, x, NULL_TREE);
38338fd1498Szrj       if (rhs1 && rhs1 != orig_lhs)
38438fd1498Szrj 	{
38538fd1498Szrj 	  tree rhs1addr = build_unary_op (loc, ADDR_EXPR, rhs1, false);
38638fd1498Szrj 	  if (rhs1addr == error_mark_node)
38738fd1498Szrj 	    return error_mark_node;
38838fd1498Szrj 	  x = omit_one_operand_loc (loc, type, x, rhs1addr);
38938fd1498Szrj 	}
39038fd1498Szrj       if (lhs1 && lhs1 != orig_lhs)
39138fd1498Szrj 	{
39238fd1498Szrj 	  tree lhs1addr = build_unary_op (loc, ADDR_EXPR, lhs1, false);
39338fd1498Szrj 	  if (lhs1addr == error_mark_node)
39438fd1498Szrj 	    return error_mark_node;
39538fd1498Szrj 	  if (code == OMP_ATOMIC_CAPTURE_OLD)
39638fd1498Szrj 	    x = omit_one_operand_loc (loc, type, x, lhs1addr);
39738fd1498Szrj 	  else
39838fd1498Szrj 	    {
39938fd1498Szrj 	      if (!test)
40038fd1498Szrj 		x = save_expr (x);
40138fd1498Szrj 	      x = omit_two_operands_loc (loc, type, x, x, lhs1addr);
40238fd1498Szrj 	    }
40338fd1498Szrj 	}
40438fd1498Szrj     }
40538fd1498Szrj   else if (rhs1 && rhs1 != orig_lhs)
40638fd1498Szrj     {
40738fd1498Szrj       tree rhs1addr = build_unary_op (loc, ADDR_EXPR, rhs1, false);
40838fd1498Szrj       if (rhs1addr == error_mark_node)
40938fd1498Szrj 	return error_mark_node;
41038fd1498Szrj       x = omit_one_operand_loc (loc, type, x, rhs1addr);
41138fd1498Szrj     }
41238fd1498Szrj 
41338fd1498Szrj   if (pre)
41438fd1498Szrj     x = omit_one_operand_loc (loc, type, x, pre);
41538fd1498Szrj   return x;
41638fd1498Szrj }
41738fd1498Szrj 
41838fd1498Szrj 
41938fd1498Szrj /* Complete a #pragma omp flush construct.  We don't do anything with
42038fd1498Szrj    the variable list that the syntax allows.  LOC is the location of
42138fd1498Szrj    the #pragma.  */
42238fd1498Szrj 
42338fd1498Szrj void
c_finish_omp_flush(location_t loc)42438fd1498Szrj c_finish_omp_flush (location_t loc)
42538fd1498Szrj {
42638fd1498Szrj   tree x;
42738fd1498Szrj 
42838fd1498Szrj   x = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
42938fd1498Szrj   x = build_call_expr_loc (loc, x, 0);
43038fd1498Szrj   add_stmt (x);
43138fd1498Szrj }
43238fd1498Szrj 
43338fd1498Szrj 
43438fd1498Szrj /* Check and canonicalize OMP_FOR increment expression.
43538fd1498Szrj    Helper function for c_finish_omp_for.  */
43638fd1498Szrj 
43738fd1498Szrj static tree
check_omp_for_incr_expr(location_t loc,tree exp,tree decl)43838fd1498Szrj check_omp_for_incr_expr (location_t loc, tree exp, tree decl)
43938fd1498Szrj {
44038fd1498Szrj   tree t;
44138fd1498Szrj 
44238fd1498Szrj   if (!INTEGRAL_TYPE_P (TREE_TYPE (exp))
44338fd1498Szrj       || TYPE_PRECISION (TREE_TYPE (exp)) < TYPE_PRECISION (TREE_TYPE (decl)))
44438fd1498Szrj     return error_mark_node;
44538fd1498Szrj 
44638fd1498Szrj   if (exp == decl)
44738fd1498Szrj     return build_int_cst (TREE_TYPE (exp), 0);
44838fd1498Szrj 
44938fd1498Szrj   switch (TREE_CODE (exp))
45038fd1498Szrj     {
45138fd1498Szrj     CASE_CONVERT:
45238fd1498Szrj       t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 0), decl);
45338fd1498Szrj       if (t != error_mark_node)
45438fd1498Szrj         return fold_convert_loc (loc, TREE_TYPE (exp), t);
45538fd1498Szrj       break;
45638fd1498Szrj     case MINUS_EXPR:
45738fd1498Szrj       t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 0), decl);
45838fd1498Szrj       if (t != error_mark_node)
45938fd1498Szrj         return fold_build2_loc (loc, MINUS_EXPR,
46038fd1498Szrj 			    TREE_TYPE (exp), t, TREE_OPERAND (exp, 1));
46138fd1498Szrj       break;
46238fd1498Szrj     case PLUS_EXPR:
46338fd1498Szrj       t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 0), decl);
46438fd1498Szrj       if (t != error_mark_node)
46538fd1498Szrj         return fold_build2_loc (loc, PLUS_EXPR,
46638fd1498Szrj 			    TREE_TYPE (exp), t, TREE_OPERAND (exp, 1));
46738fd1498Szrj       t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 1), decl);
46838fd1498Szrj       if (t != error_mark_node)
46938fd1498Szrj         return fold_build2_loc (loc, PLUS_EXPR,
47038fd1498Szrj 			    TREE_TYPE (exp), TREE_OPERAND (exp, 0), t);
47138fd1498Szrj       break;
47238fd1498Szrj     case COMPOUND_EXPR:
47338fd1498Szrj       {
47438fd1498Szrj 	/* cp_build_modify_expr forces preevaluation of the RHS to make
47538fd1498Szrj 	   sure that it is evaluated before the lvalue-rvalue conversion
47638fd1498Szrj 	   is applied to the LHS.  Reconstruct the original expression.  */
47738fd1498Szrj 	tree op0 = TREE_OPERAND (exp, 0);
47838fd1498Szrj 	if (TREE_CODE (op0) == TARGET_EXPR
47938fd1498Szrj 	    && !VOID_TYPE_P (TREE_TYPE (op0)))
48038fd1498Szrj 	  {
48138fd1498Szrj 	    tree op1 = TREE_OPERAND (exp, 1);
48238fd1498Szrj 	    tree temp = TARGET_EXPR_SLOT (op0);
48338fd1498Szrj 	    if (BINARY_CLASS_P (op1)
48438fd1498Szrj 		&& TREE_OPERAND (op1, 1) == temp)
48538fd1498Szrj 	      {
48638fd1498Szrj 		op1 = copy_node (op1);
48738fd1498Szrj 		TREE_OPERAND (op1, 1) = TARGET_EXPR_INITIAL (op0);
48838fd1498Szrj 		return check_omp_for_incr_expr (loc, op1, decl);
48938fd1498Szrj 	      }
49038fd1498Szrj 	  }
49138fd1498Szrj 	break;
49238fd1498Szrj       }
49338fd1498Szrj     default:
49438fd1498Szrj       break;
49538fd1498Szrj     }
49638fd1498Szrj 
49738fd1498Szrj   return error_mark_node;
49838fd1498Szrj }
49938fd1498Szrj 
50038fd1498Szrj /* If the OMP_FOR increment expression in INCR is of pointer type,
50138fd1498Szrj    canonicalize it into an expression handled by gimplify_omp_for()
50238fd1498Szrj    and return it.  DECL is the iteration variable.  */
50338fd1498Szrj 
50438fd1498Szrj static tree
c_omp_for_incr_canonicalize_ptr(location_t loc,tree decl,tree incr)50538fd1498Szrj c_omp_for_incr_canonicalize_ptr (location_t loc, tree decl, tree incr)
50638fd1498Szrj {
50738fd1498Szrj   if (POINTER_TYPE_P (TREE_TYPE (decl))
50838fd1498Szrj       && TREE_OPERAND (incr, 1))
50938fd1498Szrj     {
51038fd1498Szrj       tree t = fold_convert_loc (loc,
51138fd1498Szrj 				 sizetype, TREE_OPERAND (incr, 1));
51238fd1498Szrj 
51338fd1498Szrj       if (TREE_CODE (incr) == POSTDECREMENT_EXPR
51438fd1498Szrj 	  || TREE_CODE (incr) == PREDECREMENT_EXPR)
51538fd1498Szrj 	t = fold_build1_loc (loc, NEGATE_EXPR, sizetype, t);
51638fd1498Szrj       t = fold_build_pointer_plus (decl, t);
51738fd1498Szrj       incr = build2 (MODIFY_EXPR, void_type_node, decl, t);
51838fd1498Szrj     }
51938fd1498Szrj   return incr;
52038fd1498Szrj }
52138fd1498Szrj 
52238fd1498Szrj /* Validate and generate OMP_FOR.
52338fd1498Szrj    DECLV is a vector of iteration variables, for each collapsed loop.
52438fd1498Szrj 
52538fd1498Szrj    ORIG_DECLV, if non-NULL, is a vector with the original iteration
52638fd1498Szrj    variables (prior to any transformations, by say, C++ iterators).
52738fd1498Szrj 
52838fd1498Szrj    INITV, CONDV and INCRV are vectors containing initialization
52938fd1498Szrj    expressions, controlling predicates and increment expressions.
53038fd1498Szrj    BODY is the body of the loop and PRE_BODY statements that go before
53138fd1498Szrj    the loop.  */
53238fd1498Szrj 
53338fd1498Szrj tree
c_finish_omp_for(location_t locus,enum tree_code code,tree declv,tree orig_declv,tree initv,tree condv,tree incrv,tree body,tree pre_body)53438fd1498Szrj c_finish_omp_for (location_t locus, enum tree_code code, tree declv,
53538fd1498Szrj 		  tree orig_declv, tree initv, tree condv, tree incrv,
53638fd1498Szrj 		  tree body, tree pre_body)
53738fd1498Szrj {
53838fd1498Szrj   location_t elocus;
53938fd1498Szrj   bool fail = false;
54038fd1498Szrj   int i;
54138fd1498Szrj 
54238fd1498Szrj   gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (initv));
54338fd1498Szrj   gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (condv));
54438fd1498Szrj   gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (incrv));
54538fd1498Szrj   for (i = 0; i < TREE_VEC_LENGTH (declv); i++)
54638fd1498Szrj     {
54738fd1498Szrj       tree decl = TREE_VEC_ELT (declv, i);
54838fd1498Szrj       tree init = TREE_VEC_ELT (initv, i);
54938fd1498Szrj       tree cond = TREE_VEC_ELT (condv, i);
55038fd1498Szrj       tree incr = TREE_VEC_ELT (incrv, i);
55138fd1498Szrj 
55238fd1498Szrj       elocus = locus;
55338fd1498Szrj       if (EXPR_HAS_LOCATION (init))
55438fd1498Szrj 	elocus = EXPR_LOCATION (init);
55538fd1498Szrj 
55638fd1498Szrj       /* Validate the iteration variable.  */
55738fd1498Szrj       if (!INTEGRAL_TYPE_P (TREE_TYPE (decl))
55838fd1498Szrj 	  && TREE_CODE (TREE_TYPE (decl)) != POINTER_TYPE)
55938fd1498Szrj 	{
56038fd1498Szrj 	  error_at (elocus, "invalid type for iteration variable %qE", decl);
56138fd1498Szrj 	  fail = true;
56238fd1498Szrj 	}
56338fd1498Szrj       else if (TYPE_ATOMIC (TREE_TYPE (decl)))
56438fd1498Szrj 	{
56538fd1498Szrj 	  error_at (elocus, "%<_Atomic%> iteration variable %qE", decl);
56638fd1498Szrj 	  fail = true;
56738fd1498Szrj 	  /* _Atomic iterator confuses stuff too much, so we risk ICE
56838fd1498Szrj 	     trying to diagnose it further.  */
56938fd1498Szrj 	  continue;
57038fd1498Szrj 	}
57138fd1498Szrj 
57238fd1498Szrj       /* In the case of "for (int i = 0...)", init will be a decl.  It should
57338fd1498Szrj 	 have a DECL_INITIAL that we can turn into an assignment.  */
57438fd1498Szrj       if (init == decl)
57538fd1498Szrj 	{
57638fd1498Szrj 	  elocus = DECL_SOURCE_LOCATION (decl);
57738fd1498Szrj 
57838fd1498Szrj 	  init = DECL_INITIAL (decl);
57938fd1498Szrj 	  if (init == NULL)
58038fd1498Szrj 	    {
58138fd1498Szrj 	      error_at (elocus, "%qE is not initialized", decl);
58238fd1498Szrj 	      init = integer_zero_node;
58338fd1498Szrj 	      fail = true;
58438fd1498Szrj 	    }
58538fd1498Szrj 	  DECL_INITIAL (decl) = NULL_TREE;
58638fd1498Szrj 
58738fd1498Szrj 	  init = build_modify_expr (elocus, decl, NULL_TREE, NOP_EXPR,
58838fd1498Szrj 	      			    /* FIXME diagnostics: This should
58938fd1498Szrj 				       be the location of the INIT.  */
59038fd1498Szrj 	      			    elocus,
59138fd1498Szrj 				    init,
59238fd1498Szrj 				    NULL_TREE);
59338fd1498Szrj 	}
59438fd1498Szrj       if (init != error_mark_node)
59538fd1498Szrj 	{
59638fd1498Szrj 	  gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
59738fd1498Szrj 	  gcc_assert (TREE_OPERAND (init, 0) == decl);
59838fd1498Szrj 	}
59938fd1498Szrj 
60038fd1498Szrj       if (cond == NULL_TREE)
60138fd1498Szrj 	{
60238fd1498Szrj 	  error_at (elocus, "missing controlling predicate");
60338fd1498Szrj 	  fail = true;
60438fd1498Szrj 	}
60538fd1498Szrj       else
60638fd1498Szrj 	{
60738fd1498Szrj 	  bool cond_ok = false;
60838fd1498Szrj 
60938fd1498Szrj 	  /* E.g. C sizeof (vla) could add COMPOUND_EXPRs with
61038fd1498Szrj 	     evaluation of the vla VAR_DECL.  We need to readd
61138fd1498Szrj 	     them to the non-decl operand.  See PR45784.  */
61238fd1498Szrj 	  while (TREE_CODE (cond) == COMPOUND_EXPR)
61338fd1498Szrj 	    cond = TREE_OPERAND (cond, 1);
61438fd1498Szrj 
61538fd1498Szrj 	  if (EXPR_HAS_LOCATION (cond))
61638fd1498Szrj 	    elocus = EXPR_LOCATION (cond);
61738fd1498Szrj 
61838fd1498Szrj 	  if (TREE_CODE (cond) == LT_EXPR
61938fd1498Szrj 	      || TREE_CODE (cond) == LE_EXPR
62038fd1498Szrj 	      || TREE_CODE (cond) == GT_EXPR
62138fd1498Szrj 	      || TREE_CODE (cond) == GE_EXPR
62238fd1498Szrj 	      || TREE_CODE (cond) == NE_EXPR
62338fd1498Szrj 	      || TREE_CODE (cond) == EQ_EXPR)
62438fd1498Szrj 	    {
62538fd1498Szrj 	      tree op0 = TREE_OPERAND (cond, 0);
62638fd1498Szrj 	      tree op1 = TREE_OPERAND (cond, 1);
62738fd1498Szrj 
62838fd1498Szrj 	      /* 2.5.1.  The comparison in the condition is computed in
62938fd1498Szrj 		 the type of DECL, otherwise the behavior is undefined.
63038fd1498Szrj 
63138fd1498Szrj 		 For example:
63238fd1498Szrj 		 long n; int i;
63338fd1498Szrj 		 i < n;
63438fd1498Szrj 
63538fd1498Szrj 		 according to ISO will be evaluated as:
63638fd1498Szrj 		 (long)i < n;
63738fd1498Szrj 
63838fd1498Szrj 		 We want to force:
63938fd1498Szrj 		 i < (int)n;  */
64038fd1498Szrj 	      if (TREE_CODE (op0) == NOP_EXPR
64138fd1498Szrj 		  && decl == TREE_OPERAND (op0, 0))
64238fd1498Szrj 		{
64338fd1498Szrj 		  TREE_OPERAND (cond, 0) = TREE_OPERAND (op0, 0);
64438fd1498Szrj 		  TREE_OPERAND (cond, 1)
64538fd1498Szrj 		    = fold_build1_loc (elocus, NOP_EXPR, TREE_TYPE (decl),
64638fd1498Szrj 				   TREE_OPERAND (cond, 1));
64738fd1498Szrj 		}
64838fd1498Szrj 	      else if (TREE_CODE (op1) == NOP_EXPR
64938fd1498Szrj 		       && decl == TREE_OPERAND (op1, 0))
65038fd1498Szrj 		{
65138fd1498Szrj 		  TREE_OPERAND (cond, 1) = TREE_OPERAND (op1, 0);
65238fd1498Szrj 		  TREE_OPERAND (cond, 0)
65338fd1498Szrj 		    = fold_build1_loc (elocus, NOP_EXPR, TREE_TYPE (decl),
65438fd1498Szrj 				   TREE_OPERAND (cond, 0));
65538fd1498Szrj 		}
65638fd1498Szrj 
65738fd1498Szrj 	      if (decl == TREE_OPERAND (cond, 0))
65838fd1498Szrj 		cond_ok = true;
65938fd1498Szrj 	      else if (decl == TREE_OPERAND (cond, 1))
66038fd1498Szrj 		{
66138fd1498Szrj 		  TREE_SET_CODE (cond,
66238fd1498Szrj 				 swap_tree_comparison (TREE_CODE (cond)));
66338fd1498Szrj 		  TREE_OPERAND (cond, 1) = TREE_OPERAND (cond, 0);
66438fd1498Szrj 		  TREE_OPERAND (cond, 0) = decl;
66538fd1498Szrj 		  cond_ok = true;
66638fd1498Szrj 		}
66738fd1498Szrj 
66838fd1498Szrj 	      if (TREE_CODE (cond) == NE_EXPR
66938fd1498Szrj 		  || TREE_CODE (cond) == EQ_EXPR)
67038fd1498Szrj 		{
67138fd1498Szrj 		  if (!INTEGRAL_TYPE_P (TREE_TYPE (decl)))
67238fd1498Szrj 		    {
67338fd1498Szrj 		      cond_ok = false;
67438fd1498Szrj 		    }
67538fd1498Szrj 		  else if (operand_equal_p (TREE_OPERAND (cond, 1),
67638fd1498Szrj 					    TYPE_MIN_VALUE (TREE_TYPE (decl)),
67738fd1498Szrj 					    0))
67838fd1498Szrj 		    TREE_SET_CODE (cond, TREE_CODE (cond) == NE_EXPR
67938fd1498Szrj 					 ? GT_EXPR : LE_EXPR);
68038fd1498Szrj 		  else if (operand_equal_p (TREE_OPERAND (cond, 1),
68138fd1498Szrj 					    TYPE_MAX_VALUE (TREE_TYPE (decl)),
68238fd1498Szrj 					    0))
68338fd1498Szrj 		    TREE_SET_CODE (cond, TREE_CODE (cond) == NE_EXPR
68438fd1498Szrj 					 ? LT_EXPR : GE_EXPR);
68538fd1498Szrj 		  else
68638fd1498Szrj 		    cond_ok = false;
68738fd1498Szrj 		}
68838fd1498Szrj 
68938fd1498Szrj 	      if (cond_ok && TREE_VEC_ELT (condv, i) != cond)
69038fd1498Szrj 		{
69138fd1498Szrj 		  tree ce = NULL_TREE, *pce = &ce;
69238fd1498Szrj 		  tree type = TREE_TYPE (TREE_OPERAND (cond, 1));
69338fd1498Szrj 		  for (tree c = TREE_VEC_ELT (condv, i); c != cond;
69438fd1498Szrj 		       c = TREE_OPERAND (c, 1))
69538fd1498Szrj 		    {
69638fd1498Szrj 		      *pce = build2 (COMPOUND_EXPR, type, TREE_OPERAND (c, 0),
69738fd1498Szrj 				     TREE_OPERAND (cond, 1));
69838fd1498Szrj 		      pce = &TREE_OPERAND (*pce, 1);
69938fd1498Szrj 		    }
70038fd1498Szrj 		  TREE_OPERAND (cond, 1) = ce;
70138fd1498Szrj 		  TREE_VEC_ELT (condv, i) = cond;
70238fd1498Szrj 		}
70338fd1498Szrj 	    }
70438fd1498Szrj 
70538fd1498Szrj 	  if (!cond_ok)
70638fd1498Szrj 	    {
70738fd1498Szrj 	      error_at (elocus, "invalid controlling predicate");
70838fd1498Szrj 	      fail = true;
70938fd1498Szrj 	    }
71038fd1498Szrj 	}
71138fd1498Szrj 
71238fd1498Szrj       if (incr == NULL_TREE)
71338fd1498Szrj 	{
71438fd1498Szrj 	  error_at (elocus, "missing increment expression");
71538fd1498Szrj 	  fail = true;
71638fd1498Szrj 	}
71738fd1498Szrj       else
71838fd1498Szrj 	{
71938fd1498Szrj 	  bool incr_ok = false;
72038fd1498Szrj 
72138fd1498Szrj 	  if (EXPR_HAS_LOCATION (incr))
72238fd1498Szrj 	    elocus = EXPR_LOCATION (incr);
72338fd1498Szrj 
72438fd1498Szrj 	  /* Check all the valid increment expressions: v++, v--, ++v, --v,
72538fd1498Szrj 	     v = v + incr, v = incr + v and v = v - incr.  */
72638fd1498Szrj 	  switch (TREE_CODE (incr))
72738fd1498Szrj 	    {
72838fd1498Szrj 	    case POSTINCREMENT_EXPR:
72938fd1498Szrj 	    case PREINCREMENT_EXPR:
73038fd1498Szrj 	    case POSTDECREMENT_EXPR:
73138fd1498Szrj 	    case PREDECREMENT_EXPR:
73238fd1498Szrj 	      if (TREE_OPERAND (incr, 0) != decl)
73338fd1498Szrj 		break;
73438fd1498Szrj 
73538fd1498Szrj 	      incr_ok = true;
73638fd1498Szrj 	      incr = c_omp_for_incr_canonicalize_ptr (elocus, decl, incr);
73738fd1498Szrj 	      break;
73838fd1498Szrj 
73938fd1498Szrj 	    case COMPOUND_EXPR:
74038fd1498Szrj 	      if (TREE_CODE (TREE_OPERAND (incr, 0)) != SAVE_EXPR
74138fd1498Szrj 		  || TREE_CODE (TREE_OPERAND (incr, 1)) != MODIFY_EXPR)
74238fd1498Szrj 		break;
74338fd1498Szrj 	      incr = TREE_OPERAND (incr, 1);
74438fd1498Szrj 	      /* FALLTHRU */
74538fd1498Szrj 	    case MODIFY_EXPR:
74638fd1498Szrj 	      if (TREE_OPERAND (incr, 0) != decl)
74738fd1498Szrj 		break;
74838fd1498Szrj 	      if (TREE_OPERAND (incr, 1) == decl)
74938fd1498Szrj 		break;
75038fd1498Szrj 	      if (TREE_CODE (TREE_OPERAND (incr, 1)) == PLUS_EXPR
75138fd1498Szrj 		  && (TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl
75238fd1498Szrj 		      || TREE_OPERAND (TREE_OPERAND (incr, 1), 1) == decl))
75338fd1498Szrj 		incr_ok = true;
75438fd1498Szrj 	      else if ((TREE_CODE (TREE_OPERAND (incr, 1)) == MINUS_EXPR
75538fd1498Szrj 			|| (TREE_CODE (TREE_OPERAND (incr, 1))
75638fd1498Szrj 			    == POINTER_PLUS_EXPR))
75738fd1498Szrj 		       && TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl)
75838fd1498Szrj 		incr_ok = true;
75938fd1498Szrj 	      else
76038fd1498Szrj 		{
76138fd1498Szrj 		  tree t = check_omp_for_incr_expr (elocus,
76238fd1498Szrj 						    TREE_OPERAND (incr, 1),
76338fd1498Szrj 						    decl);
76438fd1498Szrj 		  if (t != error_mark_node)
76538fd1498Szrj 		    {
76638fd1498Szrj 		      incr_ok = true;
76738fd1498Szrj 		      t = build2 (PLUS_EXPR, TREE_TYPE (decl), decl, t);
76838fd1498Szrj 		      incr = build2 (MODIFY_EXPR, void_type_node, decl, t);
76938fd1498Szrj 		    }
77038fd1498Szrj 		}
77138fd1498Szrj 	      break;
77238fd1498Szrj 
77338fd1498Szrj 	    default:
77438fd1498Szrj 	      break;
77538fd1498Szrj 	    }
77638fd1498Szrj 	  if (!incr_ok)
77738fd1498Szrj 	    {
77838fd1498Szrj 	      error_at (elocus, "invalid increment expression");
77938fd1498Szrj 	      fail = true;
78038fd1498Szrj 	    }
78138fd1498Szrj 	}
78238fd1498Szrj 
78338fd1498Szrj       TREE_VEC_ELT (initv, i) = init;
78438fd1498Szrj       TREE_VEC_ELT (incrv, i) = incr;
78538fd1498Szrj     }
78638fd1498Szrj 
78738fd1498Szrj   if (fail)
78838fd1498Szrj     return NULL;
78938fd1498Szrj   else
79038fd1498Szrj     {
79138fd1498Szrj       tree t = make_node (code);
79238fd1498Szrj 
79338fd1498Szrj       TREE_TYPE (t) = void_type_node;
79438fd1498Szrj       OMP_FOR_INIT (t) = initv;
79538fd1498Szrj       OMP_FOR_COND (t) = condv;
79638fd1498Szrj       OMP_FOR_INCR (t) = incrv;
79738fd1498Szrj       OMP_FOR_BODY (t) = body;
79838fd1498Szrj       OMP_FOR_PRE_BODY (t) = pre_body;
79938fd1498Szrj       OMP_FOR_ORIG_DECLS (t) = orig_declv;
80038fd1498Szrj 
80138fd1498Szrj       SET_EXPR_LOCATION (t, locus);
80238fd1498Szrj       return t;
80338fd1498Szrj     }
80438fd1498Szrj }
80538fd1498Szrj 
80638fd1498Szrj /* Type for passing data in between c_omp_check_loop_iv and
80738fd1498Szrj    c_omp_check_loop_iv_r.  */
80838fd1498Szrj 
80938fd1498Szrj struct c_omp_check_loop_iv_data
81038fd1498Szrj {
81138fd1498Szrj   tree declv;
81238fd1498Szrj   bool fail;
81338fd1498Szrj   location_t stmt_loc;
81438fd1498Szrj   location_t expr_loc;
81538fd1498Szrj   int kind;
81638fd1498Szrj   walk_tree_lh lh;
81738fd1498Szrj   hash_set<tree> *ppset;
81838fd1498Szrj };
81938fd1498Szrj 
82038fd1498Szrj /* Helper function called via walk_tree, to diagnose uses
82138fd1498Szrj    of associated loop IVs inside of lb, b and incr expressions
82238fd1498Szrj    of OpenMP loops.  */
82338fd1498Szrj 
82438fd1498Szrj static tree
c_omp_check_loop_iv_r(tree * tp,int * walk_subtrees,void * data)82538fd1498Szrj c_omp_check_loop_iv_r (tree *tp, int *walk_subtrees, void *data)
82638fd1498Szrj {
82738fd1498Szrj   struct c_omp_check_loop_iv_data *d
82838fd1498Szrj     = (struct c_omp_check_loop_iv_data *) data;
82938fd1498Szrj   if (DECL_P (*tp))
83038fd1498Szrj     {
83138fd1498Szrj       int i;
83238fd1498Szrj       for (i = 0; i < TREE_VEC_LENGTH (d->declv); i++)
83338fd1498Szrj 	if (*tp == TREE_VEC_ELT (d->declv, i))
83438fd1498Szrj 	  {
83538fd1498Szrj 	    location_t loc = d->expr_loc;
83638fd1498Szrj 	    if (loc == UNKNOWN_LOCATION)
83738fd1498Szrj 	      loc = d->stmt_loc;
83838fd1498Szrj 	    switch (d->kind)
83938fd1498Szrj 	      {
84038fd1498Szrj 	      case 0:
84138fd1498Szrj 		error_at (loc, "initializer expression refers to "
84238fd1498Szrj 			       "iteration variable %qD", *tp);
84338fd1498Szrj 		break;
84438fd1498Szrj 	      case 1:
84538fd1498Szrj 		error_at (loc, "condition expression refers to "
84638fd1498Szrj 			       "iteration variable %qD", *tp);
84738fd1498Szrj 		break;
84838fd1498Szrj 	      case 2:
84938fd1498Szrj 		error_at (loc, "increment expression refers to "
85038fd1498Szrj 			       "iteration variable %qD", *tp);
85138fd1498Szrj 		break;
85238fd1498Szrj 	      }
85338fd1498Szrj 	    d->fail = true;
85438fd1498Szrj 	  }
85538fd1498Szrj     }
85638fd1498Szrj   /* Don't walk dtors added by C++ wrap_cleanups_r.  */
85738fd1498Szrj   else if (TREE_CODE (*tp) == TRY_CATCH_EXPR
85838fd1498Szrj 	   && TRY_CATCH_IS_CLEANUP (*tp))
85938fd1498Szrj     {
86038fd1498Szrj       *walk_subtrees = 0;
86138fd1498Szrj       return walk_tree_1 (&TREE_OPERAND (*tp, 0), c_omp_check_loop_iv_r, data,
86238fd1498Szrj 			  d->ppset, d->lh);
86338fd1498Szrj     }
86438fd1498Szrj 
86538fd1498Szrj   return NULL_TREE;
86638fd1498Szrj }
86738fd1498Szrj 
86838fd1498Szrj /* Diagnose invalid references to loop iterators in lb, b and incr
86938fd1498Szrj    expressions.  */
87038fd1498Szrj 
87138fd1498Szrj bool
c_omp_check_loop_iv(tree stmt,tree declv,walk_tree_lh lh)87238fd1498Szrj c_omp_check_loop_iv (tree stmt, tree declv, walk_tree_lh lh)
87338fd1498Szrj {
87438fd1498Szrj   hash_set<tree> pset;
87538fd1498Szrj   struct c_omp_check_loop_iv_data data;
87638fd1498Szrj   int i;
87738fd1498Szrj 
87838fd1498Szrj   data.declv = declv;
87938fd1498Szrj   data.fail = false;
88038fd1498Szrj   data.stmt_loc = EXPR_LOCATION (stmt);
88138fd1498Szrj   data.lh = lh;
88238fd1498Szrj   data.ppset = &pset;
88338fd1498Szrj   for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (stmt)); i++)
88438fd1498Szrj     {
88538fd1498Szrj       tree init = TREE_VEC_ELT (OMP_FOR_INIT (stmt), i);
88638fd1498Szrj       gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
88738fd1498Szrj       tree decl = TREE_OPERAND (init, 0);
88838fd1498Szrj       tree cond = TREE_VEC_ELT (OMP_FOR_COND (stmt), i);
88938fd1498Szrj       gcc_assert (COMPARISON_CLASS_P (cond));
89038fd1498Szrj       gcc_assert (TREE_OPERAND (cond, 0) == decl);
89138fd1498Szrj       tree incr = TREE_VEC_ELT (OMP_FOR_INCR (stmt), i);
89238fd1498Szrj       data.expr_loc = EXPR_LOCATION (TREE_OPERAND (init, 1));
89338fd1498Szrj       data.kind = 0;
89438fd1498Szrj       walk_tree_1 (&TREE_OPERAND (init, 1),
89538fd1498Szrj 		   c_omp_check_loop_iv_r, &data, &pset, lh);
89638fd1498Szrj       /* Don't warn for C++ random access iterators here, the
89738fd1498Szrj 	 expression then involves the subtraction and always refers
89838fd1498Szrj 	 to the original value.  The C++ FE needs to warn on those
89938fd1498Szrj 	 earlier.  */
90038fd1498Szrj       if (decl == TREE_VEC_ELT (declv, i))
90138fd1498Szrj 	{
90238fd1498Szrj 	  data.expr_loc = EXPR_LOCATION (cond);
90338fd1498Szrj 	  data.kind = 1;
90438fd1498Szrj 	  walk_tree_1 (&TREE_OPERAND (cond, 1),
90538fd1498Szrj 		       c_omp_check_loop_iv_r, &data, &pset, lh);
90638fd1498Szrj 	}
90738fd1498Szrj       if (TREE_CODE (incr) == MODIFY_EXPR)
90838fd1498Szrj 	{
90938fd1498Szrj 	  gcc_assert (TREE_OPERAND (incr, 0) == decl);
91038fd1498Szrj 	  incr = TREE_OPERAND (incr, 1);
91138fd1498Szrj 	  data.kind = 2;
91238fd1498Szrj 	  if (TREE_CODE (incr) == PLUS_EXPR
91338fd1498Szrj 	      && TREE_OPERAND (incr, 1) == decl)
91438fd1498Szrj 	    {
91538fd1498Szrj 	      data.expr_loc = EXPR_LOCATION (TREE_OPERAND (incr, 0));
91638fd1498Szrj 	      walk_tree_1 (&TREE_OPERAND (incr, 0),
91738fd1498Szrj 			   c_omp_check_loop_iv_r, &data, &pset, lh);
91838fd1498Szrj 	    }
91938fd1498Szrj 	  else
92038fd1498Szrj 	    {
92138fd1498Szrj 	      data.expr_loc = EXPR_LOCATION (TREE_OPERAND (incr, 1));
92238fd1498Szrj 	      walk_tree_1 (&TREE_OPERAND (incr, 1),
92338fd1498Szrj 			   c_omp_check_loop_iv_r, &data, &pset, lh);
92438fd1498Szrj 	    }
92538fd1498Szrj 	}
92638fd1498Szrj     }
92738fd1498Szrj   return !data.fail;
92838fd1498Szrj }
92938fd1498Szrj 
93038fd1498Szrj /* Similar, but allows to check the init or cond expressions individually.  */
93138fd1498Szrj 
93238fd1498Szrj bool
c_omp_check_loop_iv_exprs(location_t stmt_loc,tree declv,tree decl,tree init,tree cond,walk_tree_lh lh)93338fd1498Szrj c_omp_check_loop_iv_exprs (location_t stmt_loc, tree declv, tree decl,
93438fd1498Szrj 			   tree init, tree cond, walk_tree_lh lh)
93538fd1498Szrj {
93638fd1498Szrj   hash_set<tree> pset;
93738fd1498Szrj   struct c_omp_check_loop_iv_data data;
93838fd1498Szrj 
93938fd1498Szrj   data.declv = declv;
94038fd1498Szrj   data.fail = false;
94138fd1498Szrj   data.stmt_loc = stmt_loc;
94238fd1498Szrj   data.lh = lh;
94338fd1498Szrj   data.ppset = &pset;
94438fd1498Szrj   if (init)
94538fd1498Szrj     {
94638fd1498Szrj       data.expr_loc = EXPR_LOCATION (init);
94738fd1498Szrj       data.kind = 0;
94838fd1498Szrj       walk_tree_1 (&init,
94938fd1498Szrj 		   c_omp_check_loop_iv_r, &data, &pset, lh);
95038fd1498Szrj     }
95138fd1498Szrj   if (cond)
95238fd1498Szrj     {
95338fd1498Szrj       gcc_assert (COMPARISON_CLASS_P (cond));
95438fd1498Szrj       data.expr_loc = EXPR_LOCATION (init);
95538fd1498Szrj       data.kind = 1;
95638fd1498Szrj       if (TREE_OPERAND (cond, 0) == decl)
95738fd1498Szrj 	walk_tree_1 (&TREE_OPERAND (cond, 1),
95838fd1498Szrj 		     c_omp_check_loop_iv_r, &data, &pset, lh);
95938fd1498Szrj       else
96038fd1498Szrj 	walk_tree_1 (&TREE_OPERAND (cond, 0),
96138fd1498Szrj 		     c_omp_check_loop_iv_r, &data, &pset, lh);
96238fd1498Szrj     }
96338fd1498Szrj   return !data.fail;
96438fd1498Szrj }
96538fd1498Szrj 
96638fd1498Szrj /* This function splits clauses for OpenACC combined loop
96738fd1498Szrj    constructs.  OpenACC combined loop constructs are:
96838fd1498Szrj    #pragma acc kernels loop
96938fd1498Szrj    #pragma acc parallel loop  */
97038fd1498Szrj 
97138fd1498Szrj tree
c_oacc_split_loop_clauses(tree clauses,tree * not_loop_clauses,bool is_parallel)97238fd1498Szrj c_oacc_split_loop_clauses (tree clauses, tree *not_loop_clauses,
97338fd1498Szrj 			   bool is_parallel)
97438fd1498Szrj {
97538fd1498Szrj   tree next, loop_clauses, nc;
97638fd1498Szrj 
97738fd1498Szrj   loop_clauses = *not_loop_clauses = NULL_TREE;
97838fd1498Szrj   for (; clauses ; clauses = next)
97938fd1498Szrj     {
98038fd1498Szrj       next = OMP_CLAUSE_CHAIN (clauses);
98138fd1498Szrj 
98238fd1498Szrj       switch (OMP_CLAUSE_CODE (clauses))
98338fd1498Szrj         {
98438fd1498Szrj 	  /* Loop clauses.  */
98538fd1498Szrj 	case OMP_CLAUSE_COLLAPSE:
98638fd1498Szrj 	case OMP_CLAUSE_TILE:
98738fd1498Szrj 	case OMP_CLAUSE_GANG:
98838fd1498Szrj 	case OMP_CLAUSE_WORKER:
98938fd1498Szrj 	case OMP_CLAUSE_VECTOR:
99038fd1498Szrj 	case OMP_CLAUSE_AUTO:
99138fd1498Szrj 	case OMP_CLAUSE_SEQ:
99238fd1498Szrj 	case OMP_CLAUSE_INDEPENDENT:
99338fd1498Szrj 	case OMP_CLAUSE_PRIVATE:
99438fd1498Szrj 	  OMP_CLAUSE_CHAIN (clauses) = loop_clauses;
99538fd1498Szrj 	  loop_clauses = clauses;
99638fd1498Szrj 	  break;
99738fd1498Szrj 
99838fd1498Szrj 	  /* Reductions must be duplicated on both constructs.  */
99938fd1498Szrj 	case OMP_CLAUSE_REDUCTION:
100038fd1498Szrj 	  if (is_parallel)
100138fd1498Szrj 	    {
100238fd1498Szrj 	      nc = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
100338fd1498Szrj 				     OMP_CLAUSE_REDUCTION);
100438fd1498Szrj 	      OMP_CLAUSE_DECL (nc) = OMP_CLAUSE_DECL (clauses);
100538fd1498Szrj 	      OMP_CLAUSE_REDUCTION_CODE (nc)
100638fd1498Szrj 		= OMP_CLAUSE_REDUCTION_CODE (clauses);
100738fd1498Szrj 	      OMP_CLAUSE_CHAIN (nc) = *not_loop_clauses;
100838fd1498Szrj 	      *not_loop_clauses = nc;
100938fd1498Szrj 	    }
101038fd1498Szrj 
101138fd1498Szrj 	  OMP_CLAUSE_CHAIN (clauses) = loop_clauses;
101238fd1498Szrj 	  loop_clauses = clauses;
101338fd1498Szrj 	  break;
101438fd1498Szrj 
101538fd1498Szrj 	  /* Parallel/kernels clauses.  */
101638fd1498Szrj 	default:
101738fd1498Szrj 	  OMP_CLAUSE_CHAIN (clauses) = *not_loop_clauses;
101838fd1498Szrj 	  *not_loop_clauses = clauses;
101938fd1498Szrj 	  break;
102038fd1498Szrj 	}
102138fd1498Szrj     }
102238fd1498Szrj 
102338fd1498Szrj   return loop_clauses;
102438fd1498Szrj }
102538fd1498Szrj 
102638fd1498Szrj /* This function attempts to split or duplicate clauses for OpenMP
102738fd1498Szrj    combined/composite constructs.  Right now there are 21 different
102838fd1498Szrj    constructs.  CODE is the innermost construct in the combined construct,
102938fd1498Szrj    and MASK allows to determine which constructs are combined together,
103038fd1498Szrj    as every construct has at least one clause that no other construct
103138fd1498Szrj    has (except for OMP_SECTIONS, but that can be only combined with parallel).
103238fd1498Szrj    OpenMP combined/composite constructs are:
103338fd1498Szrj    #pragma omp distribute parallel for
103438fd1498Szrj    #pragma omp distribute parallel for simd
103538fd1498Szrj    #pragma omp distribute simd
103638fd1498Szrj    #pragma omp for simd
103738fd1498Szrj    #pragma omp parallel for
103838fd1498Szrj    #pragma omp parallel for simd
103938fd1498Szrj    #pragma omp parallel sections
104038fd1498Szrj    #pragma omp target parallel
104138fd1498Szrj    #pragma omp target parallel for
104238fd1498Szrj    #pragma omp target parallel for simd
104338fd1498Szrj    #pragma omp target teams
104438fd1498Szrj    #pragma omp target teams distribute
104538fd1498Szrj    #pragma omp target teams distribute parallel for
104638fd1498Szrj    #pragma omp target teams distribute parallel for simd
104738fd1498Szrj    #pragma omp target teams distribute simd
104838fd1498Szrj    #pragma omp target simd
104938fd1498Szrj    #pragma omp taskloop simd
105038fd1498Szrj    #pragma omp teams distribute
105138fd1498Szrj    #pragma omp teams distribute parallel for
105238fd1498Szrj    #pragma omp teams distribute parallel for simd
105338fd1498Szrj    #pragma omp teams distribute simd  */
105438fd1498Szrj 
105538fd1498Szrj void
c_omp_split_clauses(location_t loc,enum tree_code code,omp_clause_mask mask,tree clauses,tree * cclauses)105638fd1498Szrj c_omp_split_clauses (location_t loc, enum tree_code code,
105738fd1498Szrj 		     omp_clause_mask mask, tree clauses, tree *cclauses)
105838fd1498Szrj {
105938fd1498Szrj   tree next, c;
106038fd1498Szrj   enum c_omp_clause_split s;
106138fd1498Szrj   int i;
106238fd1498Szrj 
106338fd1498Szrj   for (i = 0; i < C_OMP_CLAUSE_SPLIT_COUNT; i++)
106438fd1498Szrj     cclauses[i] = NULL;
106538fd1498Szrj   /* Add implicit nowait clause on
106638fd1498Szrj      #pragma omp parallel {for,for simd,sections}.  */
106738fd1498Szrj   if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0)
106838fd1498Szrj     switch (code)
106938fd1498Szrj       {
107038fd1498Szrj       case OMP_FOR:
107138fd1498Szrj       case OMP_SIMD:
107238fd1498Szrj         cclauses[C_OMP_CLAUSE_SPLIT_FOR]
107338fd1498Szrj 	  = build_omp_clause (loc, OMP_CLAUSE_NOWAIT);
107438fd1498Szrj 	break;
107538fd1498Szrj       case OMP_SECTIONS:
107638fd1498Szrj 	cclauses[C_OMP_CLAUSE_SPLIT_SECTIONS]
107738fd1498Szrj 	  = build_omp_clause (loc, OMP_CLAUSE_NOWAIT);
107838fd1498Szrj 	break;
107938fd1498Szrj       default:
108038fd1498Szrj 	break;
108138fd1498Szrj       }
108238fd1498Szrj 
108338fd1498Szrj   for (; clauses ; clauses = next)
108438fd1498Szrj     {
108538fd1498Szrj       next = OMP_CLAUSE_CHAIN (clauses);
108638fd1498Szrj 
108738fd1498Szrj       switch (OMP_CLAUSE_CODE (clauses))
108838fd1498Szrj 	{
108938fd1498Szrj 	/* First the clauses that are unique to some constructs.  */
109038fd1498Szrj 	case OMP_CLAUSE_DEVICE:
109138fd1498Szrj 	case OMP_CLAUSE_MAP:
109238fd1498Szrj 	case OMP_CLAUSE_IS_DEVICE_PTR:
109338fd1498Szrj 	case OMP_CLAUSE_DEFAULTMAP:
109438fd1498Szrj 	case OMP_CLAUSE_DEPEND:
109538fd1498Szrj 	  s = C_OMP_CLAUSE_SPLIT_TARGET;
109638fd1498Szrj 	  break;
109738fd1498Szrj 	case OMP_CLAUSE_NUM_TEAMS:
109838fd1498Szrj 	case OMP_CLAUSE_THREAD_LIMIT:
109938fd1498Szrj 	  s = C_OMP_CLAUSE_SPLIT_TEAMS;
110038fd1498Szrj 	  break;
110138fd1498Szrj 	case OMP_CLAUSE_DIST_SCHEDULE:
110238fd1498Szrj 	  s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE;
110338fd1498Szrj 	  break;
110438fd1498Szrj 	case OMP_CLAUSE_COPYIN:
110538fd1498Szrj 	case OMP_CLAUSE_NUM_THREADS:
110638fd1498Szrj 	case OMP_CLAUSE_PROC_BIND:
110738fd1498Szrj 	  s = C_OMP_CLAUSE_SPLIT_PARALLEL;
110838fd1498Szrj 	  break;
110938fd1498Szrj 	case OMP_CLAUSE_ORDERED:
111038fd1498Szrj 	  s = C_OMP_CLAUSE_SPLIT_FOR;
111138fd1498Szrj 	  break;
111238fd1498Szrj 	case OMP_CLAUSE_SCHEDULE:
111338fd1498Szrj 	  s = C_OMP_CLAUSE_SPLIT_FOR;
111438fd1498Szrj 	  if (code != OMP_SIMD)
111538fd1498Szrj 	    OMP_CLAUSE_SCHEDULE_SIMD (clauses) = 0;
111638fd1498Szrj 	  break;
111738fd1498Szrj 	case OMP_CLAUSE_SAFELEN:
111838fd1498Szrj 	case OMP_CLAUSE_SIMDLEN:
111938fd1498Szrj 	case OMP_CLAUSE_ALIGNED:
112038fd1498Szrj 	  s = C_OMP_CLAUSE_SPLIT_SIMD;
112138fd1498Szrj 	  break;
112238fd1498Szrj 	case OMP_CLAUSE_GRAINSIZE:
112338fd1498Szrj 	case OMP_CLAUSE_NUM_TASKS:
112438fd1498Szrj 	case OMP_CLAUSE_FINAL:
112538fd1498Szrj 	case OMP_CLAUSE_UNTIED:
112638fd1498Szrj 	case OMP_CLAUSE_MERGEABLE:
112738fd1498Szrj 	case OMP_CLAUSE_NOGROUP:
112838fd1498Szrj 	case OMP_CLAUSE_PRIORITY:
112938fd1498Szrj 	  s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
113038fd1498Szrj 	  break;
113138fd1498Szrj 	/* Duplicate this to all of taskloop, distribute, for and simd.  */
113238fd1498Szrj 	case OMP_CLAUSE_COLLAPSE:
113338fd1498Szrj 	  if (code == OMP_SIMD)
113438fd1498Szrj 	    {
113538fd1498Szrj 	      if ((mask & ((OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)
113638fd1498Szrj 			   | (OMP_CLAUSE_MASK_1
113738fd1498Szrj 			      << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)
113838fd1498Szrj 			   | (OMP_CLAUSE_MASK_1
113938fd1498Szrj 			      << PRAGMA_OMP_CLAUSE_NOGROUP))) != 0)
114038fd1498Szrj 		{
114138fd1498Szrj 		  c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
114238fd1498Szrj 					OMP_CLAUSE_COLLAPSE);
114338fd1498Szrj 		  OMP_CLAUSE_COLLAPSE_EXPR (c)
114438fd1498Szrj 		    = OMP_CLAUSE_COLLAPSE_EXPR (clauses);
114538fd1498Szrj 		  OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_SIMD];
114638fd1498Szrj 		  cclauses[C_OMP_CLAUSE_SPLIT_SIMD] = c;
114738fd1498Szrj 		}
114838fd1498Szrj 	      else
114938fd1498Szrj 		{
115038fd1498Szrj 		  /* This must be #pragma omp target simd */
115138fd1498Szrj 		  s = C_OMP_CLAUSE_SPLIT_SIMD;
115238fd1498Szrj 		  break;
115338fd1498Szrj 		}
115438fd1498Szrj 	    }
115538fd1498Szrj 	  if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0)
115638fd1498Szrj 	    {
115738fd1498Szrj 	      if ((mask & (OMP_CLAUSE_MASK_1
115838fd1498Szrj 			   << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0)
115938fd1498Szrj 		{
116038fd1498Szrj 		  c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
116138fd1498Szrj 					OMP_CLAUSE_COLLAPSE);
116238fd1498Szrj 		  OMP_CLAUSE_COLLAPSE_EXPR (c)
116338fd1498Szrj 		    = OMP_CLAUSE_COLLAPSE_EXPR (clauses);
116438fd1498Szrj 		  OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_FOR];
116538fd1498Szrj 		  cclauses[C_OMP_CLAUSE_SPLIT_FOR] = c;
116638fd1498Szrj 		  s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE;
116738fd1498Szrj 		}
116838fd1498Szrj 	      else
116938fd1498Szrj 		s = C_OMP_CLAUSE_SPLIT_FOR;
117038fd1498Szrj 	    }
117138fd1498Szrj 	  else if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP))
117238fd1498Szrj 		   != 0)
117338fd1498Szrj 	    s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
117438fd1498Szrj 	  else
117538fd1498Szrj 	    s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE;
117638fd1498Szrj 	  break;
117738fd1498Szrj 	/* Private clause is supported on all constructs,
117838fd1498Szrj 	   it is enough to put it on the innermost one.  For
117938fd1498Szrj 	   #pragma omp {for,sections} put it on parallel though,
118038fd1498Szrj 	   as that's what we did for OpenMP 3.1.  */
118138fd1498Szrj 	case OMP_CLAUSE_PRIVATE:
118238fd1498Szrj 	  switch (code)
118338fd1498Szrj 	    {
118438fd1498Szrj 	    case OMP_SIMD: s = C_OMP_CLAUSE_SPLIT_SIMD; break;
118538fd1498Szrj 	    case OMP_FOR: case OMP_SECTIONS:
118638fd1498Szrj 	    case OMP_PARALLEL: s = C_OMP_CLAUSE_SPLIT_PARALLEL; break;
118738fd1498Szrj 	    case OMP_DISTRIBUTE: s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE; break;
118838fd1498Szrj 	    case OMP_TEAMS: s = C_OMP_CLAUSE_SPLIT_TEAMS; break;
118938fd1498Szrj 	    default: gcc_unreachable ();
119038fd1498Szrj 	    }
119138fd1498Szrj 	  break;
119238fd1498Szrj 	/* Firstprivate clause is supported on all constructs but
119338fd1498Szrj 	   simd.  Put it on the outermost of those and duplicate on teams
119438fd1498Szrj 	   and parallel.  */
119538fd1498Szrj 	case OMP_CLAUSE_FIRSTPRIVATE:
119638fd1498Szrj 	  if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP))
119738fd1498Szrj 	      != 0)
119838fd1498Szrj 	    {
119938fd1498Szrj 	      if (code == OMP_SIMD
120038fd1498Szrj 		  && (mask & ((OMP_CLAUSE_MASK_1
120138fd1498Szrj 			       << PRAGMA_OMP_CLAUSE_NUM_THREADS)
120238fd1498Szrj 			      | (OMP_CLAUSE_MASK_1
120338fd1498Szrj 				 << PRAGMA_OMP_CLAUSE_NUM_TEAMS))) == 0)
120438fd1498Szrj 		{
120538fd1498Szrj 		  /* This must be #pragma omp target simd.  */
120638fd1498Szrj 		  s = C_OMP_CLAUSE_SPLIT_TARGET;
120738fd1498Szrj 		  break;
120838fd1498Szrj 		}
120938fd1498Szrj 	      c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
121038fd1498Szrj 				    OMP_CLAUSE_FIRSTPRIVATE);
121138fd1498Szrj 	      OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
121238fd1498Szrj 	      OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
121338fd1498Szrj 	      cclauses[C_OMP_CLAUSE_SPLIT_TARGET] = c;
121438fd1498Szrj 	    }
121538fd1498Szrj 	  if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS))
121638fd1498Szrj 	      != 0)
121738fd1498Szrj 	    {
121838fd1498Szrj 	      if ((mask & ((OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS)
121938fd1498Szrj 			   | (OMP_CLAUSE_MASK_1
122038fd1498Szrj 			      << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE))) != 0)
122138fd1498Szrj 		{
122238fd1498Szrj 		  c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
122338fd1498Szrj 					OMP_CLAUSE_FIRSTPRIVATE);
122438fd1498Szrj 		  OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
122538fd1498Szrj 		  OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL];
122638fd1498Szrj 		  cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL] = c;
122738fd1498Szrj 		  if ((mask & (OMP_CLAUSE_MASK_1
122838fd1498Szrj 			       << PRAGMA_OMP_CLAUSE_NUM_TEAMS)) != 0)
122938fd1498Szrj 		    s = C_OMP_CLAUSE_SPLIT_TEAMS;
123038fd1498Szrj 		  else
123138fd1498Szrj 		    s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE;
123238fd1498Szrj 		}
123338fd1498Szrj 	      else
123438fd1498Szrj 		/* This must be
123538fd1498Szrj 		   #pragma omp parallel{, for{, simd}, sections}
123638fd1498Szrj 		   or
123738fd1498Szrj 		   #pragma omp target parallel.  */
123838fd1498Szrj 		s = C_OMP_CLAUSE_SPLIT_PARALLEL;
123938fd1498Szrj 	    }
124038fd1498Szrj 	  else if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS))
124138fd1498Szrj 		   != 0)
124238fd1498Szrj 	    {
124338fd1498Szrj 	      /* This must be one of
124438fd1498Szrj 		 #pragma omp {,target }teams distribute
124538fd1498Szrj 		 #pragma omp target teams
124638fd1498Szrj 		 #pragma omp {,target }teams distribute simd.  */
124738fd1498Szrj 	      gcc_assert (code == OMP_DISTRIBUTE
124838fd1498Szrj 			  || code == OMP_TEAMS
124938fd1498Szrj 			  || code == OMP_SIMD);
125038fd1498Szrj 	      s = C_OMP_CLAUSE_SPLIT_TEAMS;
125138fd1498Szrj 	    }
125238fd1498Szrj 	  else if ((mask & (OMP_CLAUSE_MASK_1
125338fd1498Szrj 			    << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0)
125438fd1498Szrj 	    {
125538fd1498Szrj 	      /* This must be #pragma omp distribute simd.  */
125638fd1498Szrj 	      gcc_assert (code == OMP_SIMD);
125738fd1498Szrj 	      s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE;
125838fd1498Szrj 	    }
125938fd1498Szrj 	  else if ((mask & (OMP_CLAUSE_MASK_1
126038fd1498Szrj 			    << PRAGMA_OMP_CLAUSE_NOGROUP)) != 0)
126138fd1498Szrj 	    {
126238fd1498Szrj 	      /* This must be #pragma omp taskloop simd.  */
126338fd1498Szrj 	      gcc_assert (code == OMP_SIMD);
126438fd1498Szrj 	      s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
126538fd1498Szrj 	    }
126638fd1498Szrj 	  else
126738fd1498Szrj 	    {
126838fd1498Szrj 	      /* This must be #pragma omp for simd.  */
126938fd1498Szrj 	      gcc_assert (code == OMP_SIMD);
127038fd1498Szrj 	      s = C_OMP_CLAUSE_SPLIT_FOR;
127138fd1498Szrj 	    }
127238fd1498Szrj 	  break;
127338fd1498Szrj 	/* Lastprivate is allowed on distribute, for, sections and simd.  In
127438fd1498Szrj 	   parallel {for{, simd},sections} we actually want to put it on
127538fd1498Szrj 	   parallel rather than for or sections.  */
127638fd1498Szrj 	case OMP_CLAUSE_LASTPRIVATE:
127738fd1498Szrj 	  if (code == OMP_DISTRIBUTE)
127838fd1498Szrj 	    {
127938fd1498Szrj 	      s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE;
128038fd1498Szrj 	      break;
128138fd1498Szrj 	    }
128238fd1498Szrj 	  if ((mask & (OMP_CLAUSE_MASK_1
128338fd1498Szrj 		       << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0)
128438fd1498Szrj 	    {
128538fd1498Szrj 	      c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
128638fd1498Szrj 				    OMP_CLAUSE_LASTPRIVATE);
128738fd1498Szrj 	      OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
128838fd1498Szrj 	      OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE];
128938fd1498Szrj 	      cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE] = c;
129038fd1498Szrj 	    }
129138fd1498Szrj 	  if (code == OMP_FOR || code == OMP_SECTIONS)
129238fd1498Szrj 	    {
129338fd1498Szrj 	      if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS))
129438fd1498Szrj 		  != 0)
129538fd1498Szrj 		s = C_OMP_CLAUSE_SPLIT_PARALLEL;
129638fd1498Szrj 	      else
129738fd1498Szrj 		s = C_OMP_CLAUSE_SPLIT_FOR;
129838fd1498Szrj 	      break;
129938fd1498Szrj 	    }
130038fd1498Szrj 	  gcc_assert (code == OMP_SIMD);
130138fd1498Szrj 	  if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0)
130238fd1498Szrj 	    {
130338fd1498Szrj 	      c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
130438fd1498Szrj 				    OMP_CLAUSE_LASTPRIVATE);
130538fd1498Szrj 	      OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
130638fd1498Szrj 	      if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS))
130738fd1498Szrj 		  != 0)
130838fd1498Szrj 		s = C_OMP_CLAUSE_SPLIT_PARALLEL;
130938fd1498Szrj 	      else
131038fd1498Szrj 		s = C_OMP_CLAUSE_SPLIT_FOR;
131138fd1498Szrj 	      OMP_CLAUSE_CHAIN (c) = cclauses[s];
131238fd1498Szrj 	      cclauses[s] = c;
131338fd1498Szrj 	    }
131438fd1498Szrj 	  s = C_OMP_CLAUSE_SPLIT_SIMD;
131538fd1498Szrj 	  break;
131638fd1498Szrj 	/* Shared and default clauses are allowed on parallel, teams and
131738fd1498Szrj 	   taskloop.  */
131838fd1498Szrj 	case OMP_CLAUSE_SHARED:
131938fd1498Szrj 	case OMP_CLAUSE_DEFAULT:
132038fd1498Szrj 	  if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP))
132138fd1498Szrj 	      != 0)
132238fd1498Szrj 	    {
132338fd1498Szrj 	      s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
132438fd1498Szrj 	      break;
132538fd1498Szrj 	    }
132638fd1498Szrj 	  if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS))
132738fd1498Szrj 	      != 0)
132838fd1498Szrj 	    {
132938fd1498Szrj 	      if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS))
133038fd1498Szrj 		  == 0)
133138fd1498Szrj 		{
133238fd1498Szrj 		  s = C_OMP_CLAUSE_SPLIT_TEAMS;
133338fd1498Szrj 		  break;
133438fd1498Szrj 		}
133538fd1498Szrj 	      c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
133638fd1498Szrj 				    OMP_CLAUSE_CODE (clauses));
133738fd1498Szrj 	      if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_SHARED)
133838fd1498Szrj 		OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
133938fd1498Szrj 	      else
134038fd1498Szrj 		OMP_CLAUSE_DEFAULT_KIND (c)
134138fd1498Szrj 		  = OMP_CLAUSE_DEFAULT_KIND (clauses);
134238fd1498Szrj 	      OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
134338fd1498Szrj 	      cclauses[C_OMP_CLAUSE_SPLIT_TEAMS] = c;
134438fd1498Szrj 	    }
134538fd1498Szrj 	  s = C_OMP_CLAUSE_SPLIT_PARALLEL;
134638fd1498Szrj 	  break;
134738fd1498Szrj 	/* Reduction is allowed on simd, for, parallel, sections and teams.
134838fd1498Szrj 	   Duplicate it on all of them, but omit on for or sections if
134938fd1498Szrj 	   parallel is present.  */
135038fd1498Szrj 	case OMP_CLAUSE_REDUCTION:
135138fd1498Szrj 	  if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0)
135238fd1498Szrj 	    {
135338fd1498Szrj 	      if (code == OMP_SIMD)
135438fd1498Szrj 		{
135538fd1498Szrj 		  c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
135638fd1498Szrj 					OMP_CLAUSE_REDUCTION);
135738fd1498Szrj 		  OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
135838fd1498Szrj 		  OMP_CLAUSE_REDUCTION_CODE (c)
135938fd1498Szrj 		    = OMP_CLAUSE_REDUCTION_CODE (clauses);
136038fd1498Szrj 		  OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
136138fd1498Szrj 		    = OMP_CLAUSE_REDUCTION_PLACEHOLDER (clauses);
136238fd1498Szrj 		  OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c)
136338fd1498Szrj 		    = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clauses);
136438fd1498Szrj 		  OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_SIMD];
136538fd1498Szrj 		  cclauses[C_OMP_CLAUSE_SPLIT_SIMD] = c;
136638fd1498Szrj 		}
136738fd1498Szrj 	      if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS))
136838fd1498Szrj 		  != 0)
136938fd1498Szrj 		{
137038fd1498Szrj 		  c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
137138fd1498Szrj 					OMP_CLAUSE_REDUCTION);
137238fd1498Szrj 		  OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
137338fd1498Szrj 		  OMP_CLAUSE_REDUCTION_CODE (c)
137438fd1498Szrj 		    = OMP_CLAUSE_REDUCTION_CODE (clauses);
137538fd1498Szrj 		  OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
137638fd1498Szrj 		    = OMP_CLAUSE_REDUCTION_PLACEHOLDER (clauses);
137738fd1498Szrj 		  OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c)
137838fd1498Szrj 		    = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clauses);
137938fd1498Szrj 		  OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL];
138038fd1498Szrj 		  cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL] = c;
138138fd1498Szrj 		  s = C_OMP_CLAUSE_SPLIT_TEAMS;
138238fd1498Szrj 		}
138338fd1498Szrj 	      else if ((mask & (OMP_CLAUSE_MASK_1
138438fd1498Szrj 				<< PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0)
138538fd1498Szrj 		s = C_OMP_CLAUSE_SPLIT_PARALLEL;
138638fd1498Szrj 	      else
138738fd1498Szrj 		s = C_OMP_CLAUSE_SPLIT_FOR;
138838fd1498Szrj 	    }
138938fd1498Szrj 	  else if (code == OMP_SECTIONS || code == OMP_PARALLEL)
139038fd1498Szrj 	    s = C_OMP_CLAUSE_SPLIT_PARALLEL;
139138fd1498Szrj 	  else if (code == OMP_SIMD)
139238fd1498Szrj 	    s = C_OMP_CLAUSE_SPLIT_SIMD;
139338fd1498Szrj 	  else
139438fd1498Szrj 	    s = C_OMP_CLAUSE_SPLIT_TEAMS;
139538fd1498Szrj 	  break;
139638fd1498Szrj 	case OMP_CLAUSE_IF:
139738fd1498Szrj 	  if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP))
139838fd1498Szrj 	      != 0)
139938fd1498Szrj 	    s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
140038fd1498Szrj 	  else if ((mask & (OMP_CLAUSE_MASK_1
140138fd1498Szrj 			    << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0)
140238fd1498Szrj 	    {
140338fd1498Szrj 	      if ((mask & (OMP_CLAUSE_MASK_1
140438fd1498Szrj 			   << PRAGMA_OMP_CLAUSE_MAP)) != 0)
140538fd1498Szrj 		{
140638fd1498Szrj 		  if (OMP_CLAUSE_IF_MODIFIER (clauses) == OMP_PARALLEL)
140738fd1498Szrj 		    s = C_OMP_CLAUSE_SPLIT_PARALLEL;
140838fd1498Szrj 		  else if (OMP_CLAUSE_IF_MODIFIER (clauses) == OMP_TARGET)
140938fd1498Szrj 		    s = C_OMP_CLAUSE_SPLIT_TARGET;
141038fd1498Szrj 		  else if (OMP_CLAUSE_IF_MODIFIER (clauses) == ERROR_MARK)
141138fd1498Szrj 		    {
141238fd1498Szrj 		      c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
141338fd1498Szrj 					    OMP_CLAUSE_IF);
141438fd1498Szrj 		      OMP_CLAUSE_IF_MODIFIER (c)
141538fd1498Szrj 			= OMP_CLAUSE_IF_MODIFIER (clauses);
141638fd1498Szrj 		      OMP_CLAUSE_IF_EXPR (c) = OMP_CLAUSE_IF_EXPR (clauses);
141738fd1498Szrj 		      OMP_CLAUSE_CHAIN (c)
141838fd1498Szrj 			= cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
141938fd1498Szrj 		      cclauses[C_OMP_CLAUSE_SPLIT_TARGET] = c;
142038fd1498Szrj 		      s = C_OMP_CLAUSE_SPLIT_PARALLEL;
142138fd1498Szrj 		    }
142238fd1498Szrj 		  else
142338fd1498Szrj 		    {
142438fd1498Szrj 		      error_at (OMP_CLAUSE_LOCATION (clauses),
142538fd1498Szrj 				"expected %<parallel%> or %<target%> %<if%> "
142638fd1498Szrj 				"clause modifier");
142738fd1498Szrj 		      continue;
142838fd1498Szrj 		    }
142938fd1498Szrj 		}
143038fd1498Szrj 	      else
143138fd1498Szrj 		s = C_OMP_CLAUSE_SPLIT_PARALLEL;
143238fd1498Szrj 	    }
143338fd1498Szrj 	  else
143438fd1498Szrj 	    s = C_OMP_CLAUSE_SPLIT_TARGET;
143538fd1498Szrj 	  break;
143638fd1498Szrj 	case OMP_CLAUSE_LINEAR:
143738fd1498Szrj 	  /* Linear clause is allowed on simd and for.  Put it on the
143838fd1498Szrj 	     innermost construct.  */
143938fd1498Szrj 	  if (code == OMP_SIMD)
144038fd1498Szrj 	    s = C_OMP_CLAUSE_SPLIT_SIMD;
144138fd1498Szrj 	  else
144238fd1498Szrj 	    s = C_OMP_CLAUSE_SPLIT_FOR;
144338fd1498Szrj 	  break;
144438fd1498Szrj 	case OMP_CLAUSE_NOWAIT:
144538fd1498Szrj 	  /* Nowait clause is allowed on target, for and sections, but
144638fd1498Szrj 	     is not allowed on parallel for or parallel sections.  Therefore,
144738fd1498Szrj 	     put it on target construct if present, because that can only
144838fd1498Szrj 	     be combined with parallel for{, simd} and not with for{, simd},
144938fd1498Szrj 	     otherwise to the worksharing construct.  */
145038fd1498Szrj 	  if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP))
145138fd1498Szrj 	      != 0)
145238fd1498Szrj 	    s = C_OMP_CLAUSE_SPLIT_TARGET;
145338fd1498Szrj 	  else
145438fd1498Szrj 	    s = C_OMP_CLAUSE_SPLIT_FOR;
145538fd1498Szrj 	  break;
145638fd1498Szrj 	default:
145738fd1498Szrj 	  gcc_unreachable ();
145838fd1498Szrj 	}
145938fd1498Szrj       OMP_CLAUSE_CHAIN (clauses) = cclauses[s];
146038fd1498Szrj       cclauses[s] = clauses;
146138fd1498Szrj     }
146238fd1498Szrj 
146338fd1498Szrj   if (!flag_checking)
146438fd1498Szrj     return;
146538fd1498Szrj 
146638fd1498Szrj   if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)) == 0)
146738fd1498Szrj     gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_TARGET] == NULL_TREE);
146838fd1498Szrj   if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS)) == 0)
146938fd1498Szrj     gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_TEAMS] == NULL_TREE);
147038fd1498Szrj   if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) == 0)
147138fd1498Szrj     gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE] == NULL_TREE);
147238fd1498Szrj   if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS)) == 0)
147338fd1498Szrj     gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL] == NULL_TREE);
147438fd1498Szrj   if ((mask & ((OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)
147538fd1498Szrj 	       | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP))) == 0
147638fd1498Szrj       && code != OMP_SECTIONS)
147738fd1498Szrj     gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_FOR] == NULL_TREE);
147838fd1498Szrj   if (code != OMP_SIMD)
147938fd1498Szrj     gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_SIMD] == NULL_TREE);
148038fd1498Szrj }
148138fd1498Szrj 
148238fd1498Szrj 
148338fd1498Szrj /* qsort callback to compare #pragma omp declare simd clauses.  */
148438fd1498Szrj 
148538fd1498Szrj static int
c_omp_declare_simd_clause_cmp(const void * p,const void * q)148638fd1498Szrj c_omp_declare_simd_clause_cmp (const void *p, const void *q)
148738fd1498Szrj {
148838fd1498Szrj   tree a = *(const tree *) p;
148938fd1498Szrj   tree b = *(const tree *) q;
149038fd1498Szrj   if (OMP_CLAUSE_CODE (a) != OMP_CLAUSE_CODE (b))
149138fd1498Szrj     {
149238fd1498Szrj       if (OMP_CLAUSE_CODE (a) > OMP_CLAUSE_CODE (b))
149338fd1498Szrj 	return -1;
149438fd1498Szrj       return 1;
149538fd1498Szrj     }
149638fd1498Szrj   if (OMP_CLAUSE_CODE (a) != OMP_CLAUSE_SIMDLEN
149738fd1498Szrj       && OMP_CLAUSE_CODE (a) != OMP_CLAUSE_INBRANCH
149838fd1498Szrj       && OMP_CLAUSE_CODE (a) != OMP_CLAUSE_NOTINBRANCH)
149938fd1498Szrj     {
150038fd1498Szrj       int c = tree_to_shwi (OMP_CLAUSE_DECL (a));
150138fd1498Szrj       int d = tree_to_shwi (OMP_CLAUSE_DECL (b));
150238fd1498Szrj       if (c < d)
150338fd1498Szrj 	return 1;
150438fd1498Szrj       if (c > d)
150538fd1498Szrj 	return -1;
150638fd1498Szrj     }
150738fd1498Szrj   return 0;
150838fd1498Szrj }
150938fd1498Szrj 
151038fd1498Szrj /* Change PARM_DECLs in OMP_CLAUSE_DECL of #pragma omp declare simd
151138fd1498Szrj    CLAUSES on FNDECL into argument indexes and sort them.  */
151238fd1498Szrj 
151338fd1498Szrj tree
c_omp_declare_simd_clauses_to_numbers(tree parms,tree clauses)151438fd1498Szrj c_omp_declare_simd_clauses_to_numbers (tree parms, tree clauses)
151538fd1498Szrj {
151638fd1498Szrj   tree c;
151738fd1498Szrj   vec<tree> clvec = vNULL;
151838fd1498Szrj 
151938fd1498Szrj   for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
152038fd1498Szrj     {
152138fd1498Szrj       if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_SIMDLEN
152238fd1498Szrj 	  && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_INBRANCH
152338fd1498Szrj 	  && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_NOTINBRANCH)
152438fd1498Szrj 	{
152538fd1498Szrj 	  tree decl = OMP_CLAUSE_DECL (c);
152638fd1498Szrj 	  tree arg;
152738fd1498Szrj 	  int idx;
152838fd1498Szrj 	  for (arg = parms, idx = 0; arg;
152938fd1498Szrj 	       arg = TREE_CHAIN (arg), idx++)
153038fd1498Szrj 	    if (arg == decl)
153138fd1498Szrj 	      break;
153238fd1498Szrj 	  if (arg == NULL_TREE)
153338fd1498Szrj 	    {
153438fd1498Szrj 	      error_at (OMP_CLAUSE_LOCATION (c),
153538fd1498Szrj 			"%qD is not an function argument", decl);
153638fd1498Szrj 	      continue;
153738fd1498Szrj 	    }
153838fd1498Szrj 	  OMP_CLAUSE_DECL (c) = build_int_cst (integer_type_node, idx);
153938fd1498Szrj 	  if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
154038fd1498Szrj 	      && OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (c))
154138fd1498Szrj 	    {
154238fd1498Szrj 	      decl = OMP_CLAUSE_LINEAR_STEP (c);
154338fd1498Szrj 	      for (arg = parms, idx = 0; arg;
154438fd1498Szrj 		   arg = TREE_CHAIN (arg), idx++)
154538fd1498Szrj 		if (arg == decl)
154638fd1498Szrj 		  break;
154738fd1498Szrj 	      if (arg == NULL_TREE)
154838fd1498Szrj 		{
154938fd1498Szrj 		  error_at (OMP_CLAUSE_LOCATION (c),
155038fd1498Szrj 			    "%qD is not an function argument", decl);
155138fd1498Szrj 		  continue;
155238fd1498Szrj 		}
155338fd1498Szrj 	      OMP_CLAUSE_LINEAR_STEP (c)
155438fd1498Szrj 		= build_int_cst (integer_type_node, idx);
155538fd1498Szrj 	    }
155638fd1498Szrj 	}
155738fd1498Szrj       clvec.safe_push (c);
155838fd1498Szrj     }
155938fd1498Szrj   if (!clvec.is_empty ())
156038fd1498Szrj     {
156138fd1498Szrj       unsigned int len = clvec.length (), i;
156238fd1498Szrj       clvec.qsort (c_omp_declare_simd_clause_cmp);
156338fd1498Szrj       clauses = clvec[0];
156438fd1498Szrj       for (i = 0; i < len; i++)
156538fd1498Szrj 	OMP_CLAUSE_CHAIN (clvec[i]) = (i < len - 1) ? clvec[i + 1] : NULL_TREE;
156638fd1498Szrj     }
156738fd1498Szrj   else
156838fd1498Szrj     clauses = NULL_TREE;
156938fd1498Szrj   clvec.release ();
157038fd1498Szrj   return clauses;
157138fd1498Szrj }
157238fd1498Szrj 
157338fd1498Szrj /* Change argument indexes in CLAUSES of FNDECL back to PARM_DECLs.  */
157438fd1498Szrj 
157538fd1498Szrj void
c_omp_declare_simd_clauses_to_decls(tree fndecl,tree clauses)157638fd1498Szrj c_omp_declare_simd_clauses_to_decls (tree fndecl, tree clauses)
157738fd1498Szrj {
157838fd1498Szrj   tree c;
157938fd1498Szrj 
158038fd1498Szrj   for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
158138fd1498Szrj     if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_SIMDLEN
158238fd1498Szrj 	&& OMP_CLAUSE_CODE (c) != OMP_CLAUSE_INBRANCH
158338fd1498Szrj 	&& OMP_CLAUSE_CODE (c) != OMP_CLAUSE_NOTINBRANCH)
158438fd1498Szrj       {
158538fd1498Szrj 	int idx = tree_to_shwi (OMP_CLAUSE_DECL (c)), i;
158638fd1498Szrj 	tree arg;
158738fd1498Szrj 	for (arg = DECL_ARGUMENTS (fndecl), i = 0; arg;
158838fd1498Szrj 	     arg = TREE_CHAIN (arg), i++)
158938fd1498Szrj 	  if (i == idx)
159038fd1498Szrj 	    break;
159138fd1498Szrj 	gcc_assert (arg);
159238fd1498Szrj 	OMP_CLAUSE_DECL (c) = arg;
159338fd1498Szrj 	if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
159438fd1498Szrj 	    && OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (c))
159538fd1498Szrj 	  {
159638fd1498Szrj 	    idx = tree_to_shwi (OMP_CLAUSE_LINEAR_STEP (c));
159738fd1498Szrj 	    for (arg = DECL_ARGUMENTS (fndecl), i = 0; arg;
159838fd1498Szrj 		 arg = TREE_CHAIN (arg), i++)
159938fd1498Szrj 	      if (i == idx)
160038fd1498Szrj 		break;
160138fd1498Szrj 	    gcc_assert (arg);
160238fd1498Szrj 	    OMP_CLAUSE_LINEAR_STEP (c) = arg;
160338fd1498Szrj 	  }
160438fd1498Szrj       }
160538fd1498Szrj }
160638fd1498Szrj 
160738fd1498Szrj /* True if OpenMP sharing attribute of DECL is predetermined.  */
160838fd1498Szrj 
160938fd1498Szrj enum omp_clause_default_kind
c_omp_predetermined_sharing(tree decl)161038fd1498Szrj c_omp_predetermined_sharing (tree decl)
161138fd1498Szrj {
161238fd1498Szrj   /* Variables with const-qualified type having no mutable member
161338fd1498Szrj      are predetermined shared.  */
161438fd1498Szrj   if (TREE_READONLY (decl))
161538fd1498Szrj     return OMP_CLAUSE_DEFAULT_SHARED;
161638fd1498Szrj 
1617*58e805e6Szrj   /* Predetermine artificial variables holding integral values, those
1618*58e805e6Szrj      are usually result of gimplify_one_sizepos or SAVE_EXPR
1619*58e805e6Szrj      gimplification.  */
1620*58e805e6Szrj   if (VAR_P (decl)
1621*58e805e6Szrj       && DECL_ARTIFICIAL (decl)
1622*58e805e6Szrj       && INTEGRAL_TYPE_P (TREE_TYPE (decl)))
1623*58e805e6Szrj     return OMP_CLAUSE_DEFAULT_SHARED;
1624*58e805e6Szrj 
162538fd1498Szrj   return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
162638fd1498Szrj }
1627