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