Branch data Line data Source code
1 : : /* This file contains routines to construct OpenACC and OpenMP constructs,
2 : : called from parsing in the C and C++ front ends.
3 : :
4 : : Copyright (C) 2005-2025 Free Software Foundation, Inc.
5 : : Contributed by Richard Henderson <rth@redhat.com>,
6 : : Diego Novillo <dnovillo@redhat.com>.
7 : :
8 : : This file is part of GCC.
9 : :
10 : : GCC is free software; you can redistribute it and/or modify it under
11 : : the terms of the GNU General Public License as published by the Free
12 : : Software Foundation; either version 3, or (at your option) any later
13 : : version.
14 : :
15 : : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
16 : : WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 : : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 : : for more details.
19 : :
20 : : You should have received a copy of the GNU General Public License
21 : : along with GCC; see the file COPYING3. If not see
22 : : <http://www.gnu.org/licenses/>. */
23 : :
24 : : #include "config.h"
25 : : #include "system.h"
26 : : #include "coretypes.h"
27 : : #include "options.h"
28 : : #include "c-common.h"
29 : : #include "gimple-expr.h"
30 : : #include "c-pragma.h"
31 : : #include "stringpool.h"
32 : : #include "omp-general.h"
33 : : #include "gomp-constants.h"
34 : : #include "memmodel.h"
35 : : #include "attribs.h"
36 : : #include "gimplify.h"
37 : : #include "langhooks.h"
38 : : #include "bitmap.h"
39 : : #include "tree-iterator.h"
40 : :
41 : :
42 : : /* Complete a #pragma oacc wait construct. LOC is the location of
43 : : the #pragma. */
44 : :
45 : : tree
46 : 217 : c_finish_oacc_wait (location_t loc, tree parms, tree clauses)
47 : : {
48 : 217 : const int nparms = list_length (parms);
49 : 217 : tree stmt, t;
50 : 217 : vec<tree, va_gc> *args;
51 : :
52 : 217 : vec_alloc (args, nparms + 2);
53 : 217 : stmt = builtin_decl_explicit (BUILT_IN_GOACC_WAIT);
54 : :
55 : 217 : if (omp_find_clause (clauses, OMP_CLAUSE_ASYNC))
56 : 35 : t = OMP_CLAUSE_ASYNC_EXPR (clauses);
57 : : else
58 : 182 : t = build_int_cst (integer_type_node, GOMP_ASYNC_SYNC);
59 : :
60 : 217 : args->quick_push (t);
61 : 217 : args->quick_push (build_int_cst (integer_type_node, nparms));
62 : :
63 : 332 : for (t = parms; t; t = TREE_CHAIN (t))
64 : : {
65 : 115 : if (TREE_CODE (OMP_CLAUSE_WAIT_EXPR (t)) == INTEGER_CST)
66 : 42 : args->quick_push (build_int_cst (integer_type_node,
67 : 42 : TREE_INT_CST_LOW (OMP_CLAUSE_WAIT_EXPR (t))));
68 : : else
69 : 73 : args->quick_push (OMP_CLAUSE_WAIT_EXPR (t));
70 : : }
71 : :
72 : 217 : stmt = build_call_expr_loc_vec (loc, stmt, args);
73 : :
74 : 217 : vec_free (args);
75 : :
76 : 217 : return stmt;
77 : : }
78 : :
79 : : /* Complete a #pragma omp master construct. STMT is the structured-block
80 : : that follows the pragma. LOC is the location of the #pragma. */
81 : :
82 : : tree
83 : 730 : c_finish_omp_master (location_t loc, tree stmt)
84 : : {
85 : 730 : tree t = add_stmt (build1 (OMP_MASTER, void_type_node, stmt));
86 : 730 : SET_EXPR_LOCATION (t, loc);
87 : 730 : return t;
88 : : }
89 : :
90 : : /* Complete a #pragma omp masked construct. BODY is the structured-block
91 : : that follows the pragma. LOC is the location of the #pragma. */
92 : :
93 : : tree
94 : 377 : c_finish_omp_masked (location_t loc, tree body, tree clauses)
95 : : {
96 : 377 : tree stmt = make_node (OMP_MASKED);
97 : 377 : TREE_TYPE (stmt) = void_type_node;
98 : 377 : OMP_MASKED_BODY (stmt) = body;
99 : 377 : OMP_MASKED_CLAUSES (stmt) = clauses;
100 : 377 : SET_EXPR_LOCATION (stmt, loc);
101 : 377 : return add_stmt (stmt);
102 : : }
103 : :
104 : : /* Complete a #pragma omp taskgroup construct. BODY is the structured-block
105 : : that follows the pragma. LOC is the location of the #pragma. */
106 : :
107 : : tree
108 : 430 : c_finish_omp_taskgroup (location_t loc, tree body, tree clauses)
109 : : {
110 : 430 : tree stmt = make_node (OMP_TASKGROUP);
111 : 430 : TREE_TYPE (stmt) = void_type_node;
112 : 430 : OMP_TASKGROUP_BODY (stmt) = body;
113 : 430 : OMP_TASKGROUP_CLAUSES (stmt) = clauses;
114 : 430 : SET_EXPR_LOCATION (stmt, loc);
115 : 430 : return add_stmt (stmt);
116 : : }
117 : :
118 : : /* Complete a #pragma omp critical construct. BODY is the structured-block
119 : : that follows the pragma, NAME is the identifier in the pragma, or null
120 : : if it was omitted. LOC is the location of the #pragma. */
121 : :
122 : : tree
123 : 411 : c_finish_omp_critical (location_t loc, tree body, tree name, tree clauses)
124 : : {
125 : 492 : gcc_assert (!clauses || OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_HINT);
126 : 411 : if (name == NULL_TREE
127 : 411 : && clauses != NULL_TREE
128 : 411 : && integer_nonzerop (OMP_CLAUSE_HINT_EXPR (clauses)))
129 : : {
130 : 2 : error_at (OMP_CLAUSE_LOCATION (clauses),
131 : : "%<#pragma omp critical%> with %<hint%> clause requires "
132 : : "a name, except when %<omp_sync_hint_none%> is used");
133 : 2 : return error_mark_node;
134 : : }
135 : :
136 : 409 : tree stmt = make_node (OMP_CRITICAL);
137 : 409 : TREE_TYPE (stmt) = void_type_node;
138 : 409 : OMP_CRITICAL_BODY (stmt) = body;
139 : 409 : OMP_CRITICAL_NAME (stmt) = name;
140 : 409 : OMP_CRITICAL_CLAUSES (stmt) = clauses;
141 : 409 : SET_EXPR_LOCATION (stmt, loc);
142 : 409 : return add_stmt (stmt);
143 : : }
144 : :
145 : : /* Complete a #pragma omp ordered construct. STMT is the structured-block
146 : : that follows the pragma. LOC is the location of the #pragma. */
147 : :
148 : : tree
149 : 1558 : c_finish_omp_ordered (location_t loc, tree clauses, tree stmt)
150 : : {
151 : 1558 : tree t = make_node (OMP_ORDERED);
152 : 1558 : TREE_TYPE (t) = void_type_node;
153 : 1558 : OMP_ORDERED_BODY (t) = stmt;
154 : 1558 : if (!flag_openmp /* flag_openmp_simd */
155 : 1598 : && (OMP_CLAUSE_CODE (clauses) != OMP_CLAUSE_SIMD
156 : 40 : || OMP_CLAUSE_CHAIN (clauses)))
157 : 4 : clauses = build_omp_clause (loc, OMP_CLAUSE_SIMD);
158 : 1558 : OMP_ORDERED_CLAUSES (t) = clauses;
159 : 1558 : SET_EXPR_LOCATION (t, loc);
160 : 1558 : return add_stmt (t);
161 : : }
162 : :
163 : :
164 : : /* Complete a #pragma omp barrier construct. LOC is the location of
165 : : the #pragma. */
166 : :
167 : : void
168 : 348 : c_finish_omp_barrier (location_t loc)
169 : : {
170 : 348 : tree x;
171 : :
172 : 348 : x = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER);
173 : 348 : x = build_call_expr_loc (loc, x, 0);
174 : 348 : add_stmt (x);
175 : 348 : }
176 : :
177 : :
178 : : /* Complete a #pragma omp taskwait construct. LOC is the location of the
179 : : pragma. */
180 : :
181 : : void
182 : 72 : c_finish_omp_taskwait (location_t loc)
183 : : {
184 : 72 : tree x;
185 : :
186 : 72 : x = builtin_decl_explicit (BUILT_IN_GOMP_TASKWAIT);
187 : 72 : x = build_call_expr_loc (loc, x, 0);
188 : 72 : add_stmt (x);
189 : 72 : }
190 : :
191 : :
192 : : /* Complete a #pragma omp taskyield construct. LOC is the location of the
193 : : pragma. */
194 : :
195 : : void
196 : 6 : c_finish_omp_taskyield (location_t loc)
197 : : {
198 : 6 : tree x;
199 : :
200 : 6 : x = builtin_decl_explicit (BUILT_IN_GOMP_TASKYIELD);
201 : 6 : x = build_call_expr_loc (loc, x, 0);
202 : 6 : add_stmt (x);
203 : 6 : }
204 : :
205 : :
206 : : /* Complete a #pragma omp atomic construct. For CODE OMP_ATOMIC
207 : : the expression to be implemented atomically is LHS opcode= RHS.
208 : : For OMP_ATOMIC_READ V = LHS, for OMP_ATOMIC_CAPTURE_{NEW,OLD} LHS
209 : : opcode= RHS with the new or old content of LHS returned.
210 : : LOC is the location of the atomic statement. The value returned
211 : : is either error_mark_node (if the construct was erroneous) or an
212 : : OMP_ATOMIC* node which should be added to the current statement
213 : : tree with add_stmt. If TEST is set, avoid calling save_expr
214 : : or create_tmp_var*. */
215 : :
216 : : tree
217 : 4592 : c_finish_omp_atomic (location_t loc, enum tree_code code,
218 : : enum tree_code opcode, tree lhs, tree rhs,
219 : : tree v, tree lhs1, tree rhs1, tree r, bool swapped,
220 : : enum omp_memory_order memory_order, bool weak,
221 : : bool test)
222 : : {
223 : 4592 : tree x, type, addr, pre = NULL_TREE, rtmp = NULL_TREE, vtmp = NULL_TREE;
224 : 4592 : HOST_WIDE_INT bitpos = 0, bitsize = 0;
225 : 4592 : enum tree_code orig_opcode = opcode;
226 : :
227 : 4592 : if (lhs == error_mark_node || rhs == error_mark_node
228 : 4592 : || v == error_mark_node || lhs1 == error_mark_node
229 : 4592 : || rhs1 == error_mark_node || r == error_mark_node)
230 : : return error_mark_node;
231 : :
232 : : /* ??? According to one reading of the OpenMP spec, complex type are
233 : : supported, but there are no atomic stores for any architecture.
234 : : But at least icc 9.0 doesn't support complex types here either.
235 : : And lets not even talk about vector types... */
236 : 4592 : type = TREE_TYPE (lhs);
237 : 4592 : if (!INTEGRAL_TYPE_P (type)
238 : 882 : && !POINTER_TYPE_P (type)
239 : 872 : && !SCALAR_FLOAT_TYPE_P (type))
240 : : {
241 : 7 : error_at (loc, "invalid expression type for %<#pragma omp atomic%>");
242 : 7 : return error_mark_node;
243 : : }
244 : 4585 : if (TYPE_ATOMIC (type))
245 : : {
246 : 8 : error_at (loc, "%<_Atomic%> expression in %<#pragma omp atomic%>");
247 : 8 : return error_mark_node;
248 : : }
249 : 4577 : if (r && r != void_list_node && !INTEGRAL_TYPE_P (TREE_TYPE (r)))
250 : : {
251 : 4 : error_at (loc, "%<#pragma omp atomic compare capture%> with non-integral "
252 : : "comparison result");
253 : 4 : return error_mark_node;
254 : : }
255 : :
256 : 4573 : if (opcode == RDIV_EXPR)
257 : 0 : opcode = TRUNC_DIV_EXPR;
258 : :
259 : : /* ??? Validate that rhs does not overlap lhs. */
260 : 4573 : tree blhs = NULL;
261 : 4573 : if (TREE_CODE (lhs) == COMPONENT_REF
262 : 69 : && TREE_CODE (TREE_OPERAND (lhs, 1)) == FIELD_DECL
263 : 69 : && DECL_C_BIT_FIELD (TREE_OPERAND (lhs, 1))
264 : 4623 : && DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (lhs, 1)))
265 : : {
266 : 50 : tree field = TREE_OPERAND (lhs, 1);
267 : 50 : tree repr = DECL_BIT_FIELD_REPRESENTATIVE (field);
268 : 50 : if (tree_fits_uhwi_p (DECL_FIELD_OFFSET (field))
269 : 100 : && tree_fits_uhwi_p (DECL_FIELD_OFFSET (repr)))
270 : 50 : bitpos = (tree_to_uhwi (DECL_FIELD_OFFSET (field))
271 : 50 : - tree_to_uhwi (DECL_FIELD_OFFSET (repr))) * BITS_PER_UNIT;
272 : : else
273 : : bitpos = 0;
274 : 50 : bitpos += (tree_to_uhwi (DECL_FIELD_BIT_OFFSET (field))
275 : 50 : - tree_to_uhwi (DECL_FIELD_BIT_OFFSET (repr)));
276 : 50 : gcc_assert (tree_fits_shwi_p (DECL_SIZE (field)));
277 : 50 : bitsize = tree_to_shwi (DECL_SIZE (field));
278 : 50 : blhs = lhs;
279 : 50 : type = TREE_TYPE (repr);
280 : 50 : lhs = build3 (COMPONENT_REF, TREE_TYPE (repr), TREE_OPERAND (lhs, 0),
281 : 50 : repr, TREE_OPERAND (lhs, 2));
282 : : }
283 : :
284 : : /* Take and save the address of the lhs. From then on we'll reference it
285 : : via indirection. */
286 : 4573 : addr = build_unary_op (loc, ADDR_EXPR, lhs, false);
287 : 4573 : if (addr == error_mark_node)
288 : : return error_mark_node;
289 : 4564 : if (!test)
290 : 4351 : addr = save_expr (addr);
291 : 4351 : if (!test
292 : 4351 : && TREE_CODE (addr) != SAVE_EXPR
293 : 3756 : && (TREE_CODE (addr) != ADDR_EXPR
294 : 3577 : || !VAR_P (TREE_OPERAND (addr, 0))))
295 : : {
296 : : /* Make sure LHS is simple enough so that goa_lhs_expr_p can recognize
297 : : it even after unsharing function body. */
298 : 364 : tree var = create_tmp_var_raw (TREE_TYPE (addr));
299 : 364 : DECL_CONTEXT (var) = current_function_decl;
300 : 364 : addr = build4 (TARGET_EXPR, TREE_TYPE (addr), var, addr, NULL, NULL);
301 : : }
302 : 4564 : tree orig_lhs = lhs;
303 : 4564 : lhs = build_indirect_ref (loc, addr, RO_NULL);
304 : 4564 : tree new_lhs = lhs;
305 : :
306 : 4564 : if (code == OMP_ATOMIC_READ)
307 : : {
308 : 750 : x = build1 (OMP_ATOMIC_READ, type, addr);
309 : 750 : SET_EXPR_LOCATION (x, loc);
310 : 750 : OMP_ATOMIC_MEMORY_ORDER (x) = memory_order;
311 : 750 : gcc_assert (!weak);
312 : 750 : if (blhs)
313 : 2 : x = build3_loc (loc, BIT_FIELD_REF, TREE_TYPE (blhs), x,
314 : 2 : bitsize_int (bitsize), bitsize_int (bitpos));
315 : 750 : return build_modify_expr (loc, v, NULL_TREE, NOP_EXPR,
316 : 750 : loc, x, NULL_TREE);
317 : : }
318 : :
319 : : /* There are lots of warnings, errors, and conversions that need to happen
320 : : in the course of interpreting a statement. Use the normal mechanisms
321 : : to do this, and then take it apart again. */
322 : 3814 : if (blhs)
323 : : {
324 : 48 : lhs = build3_loc (loc, BIT_FIELD_REF, TREE_TYPE (blhs), lhs,
325 : 48 : bitsize_int (bitsize), bitsize_int (bitpos));
326 : 48 : if (opcode == COND_EXPR)
327 : : {
328 : 16 : bool save = in_late_binary_op;
329 : 16 : in_late_binary_op = true;
330 : 16 : std::swap (rhs, rhs1);
331 : 16 : rhs1 = build_binary_op (loc, EQ_EXPR, lhs, rhs1, true);
332 : 16 : in_late_binary_op = save;
333 : : }
334 : 32 : else if (swapped)
335 : 0 : rhs = build_binary_op (loc, opcode, rhs, lhs, true);
336 : 32 : else if (opcode != NOP_EXPR)
337 : 26 : rhs = build_binary_op (loc, opcode, lhs, rhs, true);
338 : : opcode = NOP_EXPR;
339 : : }
340 : 3766 : else if (opcode == COND_EXPR)
341 : : {
342 : 334 : bool save = in_late_binary_op;
343 : 334 : in_late_binary_op = true;
344 : 334 : std::swap (rhs, rhs1);
345 : 334 : rhs1 = build_binary_op (loc, EQ_EXPR, lhs, rhs1, true);
346 : 334 : in_late_binary_op = save;
347 : 334 : opcode = NOP_EXPR;
348 : : }
349 : 3432 : else if (swapped)
350 : : {
351 : 124 : rhs = build_binary_op (loc, opcode, rhs, lhs, true);
352 : 124 : opcode = NOP_EXPR;
353 : : }
354 : 3814 : bool save = in_late_binary_op;
355 : 3814 : in_late_binary_op = true;
356 : 3814 : if ((opcode == MIN_EXPR || opcode == MAX_EXPR)
357 : 4102 : && build_binary_op (loc, LT_EXPR, blhs ? blhs : lhs, rhs,
358 : 288 : true) == error_mark_node)
359 : : x = error_mark_node;
360 : : else
361 : 7572 : x = build_modify_expr (loc, blhs ? blhs : lhs, NULL_TREE, opcode,
362 : : loc, rhs, NULL_TREE);
363 : 3814 : in_late_binary_op = save;
364 : 3814 : if (x == error_mark_node)
365 : : return error_mark_node;
366 : 3794 : if (TREE_CODE (x) == COMPOUND_EXPR)
367 : : {
368 : 14 : pre = TREE_OPERAND (x, 0);
369 : 14 : gcc_assert (TREE_CODE (pre) == SAVE_EXPR || tree_invariant_p (pre));
370 : 14 : x = TREE_OPERAND (x, 1);
371 : : }
372 : 3794 : gcc_assert (TREE_CODE (x) == MODIFY_EXPR);
373 : 3794 : rhs = TREE_OPERAND (x, 1);
374 : :
375 : 3794 : if (blhs)
376 : 48 : rhs = build3_loc (loc, BIT_INSERT_EXPR, type, new_lhs,
377 : 48 : rhs, bitsize_int (bitpos));
378 : 3794 : if (orig_opcode == COND_EXPR)
379 : : {
380 : 350 : if (error_operand_p (rhs1))
381 : 0 : return error_mark_node;
382 : 350 : gcc_assert (TREE_CODE (rhs1) == EQ_EXPR);
383 : 350 : tree cmptype = TREE_TYPE (TREE_OPERAND (rhs1, 0));
384 : 350 : if (SCALAR_FLOAT_TYPE_P (cmptype) && !test)
385 : : {
386 : 114 : bool clear_padding = false;
387 : 114 : HOST_WIDE_INT non_padding_start = 0;
388 : 114 : HOST_WIDE_INT non_padding_end = 0;
389 : 114 : if (BITS_PER_UNIT == 8
390 : : && CHAR_BIT == 8
391 : 114 : && clear_padding_type_may_have_padding_p (cmptype))
392 : : {
393 : 30 : HOST_WIDE_INT sz = int_size_in_bytes (cmptype), i;
394 : 30 : gcc_assert (sz > 0);
395 : 30 : unsigned char *buf = XALLOCAVEC (unsigned char, sz);
396 : 30 : memset (buf, ~0, sz);
397 : 30 : clear_type_padding_in_mask (cmptype, buf);
398 : 360 : for (i = 0; i < sz; i++)
399 : 330 : if (buf[i] != (unsigned char) ~0)
400 : : {
401 : : clear_padding = true;
402 : : break;
403 : : }
404 : 30 : if (clear_padding && buf[i] == 0)
405 : : {
406 : : /* Try to optimize. In the common case where
407 : : non-padding bits are all continuous and start
408 : : and end at a byte boundary, we can just adjust
409 : : the memcmp call arguments and don't need to
410 : : emit __builtin_clear_padding calls. */
411 : 30 : if (i == 0)
412 : : {
413 : 0 : for (i = 0; i < sz; i++)
414 : 0 : if (buf[i] != 0)
415 : : break;
416 : 0 : if (i < sz && buf[i] == (unsigned char) ~0)
417 : : {
418 : 0 : non_padding_start = i;
419 : 0 : for (; i < sz; i++)
420 : 0 : if (buf[i] != (unsigned char) ~0)
421 : : break;
422 : : }
423 : : else
424 : : i = 0;
425 : : }
426 : 30 : if (i != 0)
427 : : {
428 : 210 : non_padding_end = i;
429 : 210 : for (; i < sz; i++)
430 : 180 : if (buf[i] != 0)
431 : : {
432 : : non_padding_start = 0;
433 : : non_padding_end = 0;
434 : : break;
435 : : }
436 : : }
437 : : }
438 : : }
439 : 84 : tree inttype = NULL_TREE;
440 : 84 : if (!clear_padding && tree_fits_uhwi_p (TYPE_SIZE (cmptype)))
441 : : {
442 : 84 : HOST_WIDE_INT prec = tree_to_uhwi (TYPE_SIZE (cmptype));
443 : 84 : inttype = c_common_type_for_size (prec, 1);
444 : 84 : if (inttype
445 : 168 : && (!tree_int_cst_equal (TYPE_SIZE (cmptype),
446 : 84 : TYPE_SIZE (inttype))
447 : 84 : || TYPE_PRECISION (inttype) != prec))
448 : : inttype = NULL_TREE;
449 : : }
450 : 84 : if (inttype)
451 : : {
452 : 84 : TREE_OPERAND (rhs1, 0)
453 : 84 : = build1_loc (loc, VIEW_CONVERT_EXPR, inttype,
454 : 84 : TREE_OPERAND (rhs1, 0));
455 : 84 : TREE_OPERAND (rhs1, 1)
456 : 168 : = build1_loc (loc, VIEW_CONVERT_EXPR, inttype,
457 : 84 : TREE_OPERAND (rhs1, 1));
458 : : }
459 : : else
460 : : {
461 : 30 : tree pcmptype = build_pointer_type (cmptype);
462 : 30 : tree tmp1 = create_tmp_var_raw (cmptype);
463 : 30 : TREE_ADDRESSABLE (tmp1) = 1;
464 : 30 : DECL_CONTEXT (tmp1) = current_function_decl;
465 : 30 : tmp1 = build4 (TARGET_EXPR, cmptype, tmp1,
466 : 30 : TREE_OPERAND (rhs1, 0), NULL, NULL);
467 : 30 : tmp1 = build1 (ADDR_EXPR, pcmptype, tmp1);
468 : 30 : tree tmp2 = create_tmp_var_raw (cmptype);
469 : 30 : TREE_ADDRESSABLE (tmp2) = 1;
470 : 30 : DECL_CONTEXT (tmp2) = current_function_decl;
471 : 30 : tmp2 = build4 (TARGET_EXPR, cmptype, tmp2,
472 : 30 : TREE_OPERAND (rhs1, 1), NULL, NULL);
473 : 30 : tmp2 = build1 (ADDR_EXPR, pcmptype, tmp2);
474 : 30 : if (non_padding_start)
475 : : {
476 : 0 : tmp1 = build2 (POINTER_PLUS_EXPR, pcmptype, tmp1,
477 : 0 : size_int (non_padding_start));
478 : 0 : tmp2 = build2 (POINTER_PLUS_EXPR, pcmptype, tmp2,
479 : 0 : size_int (non_padding_start));
480 : : }
481 : 30 : tree fndecl = builtin_decl_explicit (BUILT_IN_MEMCMP);
482 : 60 : rhs1 = build_call_expr_loc (loc, fndecl, 3, tmp1, tmp2,
483 : : non_padding_end
484 : 30 : ? size_int (non_padding_end
485 : : - non_padding_start)
486 : 0 : : TYPE_SIZE_UNIT (cmptype));
487 : 30 : rhs1 = build2 (EQ_EXPR, boolean_type_node, rhs1,
488 : : integer_zero_node);
489 : 30 : if (clear_padding && non_padding_end == 0)
490 : : {
491 : 0 : fndecl = builtin_decl_explicit (BUILT_IN_CLEAR_PADDING);
492 : 0 : tree cp1 = build_call_expr_loc (loc, fndecl, 1, tmp1);
493 : 0 : tree cp2 = build_call_expr_loc (loc, fndecl, 1, tmp2);
494 : 0 : rhs1 = omit_two_operands_loc (loc, boolean_type_node,
495 : : rhs1, cp2, cp1);
496 : : }
497 : : }
498 : : }
499 : 350 : if (r && test)
500 : : rtmp = rhs1;
501 : 325 : else if (r)
502 : : {
503 : 118 : tree var = create_tmp_var_raw (boolean_type_node);
504 : 118 : DECL_CONTEXT (var) = current_function_decl;
505 : 118 : rtmp = build4 (TARGET_EXPR, boolean_type_node, var,
506 : : boolean_false_node, NULL, NULL);
507 : 118 : save = in_late_binary_op;
508 : 118 : in_late_binary_op = true;
509 : 118 : x = build_modify_expr (loc, var, NULL_TREE, NOP_EXPR,
510 : : loc, rhs1, NULL_TREE);
511 : 118 : in_late_binary_op = save;
512 : 118 : if (x == error_mark_node)
513 : : return error_mark_node;
514 : 118 : gcc_assert (TREE_CODE (x) == MODIFY_EXPR
515 : : && TREE_OPERAND (x, 0) == var);
516 : 118 : TREE_OPERAND (x, 0) = rtmp;
517 : 118 : rhs1 = omit_one_operand_loc (loc, boolean_type_node, x, rtmp);
518 : : }
519 : 350 : rhs = build3_loc (loc, COND_EXPR, type, rhs1, rhs, new_lhs);
520 : 350 : rhs1 = NULL_TREE;
521 : : }
522 : :
523 : : /* Punt the actual generation of atomic operations to common code. */
524 : 3794 : if (code == OMP_ATOMIC)
525 : 2528 : type = void_type_node;
526 : 3794 : x = build2 (code, type, addr, rhs);
527 : 3794 : SET_EXPR_LOCATION (x, loc);
528 : 3794 : OMP_ATOMIC_MEMORY_ORDER (x) = memory_order;
529 : 3794 : OMP_ATOMIC_WEAK (x) = weak;
530 : :
531 : : /* Generally it is hard to prove lhs1 and lhs are the same memory
532 : : location, just diagnose different variables. */
533 : 3794 : if (rhs1
534 : 1031 : && VAR_P (rhs1)
535 : 439 : && VAR_P (orig_lhs)
536 : 439 : && rhs1 != orig_lhs
537 : 0 : && !test)
538 : : {
539 : 0 : if (code == OMP_ATOMIC)
540 : 0 : error_at (loc, "%<#pragma omp atomic update%> uses two different "
541 : : "variables for memory");
542 : : else
543 : 0 : error_at (loc, "%<#pragma omp atomic capture%> uses two different "
544 : : "variables for memory");
545 : 0 : return error_mark_node;
546 : : }
547 : :
548 : 3794 : if (lhs1
549 : 3794 : && lhs1 != orig_lhs
550 : 325 : && TREE_CODE (lhs1) == COMPONENT_REF
551 : 12 : && TREE_CODE (TREE_OPERAND (lhs1, 1)) == FIELD_DECL
552 : 12 : && DECL_C_BIT_FIELD (TREE_OPERAND (lhs1, 1))
553 : 3806 : && DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (lhs1, 1)))
554 : : {
555 : 12 : tree field = TREE_OPERAND (lhs1, 1);
556 : 12 : tree repr = DECL_BIT_FIELD_REPRESENTATIVE (field);
557 : 12 : lhs1 = build3 (COMPONENT_REF, TREE_TYPE (repr), TREE_OPERAND (lhs1, 0),
558 : 12 : repr, TREE_OPERAND (lhs1, 2));
559 : : }
560 : 3794 : if (rhs1
561 : 1031 : && rhs1 != orig_lhs
562 : 592 : && TREE_CODE (rhs1) == COMPONENT_REF
563 : 16 : && TREE_CODE (TREE_OPERAND (rhs1, 1)) == FIELD_DECL
564 : 16 : && DECL_C_BIT_FIELD (TREE_OPERAND (rhs1, 1))
565 : 3810 : && DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (rhs1, 1)))
566 : : {
567 : 16 : tree field = TREE_OPERAND (rhs1, 1);
568 : 16 : tree repr = DECL_BIT_FIELD_REPRESENTATIVE (field);
569 : 16 : rhs1 = build3 (COMPONENT_REF, TREE_TYPE (repr), TREE_OPERAND (rhs1, 0),
570 : 16 : repr, TREE_OPERAND (rhs1, 2));
571 : : }
572 : :
573 : 3794 : if (code != OMP_ATOMIC)
574 : : {
575 : : /* Generally it is hard to prove lhs1 and lhs are the same memory
576 : : location, just diagnose different variables. */
577 : 1266 : if (lhs1 && VAR_P (lhs1) && VAR_P (orig_lhs))
578 : : {
579 : 434 : if (lhs1 != orig_lhs && !test)
580 : : {
581 : 0 : error_at (loc, "%<#pragma omp atomic capture%> uses two "
582 : : "different variables for memory");
583 : 0 : return error_mark_node;
584 : : }
585 : : }
586 : 1266 : if (blhs)
587 : 28 : x = build3_loc (loc, BIT_FIELD_REF, TREE_TYPE (blhs), x,
588 : 28 : bitsize_int (bitsize), bitsize_int (bitpos));
589 : 1266 : if (r && !test)
590 : : {
591 : 80 : vtmp = create_tmp_var_raw (TREE_TYPE (x));
592 : 80 : DECL_CONTEXT (vtmp) = current_function_decl;
593 : : }
594 : : else
595 : : vtmp = v;
596 : 1266 : x = build_modify_expr (loc, vtmp, NULL_TREE, NOP_EXPR,
597 : : loc, x, NULL_TREE);
598 : 1266 : if (x == error_mark_node)
599 : : return error_mark_node;
600 : 1262 : type = TREE_TYPE (x);
601 : 1262 : if (r && !test)
602 : : {
603 : 80 : vtmp = build4 (TARGET_EXPR, TREE_TYPE (vtmp), vtmp,
604 : 80 : build_zero_cst (TREE_TYPE (vtmp)), NULL, NULL);
605 : 80 : gcc_assert (TREE_CODE (x) == MODIFY_EXPR
606 : : && TREE_OPERAND (x, 0) == TARGET_EXPR_SLOT (vtmp));
607 : 80 : TREE_OPERAND (x, 0) = vtmp;
608 : : }
609 : 1262 : if (rhs1 && rhs1 != orig_lhs)
610 : : {
611 : 238 : tree rhs1addr = build_unary_op (loc, ADDR_EXPR, rhs1, false);
612 : 238 : if (rhs1addr == error_mark_node)
613 : : return error_mark_node;
614 : 238 : x = omit_one_operand_loc (loc, type, x, rhs1addr);
615 : : }
616 : 1262 : if (lhs1 && lhs1 != orig_lhs)
617 : : {
618 : 325 : tree lhs1addr = build_unary_op (loc, ADDR_EXPR, lhs1, false);
619 : 325 : if (lhs1addr == error_mark_node)
620 : : return error_mark_node;
621 : 324 : if (code == OMP_ATOMIC_CAPTURE_OLD)
622 : 205 : x = omit_one_operand_loc (loc, type, x, lhs1addr);
623 : : else
624 : : {
625 : 119 : if (!test)
626 : 103 : x = save_expr (x);
627 : 119 : x = omit_two_operands_loc (loc, type, x, x, lhs1addr);
628 : : }
629 : : }
630 : : }
631 : 2528 : else if (rhs1 && rhs1 != orig_lhs)
632 : : {
633 : 354 : tree rhs1addr = build_unary_op (loc, ADDR_EXPR, rhs1, false);
634 : 354 : if (rhs1addr == error_mark_node)
635 : : return error_mark_node;
636 : 354 : x = omit_one_operand_loc (loc, type, x, rhs1addr);
637 : : }
638 : :
639 : 3789 : if (pre)
640 : 14 : x = omit_one_operand_loc (loc, type, x, pre);
641 : 3789 : if (r && r != void_list_node)
642 : : {
643 : 88 : in_late_binary_op = true;
644 : 88 : tree x2 = build_modify_expr (loc, r, NULL_TREE, NOP_EXPR,
645 : : loc, rtmp, NULL_TREE);
646 : 88 : in_late_binary_op = save;
647 : 88 : if (x2 == error_mark_node)
648 : : return error_mark_node;
649 : 88 : x = omit_one_operand_loc (loc, TREE_TYPE (x2), x2, x);
650 : : }
651 : 3789 : if (v && vtmp != v)
652 : : {
653 : 80 : in_late_binary_op = true;
654 : 80 : tree x2 = build_modify_expr (loc, v, NULL_TREE, NOP_EXPR,
655 : : loc, vtmp, NULL_TREE);
656 : 80 : in_late_binary_op = save;
657 : 80 : if (x2 == error_mark_node)
658 : : return error_mark_node;
659 : 80 : x2 = build3_loc (loc, COND_EXPR, void_type_node, rtmp,
660 : : void_node, x2);
661 : 80 : x = omit_one_operand_loc (loc, TREE_TYPE (x2), x2, x);
662 : : }
663 : : return x;
664 : : }
665 : :
666 : :
667 : : /* Return true if TYPE is the implementation's omp_interop_t. */
668 : :
669 : : bool
670 : 1841 : c_omp_interop_t_p (tree type)
671 : : {
672 : 1841 : if (type == error_mark_node)
673 : : return false;
674 : 1817 : type = TYPE_MAIN_VARIANT (type);
675 : 1817 : return (TREE_CODE (type) == ENUMERAL_TYPE
676 : 1724 : && TYPE_NAME (type)
677 : 3448 : && ((TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
678 : 1724 : ? DECL_NAME (TYPE_NAME (type)) : TYPE_NAME (type))
679 : 1724 : == get_identifier ("omp_interop_t"))
680 : 1724 : && TYPE_FILE_SCOPE_P (type)
681 : 1724 : && COMPLETE_TYPE_P (type)
682 : 1724 : && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
683 : 3541 : && !compare_tree_int (TYPE_SIZE (type),
684 : 1724 : tree_to_uhwi (TYPE_SIZE (ptr_type_node))));
685 : : }
686 : :
687 : : /* Return true if TYPE is the implementation's omp_depend_t. */
688 : :
689 : : bool
690 : 1212 : c_omp_depend_t_p (tree type)
691 : : {
692 : 1212 : type = TYPE_MAIN_VARIANT (type);
693 : 1212 : return (TREE_CODE (type) == RECORD_TYPE
694 : 429 : && TYPE_NAME (type)
695 : 858 : && ((TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
696 : 429 : ? DECL_NAME (TYPE_NAME (type)) : TYPE_NAME (type))
697 : 429 : == get_identifier ("omp_depend_t"))
698 : 411 : && TYPE_FILE_SCOPE_P (type)
699 : 411 : && COMPLETE_TYPE_P (type)
700 : 411 : && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
701 : 1623 : && !compare_tree_int (TYPE_SIZE (type),
702 : 411 : 2 * tree_to_uhwi (TYPE_SIZE (ptr_type_node))));
703 : : }
704 : :
705 : :
706 : : /* Complete a #pragma omp depobj construct. LOC is the location of the
707 : : #pragma. */
708 : :
709 : : void
710 : 355 : c_finish_omp_depobj (location_t loc, tree depobj,
711 : : enum omp_clause_depend_kind kind, tree clause)
712 : : {
713 : 355 : tree t = NULL_TREE;
714 : 355 : if (!error_operand_p (depobj))
715 : : {
716 : 344 : if (!c_omp_depend_t_p (TREE_TYPE (depobj)))
717 : : {
718 : 42 : error_at (EXPR_LOC_OR_LOC (depobj, loc),
719 : : "type of %<depobj%> expression is not %<omp_depend_t%>");
720 : 21 : depobj = error_mark_node;
721 : : }
722 : 323 : else if (TYPE_READONLY (TREE_TYPE (depobj)))
723 : : {
724 : 14 : error_at (EXPR_LOC_OR_LOC (depobj, loc),
725 : : "%<const%> qualified %<depobj%> expression");
726 : 7 : depobj = error_mark_node;
727 : : }
728 : : }
729 : : else
730 : 11 : depobj = error_mark_node;
731 : :
732 : 355 : if (clause == error_mark_node)
733 : 355 : return;
734 : :
735 : 317 : if (clause)
736 : : {
737 : 169 : gcc_assert (TREE_CODE (clause) == OMP_CLAUSE);
738 : 169 : if (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_DOACROSS)
739 : : {
740 : 42 : error_at (OMP_CLAUSE_LOCATION (clause),
741 : : "%<depend(%s)%> is only allowed in %<omp ordered%>",
742 : 14 : OMP_CLAUSE_DOACROSS_KIND (clause)
743 : : == OMP_CLAUSE_DOACROSS_SOURCE
744 : : ? "source" : "sink");
745 : 14 : return;
746 : : }
747 : 155 : gcc_assert (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_DEPEND);
748 : 155 : if (OMP_CLAUSE_CHAIN (clause))
749 : 7 : error_at (OMP_CLAUSE_LOCATION (clause),
750 : : "more than one locator in %<depend%> clause on %<depobj%> "
751 : : "construct");
752 : 155 : switch (OMP_CLAUSE_DEPEND_KIND (clause))
753 : : {
754 : 7 : case OMP_CLAUSE_DEPEND_DEPOBJ:
755 : 7 : error_at (OMP_CLAUSE_LOCATION (clause),
756 : : "%<depobj%> dependence type specified in %<depend%> "
757 : : "clause on %<depobj%> construct");
758 : 7 : return;
759 : 148 : case OMP_CLAUSE_DEPEND_IN:
760 : 148 : case OMP_CLAUSE_DEPEND_OUT:
761 : 148 : case OMP_CLAUSE_DEPEND_INOUT:
762 : 148 : case OMP_CLAUSE_DEPEND_MUTEXINOUTSET:
763 : 148 : case OMP_CLAUSE_DEPEND_INOUTSET:
764 : 148 : kind = OMP_CLAUSE_DEPEND_KIND (clause);
765 : 148 : t = OMP_CLAUSE_DECL (clause);
766 : 148 : gcc_assert (t);
767 : 148 : if (TREE_CODE (t) == TREE_LIST
768 : 7 : && TREE_PURPOSE (t)
769 : 155 : && TREE_CODE (TREE_PURPOSE (t)) == TREE_VEC)
770 : : {
771 : 7 : error_at (OMP_CLAUSE_LOCATION (clause),
772 : : "%<iterator%> modifier may not be specified on "
773 : : "%<depobj%> construct");
774 : 7 : return;
775 : : }
776 : 141 : if (TREE_CODE (t) == COMPOUND_EXPR)
777 : : {
778 : 0 : tree t1 = build_fold_addr_expr (TREE_OPERAND (t, 1));
779 : 0 : t = build2 (COMPOUND_EXPR, TREE_TYPE (t1), TREE_OPERAND (t, 0),
780 : : t1);
781 : : }
782 : 141 : else if (t != null_pointer_node)
783 : 133 : t = build_fold_addr_expr (t);
784 : : break;
785 : 0 : default:
786 : 0 : gcc_unreachable ();
787 : : }
788 : : }
789 : : else
790 : 148 : gcc_assert (kind != OMP_CLAUSE_DEPEND_INVALID);
791 : :
792 : 289 : if (depobj == error_mark_node)
793 : : return;
794 : :
795 : 483 : depobj = build_fold_addr_expr_loc (EXPR_LOC_OR_LOC (depobj, loc), depobj);
796 : 250 : tree dtype
797 : 250 : = build_pointer_type_for_mode (ptr_type_node, TYPE_MODE (ptr_type_node),
798 : : true);
799 : 250 : depobj = fold_convert (dtype, depobj);
800 : 250 : tree r;
801 : 250 : if (clause)
802 : : {
803 : 127 : depobj = save_expr (depobj);
804 : 127 : r = build_indirect_ref (loc, depobj, RO_UNARY_STAR);
805 : 127 : add_stmt (build2 (MODIFY_EXPR, void_type_node, r, t));
806 : : }
807 : 250 : int k;
808 : 250 : switch (kind)
809 : : {
810 : : case OMP_CLAUSE_DEPEND_IN:
811 : : k = GOMP_DEPEND_IN;
812 : : break;
813 : 11 : case OMP_CLAUSE_DEPEND_OUT:
814 : 11 : k = GOMP_DEPEND_OUT;
815 : 11 : break;
816 : 45 : case OMP_CLAUSE_DEPEND_INOUT:
817 : 45 : k = GOMP_DEPEND_INOUT;
818 : 45 : break;
819 : 14 : case OMP_CLAUSE_DEPEND_MUTEXINOUTSET:
820 : 14 : k = GOMP_DEPEND_MUTEXINOUTSET;
821 : 14 : break;
822 : 12 : case OMP_CLAUSE_DEPEND_INOUTSET:
823 : 12 : k = GOMP_DEPEND_INOUTSET;
824 : 12 : break;
825 : 87 : case OMP_CLAUSE_DEPEND_LAST:
826 : 87 : k = -1;
827 : 87 : break;
828 : 0 : default:
829 : 0 : gcc_unreachable ();
830 : : }
831 : 250 : t = build_int_cst (ptr_type_node, k);
832 : 250 : depobj = build2_loc (loc, POINTER_PLUS_EXPR, TREE_TYPE (depobj), depobj,
833 : 250 : TYPE_SIZE_UNIT (ptr_type_node));
834 : 250 : r = build_indirect_ref (loc, depobj, RO_UNARY_STAR);
835 : 250 : add_stmt (build2 (MODIFY_EXPR, void_type_node, r, t));
836 : : }
837 : :
838 : :
839 : : /* Complete a #pragma omp flush construct. We don't do anything with
840 : : the variable list that the syntax allows. LOC is the location of
841 : : the #pragma. */
842 : :
843 : : void
844 : 61 : c_finish_omp_flush (location_t loc, int mo)
845 : : {
846 : 61 : tree x;
847 : :
848 : 61 : if (mo == MEMMODEL_LAST || mo == MEMMODEL_SEQ_CST)
849 : : {
850 : 43 : x = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
851 : 43 : x = build_call_expr_loc (loc, x, 0);
852 : : }
853 : : else
854 : : {
855 : 18 : x = builtin_decl_explicit (BUILT_IN_ATOMIC_THREAD_FENCE);
856 : 18 : x = build_call_expr_loc (loc, x, 1,
857 : 18 : build_int_cst (integer_type_node, mo));
858 : : }
859 : 61 : add_stmt (x);
860 : 61 : }
861 : :
862 : :
863 : : /* Check and canonicalize OMP_FOR increment expression.
864 : : Helper function for c_finish_omp_for. */
865 : :
866 : : static tree
867 : 609 : check_omp_for_incr_expr (location_t loc, tree exp, tree decl)
868 : : {
869 : 694 : tree t;
870 : :
871 : 1388 : if (!INTEGRAL_TYPE_P (TREE_TYPE (exp))
872 : 1388 : || TYPE_PRECISION (TREE_TYPE (exp)) < TYPE_PRECISION (TREE_TYPE (decl)))
873 : 0 : return error_mark_node;
874 : :
875 : 694 : if (exp == decl)
876 : 171 : return build_int_cst (TREE_TYPE (exp), 0);
877 : :
878 : 523 : switch (TREE_CODE (exp))
879 : : {
880 : 197 : CASE_CONVERT:
881 : 197 : t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 0), decl);
882 : 197 : if (t != error_mark_node)
883 : 165 : return fold_convert_loc (loc, TREE_TYPE (exp), t);
884 : : break;
885 : 16 : case MINUS_EXPR:
886 : 16 : t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 0), decl);
887 : 16 : if (t != error_mark_node)
888 : 16 : return fold_build2_loc (loc, MINUS_EXPR,
889 : 32 : TREE_TYPE (exp), t, TREE_OPERAND (exp, 1));
890 : : break;
891 : 172 : case PLUS_EXPR:
892 : 172 : t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 0), decl);
893 : 172 : if (t != error_mark_node)
894 : 131 : return fold_build2_loc (loc, PLUS_EXPR,
895 : 262 : TREE_TYPE (exp), t, TREE_OPERAND (exp, 1));
896 : 41 : t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 1), decl);
897 : 41 : if (t != error_mark_node)
898 : 33 : return fold_build2_loc (loc, PLUS_EXPR,
899 : 66 : TREE_TYPE (exp), TREE_OPERAND (exp, 0), t);
900 : : break;
901 : 85 : case COMPOUND_EXPR:
902 : 85 : {
903 : : /* cp_build_modify_expr forces preevaluation of the RHS to make
904 : : sure that it is evaluated before the lvalue-rvalue conversion
905 : : is applied to the LHS. Reconstruct the original expression. */
906 : 85 : tree op0 = TREE_OPERAND (exp, 0);
907 : 85 : if (TREE_CODE (op0) == TARGET_EXPR
908 : 85 : && !VOID_TYPE_P (TREE_TYPE (op0)))
909 : : {
910 : 85 : tree op1 = TREE_OPERAND (exp, 1);
911 : 85 : tree temp = TARGET_EXPR_SLOT (op0);
912 : 85 : if (BINARY_CLASS_P (op1)
913 : 85 : && TREE_OPERAND (op1, 1) == temp)
914 : : {
915 : 85 : op1 = copy_node (op1);
916 : 85 : TREE_OPERAND (op1, 1) = TARGET_EXPR_INITIAL (op0);
917 : 85 : return check_omp_for_incr_expr (loc, op1, decl);
918 : : }
919 : : }
920 : : break;
921 : : }
922 : : default:
923 : : break;
924 : : }
925 : :
926 : 93 : return error_mark_node;
927 : : }
928 : :
929 : : /* If the OMP_FOR increment expression in INCR is of pointer type,
930 : : canonicalize it into an expression handled by gimplify_omp_for()
931 : : and return it. DECL is the iteration variable. */
932 : :
933 : : static tree
934 : 31934 : c_omp_for_incr_canonicalize_ptr (location_t loc, tree decl, tree incr)
935 : : {
936 : 61861 : if (POINTER_TYPE_P (TREE_TYPE (decl))
937 : 31934 : && TREE_OPERAND (incr, 1))
938 : : {
939 : 1997 : tree t = fold_convert_loc (loc,
940 : 1997 : sizetype, TREE_OPERAND (incr, 1));
941 : :
942 : 1997 : if (TREE_CODE (incr) == POSTDECREMENT_EXPR
943 : 1954 : || TREE_CODE (incr) == PREDECREMENT_EXPR)
944 : 597 : t = fold_build1_loc (loc, NEGATE_EXPR, sizetype, t);
945 : 1997 : t = fold_build_pointer_plus (decl, t);
946 : 1997 : incr = build2 (MODIFY_EXPR, void_type_node, decl, t);
947 : : }
948 : 31934 : return incr;
949 : : }
950 : :
951 : : /* Validate and generate OMP_FOR.
952 : : DECLV is a vector of iteration variables, for each collapsed loop.
953 : :
954 : : ORIG_DECLV, if non-NULL, is a vector with the original iteration
955 : : variables (prior to any transformations, by say, C++ iterators).
956 : :
957 : : INITV, CONDV and INCRV are vectors containing initialization
958 : : expressions, controlling predicates and increment expressions.
959 : : BODY is the body of the loop and PRE_BODY statements that go before
960 : : the loop. */
961 : :
962 : : tree
963 : 31899 : c_finish_omp_for (location_t locus, enum tree_code code, tree declv,
964 : : tree orig_declv, tree initv, tree condv, tree incrv,
965 : : tree body, tree pre_body, bool final_p)
966 : : {
967 : 31899 : location_t elocus;
968 : 31899 : bool fail = false;
969 : 31899 : int i;
970 : :
971 : 31899 : gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (initv));
972 : 31899 : gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (condv));
973 : 31899 : gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (incrv));
974 : 73780 : for (i = 0; i < TREE_VEC_LENGTH (declv); i++)
975 : : {
976 : 43259 : tree decl = TREE_VEC_ELT (declv, i);
977 : 43259 : tree init = TREE_VEC_ELT (initv, i);
978 : 43259 : tree cond = TREE_VEC_ELT (condv, i);
979 : 43259 : tree incr = TREE_VEC_ELT (incrv, i);
980 : :
981 : 43259 : if (init == NULL_TREE)
982 : : {
983 : 1378 : gcc_assert (decl == NULL_TREE
984 : : && cond == NULL_TREE
985 : : && incr == NULL_TREE);
986 : 1649 : for (i++; i < TREE_VEC_LENGTH (declv); i++)
987 : 271 : gcc_assert (TREE_VEC_ELT (declv, i) == NULL_TREE
988 : : && TREE_VEC_ELT (initv, i) == NULL_TREE
989 : : && TREE_VEC_ELT (condv, i) == NULL_TREE
990 : : && TREE_VEC_ELT (incrv, i) == NULL_TREE);
991 : : break;
992 : : }
993 : :
994 : 41881 : elocus = locus;
995 : 41881 : if (EXPR_HAS_LOCATION (init))
996 : 37205 : elocus = EXPR_LOCATION (init);
997 : :
998 : : /* Validate the iteration variable. */
999 : 83762 : if (!INTEGRAL_TYPE_P (TREE_TYPE (decl))
1000 : 44751 : && TREE_CODE (TREE_TYPE (decl)) != POINTER_TYPE)
1001 : : {
1002 : 1 : error_at (elocus, "invalid type for iteration variable %qE", decl);
1003 : 1 : fail = true;
1004 : : }
1005 : 41880 : else if (TYPE_ATOMIC (TREE_TYPE (decl)))
1006 : : {
1007 : 16 : error_at (elocus, "%<_Atomic%> iteration variable %qE", decl);
1008 : 16 : fail = true;
1009 : : /* _Atomic iterator confuses stuff too much, so we risk ICE
1010 : : trying to diagnose it further. */
1011 : 16 : continue;
1012 : : }
1013 : :
1014 : : /* In the case of "for (int i = 0...)", init will be a decl. It should
1015 : : have a DECL_INITIAL that we can turn into an assignment. */
1016 : 41865 : if (init == decl)
1017 : : {
1018 : 4660 : elocus = DECL_SOURCE_LOCATION (decl);
1019 : :
1020 : 4660 : init = DECL_INITIAL (decl);
1021 : 4660 : if (init == NULL)
1022 : : {
1023 : 0 : error_at (elocus, "%qE is not initialized", decl);
1024 : 0 : init = integer_zero_node;
1025 : 0 : fail = true;
1026 : : }
1027 : 4660 : DECL_INITIAL (decl) = NULL_TREE;
1028 : :
1029 : 4660 : init = build_modify_expr (elocus, decl, NULL_TREE, NOP_EXPR,
1030 : : /* FIXME diagnostics: This should
1031 : : be the location of the INIT. */
1032 : : elocus,
1033 : : init,
1034 : : NULL_TREE);
1035 : : }
1036 : 41865 : if (init != error_mark_node)
1037 : : {
1038 : 41865 : gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
1039 : 41865 : gcc_assert (TREE_OPERAND (init, 0) == decl);
1040 : : }
1041 : :
1042 : 41865 : if (cond == NULL_TREE)
1043 : : {
1044 : 2 : error_at (elocus, "missing controlling predicate");
1045 : 2 : fail = true;
1046 : : }
1047 : : else
1048 : : {
1049 : 41863 : bool cond_ok = false;
1050 : :
1051 : : /* E.g. C sizeof (vla) could add COMPOUND_EXPRs with
1052 : : evaluation of the vla VAR_DECL. We need to readd
1053 : : them to the non-decl operand. See PR45784. */
1054 : 41863 : while (TREE_CODE (cond) == COMPOUND_EXPR)
1055 : 0 : cond = TREE_OPERAND (cond, 1);
1056 : :
1057 : 41863 : if (EXPR_HAS_LOCATION (cond))
1058 : 41735 : elocus = EXPR_LOCATION (cond);
1059 : :
1060 : 41863 : if (TREE_CODE (cond) == LT_EXPR
1061 : : || TREE_CODE (cond) == LE_EXPR
1062 : : || TREE_CODE (cond) == GT_EXPR
1063 : 41863 : || TREE_CODE (cond) == GE_EXPR
1064 : 5587 : || TREE_CODE (cond) == NE_EXPR
1065 : 31 : || TREE_CODE (cond) == EQ_EXPR)
1066 : : {
1067 : 41832 : tree op0 = TREE_OPERAND (cond, 0);
1068 : 41832 : tree op1 = TREE_OPERAND (cond, 1);
1069 : :
1070 : : /* 2.5.1. The comparison in the condition is computed in
1071 : : the type of DECL, otherwise the behavior is undefined.
1072 : :
1073 : : For example:
1074 : : long n; int i;
1075 : : i < n;
1076 : :
1077 : : according to ISO will be evaluated as:
1078 : : (long)i < n;
1079 : :
1080 : : We want to force:
1081 : : i < (int)n; */
1082 : 41832 : if (TREE_CODE (op0) == NOP_EXPR
1083 : 41832 : && decl == TREE_OPERAND (op0, 0))
1084 : : {
1085 : 58 : TREE_OPERAND (cond, 0) = TREE_OPERAND (op0, 0);
1086 : 58 : TREE_OPERAND (cond, 1)
1087 : 116 : = fold_build1_loc (elocus, NOP_EXPR, TREE_TYPE (decl),
1088 : 58 : TREE_OPERAND (cond, 1));
1089 : : }
1090 : 41774 : else if (TREE_CODE (op1) == NOP_EXPR
1091 : 41774 : && decl == TREE_OPERAND (op1, 0))
1092 : : {
1093 : 4 : TREE_OPERAND (cond, 1) = TREE_OPERAND (op1, 0);
1094 : 4 : TREE_OPERAND (cond, 0)
1095 : 8 : = fold_build1_loc (elocus, NOP_EXPR, TREE_TYPE (decl),
1096 : 4 : TREE_OPERAND (cond, 0));
1097 : : }
1098 : :
1099 : 41832 : if (decl == TREE_OPERAND (cond, 0))
1100 : : cond_ok = true;
1101 : 139 : else if (decl == TREE_OPERAND (cond, 1))
1102 : : {
1103 : 138 : TREE_SET_CODE (cond,
1104 : : swap_tree_comparison (TREE_CODE (cond)));
1105 : 138 : TREE_OPERAND (cond, 1) = TREE_OPERAND (cond, 0);
1106 : 138 : TREE_OPERAND (cond, 0) = decl;
1107 : 138 : cond_ok = true;
1108 : : }
1109 : :
1110 : 41832 : if (TREE_CODE (cond) == NE_EXPR
1111 : 41832 : || TREE_CODE (cond) == EQ_EXPR)
1112 : : {
1113 : 5556 : if (!INTEGRAL_TYPE_P (TREE_TYPE (decl)))
1114 : : {
1115 : 935 : if (code == OACC_LOOP || TREE_CODE (cond) == EQ_EXPR)
1116 : : cond_ok = false;
1117 : : }
1118 : 4621 : else if (operand_equal_p (TREE_OPERAND (cond, 1),
1119 : 4621 : TYPE_MIN_VALUE (TREE_TYPE (decl)),
1120 : : 0))
1121 : 221 : TREE_SET_CODE (cond, TREE_CODE (cond) == NE_EXPR
1122 : : ? GT_EXPR : LE_EXPR);
1123 : 4400 : else if (operand_equal_p (TREE_OPERAND (cond, 1),
1124 : 4400 : TYPE_MAX_VALUE (TREE_TYPE (decl)),
1125 : : 0))
1126 : 5 : TREE_SET_CODE (cond, TREE_CODE (cond) == NE_EXPR
1127 : : ? LT_EXPR : GE_EXPR);
1128 : 4395 : else if (code == OACC_LOOP || TREE_CODE (cond) == EQ_EXPR)
1129 : : cond_ok = false;
1130 : : }
1131 : :
1132 : 41832 : if (cond_ok && TREE_VEC_ELT (condv, i) != cond)
1133 : : {
1134 : 0 : tree ce = NULL_TREE, *pce = &ce;
1135 : 0 : tree type = TREE_TYPE (TREE_OPERAND (cond, 1));
1136 : 0 : for (tree c = TREE_VEC_ELT (condv, i); c != cond;
1137 : 0 : c = TREE_OPERAND (c, 1))
1138 : : {
1139 : 0 : *pce = build2 (COMPOUND_EXPR, type, TREE_OPERAND (c, 0),
1140 : 0 : TREE_OPERAND (cond, 1));
1141 : 0 : pce = &TREE_OPERAND (*pce, 1);
1142 : : }
1143 : 0 : TREE_OPERAND (cond, 1) = ce;
1144 : 0 : TREE_VEC_ELT (condv, i) = cond;
1145 : : }
1146 : : }
1147 : :
1148 : 41832 : if (!cond_ok)
1149 : : {
1150 : 32 : error_at (elocus, "invalid controlling predicate");
1151 : 32 : fail = true;
1152 : : }
1153 : : }
1154 : :
1155 : 41865 : if (incr == NULL_TREE)
1156 : : {
1157 : 0 : error_at (elocus, "missing increment expression");
1158 : 0 : fail = true;
1159 : : }
1160 : : else
1161 : : {
1162 : 41865 : bool incr_ok = false;
1163 : :
1164 : 41865 : if (EXPR_HAS_LOCATION (incr))
1165 : 40972 : elocus = EXPR_LOCATION (incr);
1166 : :
1167 : : /* Check all the valid increment expressions: v++, v--, ++v, --v,
1168 : : v = v + incr, v = incr + v and v = v - incr. */
1169 : 41865 : switch (TREE_CODE (incr))
1170 : : {
1171 : 31940 : case POSTINCREMENT_EXPR:
1172 : 31940 : case PREINCREMENT_EXPR:
1173 : 31940 : case POSTDECREMENT_EXPR:
1174 : 31940 : case PREDECREMENT_EXPR:
1175 : 31940 : if (TREE_OPERAND (incr, 0) != decl)
1176 : : break;
1177 : :
1178 : 31934 : incr_ok = true;
1179 : 31934 : if (!fail
1180 : 31909 : && TREE_CODE (cond) == NE_EXPR
1181 : 3739 : && TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
1182 : 819 : && TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl)))
1183 : 32753 : && (TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl))))
1184 : : != INTEGER_CST))
1185 : : {
1186 : : /* For pointer to VLA, transform != into < or >
1187 : : depending on whether incr is increment or decrement. */
1188 : 4 : if (TREE_CODE (incr) == PREINCREMENT_EXPR
1189 : 4 : || TREE_CODE (incr) == POSTINCREMENT_EXPR)
1190 : 2 : TREE_SET_CODE (cond, LT_EXPR);
1191 : : else
1192 : 2 : TREE_SET_CODE (cond, GT_EXPR);
1193 : : }
1194 : 31934 : incr = c_omp_for_incr_canonicalize_ptr (elocus, decl, incr);
1195 : 31934 : break;
1196 : :
1197 : 202 : case COMPOUND_EXPR:
1198 : 202 : if ((TREE_CODE (TREE_OPERAND (incr, 0)) != SAVE_EXPR
1199 : 6 : && TREE_CODE (TREE_OPERAND (incr, 0)) != TARGET_EXPR)
1200 : 203 : || TREE_CODE (TREE_OPERAND (incr, 1)) != MODIFY_EXPR)
1201 : : break;
1202 : 197 : incr = TREE_OPERAND (incr, 1);
1203 : : /* FALLTHRU */
1204 : 9909 : case MODIFY_EXPR:
1205 : 9909 : if (TREE_OPERAND (incr, 0) != decl)
1206 : : break;
1207 : 9909 : if (TREE_OPERAND (incr, 1) == decl)
1208 : : break;
1209 : 9909 : if (TREE_CODE (TREE_OPERAND (incr, 1)) == PLUS_EXPR
1210 : 9909 : && (TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl
1211 : 286 : || TREE_OPERAND (TREE_OPERAND (incr, 1), 1) == decl))
1212 : : incr_ok = true;
1213 : 2065 : else if ((TREE_CODE (TREE_OPERAND (incr, 1)) == MINUS_EXPR
1214 : 1041 : || (TREE_CODE (TREE_OPERAND (incr, 1))
1215 : : == POINTER_PLUS_EXPR))
1216 : 2926 : && TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl)
1217 : : incr_ok = true;
1218 : : else
1219 : : {
1220 : 183 : tree t = check_omp_for_incr_expr (elocus,
1221 : 183 : TREE_OPERAND (incr, 1),
1222 : : decl);
1223 : 183 : if (t != error_mark_node)
1224 : : {
1225 : 171 : incr_ok = true;
1226 : 171 : t = build2 (PLUS_EXPR, TREE_TYPE (decl), decl, t);
1227 : 171 : incr = build2 (MODIFY_EXPR, void_type_node, decl, t);
1228 : : }
1229 : : }
1230 : 9909 : if (!fail
1231 : 9909 : && incr_ok
1232 : 9891 : && TREE_CODE (cond) == NE_EXPR)
1233 : : {
1234 : 1591 : tree i = TREE_OPERAND (incr, 1);
1235 : 1591 : i = TREE_OPERAND (i, TREE_OPERAND (i, 0) == decl);
1236 : 1591 : i = c_fully_fold (i, false, NULL);
1237 : 1591 : if (!final_p
1238 : 4 : && TREE_CODE (i) != INTEGER_CST)
1239 : : ;
1240 : 1591 : else if (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE)
1241 : : {
1242 : 116 : tree unit
1243 : 116 : = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl)));
1244 : 116 : if (unit)
1245 : : {
1246 : 116 : enum tree_code ccode = GT_EXPR;
1247 : 116 : unit = c_fully_fold (unit, false, NULL);
1248 : 116 : i = fold_convert (TREE_TYPE (unit), i);
1249 : 116 : if (operand_equal_p (unit, i, 0))
1250 : : ccode = LT_EXPR;
1251 : 90 : if (ccode == GT_EXPR)
1252 : : {
1253 : 90 : i = fold_unary (NEGATE_EXPR, TREE_TYPE (i), i);
1254 : 90 : if (i == NULL_TREE
1255 : 90 : || !operand_equal_p (unit, i, 0))
1256 : : {
1257 : 72 : error_at (elocus,
1258 : : "increment is not constant 1 or "
1259 : : "-1 for %<!=%> condition");
1260 : 72 : fail = true;
1261 : : }
1262 : : }
1263 : 116 : if (TREE_CODE (unit) != INTEGER_CST)
1264 : : /* For pointer to VLA, transform != into < or >
1265 : : depending on whether the pointer is
1266 : : incremented or decremented in each
1267 : : iteration. */
1268 : 60 : TREE_SET_CODE (cond, ccode);
1269 : : }
1270 : : }
1271 : : else
1272 : : {
1273 : 1475 : if (!integer_onep (i) && !integer_minus_onep (i))
1274 : : {
1275 : 132 : error_at (elocus,
1276 : : "increment is not constant 1 or -1 for"
1277 : : " %<!=%> condition");
1278 : 132 : fail = true;
1279 : : }
1280 : : }
1281 : : }
1282 : : break;
1283 : :
1284 : : default:
1285 : : break;
1286 : : }
1287 : 41843 : if (!incr_ok)
1288 : : {
1289 : 34 : error_at (elocus, "invalid increment expression");
1290 : 34 : fail = true;
1291 : : }
1292 : : }
1293 : :
1294 : 41865 : TREE_VEC_ELT (initv, i) = init;
1295 : 41865 : TREE_VEC_ELT (incrv, i) = incr;
1296 : : }
1297 : :
1298 : 31899 : if (fail)
1299 : : return NULL;
1300 : : else
1301 : : {
1302 : 31614 : tree t = make_node (code);
1303 : :
1304 : 31614 : TREE_TYPE (t) = void_type_node;
1305 : 31614 : OMP_FOR_INIT (t) = initv;
1306 : 31614 : OMP_FOR_COND (t) = condv;
1307 : 31614 : OMP_FOR_INCR (t) = incrv;
1308 : 31614 : OMP_FOR_BODY (t) = body;
1309 : 31614 : OMP_FOR_PRE_BODY (t) = pre_body;
1310 : 31614 : OMP_FOR_ORIG_DECLS (t) = orig_declv;
1311 : :
1312 : 31614 : SET_EXPR_LOCATION (t, locus);
1313 : 31614 : return t;
1314 : : }
1315 : : }
1316 : :
1317 : : /* Type for passing data in between c_omp_check_loop_iv and
1318 : : c_omp_check_loop_iv_r. */
1319 : :
1320 : : struct c_omp_check_loop_iv_data
1321 : : {
1322 : : tree declv;
1323 : : bool fail;
1324 : : bool maybe_nonrect;
1325 : : location_t stmt_loc;
1326 : : location_t expr_loc;
1327 : : int kind;
1328 : : int idx;
1329 : : walk_tree_lh lh;
1330 : : hash_set<tree> *ppset;
1331 : : };
1332 : :
1333 : : /* Return -1 if DECL is not a loop iterator in loop nest D, otherwise
1334 : : return the index of the loop in which it is an iterator.
1335 : : Return TREE_VEC_LENGTH (d->declv) if it is a C++ range for iterator. */
1336 : :
1337 : : static int
1338 : 41980 : c_omp_is_loop_iterator (tree decl, struct c_omp_check_loop_iv_data *d)
1339 : : {
1340 : 133052 : for (int i = 0; i < TREE_VEC_LENGTH (d->declv); i++)
1341 : 105567 : if (TREE_VEC_ELT (d->declv, i) == NULL_TREE)
1342 : 253 : continue;
1343 : 105314 : else if (decl == TREE_VEC_ELT (d->declv, i)
1344 : 105314 : || (TREE_CODE (TREE_VEC_ELT (d->declv, i)) == TREE_LIST
1345 : 2292 : && decl == TREE_PURPOSE (TREE_VEC_ELT (d->declv, i))))
1346 : : return i;
1347 : 90900 : else if (TREE_CODE (TREE_VEC_ELT (d->declv, i)) == TREE_LIST
1348 : 2223 : && TREE_CHAIN (TREE_VEC_ELT (d->declv, i))
1349 : 91939 : && (TREE_CODE (TREE_CHAIN (TREE_VEC_ELT (d->declv, i)))
1350 : : == TREE_VEC))
1351 : 1461 : for (int j = 2;
1352 : 2500 : j < TREE_VEC_LENGTH (TREE_CHAIN (TREE_VEC_ELT (d->declv, i))); j++)
1353 : 1542 : if (decl == TREE_VEC_ELT (TREE_CHAIN (TREE_VEC_ELT (d->declv, i)), j))
1354 : : return TREE_VEC_LENGTH (d->declv);
1355 : : return -1;
1356 : : }
1357 : :
1358 : : /* Helper function called via walk_tree, to diagnose uses
1359 : : of associated loop IVs inside of lb, b and incr expressions
1360 : : of OpenMP loops. */
1361 : :
1362 : : static tree
1363 : 169776 : c_omp_check_loop_iv_r (tree *tp, int *walk_subtrees, void *data)
1364 : : {
1365 : 169776 : struct c_omp_check_loop_iv_data *d
1366 : : = (struct c_omp_check_loop_iv_data *) data;
1367 : 169776 : if (DECL_P (*tp))
1368 : : {
1369 : 28522 : int idx = c_omp_is_loop_iterator (*tp, d);
1370 : 28522 : if (idx == -1)
1371 : : return NULL_TREE;
1372 : :
1373 : 1441 : if ((d->kind & 4) && idx < d->idx)
1374 : : {
1375 : 787 : d->maybe_nonrect = true;
1376 : 787 : return NULL_TREE;
1377 : : }
1378 : :
1379 : 654 : if (d->ppset->add (*tp))
1380 : : return NULL_TREE;
1381 : :
1382 : 636 : location_t loc = d->expr_loc;
1383 : 636 : if (loc == UNKNOWN_LOCATION)
1384 : 175 : loc = d->stmt_loc;
1385 : :
1386 : 636 : switch (d->kind & 3)
1387 : : {
1388 : 206 : case 0:
1389 : 206 : error_at (loc, "initializer expression refers to "
1390 : : "iteration variable %qD", *tp);
1391 : 206 : break;
1392 : 201 : case 1:
1393 : 201 : error_at (loc, "condition expression refers to "
1394 : : "iteration variable %qD", *tp);
1395 : 201 : break;
1396 : 229 : case 2:
1397 : 229 : error_at (loc, "increment expression refers to "
1398 : : "iteration variable %qD", *tp);
1399 : 229 : break;
1400 : : }
1401 : 636 : d->fail = true;
1402 : : }
1403 : 141254 : else if ((d->kind & 4)
1404 : : && TREE_CODE (*tp) != TREE_VEC
1405 : : && TREE_CODE (*tp) != PLUS_EXPR
1406 : : && TREE_CODE (*tp) != MINUS_EXPR
1407 : : && TREE_CODE (*tp) != MULT_EXPR
1408 : : && TREE_CODE (*tp) != POINTER_PLUS_EXPR
1409 : : && !CONVERT_EXPR_P (*tp))
1410 : : {
1411 : 17112 : *walk_subtrees = 0;
1412 : 17112 : d->kind &= 3;
1413 : 17112 : walk_tree_1 (tp, c_omp_check_loop_iv_r, data, NULL, d->lh);
1414 : 17112 : d->kind |= 4;
1415 : 17112 : return NULL_TREE;
1416 : : }
1417 : 124142 : else if (d->ppset->add (*tp))
1418 : 17846 : *walk_subtrees = 0;
1419 : : /* Don't walk dtors added by C++ wrap_cleanups_r. */
1420 : 106296 : else if (TREE_CODE (*tp) == TRY_CATCH_EXPR
1421 : 106296 : && TRY_CATCH_IS_CLEANUP (*tp))
1422 : : {
1423 : 0 : *walk_subtrees = 0;
1424 : 0 : return walk_tree_1 (&TREE_OPERAND (*tp, 0), c_omp_check_loop_iv_r, data,
1425 : 0 : NULL, d->lh);
1426 : : }
1427 : :
1428 : : return NULL_TREE;
1429 : : }
1430 : :
1431 : : /* Check the allowed expressions for non-rectangular loop nest lb and b
1432 : : expressions. Return the outer var decl referenced in the expression. */
1433 : :
1434 : : static tree
1435 : 744 : c_omp_check_nonrect_loop_iv (tree *tp, struct c_omp_check_loop_iv_data *d,
1436 : : walk_tree_lh lh)
1437 : : {
1438 : 744 : d->maybe_nonrect = false;
1439 : 744 : if (d->fail)
1440 : : return NULL_TREE;
1441 : :
1442 : 728 : hash_set<tree> pset;
1443 : 728 : hash_set<tree> *ppset = d->ppset;
1444 : 728 : d->ppset = &pset;
1445 : :
1446 : 728 : tree t = *tp;
1447 : 728 : if (TREE_CODE (t) == TREE_VEC
1448 : 24 : && TREE_VEC_LENGTH (t) == 3
1449 : 24 : && DECL_P (TREE_VEC_ELT (t, 0))
1450 : 752 : && c_omp_is_loop_iterator (TREE_VEC_ELT (t, 0), d) >= 0)
1451 : : {
1452 : 24 : d->kind &= 3;
1453 : 24 : walk_tree_1 (&TREE_VEC_ELT (t, 1), c_omp_check_loop_iv_r, d, NULL, lh);
1454 : 24 : walk_tree_1 (&TREE_VEC_ELT (t, 1), c_omp_check_loop_iv_r, d, NULL, lh);
1455 : 24 : d->ppset = ppset;
1456 : 24 : return d->fail ? NULL_TREE : TREE_VEC_ELT (t, 0);
1457 : : }
1458 : :
1459 : 716 : while (CONVERT_EXPR_P (t))
1460 : 12 : t = TREE_OPERAND (t, 0);
1461 : :
1462 : 704 : tree a1 = t, a2 = integer_zero_node;
1463 : 704 : bool neg_a1 = false, neg_a2 = false;
1464 : 704 : switch (TREE_CODE (t))
1465 : : {
1466 : 298 : case PLUS_EXPR:
1467 : 298 : case MINUS_EXPR:
1468 : 298 : a1 = TREE_OPERAND (t, 0);
1469 : 298 : a2 = TREE_OPERAND (t, 1);
1470 : 350 : while (CONVERT_EXPR_P (a1))
1471 : 52 : a1 = TREE_OPERAND (a1, 0);
1472 : 386 : while (CONVERT_EXPR_P (a2))
1473 : 88 : a2 = TREE_OPERAND (a2, 0);
1474 : 298 : if (DECL_P (a1) && c_omp_is_loop_iterator (a1, d) >= 0)
1475 : : {
1476 : 64 : a2 = TREE_OPERAND (t, 1);
1477 : 64 : if (TREE_CODE (t) == MINUS_EXPR)
1478 : 19 : neg_a2 = true;
1479 : 64 : t = a1;
1480 : 64 : break;
1481 : : }
1482 : 234 : if (DECL_P (a2) && c_omp_is_loop_iterator (a2, d) >= 0)
1483 : : {
1484 : 0 : a1 = TREE_OPERAND (t, 0);
1485 : 0 : if (TREE_CODE (t) == MINUS_EXPR)
1486 : 0 : neg_a1 = true;
1487 : 0 : t = a2;
1488 : 0 : a2 = a1;
1489 : 0 : break;
1490 : : }
1491 : 234 : if (TREE_CODE (a1) == MULT_EXPR && TREE_CODE (a2) == MULT_EXPR)
1492 : : {
1493 : 0 : tree o1 = TREE_OPERAND (a1, 0);
1494 : 0 : tree o2 = TREE_OPERAND (a1, 1);
1495 : 0 : while (CONVERT_EXPR_P (o1))
1496 : 0 : o1 = TREE_OPERAND (o1, 0);
1497 : 0 : while (CONVERT_EXPR_P (o2))
1498 : 0 : o2 = TREE_OPERAND (o2, 0);
1499 : 0 : if ((DECL_P (o1) && c_omp_is_loop_iterator (o1, d) >= 0)
1500 : 0 : || (DECL_P (o2) && c_omp_is_loop_iterator (o2, d) >= 0))
1501 : : {
1502 : 0 : a2 = TREE_OPERAND (t, 1);
1503 : 0 : if (TREE_CODE (t) == MINUS_EXPR)
1504 : 0 : neg_a2 = true;
1505 : 0 : t = a1;
1506 : 0 : break;
1507 : : }
1508 : : }
1509 : 234 : if (TREE_CODE (a2) == MULT_EXPR)
1510 : : {
1511 : 60 : a1 = TREE_OPERAND (t, 0);
1512 : 60 : if (TREE_CODE (t) == MINUS_EXPR)
1513 : 0 : neg_a1 = true;
1514 : 60 : t = a2;
1515 : 60 : a2 = a1;
1516 : 60 : break;
1517 : : }
1518 : 174 : if (TREE_CODE (a1) == MULT_EXPR)
1519 : : {
1520 : 174 : a2 = TREE_OPERAND (t, 1);
1521 : 174 : if (TREE_CODE (t) == MINUS_EXPR)
1522 : 32 : neg_a2 = true;
1523 : 174 : t = a1;
1524 : 174 : break;
1525 : : }
1526 : 0 : a2 = integer_zero_node;
1527 : 0 : break;
1528 : 75 : case POINTER_PLUS_EXPR:
1529 : 75 : a1 = TREE_OPERAND (t, 0);
1530 : 75 : a2 = TREE_OPERAND (t, 1);
1531 : 79 : while (CONVERT_EXPR_P (a1))
1532 : 4 : a1 = TREE_OPERAND (a1, 0);
1533 : 75 : if (DECL_P (a1) && c_omp_is_loop_iterator (a1, d) >= 0)
1534 : : {
1535 : 71 : a2 = TREE_OPERAND (t, 1);
1536 : 71 : t = a1;
1537 : 71 : break;
1538 : : }
1539 : : break;
1540 : : default:
1541 : : break;
1542 : : }
1543 : :
1544 : 704 : a1 = integer_one_node;
1545 : 704 : if (TREE_CODE (t) == MULT_EXPR)
1546 : : {
1547 : 367 : tree o1 = TREE_OPERAND (t, 0);
1548 : 367 : tree o2 = TREE_OPERAND (t, 1);
1549 : 448 : while (CONVERT_EXPR_P (o1))
1550 : 81 : o1 = TREE_OPERAND (o1, 0);
1551 : 435 : while (CONVERT_EXPR_P (o2))
1552 : 68 : o2 = TREE_OPERAND (o2, 0);
1553 : 367 : if (DECL_P (o1) && c_omp_is_loop_iterator (o1, d) >= 0)
1554 : : {
1555 : 118 : a1 = TREE_OPERAND (t, 1);
1556 : 118 : t = o1;
1557 : : }
1558 : 249 : else if (DECL_P (o2) && c_omp_is_loop_iterator (o2, d) >= 0)
1559 : : {
1560 : 240 : a1 = TREE_OPERAND (t, 0);
1561 : 240 : t = o2;
1562 : : }
1563 : : }
1564 : :
1565 : 704 : d->kind &= 3;
1566 : 704 : tree ret = NULL_TREE;
1567 : 704 : if (DECL_P (t) && c_omp_is_loop_iterator (t, d) >= 0)
1568 : : {
1569 : 691 : location_t loc = d->expr_loc;
1570 : 691 : if (loc == UNKNOWN_LOCATION)
1571 : 93 : loc = d->stmt_loc;
1572 : 691 : if (!lang_hooks.types_compatible_p (TREE_TYPE (*tp), TREE_TYPE (t)))
1573 : : {
1574 : 16 : if (d->kind == 0)
1575 : 12 : error_at (loc, "outer iteration variable %qD used in initializer"
1576 : : " expression has type other than %qT",
1577 : 12 : t, TREE_TYPE (*tp));
1578 : : else
1579 : 4 : error_at (loc, "outer iteration variable %qD used in condition"
1580 : : " expression has type other than %qT",
1581 : 4 : t, TREE_TYPE (*tp));
1582 : 16 : d->fail = true;
1583 : : }
1584 : 675 : else if (!INTEGRAL_TYPE_P (TREE_TYPE (a1)))
1585 : : {
1586 : 0 : error_at (loc, "outer iteration variable %qD multiplier expression"
1587 : : " %qE is not integral", t, a1);
1588 : 0 : d->fail = true;
1589 : : }
1590 : 675 : else if (!INTEGRAL_TYPE_P (TREE_TYPE (a2)))
1591 : : {
1592 : 0 : error_at (loc, "outer iteration variable %qD addend expression"
1593 : : " %qE is not integral", t, a2);
1594 : 0 : d->fail = true;
1595 : : }
1596 : : else
1597 : : {
1598 : 675 : walk_tree_1 (&a1, c_omp_check_loop_iv_r, d, NULL, lh);
1599 : 675 : walk_tree_1 (&a2, c_omp_check_loop_iv_r, d, NULL, lh);
1600 : : }
1601 : 691 : if (!d->fail)
1602 : : {
1603 : 660 : a1 = fold_convert (TREE_TYPE (*tp), a1);
1604 : 660 : a2 = fold_convert (TREE_TYPE (*tp), a2);
1605 : 660 : if (neg_a1)
1606 : 0 : a1 = fold_build1 (NEGATE_EXPR, TREE_TYPE (a1), a1);
1607 : 660 : if (neg_a2)
1608 : 51 : a2 = fold_build1 (NEGATE_EXPR, TREE_TYPE (a2), a2);
1609 : 660 : ret = t;
1610 : 660 : *tp = make_tree_vec (3);
1611 : 660 : TREE_VEC_ELT (*tp, 0) = t;
1612 : 660 : TREE_VEC_ELT (*tp, 1) = a1;
1613 : 660 : TREE_VEC_ELT (*tp, 2) = a2;
1614 : : }
1615 : : }
1616 : : else
1617 : 13 : walk_tree_1 (&t, c_omp_check_loop_iv_r, d, NULL, lh);
1618 : :
1619 : 704 : d->ppset = ppset;
1620 : 704 : return ret;
1621 : 728 : }
1622 : :
1623 : : /* Callback for walk_tree to find nested loop transforming construct. */
1624 : :
1625 : : static tree
1626 : 10060 : c_find_nested_loop_xform_r (tree *tp, int *walk_subtrees, void *)
1627 : : {
1628 : 10060 : *walk_subtrees = 0;
1629 : 10060 : switch (TREE_CODE (*tp))
1630 : : {
1631 : : case OMP_TILE:
1632 : : case OMP_UNROLL:
1633 : : return *tp;
1634 : 2817 : case BIND_EXPR:
1635 : 2817 : *walk_subtrees = 1;
1636 : 2817 : break;
1637 : 41 : case STATEMENT_LIST:
1638 : 41 : *walk_subtrees = 1;
1639 : 41 : break;
1640 : 46 : case TRY_FINALLY_EXPR:
1641 : 46 : case CLEANUP_POINT_EXPR:
1642 : 46 : *walk_subtrees = 1;
1643 : 46 : break;
1644 : : default:
1645 : : break;
1646 : : }
1647 : : return NULL;
1648 : : }
1649 : :
1650 : : /* Find Jth loop among generated loops of STMT. */
1651 : :
1652 : : int
1653 : 1659 : c_omp_find_generated_loop (tree &stmt, int j, walk_tree_lh lh)
1654 : : {
1655 : 2498 : stmt = walk_tree_1 (&stmt, c_find_nested_loop_xform_r,
1656 : : NULL, NULL, lh);
1657 : 2498 : gcc_assert (stmt);
1658 : 2498 : switch (TREE_CODE (stmt))
1659 : : {
1660 : 726 : case OMP_UNROLL:
1661 : 726 : gcc_assert (omp_find_clause (OMP_FOR_CLAUSES (stmt),
1662 : : OMP_CLAUSE_PARTIAL));
1663 : : /* FALLTHRU */
1664 : : case OMP_TILE:
1665 : : int k;
1666 : : k = 0;
1667 : 2859 : for (int i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (stmt)); ++i)
1668 : 2859 : if (i == j)
1669 : : {
1670 : 2498 : if (TREE_VEC_ELT (OMP_FOR_INIT (stmt), i) == NULL_TREE)
1671 : : {
1672 : 839 : stmt = OMP_FOR_BODY (stmt);
1673 : 839 : return c_omp_find_generated_loop (stmt, k, lh);
1674 : : }
1675 : : else
1676 : 1659 : return i;
1677 : : }
1678 : 361 : else if (TREE_VEC_ELT (OMP_FOR_INIT (stmt), i) == NULL_TREE)
1679 : 56 : ++k;
1680 : 0 : gcc_unreachable ();
1681 : 0 : default:
1682 : 0 : gcc_unreachable ();
1683 : : }
1684 : : }
1685 : :
1686 : : /* Diagnose invalid references to loop iterators in lb, b and incr
1687 : : expressions. */
1688 : :
1689 : : bool
1690 : 31614 : c_omp_check_loop_iv (tree stmt, tree declv, walk_tree_lh lh)
1691 : : {
1692 : 31614 : hash_set<tree> pset;
1693 : 31614 : struct c_omp_check_loop_iv_data data;
1694 : 31614 : int i, k = 0;
1695 : :
1696 : 31614 : data.declv = declv;
1697 : 31614 : data.fail = false;
1698 : 31614 : data.maybe_nonrect = false;
1699 : 31614 : data.stmt_loc = EXPR_LOCATION (stmt);
1700 : 31614 : data.lh = lh;
1701 : 31614 : data.ppset = &pset;
1702 : 74855 : for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (stmt)); i++)
1703 : : {
1704 : 43241 : tree this_stmt = stmt;
1705 : 43241 : int j = i;
1706 : 43241 : tree init = TREE_VEC_ELT (OMP_FOR_INIT (stmt), i);
1707 : 43241 : if (init == NULL_TREE)
1708 : : {
1709 : 1649 : if (k == 0)
1710 : 1378 : data.declv = copy_node (declv);
1711 : 1649 : this_stmt = OMP_FOR_BODY (stmt);
1712 : 1649 : j = c_omp_find_generated_loop (this_stmt, k++, lh);
1713 : 1649 : init = TREE_VEC_ELT (OMP_FOR_INIT (this_stmt), j);
1714 : 1649 : TREE_VEC_ELT (data.declv, i) = TREE_OPERAND (init, 0);
1715 : : }
1716 : 43241 : gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
1717 : 43241 : tree decl = TREE_OPERAND (init, 0);
1718 : 43241 : tree cond = TREE_VEC_ELT (OMP_FOR_COND (this_stmt), j);
1719 : 43241 : gcc_assert (COMPARISON_CLASS_P (cond));
1720 : 43241 : gcc_assert (TREE_OPERAND (cond, 0) == decl);
1721 : 43241 : tree incr = TREE_VEC_ELT (OMP_FOR_INCR (this_stmt), j);
1722 : 43241 : data.expr_loc = EXPR_LOCATION (TREE_OPERAND (init, 1));
1723 : 43241 : tree vec_outer1 = NULL_TREE, vec_outer2 = NULL_TREE;
1724 : 43241 : int kind = 0;
1725 : 43241 : if (i > 0
1726 : 43241 : && (unsigned) c_omp_is_loop_iterator (decl, &data) < (unsigned) i)
1727 : : {
1728 : 24 : location_t loc = data.expr_loc;
1729 : 24 : if (loc == UNKNOWN_LOCATION)
1730 : 24 : loc = data.stmt_loc;
1731 : 24 : error_at (loc, "the same loop iteration variables %qD used in "
1732 : : "multiple associated loops", decl);
1733 : 24 : data.fail = true;
1734 : : }
1735 : : /* Handle non-rectangular loop nests. */
1736 : 43241 : if (TREE_CODE (stmt) != OACC_LOOP && i > 0)
1737 : 43241 : kind = 4;
1738 : 43241 : data.kind = kind;
1739 : 43241 : data.idx = i;
1740 : 43241 : walk_tree_1 (&TREE_OPERAND (init, 1),
1741 : : c_omp_check_loop_iv_r, &data, NULL, lh);
1742 : 43241 : if (data.maybe_nonrect)
1743 : 357 : vec_outer1 = c_omp_check_nonrect_loop_iv (&TREE_OPERAND (init, 1),
1744 : : &data, lh);
1745 : : /* Don't warn for C++ random access iterators here, the
1746 : : expression then involves the subtraction and always refers
1747 : : to the original value. The C++ FE needs to warn on those
1748 : : earlier. */
1749 : 43241 : if (decl == TREE_VEC_ELT (data.declv, i)
1750 : 43241 : || (TREE_CODE (TREE_VEC_ELT (data.declv, i)) == TREE_LIST
1751 : 933 : && decl == TREE_PURPOSE (TREE_VEC_ELT (data.declv, i))))
1752 : : {
1753 : 42308 : data.expr_loc = EXPR_LOCATION (cond);
1754 : 42308 : data.kind = kind | 1;
1755 : 42308 : walk_tree_1 (&TREE_OPERAND (cond, 1),
1756 : : c_omp_check_loop_iv_r, &data, NULL, lh);
1757 : 42308 : if (data.maybe_nonrect)
1758 : 387 : vec_outer2 = c_omp_check_nonrect_loop_iv (&TREE_OPERAND (cond, 1),
1759 : : &data, lh);
1760 : : }
1761 : 43241 : if (vec_outer1 && vec_outer2 && vec_outer1 != vec_outer2)
1762 : : {
1763 : 8 : location_t loc = data.expr_loc;
1764 : 8 : if (loc == UNKNOWN_LOCATION)
1765 : 0 : loc = data.stmt_loc;
1766 : 8 : error_at (loc, "two different outer iteration variables %qD and %qD"
1767 : : " used in a single loop", vec_outer1, vec_outer2);
1768 : 8 : data.fail = true;
1769 : 8 : }
1770 : 43233 : else if ((vec_outer1 || vec_outer2) && this_stmt != stmt)
1771 : : {
1772 : 16 : location_t loc = data.expr_loc;
1773 : 16 : if (loc == UNKNOWN_LOCATION)
1774 : 0 : loc = data.stmt_loc;
1775 : 16 : sorry_at (loc, "non-rectangular loops from generated loops "
1776 : : "unsupported");
1777 : 16 : data.fail = true;
1778 : : }
1779 : 43241 : if (vec_outer1 || vec_outer2)
1780 : 474 : OMP_FOR_NON_RECTANGULAR (stmt) = 1;
1781 : 43241 : if (TREE_CODE (incr) == MODIFY_EXPR)
1782 : : {
1783 : 11740 : gcc_assert (TREE_OPERAND (incr, 0) == decl);
1784 : 11740 : incr = TREE_OPERAND (incr, 1);
1785 : 11740 : data.kind = 2;
1786 : 11740 : if (TREE_CODE (incr) == PLUS_EXPR
1787 : 11740 : && TREE_OPERAND (incr, 1) == decl)
1788 : : {
1789 : 299 : data.expr_loc = EXPR_LOCATION (TREE_OPERAND (incr, 0));
1790 : 299 : walk_tree_1 (&TREE_OPERAND (incr, 0),
1791 : : c_omp_check_loop_iv_r, &data, NULL, lh);
1792 : : }
1793 : : else
1794 : : {
1795 : 11441 : data.expr_loc = EXPR_LOCATION (TREE_OPERAND (incr, 1));
1796 : 11441 : walk_tree_1 (&TREE_OPERAND (incr, 1),
1797 : : c_omp_check_loop_iv_r, &data, NULL, lh);
1798 : : }
1799 : : }
1800 : : }
1801 : 31614 : return !data.fail;
1802 : 31614 : }
1803 : :
1804 : : /* Similar, but allows to check the init or cond expressions individually. */
1805 : :
1806 : : bool
1807 : 1971 : c_omp_check_loop_iv_exprs (location_t stmt_loc, enum tree_code code,
1808 : : tree declv, int i, tree decl, tree init, tree cond,
1809 : : walk_tree_lh lh)
1810 : : {
1811 : 1971 : hash_set<tree> pset;
1812 : 1971 : struct c_omp_check_loop_iv_data data;
1813 : 1971 : int kind = (code != OACC_LOOP && i > 0) ? 4 : 0;
1814 : :
1815 : 1971 : data.declv = declv;
1816 : 1971 : data.fail = false;
1817 : 1971 : data.maybe_nonrect = false;
1818 : 1971 : data.stmt_loc = stmt_loc;
1819 : 1971 : data.lh = lh;
1820 : 1971 : data.ppset = &pset;
1821 : 1971 : data.idx = i;
1822 : 1971 : if (i > 0
1823 : 1971 : && (unsigned) c_omp_is_loop_iterator (decl, &data) < (unsigned) i)
1824 : : {
1825 : 6 : error_at (stmt_loc, "the same loop iteration variables %qD used in "
1826 : : "multiple associated loops", decl);
1827 : 6 : data.fail = true;
1828 : : }
1829 : 1971 : if (init)
1830 : : {
1831 : 1164 : data.expr_loc = EXPR_LOCATION (init);
1832 : 1164 : data.kind = kind;
1833 : 1164 : walk_tree_1 (&init,
1834 : : c_omp_check_loop_iv_r, &data, NULL, lh);
1835 : : }
1836 : 1971 : if (cond)
1837 : : {
1838 : 807 : gcc_assert (COMPARISON_CLASS_P (cond));
1839 : 807 : data.expr_loc = EXPR_LOCATION (init);
1840 : 807 : data.kind = kind | 1;
1841 : 807 : if (TREE_OPERAND (cond, 0) == decl)
1842 : 807 : walk_tree_1 (&TREE_OPERAND (cond, 1),
1843 : : c_omp_check_loop_iv_r, &data, NULL, lh);
1844 : : else
1845 : 0 : walk_tree_1 (&TREE_OPERAND (cond, 0),
1846 : : c_omp_check_loop_iv_r, &data, NULL, lh);
1847 : : }
1848 : 1971 : return !data.fail;
1849 : 1971 : }
1850 : :
1851 : :
1852 : : /* Helper function for c_omp_check_loop_binding_exprs: look for a binding
1853 : : of DECL in BODY. Only traverse things that might be containers for
1854 : : intervening code in an OMP loop. Returns the BIND_EXPR or DECL_EXPR
1855 : : if found, otherwise null. */
1856 : :
1857 : : static tree
1858 : 3909 : find_binding_in_body (tree decl, tree body)
1859 : : {
1860 : 5367 : if (!body)
1861 : : return NULL_TREE;
1862 : :
1863 : 5367 : switch (TREE_CODE (body))
1864 : : {
1865 : 365 : case BIND_EXPR:
1866 : 502 : for (tree b = BIND_EXPR_VARS (body); b; b = DECL_CHAIN (b))
1867 : 165 : if (b == decl)
1868 : : return body;
1869 : 337 : return find_binding_in_body (decl, BIND_EXPR_BODY (body));
1870 : :
1871 : 257 : case DECL_EXPR:
1872 : 257 : if (DECL_EXPR_DECL (body) == decl)
1873 : : return body;
1874 : : return NULL_TREE;
1875 : :
1876 : 1016 : case STATEMENT_LIST:
1877 : 4509 : for (tree_stmt_iterator si = tsi_start (body); !tsi_end_p (si);
1878 : 3493 : tsi_next (&si))
1879 : : {
1880 : 3521 : tree b = find_binding_in_body (decl, tsi_stmt (si));
1881 : 3521 : if (b)
1882 : 28 : return b;
1883 : : }
1884 : 988 : return NULL_TREE;
1885 : :
1886 : 1121 : case OMP_STRUCTURED_BLOCK:
1887 : 1121 : return find_binding_in_body (decl, OMP_BODY (body));
1888 : :
1889 : : default:
1890 : : return NULL_TREE;
1891 : : }
1892 : : }
1893 : :
1894 : : /* Traversal function for check_loop_binding_expr, to diagnose
1895 : : errors when a binding made in intervening code is referenced outside
1896 : : of the loop. Returns non-null if such a reference is found. DATA points
1897 : : to the tree containing the loop body. */
1898 : :
1899 : : static tree
1900 : 808 : check_loop_binding_expr_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
1901 : : void *data)
1902 : : {
1903 : 808 : tree body = *(tree *)data;
1904 : :
1905 : 808 : if (DECL_P (*tp) && find_binding_in_body (*tp, body))
1906 : 49 : return *tp;
1907 : : return NULL_TREE;
1908 : : }
1909 : :
1910 : : /* Helper macro used below. */
1911 : :
1912 : : #define LOCATION_OR(loc1, loc2) \
1913 : : ((loc1) != UNKNOWN_LOCATION ? (loc1) : (loc2))
1914 : :
1915 : : enum check_loop_binding_expr_ctx {
1916 : : CHECK_LOOP_BINDING_EXPR_CTX_LOOP_VAR,
1917 : : CHECK_LOOP_BINDING_EXPR_CTX_IN_INIT,
1918 : : CHECK_LOOP_BINDING_EXPR_CTX_END_TEST,
1919 : : CHECK_LOOP_BINDING_EXPR_CTX_INCR
1920 : : };
1921 : :
1922 : : /* Check a single expression EXPR for references to variables bound in
1923 : : intervening code in BODY. Return true if ok, otherwise give an error
1924 : : referencing CONTEXT and return false. Use LOC for the error message
1925 : : if EXPR doesn't have one. */
1926 : : static bool
1927 : 622 : check_loop_binding_expr (tree expr, tree body, location_t loc,
1928 : : check_loop_binding_expr_ctx ctx)
1929 : : {
1930 : 622 : tree bad = walk_tree (&expr, check_loop_binding_expr_r, (void *)&body, NULL);
1931 : :
1932 : 622 : if (bad)
1933 : : {
1934 : 49 : location_t eloc = EXPR_LOCATION (expr);
1935 : 49 : eloc = LOCATION_OR (eloc, loc);
1936 : 49 : switch (ctx)
1937 : : {
1938 : 14 : case CHECK_LOOP_BINDING_EXPR_CTX_LOOP_VAR:
1939 : 14 : error_at (eloc, "variable %qD used as loop variable is bound "
1940 : : "in intervening code", bad);
1941 : 14 : break;
1942 : 21 : case CHECK_LOOP_BINDING_EXPR_CTX_IN_INIT:
1943 : 21 : error_at (eloc, "variable %qD used in initializer is bound "
1944 : : "in intervening code", bad);
1945 : 21 : break;
1946 : 7 : case CHECK_LOOP_BINDING_EXPR_CTX_END_TEST:
1947 : 7 : error_at (eloc, "variable %qD used in end test is bound "
1948 : : "in intervening code", bad);
1949 : 7 : break;
1950 : 7 : case CHECK_LOOP_BINDING_EXPR_CTX_INCR:
1951 : 7 : error_at (eloc, "variable %qD used in increment expression is bound "
1952 : : "in intervening code", bad);
1953 : 7 : break;
1954 : : }
1955 : 49 : return false;
1956 : : }
1957 : : return true;
1958 : : }
1959 : :
1960 : : /* STMT is an OMP_FOR construct. Check all of the iteration variable,
1961 : : initializer, end condition, and increment for bindings inside the
1962 : : loop body. If ORIG_INITS is provided, check those elements too.
1963 : : Return true if OK, false otherwise. */
1964 : : bool
1965 : 173 : c_omp_check_loop_binding_exprs (tree stmt, vec<tree> *orig_inits)
1966 : : {
1967 : 173 : bool ok = true;
1968 : 173 : location_t loc = EXPR_LOCATION (stmt);
1969 : 173 : tree body = OMP_FOR_BODY (stmt);
1970 : 308 : int orig_init_length = orig_inits ? orig_inits->length () : 0;
1971 : :
1972 : 376 : for (int i = 1; i < TREE_VEC_LENGTH (OMP_FOR_INIT (stmt)); i++)
1973 : : {
1974 : 203 : tree init = TREE_VEC_ELT (OMP_FOR_INIT (stmt), i);
1975 : 203 : if (init == NULL_TREE)
1976 : : {
1977 : 16 : sorry_at (loc, "imperfectly nested loop using generated loops");
1978 : 16 : ok = false;
1979 : 16 : continue;
1980 : : }
1981 : 187 : tree cond = TREE_VEC_ELT (OMP_FOR_COND (stmt), i);
1982 : 187 : tree incr = TREE_VEC_ELT (OMP_FOR_INCR (stmt), i);
1983 : 187 : gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
1984 : 187 : tree decl = TREE_OPERAND (init, 0);
1985 : 187 : tree orig_init = i < orig_init_length ? (*orig_inits)[i] : NULL_TREE;
1986 : 187 : tree e;
1987 : 187 : location_t eloc;
1988 : :
1989 : 187 : e = TREE_OPERAND (init, 1);
1990 : 187 : eloc = LOCATION_OR (EXPR_LOCATION (init), loc);
1991 : 187 : if (!check_loop_binding_expr (decl, body, eloc,
1992 : : CHECK_LOOP_BINDING_EXPR_CTX_LOOP_VAR))
1993 : 14 : ok = false;
1994 : 187 : if (!check_loop_binding_expr (e, body, eloc,
1995 : : CHECK_LOOP_BINDING_EXPR_CTX_IN_INIT))
1996 : 15 : ok = false;
1997 : 187 : if (orig_init
1998 : 187 : && !check_loop_binding_expr (orig_init, body, eloc,
1999 : : CHECK_LOOP_BINDING_EXPR_CTX_IN_INIT))
2000 : : ok = false;
2001 : :
2002 : : /* INCR and/or COND may be null if this is a template with a
2003 : : class iterator. */
2004 : 187 : if (cond)
2005 : : {
2006 : 187 : eloc = LOCATION_OR (EXPR_LOCATION (cond), loc);
2007 : 187 : if (COMPARISON_CLASS_P (cond) && TREE_OPERAND (cond, 0) == decl)
2008 : 185 : e = TREE_OPERAND (cond, 1);
2009 : 2 : else if (COMPARISON_CLASS_P (cond) && TREE_OPERAND (cond, 1) == decl)
2010 : 0 : e = TREE_OPERAND (cond, 0);
2011 : : else
2012 : : e = cond;
2013 : 187 : if (!check_loop_binding_expr (e, body, eloc,
2014 : : CHECK_LOOP_BINDING_EXPR_CTX_END_TEST))
2015 : 187 : ok = false;
2016 : : }
2017 : :
2018 : 187 : if (incr)
2019 : : {
2020 : 185 : eloc = LOCATION_OR (EXPR_LOCATION (incr), loc);
2021 : : /* INCR should be either a MODIFY_EXPR or pre/post
2022 : : increment/decrement. We don't have to check the latter
2023 : : since there are no operands besides the iteration variable. */
2024 : 185 : if (TREE_CODE (incr) == MODIFY_EXPR
2025 : 185 : && !check_loop_binding_expr (TREE_OPERAND (incr, 1), body, eloc,
2026 : : CHECK_LOOP_BINDING_EXPR_CTX_INCR))
2027 : : ok = false;
2028 : : }
2029 : : }
2030 : :
2031 : 173 : return ok;
2032 : : }
2033 : :
2034 : : /* This function splits clauses for OpenACC combined loop
2035 : : constructs. OpenACC combined loop constructs are:
2036 : : #pragma acc kernels loop
2037 : : #pragma acc parallel loop */
2038 : :
2039 : : tree
2040 : 1832 : c_oacc_split_loop_clauses (tree clauses, tree *not_loop_clauses,
2041 : : bool is_parallel)
2042 : : {
2043 : 1832 : tree next, loop_clauses, nc;
2044 : :
2045 : 1832 : loop_clauses = *not_loop_clauses = NULL_TREE;
2046 : 3616 : for (; clauses ; clauses = next)
2047 : : {
2048 : 1784 : next = OMP_CLAUSE_CHAIN (clauses);
2049 : :
2050 : 1784 : switch (OMP_CLAUSE_CODE (clauses))
2051 : : {
2052 : : /* Loop clauses. */
2053 : 1174 : case OMP_CLAUSE_COLLAPSE:
2054 : 1174 : case OMP_CLAUSE_TILE:
2055 : 1174 : case OMP_CLAUSE_GANG:
2056 : 1174 : case OMP_CLAUSE_WORKER:
2057 : 1174 : case OMP_CLAUSE_VECTOR:
2058 : 1174 : case OMP_CLAUSE_AUTO:
2059 : 1174 : case OMP_CLAUSE_SEQ:
2060 : 1174 : case OMP_CLAUSE_INDEPENDENT:
2061 : 1174 : case OMP_CLAUSE_PRIVATE:
2062 : 1174 : OMP_CLAUSE_CHAIN (clauses) = loop_clauses;
2063 : 1174 : loop_clauses = clauses;
2064 : 1174 : break;
2065 : :
2066 : : /* Reductions must be duplicated on both constructs. */
2067 : 114 : case OMP_CLAUSE_REDUCTION:
2068 : 114 : if (is_parallel)
2069 : : {
2070 : 83 : nc = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2071 : : OMP_CLAUSE_REDUCTION);
2072 : 83 : OMP_CLAUSE_DECL (nc) = OMP_CLAUSE_DECL (clauses);
2073 : 166 : OMP_CLAUSE_REDUCTION_CODE (nc)
2074 : 83 : = OMP_CLAUSE_REDUCTION_CODE (clauses);
2075 : 83 : OMP_CLAUSE_CHAIN (nc) = *not_loop_clauses;
2076 : 83 : *not_loop_clauses = nc;
2077 : : }
2078 : :
2079 : 114 : OMP_CLAUSE_CHAIN (clauses) = loop_clauses;
2080 : 114 : loop_clauses = clauses;
2081 : 114 : break;
2082 : :
2083 : : /* Parallel/kernels clauses. */
2084 : 496 : default:
2085 : 496 : OMP_CLAUSE_CHAIN (clauses) = *not_loop_clauses;
2086 : 496 : *not_loop_clauses = clauses;
2087 : 496 : break;
2088 : : }
2089 : : }
2090 : :
2091 : 1832 : return loop_clauses;
2092 : : }
2093 : :
2094 : : /* This function attempts to split or duplicate clauses for OpenMP
2095 : : combined/composite constructs. Right now there are 30 different
2096 : : constructs. CODE is the innermost construct in the combined construct,
2097 : : and MASK allows to determine which constructs are combined together,
2098 : : as every construct has at least one clause that no other construct
2099 : : has (except for OMP_SECTIONS, but that can be only combined with parallel,
2100 : : and OMP_MASTER, which doesn't have any clauses at all).
2101 : : OpenMP combined/composite constructs are:
2102 : : #pragma omp distribute parallel for
2103 : : #pragma omp distribute parallel for simd
2104 : : #pragma omp distribute simd
2105 : : #pragma omp for simd
2106 : : #pragma omp masked taskloop
2107 : : #pragma omp masked taskloop simd
2108 : : #pragma omp master taskloop
2109 : : #pragma omp master taskloop simd
2110 : : #pragma omp parallel for
2111 : : #pragma omp parallel for simd
2112 : : #pragma omp parallel loop
2113 : : #pragma omp parallel masked
2114 : : #pragma omp parallel masked taskloop
2115 : : #pragma omp parallel masked taskloop simd
2116 : : #pragma omp parallel master
2117 : : #pragma omp parallel master taskloop
2118 : : #pragma omp parallel master taskloop simd
2119 : : #pragma omp parallel sections
2120 : : #pragma omp target parallel
2121 : : #pragma omp target parallel for
2122 : : #pragma omp target parallel for simd
2123 : : #pragma omp target parallel loop
2124 : : #pragma omp target teams
2125 : : #pragma omp target teams distribute
2126 : : #pragma omp target teams distribute parallel for
2127 : : #pragma omp target teams distribute parallel for simd
2128 : : #pragma omp target teams distribute simd
2129 : : #pragma omp target teams loop
2130 : : #pragma omp target simd
2131 : : #pragma omp taskloop simd
2132 : : #pragma omp teams distribute
2133 : : #pragma omp teams distribute parallel for
2134 : : #pragma omp teams distribute parallel for simd
2135 : : #pragma omp teams distribute simd
2136 : : #pragma omp teams loop */
2137 : :
2138 : : void
2139 : 15815 : c_omp_split_clauses (location_t loc, enum tree_code code,
2140 : : omp_clause_mask mask, tree clauses, tree *cclauses)
2141 : : {
2142 : 15815 : tree next, c;
2143 : 15815 : enum c_omp_clause_split s;
2144 : 15815 : int i;
2145 : 15815 : bool has_dup_allocate = false;
2146 : :
2147 : 110705 : for (i = 0; i < C_OMP_CLAUSE_SPLIT_COUNT; i++)
2148 : 94890 : cclauses[i] = NULL;
2149 : : /* Add implicit nowait clause on
2150 : : #pragma omp parallel {for,for simd,sections}. */
2151 : 15815 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0)
2152 : 10942 : switch (code)
2153 : : {
2154 : 10284 : case OMP_FOR:
2155 : 10284 : case OMP_SIMD:
2156 : 25917 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0)
2157 : 10102 : cclauses[C_OMP_CLAUSE_SPLIT_FOR]
2158 : 10102 : = build_omp_clause (loc, OMP_CLAUSE_NOWAIT);
2159 : : break;
2160 : 155 : case OMP_SECTIONS:
2161 : 155 : cclauses[C_OMP_CLAUSE_SPLIT_SECTIONS]
2162 : 155 : = build_omp_clause (loc, OMP_CLAUSE_NOWAIT);
2163 : 155 : break;
2164 : : default:
2165 : : break;
2166 : : }
2167 : :
2168 : 55626 : for (; clauses ; clauses = next)
2169 : : {
2170 : 39811 : next = OMP_CLAUSE_CHAIN (clauses);
2171 : :
2172 : 39811 : switch (OMP_CLAUSE_CODE (clauses))
2173 : : {
2174 : : /* First the clauses that are unique to some constructs. */
2175 : : case OMP_CLAUSE_DEVICE:
2176 : : case OMP_CLAUSE_MAP:
2177 : : case OMP_CLAUSE_IS_DEVICE_PTR:
2178 : : case OMP_CLAUSE_HAS_DEVICE_ADDR:
2179 : : case OMP_CLAUSE_DEFAULTMAP:
2180 : : case OMP_CLAUSE_DEPEND:
2181 : : s = C_OMP_CLAUSE_SPLIT_TARGET;
2182 : : break;
2183 : 4 : case OMP_CLAUSE_DOACROSS:
2184 : : /* This can happen with invalid depend(source) or
2185 : : depend(sink:vec) on target combined with other constructs. */
2186 : 4 : gcc_assert (OMP_CLAUSE_DOACROSS_DEPEND (clauses));
2187 : : s = C_OMP_CLAUSE_SPLIT_TARGET;
2188 : : break;
2189 : : case OMP_CLAUSE_NUM_TEAMS:
2190 : 2454 : s = C_OMP_CLAUSE_SPLIT_TEAMS;
2191 : : break;
2192 : : case OMP_CLAUSE_DIST_SCHEDULE:
2193 : 6925 : s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE;
2194 : : break;
2195 : : case OMP_CLAUSE_COPYIN:
2196 : : case OMP_CLAUSE_NUM_THREADS:
2197 : : case OMP_CLAUSE_PROC_BIND:
2198 : 7732 : s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2199 : : break;
2200 : : case OMP_CLAUSE_ORDERED:
2201 : 13074 : s = C_OMP_CLAUSE_SPLIT_FOR;
2202 : : break;
2203 : 6075 : case OMP_CLAUSE_SCHEDULE:
2204 : 6075 : s = C_OMP_CLAUSE_SPLIT_FOR;
2205 : 6075 : if (code != OMP_SIMD)
2206 : 3076 : OMP_CLAUSE_SCHEDULE_SIMD (clauses) = 0;
2207 : : break;
2208 : : case OMP_CLAUSE_SAFELEN:
2209 : : case OMP_CLAUSE_SIMDLEN:
2210 : : case OMP_CLAUSE_ALIGNED:
2211 : : case OMP_CLAUSE_NONTEMPORAL:
2212 : 5337 : s = C_OMP_CLAUSE_SPLIT_SIMD;
2213 : : break;
2214 : : case OMP_CLAUSE_GRAINSIZE:
2215 : : case OMP_CLAUSE_NUM_TASKS:
2216 : : case OMP_CLAUSE_FINAL:
2217 : : case OMP_CLAUSE_UNTIED:
2218 : : case OMP_CLAUSE_MERGEABLE:
2219 : : case OMP_CLAUSE_NOGROUP:
2220 : : case OMP_CLAUSE_PRIORITY:
2221 : 13074 : s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
2222 : : break;
2223 : : case OMP_CLAUSE_BIND:
2224 : 13074 : s = C_OMP_CLAUSE_SPLIT_LOOP;
2225 : : break;
2226 : : case OMP_CLAUSE_FILTER:
2227 : 6925 : s = C_OMP_CLAUSE_SPLIT_MASKED;
2228 : : break;
2229 : : /* Duplicate this to all of taskloop, distribute, for, simd and
2230 : : loop. */
2231 : 5055 : case OMP_CLAUSE_COLLAPSE:
2232 : 5055 : if (code == OMP_SIMD)
2233 : : {
2234 : 2574 : if ((mask & ((OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)
2235 : 2574 : | (OMP_CLAUSE_MASK_1
2236 : 2574 : << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)
2237 : 2574 : | (OMP_CLAUSE_MASK_1
2238 : 2574 : << PRAGMA_OMP_CLAUSE_NOGROUP))) != 0)
2239 : : {
2240 : 2526 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2241 : : OMP_CLAUSE_COLLAPSE);
2242 : 2526 : OMP_CLAUSE_COLLAPSE_EXPR (c)
2243 : 2526 : = OMP_CLAUSE_COLLAPSE_EXPR (clauses);
2244 : 2526 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_SIMD];
2245 : 2526 : cclauses[C_OMP_CLAUSE_SPLIT_SIMD] = c;
2246 : : }
2247 : : else
2248 : : {
2249 : : /* This must be #pragma omp target simd */
2250 : : s = C_OMP_CLAUSE_SPLIT_SIMD;
2251 : : break;
2252 : : }
2253 : : }
2254 : 5007 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0)
2255 : : {
2256 : 3907 : if ((mask & (OMP_CLAUSE_MASK_1
2257 : 3907 : << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0)
2258 : : {
2259 : 2621 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2260 : : OMP_CLAUSE_COLLAPSE);
2261 : 2621 : OMP_CLAUSE_COLLAPSE_EXPR (c)
2262 : 2621 : = OMP_CLAUSE_COLLAPSE_EXPR (clauses);
2263 : 2621 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_FOR];
2264 : 2621 : cclauses[C_OMP_CLAUSE_SPLIT_FOR] = c;
2265 : 2621 : s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE;
2266 : : }
2267 : : else
2268 : : s = C_OMP_CLAUSE_SPLIT_FOR;
2269 : : }
2270 : 1100 : else if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP))
2271 : 13760 : != 0)
2272 : : s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
2273 : 686 : else if (code == OMP_LOOP)
2274 : : s = C_OMP_CLAUSE_SPLIT_LOOP;
2275 : : else
2276 : 6925 : s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE;
2277 : : break;
2278 : : /* Private clause is supported on all constructs but master/masked,
2279 : : it is enough to put it on the innermost one other than
2280 : : master/masked. For #pragma omp {for,sections} put it on parallel
2281 : : though, as that's what we did for OpenMP 3.1. */
2282 : 1293 : case OMP_CLAUSE_PRIVATE:
2283 : 1293 : switch (code)
2284 : : {
2285 : : case OMP_SIMD: s = C_OMP_CLAUSE_SPLIT_SIMD; break;
2286 : : case OMP_FOR: case OMP_SECTIONS:
2287 : 7732 : case OMP_PARALLEL: s = C_OMP_CLAUSE_SPLIT_PARALLEL; break;
2288 : 6925 : case OMP_DISTRIBUTE: s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE; break;
2289 : 2454 : case OMP_TEAMS: s = C_OMP_CLAUSE_SPLIT_TEAMS; break;
2290 : 7732 : case OMP_MASTER: s = C_OMP_CLAUSE_SPLIT_PARALLEL; break;
2291 : 7732 : case OMP_MASKED: s = C_OMP_CLAUSE_SPLIT_PARALLEL; break;
2292 : 13074 : case OMP_TASKLOOP: s = C_OMP_CLAUSE_SPLIT_TASKLOOP; break;
2293 : 13074 : case OMP_LOOP: s = C_OMP_CLAUSE_SPLIT_LOOP; break;
2294 : 0 : default: gcc_unreachable ();
2295 : : }
2296 : : break;
2297 : : /* Firstprivate clause is supported on all constructs but
2298 : : simd, master, masked and loop. Put it on the outermost of those
2299 : : and duplicate on teams and parallel. */
2300 : 1741 : case OMP_CLAUSE_FIRSTPRIVATE:
2301 : 1741 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP))
2302 : 2101 : != 0)
2303 : : {
2304 : 388 : if (code == OMP_SIMD
2305 : 388 : && (mask & ((OMP_CLAUSE_MASK_1
2306 : 134 : << PRAGMA_OMP_CLAUSE_NUM_THREADS)
2307 : 134 : | (OMP_CLAUSE_MASK_1
2308 : 134 : << PRAGMA_OMP_CLAUSE_NUM_TEAMS))) == 0)
2309 : : {
2310 : : /* This must be #pragma omp target simd. */
2311 : 28 : s = C_OMP_CLAUSE_SPLIT_TARGET;
2312 : 28 : OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (clauses) = 1;
2313 : 28 : OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT_TARGET (clauses) = 1;
2314 : 28 : break;
2315 : : }
2316 : 360 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2317 : : OMP_CLAUSE_FIRSTPRIVATE);
2318 : : /* firstprivate should not be applied to target if it is
2319 : : also lastprivate or on the combined/composite construct,
2320 : : or if it is mentioned in map clause. OMP_CLAUSE_DECLs
2321 : : may need to go through FE handling though (instantiation,
2322 : : C++ non-static data members, array section lowering), so
2323 : : add the clause with OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT and
2324 : : let *finish_omp_clauses and the gimplifier handle it
2325 : : right. */
2326 : 360 : OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c) = 1;
2327 : 360 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2328 : 360 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
2329 : 360 : cclauses[C_OMP_CLAUSE_SPLIT_TARGET] = c;
2330 : : }
2331 : 1713 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS))
2332 : 1713 : != 0)
2333 : : {
2334 : 1105 : if ((mask & ((OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS)
2335 : 1105 : | (OMP_CLAUSE_MASK_1
2336 : 1105 : << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE))) != 0)
2337 : : {
2338 : 465 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2339 : : OMP_CLAUSE_FIRSTPRIVATE);
2340 : 465 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2341 : 465 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL];
2342 : 465 : cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL] = c;
2343 : 465 : if ((mask & (OMP_CLAUSE_MASK_1
2344 : 465 : << PRAGMA_OMP_CLAUSE_NUM_TEAMS)) != 0)
2345 : : s = C_OMP_CLAUSE_SPLIT_TEAMS;
2346 : : else
2347 : 6925 : s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE;
2348 : : }
2349 : 640 : else if ((mask & (OMP_CLAUSE_MASK_1
2350 : 640 : << PRAGMA_OMP_CLAUSE_NOGROUP)) != 0)
2351 : : /* This must be
2352 : : #pragma omp parallel mas{ked,ter} taskloop{, simd}. */
2353 : : s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
2354 : : else
2355 : : /* This must be
2356 : : #pragma omp parallel{, for{, simd}, sections,loop}
2357 : : or
2358 : : #pragma omp target parallel. */
2359 : 7732 : s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2360 : : }
2361 : 608 : else if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS))
2362 : 608 : != 0)
2363 : : {
2364 : : /* This must be one of
2365 : : #pragma omp {,target }teams {distribute,loop}
2366 : : #pragma omp target teams
2367 : : #pragma omp {,target }teams distribute simd. */
2368 : 276 : gcc_assert (code == OMP_DISTRIBUTE
2369 : : || code == OMP_LOOP
2370 : : || code == OMP_TEAMS
2371 : : || code == OMP_SIMD);
2372 : : s = C_OMP_CLAUSE_SPLIT_TEAMS;
2373 : : }
2374 : 332 : else if ((mask & (OMP_CLAUSE_MASK_1
2375 : 332 : << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0)
2376 : : {
2377 : : /* This must be #pragma omp distribute simd. */
2378 : 76 : gcc_assert (code == OMP_SIMD);
2379 : : s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE;
2380 : : }
2381 : 256 : else if ((mask & (OMP_CLAUSE_MASK_1
2382 : 256 : << PRAGMA_OMP_CLAUSE_NOGROUP)) != 0)
2383 : : {
2384 : : /* This must be
2385 : : #pragma omp {,{,parallel }mas{ked,ter} }taskloop simd
2386 : : or
2387 : : #pragma omp {,parallel }mas{ked,ter} taskloop. */
2388 : 228 : gcc_assert (code == OMP_SIMD || code == OMP_TASKLOOP);
2389 : : s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
2390 : : }
2391 : : else
2392 : : {
2393 : : /* This must be #pragma omp for simd. */
2394 : 28 : gcc_assert (code == OMP_SIMD);
2395 : : s = C_OMP_CLAUSE_SPLIT_FOR;
2396 : : }
2397 : : break;
2398 : : /* Lastprivate is allowed on distribute, for, sections, taskloop, loop
2399 : : and simd. In parallel {for{, simd},sections} we actually want to
2400 : : put it on parallel rather than for or sections. */
2401 : 1955 : case OMP_CLAUSE_LASTPRIVATE:
2402 : 1955 : if (code == OMP_DISTRIBUTE)
2403 : : {
2404 : : s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE;
2405 : : break;
2406 : : }
2407 : 1947 : if ((mask & (OMP_CLAUSE_MASK_1
2408 : 1947 : << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0)
2409 : : {
2410 : 548 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2411 : : OMP_CLAUSE_LASTPRIVATE);
2412 : 548 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2413 : 548 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE];
2414 : 1096 : OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c)
2415 : 548 : = OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (clauses);
2416 : 548 : cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE] = c;
2417 : : }
2418 : 1947 : if (code == OMP_FOR || code == OMP_SECTIONS)
2419 : : {
2420 : 823 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS))
2421 : 20806 : != 0)
2422 : : s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2423 : : else
2424 : 13074 : s = C_OMP_CLAUSE_SPLIT_FOR;
2425 : : break;
2426 : : }
2427 : : if (code == OMP_TASKLOOP)
2428 : : {
2429 : : s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
2430 : : break;
2431 : : }
2432 : : if (code == OMP_LOOP)
2433 : : {
2434 : : s = C_OMP_CLAUSE_SPLIT_LOOP;
2435 : : break;
2436 : : }
2437 : 0 : gcc_assert (code == OMP_SIMD);
2438 : 812 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0)
2439 : : {
2440 : 423 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2441 : : OMP_CLAUSE_LASTPRIVATE);
2442 : 423 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2443 : 846 : OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c)
2444 : 423 : = OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (clauses);
2445 : 423 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS))
2446 : 498 : != 0)
2447 : : s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2448 : : else
2449 : 75 : s = C_OMP_CLAUSE_SPLIT_FOR;
2450 : 423 : OMP_CLAUSE_CHAIN (c) = cclauses[s];
2451 : 423 : cclauses[s] = c;
2452 : : }
2453 : 812 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP)) != 0)
2454 : : {
2455 : 253 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2456 : : OMP_CLAUSE_LASTPRIVATE);
2457 : 253 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2458 : 506 : OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c)
2459 : 253 : = OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (clauses);
2460 : 253 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP];
2461 : 253 : cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP] = c;
2462 : : }
2463 : : s = C_OMP_CLAUSE_SPLIT_SIMD;
2464 : : break;
2465 : : /* Shared and default clauses are allowed on parallel, teams and
2466 : : taskloop. */
2467 : 3559 : case OMP_CLAUSE_SHARED:
2468 : 3559 : case OMP_CLAUSE_DEFAULT:
2469 : 3559 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP))
2470 : 3559 : != 0)
2471 : : {
2472 : 890 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS))
2473 : 13430 : != 0)
2474 : : {
2475 : 712 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2476 : 356 : OMP_CLAUSE_CODE (clauses));
2477 : 356 : if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_SHARED)
2478 : 128 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2479 : : else
2480 : 456 : OMP_CLAUSE_DEFAULT_KIND (c)
2481 : 228 : = OMP_CLAUSE_DEFAULT_KIND (clauses);
2482 : 356 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL];
2483 : 356 : cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL] = c;
2484 : : }
2485 : : s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
2486 : : break;
2487 : : }
2488 : 2669 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS))
2489 : 9027 : != 0)
2490 : : {
2491 : 1295 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS))
2492 : 3062 : == 0)
2493 : : {
2494 : : s = C_OMP_CLAUSE_SPLIT_TEAMS;
2495 : : break;
2496 : : }
2497 : 1216 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2498 : 608 : OMP_CLAUSE_CODE (clauses));
2499 : 608 : if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_SHARED)
2500 : 284 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2501 : : else
2502 : 648 : OMP_CLAUSE_DEFAULT_KIND (c)
2503 : 324 : = OMP_CLAUSE_DEFAULT_KIND (clauses);
2504 : 608 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
2505 : 608 : cclauses[C_OMP_CLAUSE_SPLIT_TEAMS] = c;
2506 : : }
2507 : : s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2508 : : break;
2509 : : /* order clauses are allowed on distribute, for, simd and loop. */
2510 : 880 : case OMP_CLAUSE_ORDER:
2511 : 880 : if ((mask & (OMP_CLAUSE_MASK_1
2512 : 880 : << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0)
2513 : : {
2514 : 332 : if (code == OMP_DISTRIBUTE)
2515 : : {
2516 : : s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE;
2517 : : break;
2518 : : }
2519 : 288 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2520 : : OMP_CLAUSE_ORDER);
2521 : 576 : OMP_CLAUSE_ORDER_UNCONSTRAINED (c)
2522 : 288 : = OMP_CLAUSE_ORDER_UNCONSTRAINED (clauses);
2523 : 576 : OMP_CLAUSE_ORDER_REPRODUCIBLE (c)
2524 : 288 : = OMP_CLAUSE_ORDER_REPRODUCIBLE (clauses);
2525 : 288 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE];
2526 : 288 : cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE] = c;
2527 : : }
2528 : 836 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0)
2529 : : {
2530 : 465 : if (code == OMP_SIMD)
2531 : : {
2532 : 317 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2533 : : OMP_CLAUSE_ORDER);
2534 : 634 : OMP_CLAUSE_ORDER_UNCONSTRAINED (c)
2535 : 317 : = OMP_CLAUSE_ORDER_UNCONSTRAINED (clauses);
2536 : 634 : OMP_CLAUSE_ORDER_REPRODUCIBLE (c)
2537 : 317 : = OMP_CLAUSE_ORDER_REPRODUCIBLE (clauses);
2538 : 317 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_FOR];
2539 : 317 : cclauses[C_OMP_CLAUSE_SPLIT_FOR] = c;
2540 : 317 : s = C_OMP_CLAUSE_SPLIT_SIMD;
2541 : : }
2542 : : else
2543 : : s = C_OMP_CLAUSE_SPLIT_FOR;
2544 : : }
2545 : 371 : else if (code == OMP_LOOP)
2546 : : s = C_OMP_CLAUSE_SPLIT_LOOP;
2547 : : else
2548 : 5337 : s = C_OMP_CLAUSE_SPLIT_SIMD;
2549 : : break;
2550 : : /* Reduction is allowed on simd, for, parallel, sections, taskloop,
2551 : : teams and loop. Duplicate it on all of them, but omit on for or
2552 : : sections if parallel is present (unless inscan, in that case
2553 : : omit on parallel). If taskloop or loop is combined with
2554 : : parallel, omit it on parallel. */
2555 : 2905 : case OMP_CLAUSE_REDUCTION:
2556 : 2905 : if (OMP_CLAUSE_REDUCTION_TASK (clauses))
2557 : : {
2558 : 56 : if (code == OMP_SIMD || code == OMP_LOOP)
2559 : : {
2560 : 16 : error_at (OMP_CLAUSE_LOCATION (clauses),
2561 : : "invalid %<task%> reduction modifier on construct "
2562 : : "combined with %<simd%> or %<loop%>");
2563 : 16 : OMP_CLAUSE_REDUCTION_TASK (clauses) = 0;
2564 : : }
2565 : 40 : else if (code != OMP_SECTIONS
2566 : 34 : && (mask & (OMP_CLAUSE_MASK_1
2567 : 34 : << PRAGMA_OMP_CLAUSE_NUM_THREADS)) == 0
2568 : 40 : && (mask & (OMP_CLAUSE_MASK_1
2569 : 4 : << PRAGMA_OMP_CLAUSE_SCHEDULE)) == 0)
2570 : : {
2571 : 4 : error_at (OMP_CLAUSE_LOCATION (clauses),
2572 : : "invalid %<task%> reduction modifier on construct "
2573 : : "not combined with %<parallel%>, %<for%> or "
2574 : : "%<sections%>");
2575 : 4 : OMP_CLAUSE_REDUCTION_TASK (clauses) = 0;
2576 : : }
2577 : : }
2578 : 2905 : if (OMP_CLAUSE_REDUCTION_INSCAN (clauses)
2579 : 2905 : && ((mask & ((OMP_CLAUSE_MASK_1
2580 : 196 : << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)
2581 : 196 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)))
2582 : 2917 : != 0))
2583 : : {
2584 : 12 : error_at (OMP_CLAUSE_LOCATION (clauses),
2585 : : "%<inscan%> %<reduction%> clause on construct other "
2586 : : "than %<for%>, %<simd%>, %<for simd%>, "
2587 : : "%<parallel for%>, %<parallel for simd%>");
2588 : 12 : OMP_CLAUSE_REDUCTION_INSCAN (clauses) = 0;
2589 : : }
2590 : 2905 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)) != 0)
2591 : : {
2592 : 572 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2593 : : OMP_CLAUSE_MAP);
2594 : 572 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2595 : 572 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_TOFROM);
2596 : 572 : OMP_CLAUSE_MAP_IMPLICIT (c) = 1;
2597 : 572 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
2598 : 572 : cclauses[C_OMP_CLAUSE_SPLIT_TARGET] = c;
2599 : : }
2600 : 2905 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0)
2601 : : {
2602 : 1748 : if (code == OMP_SIMD)
2603 : : {
2604 : 561 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2605 : : OMP_CLAUSE_REDUCTION);
2606 : 561 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2607 : 1122 : OMP_CLAUSE_REDUCTION_CODE (c)
2608 : 561 : = OMP_CLAUSE_REDUCTION_CODE (clauses);
2609 : 561 : OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
2610 : 561 : = OMP_CLAUSE_REDUCTION_PLACEHOLDER (clauses);
2611 : 561 : OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c)
2612 : 561 : = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clauses);
2613 : 1122 : OMP_CLAUSE_REDUCTION_INSCAN (c)
2614 : 561 : = OMP_CLAUSE_REDUCTION_INSCAN (clauses);
2615 : 561 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_SIMD];
2616 : 561 : cclauses[C_OMP_CLAUSE_SPLIT_SIMD] = c;
2617 : : }
2618 : 1748 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS))
2619 : 1748 : != 0)
2620 : : {
2621 : 464 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2622 : : OMP_CLAUSE_REDUCTION);
2623 : 464 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2624 : 928 : OMP_CLAUSE_REDUCTION_CODE (c)
2625 : 464 : = OMP_CLAUSE_REDUCTION_CODE (clauses);
2626 : 464 : OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
2627 : 464 : = OMP_CLAUSE_REDUCTION_PLACEHOLDER (clauses);
2628 : 464 : OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c)
2629 : 464 : = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clauses);
2630 : 928 : OMP_CLAUSE_REDUCTION_INSCAN (c)
2631 : 464 : = OMP_CLAUSE_REDUCTION_INSCAN (clauses);
2632 : 464 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
2633 : 464 : cclauses[C_OMP_CLAUSE_SPLIT_TEAMS] = c;
2634 : 464 : s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2635 : : }
2636 : 1284 : else if ((mask & (OMP_CLAUSE_MASK_1
2637 : 1284 : << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0
2638 : 1195 : && !OMP_CLAUSE_REDUCTION_INSCAN (clauses))
2639 : : s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2640 : : else
2641 : 13074 : s = C_OMP_CLAUSE_SPLIT_FOR;
2642 : : }
2643 : 1157 : else if (code == OMP_SECTIONS
2644 : 1157 : || code == OMP_PARALLEL
2645 : : || code == OMP_MASTER
2646 : : || code == OMP_MASKED)
2647 : : s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2648 : : else if (code == OMP_TASKLOOP)
2649 : : s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
2650 : : else if (code == OMP_LOOP)
2651 : : s = C_OMP_CLAUSE_SPLIT_LOOP;
2652 : : else if (code == OMP_SIMD)
2653 : : {
2654 : 437 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP))
2655 : 437 : != 0)
2656 : : {
2657 : 247 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2658 : : OMP_CLAUSE_REDUCTION);
2659 : 247 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2660 : 494 : OMP_CLAUSE_REDUCTION_CODE (c)
2661 : 247 : = OMP_CLAUSE_REDUCTION_CODE (clauses);
2662 : 247 : OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
2663 : 247 : = OMP_CLAUSE_REDUCTION_PLACEHOLDER (clauses);
2664 : 247 : OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c)
2665 : 247 : = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clauses);
2666 : 494 : OMP_CLAUSE_REDUCTION_INSCAN (c)
2667 : 247 : = OMP_CLAUSE_REDUCTION_INSCAN (clauses);
2668 : 247 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP];
2669 : 247 : cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP] = c;
2670 : : }
2671 : 190 : else if ((mask & (OMP_CLAUSE_MASK_1
2672 : 190 : << PRAGMA_OMP_CLAUSE_NUM_TEAMS)) != 0)
2673 : : {
2674 : 90 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2675 : : OMP_CLAUSE_REDUCTION);
2676 : 90 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2677 : 180 : OMP_CLAUSE_REDUCTION_CODE (c)
2678 : 90 : = OMP_CLAUSE_REDUCTION_CODE (clauses);
2679 : 90 : OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
2680 : 90 : = OMP_CLAUSE_REDUCTION_PLACEHOLDER (clauses);
2681 : 90 : OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c)
2682 : 90 : = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clauses);
2683 : 180 : OMP_CLAUSE_REDUCTION_INSCAN (c)
2684 : 90 : = OMP_CLAUSE_REDUCTION_INSCAN (clauses);
2685 : 90 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
2686 : 90 : cclauses[C_OMP_CLAUSE_SPLIT_TEAMS] = c;
2687 : : }
2688 : : s = C_OMP_CLAUSE_SPLIT_SIMD;
2689 : : }
2690 : : else
2691 : : s = C_OMP_CLAUSE_SPLIT_TEAMS;
2692 : : break;
2693 : 396 : case OMP_CLAUSE_IN_REDUCTION:
2694 : 396 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)) != 0)
2695 : : {
2696 : : /* When on target, map(always, tofrom: item) is added as
2697 : : well. For non-combined target it is added in the FEs. */
2698 : 228 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2699 : : OMP_CLAUSE_MAP);
2700 : 228 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2701 : 228 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_ALWAYS_TOFROM);
2702 : 228 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
2703 : 228 : cclauses[C_OMP_CLAUSE_SPLIT_TARGET] = c;
2704 : 228 : s = C_OMP_CLAUSE_SPLIT_TARGET;
2705 : 228 : break;
2706 : : }
2707 : : /* in_reduction on taskloop simd becomes reduction on the simd
2708 : : and keeps being in_reduction on taskloop. */
2709 : 168 : if (code == OMP_SIMD)
2710 : : {
2711 : 108 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2712 : : OMP_CLAUSE_REDUCTION);
2713 : 108 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2714 : 216 : OMP_CLAUSE_REDUCTION_CODE (c)
2715 : 108 : = OMP_CLAUSE_REDUCTION_CODE (clauses);
2716 : 108 : OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
2717 : 108 : = OMP_CLAUSE_REDUCTION_PLACEHOLDER (clauses);
2718 : 108 : OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c)
2719 : 108 : = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clauses);
2720 : 108 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_SIMD];
2721 : 108 : cclauses[C_OMP_CLAUSE_SPLIT_SIMD] = c;
2722 : : }
2723 : : s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
2724 : : break;
2725 : 1613 : case OMP_CLAUSE_IF:
2726 : 1613 : if (OMP_CLAUSE_IF_MODIFIER (clauses) != ERROR_MARK)
2727 : : {
2728 : 1188 : s = C_OMP_CLAUSE_SPLIT_COUNT;
2729 : 1188 : switch (OMP_CLAUSE_IF_MODIFIER (clauses))
2730 : : {
2731 : 510 : case OMP_PARALLEL:
2732 : 510 : if ((mask & (OMP_CLAUSE_MASK_1
2733 : 510 : << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0)
2734 : : s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2735 : : break;
2736 : 280 : case OMP_SIMD:
2737 : 280 : if (code == OMP_SIMD)
2738 : : s = C_OMP_CLAUSE_SPLIT_SIMD;
2739 : : break;
2740 : 168 : case OMP_TASKLOOP:
2741 : 168 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP))
2742 : 13082 : != 0)
2743 : : s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
2744 : : break;
2745 : 222 : case OMP_TARGET:
2746 : 222 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP))
2747 : 3144 : != 0)
2748 : : s = C_OMP_CLAUSE_SPLIT_TARGET;
2749 : : break;
2750 : : default:
2751 : : break;
2752 : : }
2753 : : if (s != C_OMP_CLAUSE_SPLIT_COUNT)
2754 : : break;
2755 : : /* Error-recovery here, invalid if-modifier specified, add the
2756 : : clause to just one construct. */
2757 : 8 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)) != 0)
2758 : : s = C_OMP_CLAUSE_SPLIT_TARGET;
2759 : 4 : else if ((mask & (OMP_CLAUSE_MASK_1
2760 : 4 : << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0)
2761 : : s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2762 : 0 : else if ((mask & (OMP_CLAUSE_MASK_1
2763 : 0 : << PRAGMA_OMP_CLAUSE_NOGROUP)) != 0)
2764 : : s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
2765 : 0 : else if (code == OMP_SIMD)
2766 : : s = C_OMP_CLAUSE_SPLIT_SIMD;
2767 : : else
2768 : 0 : gcc_unreachable ();
2769 : : break;
2770 : : }
2771 : : /* Otherwise, duplicate if clause to all constructs. */
2772 : 425 : if (code == OMP_SIMD)
2773 : : {
2774 : 266 : if ((mask & ((OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)
2775 : 266 : | (OMP_CLAUSE_MASK_1
2776 : 266 : << PRAGMA_OMP_CLAUSE_NUM_THREADS)
2777 : 266 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP)))
2778 : 5337 : != 0)
2779 : : {
2780 : 176 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2781 : : OMP_CLAUSE_IF);
2782 : 352 : OMP_CLAUSE_IF_MODIFIER (c)
2783 : 176 : = OMP_CLAUSE_IF_MODIFIER (clauses);
2784 : 176 : OMP_CLAUSE_IF_EXPR (c) = OMP_CLAUSE_IF_EXPR (clauses);
2785 : 176 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_SIMD];
2786 : 176 : cclauses[C_OMP_CLAUSE_SPLIT_SIMD] = c;
2787 : : }
2788 : : else
2789 : : {
2790 : : s = C_OMP_CLAUSE_SPLIT_SIMD;
2791 : : break;
2792 : : }
2793 : : }
2794 : 335 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP))
2795 : 335 : != 0)
2796 : : {
2797 : 144 : if ((mask & (OMP_CLAUSE_MASK_1
2798 : 144 : << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0)
2799 : : {
2800 : 64 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2801 : : OMP_CLAUSE_IF);
2802 : 128 : OMP_CLAUSE_IF_MODIFIER (c)
2803 : 64 : = OMP_CLAUSE_IF_MODIFIER (clauses);
2804 : 64 : OMP_CLAUSE_IF_EXPR (c) = OMP_CLAUSE_IF_EXPR (clauses);
2805 : 64 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP];
2806 : 64 : cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP] = c;
2807 : 64 : s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2808 : : }
2809 : : else
2810 : : s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
2811 : : }
2812 : 191 : else if ((mask & (OMP_CLAUSE_MASK_1
2813 : 191 : << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0)
2814 : : {
2815 : 119 : if ((mask & (OMP_CLAUSE_MASK_1
2816 : 7752 : << PRAGMA_OMP_CLAUSE_MAP)) != 0)
2817 : : {
2818 : 20 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2819 : : OMP_CLAUSE_IF);
2820 : 40 : OMP_CLAUSE_IF_MODIFIER (c)
2821 : 20 : = OMP_CLAUSE_IF_MODIFIER (clauses);
2822 : 20 : OMP_CLAUSE_IF_EXPR (c) = OMP_CLAUSE_IF_EXPR (clauses);
2823 : 20 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
2824 : 20 : cclauses[C_OMP_CLAUSE_SPLIT_TARGET] = c;
2825 : 20 : s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2826 : : }
2827 : : else
2828 : : s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2829 : : }
2830 : : else
2831 : : s = C_OMP_CLAUSE_SPLIT_TARGET;
2832 : : break;
2833 : 800 : case OMP_CLAUSE_LINEAR:
2834 : : /* Linear clause is allowed on simd and for. Put it on the
2835 : : innermost construct. */
2836 : 800 : if (code == OMP_SIMD)
2837 : : s = C_OMP_CLAUSE_SPLIT_SIMD;
2838 : : else
2839 : 13074 : s = C_OMP_CLAUSE_SPLIT_FOR;
2840 : : break;
2841 : 247 : case OMP_CLAUSE_NOWAIT:
2842 : : /* Nowait clause is allowed on target, for and sections, but
2843 : : is not allowed on parallel for or parallel sections. Therefore,
2844 : : put it on target construct if present, because that can only
2845 : : be combined with parallel for{, simd} and not with for{, simd},
2846 : : otherwise to the worksharing construct. */
2847 : 247 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP))
2848 : 16210 : != 0)
2849 : : s = C_OMP_CLAUSE_SPLIT_TARGET;
2850 : : else
2851 : 13074 : s = C_OMP_CLAUSE_SPLIT_FOR;
2852 : : break;
2853 : : /* thread_limit is allowed on target and teams. Distribute it
2854 : : to all. */
2855 : 443 : case OMP_CLAUSE_THREAD_LIMIT:
2856 : 443 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP))
2857 : 2454 : != 0)
2858 : : {
2859 : 231 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS))
2860 : 3136 : != 0)
2861 : : {
2862 : 229 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2863 : : OMP_CLAUSE_THREAD_LIMIT);
2864 : 229 : OMP_CLAUSE_THREAD_LIMIT_EXPR (c)
2865 : 229 : = OMP_CLAUSE_THREAD_LIMIT_EXPR (clauses);
2866 : 229 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
2867 : 229 : cclauses[C_OMP_CLAUSE_SPLIT_TARGET] = c;
2868 : : }
2869 : : else
2870 : : {
2871 : : s = C_OMP_CLAUSE_SPLIT_TARGET;
2872 : : break;
2873 : : }
2874 : : }
2875 : : s = C_OMP_CLAUSE_SPLIT_TEAMS;
2876 : : break;
2877 : : /* Allocate clause is allowed on target, teams, distribute, parallel,
2878 : : for, sections and taskloop. Distribute it to all. */
2879 : : case OMP_CLAUSE_ALLOCATE:
2880 : : s = C_OMP_CLAUSE_SPLIT_COUNT;
2881 : 8071 : for (i = 0; i < C_OMP_CLAUSE_SPLIT_COUNT; i++)
2882 : : {
2883 : 6918 : switch (i)
2884 : : {
2885 : 1153 : case C_OMP_CLAUSE_SPLIT_TARGET:
2886 : 2046 : if ((mask & (OMP_CLAUSE_MASK_1
2887 : 1153 : << PRAGMA_OMP_CLAUSE_MAP)) == 0)
2888 : 893 : continue;
2889 : : break;
2890 : 1153 : case C_OMP_CLAUSE_SPLIT_TEAMS:
2891 : 1872 : if ((mask & (OMP_CLAUSE_MASK_1
2892 : 1153 : << PRAGMA_OMP_CLAUSE_NUM_TEAMS)) == 0)
2893 : 719 : continue;
2894 : : break;
2895 : 1153 : case C_OMP_CLAUSE_SPLIT_DISTRIBUTE:
2896 : 1824 : if ((mask & (OMP_CLAUSE_MASK_1
2897 : 1153 : << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) == 0)
2898 : 671 : continue;
2899 : : break;
2900 : 1153 : case C_OMP_CLAUSE_SPLIT_PARALLEL:
2901 : 1525 : if ((mask & (OMP_CLAUSE_MASK_1
2902 : 1153 : << PRAGMA_OMP_CLAUSE_NUM_THREADS)) == 0)
2903 : 372 : continue;
2904 : : break;
2905 : 1153 : case C_OMP_CLAUSE_SPLIT_FOR:
2906 : 1153 : STATIC_ASSERT (C_OMP_CLAUSE_SPLIT_SECTIONS
2907 : : == C_OMP_CLAUSE_SPLIT_FOR
2908 : : && (C_OMP_CLAUSE_SPLIT_TASKLOOP
2909 : : == C_OMP_CLAUSE_SPLIT_FOR)
2910 : : && (C_OMP_CLAUSE_SPLIT_LOOP
2911 : : == C_OMP_CLAUSE_SPLIT_FOR));
2912 : 1153 : if (code == OMP_SECTIONS)
2913 : : break;
2914 : 1137 : if ((mask & (OMP_CLAUSE_MASK_1
2915 : 1137 : << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0)
2916 : : break;
2917 : 602 : if ((mask & (OMP_CLAUSE_MASK_1
2918 : 602 : << PRAGMA_OMP_CLAUSE_NOGROUP)) != 0)
2919 : : break;
2920 : 322 : continue;
2921 : 1153 : case C_OMP_CLAUSE_SPLIT_SIMD:
2922 : 1153 : continue;
2923 : : default:
2924 : : gcc_unreachable ();
2925 : : }
2926 : 2788 : if (s != C_OMP_CLAUSE_SPLIT_COUNT)
2927 : : {
2928 : 1635 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2929 : : OMP_CLAUSE_ALLOCATE);
2930 : 3270 : OMP_CLAUSE_DECL (c)
2931 : 1635 : = OMP_CLAUSE_DECL (clauses);
2932 : 1635 : OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)
2933 : 1635 : = OMP_CLAUSE_ALLOCATE_ALLOCATOR (clauses);
2934 : 1635 : OMP_CLAUSE_ALLOCATE_ALIGN (c)
2935 : 1635 : = OMP_CLAUSE_ALLOCATE_ALIGN (clauses);
2936 : 1635 : OMP_CLAUSE_CHAIN (c) = cclauses[s];
2937 : 1635 : cclauses[s] = c;
2938 : 1635 : has_dup_allocate = true;
2939 : : }
2940 : 2788 : s = (enum c_omp_clause_split) i;
2941 : : }
2942 : 1153 : gcc_assert (s != C_OMP_CLAUSE_SPLIT_COUNT);
2943 : : break;
2944 : 0 : default:
2945 : 0 : gcc_unreachable ();
2946 : : }
2947 : 39811 : OMP_CLAUSE_CHAIN (clauses) = cclauses[s];
2948 : 39811 : cclauses[s] = clauses;
2949 : : }
2950 : :
2951 : 15815 : if (has_dup_allocate)
2952 : : {
2953 : 783 : bool need_prune = false;
2954 : 783 : bitmap_obstack_initialize (NULL);
2955 : 8948 : for (i = 0; i < C_OMP_CLAUSE_SPLIT_SIMD - (code == OMP_LOOP); i++)
2956 : 3851 : if (cclauses[i])
2957 : : {
2958 : 2350 : bitmap_head allocate_head;
2959 : 2350 : bitmap_initialize (&allocate_head, &bitmap_default_obstack);
2960 : 17746 : for (c = cclauses[i]; c; c = OMP_CLAUSE_CHAIN (c))
2961 : 15396 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_ALLOCATE
2962 : 15396 : && DECL_P (OMP_CLAUSE_DECL (c)))
2963 : 4956 : bitmap_set_bit (&allocate_head,
2964 : 2478 : DECL_UID (OMP_CLAUSE_DECL (c)));
2965 : 17746 : for (c = cclauses[i]; c; c = OMP_CLAUSE_CHAIN (c))
2966 : 15396 : switch (OMP_CLAUSE_CODE (c))
2967 : : {
2968 : 1159 : case OMP_CLAUSE_REDUCTION:
2969 : 1159 : case OMP_CLAUSE_IN_REDUCTION:
2970 : 1159 : case OMP_CLAUSE_TASK_REDUCTION:
2971 : 1159 : if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
2972 : : {
2973 : 0 : tree t = TREE_OPERAND (OMP_CLAUSE_DECL (c), 0);
2974 : 0 : if (TREE_CODE (t) == POINTER_PLUS_EXPR)
2975 : 0 : t = TREE_OPERAND (t, 0);
2976 : 0 : if (TREE_CODE (t) == ADDR_EXPR
2977 : 0 : || INDIRECT_REF_P (t))
2978 : 0 : t = TREE_OPERAND (t, 0);
2979 : 0 : if (DECL_P (t))
2980 : 0 : bitmap_clear_bit (&allocate_head, DECL_UID (t));
2981 : : break;
2982 : : }
2983 : 1159 : else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == TREE_LIST)
2984 : : {
2985 : : /* TODO: This can go away once we transition all uses of
2986 : : TREE_LIST for representing OMP array sections to
2987 : : OMP_ARRAY_SECTION. */
2988 : 0 : tree t;
2989 : 0 : for (t = OMP_CLAUSE_DECL (c);
2990 : 0 : TREE_CODE (t) == TREE_LIST; t = TREE_CHAIN (t))
2991 : : ;
2992 : 0 : if (DECL_P (t))
2993 : 0 : bitmap_clear_bit (&allocate_head, DECL_UID (t));
2994 : : break;
2995 : : }
2996 : 1159 : else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == OMP_ARRAY_SECTION)
2997 : : {
2998 : 152 : tree t;
2999 : 152 : for (t = OMP_CLAUSE_DECL (c);
3000 : 304 : TREE_CODE (t) == OMP_ARRAY_SECTION;
3001 : 152 : t = TREE_OPERAND (t, 0))
3002 : : ;
3003 : 152 : if (DECL_P (t))
3004 : 152 : bitmap_clear_bit (&allocate_head, DECL_UID (t));
3005 : : break;
3006 : : }
3007 : : /* FALLTHRU */
3008 : 3261 : case OMP_CLAUSE_PRIVATE:
3009 : 3261 : case OMP_CLAUSE_FIRSTPRIVATE:
3010 : 3261 : case OMP_CLAUSE_LASTPRIVATE:
3011 : 3261 : case OMP_CLAUSE_LINEAR:
3012 : 3261 : if (DECL_P (OMP_CLAUSE_DECL (c)))
3013 : 6522 : bitmap_clear_bit (&allocate_head,
3014 : 3261 : DECL_UID (OMP_CLAUSE_DECL (c)));
3015 : : break;
3016 : : default:
3017 : : break;
3018 : : }
3019 : 17746 : for (c = cclauses[i]; c; c = OMP_CLAUSE_CHAIN (c))
3020 : 15396 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_ALLOCATE
3021 : 2478 : && DECL_P (OMP_CLAUSE_DECL (c))
3022 : 17874 : && bitmap_bit_p (&allocate_head,
3023 : 2478 : DECL_UID (OMP_CLAUSE_DECL (c))))
3024 : : {
3025 : : /* Mark allocate clauses which don't have corresponding
3026 : : explicit data sharing clause. */
3027 : 1089 : OMP_CLAUSE_ALLOCATE_COMBINED (c) = 1;
3028 : 1089 : need_prune = true;
3029 : : }
3030 : : }
3031 : 783 : bitmap_obstack_release (NULL);
3032 : 783 : if (need_prune)
3033 : : {
3034 : : /* At least one allocate clause has been marked. Walk all the
3035 : : duplicated allocate clauses in sync. If it is marked in all
3036 : : constituent constructs, diagnose it as invalid and remove
3037 : : them. Otherwise, remove all marked inner clauses inside
3038 : : a construct that doesn't have them marked. Keep the outer
3039 : : marked ones, because some clause duplication is done only
3040 : : during gimplification. */
3041 : : tree *p[C_OMP_CLAUSE_SPLIT_COUNT];
3042 : 4809 : for (i = 0; i < C_OMP_CLAUSE_SPLIT_COUNT; i++)
3043 : 4122 : if (cclauses[i] == NULL_TREE
3044 : 2418 : || i == C_OMP_CLAUSE_SPLIT_SIMD
3045 : 2158 : || (i == C_OMP_CLAUSE_SPLIT_LOOP && code == OMP_LOOP))
3046 : 1964 : p[i] = NULL;
3047 : : else
3048 : 2158 : p[i] = &cclauses[i];
3049 : 1370 : do
3050 : : {
3051 : 1370 : int j = -1;
3052 : 1370 : tree seen = NULL_TREE;
3053 : 6443 : for (i = C_OMP_CLAUSE_SPLIT_COUNT - 1; i >= 0; i--)
3054 : 5760 : if (p[i])
3055 : : {
3056 : 13697 : while (*p[i]
3057 : 13697 : && OMP_CLAUSE_CODE (*p[i]) != OMP_CLAUSE_ALLOCATE)
3058 : 10724 : p[i] = &OMP_CLAUSE_CHAIN (*p[i]);
3059 : 2973 : if (*p[i] == NULL_TREE)
3060 : : {
3061 : : i = C_OMP_CLAUSE_SPLIT_COUNT;
3062 : : break;
3063 : : }
3064 : 2286 : if (!OMP_CLAUSE_ALLOCATE_COMBINED (*p[i]) && j == -1)
3065 : 5073 : j = i;
3066 : : seen = *p[i];
3067 : : }
3068 : 1370 : if (i == C_OMP_CLAUSE_SPLIT_COUNT)
3069 : : break;
3070 : 683 : if (j == -1)
3071 : 8 : error_at (OMP_CLAUSE_LOCATION (seen),
3072 : : "%qD specified in %<allocate%> clause but not in "
3073 : : "an explicit privatization clause",
3074 : 4 : OMP_CLAUSE_DECL (seen));
3075 : 4781 : for (i = 0; i < C_OMP_CLAUSE_SPLIT_COUNT; i++)
3076 : 4098 : if (p[i])
3077 : : {
3078 : 2158 : if (i > j)
3079 : : /* Remove. */
3080 : 610 : *p[i] = OMP_CLAUSE_CHAIN (*p[i]);
3081 : : else
3082 : : /* Keep. */
3083 : 1548 : p[i] = &OMP_CLAUSE_CHAIN (*p[i]);
3084 : : }
3085 : : }
3086 : : while (1);
3087 : : }
3088 : : }
3089 : :
3090 : 15815 : if (!flag_checking)
3091 : : return;
3092 : :
3093 : 15815 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)) == 0)
3094 : 10651 : gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_TARGET] == NULL_TREE);
3095 : 15815 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS)) == 0)
3096 : 8962 : gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_TEAMS] == NULL_TREE);
3097 : 15815 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) == 0
3098 : 8513 : && (mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FILTER)) == 0)
3099 : 8267 : gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE] == NULL_TREE);
3100 : 15815 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS)) == 0)
3101 : 4873 : gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL] == NULL_TREE);
3102 : 15815 : if ((mask & ((OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)
3103 : 15815 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP))) == 0
3104 : 4092 : && code != OMP_SECTIONS
3105 : 4092 : && code != OMP_LOOP)
3106 : 3632 : gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_FOR] == NULL_TREE);
3107 : 15815 : if (code != OMP_SIMD)
3108 : 9310 : gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_SIMD] == NULL_TREE);
3109 : : }
3110 : :
3111 : :
3112 : : /* qsort callback to compare #pragma omp declare simd clauses. */
3113 : :
3114 : : static int
3115 : 12176 : c_omp_declare_simd_clause_cmp (const void *p, const void *q)
3116 : : {
3117 : 12176 : tree a = *(const tree *) p;
3118 : 12176 : tree b = *(const tree *) q;
3119 : 12176 : if (OMP_CLAUSE_CODE (a) != OMP_CLAUSE_CODE (b))
3120 : : {
3121 : 10701 : if (OMP_CLAUSE_CODE (a) > OMP_CLAUSE_CODE (b))
3122 : : return -1;
3123 : 4474 : return 1;
3124 : : }
3125 : 1475 : if (OMP_CLAUSE_CODE (a) != OMP_CLAUSE_SIMDLEN
3126 : : && OMP_CLAUSE_CODE (a) != OMP_CLAUSE_INBRANCH
3127 : : && OMP_CLAUSE_CODE (a) != OMP_CLAUSE_NOTINBRANCH)
3128 : : {
3129 : 1451 : int c = tree_to_shwi (OMP_CLAUSE_DECL (a));
3130 : 1451 : int d = tree_to_shwi (OMP_CLAUSE_DECL (b));
3131 : 1451 : if (c < d)
3132 : : return 1;
3133 : 670 : if (c > d)
3134 : 670 : return -1;
3135 : : }
3136 : : return 0;
3137 : : }
3138 : :
3139 : : /* Change PARM_DECLs in OMP_CLAUSE_DECL of #pragma omp declare simd
3140 : : CLAUSES on FNDECL into argument indexes and sort them. */
3141 : :
3142 : : tree
3143 : 1396 : c_omp_declare_simd_clauses_to_numbers (tree parms, tree clauses)
3144 : : {
3145 : 1396 : tree c;
3146 : 1396 : vec<tree> clvec = vNULL;
3147 : :
3148 : 4443 : for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
3149 : : {
3150 : 3047 : if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_SIMDLEN
3151 : : && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_INBRANCH
3152 : : && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_NOTINBRANCH)
3153 : : {
3154 : 1692 : tree decl = OMP_CLAUSE_DECL (c);
3155 : 1692 : tree arg;
3156 : 1692 : int idx;
3157 : 3785 : for (arg = parms, idx = 0; arg;
3158 : 2093 : arg = TREE_CHAIN (arg), idx++)
3159 : 3785 : if (arg == decl)
3160 : : break;
3161 : 1692 : if (arg == NULL_TREE)
3162 : : {
3163 : 0 : error_at (OMP_CLAUSE_LOCATION (c),
3164 : : "%qD is not a function argument", decl);
3165 : 3047 : continue;
3166 : : }
3167 : 1692 : OMP_CLAUSE_DECL (c) = build_int_cst (integer_type_node, idx);
3168 : 1692 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3169 : 1692 : && OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (c))
3170 : : {
3171 : 43 : decl = OMP_CLAUSE_LINEAR_STEP (c);
3172 : 121 : for (arg = parms, idx = 0; arg;
3173 : 78 : arg = TREE_CHAIN (arg), idx++)
3174 : 121 : if (arg == decl)
3175 : : break;
3176 : 43 : if (arg == NULL_TREE)
3177 : : {
3178 : 0 : error_at (OMP_CLAUSE_LOCATION (c),
3179 : : "%qD is not a function argument", decl);
3180 : 0 : continue;
3181 : : }
3182 : 43 : OMP_CLAUSE_LINEAR_STEP (c)
3183 : 86 : = build_int_cst (integer_type_node, idx);
3184 : : }
3185 : : }
3186 : 3047 : clvec.safe_push (c);
3187 : : }
3188 : 1396 : if (!clvec.is_empty ())
3189 : : {
3190 : 1287 : unsigned int len = clvec.length (), i;
3191 : 1287 : clvec.qsort (c_omp_declare_simd_clause_cmp);
3192 : 1287 : clauses = clvec[0];
3193 : 4334 : for (i = 0; i < len; i++)
3194 : 3047 : OMP_CLAUSE_CHAIN (clvec[i]) = (i < len - 1) ? clvec[i + 1] : NULL_TREE;
3195 : : }
3196 : : else
3197 : : clauses = NULL_TREE;
3198 : 1396 : clvec.release ();
3199 : 1396 : return clauses;
3200 : : }
3201 : :
3202 : : /* Change argument indexes in CLAUSES of FNDECL back to PARM_DECLs. */
3203 : :
3204 : : void
3205 : 105 : c_omp_declare_simd_clauses_to_decls (tree fndecl, tree clauses)
3206 : : {
3207 : 105 : tree c;
3208 : :
3209 : 393 : for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
3210 : 288 : if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_SIMDLEN
3211 : : && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_INBRANCH
3212 : : && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_NOTINBRANCH)
3213 : : {
3214 : 189 : int idx = tree_to_shwi (OMP_CLAUSE_DECL (c)), i;
3215 : 189 : tree arg;
3216 : 369 : for (arg = DECL_ARGUMENTS (fndecl), i = 0; arg;
3217 : 180 : arg = TREE_CHAIN (arg), i++)
3218 : 369 : if (i == idx)
3219 : : break;
3220 : 0 : gcc_assert (arg);
3221 : 189 : OMP_CLAUSE_DECL (c) = arg;
3222 : 189 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3223 : 189 : && OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (c))
3224 : : {
3225 : 0 : idx = tree_to_shwi (OMP_CLAUSE_LINEAR_STEP (c));
3226 : 0 : for (arg = DECL_ARGUMENTS (fndecl), i = 0; arg;
3227 : 0 : arg = TREE_CHAIN (arg), i++)
3228 : 0 : if (i == idx)
3229 : : break;
3230 : 0 : gcc_assert (arg);
3231 : 0 : OMP_CLAUSE_LINEAR_STEP (c) = arg;
3232 : : }
3233 : : }
3234 : 105 : }
3235 : :
3236 : : /* Return true for __func__ and similar function-local predefined
3237 : : variables (which are in OpenMP predetermined shared, allowed in
3238 : : shared/firstprivate clauses). */
3239 : :
3240 : : bool
3241 : 65368 : c_omp_predefined_variable (tree decl)
3242 : : {
3243 : 65368 : if (VAR_P (decl)
3244 : 34183 : && DECL_ARTIFICIAL (decl)
3245 : 306 : && TREE_STATIC (decl)
3246 : 65659 : && DECL_NAME (decl))
3247 : : {
3248 : 291 : if (TREE_READONLY (decl)
3249 : 291 : && (DECL_NAME (decl) == ridpointers[RID_C99_FUNCTION_NAME]
3250 : 223 : || DECL_NAME (decl) == ridpointers[RID_FUNCTION_NAME]
3251 : 179 : || DECL_NAME (decl) == ridpointers[RID_PRETTY_FUNCTION_NAME]))
3252 : : return true;
3253 : : /* For UBSan handle the same also ubsan_create_data created
3254 : : variables. There is no magic flag for those, but user variables
3255 : : shouldn't be DECL_ARTIFICIAL or have TYPE_ARTIFICIAL type with
3256 : : such names. */
3257 : 139 : if ((flag_sanitize & (SANITIZE_UNDEFINED
3258 : : | SANITIZE_UNDEFINED_NONDEFAULT)) != 0
3259 : 36 : && DECL_IGNORED_P (decl)
3260 : 36 : && !TREE_READONLY (decl)
3261 : 30 : && TREE_CODE (DECL_NAME (decl)) == IDENTIFIER_NODE
3262 : 30 : && TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE
3263 : 30 : && TYPE_ARTIFICIAL (TREE_TYPE (decl))
3264 : 30 : && TYPE_NAME (TREE_TYPE (decl))
3265 : 30 : && TREE_CODE (TYPE_NAME (TREE_TYPE (decl))) == TYPE_DECL
3266 : 30 : && DECL_NAME (TYPE_NAME (TREE_TYPE (decl)))
3267 : 169 : && (TREE_CODE (DECL_NAME (TYPE_NAME (TREE_TYPE (decl))))
3268 : : == IDENTIFIER_NODE))
3269 : : {
3270 : 30 : tree id1 = DECL_NAME (decl);
3271 : 30 : tree id2 = DECL_NAME (TYPE_NAME (TREE_TYPE (decl)));
3272 : 30 : if (IDENTIFIER_LENGTH (id1) >= sizeof ("ubsan_data") - 1
3273 : 30 : && IDENTIFIER_LENGTH (id2) >= sizeof ("__ubsan__data")
3274 : 30 : && !memcmp (IDENTIFIER_POINTER (id2), "__ubsan_",
3275 : : sizeof ("__ubsan_") - 1)
3276 : 30 : && !memcmp (IDENTIFIER_POINTER (id2) + IDENTIFIER_LENGTH (id2)
3277 : 30 : - sizeof ("_data") + 1, "_data",
3278 : : sizeof ("_data") - 1)
3279 : 60 : && strstr (IDENTIFIER_POINTER (id1), "ubsan_data"))
3280 : 30 : return true;
3281 : : }
3282 : : }
3283 : : return false;
3284 : : }
3285 : :
3286 : : /* OMP_CLAUSE_DEFAULT_UNSPECIFIED unless OpenMP sharing attribute of DECL
3287 : : is predetermined. */
3288 : :
3289 : : enum omp_clause_default_kind
3290 : 27939 : c_omp_predetermined_sharing (tree decl)
3291 : : {
3292 : : /* Predetermine artificial variables holding integral values, those
3293 : : are usually result of gimplify_one_sizepos or SAVE_EXPR
3294 : : gimplification. */
3295 : 27939 : if (VAR_P (decl)
3296 : 17173 : && DECL_ARTIFICIAL (decl)
3297 : 28578 : && INTEGRAL_TYPE_P (TREE_TYPE (decl)))
3298 : : return OMP_CLAUSE_DEFAULT_SHARED;
3299 : :
3300 : 27391 : if (c_omp_predefined_variable (decl))
3301 : : return OMP_CLAUSE_DEFAULT_SHARED;
3302 : :
3303 : : return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
3304 : : }
3305 : :
3306 : : /* OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED unless OpenMP mapping attribute
3307 : : of DECL is predetermined. */
3308 : :
3309 : : enum omp_clause_defaultmap_kind
3310 : 5137 : c_omp_predetermined_mapping (tree decl)
3311 : : {
3312 : : /* Predetermine artificial variables holding integral values, those
3313 : : are usually result of gimplify_one_sizepos or SAVE_EXPR
3314 : : gimplification. */
3315 : 5137 : if (VAR_P (decl)
3316 : 947 : && DECL_ARTIFICIAL (decl)
3317 : 5169 : && INTEGRAL_TYPE_P (TREE_TYPE (decl)))
3318 : : return OMP_CLAUSE_DEFAULTMAP_FIRSTPRIVATE;
3319 : :
3320 : 5109 : if (c_omp_predefined_variable (decl))
3321 : 2 : return OMP_CLAUSE_DEFAULTMAP_TO;
3322 : :
3323 : : return OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED;
3324 : : }
3325 : :
3326 : :
3327 : : /* Used to merge map clause information in c_omp_adjust_map_clauses. */
3328 : : struct map_clause
3329 : : {
3330 : : tree clause;
3331 : : bool firstprivate_ptr_p;
3332 : : bool decl_mapped;
3333 : : bool omp_declare_target;
3334 : 3256 : map_clause (void) : clause (NULL_TREE), firstprivate_ptr_p (false),
3335 : 3256 : decl_mapped (false), omp_declare_target (false) { }
3336 : : };
3337 : :
3338 : : /* Adjust map clauses after normal clause parsing, mainly to mark specific
3339 : : base-pointer map cases addressable that may be turned into attach/detach
3340 : : operations during gimplification. */
3341 : : void
3342 : 12073 : c_omp_adjust_map_clauses (tree clauses, bool is_target)
3343 : : {
3344 : 12073 : if (!is_target)
3345 : : {
3346 : : /* If this is not a target construct, just turn firstprivate pointers
3347 : : into attach/detach, the runtime will check and do the rest. */
3348 : :
3349 : 4100 : for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
3350 : 2768 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
3351 : 2307 : && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
3352 : 0 : && DECL_P (OMP_CLAUSE_DECL (c))
3353 : 2768 : && POINTER_TYPE_P (TREE_TYPE (OMP_CLAUSE_DECL (c))))
3354 : : {
3355 : 0 : tree ptr = OMP_CLAUSE_DECL (c);
3356 : 0 : c_common_mark_addressable_vec (ptr);
3357 : : }
3358 : 1332 : return;
3359 : : }
3360 : :
3361 : 10741 : hash_map<tree, map_clause> maps;
3362 : :
3363 : 23241 : for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
3364 : 12500 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
3365 : 12500 : && DECL_P (OMP_CLAUSE_DECL (c)))
3366 : : {
3367 : : /* If this is for a target construct, the firstprivate pointer
3368 : : is marked addressable if either is true:
3369 : : (1) the base-pointer is mapped in this same construct, or
3370 : : (2) the base-pointer is a variable place on the device by
3371 : : "declare target" directives.
3372 : :
3373 : : Here we iterate through all map clauses collecting these cases,
3374 : : and merge them with a hash_map to process below. */
3375 : :
3376 : 3812 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
3377 : 3812 : && POINTER_TYPE_P (TREE_TYPE (OMP_CLAUSE_DECL (c))))
3378 : : {
3379 : 300 : tree ptr = OMP_CLAUSE_DECL (c);
3380 : 300 : map_clause &mc = maps.get_or_insert (ptr);
3381 : 300 : if (mc.clause == NULL_TREE)
3382 : 300 : mc.clause = c;
3383 : 300 : mc.firstprivate_ptr_p = true;
3384 : :
3385 : 300 : if (is_global_var (ptr)
3386 : 348 : && lookup_attribute ("omp declare target",
3387 : 48 : DECL_ATTRIBUTES (ptr)))
3388 : 0 : mc.omp_declare_target = true;
3389 : : }
3390 : 3512 : else if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALLOC
3391 : 3433 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_TO
3392 : 2999 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FROM
3393 : 2129 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_TOFROM
3394 : 957 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_TO
3395 : 895 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_FROM
3396 : 4406 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_TOFROM)
3397 : : {
3398 : 2979 : map_clause &mc = maps.get_or_insert (OMP_CLAUSE_DECL (c));
3399 : 2979 : mc.decl_mapped = true;
3400 : : }
3401 : : }
3402 : :
3403 : 13997 : for (hash_map<tree, map_clause>::iterator i = maps.begin ();
3404 : 27994 : i != maps.end (); ++i)
3405 : : {
3406 : 3256 : map_clause &mc = (*i).second;
3407 : :
3408 : 3256 : if (mc.firstprivate_ptr_p
3409 : 300 : && (mc.decl_mapped || mc.omp_declare_target))
3410 : 23 : c_common_mark_addressable_vec (OMP_CLAUSE_DECL (mc.clause));
3411 : : }
3412 : 10741 : }
3413 : :
3414 : : /* Maybe strip off an indirection from a "converted" reference, then find the
3415 : : origin of a pointer (i.e. without any offset). */
3416 : :
3417 : : tree
3418 : 69848 : c_omp_address_inspector::unconverted_ref_origin ()
3419 : : {
3420 : 69848 : tree t = orig;
3421 : :
3422 : : /* We may have a reference-typed component access at the outermost level
3423 : : that has had convert_from_reference called on it. Get the un-dereferenced
3424 : : reference itself. */
3425 : 69848 : t = maybe_unconvert_ref (t);
3426 : :
3427 : : /* Find base pointer for POINTER_PLUS_EXPR, etc. */
3428 : 69848 : t = get_origin (t);
3429 : :
3430 : 69848 : return t;
3431 : : }
3432 : :
3433 : : /* Return TRUE if the address is a component access. */
3434 : :
3435 : : bool
3436 : 12422 : c_omp_address_inspector::component_access_p ()
3437 : : {
3438 : 12422 : tree t = maybe_unconvert_ref (orig);
3439 : :
3440 : 12422 : t = get_origin (t);
3441 : :
3442 : 12422 : return TREE_CODE (t) == COMPONENT_REF;
3443 : : }
3444 : :
3445 : : /* Perform various checks on the address, as described by clause CLAUSE (we
3446 : : only use its code and location here). */
3447 : :
3448 : : bool
3449 : 32653 : c_omp_address_inspector::check_clause (tree clause)
3450 : : {
3451 : 32653 : tree t = unconverted_ref_origin ();
3452 : :
3453 : 32653 : if (TREE_CODE (t) != COMPONENT_REF)
3454 : : return true;
3455 : :
3456 : 4541 : if (TREE_CODE (TREE_OPERAND (t, 1)) == FIELD_DECL
3457 : 4541 : && DECL_BIT_FIELD (TREE_OPERAND (t, 1)))
3458 : : {
3459 : 24 : error_at (OMP_CLAUSE_LOCATION (clause),
3460 : : "bit-field %qE in %qs clause",
3461 : 24 : t, omp_clause_code_name[OMP_CLAUSE_CODE (clause)]);
3462 : 24 : return false;
3463 : : }
3464 : 4517 : else if (!processing_template_decl_p ()
3465 : 4517 : && !omp_mappable_type (TREE_TYPE (t)))
3466 : : {
3467 : 0 : error_at (OMP_CLAUSE_LOCATION (clause),
3468 : : "%qE does not have a mappable type in %qs clause",
3469 : 0 : t, omp_clause_code_name[OMP_CLAUSE_CODE (clause)]);
3470 : 0 : emit_unmappable_type_notes (TREE_TYPE (t));
3471 : 0 : return false;
3472 : : }
3473 : 4517 : else if (TREE_TYPE (t) && TYPE_ATOMIC (TREE_TYPE (t)))
3474 : : {
3475 : 2 : error_at (OMP_CLAUSE_LOCATION (clause),
3476 : : "%<_Atomic%> %qE in %qs clause", t,
3477 : 2 : omp_clause_code_name[OMP_CLAUSE_CODE (clause)]);
3478 : 2 : return false;
3479 : : }
3480 : :
3481 : : return true;
3482 : : }
3483 : :
3484 : : /* Find the "root term" for the address. This is the innermost decl, etc.
3485 : : of the access. */
3486 : :
3487 : : tree
3488 : 1690 : c_omp_address_inspector::get_root_term (bool checking)
3489 : : {
3490 : 1690 : if (root_term && !checking)
3491 : : return root_term;
3492 : :
3493 : 1690 : tree t = unconverted_ref_origin ();
3494 : :
3495 : 5734 : while (TREE_CODE (t) == COMPONENT_REF)
3496 : : {
3497 : 2354 : if (checking
3498 : 2354 : && TREE_TYPE (TREE_OPERAND (t, 0))
3499 : 4520 : && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == UNION_TYPE)
3500 : : {
3501 : 0 : error_at (loc, "%qE is a member of a union", t);
3502 : 0 : return error_mark_node;
3503 : : }
3504 : 2354 : t = TREE_OPERAND (t, 0);
3505 : 2354 : while (TREE_CODE (t) == MEM_REF
3506 : 3773 : || TREE_CODE (t) == INDIRECT_REF
3507 : 3773 : || TREE_CODE (t) == ARRAY_REF)
3508 : : {
3509 : 1419 : if (TREE_CODE (t) == MEM_REF
3510 : : || TREE_CODE (t) == INDIRECT_REF)
3511 : 1275 : indirections = true;
3512 : 1419 : t = TREE_OPERAND (t, 0);
3513 : 1419 : STRIP_NOPS (t);
3514 : 1419 : if (TREE_CODE (t) == POINTER_PLUS_EXPR)
3515 : 102 : t = TREE_OPERAND (t, 0);
3516 : : }
3517 : : }
3518 : :
3519 : 1690 : root_term = t;
3520 : :
3521 : 1690 : return t;
3522 : : }
3523 : :
3524 : : /* Return TRUE if the address is supported in mapping clauses. At present,
3525 : : this means that the innermost expression is a DECL_P, but could be extended
3526 : : to other types of expression in the future. */
3527 : :
3528 : : bool
3529 : 24773 : c_omp_address_inspector::map_supported_p ()
3530 : : {
3531 : : /* If we've already decided if the mapped address is supported, return
3532 : : that. */
3533 : 24773 : if (map_supported != -1)
3534 : 0 : return map_supported;
3535 : :
3536 : 24773 : tree t = unconverted_ref_origin ();
3537 : :
3538 : 24773 : STRIP_NOPS (t);
3539 : :
3540 : 24773 : while (TREE_CODE (t) == INDIRECT_REF
3541 : 40341 : || TREE_CODE (t) == MEM_REF
3542 : : || TREE_CODE (t) == ARRAY_REF
3543 : : || TREE_CODE (t) == COMPONENT_REF
3544 : : || TREE_CODE (t) == COMPOUND_EXPR
3545 : : || TREE_CODE (t) == SAVE_EXPR
3546 : : || TREE_CODE (t) == POINTER_PLUS_EXPR
3547 : : || TREE_CODE (t) == NON_LVALUE_EXPR
3548 : : || TREE_CODE (t) == OMP_ARRAY_SECTION
3549 : 40341 : || TREE_CODE (t) == NOP_EXPR)
3550 : 15568 : if (TREE_CODE (t) == COMPOUND_EXPR)
3551 : 27 : t = TREE_OPERAND (t, 1);
3552 : : else
3553 : 15541 : t = TREE_OPERAND (t, 0);
3554 : :
3555 : 24773 : STRIP_NOPS (t);
3556 : :
3557 : 24773 : map_supported = DECL_P (t);
3558 : :
3559 : 24773 : return map_supported;
3560 : : }
3561 : :
3562 : : /* Get the origin of an address T, stripping off offsets and some other
3563 : : bits. */
3564 : :
3565 : : tree
3566 : 82270 : c_omp_address_inspector::get_origin (tree t)
3567 : : {
3568 : 82538 : while (1)
3569 : : {
3570 : 82538 : if (TREE_CODE (t) == COMPOUND_EXPR)
3571 : : {
3572 : 10 : t = TREE_OPERAND (t, 1);
3573 : 10 : STRIP_NOPS (t);
3574 : : }
3575 : 82528 : else if (TREE_CODE (t) == POINTER_PLUS_EXPR
3576 : 82528 : || TREE_CODE (t) == SAVE_EXPR)
3577 : 231 : t = TREE_OPERAND (t, 0);
3578 : 82297 : else if (!processing_template_decl_p ()
3579 : 75348 : && TREE_CODE (t) == INDIRECT_REF
3580 : 84781 : && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == REFERENCE_TYPE)
3581 : 27 : t = TREE_OPERAND (t, 0);
3582 : : else
3583 : : break;
3584 : : }
3585 : 82270 : STRIP_NOPS (t);
3586 : 82270 : return t;
3587 : : }
3588 : :
3589 : : /* For an address T that might be a reference that has had
3590 : : "convert_from_reference" called on it, return the actual reference without
3591 : : any indirection. */
3592 : :
3593 : : tree
3594 : 91758 : c_omp_address_inspector::maybe_unconvert_ref (tree t)
3595 : : {
3596 : : /* Be careful not to dereference the type if we're processing a
3597 : : template decl, else it might be NULL. */
3598 : 91758 : if (!processing_template_decl_p ()
3599 : 82747 : && TREE_CODE (t) == INDIRECT_REF
3600 : 94805 : && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == REFERENCE_TYPE)
3601 : 587 : return TREE_OPERAND (t, 0);
3602 : :
3603 : : return t;
3604 : : }
3605 : :
3606 : : /* Return TRUE if CLAUSE might describe a zero-length array section. */
3607 : :
3608 : : bool
3609 : 5369 : c_omp_address_inspector::maybe_zero_length_array_section (tree clause)
3610 : : {
3611 : 5369 : switch (OMP_CLAUSE_MAP_KIND (clause))
3612 : : {
3613 : : case GOMP_MAP_ALLOC:
3614 : : case GOMP_MAP_IF_PRESENT:
3615 : : case GOMP_MAP_TO:
3616 : : case GOMP_MAP_FROM:
3617 : : case GOMP_MAP_TOFROM:
3618 : : case GOMP_MAP_ALWAYS_TO:
3619 : : case GOMP_MAP_ALWAYS_FROM:
3620 : : case GOMP_MAP_ALWAYS_TOFROM:
3621 : : case GOMP_MAP_PRESENT_ALLOC:
3622 : : case GOMP_MAP_PRESENT_TO:
3623 : : case GOMP_MAP_PRESENT_FROM:
3624 : : case GOMP_MAP_PRESENT_TOFROM:
3625 : : case GOMP_MAP_ALWAYS_PRESENT_TO:
3626 : : case GOMP_MAP_ALWAYS_PRESENT_FROM:
3627 : : case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
3628 : : case GOMP_MAP_RELEASE:
3629 : : case GOMP_MAP_DELETE:
3630 : : case GOMP_MAP_FORCE_TO:
3631 : : case GOMP_MAP_FORCE_FROM:
3632 : : case GOMP_MAP_FORCE_TOFROM:
3633 : : case GOMP_MAP_FORCE_PRESENT:
3634 : : return true;
3635 : 28 : default:
3636 : 28 : return false;
3637 : : }
3638 : : }
3639 : :
3640 : : /* Expand a chained access. We only expect to see a quite limited range of
3641 : : expression types here, because e.g. you can't have an array of
3642 : : references. */
3643 : :
3644 : : static tree
3645 : 49 : omp_expand_access_chain (tree c, tree expr, vec<omp_addr_token *> &addr_tokens,
3646 : : unsigned *idx, c_omp_region_type ort)
3647 : : {
3648 : 49 : using namespace omp_addr_tokenizer;
3649 : 49 : location_t loc = OMP_CLAUSE_LOCATION (c);
3650 : 49 : unsigned i = *idx;
3651 : 49 : tree c2 = NULL_TREE;
3652 : 49 : gomp_map_kind kind;
3653 : :
3654 : 49 : if ((ort & C_ORT_EXIT_DATA) != 0
3655 : 37 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FROM
3656 : 86 : || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
3657 : 37 : && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FROM
3658 : 37 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DELETE
3659 : 37 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_RELEASE
3660 : 37 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_FROM
3661 : 37 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FORCE_FROM
3662 : 37 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_PRESENT_FROM
3663 : 37 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_PRESENT_FROM)))
3664 : : kind = GOMP_MAP_DETACH;
3665 : : else
3666 : : kind = GOMP_MAP_ATTACH;
3667 : :
3668 : 49 : switch (addr_tokens[i]->u.access_kind)
3669 : : {
3670 : 49 : case ACCESS_POINTER:
3671 : 49 : case ACCESS_POINTER_OFFSET:
3672 : 49 : {
3673 : 49 : tree virtual_origin
3674 : 49 : = fold_convert_loc (loc, ptrdiff_type_node, addr_tokens[i]->expr);
3675 : 49 : tree data_addr = omp_accessed_addr (addr_tokens, i, expr);
3676 : 49 : c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
3677 : 49 : OMP_CLAUSE_SET_MAP_KIND (c2, kind);
3678 : 49 : OMP_CLAUSE_DECL (c2) = addr_tokens[i]->expr;
3679 : 49 : OMP_CLAUSE_SIZE (c2)
3680 : 49 : = fold_build2_loc (loc, MINUS_EXPR, ptrdiff_type_node,
3681 : : fold_convert_loc (loc, ptrdiff_type_node,
3682 : : data_addr),
3683 : : virtual_origin);
3684 : : }
3685 : 49 : break;
3686 : :
3687 : : case ACCESS_INDEXED_ARRAY:
3688 : : break;
3689 : :
3690 : 0 : default:
3691 : 0 : return error_mark_node;
3692 : : }
3693 : :
3694 : 49 : if (c2)
3695 : : {
3696 : 49 : OMP_CLAUSE_CHAIN (c2) = OMP_CLAUSE_CHAIN (c);
3697 : 49 : OMP_CLAUSE_CHAIN (c) = c2;
3698 : 49 : c = c2;
3699 : : }
3700 : :
3701 : 49 : *idx = ++i;
3702 : :
3703 : 49 : if (i < addr_tokens.length ()
3704 : 49 : && addr_tokens[i]->type == ACCESS_METHOD)
3705 : : return omp_expand_access_chain (c, expr, addr_tokens, idx, ort);
3706 : :
3707 : : return c;
3708 : : }
3709 : :
3710 : : /* Translate "array_base_decl access_method" to OMP mapping clauses. */
3711 : :
3712 : : tree
3713 : 17798 : c_omp_address_inspector::expand_array_base (tree c,
3714 : : vec<omp_addr_token *> &addr_tokens,
3715 : : tree expr, unsigned *idx,
3716 : : c_omp_region_type ort)
3717 : : {
3718 : 17798 : using namespace omp_addr_tokenizer;
3719 : 17798 : location_t loc = OMP_CLAUSE_LOCATION (c);
3720 : 17798 : int i = *idx;
3721 : 17798 : tree decl = addr_tokens[i + 1]->expr;
3722 : 17798 : bool decl_p = DECL_P (decl);
3723 : 17798 : bool declare_target_p = (decl_p
3724 : 17789 : && is_global_var (decl)
3725 : 25273 : && lookup_attribute ("omp declare target",
3726 : 7475 : DECL_ATTRIBUTES (decl)));
3727 : 17798 : bool map_p = OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP;
3728 : 17798 : bool implicit_p = map_p && OMP_CLAUSE_MAP_IMPLICIT (c);
3729 : 17798 : bool chain_p = omp_access_chain_p (addr_tokens, i + 1);
3730 : 17798 : tree c2 = NULL_TREE, c3 = NULL_TREE;
3731 : 17798 : unsigned consume_tokens = 2;
3732 : 17798 : bool target_p = (ort & C_ORT_TARGET) != 0;
3733 : 17798 : bool openmp_p = (ort & C_ORT_OMP) != 0;
3734 : :
3735 : 17798 : gcc_assert (i == 0);
3736 : :
3737 : 17798 : if (!openmp_p
3738 : 17798 : && map_p
3739 : 17798 : && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH
3740 : 6753 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DETACH))
3741 : : {
3742 : 28 : i += 2;
3743 : 28 : *idx = i;
3744 : 28 : return c;
3745 : : }
3746 : :
3747 : 17770 : switch (addr_tokens[i + 1]->u.access_kind)
3748 : : {
3749 : 13586 : case ACCESS_DIRECT:
3750 : 13586 : if (decl_p && !target_p)
3751 : 8559 : c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
3752 : : break;
3753 : :
3754 : 150 : case ACCESS_REF:
3755 : 150 : {
3756 : : /* Copy the referenced object. Note that we do this even for !MAP_P
3757 : : clauses. */
3758 : 150 : tree obj = convert_from_reference (addr_tokens[i + 1]->expr);
3759 : 150 : if (TREE_CODE (TREE_TYPE (obj)) == ARRAY_TYPE)
3760 : : /* We have a ref to array: add a [0] element as the ME expects. */
3761 : 43 : OMP_CLAUSE_DECL (c) = build_array_ref (loc, obj, integer_zero_node);
3762 : : else
3763 : 107 : OMP_CLAUSE_DECL (c) = obj;
3764 : 150 : OMP_CLAUSE_SIZE (c) = TYPE_SIZE_UNIT (TREE_TYPE (obj));
3765 : :
3766 : 150 : if (!map_p)
3767 : : {
3768 : 6 : if (decl_p)
3769 : 6 : c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
3770 : : break;
3771 : : }
3772 : :
3773 : 144 : if (!target_p)
3774 : : break;
3775 : :
3776 : : /* If we have a reference to a pointer, avoid using
3777 : : FIRSTPRIVATE_REFERENCE here in case the pointer is modified in the
3778 : : offload region (we can only do that if the pointer does not point
3779 : : to a mapped block). We could avoid doing this if we don't have a
3780 : : FROM mapping... */
3781 : 84 : bool ref_to_ptr = TREE_CODE (TREE_TYPE (obj)) == POINTER_TYPE;
3782 : :
3783 : 84 : c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
3784 : 84 : if (!ref_to_ptr
3785 : 84 : && !declare_target_p
3786 : 50 : && decl_p)
3787 : 50 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_FIRSTPRIVATE_REFERENCE);
3788 : : else
3789 : : {
3790 : 34 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
3791 : 34 : if (decl_p)
3792 : 34 : c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
3793 : : }
3794 : 84 : OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
3795 : 84 : OMP_CLAUSE_SIZE (c2) = size_zero_node;
3796 : :
3797 : 84 : if (ref_to_ptr)
3798 : : {
3799 : 34 : c3 = c2;
3800 : 34 : c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
3801 : 34 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ALLOC);
3802 : 34 : OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
3803 : 68 : OMP_CLAUSE_SIZE (c2)
3804 : 34 : = TYPE_SIZE_UNIT (TREE_TYPE (OMP_CLAUSE_DECL (c2)));
3805 : : }
3806 : : }
3807 : : break;
3808 : :
3809 : 83 : case ACCESS_INDEXED_REF_TO_ARRAY:
3810 : 83 : {
3811 : 83 : if (!map_p)
3812 : : {
3813 : 0 : if (decl_p)
3814 : 0 : c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
3815 : : break;
3816 : : }
3817 : :
3818 : 83 : if (!target_p)
3819 : : break;
3820 : :
3821 : 64 : tree virtual_origin
3822 : 64 : = convert_from_reference (addr_tokens[i + 1]->expr);
3823 : 64 : virtual_origin = build_fold_addr_expr (virtual_origin);
3824 : 64 : virtual_origin = fold_convert_loc (loc, ptrdiff_type_node,
3825 : : virtual_origin);
3826 : 64 : tree data_addr = omp_accessed_addr (addr_tokens, i + 1, expr);
3827 : 64 : c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
3828 : 64 : if (decl_p && target_p && !declare_target_p)
3829 : : {
3830 : : /* It appears that omp-low.cc mishandles cases where we have a
3831 : : [reference to an] array of pointers such as:
3832 : :
3833 : : int *arr[N]; (or "int *(&arr)[N] = ...")
3834 : : #pragma omp target map(arr[a][b:c])
3835 : : { ... }
3836 : :
3837 : : in such cases chain_p will be true. For now, fall back to
3838 : : GOMP_MAP_POINTER. */
3839 : 61 : enum gomp_map_kind k = chain_p ? GOMP_MAP_POINTER
3840 : : : GOMP_MAP_FIRSTPRIVATE_REFERENCE;
3841 : 61 : OMP_CLAUSE_SET_MAP_KIND (c2, k);
3842 : 61 : }
3843 : : else
3844 : : {
3845 : 3 : if (decl_p)
3846 : 0 : c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
3847 : 3 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
3848 : : }
3849 : 64 : OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
3850 : 64 : OMP_CLAUSE_SIZE (c2)
3851 : 64 : = fold_build2_loc (loc, MINUS_EXPR, ptrdiff_type_node,
3852 : : fold_convert_loc (loc, ptrdiff_type_node,
3853 : : data_addr),
3854 : : virtual_origin);
3855 : : }
3856 : 64 : break;
3857 : :
3858 : 1306 : case ACCESS_INDEXED_ARRAY:
3859 : 1306 : {
3860 : 1306 : if (!map_p)
3861 : : {
3862 : 0 : if (decl_p)
3863 : 0 : c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
3864 : : break;
3865 : : }
3866 : :
3867 : : /* The code handling "firstprivatize_array_bases" in gimplify.cc is
3868 : : relevant here. What do we need to create for arrays at this
3869 : : stage? (This condition doesn't feel quite right. FIXME?) */
3870 : 1306 : if (!target_p
3871 : 1306 : && (TREE_CODE (TREE_TYPE (addr_tokens[i + 1]->expr))
3872 : : == ARRAY_TYPE))
3873 : : break;
3874 : :
3875 : 653 : tree virtual_origin
3876 : 653 : = build_fold_addr_expr (addr_tokens[i + 1]->expr);
3877 : 653 : virtual_origin = fold_convert_loc (loc, ptrdiff_type_node,
3878 : : virtual_origin);
3879 : 653 : tree data_addr = omp_accessed_addr (addr_tokens, i + 1, expr);
3880 : 653 : c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
3881 : 653 : if (decl_p && target_p)
3882 : : {
3883 : : /* See comment for ACCESS_INDEXED_REF_TO_ARRAY above. */
3884 : 653 : enum gomp_map_kind k = chain_p ? GOMP_MAP_POINTER
3885 : : : GOMP_MAP_FIRSTPRIVATE_POINTER;
3886 : 653 : OMP_CLAUSE_SET_MAP_KIND (c2, k);
3887 : : }
3888 : : else
3889 : : {
3890 : 0 : if (decl_p)
3891 : 0 : c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
3892 : 0 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
3893 : : }
3894 : 653 : OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
3895 : 653 : OMP_CLAUSE_SIZE (c2)
3896 : 653 : = fold_build2_loc (loc, MINUS_EXPR, ptrdiff_type_node,
3897 : : fold_convert_loc (loc, ptrdiff_type_node,
3898 : : data_addr),
3899 : : virtual_origin);
3900 : : }
3901 : 653 : break;
3902 : :
3903 : 2571 : case ACCESS_POINTER:
3904 : 2571 : case ACCESS_POINTER_OFFSET:
3905 : 2571 : {
3906 : 2571 : if (!map_p)
3907 : : {
3908 : 0 : if (decl_p)
3909 : 0 : c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
3910 : : break;
3911 : : }
3912 : :
3913 : 2571 : unsigned last_access = i + 1;
3914 : 2571 : tree virtual_origin;
3915 : :
3916 : 2571 : if (chain_p
3917 : 127 : && addr_tokens[i + 2]->type == ACCESS_METHOD
3918 : 2698 : && addr_tokens[i + 2]->u.access_kind == ACCESS_INDEXED_ARRAY)
3919 : : {
3920 : : /* !!! This seems wrong for ACCESS_POINTER_OFFSET. */
3921 : 117 : consume_tokens = 3;
3922 : 117 : chain_p = omp_access_chain_p (addr_tokens, i + 2);
3923 : 117 : last_access = i + 2;
3924 : 117 : virtual_origin
3925 : 117 : = build_array_ref (loc, addr_tokens[last_access]->expr,
3926 : : integer_zero_node);
3927 : 117 : virtual_origin = build_fold_addr_expr (virtual_origin);
3928 : 117 : virtual_origin = fold_convert_loc (loc, ptrdiff_type_node,
3929 : : virtual_origin);
3930 : : }
3931 : : else
3932 : 2454 : virtual_origin = fold_convert_loc (loc, ptrdiff_type_node,
3933 : 2454 : addr_tokens[last_access]->expr);
3934 : 2571 : tree data_addr = omp_accessed_addr (addr_tokens, last_access, expr);
3935 : 2571 : c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
3936 : : /* For OpenACC, use FIRSTPRIVATE_POINTER for decls even on non-compute
3937 : : regions (e.g. "acc data" constructs). It'll be removed anyway in
3938 : : gimplify.cc, but doing it this way maintains diagnostic
3939 : : behaviour. */
3940 : 2571 : if (decl_p && (target_p || !openmp_p) && !chain_p && !declare_target_p)
3941 : 2406 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_FIRSTPRIVATE_POINTER);
3942 : : else
3943 : : {
3944 : 162 : if (decl_p)
3945 : 162 : c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
3946 : 165 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
3947 : : }
3948 : 2571 : OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
3949 : 2571 : OMP_CLAUSE_SIZE (c2)
3950 : 2571 : = fold_build2_loc (loc, MINUS_EXPR, ptrdiff_type_node,
3951 : : fold_convert_loc (loc, ptrdiff_type_node,
3952 : : data_addr),
3953 : : virtual_origin);
3954 : : }
3955 : 2571 : break;
3956 : :
3957 : 74 : case ACCESS_REF_TO_POINTER:
3958 : 74 : case ACCESS_REF_TO_POINTER_OFFSET:
3959 : 74 : {
3960 : 74 : if (!map_p)
3961 : : {
3962 : 0 : if (decl_p)
3963 : 0 : c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
3964 : : break;
3965 : : }
3966 : :
3967 : 74 : unsigned last_access = i + 1;
3968 : 74 : tree virtual_origin;
3969 : :
3970 : 74 : if (chain_p
3971 : 6 : && addr_tokens[i + 2]->type == ACCESS_METHOD
3972 : 80 : && addr_tokens[i + 2]->u.access_kind == ACCESS_INDEXED_ARRAY)
3973 : : {
3974 : : /* !!! This seems wrong for ACCESS_POINTER_OFFSET. */
3975 : 2 : consume_tokens = 3;
3976 : 2 : chain_p = omp_access_chain_p (addr_tokens, i + 2);
3977 : 2 : last_access = i + 2;
3978 : 2 : virtual_origin
3979 : 2 : = build_array_ref (loc, addr_tokens[last_access]->expr,
3980 : : integer_zero_node);
3981 : 2 : virtual_origin = build_fold_addr_expr (virtual_origin);
3982 : 2 : virtual_origin = fold_convert_loc (loc, ptrdiff_type_node,
3983 : : virtual_origin);
3984 : : }
3985 : : else
3986 : : {
3987 : 72 : virtual_origin
3988 : 72 : = convert_from_reference (addr_tokens[last_access]->expr);
3989 : 72 : virtual_origin = fold_convert_loc (loc, ptrdiff_type_node,
3990 : : virtual_origin);
3991 : : }
3992 : :
3993 : 74 : tree data_addr = omp_accessed_addr (addr_tokens, last_access, expr);
3994 : 74 : c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
3995 : 74 : if (decl_p && target_p && !chain_p && !declare_target_p)
3996 : : {
3997 : 58 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_FIRSTPRIVATE_REFERENCE);
3998 : 58 : OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
3999 : : }
4000 : : else
4001 : : {
4002 : 16 : if (decl_p)
4003 : 16 : c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
4004 : 16 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
4005 : 16 : OMP_CLAUSE_DECL (c2)
4006 : 32 : = convert_from_reference (addr_tokens[i + 1]->expr);
4007 : : }
4008 : 74 : OMP_CLAUSE_SIZE (c2)
4009 : 74 : = fold_build2_loc (loc, MINUS_EXPR, ptrdiff_type_node,
4010 : : fold_convert_loc (loc, ptrdiff_type_node,
4011 : : data_addr),
4012 : : virtual_origin);
4013 : : }
4014 : 74 : break;
4015 : :
4016 : 0 : default:
4017 : 0 : *idx = i + consume_tokens;
4018 : 0 : return error_mark_node;
4019 : : }
4020 : :
4021 : 11927 : if (c3)
4022 : : {
4023 : 34 : OMP_CLAUSE_CHAIN (c3) = OMP_CLAUSE_CHAIN (c);
4024 : 34 : OMP_CLAUSE_CHAIN (c2) = c3;
4025 : 34 : OMP_CLAUSE_CHAIN (c) = c2;
4026 : 34 : if (implicit_p)
4027 : : {
4028 : 0 : OMP_CLAUSE_MAP_IMPLICIT (c2) = 1;
4029 : 0 : OMP_CLAUSE_MAP_IMPLICIT (c3) = 1;
4030 : : }
4031 : : c = c3;
4032 : : }
4033 : 17736 : else if (c2)
4034 : : {
4035 : 3412 : OMP_CLAUSE_CHAIN (c2) = OMP_CLAUSE_CHAIN (c);
4036 : 3412 : OMP_CLAUSE_CHAIN (c) = c2;
4037 : 3412 : if (implicit_p)
4038 : 116 : OMP_CLAUSE_MAP_IMPLICIT (c2) = 1;
4039 : : c = c2;
4040 : : }
4041 : :
4042 : 17770 : i += consume_tokens;
4043 : 17770 : *idx = i;
4044 : :
4045 : 17770 : if (chain_p && map_p)
4046 : 27 : return omp_expand_access_chain (c, expr, addr_tokens, idx, ort);
4047 : :
4048 : : return c;
4049 : : }
4050 : :
4051 : : /* Translate "component_selector access_method" to OMP mapping clauses. */
4052 : :
4053 : : tree
4054 : 2894 : c_omp_address_inspector::expand_component_selector (tree c,
4055 : : vec<omp_addr_token *>
4056 : : &addr_tokens,
4057 : : tree expr, unsigned *idx,
4058 : : c_omp_region_type ort)
4059 : : {
4060 : 2894 : using namespace omp_addr_tokenizer;
4061 : 2894 : location_t loc = OMP_CLAUSE_LOCATION (c);
4062 : 2894 : unsigned i = *idx;
4063 : 2894 : tree c2 = NULL_TREE, c3 = NULL_TREE;
4064 : 2894 : bool chain_p = omp_access_chain_p (addr_tokens, i + 1);
4065 : 2894 : bool map_p = OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP;
4066 : :
4067 : 2894 : switch (addr_tokens[i + 1]->u.access_kind)
4068 : : {
4069 : : case ACCESS_DIRECT:
4070 : : case ACCESS_INDEXED_ARRAY:
4071 : : break;
4072 : :
4073 : 479 : case ACCESS_REF:
4074 : 479 : {
4075 : : /* Copy the referenced object. Note that we also do this for !MAP_P
4076 : : clauses. */
4077 : 479 : tree obj = convert_from_reference (addr_tokens[i + 1]->expr);
4078 : 479 : OMP_CLAUSE_DECL (c) = obj;
4079 : 479 : OMP_CLAUSE_SIZE (c) = TYPE_SIZE_UNIT (TREE_TYPE (obj));
4080 : :
4081 : 479 : if (!map_p)
4082 : : break;
4083 : :
4084 : 461 : c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
4085 : 461 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
4086 : 461 : OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
4087 : 461 : OMP_CLAUSE_SIZE (c2) = size_zero_node;
4088 : : }
4089 : 461 : break;
4090 : :
4091 : 92 : case ACCESS_INDEXED_REF_TO_ARRAY:
4092 : 92 : {
4093 : 92 : if (!map_p)
4094 : : break;
4095 : :
4096 : 92 : tree virtual_origin
4097 : 92 : = convert_from_reference (addr_tokens[i + 1]->expr);
4098 : 92 : virtual_origin = build_fold_addr_expr (virtual_origin);
4099 : 92 : virtual_origin = fold_convert_loc (loc, ptrdiff_type_node,
4100 : : virtual_origin);
4101 : 92 : tree data_addr = omp_accessed_addr (addr_tokens, i + 1, expr);
4102 : :
4103 : 92 : c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
4104 : 92 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
4105 : 92 : OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
4106 : 92 : OMP_CLAUSE_SIZE (c2)
4107 : 92 : = fold_build2_loc (loc, MINUS_EXPR, ptrdiff_type_node,
4108 : : fold_convert_loc (loc, ptrdiff_type_node,
4109 : : data_addr),
4110 : : virtual_origin);
4111 : : }
4112 : 92 : break;
4113 : :
4114 : 778 : case ACCESS_POINTER:
4115 : 778 : case ACCESS_POINTER_OFFSET:
4116 : 778 : {
4117 : 778 : if (!map_p)
4118 : : break;
4119 : :
4120 : 778 : tree virtual_origin
4121 : 1556 : = fold_convert_loc (loc, ptrdiff_type_node,
4122 : 778 : addr_tokens[i + 1]->expr);
4123 : 778 : tree data_addr = omp_accessed_addr (addr_tokens, i + 1, expr);
4124 : :
4125 : 778 : c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
4126 : 778 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
4127 : 778 : OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
4128 : 778 : OMP_CLAUSE_SIZE (c2)
4129 : 778 : = fold_build2_loc (loc, MINUS_EXPR, ptrdiff_type_node,
4130 : : fold_convert_loc (loc, ptrdiff_type_node,
4131 : : data_addr),
4132 : : virtual_origin);
4133 : : }
4134 : 778 : break;
4135 : :
4136 : 185 : case ACCESS_REF_TO_POINTER:
4137 : 185 : case ACCESS_REF_TO_POINTER_OFFSET:
4138 : 185 : {
4139 : 185 : if (!map_p)
4140 : : break;
4141 : :
4142 : 185 : tree ptr = convert_from_reference (addr_tokens[i + 1]->expr);
4143 : 185 : tree virtual_origin = fold_convert_loc (loc, ptrdiff_type_node,
4144 : : ptr);
4145 : 185 : tree data_addr = omp_accessed_addr (addr_tokens, i + 1, expr);
4146 : :
4147 : : /* Attach the pointer... */
4148 : 185 : c2 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
4149 : 185 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
4150 : 185 : OMP_CLAUSE_DECL (c2) = ptr;
4151 : 185 : OMP_CLAUSE_SIZE (c2)
4152 : 185 : = fold_build2_loc (loc, MINUS_EXPR, ptrdiff_type_node,
4153 : : fold_convert_loc (loc, ptrdiff_type_node,
4154 : : data_addr),
4155 : : virtual_origin);
4156 : :
4157 : : /* ...and also the reference. */
4158 : 185 : c3 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
4159 : 185 : OMP_CLAUSE_SET_MAP_KIND (c3, GOMP_MAP_ATTACH_DETACH);
4160 : 185 : OMP_CLAUSE_DECL (c3) = addr_tokens[i + 1]->expr;
4161 : 185 : OMP_CLAUSE_SIZE (c3) = size_zero_node;
4162 : : }
4163 : 185 : break;
4164 : :
4165 : 0 : default:
4166 : 0 : *idx = i + 2;
4167 : 0 : return error_mark_node;
4168 : : }
4169 : :
4170 : 1331 : if (c3)
4171 : : {
4172 : 185 : OMP_CLAUSE_CHAIN (c3) = OMP_CLAUSE_CHAIN (c);
4173 : 185 : OMP_CLAUSE_CHAIN (c2) = c3;
4174 : 185 : OMP_CLAUSE_CHAIN (c) = c2;
4175 : 185 : c = c3;
4176 : : }
4177 : 2709 : else if (c2)
4178 : : {
4179 : 1331 : OMP_CLAUSE_CHAIN (c2) = OMP_CLAUSE_CHAIN (c);
4180 : 1331 : OMP_CLAUSE_CHAIN (c) = c2;
4181 : 1331 : c = c2;
4182 : : }
4183 : :
4184 : 2894 : i += 2;
4185 : 2894 : *idx = i;
4186 : :
4187 : 2894 : if (chain_p && map_p)
4188 : 22 : return omp_expand_access_chain (c, expr, addr_tokens, idx, ort);
4189 : :
4190 : : return c;
4191 : : }
4192 : :
4193 : : /* Expand a map clause into a group of mapping clauses, creating nodes to
4194 : : attach/detach pointers and so forth as necessary. */
4195 : :
4196 : : tree
4197 : 20692 : c_omp_address_inspector::expand_map_clause (tree c, tree expr,
4198 : : vec<omp_addr_token *> &addr_tokens,
4199 : : c_omp_region_type ort)
4200 : : {
4201 : 20692 : using namespace omp_addr_tokenizer;
4202 : 20692 : unsigned i, length = addr_tokens.length ();
4203 : :
4204 : 44973 : for (i = 0; i < length;)
4205 : : {
4206 : 24281 : int remaining = length - i;
4207 : :
4208 : 24281 : if (remaining >= 2
4209 : 24281 : && addr_tokens[i]->type == ARRAY_BASE
4210 : 17798 : && addr_tokens[i]->u.structure_base_kind == BASE_DECL
4211 : 42070 : && addr_tokens[i + 1]->type == ACCESS_METHOD)
4212 : : {
4213 : 17789 : c = expand_array_base (c, addr_tokens, expr, &i, ort);
4214 : 17789 : if (c == error_mark_node)
4215 : : return error_mark_node;
4216 : : }
4217 : 6492 : else if (remaining >= 2
4218 : 6492 : && addr_tokens[i]->type == ARRAY_BASE
4219 : 9 : && addr_tokens[i]->u.structure_base_kind == BASE_ARBITRARY_EXPR
4220 : 6501 : && addr_tokens[i + 1]->type == ACCESS_METHOD)
4221 : : {
4222 : 9 : c = expand_array_base (c, addr_tokens, expr, &i, ort);
4223 : 9 : if (c == error_mark_node)
4224 : : return error_mark_node;
4225 : : }
4226 : 6483 : else if (remaining >= 2
4227 : 6483 : && addr_tokens[i]->type == STRUCTURE_BASE
4228 : 2894 : && addr_tokens[i]->u.structure_base_kind == BASE_DECL
4229 : 9374 : && addr_tokens[i + 1]->type == ACCESS_METHOD)
4230 : : {
4231 : 2891 : if (addr_tokens[i + 1]->u.access_kind == ACCESS_DIRECT)
4232 : 1422 : c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
4233 : 2891 : i += 2;
4234 : 3051 : while (addr_tokens[i]->type == ACCESS_METHOD)
4235 : 160 : i++;
4236 : : }
4237 : 3592 : else if (remaining >= 2
4238 : 3592 : && addr_tokens[i]->type == STRUCTURE_BASE
4239 : 3 : && addr_tokens[i]->u.structure_base_kind == BASE_ARBITRARY_EXPR
4240 : 3595 : && addr_tokens[i + 1]->type == ACCESS_METHOD)
4241 : : {
4242 : 3 : switch (addr_tokens[i + 1]->u.access_kind)
4243 : : {
4244 : 3 : case ACCESS_DIRECT:
4245 : 3 : case ACCESS_POINTER:
4246 : 3 : i += 2;
4247 : 3 : while (addr_tokens[i]->type == ACCESS_METHOD)
4248 : 0 : i++;
4249 : : break;
4250 : 0 : default:
4251 : 0 : return error_mark_node;
4252 : : }
4253 : : }
4254 : 3589 : else if (remaining >= 2
4255 : 3589 : && addr_tokens[i]->type == COMPONENT_SELECTOR
4256 : 7178 : && addr_tokens[i + 1]->type == ACCESS_METHOD)
4257 : : {
4258 : 2894 : c = expand_component_selector (c, addr_tokens, expr, &i, ort);
4259 : : /* We used 'expr', so these must have been the last tokens. */
4260 : 2894 : gcc_assert (i == length);
4261 : 2894 : if (c == error_mark_node)
4262 : : return error_mark_node;
4263 : : }
4264 : 695 : else if (remaining >= 3
4265 : 695 : && addr_tokens[i]->type == COMPONENT_SELECTOR
4266 : 695 : && addr_tokens[i + 1]->type == STRUCTURE_BASE
4267 : 695 : && (addr_tokens[i + 1]->u.structure_base_kind
4268 : : == BASE_COMPONENT_EXPR)
4269 : 1390 : && addr_tokens[i + 2]->type == ACCESS_METHOD)
4270 : : {
4271 : 695 : i += 3;
4272 : 719 : while (addr_tokens[i]->type == ACCESS_METHOD)
4273 : 24 : i++;
4274 : : }
4275 : : else
4276 : : break;
4277 : : }
4278 : :
4279 : 20692 : if (i == length)
4280 : : return c;
4281 : :
4282 : 0 : return error_mark_node;
4283 : : }
4284 : :
4285 : : /* Given a mapper function MAPPER_FN, recursively scan through the map clauses
4286 : : for that mapper, and if any of those should use a (named or unnamed) mapper
4287 : : themselves, add it to MLIST. */
4288 : :
4289 : : void
4290 : 130 : c_omp_find_nested_mappers (omp_mapper_list<tree> *mlist, tree mapper_fn)
4291 : : {
4292 : 130 : tree mapper = lang_hooks.decls.omp_extract_mapper_directive (mapper_fn);
4293 : 130 : tree mapper_name = NULL_TREE;
4294 : :
4295 : 130 : if (mapper == error_mark_node)
4296 : : return;
4297 : :
4298 : 130 : gcc_assert (TREE_CODE (mapper) == OMP_DECLARE_MAPPER);
4299 : :
4300 : 410 : for (tree clause = OMP_DECLARE_MAPPER_CLAUSES (mapper);
4301 : 410 : clause;
4302 : 280 : clause = OMP_CLAUSE_CHAIN (clause))
4303 : : {
4304 : 280 : tree expr = OMP_CLAUSE_DECL (clause);
4305 : 280 : enum gomp_map_kind clause_kind = OMP_CLAUSE_MAP_KIND (clause);
4306 : 280 : tree elem_type;
4307 : :
4308 : 280 : if (clause_kind == GOMP_MAP_PUSH_MAPPER_NAME)
4309 : : {
4310 : 0 : mapper_name = expr;
4311 : 0 : continue;
4312 : : }
4313 : 280 : else if (clause_kind == GOMP_MAP_POP_MAPPER_NAME)
4314 : : {
4315 : 0 : mapper_name = NULL_TREE;
4316 : 0 : continue;
4317 : : }
4318 : :
4319 : 280 : gcc_assert (TREE_CODE (expr) != TREE_LIST);
4320 : 280 : if (TREE_CODE (expr) == OMP_ARRAY_SECTION)
4321 : : {
4322 : 220 : while (TREE_CODE (expr) == OMP_ARRAY_SECTION)
4323 : 110 : expr = TREE_OPERAND (expr, 0);
4324 : :
4325 : 110 : elem_type = TREE_TYPE (expr);
4326 : : }
4327 : : else
4328 : 170 : elem_type = TREE_TYPE (expr);
4329 : :
4330 : : /* This might be too much... or not enough? */
4331 : 478 : while (TREE_CODE (elem_type) == ARRAY_TYPE
4332 : 472 : || TREE_CODE (elem_type) == POINTER_TYPE
4333 : 758 : || TREE_CODE (elem_type) == REFERENCE_TYPE)
4334 : 198 : elem_type = TREE_TYPE (elem_type);
4335 : :
4336 : 280 : elem_type = TYPE_MAIN_VARIANT (elem_type);
4337 : :
4338 : 280 : if (RECORD_OR_UNION_TYPE_P (elem_type)
4339 : 280 : && !mlist->contains (mapper_name, elem_type))
4340 : : {
4341 : 5 : tree nested_mapper_fn
4342 : 5 : = lang_hooks.decls.omp_mapper_lookup (mapper_name, elem_type);
4343 : :
4344 : 5 : if (nested_mapper_fn)
4345 : : {
4346 : 5 : mlist->add_mapper (mapper_name, elem_type, nested_mapper_fn);
4347 : 5 : c_omp_find_nested_mappers (mlist, nested_mapper_fn);
4348 : : }
4349 : 0 : else if (mapper_name)
4350 : : {
4351 : 0 : error ("mapper %qE not found for type %qT", mapper_name,
4352 : : elem_type);
4353 : 0 : continue;
4354 : : }
4355 : : }
4356 : : }
4357 : : }
4358 : :
4359 : : struct remap_mapper_decl_info
4360 : : {
4361 : : tree dummy_var;
4362 : : tree expr;
4363 : : };
4364 : :
4365 : : /* Helper for rewriting DUMMY_VAR into EXPR in a map clause decl. */
4366 : :
4367 : : static tree
4368 : 1072 : remap_mapper_decl_1 (tree *tp, int *walk_subtrees, void *data)
4369 : : {
4370 : 1072 : remap_mapper_decl_info *map_info = (remap_mapper_decl_info *) data;
4371 : :
4372 : 1072 : if (operand_equal_p (*tp, map_info->dummy_var))
4373 : : {
4374 : 251 : *tp = map_info->expr;
4375 : 251 : *walk_subtrees = 0;
4376 : : }
4377 : :
4378 : 1072 : return NULL_TREE;
4379 : : }
4380 : :
4381 : : /* Instantiate a mapper MAPPER for expression EXPR, adding new clauses to
4382 : : OUTLIST. OUTER_KIND is the mapping kind to use if not already specified in
4383 : : the mapper declaration. */
4384 : :
4385 : : static tree *
4386 : 49 : omp_instantiate_mapper (tree *outlist, tree mapper, tree expr,
4387 : : enum gomp_map_kind outer_kind)
4388 : : {
4389 : 49 : tree clauses = OMP_DECLARE_MAPPER_CLAUSES (mapper);
4390 : 49 : tree dummy_var = OMP_DECLARE_MAPPER_DECL (mapper);
4391 : 49 : tree mapper_name = NULL_TREE;
4392 : :
4393 : 49 : remap_mapper_decl_info map_info;
4394 : 49 : map_info.dummy_var = dummy_var;
4395 : 49 : map_info.expr = expr;
4396 : :
4397 : 163 : for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
4398 : : {
4399 : 114 : tree unshared = unshare_expr (c);
4400 : 114 : enum gomp_map_kind clause_kind = OMP_CLAUSE_MAP_KIND (c);
4401 : 114 : tree t = OMP_CLAUSE_DECL (unshared);
4402 : 114 : tree type = NULL_TREE;
4403 : 114 : bool nonunit_array_with_mapper = false;
4404 : :
4405 : 114 : if (clause_kind == GOMP_MAP_PUSH_MAPPER_NAME)
4406 : : {
4407 : 0 : mapper_name = t;
4408 : 2 : continue;
4409 : : }
4410 : 114 : else if (clause_kind == GOMP_MAP_POP_MAPPER_NAME)
4411 : : {
4412 : 0 : mapper_name = NULL_TREE;
4413 : 0 : continue;
4414 : : }
4415 : :
4416 : 114 : if (TREE_CODE (t) == OMP_ARRAY_SECTION)
4417 : : {
4418 : 41 : location_t loc = OMP_CLAUSE_LOCATION (c);
4419 : 41 : tree t2 = lang_hooks.decls.omp_map_array_section (loc, t);
4420 : :
4421 : 41 : if (t2 == t)
4422 : : {
4423 : 40 : nonunit_array_with_mapper = true;
4424 : : /* We'd want use the mapper for the element type if this worked:
4425 : : look that one up. */
4426 : 40 : type = TREE_TYPE (TREE_TYPE (t));
4427 : : }
4428 : : else
4429 : : {
4430 : 1 : t = t2;
4431 : 1 : type = TREE_TYPE (t);
4432 : : }
4433 : : }
4434 : : else
4435 : 73 : type = TREE_TYPE (t);
4436 : :
4437 : 114 : gcc_assert (type);
4438 : :
4439 : 114 : if (type == error_mark_node)
4440 : 0 : continue;
4441 : :
4442 : 114 : walk_tree (&unshared, remap_mapper_decl_1, &map_info, NULL);
4443 : :
4444 : 114 : if (OMP_CLAUSE_MAP_KIND (unshared) == GOMP_MAP_UNSET)
4445 : 56 : OMP_CLAUSE_SET_MAP_KIND (unshared, outer_kind);
4446 : :
4447 : 114 : type = TYPE_MAIN_VARIANT (type);
4448 : :
4449 : 114 : tree mapper_fn = lang_hooks.decls.omp_mapper_lookup (mapper_name, type);
4450 : :
4451 : 114 : if (mapper_fn && nonunit_array_with_mapper)
4452 : : {
4453 : 0 : sorry ("user-defined mapper with non-unit length array section");
4454 : 0 : continue;
4455 : : }
4456 : 114 : else if (mapper_fn)
4457 : : {
4458 : 12 : tree nested_mapper
4459 : 12 : = lang_hooks.decls.omp_extract_mapper_directive (mapper_fn);
4460 : 12 : if (nested_mapper != mapper)
4461 : : {
4462 : 2 : if (clause_kind == GOMP_MAP_UNSET)
4463 : 0 : clause_kind = outer_kind;
4464 : :
4465 : 2 : outlist = omp_instantiate_mapper (outlist, nested_mapper,
4466 : : t, clause_kind);
4467 : 2 : continue;
4468 : : }
4469 : : }
4470 : 102 : else if (mapper_name)
4471 : : {
4472 : 0 : error ("mapper %qE not found for type %qT", mapper_name, type);
4473 : 0 : continue;
4474 : : }
4475 : :
4476 : 112 : *outlist = unshared;
4477 : 112 : outlist = &OMP_CLAUSE_CHAIN (unshared);
4478 : : }
4479 : :
4480 : 49 : return outlist;
4481 : : }
4482 : :
4483 : : /* Given a list of CLAUSES, scan each clause and invoke a user-defined mapper
4484 : : appropriate to the type of the data in that clause, if such a mapper is
4485 : : visible in the current parsing context. */
4486 : :
4487 : : tree
4488 : 5734 : c_omp_instantiate_mappers (tree clauses)
4489 : : {
4490 : 5734 : tree c, *pc, mapper_name = NULL_TREE;
4491 : :
4492 : 12054 : for (pc = &clauses, c = clauses; c; c = *pc)
4493 : : {
4494 : 6320 : bool using_mapper = false;
4495 : :
4496 : 6320 : switch (OMP_CLAUSE_CODE (c))
4497 : : {
4498 : 4577 : case OMP_CLAUSE_MAP:
4499 : 4577 : {
4500 : 4577 : tree t = OMP_CLAUSE_DECL (c);
4501 : 4577 : tree type = NULL_TREE;
4502 : 4577 : bool nonunit_array_with_mapper = false;
4503 : :
4504 : 4577 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_PUSH_MAPPER_NAME
4505 : 4577 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POP_MAPPER_NAME)
4506 : : {
4507 : 38 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_PUSH_MAPPER_NAME)
4508 : 19 : mapper_name = OMP_CLAUSE_DECL (c);
4509 : : else
4510 : : mapper_name = NULL_TREE;
4511 : 38 : pc = &OMP_CLAUSE_CHAIN (c);
4512 : 38 : continue;
4513 : : }
4514 : :
4515 : 4539 : if (TREE_CODE (t) == OMP_ARRAY_SECTION)
4516 : : {
4517 : 1717 : location_t loc = OMP_CLAUSE_LOCATION (c);
4518 : 1717 : tree t2 = lang_hooks.decls.omp_map_array_section (loc, t);
4519 : :
4520 : 1717 : if (t2 == t)
4521 : : {
4522 : : /* !!! Array sections of size >1 with mappers for elements
4523 : : are hard to support. Do something here. */
4524 : 1462 : nonunit_array_with_mapper = true;
4525 : 1462 : type = TREE_TYPE (TREE_TYPE (t));
4526 : : }
4527 : : else
4528 : : {
4529 : 255 : t = t2;
4530 : 255 : type = TREE_TYPE (t);
4531 : : }
4532 : : }
4533 : : else
4534 : 2822 : type = TREE_TYPE (t);
4535 : :
4536 : 4539 : if (type == NULL_TREE || type == error_mark_node)
4537 : : {
4538 : 56 : pc = &OMP_CLAUSE_CHAIN (c);
4539 : 56 : continue;
4540 : : }
4541 : :
4542 : 4483 : enum gomp_map_kind kind = OMP_CLAUSE_MAP_KIND (c);
4543 : 4483 : if (kind == GOMP_MAP_UNSET)
4544 : 0 : kind = GOMP_MAP_TOFROM;
4545 : :
4546 : 4483 : type = TYPE_MAIN_VARIANT (type);
4547 : :
4548 : 4483 : tree mapper_fn
4549 : 4483 : = lang_hooks.decls.omp_mapper_lookup (mapper_name, type);
4550 : :
4551 : 4483 : if (mapper_fn && nonunit_array_with_mapper)
4552 : : {
4553 : 0 : sorry ("user-defined mapper with non-unit length "
4554 : : "array section");
4555 : 0 : using_mapper = true;
4556 : : }
4557 : 4483 : else if (mapper_fn)
4558 : : {
4559 : 47 : tree mapper
4560 : 47 : = lang_hooks.decls.omp_extract_mapper_directive (mapper_fn);
4561 : 47 : pc = omp_instantiate_mapper (pc, mapper, t, kind);
4562 : 47 : using_mapper = true;
4563 : : }
4564 : 4436 : else if (mapper_name)
4565 : : {
4566 : 0 : error ("mapper %qE not found for type %qT", mapper_name, type);
4567 : 0 : using_mapper = true;
4568 : : }
4569 : : }
4570 : : break;
4571 : :
4572 : 47 : default:
4573 : 47 : ;
4574 : : }
4575 : :
4576 : 47 : if (using_mapper)
4577 : 47 : *pc = OMP_CLAUSE_CHAIN (c);
4578 : : else
4579 : 6179 : pc = &OMP_CLAUSE_CHAIN (c);
4580 : : }
4581 : :
4582 : 5734 : return clauses;
4583 : : }
4584 : :
4585 : : const struct c_omp_directive c_omp_directives[] = {
4586 : : /* Keep this alphabetically sorted by the first word. Non-null second/third
4587 : : if any should precede null ones. */
4588 : : { "allocate", nullptr, nullptr, PRAGMA_OMP_ALLOCATE,
4589 : : C_OMP_DIR_DECLARATIVE, false },
4590 : : { "assume", nullptr, nullptr, PRAGMA_OMP_ASSUME,
4591 : : C_OMP_DIR_INFORMATIONAL, false },
4592 : : { "assumes", nullptr, nullptr, PRAGMA_OMP_ASSUMES,
4593 : : C_OMP_DIR_INFORMATIONAL, false },
4594 : : { "atomic", nullptr, nullptr, PRAGMA_OMP_ATOMIC,
4595 : : C_OMP_DIR_CONSTRUCT, false },
4596 : : { "barrier", nullptr, nullptr, PRAGMA_OMP_BARRIER,
4597 : : C_OMP_DIR_STANDALONE, false },
4598 : : { "begin", "assumes", nullptr, PRAGMA_OMP_BEGIN,
4599 : : C_OMP_DIR_INFORMATIONAL, false },
4600 : : { "begin", "declare", "target", PRAGMA_OMP_BEGIN,
4601 : : C_OMP_DIR_DECLARATIVE, false },
4602 : : /* { "begin", "declare", "variant", PRAGMA_OMP_BEGIN,
4603 : : C_OMP_DIR_DECLARATIVE, false }, */
4604 : : /* { "begin", "metadirective", nullptr, PRAGMA_OMP_BEGIN,
4605 : : C_OMP_DIR_META, false }, */
4606 : : { "cancel", nullptr, nullptr, PRAGMA_OMP_CANCEL,
4607 : : C_OMP_DIR_STANDALONE, false },
4608 : : { "cancellation", "point", nullptr, PRAGMA_OMP_CANCELLATION_POINT,
4609 : : C_OMP_DIR_STANDALONE, false },
4610 : : { "critical", nullptr, nullptr, PRAGMA_OMP_CRITICAL,
4611 : : C_OMP_DIR_CONSTRUCT, false },
4612 : : /* { "declare", "mapper", nullptr, PRAGMA_OMP_DECLARE,
4613 : : C_OMP_DIR_DECLARATIVE, false }, */
4614 : : { "declare", "reduction", nullptr, PRAGMA_OMP_DECLARE,
4615 : : C_OMP_DIR_DECLARATIVE, true },
4616 : : { "declare", "simd", nullptr, PRAGMA_OMP_DECLARE,
4617 : : C_OMP_DIR_DECLARATIVE, true },
4618 : : { "declare", "target", nullptr, PRAGMA_OMP_DECLARE,
4619 : : C_OMP_DIR_DECLARATIVE, false },
4620 : : { "declare", "variant", nullptr, PRAGMA_OMP_DECLARE,
4621 : : C_OMP_DIR_DECLARATIVE, false },
4622 : : { "depobj", nullptr, nullptr, PRAGMA_OMP_DEPOBJ,
4623 : : C_OMP_DIR_STANDALONE, false },
4624 : : { "dispatch", nullptr, nullptr, PRAGMA_OMP_DISPATCH,
4625 : : C_OMP_DIR_DECLARATIVE, false },
4626 : : { "distribute", nullptr, nullptr, PRAGMA_OMP_DISTRIBUTE,
4627 : : C_OMP_DIR_CONSTRUCT, true },
4628 : : { "end", "assumes", nullptr, PRAGMA_OMP_END,
4629 : : C_OMP_DIR_INFORMATIONAL, false },
4630 : : { "end", "declare", "target", PRAGMA_OMP_END,
4631 : : C_OMP_DIR_DECLARATIVE, false },
4632 : : /* { "end", "declare", "variant", PRAGMA_OMP_END,
4633 : : C_OMP_DIR_DECLARATIVE, false }, */
4634 : : /* { "end", "metadirective", nullptr, PRAGMA_OMP_END,
4635 : : C_OMP_DIR_META, false }, */
4636 : : /* error with at(execution) is C_OMP_DIR_STANDALONE. */
4637 : : { "error", nullptr, nullptr, PRAGMA_OMP_ERROR,
4638 : : C_OMP_DIR_UTILITY, false },
4639 : : { "flush", nullptr, nullptr, PRAGMA_OMP_FLUSH,
4640 : : C_OMP_DIR_STANDALONE, false },
4641 : : { "for", nullptr, nullptr, PRAGMA_OMP_FOR,
4642 : : C_OMP_DIR_CONSTRUCT, true },
4643 : : /* { "groupprivate", nullptr, nullptr, PRAGMA_OMP_GROUPPRIVATE,
4644 : : C_OMP_DIR_DECLARATIVE, false }, */
4645 : : { "interop", nullptr, nullptr, PRAGMA_OMP_INTEROP,
4646 : : C_OMP_DIR_STANDALONE, false },
4647 : : { "loop", nullptr, nullptr, PRAGMA_OMP_LOOP,
4648 : : C_OMP_DIR_CONSTRUCT, true },
4649 : : { "masked", nullptr, nullptr, PRAGMA_OMP_MASKED,
4650 : : C_OMP_DIR_CONSTRUCT, true },
4651 : : { "master", nullptr, nullptr, PRAGMA_OMP_MASTER,
4652 : : C_OMP_DIR_CONSTRUCT, true },
4653 : : { "metadirective", nullptr, nullptr, PRAGMA_OMP_METADIRECTIVE,
4654 : : C_OMP_DIR_META, false },
4655 : : { "nothing", nullptr, nullptr, PRAGMA_OMP_NOTHING,
4656 : : C_OMP_DIR_UTILITY, false },
4657 : : /* ordered with depend clause is C_OMP_DIR_STANDALONE. */
4658 : : { "ordered", nullptr, nullptr, PRAGMA_OMP_ORDERED,
4659 : : C_OMP_DIR_CONSTRUCT, true },
4660 : : { "parallel", nullptr, nullptr, PRAGMA_OMP_PARALLEL,
4661 : : C_OMP_DIR_CONSTRUCT, true },
4662 : : { "requires", nullptr, nullptr, PRAGMA_OMP_REQUIRES,
4663 : : C_OMP_DIR_INFORMATIONAL, false },
4664 : : { "scan", nullptr, nullptr, PRAGMA_OMP_SCAN,
4665 : : C_OMP_DIR_CONSTRUCT, true },
4666 : : { "scope", nullptr, nullptr, PRAGMA_OMP_SCOPE,
4667 : : C_OMP_DIR_CONSTRUCT, false },
4668 : : { "section", nullptr, nullptr, PRAGMA_OMP_SECTION,
4669 : : C_OMP_DIR_CONSTRUCT, false },
4670 : : { "sections", nullptr, nullptr, PRAGMA_OMP_SECTIONS,
4671 : : C_OMP_DIR_CONSTRUCT, false },
4672 : : { "simd", nullptr, nullptr, PRAGMA_OMP_SIMD,
4673 : : C_OMP_DIR_CONSTRUCT, true },
4674 : : { "single", nullptr, nullptr, PRAGMA_OMP_SINGLE,
4675 : : C_OMP_DIR_CONSTRUCT, false },
4676 : : { "target", "data", nullptr, PRAGMA_OMP_TARGET,
4677 : : C_OMP_DIR_CONSTRUCT, false },
4678 : : { "target", "enter", "data", PRAGMA_OMP_TARGET,
4679 : : C_OMP_DIR_STANDALONE, false },
4680 : : { "target", "exit", "data", PRAGMA_OMP_TARGET,
4681 : : C_OMP_DIR_STANDALONE, false },
4682 : : { "target", "update", nullptr, PRAGMA_OMP_TARGET,
4683 : : C_OMP_DIR_STANDALONE, false },
4684 : : { "target", nullptr, nullptr, PRAGMA_OMP_TARGET,
4685 : : C_OMP_DIR_CONSTRUCT, true },
4686 : : { "task", nullptr, nullptr, PRAGMA_OMP_TASK,
4687 : : C_OMP_DIR_CONSTRUCT, false },
4688 : : { "taskgroup", nullptr, nullptr, PRAGMA_OMP_TASKGROUP,
4689 : : C_OMP_DIR_CONSTRUCT, false },
4690 : : { "taskloop", nullptr, nullptr, PRAGMA_OMP_TASKLOOP,
4691 : : C_OMP_DIR_CONSTRUCT, true },
4692 : : { "taskwait", nullptr, nullptr, PRAGMA_OMP_TASKWAIT,
4693 : : C_OMP_DIR_STANDALONE, false },
4694 : : { "taskyield", nullptr, nullptr, PRAGMA_OMP_TASKYIELD,
4695 : : C_OMP_DIR_STANDALONE, false },
4696 : : { "tile", nullptr, nullptr, PRAGMA_OMP_TILE,
4697 : : C_OMP_DIR_CONSTRUCT, false },
4698 : : { "teams", nullptr, nullptr, PRAGMA_OMP_TEAMS,
4699 : : C_OMP_DIR_CONSTRUCT, true },
4700 : : { "threadprivate", nullptr, nullptr, PRAGMA_OMP_THREADPRIVATE,
4701 : : C_OMP_DIR_DECLARATIVE, false },
4702 : : { "unroll", nullptr, nullptr, PRAGMA_OMP_UNROLL,
4703 : : C_OMP_DIR_CONSTRUCT, false },
4704 : : };
4705 : :
4706 : : /* Find (non-combined/composite) OpenMP directive (if any) which starts
4707 : : with FIRST keyword and for multi-word directives has SECOND and
4708 : : THIRD keyword after it. */
4709 : :
4710 : : const struct c_omp_directive *
4711 : 6534 : c_omp_categorize_directive (const char *first, const char *second,
4712 : : const char *third)
4713 : : {
4714 : 6534 : const size_t n_omp_directives = ARRAY_SIZE (c_omp_directives);
4715 : 187941 : for (size_t i = 0; i < n_omp_directives; i++)
4716 : : {
4717 : 350536 : if ((unsigned char) c_omp_directives[i].first[0]
4718 : 187941 : < (unsigned char) first[0])
4719 : 162595 : continue;
4720 : 25346 : if ((unsigned char) c_omp_directives[i].first[0]
4721 : : > (unsigned char) first[0])
4722 : : break;
4723 : 25259 : if (strcmp (c_omp_directives[i].first, first))
4724 : 15566 : continue;
4725 : 9693 : if (!c_omp_directives[i].second)
4726 : 5072 : return &c_omp_directives[i];
4727 : 4621 : if (!second || strcmp (c_omp_directives[i].second, second))
4728 : 3234 : continue;
4729 : 1387 : if (!c_omp_directives[i].third)
4730 : 1099 : return &c_omp_directives[i];
4731 : 288 : if (!third || strcmp (c_omp_directives[i].third, third))
4732 : 12 : continue;
4733 : 276 : return &c_omp_directives[i];
4734 : : }
4735 : : return NULL;
4736 : : }
4737 : :
4738 : : /* Auxilliary helper function for c_omp_expand_variant_construct. */
4739 : :
4740 : : static tree
4741 : 462 : c_omp_expand_variant_construct_r (vec<struct omp_variant> &candidates,
4742 : : hash_map<tree, tree> &body_labels,
4743 : : unsigned index)
4744 : : {
4745 : 462 : struct omp_variant &candidate = candidates[index];
4746 : 462 : tree if_block = push_stmt_list ();
4747 : 462 : if (candidate.alternative != NULL_TREE)
4748 : 462 : add_stmt (candidate.alternative);
4749 : 462 : if (candidate.body != NULL_TREE)
4750 : : {
4751 : 138 : tree *label = body_labels.get (candidate.body);
4752 : 138 : if (label != NULL)
4753 : 0 : add_stmt (build1 (GOTO_EXPR, void_type_node, *label));
4754 : : else
4755 : : {
4756 : 138 : tree body_label = create_artificial_label (UNKNOWN_LOCATION);
4757 : 138 : add_stmt (build1 (LABEL_EXPR, void_type_node, body_label));
4758 : 138 : add_stmt (candidate.body);
4759 : 138 : body_labels.put (candidate.body, body_label);
4760 : : }
4761 : : }
4762 : 462 : if_block = pop_stmt_list (if_block);
4763 : :
4764 : 924 : if (index == candidates.length () - 1)
4765 : : return if_block;
4766 : :
4767 : 154 : tree cond = omp_dynamic_cond (candidate.selector, NULL_TREE);
4768 : 154 : gcc_assert (cond != NULL_TREE);
4769 : :
4770 : 154 : tree else_block = c_omp_expand_variant_construct_r (candidates, body_labels,
4771 : : index + 1);
4772 : 154 : tree ret = push_stmt_list ();
4773 : 154 : tree stmt = build3 (COND_EXPR, void_type_node, cond, if_block, else_block);
4774 : 154 : add_stmt (stmt);
4775 : 154 : ret = pop_stmt_list (ret);
4776 : :
4777 : 154 : return ret;
4778 : : }
4779 : :
4780 : : /* Resolve the vector of metadirective variant CANDIDATES to a parse tree
4781 : : structure. */
4782 : :
4783 : : tree
4784 : 308 : c_omp_expand_variant_construct (vec<struct omp_variant> &candidates)
4785 : : {
4786 : 308 : hash_map<tree, tree> body_labels;
4787 : 308 : return c_omp_expand_variant_construct_r (candidates, body_labels, 0);
4788 : 308 : }
|