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-2023 Free Software Foundation, Inc.
5 Contributed by Richard Henderson <rth@redhat.com>,
6 Diego Novillo <dnovillo@redhat.com>.
7
8This file is part of GCC.
9
10GCC is free software; you can redistribute it and/or modify it under
11the terms of the GNU General Public License as published by the Free
12Software Foundation; either version 3, or (at your option) any later
13version.
14
15GCC is distributed in the hope that it will be useful, but WITHOUT ANY
16WARRANTY; without even the implied warranty of MERCHANTABILITY or
17FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18for more details.
19
20You should have received a copy of the GNU General Public License
21along 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
45tree
46c_finish_oacc_wait (location_t loc, tree parms, tree clauses)
47{
48 const int nparms = list_length (parms);
49 tree stmt, t;
50 vec<tree, va_gc> *args;
51
52 vec_alloc (v&: args, nelems: nparms + 2);
53 stmt = builtin_decl_explicit (fncode: BUILT_IN_GOACC_WAIT);
54
55 if (omp_find_clause (clauses, kind: OMP_CLAUSE_ASYNC))
56 t = OMP_CLAUSE_ASYNC_EXPR (clauses);
57 else
58 t = build_int_cst (integer_type_node, GOMP_ASYNC_SYNC);
59
60 args->quick_push (obj: t);
61 args->quick_push (obj: build_int_cst (integer_type_node, nparms));
62
63 for (t = parms; t; t = TREE_CHAIN (t))
64 {
65 if (TREE_CODE (OMP_CLAUSE_WAIT_EXPR (t)) == INTEGER_CST)
66 args->quick_push (obj: build_int_cst (integer_type_node,
67 TREE_INT_CST_LOW (OMP_CLAUSE_WAIT_EXPR (t))));
68 else
69 args->quick_push (OMP_CLAUSE_WAIT_EXPR (t));
70 }
71
72 stmt = build_call_expr_loc_vec (loc, stmt, args);
73
74 vec_free (v&: args);
75
76 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
82tree
83c_finish_omp_master (location_t loc, tree stmt)
84{
85 tree t = add_stmt (build1 (OMP_MASTER, void_type_node, stmt));
86 SET_EXPR_LOCATION (t, loc);
87 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
93tree
94c_finish_omp_masked (location_t loc, tree body, tree clauses)
95{
96 tree stmt = make_node (OMP_MASKED);
97 TREE_TYPE (stmt) = void_type_node;
98 OMP_MASKED_BODY (stmt) = body;
99 OMP_MASKED_CLAUSES (stmt) = clauses;
100 SET_EXPR_LOCATION (stmt, loc);
101 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
107tree
108c_finish_omp_taskgroup (location_t loc, tree body, tree clauses)
109{
110 tree stmt = make_node (OMP_TASKGROUP);
111 TREE_TYPE (stmt) = void_type_node;
112 OMP_TASKGROUP_BODY (stmt) = body;
113 OMP_TASKGROUP_CLAUSES (stmt) = clauses;
114 SET_EXPR_LOCATION (stmt, loc);
115 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
122tree
123c_finish_omp_critical (location_t loc, tree body, tree name, tree clauses)
124{
125 gcc_assert (!clauses || OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_HINT);
126 if (name == NULL_TREE
127 && clauses != NULL_TREE
128 && integer_nonzerop (OMP_CLAUSE_HINT_EXPR (clauses)))
129 {
130 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 return error_mark_node;
134 }
135
136 tree stmt = make_node (OMP_CRITICAL);
137 TREE_TYPE (stmt) = void_type_node;
138 OMP_CRITICAL_BODY (stmt) = body;
139 OMP_CRITICAL_NAME (stmt) = name;
140 OMP_CRITICAL_CLAUSES (stmt) = clauses;
141 SET_EXPR_LOCATION (stmt, loc);
142 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
148tree
149c_finish_omp_ordered (location_t loc, tree clauses, tree stmt)
150{
151 tree t = make_node (OMP_ORDERED);
152 TREE_TYPE (t) = void_type_node;
153 OMP_ORDERED_BODY (t) = stmt;
154 if (!flag_openmp /* flag_openmp_simd */
155 && (OMP_CLAUSE_CODE (clauses) != OMP_CLAUSE_SIMD
156 || OMP_CLAUSE_CHAIN (clauses)))
157 clauses = build_omp_clause (loc, OMP_CLAUSE_SIMD);
158 OMP_ORDERED_CLAUSES (t) = clauses;
159 SET_EXPR_LOCATION (t, loc);
160 return add_stmt (t);
161}
162
163
164/* Complete a #pragma omp barrier construct. LOC is the location of
165 the #pragma. */
166
167void
168c_finish_omp_barrier (location_t loc)
169{
170 tree x;
171
172 x = builtin_decl_explicit (fncode: BUILT_IN_GOMP_BARRIER);
173 x = build_call_expr_loc (loc, x, 0);
174 add_stmt (x);
175}
176
177
178/* Complete a #pragma omp taskwait construct. LOC is the location of the
179 pragma. */
180
181void
182c_finish_omp_taskwait (location_t loc)
183{
184 tree x;
185
186 x = builtin_decl_explicit (fncode: BUILT_IN_GOMP_TASKWAIT);
187 x = build_call_expr_loc (loc, x, 0);
188 add_stmt (x);
189}
190
191
192/* Complete a #pragma omp taskyield construct. LOC is the location of the
193 pragma. */
194
195void
196c_finish_omp_taskyield (location_t loc)
197{
198 tree x;
199
200 x = builtin_decl_explicit (fncode: BUILT_IN_GOMP_TASKYIELD);
201 x = build_call_expr_loc (loc, x, 0);
202 add_stmt (x);
203}
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
216tree
217c_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 tree x, type, addr, pre = NULL_TREE, rtmp = NULL_TREE, vtmp = NULL_TREE;
224 HOST_WIDE_INT bitpos = 0, bitsize = 0;
225 enum tree_code orig_opcode = opcode;
226
227 if (lhs == error_mark_node || rhs == error_mark_node
228 || v == error_mark_node || lhs1 == error_mark_node
229 || 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 type = TREE_TYPE (lhs);
237 if (!INTEGRAL_TYPE_P (type)
238 && !POINTER_TYPE_P (type)
239 && !SCALAR_FLOAT_TYPE_P (type))
240 {
241 error_at (loc, "invalid expression type for %<#pragma omp atomic%>");
242 return error_mark_node;
243 }
244 if (TYPE_ATOMIC (type))
245 {
246 error_at (loc, "%<_Atomic%> expression in %<#pragma omp atomic%>");
247 return error_mark_node;
248 }
249 if (r && r != void_list_node && !INTEGRAL_TYPE_P (TREE_TYPE (r)))
250 {
251 error_at (loc, "%<#pragma omp atomic compare capture%> with non-integral "
252 "comparison result");
253 return error_mark_node;
254 }
255
256 if (opcode == RDIV_EXPR)
257 opcode = TRUNC_DIV_EXPR;
258
259 /* ??? Validate that rhs does not overlap lhs. */
260 tree blhs = NULL;
261 if (TREE_CODE (lhs) == COMPONENT_REF
262 && TREE_CODE (TREE_OPERAND (lhs, 1)) == FIELD_DECL
263 && DECL_C_BIT_FIELD (TREE_OPERAND (lhs, 1))
264 && DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (lhs, 1)))
265 {
266 tree field = TREE_OPERAND (lhs, 1);
267 tree repr = DECL_BIT_FIELD_REPRESENTATIVE (field);
268 if (tree_fits_uhwi_p (DECL_FIELD_OFFSET (field))
269 && tree_fits_uhwi_p (DECL_FIELD_OFFSET (repr)))
270 bitpos = (tree_to_uhwi (DECL_FIELD_OFFSET (field))
271 - tree_to_uhwi (DECL_FIELD_OFFSET (repr))) * BITS_PER_UNIT;
272 else
273 bitpos = 0;
274 bitpos += (tree_to_uhwi (DECL_FIELD_BIT_OFFSET (field))
275 - tree_to_uhwi (DECL_FIELD_BIT_OFFSET (repr)));
276 gcc_assert (tree_fits_shwi_p (DECL_SIZE (field)));
277 bitsize = tree_to_shwi (DECL_SIZE (field));
278 blhs = lhs;
279 type = TREE_TYPE (repr);
280 lhs = build3 (COMPONENT_REF, TREE_TYPE (repr), TREE_OPERAND (lhs, 0),
281 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 addr = build_unary_op (loc, ADDR_EXPR, lhs, false);
287 if (addr == error_mark_node)
288 return error_mark_node;
289 if (!test)
290 addr = save_expr (addr);
291 if (!test
292 && TREE_CODE (addr) != SAVE_EXPR
293 && (TREE_CODE (addr) != ADDR_EXPR
294 || !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 tree var = create_tmp_var_raw (TREE_TYPE (addr));
299 DECL_CONTEXT (var) = current_function_decl;
300 addr = build4 (TARGET_EXPR, TREE_TYPE (addr), var, addr, NULL, NULL);
301 }
302 tree orig_lhs = lhs;
303 lhs = build_indirect_ref (loc, addr, RO_NULL);
304 tree new_lhs = lhs;
305
306 if (code == OMP_ATOMIC_READ)
307 {
308 x = build1 (OMP_ATOMIC_READ, type, addr);
309 SET_EXPR_LOCATION (x, loc);
310 OMP_ATOMIC_MEMORY_ORDER (x) = memory_order;
311 gcc_assert (!weak);
312 if (blhs)
313 x = build3_loc (loc, code: BIT_FIELD_REF, TREE_TYPE (blhs), arg0: x,
314 bitsize_int (bitsize), bitsize_int (bitpos));
315 return build_modify_expr (loc, v, NULL_TREE, NOP_EXPR,
316 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 if (blhs)
323 {
324 lhs = build3_loc (loc, code: BIT_FIELD_REF, TREE_TYPE (blhs), arg0: lhs,
325 bitsize_int (bitsize), bitsize_int (bitpos));
326 if (opcode == COND_EXPR)
327 {
328 bool save = in_late_binary_op;
329 in_late_binary_op = true;
330 std::swap (a&: rhs, b&: rhs1);
331 rhs1 = build_binary_op (loc, EQ_EXPR, lhs, rhs1, true);
332 in_late_binary_op = save;
333 }
334 else if (swapped)
335 rhs = build_binary_op (loc, opcode, rhs, lhs, true);
336 else if (opcode != NOP_EXPR)
337 rhs = build_binary_op (loc, opcode, lhs, rhs, true);
338 opcode = NOP_EXPR;
339 }
340 else if (opcode == COND_EXPR)
341 {
342 bool save = in_late_binary_op;
343 in_late_binary_op = true;
344 std::swap (a&: rhs, b&: rhs1);
345 rhs1 = build_binary_op (loc, EQ_EXPR, lhs, rhs1, true);
346 in_late_binary_op = save;
347 opcode = NOP_EXPR;
348 }
349 else if (swapped)
350 {
351 rhs = build_binary_op (loc, opcode, rhs, lhs, true);
352 opcode = NOP_EXPR;
353 }
354 bool save = in_late_binary_op;
355 in_late_binary_op = true;
356 if ((opcode == MIN_EXPR || opcode == MAX_EXPR)
357 && build_binary_op (loc, LT_EXPR, blhs ? blhs : lhs, rhs,
358 true) == error_mark_node)
359 x = error_mark_node;
360 else
361 x = build_modify_expr (loc, blhs ? blhs : lhs, NULL_TREE, opcode,
362 loc, rhs, NULL_TREE);
363 in_late_binary_op = save;
364 if (x == error_mark_node)
365 return error_mark_node;
366 if (TREE_CODE (x) == COMPOUND_EXPR)
367 {
368 pre = TREE_OPERAND (x, 0);
369 gcc_assert (TREE_CODE (pre) == SAVE_EXPR || tree_invariant_p (pre));
370 x = TREE_OPERAND (x, 1);
371 }
372 gcc_assert (TREE_CODE (x) == MODIFY_EXPR);
373 rhs = TREE_OPERAND (x, 1);
374
375 if (blhs)
376 rhs = build3_loc (loc, code: BIT_INSERT_EXPR, type, arg0: new_lhs,
377 arg1: rhs, bitsize_int (bitpos));
378 if (orig_opcode == COND_EXPR)
379 {
380 if (error_operand_p (t: rhs1))
381 return error_mark_node;
382 gcc_assert (TREE_CODE (rhs1) == EQ_EXPR);
383 tree cmptype = TREE_TYPE (TREE_OPERAND (rhs1, 0));
384 if (SCALAR_FLOAT_TYPE_P (cmptype) && !test)
385 {
386 bool clear_padding = false;
387 HOST_WIDE_INT non_padding_start = 0;
388 HOST_WIDE_INT non_padding_end = 0;
389 if (BITS_PER_UNIT == 8
390 && CHAR_BIT == 8
391 && clear_padding_type_may_have_padding_p (cmptype))
392 {
393 HOST_WIDE_INT sz = int_size_in_bytes (cmptype), i;
394 gcc_assert (sz > 0);
395 unsigned char *buf = XALLOCAVEC (unsigned char, sz);
396 memset (s: buf, c: ~0, n: sz);
397 clear_type_padding_in_mask (cmptype, buf);
398 for (i = 0; i < sz; i++)
399 if (buf[i] != (unsigned char) ~0)
400 {
401 clear_padding = true;
402 break;
403 }
404 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 if (i == 0)
412 {
413 for (i = 0; i < sz; i++)
414 if (buf[i] != 0)
415 break;
416 if (i < sz && buf[i] == (unsigned char) ~0)
417 {
418 non_padding_start = i;
419 for (; i < sz; i++)
420 if (buf[i] != (unsigned char) ~0)
421 break;
422 }
423 else
424 i = 0;
425 }
426 if (i != 0)
427 {
428 non_padding_end = i;
429 for (; i < sz; i++)
430 if (buf[i] != 0)
431 {
432 non_padding_start = 0;
433 non_padding_end = 0;
434 break;
435 }
436 }
437 }
438 }
439 tree inttype = NULL_TREE;
440 if (!clear_padding && tree_fits_uhwi_p (TYPE_SIZE (cmptype)))
441 {
442 HOST_WIDE_INT prec = tree_to_uhwi (TYPE_SIZE (cmptype));
443 inttype = c_common_type_for_size (prec, 1);
444 if (inttype
445 && (!tree_int_cst_equal (TYPE_SIZE (cmptype),
446 TYPE_SIZE (inttype))
447 || TYPE_PRECISION (inttype) != prec))
448 inttype = NULL_TREE;
449 }
450 if (inttype)
451 {
452 TREE_OPERAND (rhs1, 0)
453 = build1_loc (loc, code: VIEW_CONVERT_EXPR, type: inttype,
454 TREE_OPERAND (rhs1, 0));
455 TREE_OPERAND (rhs1, 1)
456 = build1_loc (loc, code: VIEW_CONVERT_EXPR, type: inttype,
457 TREE_OPERAND (rhs1, 1));
458 }
459 else
460 {
461 tree pcmptype = build_pointer_type (cmptype);
462 tree tmp1 = create_tmp_var_raw (cmptype);
463 TREE_ADDRESSABLE (tmp1) = 1;
464 DECL_CONTEXT (tmp1) = current_function_decl;
465 tmp1 = build4 (TARGET_EXPR, cmptype, tmp1,
466 TREE_OPERAND (rhs1, 0), NULL, NULL);
467 tmp1 = build1 (ADDR_EXPR, pcmptype, tmp1);
468 tree tmp2 = create_tmp_var_raw (cmptype);
469 TREE_ADDRESSABLE (tmp2) = 1;
470 DECL_CONTEXT (tmp2) = current_function_decl;
471 tmp2 = build4 (TARGET_EXPR, cmptype, tmp2,
472 TREE_OPERAND (rhs1, 1), NULL, NULL);
473 tmp2 = build1 (ADDR_EXPR, pcmptype, tmp2);
474 if (non_padding_start)
475 {
476 tmp1 = build2 (POINTER_PLUS_EXPR, pcmptype, tmp1,
477 size_int (non_padding_start));
478 tmp2 = build2 (POINTER_PLUS_EXPR, pcmptype, tmp2,
479 size_int (non_padding_start));
480 }
481 tree fndecl = builtin_decl_explicit (fncode: BUILT_IN_MEMCMP);
482 rhs1 = build_call_expr_loc (loc, fndecl, 3, tmp1, tmp2,
483 non_padding_end
484 ? size_int (non_padding_end
485 - non_padding_start)
486 : TYPE_SIZE_UNIT (cmptype));
487 rhs1 = build2 (EQ_EXPR, boolean_type_node, rhs1,
488 integer_zero_node);
489 if (clear_padding && non_padding_end == 0)
490 {
491 fndecl = builtin_decl_explicit (fncode: BUILT_IN_CLEAR_PADDING);
492 tree cp1 = build_call_expr_loc (loc, fndecl, 1, tmp1);
493 tree cp2 = build_call_expr_loc (loc, fndecl, 1, tmp2);
494 rhs1 = omit_two_operands_loc (loc, boolean_type_node,
495 rhs1, cp2, cp1);
496 }
497 }
498 }
499 if (r && test)
500 rtmp = rhs1;
501 else if (r)
502 {
503 tree var = create_tmp_var_raw (boolean_type_node);
504 DECL_CONTEXT (var) = current_function_decl;
505 rtmp = build4 (TARGET_EXPR, boolean_type_node, var,
506 boolean_false_node, NULL, NULL);
507 save = in_late_binary_op;
508 in_late_binary_op = true;
509 x = build_modify_expr (loc, var, NULL_TREE, NOP_EXPR,
510 loc, rhs1, NULL_TREE);
511 in_late_binary_op = save;
512 if (x == error_mark_node)
513 return error_mark_node;
514 gcc_assert (TREE_CODE (x) == MODIFY_EXPR
515 && TREE_OPERAND (x, 0) == var);
516 TREE_OPERAND (x, 0) = rtmp;
517 rhs1 = omit_one_operand_loc (loc, boolean_type_node, x, rtmp);
518 }
519 rhs = build3_loc (loc, code: COND_EXPR, type, arg0: rhs1, arg1: rhs, arg2: new_lhs);
520 rhs1 = NULL_TREE;
521 }
522
523 /* Punt the actual generation of atomic operations to common code. */
524 if (code == OMP_ATOMIC)
525 type = void_type_node;
526 x = build2 (code, type, addr, rhs);
527 SET_EXPR_LOCATION (x, loc);
528 OMP_ATOMIC_MEMORY_ORDER (x) = memory_order;
529 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 if (rhs1
534 && VAR_P (rhs1)
535 && VAR_P (orig_lhs)
536 && rhs1 != orig_lhs
537 && !test)
538 {
539 if (code == OMP_ATOMIC)
540 error_at (loc, "%<#pragma omp atomic update%> uses two different "
541 "variables for memory");
542 else
543 error_at (loc, "%<#pragma omp atomic capture%> uses two different "
544 "variables for memory");
545 return error_mark_node;
546 }
547
548 if (lhs1
549 && lhs1 != orig_lhs
550 && TREE_CODE (lhs1) == COMPONENT_REF
551 && TREE_CODE (TREE_OPERAND (lhs1, 1)) == FIELD_DECL
552 && DECL_C_BIT_FIELD (TREE_OPERAND (lhs1, 1))
553 && DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (lhs1, 1)))
554 {
555 tree field = TREE_OPERAND (lhs1, 1);
556 tree repr = DECL_BIT_FIELD_REPRESENTATIVE (field);
557 lhs1 = build3 (COMPONENT_REF, TREE_TYPE (repr), TREE_OPERAND (lhs1, 0),
558 repr, TREE_OPERAND (lhs1, 2));
559 }
560 if (rhs1
561 && rhs1 != orig_lhs
562 && TREE_CODE (rhs1) == COMPONENT_REF
563 && TREE_CODE (TREE_OPERAND (rhs1, 1)) == FIELD_DECL
564 && DECL_C_BIT_FIELD (TREE_OPERAND (rhs1, 1))
565 && DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (rhs1, 1)))
566 {
567 tree field = TREE_OPERAND (rhs1, 1);
568 tree repr = DECL_BIT_FIELD_REPRESENTATIVE (field);
569 rhs1 = build3 (COMPONENT_REF, TREE_TYPE (repr), TREE_OPERAND (rhs1, 0),
570 repr, TREE_OPERAND (rhs1, 2));
571 }
572
573 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 if (lhs1 && VAR_P (lhs1) && VAR_P (orig_lhs))
578 {
579 if (lhs1 != orig_lhs && !test)
580 {
581 error_at (loc, "%<#pragma omp atomic capture%> uses two "
582 "different variables for memory");
583 return error_mark_node;
584 }
585 }
586 if (blhs)
587 x = build3_loc (loc, code: BIT_FIELD_REF, TREE_TYPE (blhs), arg0: x,
588 bitsize_int (bitsize), bitsize_int (bitpos));
589 if (r && !test)
590 {
591 vtmp = create_tmp_var_raw (TREE_TYPE (x));
592 DECL_CONTEXT (vtmp) = current_function_decl;
593 }
594 else
595 vtmp = v;
596 x = build_modify_expr (loc, vtmp, NULL_TREE, NOP_EXPR,
597 loc, x, NULL_TREE);
598 if (x == error_mark_node)
599 return error_mark_node;
600 type = TREE_TYPE (x);
601 if (r && !test)
602 {
603 vtmp = build4 (TARGET_EXPR, TREE_TYPE (vtmp), vtmp,
604 build_zero_cst (TREE_TYPE (vtmp)), NULL, NULL);
605 gcc_assert (TREE_CODE (x) == MODIFY_EXPR
606 && TREE_OPERAND (x, 0) == TARGET_EXPR_SLOT (vtmp));
607 TREE_OPERAND (x, 0) = vtmp;
608 }
609 if (rhs1 && rhs1 != orig_lhs)
610 {
611 tree rhs1addr = build_unary_op (loc, ADDR_EXPR, rhs1, false);
612 if (rhs1addr == error_mark_node)
613 return error_mark_node;
614 x = omit_one_operand_loc (loc, type, x, rhs1addr);
615 }
616 if (lhs1 && lhs1 != orig_lhs)
617 {
618 tree lhs1addr = build_unary_op (loc, ADDR_EXPR, lhs1, false);
619 if (lhs1addr == error_mark_node)
620 return error_mark_node;
621 if (code == OMP_ATOMIC_CAPTURE_OLD)
622 x = omit_one_operand_loc (loc, type, x, lhs1addr);
623 else
624 {
625 if (!test)
626 x = save_expr (x);
627 x = omit_two_operands_loc (loc, type, x, x, lhs1addr);
628 }
629 }
630 }
631 else if (rhs1 && rhs1 != orig_lhs)
632 {
633 tree rhs1addr = build_unary_op (loc, ADDR_EXPR, rhs1, false);
634 if (rhs1addr == error_mark_node)
635 return error_mark_node;
636 x = omit_one_operand_loc (loc, type, x, rhs1addr);
637 }
638
639 if (pre)
640 x = omit_one_operand_loc (loc, type, x, pre);
641 if (r && r != void_list_node)
642 {
643 in_late_binary_op = true;
644 tree x2 = build_modify_expr (loc, r, NULL_TREE, NOP_EXPR,
645 loc, rtmp, NULL_TREE);
646 in_late_binary_op = save;
647 if (x2 == error_mark_node)
648 return error_mark_node;
649 x = omit_one_operand_loc (loc, TREE_TYPE (x2), x2, x);
650 }
651 if (v && vtmp != v)
652 {
653 in_late_binary_op = true;
654 tree x2 = build_modify_expr (loc, v, NULL_TREE, NOP_EXPR,
655 loc, vtmp, NULL_TREE);
656 in_late_binary_op = save;
657 if (x2 == error_mark_node)
658 return error_mark_node;
659 x2 = build3_loc (loc, code: COND_EXPR, void_type_node, arg0: rtmp,
660 void_node, arg2: x2);
661 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_depend_t. */
668
669bool
670c_omp_depend_t_p (tree type)
671{
672 type = TYPE_MAIN_VARIANT (type);
673 return (TREE_CODE (type) == RECORD_TYPE
674 && TYPE_NAME (type)
675 && ((TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
676 ? DECL_NAME (TYPE_NAME (type)) : TYPE_NAME (type))
677 == get_identifier ("omp_depend_t"))
678 && TYPE_FILE_SCOPE_P (type)
679 && COMPLETE_TYPE_P (type)
680 && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
681 && !compare_tree_int (TYPE_SIZE (type),
682 2 * tree_to_uhwi (TYPE_SIZE (ptr_type_node))));
683}
684
685
686/* Complete a #pragma omp depobj construct. LOC is the location of the
687 #pragma. */
688
689void
690c_finish_omp_depobj (location_t loc, tree depobj,
691 enum omp_clause_depend_kind kind, tree clause)
692{
693 tree t = NULL_TREE;
694 if (!error_operand_p (t: depobj))
695 {
696 if (!c_omp_depend_t_p (TREE_TYPE (depobj)))
697 {
698 error_at (EXPR_LOC_OR_LOC (depobj, loc),
699 "type of %<depobj%> expression is not %<omp_depend_t%>");
700 depobj = error_mark_node;
701 }
702 else if (TYPE_READONLY (TREE_TYPE (depobj)))
703 {
704 error_at (EXPR_LOC_OR_LOC (depobj, loc),
705 "%<const%> qualified %<depobj%> expression");
706 depobj = error_mark_node;
707 }
708 }
709 else
710 depobj = error_mark_node;
711
712 if (clause == error_mark_node)
713 return;
714
715 if (clause)
716 {
717 gcc_assert (TREE_CODE (clause) == OMP_CLAUSE);
718 if (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_DOACROSS)
719 {
720 error_at (OMP_CLAUSE_LOCATION (clause),
721 "%<depend(%s)%> is only allowed in %<omp ordered%>",
722 OMP_CLAUSE_DOACROSS_KIND (clause)
723 == OMP_CLAUSE_DOACROSS_SOURCE
724 ? "source" : "sink");
725 return;
726 }
727 gcc_assert (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_DEPEND);
728 if (OMP_CLAUSE_CHAIN (clause))
729 error_at (OMP_CLAUSE_LOCATION (clause),
730 "more than one locator in %<depend%> clause on %<depobj%> "
731 "construct");
732 switch (OMP_CLAUSE_DEPEND_KIND (clause))
733 {
734 case OMP_CLAUSE_DEPEND_DEPOBJ:
735 error_at (OMP_CLAUSE_LOCATION (clause),
736 "%<depobj%> dependence type specified in %<depend%> "
737 "clause on %<depobj%> construct");
738 return;
739 case OMP_CLAUSE_DEPEND_IN:
740 case OMP_CLAUSE_DEPEND_OUT:
741 case OMP_CLAUSE_DEPEND_INOUT:
742 case OMP_CLAUSE_DEPEND_MUTEXINOUTSET:
743 case OMP_CLAUSE_DEPEND_INOUTSET:
744 kind = OMP_CLAUSE_DEPEND_KIND (clause);
745 t = OMP_CLAUSE_DECL (clause);
746 gcc_assert (t);
747 if (TREE_CODE (t) == TREE_LIST
748 && TREE_PURPOSE (t)
749 && TREE_CODE (TREE_PURPOSE (t)) == TREE_VEC)
750 {
751 error_at (OMP_CLAUSE_LOCATION (clause),
752 "%<iterator%> modifier may not be specified on "
753 "%<depobj%> construct");
754 return;
755 }
756 if (TREE_CODE (t) == COMPOUND_EXPR)
757 {
758 tree t1 = build_fold_addr_expr (TREE_OPERAND (t, 1));
759 t = build2 (COMPOUND_EXPR, TREE_TYPE (t1), TREE_OPERAND (t, 0),
760 t1);
761 }
762 else if (t != null_pointer_node)
763 t = build_fold_addr_expr (t);
764 break;
765 default:
766 gcc_unreachable ();
767 }
768 }
769 else
770 gcc_assert (kind != OMP_CLAUSE_DEPEND_INVALID);
771
772 if (depobj == error_mark_node)
773 return;
774
775 depobj = build_fold_addr_expr_loc (EXPR_LOC_OR_LOC (depobj, loc), depobj);
776 tree dtype
777 = build_pointer_type_for_mode (ptr_type_node, TYPE_MODE (ptr_type_node),
778 true);
779 depobj = fold_convert (dtype, depobj);
780 tree r;
781 if (clause)
782 {
783 depobj = save_expr (depobj);
784 r = build_indirect_ref (loc, depobj, RO_UNARY_STAR);
785 add_stmt (build2 (MODIFY_EXPR, void_type_node, r, t));
786 }
787 int k;
788 switch (kind)
789 {
790 case OMP_CLAUSE_DEPEND_IN:
791 k = GOMP_DEPEND_IN;
792 break;
793 case OMP_CLAUSE_DEPEND_OUT:
794 k = GOMP_DEPEND_OUT;
795 break;
796 case OMP_CLAUSE_DEPEND_INOUT:
797 k = GOMP_DEPEND_INOUT;
798 break;
799 case OMP_CLAUSE_DEPEND_MUTEXINOUTSET:
800 k = GOMP_DEPEND_MUTEXINOUTSET;
801 break;
802 case OMP_CLAUSE_DEPEND_INOUTSET:
803 k = GOMP_DEPEND_INOUTSET;
804 break;
805 case OMP_CLAUSE_DEPEND_LAST:
806 k = -1;
807 break;
808 default:
809 gcc_unreachable ();
810 }
811 t = build_int_cst (ptr_type_node, k);
812 depobj = build2_loc (loc, code: POINTER_PLUS_EXPR, TREE_TYPE (depobj), arg0: depobj,
813 TYPE_SIZE_UNIT (ptr_type_node));
814 r = build_indirect_ref (loc, depobj, RO_UNARY_STAR);
815 add_stmt (build2 (MODIFY_EXPR, void_type_node, r, t));
816}
817
818
819/* Complete a #pragma omp flush construct. We don't do anything with
820 the variable list that the syntax allows. LOC is the location of
821 the #pragma. */
822
823void
824c_finish_omp_flush (location_t loc, int mo)
825{
826 tree x;
827
828 if (mo == MEMMODEL_LAST || mo == MEMMODEL_SEQ_CST)
829 {
830 x = builtin_decl_explicit (fncode: BUILT_IN_SYNC_SYNCHRONIZE);
831 x = build_call_expr_loc (loc, x, 0);
832 }
833 else
834 {
835 x = builtin_decl_explicit (fncode: BUILT_IN_ATOMIC_THREAD_FENCE);
836 x = build_call_expr_loc (loc, x, 1,
837 build_int_cst (integer_type_node, mo));
838 }
839 add_stmt (x);
840}
841
842
843/* Check and canonicalize OMP_FOR increment expression.
844 Helper function for c_finish_omp_for. */
845
846static tree
847check_omp_for_incr_expr (location_t loc, tree exp, tree decl)
848{
849 tree t;
850
851 if (!INTEGRAL_TYPE_P (TREE_TYPE (exp))
852 || TYPE_PRECISION (TREE_TYPE (exp)) < TYPE_PRECISION (TREE_TYPE (decl)))
853 return error_mark_node;
854
855 if (exp == decl)
856 return build_int_cst (TREE_TYPE (exp), 0);
857
858 switch (TREE_CODE (exp))
859 {
860 CASE_CONVERT:
861 t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 0), decl);
862 if (t != error_mark_node)
863 return fold_convert_loc (loc, TREE_TYPE (exp), t);
864 break;
865 case MINUS_EXPR:
866 t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 0), decl);
867 if (t != error_mark_node)
868 return fold_build2_loc (loc, MINUS_EXPR,
869 TREE_TYPE (exp), t, TREE_OPERAND (exp, 1));
870 break;
871 case PLUS_EXPR:
872 t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 0), decl);
873 if (t != error_mark_node)
874 return fold_build2_loc (loc, PLUS_EXPR,
875 TREE_TYPE (exp), t, TREE_OPERAND (exp, 1));
876 t = check_omp_for_incr_expr (loc, TREE_OPERAND (exp, 1), decl);
877 if (t != error_mark_node)
878 return fold_build2_loc (loc, PLUS_EXPR,
879 TREE_TYPE (exp), TREE_OPERAND (exp, 0), t);
880 break;
881 case COMPOUND_EXPR:
882 {
883 /* cp_build_modify_expr forces preevaluation of the RHS to make
884 sure that it is evaluated before the lvalue-rvalue conversion
885 is applied to the LHS. Reconstruct the original expression. */
886 tree op0 = TREE_OPERAND (exp, 0);
887 if (TREE_CODE (op0) == TARGET_EXPR
888 && !VOID_TYPE_P (TREE_TYPE (op0)))
889 {
890 tree op1 = TREE_OPERAND (exp, 1);
891 tree temp = TARGET_EXPR_SLOT (op0);
892 if (BINARY_CLASS_P (op1)
893 && TREE_OPERAND (op1, 1) == temp)
894 {
895 op1 = copy_node (op1);
896 TREE_OPERAND (op1, 1) = TARGET_EXPR_INITIAL (op0);
897 return check_omp_for_incr_expr (loc, exp: op1, decl);
898 }
899 }
900 break;
901 }
902 default:
903 break;
904 }
905
906 return error_mark_node;
907}
908
909/* If the OMP_FOR increment expression in INCR is of pointer type,
910 canonicalize it into an expression handled by gimplify_omp_for()
911 and return it. DECL is the iteration variable. */
912
913static tree
914c_omp_for_incr_canonicalize_ptr (location_t loc, tree decl, tree incr)
915{
916 if (POINTER_TYPE_P (TREE_TYPE (decl))
917 && TREE_OPERAND (incr, 1))
918 {
919 tree t = fold_convert_loc (loc,
920 sizetype, TREE_OPERAND (incr, 1));
921
922 if (TREE_CODE (incr) == POSTDECREMENT_EXPR
923 || TREE_CODE (incr) == PREDECREMENT_EXPR)
924 t = fold_build1_loc (loc, NEGATE_EXPR, sizetype, t);
925 t = fold_build_pointer_plus (decl, t);
926 incr = build2 (MODIFY_EXPR, void_type_node, decl, t);
927 }
928 return incr;
929}
930
931/* Validate and generate OMP_FOR.
932 DECLV is a vector of iteration variables, for each collapsed loop.
933
934 ORIG_DECLV, if non-NULL, is a vector with the original iteration
935 variables (prior to any transformations, by say, C++ iterators).
936
937 INITV, CONDV and INCRV are vectors containing initialization
938 expressions, controlling predicates and increment expressions.
939 BODY is the body of the loop and PRE_BODY statements that go before
940 the loop. */
941
942tree
943c_finish_omp_for (location_t locus, enum tree_code code, tree declv,
944 tree orig_declv, tree initv, tree condv, tree incrv,
945 tree body, tree pre_body, bool final_p)
946{
947 location_t elocus;
948 bool fail = false;
949 int i;
950
951 gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (initv));
952 gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (condv));
953 gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (incrv));
954 for (i = 0; i < TREE_VEC_LENGTH (declv); i++)
955 {
956 tree decl = TREE_VEC_ELT (declv, i);
957 tree init = TREE_VEC_ELT (initv, i);
958 tree cond = TREE_VEC_ELT (condv, i);
959 tree incr = TREE_VEC_ELT (incrv, i);
960
961 elocus = locus;
962 if (EXPR_HAS_LOCATION (init))
963 elocus = EXPR_LOCATION (init);
964
965 /* Validate the iteration variable. */
966 if (!INTEGRAL_TYPE_P (TREE_TYPE (decl))
967 && TREE_CODE (TREE_TYPE (decl)) != POINTER_TYPE)
968 {
969 error_at (elocus, "invalid type for iteration variable %qE", decl);
970 fail = true;
971 }
972 else if (TYPE_ATOMIC (TREE_TYPE (decl)))
973 {
974 error_at (elocus, "%<_Atomic%> iteration variable %qE", decl);
975 fail = true;
976 /* _Atomic iterator confuses stuff too much, so we risk ICE
977 trying to diagnose it further. */
978 continue;
979 }
980
981 /* In the case of "for (int i = 0...)", init will be a decl. It should
982 have a DECL_INITIAL that we can turn into an assignment. */
983 if (init == decl)
984 {
985 elocus = DECL_SOURCE_LOCATION (decl);
986
987 init = DECL_INITIAL (decl);
988 if (init == NULL)
989 {
990 error_at (elocus, "%qE is not initialized", decl);
991 init = integer_zero_node;
992 fail = true;
993 }
994 DECL_INITIAL (decl) = NULL_TREE;
995
996 init = build_modify_expr (elocus, decl, NULL_TREE, NOP_EXPR,
997 /* FIXME diagnostics: This should
998 be the location of the INIT. */
999 elocus,
1000 init,
1001 NULL_TREE);
1002 }
1003 if (init != error_mark_node)
1004 {
1005 gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
1006 gcc_assert (TREE_OPERAND (init, 0) == decl);
1007 }
1008
1009 if (cond == NULL_TREE)
1010 {
1011 error_at (elocus, "missing controlling predicate");
1012 fail = true;
1013 }
1014 else
1015 {
1016 bool cond_ok = false;
1017
1018 /* E.g. C sizeof (vla) could add COMPOUND_EXPRs with
1019 evaluation of the vla VAR_DECL. We need to readd
1020 them to the non-decl operand. See PR45784. */
1021 while (TREE_CODE (cond) == COMPOUND_EXPR)
1022 cond = TREE_OPERAND (cond, 1);
1023
1024 if (EXPR_HAS_LOCATION (cond))
1025 elocus = EXPR_LOCATION (cond);
1026
1027 if (TREE_CODE (cond) == LT_EXPR
1028 || TREE_CODE (cond) == LE_EXPR
1029 || TREE_CODE (cond) == GT_EXPR
1030 || TREE_CODE (cond) == GE_EXPR
1031 || TREE_CODE (cond) == NE_EXPR
1032 || TREE_CODE (cond) == EQ_EXPR)
1033 {
1034 tree op0 = TREE_OPERAND (cond, 0);
1035 tree op1 = TREE_OPERAND (cond, 1);
1036
1037 /* 2.5.1. The comparison in the condition is computed in
1038 the type of DECL, otherwise the behavior is undefined.
1039
1040 For example:
1041 long n; int i;
1042 i < n;
1043
1044 according to ISO will be evaluated as:
1045 (long)i < n;
1046
1047 We want to force:
1048 i < (int)n; */
1049 if (TREE_CODE (op0) == NOP_EXPR
1050 && decl == TREE_OPERAND (op0, 0))
1051 {
1052 TREE_OPERAND (cond, 0) = TREE_OPERAND (op0, 0);
1053 TREE_OPERAND (cond, 1)
1054 = fold_build1_loc (elocus, NOP_EXPR, TREE_TYPE (decl),
1055 TREE_OPERAND (cond, 1));
1056 }
1057 else if (TREE_CODE (op1) == NOP_EXPR
1058 && decl == TREE_OPERAND (op1, 0))
1059 {
1060 TREE_OPERAND (cond, 1) = TREE_OPERAND (op1, 0);
1061 TREE_OPERAND (cond, 0)
1062 = fold_build1_loc (elocus, NOP_EXPR, TREE_TYPE (decl),
1063 TREE_OPERAND (cond, 0));
1064 }
1065
1066 if (decl == TREE_OPERAND (cond, 0))
1067 cond_ok = true;
1068 else if (decl == TREE_OPERAND (cond, 1))
1069 {
1070 TREE_SET_CODE (cond,
1071 swap_tree_comparison (TREE_CODE (cond)));
1072 TREE_OPERAND (cond, 1) = TREE_OPERAND (cond, 0);
1073 TREE_OPERAND (cond, 0) = decl;
1074 cond_ok = true;
1075 }
1076
1077 if (TREE_CODE (cond) == NE_EXPR
1078 || TREE_CODE (cond) == EQ_EXPR)
1079 {
1080 if (!INTEGRAL_TYPE_P (TREE_TYPE (decl)))
1081 {
1082 if (code == OACC_LOOP || TREE_CODE (cond) == EQ_EXPR)
1083 cond_ok = false;
1084 }
1085 else if (operand_equal_p (TREE_OPERAND (cond, 1),
1086 TYPE_MIN_VALUE (TREE_TYPE (decl)),
1087 flags: 0))
1088 TREE_SET_CODE (cond, TREE_CODE (cond) == NE_EXPR
1089 ? GT_EXPR : LE_EXPR);
1090 else if (operand_equal_p (TREE_OPERAND (cond, 1),
1091 TYPE_MAX_VALUE (TREE_TYPE (decl)),
1092 flags: 0))
1093 TREE_SET_CODE (cond, TREE_CODE (cond) == NE_EXPR
1094 ? LT_EXPR : GE_EXPR);
1095 else if (code == OACC_LOOP || TREE_CODE (cond) == EQ_EXPR)
1096 cond_ok = false;
1097 }
1098
1099 if (cond_ok && TREE_VEC_ELT (condv, i) != cond)
1100 {
1101 tree ce = NULL_TREE, *pce = &ce;
1102 tree type = TREE_TYPE (TREE_OPERAND (cond, 1));
1103 for (tree c = TREE_VEC_ELT (condv, i); c != cond;
1104 c = TREE_OPERAND (c, 1))
1105 {
1106 *pce = build2 (COMPOUND_EXPR, type, TREE_OPERAND (c, 0),
1107 TREE_OPERAND (cond, 1));
1108 pce = &TREE_OPERAND (*pce, 1);
1109 }
1110 TREE_OPERAND (cond, 1) = ce;
1111 TREE_VEC_ELT (condv, i) = cond;
1112 }
1113 }
1114
1115 if (!cond_ok)
1116 {
1117 error_at (elocus, "invalid controlling predicate");
1118 fail = true;
1119 }
1120 }
1121
1122 if (incr == NULL_TREE)
1123 {
1124 error_at (elocus, "missing increment expression");
1125 fail = true;
1126 }
1127 else
1128 {
1129 bool incr_ok = false;
1130
1131 if (EXPR_HAS_LOCATION (incr))
1132 elocus = EXPR_LOCATION (incr);
1133
1134 /* Check all the valid increment expressions: v++, v--, ++v, --v,
1135 v = v + incr, v = incr + v and v = v - incr. */
1136 switch (TREE_CODE (incr))
1137 {
1138 case POSTINCREMENT_EXPR:
1139 case PREINCREMENT_EXPR:
1140 case POSTDECREMENT_EXPR:
1141 case PREDECREMENT_EXPR:
1142 if (TREE_OPERAND (incr, 0) != decl)
1143 break;
1144
1145 incr_ok = true;
1146 if (!fail
1147 && TREE_CODE (cond) == NE_EXPR
1148 && TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
1149 && TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl)))
1150 && (TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl))))
1151 != INTEGER_CST))
1152 {
1153 /* For pointer to VLA, transform != into < or >
1154 depending on whether incr is increment or decrement. */
1155 if (TREE_CODE (incr) == PREINCREMENT_EXPR
1156 || TREE_CODE (incr) == POSTINCREMENT_EXPR)
1157 TREE_SET_CODE (cond, LT_EXPR);
1158 else
1159 TREE_SET_CODE (cond, GT_EXPR);
1160 }
1161 incr = c_omp_for_incr_canonicalize_ptr (loc: elocus, decl, incr);
1162 break;
1163
1164 case COMPOUND_EXPR:
1165 if (TREE_CODE (TREE_OPERAND (incr, 0)) != SAVE_EXPR
1166 || TREE_CODE (TREE_OPERAND (incr, 1)) != MODIFY_EXPR)
1167 break;
1168 incr = TREE_OPERAND (incr, 1);
1169 /* FALLTHRU */
1170 case MODIFY_EXPR:
1171 if (TREE_OPERAND (incr, 0) != decl)
1172 break;
1173 if (TREE_OPERAND (incr, 1) == decl)
1174 break;
1175 if (TREE_CODE (TREE_OPERAND (incr, 1)) == PLUS_EXPR
1176 && (TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl
1177 || TREE_OPERAND (TREE_OPERAND (incr, 1), 1) == decl))
1178 incr_ok = true;
1179 else if ((TREE_CODE (TREE_OPERAND (incr, 1)) == MINUS_EXPR
1180 || (TREE_CODE (TREE_OPERAND (incr, 1))
1181 == POINTER_PLUS_EXPR))
1182 && TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl)
1183 incr_ok = true;
1184 else
1185 {
1186 tree t = check_omp_for_incr_expr (loc: elocus,
1187 TREE_OPERAND (incr, 1),
1188 decl);
1189 if (t != error_mark_node)
1190 {
1191 incr_ok = true;
1192 t = build2 (PLUS_EXPR, TREE_TYPE (decl), decl, t);
1193 incr = build2 (MODIFY_EXPR, void_type_node, decl, t);
1194 }
1195 }
1196 if (!fail
1197 && incr_ok
1198 && TREE_CODE (cond) == NE_EXPR)
1199 {
1200 tree i = TREE_OPERAND (incr, 1);
1201 i = TREE_OPERAND (i, TREE_OPERAND (i, 0) == decl);
1202 i = c_fully_fold (i, false, NULL);
1203 if (!final_p
1204 && TREE_CODE (i) != INTEGER_CST)
1205 ;
1206 else if (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE)
1207 {
1208 tree unit
1209 = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl)));
1210 if (unit)
1211 {
1212 enum tree_code ccode = GT_EXPR;
1213 unit = c_fully_fold (unit, false, NULL);
1214 i = fold_convert (TREE_TYPE (unit), i);
1215 if (operand_equal_p (unit, i, flags: 0))
1216 ccode = LT_EXPR;
1217 if (ccode == GT_EXPR)
1218 {
1219 i = fold_unary (NEGATE_EXPR, TREE_TYPE (i), i);
1220 if (i == NULL_TREE
1221 || !operand_equal_p (unit, i, flags: 0))
1222 {
1223 error_at (elocus,
1224 "increment is not constant 1 or "
1225 "-1 for %<!=%> condition");
1226 fail = true;
1227 }
1228 }
1229 if (TREE_CODE (unit) != INTEGER_CST)
1230 /* For pointer to VLA, transform != into < or >
1231 depending on whether the pointer is
1232 incremented or decremented in each
1233 iteration. */
1234 TREE_SET_CODE (cond, ccode);
1235 }
1236 }
1237 else
1238 {
1239 if (!integer_onep (i) && !integer_minus_onep (i))
1240 {
1241 error_at (elocus,
1242 "increment is not constant 1 or -1 for"
1243 " %<!=%> condition");
1244 fail = true;
1245 }
1246 }
1247 }
1248 break;
1249
1250 default:
1251 break;
1252 }
1253 if (!incr_ok)
1254 {
1255 error_at (elocus, "invalid increment expression");
1256 fail = true;
1257 }
1258 }
1259
1260 TREE_VEC_ELT (initv, i) = init;
1261 TREE_VEC_ELT (incrv, i) = incr;
1262 }
1263
1264 if (fail)
1265 return NULL;
1266 else
1267 {
1268 tree t = make_node (code);
1269
1270 TREE_TYPE (t) = void_type_node;
1271 OMP_FOR_INIT (t) = initv;
1272 OMP_FOR_COND (t) = condv;
1273 OMP_FOR_INCR (t) = incrv;
1274 OMP_FOR_BODY (t) = body;
1275 OMP_FOR_PRE_BODY (t) = pre_body;
1276 OMP_FOR_ORIG_DECLS (t) = orig_declv;
1277
1278 SET_EXPR_LOCATION (t, locus);
1279 return t;
1280 }
1281}
1282
1283/* Type for passing data in between c_omp_check_loop_iv and
1284 c_omp_check_loop_iv_r. */
1285
1286struct c_omp_check_loop_iv_data
1287{
1288 tree declv;
1289 bool fail;
1290 bool maybe_nonrect;
1291 location_t stmt_loc;
1292 location_t expr_loc;
1293 int kind;
1294 int idx;
1295 walk_tree_lh lh;
1296 hash_set<tree> *ppset;
1297};
1298
1299/* Return -1 if DECL is not a loop iterator in loop nest D, otherwise
1300 return the index of the loop in which it is an iterator.
1301 Return TREE_VEC_LENGTH (d->declv) if it is a C++ range for iterator. */
1302
1303static int
1304c_omp_is_loop_iterator (tree decl, struct c_omp_check_loop_iv_data *d)
1305{
1306 for (int i = 0; i < TREE_VEC_LENGTH (d->declv); i++)
1307 if (decl == TREE_VEC_ELT (d->declv, i)
1308 || (TREE_CODE (TREE_VEC_ELT (d->declv, i)) == TREE_LIST
1309 && decl == TREE_PURPOSE (TREE_VEC_ELT (d->declv, i))))
1310 return i;
1311 else if (TREE_CODE (TREE_VEC_ELT (d->declv, i)) == TREE_LIST
1312 && TREE_CHAIN (TREE_VEC_ELT (d->declv, i))
1313 && (TREE_CODE (TREE_CHAIN (TREE_VEC_ELT (d->declv, i)))
1314 == TREE_VEC))
1315 for (int j = 2;
1316 j < TREE_VEC_LENGTH (TREE_CHAIN (TREE_VEC_ELT (d->declv, i))); j++)
1317 if (decl == TREE_VEC_ELT (TREE_CHAIN (TREE_VEC_ELT (d->declv, i)), j))
1318 return TREE_VEC_LENGTH (d->declv);
1319 return -1;
1320}
1321
1322/* Helper function called via walk_tree, to diagnose uses
1323 of associated loop IVs inside of lb, b and incr expressions
1324 of OpenMP loops. */
1325
1326static tree
1327c_omp_check_loop_iv_r (tree *tp, int *walk_subtrees, void *data)
1328{
1329 struct c_omp_check_loop_iv_data *d
1330 = (struct c_omp_check_loop_iv_data *) data;
1331 if (DECL_P (*tp))
1332 {
1333 int idx = c_omp_is_loop_iterator (decl: *tp, d);
1334 if (idx == -1)
1335 return NULL_TREE;
1336
1337 if ((d->kind & 4) && idx < d->idx)
1338 {
1339 d->maybe_nonrect = true;
1340 return NULL_TREE;
1341 }
1342
1343 if (d->ppset->add (k: *tp))
1344 return NULL_TREE;
1345
1346 location_t loc = d->expr_loc;
1347 if (loc == UNKNOWN_LOCATION)
1348 loc = d->stmt_loc;
1349
1350 switch (d->kind & 3)
1351 {
1352 case 0:
1353 error_at (loc, "initializer expression refers to "
1354 "iteration variable %qD", *tp);
1355 break;
1356 case 1:
1357 error_at (loc, "condition expression refers to "
1358 "iteration variable %qD", *tp);
1359 break;
1360 case 2:
1361 error_at (loc, "increment expression refers to "
1362 "iteration variable %qD", *tp);
1363 break;
1364 }
1365 d->fail = true;
1366 }
1367 else if ((d->kind & 4)
1368 && TREE_CODE (*tp) != TREE_VEC
1369 && TREE_CODE (*tp) != PLUS_EXPR
1370 && TREE_CODE (*tp) != MINUS_EXPR
1371 && TREE_CODE (*tp) != MULT_EXPR
1372 && TREE_CODE (*tp) != POINTER_PLUS_EXPR
1373 && !CONVERT_EXPR_P (*tp))
1374 {
1375 *walk_subtrees = 0;
1376 d->kind &= 3;
1377 walk_tree_1 (tp, c_omp_check_loop_iv_r, data, NULL, d->lh);
1378 d->kind |= 4;
1379 return NULL_TREE;
1380 }
1381 else if (d->ppset->add (k: *tp))
1382 *walk_subtrees = 0;
1383 /* Don't walk dtors added by C++ wrap_cleanups_r. */
1384 else if (TREE_CODE (*tp) == TRY_CATCH_EXPR
1385 && TRY_CATCH_IS_CLEANUP (*tp))
1386 {
1387 *walk_subtrees = 0;
1388 return walk_tree_1 (&TREE_OPERAND (*tp, 0), c_omp_check_loop_iv_r, data,
1389 NULL, d->lh);
1390 }
1391
1392 return NULL_TREE;
1393}
1394
1395/* Check the allowed expressions for non-rectangular loop nest lb and b
1396 expressions. Return the outer var decl referenced in the expression. */
1397
1398static tree
1399c_omp_check_nonrect_loop_iv (tree *tp, struct c_omp_check_loop_iv_data *d,
1400 walk_tree_lh lh)
1401{
1402 d->maybe_nonrect = false;
1403 if (d->fail)
1404 return NULL_TREE;
1405
1406 hash_set<tree> pset;
1407 hash_set<tree> *ppset = d->ppset;
1408 d->ppset = &pset;
1409
1410 tree t = *tp;
1411 if (TREE_CODE (t) == TREE_VEC
1412 && TREE_VEC_LENGTH (t) == 3
1413 && DECL_P (TREE_VEC_ELT (t, 0))
1414 && c_omp_is_loop_iterator (TREE_VEC_ELT (t, 0), d) >= 0)
1415 {
1416 d->kind &= 3;
1417 walk_tree_1 (&TREE_VEC_ELT (t, 1), c_omp_check_loop_iv_r, d, NULL, lh);
1418 walk_tree_1 (&TREE_VEC_ELT (t, 1), c_omp_check_loop_iv_r, d, NULL, lh);
1419 d->ppset = ppset;
1420 return d->fail ? NULL_TREE : TREE_VEC_ELT (t, 0);
1421 }
1422
1423 while (CONVERT_EXPR_P (t))
1424 t = TREE_OPERAND (t, 0);
1425
1426 tree a1 = t, a2 = integer_zero_node;
1427 bool neg_a1 = false, neg_a2 = false;
1428 switch (TREE_CODE (t))
1429 {
1430 case PLUS_EXPR:
1431 case MINUS_EXPR:
1432 a1 = TREE_OPERAND (t, 0);
1433 a2 = TREE_OPERAND (t, 1);
1434 while (CONVERT_EXPR_P (a1))
1435 a1 = TREE_OPERAND (a1, 0);
1436 while (CONVERT_EXPR_P (a2))
1437 a2 = TREE_OPERAND (a2, 0);
1438 if (DECL_P (a1) && c_omp_is_loop_iterator (decl: a1, d) >= 0)
1439 {
1440 a2 = TREE_OPERAND (t, 1);
1441 if (TREE_CODE (t) == MINUS_EXPR)
1442 neg_a2 = true;
1443 t = a1;
1444 break;
1445 }
1446 if (DECL_P (a2) && c_omp_is_loop_iterator (decl: a2, d) >= 0)
1447 {
1448 a1 = TREE_OPERAND (t, 0);
1449 if (TREE_CODE (t) == MINUS_EXPR)
1450 neg_a1 = true;
1451 t = a2;
1452 a2 = a1;
1453 break;
1454 }
1455 if (TREE_CODE (a1) == MULT_EXPR && TREE_CODE (a2) == MULT_EXPR)
1456 {
1457 tree o1 = TREE_OPERAND (a1, 0);
1458 tree o2 = TREE_OPERAND (a1, 1);
1459 while (CONVERT_EXPR_P (o1))
1460 o1 = TREE_OPERAND (o1, 0);
1461 while (CONVERT_EXPR_P (o2))
1462 o2 = TREE_OPERAND (o2, 0);
1463 if ((DECL_P (o1) && c_omp_is_loop_iterator (decl: o1, d) >= 0)
1464 || (DECL_P (o2) && c_omp_is_loop_iterator (decl: o2, d) >= 0))
1465 {
1466 a2 = TREE_OPERAND (t, 1);
1467 if (TREE_CODE (t) == MINUS_EXPR)
1468 neg_a2 = true;
1469 t = a1;
1470 break;
1471 }
1472 }
1473 if (TREE_CODE (a2) == MULT_EXPR)
1474 {
1475 a1 = TREE_OPERAND (t, 0);
1476 if (TREE_CODE (t) == MINUS_EXPR)
1477 neg_a1 = true;
1478 t = a2;
1479 a2 = a1;
1480 break;
1481 }
1482 if (TREE_CODE (a1) == MULT_EXPR)
1483 {
1484 a2 = TREE_OPERAND (t, 1);
1485 if (TREE_CODE (t) == MINUS_EXPR)
1486 neg_a2 = true;
1487 t = a1;
1488 break;
1489 }
1490 a2 = integer_zero_node;
1491 break;
1492 case POINTER_PLUS_EXPR:
1493 a1 = TREE_OPERAND (t, 0);
1494 a2 = TREE_OPERAND (t, 1);
1495 while (CONVERT_EXPR_P (a1))
1496 a1 = TREE_OPERAND (a1, 0);
1497 if (DECL_P (a1) && c_omp_is_loop_iterator (decl: a1, d) >= 0)
1498 {
1499 a2 = TREE_OPERAND (t, 1);
1500 t = a1;
1501 break;
1502 }
1503 break;
1504 default:
1505 break;
1506 }
1507
1508 a1 = integer_one_node;
1509 if (TREE_CODE (t) == MULT_EXPR)
1510 {
1511 tree o1 = TREE_OPERAND (t, 0);
1512 tree o2 = TREE_OPERAND (t, 1);
1513 while (CONVERT_EXPR_P (o1))
1514 o1 = TREE_OPERAND (o1, 0);
1515 while (CONVERT_EXPR_P (o2))
1516 o2 = TREE_OPERAND (o2, 0);
1517 if (DECL_P (o1) && c_omp_is_loop_iterator (decl: o1, d) >= 0)
1518 {
1519 a1 = TREE_OPERAND (t, 1);
1520 t = o1;
1521 }
1522 else if (DECL_P (o2) && c_omp_is_loop_iterator (decl: o2, d) >= 0)
1523 {
1524 a1 = TREE_OPERAND (t, 0);
1525 t = o2;
1526 }
1527 }
1528
1529 d->kind &= 3;
1530 tree ret = NULL_TREE;
1531 if (DECL_P (t) && c_omp_is_loop_iterator (decl: t, d) >= 0)
1532 {
1533 location_t loc = d->expr_loc;
1534 if (loc == UNKNOWN_LOCATION)
1535 loc = d->stmt_loc;
1536 if (!lang_hooks.types_compatible_p (TREE_TYPE (*tp), TREE_TYPE (t)))
1537 {
1538 if (d->kind == 0)
1539 error_at (loc, "outer iteration variable %qD used in initializer"
1540 " expression has type other than %qT",
1541 t, TREE_TYPE (*tp));
1542 else
1543 error_at (loc, "outer iteration variable %qD used in condition"
1544 " expression has type other than %qT",
1545 t, TREE_TYPE (*tp));
1546 d->fail = true;
1547 }
1548 else if (!INTEGRAL_TYPE_P (TREE_TYPE (a1)))
1549 {
1550 error_at (loc, "outer iteration variable %qD multiplier expression"
1551 " %qE is not integral", t, a1);
1552 d->fail = true;
1553 }
1554 else if (!INTEGRAL_TYPE_P (TREE_TYPE (a2)))
1555 {
1556 error_at (loc, "outer iteration variable %qD addend expression"
1557 " %qE is not integral", t, a2);
1558 d->fail = true;
1559 }
1560 else
1561 {
1562 walk_tree_1 (&a1, c_omp_check_loop_iv_r, d, NULL, lh);
1563 walk_tree_1 (&a2, c_omp_check_loop_iv_r, d, NULL, lh);
1564 }
1565 if (!d->fail)
1566 {
1567 a1 = fold_convert (TREE_TYPE (*tp), a1);
1568 a2 = fold_convert (TREE_TYPE (*tp), a2);
1569 if (neg_a1)
1570 a1 = fold_build1 (NEGATE_EXPR, TREE_TYPE (a1), a1);
1571 if (neg_a2)
1572 a2 = fold_build1 (NEGATE_EXPR, TREE_TYPE (a2), a2);
1573 ret = t;
1574 *tp = make_tree_vec (3);
1575 TREE_VEC_ELT (*tp, 0) = t;
1576 TREE_VEC_ELT (*tp, 1) = a1;
1577 TREE_VEC_ELT (*tp, 2) = a2;
1578 }
1579 }
1580 else
1581 walk_tree_1 (&t, c_omp_check_loop_iv_r, d, NULL, lh);
1582
1583 d->ppset = ppset;
1584 return ret;
1585}
1586
1587/* Diagnose invalid references to loop iterators in lb, b and incr
1588 expressions. */
1589
1590bool
1591c_omp_check_loop_iv (tree stmt, tree declv, walk_tree_lh lh)
1592{
1593 hash_set<tree> pset;
1594 struct c_omp_check_loop_iv_data data;
1595 int i;
1596
1597 data.declv = declv;
1598 data.fail = false;
1599 data.maybe_nonrect = false;
1600 data.stmt_loc = EXPR_LOCATION (stmt);
1601 data.lh = lh;
1602 data.ppset = &pset;
1603 for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (stmt)); i++)
1604 {
1605 tree init = TREE_VEC_ELT (OMP_FOR_INIT (stmt), i);
1606 gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
1607 tree decl = TREE_OPERAND (init, 0);
1608 tree cond = TREE_VEC_ELT (OMP_FOR_COND (stmt), i);
1609 gcc_assert (COMPARISON_CLASS_P (cond));
1610 gcc_assert (TREE_OPERAND (cond, 0) == decl);
1611 tree incr = TREE_VEC_ELT (OMP_FOR_INCR (stmt), i);
1612 data.expr_loc = EXPR_LOCATION (TREE_OPERAND (init, 1));
1613 tree vec_outer1 = NULL_TREE, vec_outer2 = NULL_TREE;
1614 int kind = 0;
1615 if (i > 0
1616 && (unsigned) c_omp_is_loop_iterator (decl, d: &data) < (unsigned) i)
1617 {
1618 location_t loc = data.expr_loc;
1619 if (loc == UNKNOWN_LOCATION)
1620 loc = data.stmt_loc;
1621 error_at (loc, "the same loop iteration variables %qD used in "
1622 "multiple associated loops", decl);
1623 data.fail = true;
1624 }
1625 /* Handle non-rectangular loop nests. */
1626 if (TREE_CODE (stmt) != OACC_LOOP && i > 0)
1627 kind = 4;
1628 data.kind = kind;
1629 data.idx = i;
1630 walk_tree_1 (&TREE_OPERAND (init, 1),
1631 c_omp_check_loop_iv_r, &data, NULL, lh);
1632 if (data.maybe_nonrect)
1633 vec_outer1 = c_omp_check_nonrect_loop_iv (tp: &TREE_OPERAND (init, 1),
1634 d: &data, lh);
1635 /* Don't warn for C++ random access iterators here, the
1636 expression then involves the subtraction and always refers
1637 to the original value. The C++ FE needs to warn on those
1638 earlier. */
1639 if (decl == TREE_VEC_ELT (declv, i)
1640 || (TREE_CODE (TREE_VEC_ELT (declv, i)) == TREE_LIST
1641 && decl == TREE_PURPOSE (TREE_VEC_ELT (declv, i))))
1642 {
1643 data.expr_loc = EXPR_LOCATION (cond);
1644 data.kind = kind | 1;
1645 walk_tree_1 (&TREE_OPERAND (cond, 1),
1646 c_omp_check_loop_iv_r, &data, NULL, lh);
1647 if (data.maybe_nonrect)
1648 vec_outer2 = c_omp_check_nonrect_loop_iv (tp: &TREE_OPERAND (cond, 1),
1649 d: &data, lh);
1650 }
1651 if (vec_outer1 && vec_outer2 && vec_outer1 != vec_outer2)
1652 {
1653 location_t loc = data.expr_loc;
1654 if (loc == UNKNOWN_LOCATION)
1655 loc = data.stmt_loc;
1656 error_at (loc, "two different outer iteration variables %qD and %qD"
1657 " used in a single loop", vec_outer1, vec_outer2);
1658 data.fail = true;
1659 }
1660 if (vec_outer1 || vec_outer2)
1661 OMP_FOR_NON_RECTANGULAR (stmt) = 1;
1662 if (TREE_CODE (incr) == MODIFY_EXPR)
1663 {
1664 gcc_assert (TREE_OPERAND (incr, 0) == decl);
1665 incr = TREE_OPERAND (incr, 1);
1666 data.kind = 2;
1667 if (TREE_CODE (incr) == PLUS_EXPR
1668 && TREE_OPERAND (incr, 1) == decl)
1669 {
1670 data.expr_loc = EXPR_LOCATION (TREE_OPERAND (incr, 0));
1671 walk_tree_1 (&TREE_OPERAND (incr, 0),
1672 c_omp_check_loop_iv_r, &data, NULL, lh);
1673 }
1674 else
1675 {
1676 data.expr_loc = EXPR_LOCATION (TREE_OPERAND (incr, 1));
1677 walk_tree_1 (&TREE_OPERAND (incr, 1),
1678 c_omp_check_loop_iv_r, &data, NULL, lh);
1679 }
1680 }
1681 }
1682 return !data.fail;
1683}
1684
1685/* Similar, but allows to check the init or cond expressions individually. */
1686
1687bool
1688c_omp_check_loop_iv_exprs (location_t stmt_loc, enum tree_code code,
1689 tree declv, int i, tree decl, tree init, tree cond,
1690 walk_tree_lh lh)
1691{
1692 hash_set<tree> pset;
1693 struct c_omp_check_loop_iv_data data;
1694 int kind = (code != OACC_LOOP && i > 0) ? 4 : 0;
1695
1696 data.declv = declv;
1697 data.fail = false;
1698 data.maybe_nonrect = false;
1699 data.stmt_loc = stmt_loc;
1700 data.lh = lh;
1701 data.ppset = &pset;
1702 data.idx = i;
1703 if (i > 0
1704 && (unsigned) c_omp_is_loop_iterator (decl, d: &data) < (unsigned) i)
1705 {
1706 error_at (stmt_loc, "the same loop iteration variables %qD used in "
1707 "multiple associated loops", decl);
1708 data.fail = true;
1709 }
1710 if (init)
1711 {
1712 data.expr_loc = EXPR_LOCATION (init);
1713 data.kind = kind;
1714 walk_tree_1 (&init,
1715 c_omp_check_loop_iv_r, &data, NULL, lh);
1716 }
1717 if (cond)
1718 {
1719 gcc_assert (COMPARISON_CLASS_P (cond));
1720 data.expr_loc = EXPR_LOCATION (init);
1721 data.kind = kind | 1;
1722 if (TREE_OPERAND (cond, 0) == decl)
1723 walk_tree_1 (&TREE_OPERAND (cond, 1),
1724 c_omp_check_loop_iv_r, &data, NULL, lh);
1725 else
1726 walk_tree_1 (&TREE_OPERAND (cond, 0),
1727 c_omp_check_loop_iv_r, &data, NULL, lh);
1728 }
1729 return !data.fail;
1730}
1731
1732
1733/* Helper function for c_omp_check_loop_binding_exprs: look for a binding
1734 of DECL in BODY. Only traverse things that might be containers for
1735 intervening code in an OMP loop. Returns the BIND_EXPR or DECL_EXPR
1736 if found, otherwise null. */
1737
1738static tree
1739find_binding_in_body (tree decl, tree body)
1740{
1741 if (!body)
1742 return NULL_TREE;
1743
1744 switch (TREE_CODE (body))
1745 {
1746 case BIND_EXPR:
1747 for (tree b = BIND_EXPR_VARS (body); b; b = DECL_CHAIN (b))
1748 if (b == decl)
1749 return body;
1750 return find_binding_in_body (decl, BIND_EXPR_BODY (body));
1751
1752 case DECL_EXPR:
1753 if (DECL_EXPR_DECL (body) == decl)
1754 return body;
1755 return NULL_TREE;
1756
1757 case STATEMENT_LIST:
1758 for (tree_stmt_iterator si = tsi_start (t: body); !tsi_end_p (i: si);
1759 tsi_next (i: &si))
1760 {
1761 tree b = find_binding_in_body (decl, body: tsi_stmt (i: si));
1762 if (b)
1763 return b;
1764 }
1765 return NULL_TREE;
1766
1767 case OMP_STRUCTURED_BLOCK:
1768 return find_binding_in_body (decl, OMP_BODY (body));
1769
1770 default:
1771 return NULL_TREE;
1772 }
1773}
1774
1775/* Traversal function for check_loop_binding_expr, to diagnose
1776 errors when a binding made in intervening code is referenced outside
1777 of the loop. Returns non-null if such a reference is found. DATA points
1778 to the tree containing the loop body. */
1779
1780static tree
1781check_loop_binding_expr_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
1782 void *data)
1783{
1784 tree body = *(tree *)data;
1785
1786 if (DECL_P (*tp) && find_binding_in_body (decl: *tp, body))
1787 return *tp;
1788 return NULL_TREE;
1789}
1790
1791/* Helper macro used below. */
1792
1793#define LOCATION_OR(loc1, loc2) \
1794 ((loc1) != UNKNOWN_LOCATION ? (loc1) : (loc2))
1795
1796/* Check a single expression EXPR for references to variables bound in
1797 intervening code in BODY. Return true if ok, otherwise give an error
1798 referencing CONTEXT and return false. Use LOC for the error message
1799 if EXPR doesn't have one. */
1800static bool
1801check_loop_binding_expr (tree expr, tree body, const char *context,
1802 location_t loc)
1803{
1804 tree bad = walk_tree (&expr, check_loop_binding_expr_r, (void *)&body, NULL);
1805
1806 if (bad)
1807 {
1808 location_t eloc = EXPR_LOCATION (expr);
1809 error_at (LOCATION_OR (eloc, loc),
1810 "variable %qD used %s is bound "
1811 "in intervening code", bad, context);
1812 return false;
1813 }
1814 return true;
1815}
1816
1817/* STMT is an OMP_FOR construct. Check all of the iteration variable,
1818 initializer, end condition, and increment for bindings inside the
1819 loop body. If ORIG_INITS is provided, check those elements too.
1820 Return true if OK, false otherwise. */
1821bool
1822c_omp_check_loop_binding_exprs (tree stmt, vec<tree> *orig_inits)
1823{
1824 bool ok = true;
1825 location_t loc = EXPR_LOCATION (stmt);
1826 tree body = OMP_FOR_BODY (stmt);
1827 int orig_init_length = orig_inits ? orig_inits->length () : 0;
1828
1829 for (int i = 1; i < TREE_VEC_LENGTH (OMP_FOR_INIT (stmt)); i++)
1830 {
1831 tree init = TREE_VEC_ELT (OMP_FOR_INIT (stmt), i);
1832 tree cond = TREE_VEC_ELT (OMP_FOR_COND (stmt), i);
1833 tree incr = TREE_VEC_ELT (OMP_FOR_INCR (stmt), i);
1834 gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
1835 tree decl = TREE_OPERAND (init, 0);
1836 tree orig_init = i < orig_init_length ? (*orig_inits)[i] : NULL_TREE;
1837 tree e;
1838 location_t eloc;
1839
1840 e = TREE_OPERAND (init, 1);
1841 eloc = LOCATION_OR (EXPR_LOCATION (init), loc);
1842 if (!check_loop_binding_expr (expr: decl, body, context: "as loop variable", loc: eloc))
1843 ok = false;
1844 if (!check_loop_binding_expr (expr: e, body, context: "in initializer", loc: eloc))
1845 ok = false;
1846 if (orig_init
1847 && !check_loop_binding_expr (expr: orig_init, body,
1848 context: "in initializer", loc: eloc))
1849 ok = false;
1850
1851 /* INCR and/or COND may be null if this is a template with a
1852 class iterator. */
1853 if (cond)
1854 {
1855 eloc = LOCATION_OR (EXPR_LOCATION (cond), loc);
1856 if (COMPARISON_CLASS_P (cond) && TREE_OPERAND (cond, 0) == decl)
1857 e = TREE_OPERAND (cond, 1);
1858 else if (COMPARISON_CLASS_P (cond) && TREE_OPERAND (cond, 1) == decl)
1859 e = TREE_OPERAND (cond, 0);
1860 else
1861 e = cond;
1862 if (!check_loop_binding_expr (expr: e, body, context: "in end test", loc: eloc))
1863 ok = false;
1864 }
1865
1866 if (incr)
1867 {
1868 eloc = LOCATION_OR (EXPR_LOCATION (incr), loc);
1869 /* INCR should be either a MODIFY_EXPR or pre/post
1870 increment/decrement. We don't have to check the latter
1871 since there are no operands besides the iteration variable. */
1872 if (TREE_CODE (incr) == MODIFY_EXPR
1873 && !check_loop_binding_expr (TREE_OPERAND (incr, 1), body,
1874 context: "in increment expression", loc: eloc))
1875 ok = false;
1876 }
1877 }
1878
1879 return ok;
1880}
1881
1882/* This function splits clauses for OpenACC combined loop
1883 constructs. OpenACC combined loop constructs are:
1884 #pragma acc kernels loop
1885 #pragma acc parallel loop */
1886
1887tree
1888c_oacc_split_loop_clauses (tree clauses, tree *not_loop_clauses,
1889 bool is_parallel)
1890{
1891 tree next, loop_clauses, nc;
1892
1893 loop_clauses = *not_loop_clauses = NULL_TREE;
1894 for (; clauses ; clauses = next)
1895 {
1896 next = OMP_CLAUSE_CHAIN (clauses);
1897
1898 switch (OMP_CLAUSE_CODE (clauses))
1899 {
1900 /* Loop clauses. */
1901 case OMP_CLAUSE_COLLAPSE:
1902 case OMP_CLAUSE_TILE:
1903 case OMP_CLAUSE_GANG:
1904 case OMP_CLAUSE_WORKER:
1905 case OMP_CLAUSE_VECTOR:
1906 case OMP_CLAUSE_AUTO:
1907 case OMP_CLAUSE_SEQ:
1908 case OMP_CLAUSE_INDEPENDENT:
1909 case OMP_CLAUSE_PRIVATE:
1910 OMP_CLAUSE_CHAIN (clauses) = loop_clauses;
1911 loop_clauses = clauses;
1912 break;
1913
1914 /* Reductions must be duplicated on both constructs. */
1915 case OMP_CLAUSE_REDUCTION:
1916 if (is_parallel)
1917 {
1918 nc = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
1919 OMP_CLAUSE_REDUCTION);
1920 OMP_CLAUSE_DECL (nc) = OMP_CLAUSE_DECL (clauses);
1921 OMP_CLAUSE_REDUCTION_CODE (nc)
1922 = OMP_CLAUSE_REDUCTION_CODE (clauses);
1923 OMP_CLAUSE_CHAIN (nc) = *not_loop_clauses;
1924 *not_loop_clauses = nc;
1925 }
1926
1927 OMP_CLAUSE_CHAIN (clauses) = loop_clauses;
1928 loop_clauses = clauses;
1929 break;
1930
1931 /* Parallel/kernels clauses. */
1932 default:
1933 OMP_CLAUSE_CHAIN (clauses) = *not_loop_clauses;
1934 *not_loop_clauses = clauses;
1935 break;
1936 }
1937 }
1938
1939 return loop_clauses;
1940}
1941
1942/* This function attempts to split or duplicate clauses for OpenMP
1943 combined/composite constructs. Right now there are 30 different
1944 constructs. CODE is the innermost construct in the combined construct,
1945 and MASK allows to determine which constructs are combined together,
1946 as every construct has at least one clause that no other construct
1947 has (except for OMP_SECTIONS, but that can be only combined with parallel,
1948 and OMP_MASTER, which doesn't have any clauses at all).
1949 OpenMP combined/composite constructs are:
1950 #pragma omp distribute parallel for
1951 #pragma omp distribute parallel for simd
1952 #pragma omp distribute simd
1953 #pragma omp for simd
1954 #pragma omp masked taskloop
1955 #pragma omp masked taskloop simd
1956 #pragma omp master taskloop
1957 #pragma omp master taskloop simd
1958 #pragma omp parallel for
1959 #pragma omp parallel for simd
1960 #pragma omp parallel loop
1961 #pragma omp parallel masked
1962 #pragma omp parallel masked taskloop
1963 #pragma omp parallel masked taskloop simd
1964 #pragma omp parallel master
1965 #pragma omp parallel master taskloop
1966 #pragma omp parallel master taskloop simd
1967 #pragma omp parallel sections
1968 #pragma omp target parallel
1969 #pragma omp target parallel for
1970 #pragma omp target parallel for simd
1971 #pragma omp target parallel loop
1972 #pragma omp target teams
1973 #pragma omp target teams distribute
1974 #pragma omp target teams distribute parallel for
1975 #pragma omp target teams distribute parallel for simd
1976 #pragma omp target teams distribute simd
1977 #pragma omp target teams loop
1978 #pragma omp target simd
1979 #pragma omp taskloop simd
1980 #pragma omp teams distribute
1981 #pragma omp teams distribute parallel for
1982 #pragma omp teams distribute parallel for simd
1983 #pragma omp teams distribute simd
1984 #pragma omp teams loop */
1985
1986void
1987c_omp_split_clauses (location_t loc, enum tree_code code,
1988 omp_clause_mask mask, tree clauses, tree *cclauses)
1989{
1990 tree next, c;
1991 enum c_omp_clause_split s;
1992 int i;
1993 bool has_dup_allocate = false;
1994
1995 for (i = 0; i < C_OMP_CLAUSE_SPLIT_COUNT; i++)
1996 cclauses[i] = NULL;
1997 /* Add implicit nowait clause on
1998 #pragma omp parallel {for,for simd,sections}. */
1999 if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0)
2000 switch (code)
2001 {
2002 case OMP_FOR:
2003 case OMP_SIMD:
2004 if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0)
2005 cclauses[C_OMP_CLAUSE_SPLIT_FOR]
2006 = build_omp_clause (loc, OMP_CLAUSE_NOWAIT);
2007 break;
2008 case OMP_SECTIONS:
2009 cclauses[C_OMP_CLAUSE_SPLIT_SECTIONS]
2010 = build_omp_clause (loc, OMP_CLAUSE_NOWAIT);
2011 break;
2012 default:
2013 break;
2014 }
2015
2016 for (; clauses ; clauses = next)
2017 {
2018 next = OMP_CLAUSE_CHAIN (clauses);
2019
2020 switch (OMP_CLAUSE_CODE (clauses))
2021 {
2022 /* First the clauses that are unique to some constructs. */
2023 case OMP_CLAUSE_DEVICE:
2024 case OMP_CLAUSE_MAP:
2025 case OMP_CLAUSE_IS_DEVICE_PTR:
2026 case OMP_CLAUSE_HAS_DEVICE_ADDR:
2027 case OMP_CLAUSE_DEFAULTMAP:
2028 case OMP_CLAUSE_DEPEND:
2029 s = C_OMP_CLAUSE_SPLIT_TARGET;
2030 break;
2031 case OMP_CLAUSE_DOACROSS:
2032 /* This can happen with invalid depend(source) or
2033 depend(sink:vec) on target combined with other constructs. */
2034 gcc_assert (OMP_CLAUSE_DOACROSS_DEPEND (clauses));
2035 s = C_OMP_CLAUSE_SPLIT_TARGET;
2036 break;
2037 case OMP_CLAUSE_NUM_TEAMS:
2038 s = C_OMP_CLAUSE_SPLIT_TEAMS;
2039 break;
2040 case OMP_CLAUSE_DIST_SCHEDULE:
2041 s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE;
2042 break;
2043 case OMP_CLAUSE_COPYIN:
2044 case OMP_CLAUSE_NUM_THREADS:
2045 case OMP_CLAUSE_PROC_BIND:
2046 s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2047 break;
2048 case OMP_CLAUSE_ORDERED:
2049 s = C_OMP_CLAUSE_SPLIT_FOR;
2050 break;
2051 case OMP_CLAUSE_SCHEDULE:
2052 s = C_OMP_CLAUSE_SPLIT_FOR;
2053 if (code != OMP_SIMD)
2054 OMP_CLAUSE_SCHEDULE_SIMD (clauses) = 0;
2055 break;
2056 case OMP_CLAUSE_SAFELEN:
2057 case OMP_CLAUSE_SIMDLEN:
2058 case OMP_CLAUSE_ALIGNED:
2059 case OMP_CLAUSE_NONTEMPORAL:
2060 s = C_OMP_CLAUSE_SPLIT_SIMD;
2061 break;
2062 case OMP_CLAUSE_GRAINSIZE:
2063 case OMP_CLAUSE_NUM_TASKS:
2064 case OMP_CLAUSE_FINAL:
2065 case OMP_CLAUSE_UNTIED:
2066 case OMP_CLAUSE_MERGEABLE:
2067 case OMP_CLAUSE_NOGROUP:
2068 case OMP_CLAUSE_PRIORITY:
2069 s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
2070 break;
2071 case OMP_CLAUSE_BIND:
2072 s = C_OMP_CLAUSE_SPLIT_LOOP;
2073 break;
2074 case OMP_CLAUSE_FILTER:
2075 s = C_OMP_CLAUSE_SPLIT_MASKED;
2076 break;
2077 /* Duplicate this to all of taskloop, distribute, for, simd and
2078 loop. */
2079 case OMP_CLAUSE_COLLAPSE:
2080 if (code == OMP_SIMD)
2081 {
2082 if ((mask & ((OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)
2083 | (OMP_CLAUSE_MASK_1
2084 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)
2085 | (OMP_CLAUSE_MASK_1
2086 << PRAGMA_OMP_CLAUSE_NOGROUP))) != 0)
2087 {
2088 c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2089 OMP_CLAUSE_COLLAPSE);
2090 OMP_CLAUSE_COLLAPSE_EXPR (c)
2091 = OMP_CLAUSE_COLLAPSE_EXPR (clauses);
2092 OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_SIMD];
2093 cclauses[C_OMP_CLAUSE_SPLIT_SIMD] = c;
2094 }
2095 else
2096 {
2097 /* This must be #pragma omp target simd */
2098 s = C_OMP_CLAUSE_SPLIT_SIMD;
2099 break;
2100 }
2101 }
2102 if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0)
2103 {
2104 if ((mask & (OMP_CLAUSE_MASK_1
2105 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0)
2106 {
2107 c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2108 OMP_CLAUSE_COLLAPSE);
2109 OMP_CLAUSE_COLLAPSE_EXPR (c)
2110 = OMP_CLAUSE_COLLAPSE_EXPR (clauses);
2111 OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_FOR];
2112 cclauses[C_OMP_CLAUSE_SPLIT_FOR] = c;
2113 s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE;
2114 }
2115 else
2116 s = C_OMP_CLAUSE_SPLIT_FOR;
2117 }
2118 else if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP))
2119 != 0)
2120 s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
2121 else if (code == OMP_LOOP)
2122 s = C_OMP_CLAUSE_SPLIT_LOOP;
2123 else
2124 s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE;
2125 break;
2126 /* Private clause is supported on all constructs but master/masked,
2127 it is enough to put it on the innermost one other than
2128 master/masked. For #pragma omp {for,sections} put it on parallel
2129 though, as that's what we did for OpenMP 3.1. */
2130 case OMP_CLAUSE_PRIVATE:
2131 switch (code)
2132 {
2133 case OMP_SIMD: s = C_OMP_CLAUSE_SPLIT_SIMD; break;
2134 case OMP_FOR: case OMP_SECTIONS:
2135 case OMP_PARALLEL: s = C_OMP_CLAUSE_SPLIT_PARALLEL; break;
2136 case OMP_DISTRIBUTE: s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE; break;
2137 case OMP_TEAMS: s = C_OMP_CLAUSE_SPLIT_TEAMS; break;
2138 case OMP_MASTER: s = C_OMP_CLAUSE_SPLIT_PARALLEL; break;
2139 case OMP_MASKED: s = C_OMP_CLAUSE_SPLIT_PARALLEL; break;
2140 case OMP_TASKLOOP: s = C_OMP_CLAUSE_SPLIT_TASKLOOP; break;
2141 case OMP_LOOP: s = C_OMP_CLAUSE_SPLIT_LOOP; break;
2142 default: gcc_unreachable ();
2143 }
2144 break;
2145 /* Firstprivate clause is supported on all constructs but
2146 simd, master, masked and loop. Put it on the outermost of those
2147 and duplicate on teams and parallel. */
2148 case OMP_CLAUSE_FIRSTPRIVATE:
2149 if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP))
2150 != 0)
2151 {
2152 if (code == OMP_SIMD
2153 && (mask & ((OMP_CLAUSE_MASK_1
2154 << PRAGMA_OMP_CLAUSE_NUM_THREADS)
2155 | (OMP_CLAUSE_MASK_1
2156 << PRAGMA_OMP_CLAUSE_NUM_TEAMS))) == 0)
2157 {
2158 /* This must be #pragma omp target simd. */
2159 s = C_OMP_CLAUSE_SPLIT_TARGET;
2160 OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (clauses) = 1;
2161 OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT_TARGET (clauses) = 1;
2162 break;
2163 }
2164 c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2165 OMP_CLAUSE_FIRSTPRIVATE);
2166 /* firstprivate should not be applied to target if it is
2167 also lastprivate or on the combined/composite construct,
2168 or if it is mentioned in map clause. OMP_CLAUSE_DECLs
2169 may need to go through FE handling though (instantiation,
2170 C++ non-static data members, array section lowering), so
2171 add the clause with OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT and
2172 let *finish_omp_clauses and the gimplifier handle it
2173 right. */
2174 OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c) = 1;
2175 OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2176 OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
2177 cclauses[C_OMP_CLAUSE_SPLIT_TARGET] = c;
2178 }
2179 if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS))
2180 != 0)
2181 {
2182 if ((mask & ((OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS)
2183 | (OMP_CLAUSE_MASK_1
2184 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE))) != 0)
2185 {
2186 c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2187 OMP_CLAUSE_FIRSTPRIVATE);
2188 OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2189 OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL];
2190 cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL] = c;
2191 if ((mask & (OMP_CLAUSE_MASK_1
2192 << PRAGMA_OMP_CLAUSE_NUM_TEAMS)) != 0)
2193 s = C_OMP_CLAUSE_SPLIT_TEAMS;
2194 else
2195 s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE;
2196 }
2197 else if ((mask & (OMP_CLAUSE_MASK_1
2198 << PRAGMA_OMP_CLAUSE_NOGROUP)) != 0)
2199 /* This must be
2200 #pragma omp parallel mas{ked,ter} taskloop{, simd}. */
2201 s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
2202 else
2203 /* This must be
2204 #pragma omp parallel{, for{, simd}, sections,loop}
2205 or
2206 #pragma omp target parallel. */
2207 s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2208 }
2209 else if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS))
2210 != 0)
2211 {
2212 /* This must be one of
2213 #pragma omp {,target }teams {distribute,loop}
2214 #pragma omp target teams
2215 #pragma omp {,target }teams distribute simd. */
2216 gcc_assert (code == OMP_DISTRIBUTE
2217 || code == OMP_LOOP
2218 || code == OMP_TEAMS
2219 || code == OMP_SIMD);
2220 s = C_OMP_CLAUSE_SPLIT_TEAMS;
2221 }
2222 else if ((mask & (OMP_CLAUSE_MASK_1
2223 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0)
2224 {
2225 /* This must be #pragma omp distribute simd. */
2226 gcc_assert (code == OMP_SIMD);
2227 s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE;
2228 }
2229 else if ((mask & (OMP_CLAUSE_MASK_1
2230 << PRAGMA_OMP_CLAUSE_NOGROUP)) != 0)
2231 {
2232 /* This must be
2233 #pragma omp {,{,parallel }mas{ked,ter} }taskloop simd
2234 or
2235 #pragma omp {,parallel }mas{ked,ter} taskloop. */
2236 gcc_assert (code == OMP_SIMD || code == OMP_TASKLOOP);
2237 s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
2238 }
2239 else
2240 {
2241 /* This must be #pragma omp for simd. */
2242 gcc_assert (code == OMP_SIMD);
2243 s = C_OMP_CLAUSE_SPLIT_FOR;
2244 }
2245 break;
2246 /* Lastprivate is allowed on distribute, for, sections, taskloop, loop
2247 and simd. In parallel {for{, simd},sections} we actually want to
2248 put it on parallel rather than for or sections. */
2249 case OMP_CLAUSE_LASTPRIVATE:
2250 if (code == OMP_DISTRIBUTE)
2251 {
2252 s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE;
2253 break;
2254 }
2255 if ((mask & (OMP_CLAUSE_MASK_1
2256 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0)
2257 {
2258 c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2259 OMP_CLAUSE_LASTPRIVATE);
2260 OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2261 OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE];
2262 OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c)
2263 = OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (clauses);
2264 cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE] = c;
2265 }
2266 if (code == OMP_FOR || code == OMP_SECTIONS)
2267 {
2268 if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS))
2269 != 0)
2270 s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2271 else
2272 s = C_OMP_CLAUSE_SPLIT_FOR;
2273 break;
2274 }
2275 if (code == OMP_TASKLOOP)
2276 {
2277 s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
2278 break;
2279 }
2280 if (code == OMP_LOOP)
2281 {
2282 s = C_OMP_CLAUSE_SPLIT_LOOP;
2283 break;
2284 }
2285 gcc_assert (code == OMP_SIMD);
2286 if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0)
2287 {
2288 c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2289 OMP_CLAUSE_LASTPRIVATE);
2290 OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2291 OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c)
2292 = OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (clauses);
2293 if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS))
2294 != 0)
2295 s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2296 else
2297 s = C_OMP_CLAUSE_SPLIT_FOR;
2298 OMP_CLAUSE_CHAIN (c) = cclauses[s];
2299 cclauses[s] = c;
2300 }
2301 if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP)) != 0)
2302 {
2303 c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2304 OMP_CLAUSE_LASTPRIVATE);
2305 OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2306 OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c)
2307 = OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (clauses);
2308 OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP];
2309 cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP] = c;
2310 }
2311 s = C_OMP_CLAUSE_SPLIT_SIMD;
2312 break;
2313 /* Shared and default clauses are allowed on parallel, teams and
2314 taskloop. */
2315 case OMP_CLAUSE_SHARED:
2316 case OMP_CLAUSE_DEFAULT:
2317 if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP))
2318 != 0)
2319 {
2320 if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS))
2321 != 0)
2322 {
2323 c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2324 OMP_CLAUSE_CODE (clauses));
2325 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_SHARED)
2326 OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2327 else
2328 OMP_CLAUSE_DEFAULT_KIND (c)
2329 = OMP_CLAUSE_DEFAULT_KIND (clauses);
2330 OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL];
2331 cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL] = c;
2332 }
2333 s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
2334 break;
2335 }
2336 if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS))
2337 != 0)
2338 {
2339 if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS))
2340 == 0)
2341 {
2342 s = C_OMP_CLAUSE_SPLIT_TEAMS;
2343 break;
2344 }
2345 c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2346 OMP_CLAUSE_CODE (clauses));
2347 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_SHARED)
2348 OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2349 else
2350 OMP_CLAUSE_DEFAULT_KIND (c)
2351 = OMP_CLAUSE_DEFAULT_KIND (clauses);
2352 OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
2353 cclauses[C_OMP_CLAUSE_SPLIT_TEAMS] = c;
2354 }
2355 s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2356 break;
2357 /* order clauses are allowed on distribute, for, simd and loop. */
2358 case OMP_CLAUSE_ORDER:
2359 if ((mask & (OMP_CLAUSE_MASK_1
2360 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0)
2361 {
2362 if (code == OMP_DISTRIBUTE)
2363 {
2364 s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE;
2365 break;
2366 }
2367 c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2368 OMP_CLAUSE_ORDER);
2369 OMP_CLAUSE_ORDER_UNCONSTRAINED (c)
2370 = OMP_CLAUSE_ORDER_UNCONSTRAINED (clauses);
2371 OMP_CLAUSE_ORDER_REPRODUCIBLE (c)
2372 = OMP_CLAUSE_ORDER_REPRODUCIBLE (clauses);
2373 OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE];
2374 cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE] = c;
2375 }
2376 if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0)
2377 {
2378 if (code == OMP_SIMD)
2379 {
2380 c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2381 OMP_CLAUSE_ORDER);
2382 OMP_CLAUSE_ORDER_UNCONSTRAINED (c)
2383 = OMP_CLAUSE_ORDER_UNCONSTRAINED (clauses);
2384 OMP_CLAUSE_ORDER_REPRODUCIBLE (c)
2385 = OMP_CLAUSE_ORDER_REPRODUCIBLE (clauses);
2386 OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_FOR];
2387 cclauses[C_OMP_CLAUSE_SPLIT_FOR] = c;
2388 s = C_OMP_CLAUSE_SPLIT_SIMD;
2389 }
2390 else
2391 s = C_OMP_CLAUSE_SPLIT_FOR;
2392 }
2393 else if (code == OMP_LOOP)
2394 s = C_OMP_CLAUSE_SPLIT_LOOP;
2395 else
2396 s = C_OMP_CLAUSE_SPLIT_SIMD;
2397 break;
2398 /* Reduction is allowed on simd, for, parallel, sections, taskloop,
2399 teams and loop. Duplicate it on all of them, but omit on for or
2400 sections if parallel is present (unless inscan, in that case
2401 omit on parallel). If taskloop or loop is combined with
2402 parallel, omit it on parallel. */
2403 case OMP_CLAUSE_REDUCTION:
2404 if (OMP_CLAUSE_REDUCTION_TASK (clauses))
2405 {
2406 if (code == OMP_SIMD || code == OMP_LOOP)
2407 {
2408 error_at (OMP_CLAUSE_LOCATION (clauses),
2409 "invalid %<task%> reduction modifier on construct "
2410 "combined with %<simd%> or %<loop%>");
2411 OMP_CLAUSE_REDUCTION_TASK (clauses) = 0;
2412 }
2413 else if (code != OMP_SECTIONS
2414 && (mask & (OMP_CLAUSE_MASK_1
2415 << PRAGMA_OMP_CLAUSE_NUM_THREADS)) == 0
2416 && (mask & (OMP_CLAUSE_MASK_1
2417 << PRAGMA_OMP_CLAUSE_SCHEDULE)) == 0)
2418 {
2419 error_at (OMP_CLAUSE_LOCATION (clauses),
2420 "invalid %<task%> reduction modifier on construct "
2421 "not combined with %<parallel%>, %<for%> or "
2422 "%<sections%>");
2423 OMP_CLAUSE_REDUCTION_TASK (clauses) = 0;
2424 }
2425 }
2426 if (OMP_CLAUSE_REDUCTION_INSCAN (clauses)
2427 && ((mask & ((OMP_CLAUSE_MASK_1
2428 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)
2429 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)))
2430 != 0))
2431 {
2432 error_at (OMP_CLAUSE_LOCATION (clauses),
2433 "%<inscan%> %<reduction%> clause on construct other "
2434 "than %<for%>, %<simd%>, %<for simd%>, "
2435 "%<parallel for%>, %<parallel for simd%>");
2436 OMP_CLAUSE_REDUCTION_INSCAN (clauses) = 0;
2437 }
2438 if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)) != 0)
2439 {
2440 c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2441 OMP_CLAUSE_MAP);
2442 OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2443 OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_TOFROM);
2444 OMP_CLAUSE_MAP_IMPLICIT (c) = 1;
2445 OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
2446 cclauses[C_OMP_CLAUSE_SPLIT_TARGET] = c;
2447 }
2448 if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0)
2449 {
2450 if (code == OMP_SIMD)
2451 {
2452 c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2453 OMP_CLAUSE_REDUCTION);
2454 OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2455 OMP_CLAUSE_REDUCTION_CODE (c)
2456 = OMP_CLAUSE_REDUCTION_CODE (clauses);
2457 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
2458 = OMP_CLAUSE_REDUCTION_PLACEHOLDER (clauses);
2459 OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c)
2460 = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clauses);
2461 OMP_CLAUSE_REDUCTION_INSCAN (c)
2462 = OMP_CLAUSE_REDUCTION_INSCAN (clauses);
2463 OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_SIMD];
2464 cclauses[C_OMP_CLAUSE_SPLIT_SIMD] = c;
2465 }
2466 if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS))
2467 != 0)
2468 {
2469 c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2470 OMP_CLAUSE_REDUCTION);
2471 OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2472 OMP_CLAUSE_REDUCTION_CODE (c)
2473 = OMP_CLAUSE_REDUCTION_CODE (clauses);
2474 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
2475 = OMP_CLAUSE_REDUCTION_PLACEHOLDER (clauses);
2476 OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c)
2477 = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clauses);
2478 OMP_CLAUSE_REDUCTION_INSCAN (c)
2479 = OMP_CLAUSE_REDUCTION_INSCAN (clauses);
2480 OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
2481 cclauses[C_OMP_CLAUSE_SPLIT_TEAMS] = c;
2482 s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2483 }
2484 else if ((mask & (OMP_CLAUSE_MASK_1
2485 << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0
2486 && !OMP_CLAUSE_REDUCTION_INSCAN (clauses))
2487 s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2488 else
2489 s = C_OMP_CLAUSE_SPLIT_FOR;
2490 }
2491 else if (code == OMP_SECTIONS
2492 || code == OMP_PARALLEL
2493 || code == OMP_MASTER
2494 || code == OMP_MASKED)
2495 s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2496 else if (code == OMP_TASKLOOP)
2497 s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
2498 else if (code == OMP_LOOP)
2499 s = C_OMP_CLAUSE_SPLIT_LOOP;
2500 else if (code == OMP_SIMD)
2501 {
2502 if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP))
2503 != 0)
2504 {
2505 c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2506 OMP_CLAUSE_REDUCTION);
2507 OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2508 OMP_CLAUSE_REDUCTION_CODE (c)
2509 = OMP_CLAUSE_REDUCTION_CODE (clauses);
2510 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
2511 = OMP_CLAUSE_REDUCTION_PLACEHOLDER (clauses);
2512 OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c)
2513 = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clauses);
2514 OMP_CLAUSE_REDUCTION_INSCAN (c)
2515 = OMP_CLAUSE_REDUCTION_INSCAN (clauses);
2516 OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP];
2517 cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP] = c;
2518 }
2519 else if ((mask & (OMP_CLAUSE_MASK_1
2520 << PRAGMA_OMP_CLAUSE_NUM_TEAMS)) != 0)
2521 {
2522 c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2523 OMP_CLAUSE_REDUCTION);
2524 OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2525 OMP_CLAUSE_REDUCTION_CODE (c)
2526 = OMP_CLAUSE_REDUCTION_CODE (clauses);
2527 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
2528 = OMP_CLAUSE_REDUCTION_PLACEHOLDER (clauses);
2529 OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c)
2530 = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clauses);
2531 OMP_CLAUSE_REDUCTION_INSCAN (c)
2532 = OMP_CLAUSE_REDUCTION_INSCAN (clauses);
2533 OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
2534 cclauses[C_OMP_CLAUSE_SPLIT_TEAMS] = c;
2535 }
2536 s = C_OMP_CLAUSE_SPLIT_SIMD;
2537 }
2538 else
2539 s = C_OMP_CLAUSE_SPLIT_TEAMS;
2540 break;
2541 case OMP_CLAUSE_IN_REDUCTION:
2542 if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)) != 0)
2543 {
2544 /* When on target, map(always, tofrom: item) is added as
2545 well. For non-combined target it is added in the FEs. */
2546 c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2547 OMP_CLAUSE_MAP);
2548 OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2549 OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_ALWAYS_TOFROM);
2550 OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
2551 cclauses[C_OMP_CLAUSE_SPLIT_TARGET] = c;
2552 s = C_OMP_CLAUSE_SPLIT_TARGET;
2553 break;
2554 }
2555 /* in_reduction on taskloop simd becomes reduction on the simd
2556 and keeps being in_reduction on taskloop. */
2557 if (code == OMP_SIMD)
2558 {
2559 c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2560 OMP_CLAUSE_REDUCTION);
2561 OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2562 OMP_CLAUSE_REDUCTION_CODE (c)
2563 = OMP_CLAUSE_REDUCTION_CODE (clauses);
2564 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
2565 = OMP_CLAUSE_REDUCTION_PLACEHOLDER (clauses);
2566 OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c)
2567 = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clauses);
2568 OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_SIMD];
2569 cclauses[C_OMP_CLAUSE_SPLIT_SIMD] = c;
2570 }
2571 s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
2572 break;
2573 case OMP_CLAUSE_IF:
2574 if (OMP_CLAUSE_IF_MODIFIER (clauses) != ERROR_MARK)
2575 {
2576 s = C_OMP_CLAUSE_SPLIT_COUNT;
2577 switch (OMP_CLAUSE_IF_MODIFIER (clauses))
2578 {
2579 case OMP_PARALLEL:
2580 if ((mask & (OMP_CLAUSE_MASK_1
2581 << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0)
2582 s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2583 break;
2584 case OMP_SIMD:
2585 if (code == OMP_SIMD)
2586 s = C_OMP_CLAUSE_SPLIT_SIMD;
2587 break;
2588 case OMP_TASKLOOP:
2589 if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP))
2590 != 0)
2591 s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
2592 break;
2593 case OMP_TARGET:
2594 if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP))
2595 != 0)
2596 s = C_OMP_CLAUSE_SPLIT_TARGET;
2597 break;
2598 default:
2599 break;
2600 }
2601 if (s != C_OMP_CLAUSE_SPLIT_COUNT)
2602 break;
2603 /* Error-recovery here, invalid if-modifier specified, add the
2604 clause to just one construct. */
2605 if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)) != 0)
2606 s = C_OMP_CLAUSE_SPLIT_TARGET;
2607 else if ((mask & (OMP_CLAUSE_MASK_1
2608 << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0)
2609 s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2610 else if ((mask & (OMP_CLAUSE_MASK_1
2611 << PRAGMA_OMP_CLAUSE_NOGROUP)) != 0)
2612 s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
2613 else if (code == OMP_SIMD)
2614 s = C_OMP_CLAUSE_SPLIT_SIMD;
2615 else
2616 gcc_unreachable ();
2617 break;
2618 }
2619 /* Otherwise, duplicate if clause to all constructs. */
2620 if (code == OMP_SIMD)
2621 {
2622 if ((mask & ((OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)
2623 | (OMP_CLAUSE_MASK_1
2624 << PRAGMA_OMP_CLAUSE_NUM_THREADS)
2625 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP)))
2626 != 0)
2627 {
2628 c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2629 OMP_CLAUSE_IF);
2630 OMP_CLAUSE_IF_MODIFIER (c)
2631 = OMP_CLAUSE_IF_MODIFIER (clauses);
2632 OMP_CLAUSE_IF_EXPR (c) = OMP_CLAUSE_IF_EXPR (clauses);
2633 OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_SIMD];
2634 cclauses[C_OMP_CLAUSE_SPLIT_SIMD] = c;
2635 }
2636 else
2637 {
2638 s = C_OMP_CLAUSE_SPLIT_SIMD;
2639 break;
2640 }
2641 }
2642 if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP))
2643 != 0)
2644 {
2645 if ((mask & (OMP_CLAUSE_MASK_1
2646 << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0)
2647 {
2648 c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2649 OMP_CLAUSE_IF);
2650 OMP_CLAUSE_IF_MODIFIER (c)
2651 = OMP_CLAUSE_IF_MODIFIER (clauses);
2652 OMP_CLAUSE_IF_EXPR (c) = OMP_CLAUSE_IF_EXPR (clauses);
2653 OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP];
2654 cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP] = c;
2655 s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2656 }
2657 else
2658 s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
2659 }
2660 else if ((mask & (OMP_CLAUSE_MASK_1
2661 << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0)
2662 {
2663 if ((mask & (OMP_CLAUSE_MASK_1
2664 << PRAGMA_OMP_CLAUSE_MAP)) != 0)
2665 {
2666 c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2667 OMP_CLAUSE_IF);
2668 OMP_CLAUSE_IF_MODIFIER (c)
2669 = OMP_CLAUSE_IF_MODIFIER (clauses);
2670 OMP_CLAUSE_IF_EXPR (c) = OMP_CLAUSE_IF_EXPR (clauses);
2671 OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
2672 cclauses[C_OMP_CLAUSE_SPLIT_TARGET] = c;
2673 s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2674 }
2675 else
2676 s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2677 }
2678 else
2679 s = C_OMP_CLAUSE_SPLIT_TARGET;
2680 break;
2681 case OMP_CLAUSE_LINEAR:
2682 /* Linear clause is allowed on simd and for. Put it on the
2683 innermost construct. */
2684 if (code == OMP_SIMD)
2685 s = C_OMP_CLAUSE_SPLIT_SIMD;
2686 else
2687 s = C_OMP_CLAUSE_SPLIT_FOR;
2688 break;
2689 case OMP_CLAUSE_NOWAIT:
2690 /* Nowait clause is allowed on target, for and sections, but
2691 is not allowed on parallel for or parallel sections. Therefore,
2692 put it on target construct if present, because that can only
2693 be combined with parallel for{, simd} and not with for{, simd},
2694 otherwise to the worksharing construct. */
2695 if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP))
2696 != 0)
2697 s = C_OMP_CLAUSE_SPLIT_TARGET;
2698 else
2699 s = C_OMP_CLAUSE_SPLIT_FOR;
2700 break;
2701 /* thread_limit is allowed on target and teams. Distribute it
2702 to all. */
2703 case OMP_CLAUSE_THREAD_LIMIT:
2704 if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP))
2705 != 0)
2706 {
2707 if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS))
2708 != 0)
2709 {
2710 c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2711 OMP_CLAUSE_THREAD_LIMIT);
2712 OMP_CLAUSE_THREAD_LIMIT_EXPR (c)
2713 = OMP_CLAUSE_THREAD_LIMIT_EXPR (clauses);
2714 OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
2715 cclauses[C_OMP_CLAUSE_SPLIT_TARGET] = c;
2716 }
2717 else
2718 {
2719 s = C_OMP_CLAUSE_SPLIT_TARGET;
2720 break;
2721 }
2722 }
2723 s = C_OMP_CLAUSE_SPLIT_TEAMS;
2724 break;
2725 /* Allocate clause is allowed on target, teams, distribute, parallel,
2726 for, sections and taskloop. Distribute it to all. */
2727 case OMP_CLAUSE_ALLOCATE:
2728 s = C_OMP_CLAUSE_SPLIT_COUNT;
2729 for (i = 0; i < C_OMP_CLAUSE_SPLIT_COUNT; i++)
2730 {
2731 switch (i)
2732 {
2733 case C_OMP_CLAUSE_SPLIT_TARGET:
2734 if ((mask & (OMP_CLAUSE_MASK_1
2735 << PRAGMA_OMP_CLAUSE_MAP)) == 0)
2736 continue;
2737 break;
2738 case C_OMP_CLAUSE_SPLIT_TEAMS:
2739 if ((mask & (OMP_CLAUSE_MASK_1
2740 << PRAGMA_OMP_CLAUSE_NUM_TEAMS)) == 0)
2741 continue;
2742 break;
2743 case C_OMP_CLAUSE_SPLIT_DISTRIBUTE:
2744 if ((mask & (OMP_CLAUSE_MASK_1
2745 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) == 0)
2746 continue;
2747 break;
2748 case C_OMP_CLAUSE_SPLIT_PARALLEL:
2749 if ((mask & (OMP_CLAUSE_MASK_1
2750 << PRAGMA_OMP_CLAUSE_NUM_THREADS)) == 0)
2751 continue;
2752 break;
2753 case C_OMP_CLAUSE_SPLIT_FOR:
2754 STATIC_ASSERT (C_OMP_CLAUSE_SPLIT_SECTIONS
2755 == C_OMP_CLAUSE_SPLIT_FOR
2756 && (C_OMP_CLAUSE_SPLIT_TASKLOOP
2757 == C_OMP_CLAUSE_SPLIT_FOR)
2758 && (C_OMP_CLAUSE_SPLIT_LOOP
2759 == C_OMP_CLAUSE_SPLIT_FOR));
2760 if (code == OMP_SECTIONS)
2761 break;
2762 if ((mask & (OMP_CLAUSE_MASK_1
2763 << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0)
2764 break;
2765 if ((mask & (OMP_CLAUSE_MASK_1
2766 << PRAGMA_OMP_CLAUSE_NOGROUP)) != 0)
2767 break;
2768 continue;
2769 case C_OMP_CLAUSE_SPLIT_SIMD:
2770 continue;
2771 default:
2772 gcc_unreachable ();
2773 }
2774 if (s != C_OMP_CLAUSE_SPLIT_COUNT)
2775 {
2776 c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2777 OMP_CLAUSE_ALLOCATE);
2778 OMP_CLAUSE_DECL (c)
2779 = OMP_CLAUSE_DECL (clauses);
2780 OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)
2781 = OMP_CLAUSE_ALLOCATE_ALLOCATOR (clauses);
2782 OMP_CLAUSE_ALLOCATE_ALIGN (c)
2783 = OMP_CLAUSE_ALLOCATE_ALIGN (clauses);
2784 OMP_CLAUSE_CHAIN (c) = cclauses[s];
2785 cclauses[s] = c;
2786 has_dup_allocate = true;
2787 }
2788 s = (enum c_omp_clause_split) i;
2789 }
2790 gcc_assert (s != C_OMP_CLAUSE_SPLIT_COUNT);
2791 break;
2792 default:
2793 gcc_unreachable ();
2794 }
2795 OMP_CLAUSE_CHAIN (clauses) = cclauses[s];
2796 cclauses[s] = clauses;
2797 }
2798
2799 if (has_dup_allocate)
2800 {
2801 bool need_prune = false;
2802 bitmap_obstack_initialize (NULL);
2803 for (i = 0; i < C_OMP_CLAUSE_SPLIT_SIMD - (code == OMP_LOOP); i++)
2804 if (cclauses[i])
2805 {
2806 bitmap_head allocate_head;
2807 bitmap_initialize (head: &allocate_head, obstack: &bitmap_default_obstack);
2808 for (c = cclauses[i]; c; c = OMP_CLAUSE_CHAIN (c))
2809 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_ALLOCATE
2810 && DECL_P (OMP_CLAUSE_DECL (c)))
2811 bitmap_set_bit (&allocate_head,
2812 DECL_UID (OMP_CLAUSE_DECL (c)));
2813 for (c = cclauses[i]; c; c = OMP_CLAUSE_CHAIN (c))
2814 switch (OMP_CLAUSE_CODE (c))
2815 {
2816 case OMP_CLAUSE_REDUCTION:
2817 case OMP_CLAUSE_IN_REDUCTION:
2818 case OMP_CLAUSE_TASK_REDUCTION:
2819 if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
2820 {
2821 tree t = TREE_OPERAND (OMP_CLAUSE_DECL (c), 0);
2822 if (TREE_CODE (t) == POINTER_PLUS_EXPR)
2823 t = TREE_OPERAND (t, 0);
2824 if (TREE_CODE (t) == ADDR_EXPR
2825 || INDIRECT_REF_P (t))
2826 t = TREE_OPERAND (t, 0);
2827 if (DECL_P (t))
2828 bitmap_clear_bit (&allocate_head, DECL_UID (t));
2829 break;
2830 }
2831 else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == TREE_LIST)
2832 {
2833 tree t;
2834 for (t = OMP_CLAUSE_DECL (c);
2835 TREE_CODE (t) == TREE_LIST; t = TREE_CHAIN (t))
2836 ;
2837 if (DECL_P (t))
2838 bitmap_clear_bit (&allocate_head, DECL_UID (t));
2839 break;
2840 }
2841 /* FALLTHRU */
2842 case OMP_CLAUSE_PRIVATE:
2843 case OMP_CLAUSE_FIRSTPRIVATE:
2844 case OMP_CLAUSE_LASTPRIVATE:
2845 case OMP_CLAUSE_LINEAR:
2846 if (DECL_P (OMP_CLAUSE_DECL (c)))
2847 bitmap_clear_bit (&allocate_head,
2848 DECL_UID (OMP_CLAUSE_DECL (c)));
2849 break;
2850 default:
2851 break;
2852 }
2853 for (c = cclauses[i]; c; c = OMP_CLAUSE_CHAIN (c))
2854 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_ALLOCATE
2855 && DECL_P (OMP_CLAUSE_DECL (c))
2856 && bitmap_bit_p (&allocate_head,
2857 DECL_UID (OMP_CLAUSE_DECL (c))))
2858 {
2859 /* Mark allocate clauses which don't have corresponding
2860 explicit data sharing clause. */
2861 OMP_CLAUSE_ALLOCATE_COMBINED (c) = 1;
2862 need_prune = true;
2863 }
2864 }
2865 bitmap_obstack_release (NULL);
2866 if (need_prune)
2867 {
2868 /* At least one allocate clause has been marked. Walk all the
2869 duplicated allocate clauses in sync. If it is marked in all
2870 constituent constructs, diagnose it as invalid and remove
2871 them. Otherwise, remove all marked inner clauses inside
2872 a construct that doesn't have them marked. Keep the outer
2873 marked ones, because some clause duplication is done only
2874 during gimplification. */
2875 tree *p[C_OMP_CLAUSE_SPLIT_COUNT];
2876 for (i = 0; i < C_OMP_CLAUSE_SPLIT_COUNT; i++)
2877 if (cclauses[i] == NULL_TREE
2878 || i == C_OMP_CLAUSE_SPLIT_SIMD
2879 || (i == C_OMP_CLAUSE_SPLIT_LOOP && code == OMP_LOOP))
2880 p[i] = NULL;
2881 else
2882 p[i] = &cclauses[i];
2883 do
2884 {
2885 int j = -1;
2886 tree seen = NULL_TREE;
2887 for (i = C_OMP_CLAUSE_SPLIT_COUNT - 1; i >= 0; i--)
2888 if (p[i])
2889 {
2890 while (*p[i]
2891 && OMP_CLAUSE_CODE (*p[i]) != OMP_CLAUSE_ALLOCATE)
2892 p[i] = &OMP_CLAUSE_CHAIN (*p[i]);
2893 if (*p[i] == NULL_TREE)
2894 {
2895 i = C_OMP_CLAUSE_SPLIT_COUNT;
2896 break;
2897 }
2898 if (!OMP_CLAUSE_ALLOCATE_COMBINED (*p[i]) && j == -1)
2899 j = i;
2900 seen = *p[i];
2901 }
2902 if (i == C_OMP_CLAUSE_SPLIT_COUNT)
2903 break;
2904 if (j == -1)
2905 error_at (OMP_CLAUSE_LOCATION (seen),
2906 "%qD specified in %<allocate%> clause but not in "
2907 "an explicit privatization clause",
2908 OMP_CLAUSE_DECL (seen));
2909 for (i = 0; i < C_OMP_CLAUSE_SPLIT_COUNT; i++)
2910 if (p[i])
2911 {
2912 if (i > j)
2913 /* Remove. */
2914 *p[i] = OMP_CLAUSE_CHAIN (*p[i]);
2915 else
2916 /* Keep. */
2917 p[i] = &OMP_CLAUSE_CHAIN (*p[i]);
2918 }
2919 }
2920 while (1);
2921 }
2922 }
2923
2924 if (!flag_checking)
2925 return;
2926
2927 if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)) == 0)
2928 gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_TARGET] == NULL_TREE);
2929 if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS)) == 0)
2930 gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_TEAMS] == NULL_TREE);
2931 if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) == 0
2932 && (mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FILTER)) == 0)
2933 gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE] == NULL_TREE);
2934 if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS)) == 0)
2935 gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL] == NULL_TREE);
2936 if ((mask & ((OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)
2937 | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP))) == 0
2938 && code != OMP_SECTIONS
2939 && code != OMP_LOOP)
2940 gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_FOR] == NULL_TREE);
2941 if (code != OMP_SIMD)
2942 gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_SIMD] == NULL_TREE);
2943}
2944
2945
2946/* qsort callback to compare #pragma omp declare simd clauses. */
2947
2948static int
2949c_omp_declare_simd_clause_cmp (const void *p, const void *q)
2950{
2951 tree a = *(const tree *) p;
2952 tree b = *(const tree *) q;
2953 if (OMP_CLAUSE_CODE (a) != OMP_CLAUSE_CODE (b))
2954 {
2955 if (OMP_CLAUSE_CODE (a) > OMP_CLAUSE_CODE (b))
2956 return -1;
2957 return 1;
2958 }
2959 if (OMP_CLAUSE_CODE (a) != OMP_CLAUSE_SIMDLEN
2960 && OMP_CLAUSE_CODE (a) != OMP_CLAUSE_INBRANCH
2961 && OMP_CLAUSE_CODE (a) != OMP_CLAUSE_NOTINBRANCH)
2962 {
2963 int c = tree_to_shwi (OMP_CLAUSE_DECL (a));
2964 int d = tree_to_shwi (OMP_CLAUSE_DECL (b));
2965 if (c < d)
2966 return 1;
2967 if (c > d)
2968 return -1;
2969 }
2970 return 0;
2971}
2972
2973/* Change PARM_DECLs in OMP_CLAUSE_DECL of #pragma omp declare simd
2974 CLAUSES on FNDECL into argument indexes and sort them. */
2975
2976tree
2977c_omp_declare_simd_clauses_to_numbers (tree parms, tree clauses)
2978{
2979 tree c;
2980 vec<tree> clvec = vNULL;
2981
2982 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2983 {
2984 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_SIMDLEN
2985 && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_INBRANCH
2986 && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_NOTINBRANCH)
2987 {
2988 tree decl = OMP_CLAUSE_DECL (c);
2989 tree arg;
2990 int idx;
2991 for (arg = parms, idx = 0; arg;
2992 arg = TREE_CHAIN (arg), idx++)
2993 if (arg == decl)
2994 break;
2995 if (arg == NULL_TREE)
2996 {
2997 error_at (OMP_CLAUSE_LOCATION (c),
2998 "%qD is not a function argument", decl);
2999 continue;
3000 }
3001 OMP_CLAUSE_DECL (c) = build_int_cst (integer_type_node, idx);
3002 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3003 && OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (c))
3004 {
3005 decl = OMP_CLAUSE_LINEAR_STEP (c);
3006 for (arg = parms, idx = 0; arg;
3007 arg = TREE_CHAIN (arg), idx++)
3008 if (arg == decl)
3009 break;
3010 if (arg == NULL_TREE)
3011 {
3012 error_at (OMP_CLAUSE_LOCATION (c),
3013 "%qD is not a function argument", decl);
3014 continue;
3015 }
3016 OMP_CLAUSE_LINEAR_STEP (c)
3017 = build_int_cst (integer_type_node, idx);
3018 }
3019 }
3020 clvec.safe_push (obj: c);
3021 }
3022 if (!clvec.is_empty ())
3023 {
3024 unsigned int len = clvec.length (), i;
3025 clvec.qsort (c_omp_declare_simd_clause_cmp);
3026 clauses = clvec[0];
3027 for (i = 0; i < len; i++)
3028 OMP_CLAUSE_CHAIN (clvec[i]) = (i < len - 1) ? clvec[i + 1] : NULL_TREE;
3029 }
3030 else
3031 clauses = NULL_TREE;
3032 clvec.release ();
3033 return clauses;
3034}
3035
3036/* Change argument indexes in CLAUSES of FNDECL back to PARM_DECLs. */
3037
3038void
3039c_omp_declare_simd_clauses_to_decls (tree fndecl, tree clauses)
3040{
3041 tree c;
3042
3043 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
3044 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_SIMDLEN
3045 && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_INBRANCH
3046 && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_NOTINBRANCH)
3047 {
3048 int idx = tree_to_shwi (OMP_CLAUSE_DECL (c)), i;
3049 tree arg;
3050 for (arg = DECL_ARGUMENTS (fndecl), i = 0; arg;
3051 arg = TREE_CHAIN (arg), i++)
3052 if (i == idx)
3053 break;
3054 gcc_assert (arg);
3055 OMP_CLAUSE_DECL (c) = arg;
3056 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3057 && OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (c))
3058 {
3059 idx = tree_to_shwi (OMP_CLAUSE_LINEAR_STEP (c));
3060 for (arg = DECL_ARGUMENTS (fndecl), i = 0; arg;
3061 arg = TREE_CHAIN (arg), i++)
3062 if (i == idx)
3063 break;
3064 gcc_assert (arg);
3065 OMP_CLAUSE_LINEAR_STEP (c) = arg;
3066 }
3067 }
3068}
3069
3070/* Return true for __func__ and similar function-local predefined
3071 variables (which are in OpenMP predetermined shared, allowed in
3072 shared/firstprivate clauses). */
3073
3074bool
3075c_omp_predefined_variable (tree decl)
3076{
3077 if (VAR_P (decl)
3078 && DECL_ARTIFICIAL (decl)
3079 && TREE_STATIC (decl)
3080 && DECL_NAME (decl))
3081 {
3082 if (TREE_READONLY (decl)
3083 && (DECL_NAME (decl) == ridpointers[RID_C99_FUNCTION_NAME]
3084 || DECL_NAME (decl) == ridpointers[RID_FUNCTION_NAME]
3085 || DECL_NAME (decl) == ridpointers[RID_PRETTY_FUNCTION_NAME]))
3086 return true;
3087 /* For UBSan handle the same also ubsan_create_data created
3088 variables. There is no magic flag for those, but user variables
3089 shouldn't be DECL_ARTIFICIAL or have TYPE_ARTIFICIAL type with
3090 such names. */
3091 if ((flag_sanitize & (SANITIZE_UNDEFINED
3092 | SANITIZE_UNDEFINED_NONDEFAULT)) != 0
3093 && DECL_IGNORED_P (decl)
3094 && !TREE_READONLY (decl)
3095 && TREE_CODE (DECL_NAME (decl)) == IDENTIFIER_NODE
3096 && TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE
3097 && TYPE_ARTIFICIAL (TREE_TYPE (decl))
3098 && TYPE_NAME (TREE_TYPE (decl))
3099 && TREE_CODE (TYPE_NAME (TREE_TYPE (decl))) == TYPE_DECL
3100 && DECL_NAME (TYPE_NAME (TREE_TYPE (decl)))
3101 && (TREE_CODE (DECL_NAME (TYPE_NAME (TREE_TYPE (decl))))
3102 == IDENTIFIER_NODE))
3103 {
3104 tree id1 = DECL_NAME (decl);
3105 tree id2 = DECL_NAME (TYPE_NAME (TREE_TYPE (decl)));
3106 if (IDENTIFIER_LENGTH (id1) >= sizeof ("ubsan_data") - 1
3107 && IDENTIFIER_LENGTH (id2) >= sizeof ("__ubsan__data")
3108 && !memcmp (IDENTIFIER_POINTER (id2), s2: "__ubsan_",
3109 n: sizeof ("__ubsan_") - 1)
3110 && !memcmp (IDENTIFIER_POINTER (id2) + IDENTIFIER_LENGTH (id2)
3111 - sizeof ("_data") + 1, s2: "_data",
3112 n: sizeof ("_data") - 1)
3113 && strstr (IDENTIFIER_POINTER (id1), needle: "ubsan_data"))
3114 return true;
3115 }
3116 }
3117 return false;
3118}
3119
3120/* OMP_CLAUSE_DEFAULT_UNSPECIFIED unless OpenMP sharing attribute of DECL
3121 is predetermined. */
3122
3123enum omp_clause_default_kind
3124c_omp_predetermined_sharing (tree decl)
3125{
3126 /* Predetermine artificial variables holding integral values, those
3127 are usually result of gimplify_one_sizepos or SAVE_EXPR
3128 gimplification. */
3129 if (VAR_P (decl)
3130 && DECL_ARTIFICIAL (decl)
3131 && INTEGRAL_TYPE_P (TREE_TYPE (decl)))
3132 return OMP_CLAUSE_DEFAULT_SHARED;
3133
3134 if (c_omp_predefined_variable (decl))
3135 return OMP_CLAUSE_DEFAULT_SHARED;
3136
3137 return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
3138}
3139
3140/* OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED unless OpenMP mapping attribute
3141 of DECL is predetermined. */
3142
3143enum omp_clause_defaultmap_kind
3144c_omp_predetermined_mapping (tree decl)
3145{
3146 /* Predetermine artificial variables holding integral values, those
3147 are usually result of gimplify_one_sizepos or SAVE_EXPR
3148 gimplification. */
3149 if (VAR_P (decl)
3150 && DECL_ARTIFICIAL (decl)
3151 && INTEGRAL_TYPE_P (TREE_TYPE (decl)))
3152 return OMP_CLAUSE_DEFAULTMAP_FIRSTPRIVATE;
3153
3154 if (c_omp_predefined_variable (decl))
3155 return OMP_CLAUSE_DEFAULTMAP_TO;
3156
3157 return OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED;
3158}
3159
3160
3161/* Used to merge map clause information in c_omp_adjust_map_clauses. */
3162struct map_clause
3163{
3164 tree clause;
3165 bool firstprivate_ptr_p;
3166 bool decl_mapped;
3167 bool omp_declare_target;
3168 map_clause (void) : clause (NULL_TREE), firstprivate_ptr_p (false),
3169 decl_mapped (false), omp_declare_target (false) { }
3170};
3171
3172/* Adjust map clauses after normal clause parsing, mainly to turn specific
3173 base-pointer map cases into attach/detach and mark them addressable. */
3174void
3175c_omp_adjust_map_clauses (tree clauses, bool is_target)
3176{
3177 if (!is_target)
3178 {
3179 /* If this is not a target construct, just turn firstprivate pointers
3180 into attach/detach, the runtime will check and do the rest. */
3181
3182 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
3183 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
3184 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
3185 && DECL_P (OMP_CLAUSE_DECL (c))
3186 && POINTER_TYPE_P (TREE_TYPE (OMP_CLAUSE_DECL (c))))
3187 {
3188 tree ptr = OMP_CLAUSE_DECL (c);
3189 OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_ATTACH_DETACH);
3190 c_common_mark_addressable_vec (ptr);
3191 }
3192 return;
3193 }
3194
3195 hash_map<tree, map_clause> maps;
3196
3197 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
3198 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
3199 && DECL_P (OMP_CLAUSE_DECL (c)))
3200 {
3201 /* If this is for a target construct, the firstprivate pointer
3202 is changed to attach/detach if either is true:
3203 (1) the base-pointer is mapped in this same construct, or
3204 (2) the base-pointer is a variable place on the device by
3205 "declare target" directives.
3206
3207 Here we iterate through all map clauses collecting these cases,
3208 and merge them with a hash_map to process below. */
3209
3210 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
3211 && POINTER_TYPE_P (TREE_TYPE (OMP_CLAUSE_DECL (c))))
3212 {
3213 tree ptr = OMP_CLAUSE_DECL (c);
3214 map_clause &mc = maps.get_or_insert (k: ptr);
3215 if (mc.clause == NULL_TREE)
3216 mc.clause = c;
3217 mc.firstprivate_ptr_p = true;
3218
3219 if (is_global_var (t: ptr)
3220 && lookup_attribute (attr_name: "omp declare target",
3221 DECL_ATTRIBUTES (ptr)))
3222 mc.omp_declare_target = true;
3223 }
3224 else if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALLOC
3225 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_TO
3226 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FROM
3227 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_TOFROM
3228 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_TO
3229 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_FROM
3230 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_TOFROM)
3231 {
3232 map_clause &mc = maps.get_or_insert (OMP_CLAUSE_DECL (c));
3233 mc.decl_mapped = true;
3234 }
3235 }
3236
3237 for (hash_map<tree, map_clause>::iterator i = maps.begin ();
3238 i != maps.end (); ++i)
3239 {
3240 map_clause &mc = (*i).second;
3241
3242 if (mc.firstprivate_ptr_p
3243 && (mc.decl_mapped || mc.omp_declare_target))
3244 {
3245 OMP_CLAUSE_SET_MAP_KIND (mc.clause, GOMP_MAP_ATTACH_DETACH);
3246 c_common_mark_addressable_vec (OMP_CLAUSE_DECL (mc.clause));
3247 }
3248 }
3249}
3250
3251const struct c_omp_directive c_omp_directives[] = {
3252 /* Keep this alphabetically sorted by the first word. Non-null second/third
3253 if any should precede null ones. */
3254 { .first: "allocate", .second: nullptr, .third: nullptr, .id: PRAGMA_OMP_ALLOCATE,
3255 .kind: C_OMP_DIR_DECLARATIVE, .simd: false },
3256 { .first: "assume", .second: nullptr, .third: nullptr, .id: PRAGMA_OMP_ASSUME,
3257 .kind: C_OMP_DIR_INFORMATIONAL, .simd: false },
3258 { .first: "assumes", .second: nullptr, .third: nullptr, .id: PRAGMA_OMP_ASSUMES,
3259 .kind: C_OMP_DIR_INFORMATIONAL, .simd: false },
3260 { .first: "atomic", .second: nullptr, .third: nullptr, .id: PRAGMA_OMP_ATOMIC,
3261 .kind: C_OMP_DIR_CONSTRUCT, .simd: false },
3262 { .first: "barrier", .second: nullptr, .third: nullptr, .id: PRAGMA_OMP_BARRIER,
3263 .kind: C_OMP_DIR_STANDALONE, .simd: false },
3264 { .first: "begin", .second: "assumes", .third: nullptr, .id: PRAGMA_OMP_BEGIN,
3265 .kind: C_OMP_DIR_INFORMATIONAL, .simd: false },
3266 { .first: "begin", .second: "declare", .third: "target", .id: PRAGMA_OMP_BEGIN,
3267 .kind: C_OMP_DIR_DECLARATIVE, .simd: false },
3268 /* { "begin", "declare", "variant", PRAGMA_OMP_BEGIN,
3269 C_OMP_DIR_DECLARATIVE, false }, */
3270 /* { "begin", "metadirective", nullptr, PRAGMA_OMP_BEGIN,
3271 C_OMP_DIR_???, ??? }, */
3272 { .first: "cancel", .second: nullptr, .third: nullptr, .id: PRAGMA_OMP_CANCEL,
3273 .kind: C_OMP_DIR_STANDALONE, .simd: false },
3274 { .first: "cancellation", .second: "point", .third: nullptr, .id: PRAGMA_OMP_CANCELLATION_POINT,
3275 .kind: C_OMP_DIR_STANDALONE, .simd: false },
3276 { .first: "critical", .second: nullptr, .third: nullptr, .id: PRAGMA_OMP_CRITICAL,
3277 .kind: C_OMP_DIR_CONSTRUCT, .simd: false },
3278 /* { "declare", "mapper", nullptr, PRAGMA_OMP_DECLARE,
3279 C_OMP_DIR_DECLARATIVE, false }, */
3280 { .first: "declare", .second: "reduction", .third: nullptr, .id: PRAGMA_OMP_DECLARE,
3281 .kind: C_OMP_DIR_DECLARATIVE, .simd: true },
3282 { .first: "declare", .second: "simd", .third: nullptr, .id: PRAGMA_OMP_DECLARE,
3283 .kind: C_OMP_DIR_DECLARATIVE, .simd: true },
3284 { .first: "declare", .second: "target", .third: nullptr, .id: PRAGMA_OMP_DECLARE,
3285 .kind: C_OMP_DIR_DECLARATIVE, .simd: false },
3286 { .first: "declare", .second: "variant", .third: nullptr, .id: PRAGMA_OMP_DECLARE,
3287 .kind: C_OMP_DIR_DECLARATIVE, .simd: false },
3288 { .first: "depobj", .second: nullptr, .third: nullptr, .id: PRAGMA_OMP_DEPOBJ,
3289 .kind: C_OMP_DIR_STANDALONE, .simd: false },
3290 /* { "dispatch", nullptr, nullptr, PRAGMA_OMP_DISPATCH,
3291 C_OMP_DIR_CONSTRUCT, false }, */
3292 { .first: "distribute", .second: nullptr, .third: nullptr, .id: PRAGMA_OMP_DISTRIBUTE,
3293 .kind: C_OMP_DIR_CONSTRUCT, .simd: true },
3294 { .first: "end", .second: "assumes", .third: nullptr, .id: PRAGMA_OMP_END,
3295 .kind: C_OMP_DIR_INFORMATIONAL, .simd: false },
3296 { .first: "end", .second: "declare", .third: "target", .id: PRAGMA_OMP_END,
3297 .kind: C_OMP_DIR_DECLARATIVE, .simd: false },
3298 /* { "end", "declare", "variant", PRAGMA_OMP_END,
3299 C_OMP_DIR_DECLARATIVE, false }, */
3300 /* { "end", "metadirective", nullptr, PRAGMA_OMP_END,
3301 C_OMP_DIR_???, ??? }, */
3302 /* error with at(execution) is C_OMP_DIR_STANDALONE. */
3303 { .first: "error", .second: nullptr, .third: nullptr, .id: PRAGMA_OMP_ERROR,
3304 .kind: C_OMP_DIR_UTILITY, .simd: false },
3305 { .first: "flush", .second: nullptr, .third: nullptr, .id: PRAGMA_OMP_FLUSH,
3306 .kind: C_OMP_DIR_STANDALONE, .simd: false },
3307 { .first: "for", .second: nullptr, .third: nullptr, .id: PRAGMA_OMP_FOR,
3308 .kind: C_OMP_DIR_CONSTRUCT, .simd: true },
3309 /* { "groupprivate", nullptr, nullptr, PRAGMA_OMP_GROUPPRIVATE,
3310 C_OMP_DIR_DECLARATIVE, false }, */
3311 /* { "interop", nullptr, nullptr, PRAGMA_OMP_INTEROP,
3312 C_OMP_DIR_STANDALONE, false }, */
3313 { .first: "loop", .second: nullptr, .third: nullptr, .id: PRAGMA_OMP_LOOP,
3314 .kind: C_OMP_DIR_CONSTRUCT, .simd: true },
3315 { .first: "masked", .second: nullptr, .third: nullptr, .id: PRAGMA_OMP_MASKED,
3316 .kind: C_OMP_DIR_CONSTRUCT, .simd: true },
3317 { .first: "master", .second: nullptr, .third: nullptr, .id: PRAGMA_OMP_MASTER,
3318 .kind: C_OMP_DIR_CONSTRUCT, .simd: true },
3319 /* { "metadirective", nullptr, nullptr, PRAGMA_OMP_METADIRECTIVE,
3320 C_OMP_DIR_???, ??? }, */
3321 { .first: "nothing", .second: nullptr, .third: nullptr, .id: PRAGMA_OMP_NOTHING,
3322 .kind: C_OMP_DIR_UTILITY, .simd: false },
3323 /* ordered with depend clause is C_OMP_DIR_STANDALONE. */
3324 { .first: "ordered", .second: nullptr, .third: nullptr, .id: PRAGMA_OMP_ORDERED,
3325 .kind: C_OMP_DIR_CONSTRUCT, .simd: true },
3326 { .first: "parallel", .second: nullptr, .third: nullptr, .id: PRAGMA_OMP_PARALLEL,
3327 .kind: C_OMP_DIR_CONSTRUCT, .simd: true },
3328 { .first: "requires", .second: nullptr, .third: nullptr, .id: PRAGMA_OMP_REQUIRES,
3329 .kind: C_OMP_DIR_INFORMATIONAL, .simd: false },
3330 { .first: "scan", .second: nullptr, .third: nullptr, .id: PRAGMA_OMP_SCAN,
3331 .kind: C_OMP_DIR_CONSTRUCT, .simd: true },
3332 { .first: "scope", .second: nullptr, .third: nullptr, .id: PRAGMA_OMP_SCOPE,
3333 .kind: C_OMP_DIR_CONSTRUCT, .simd: false },
3334 { .first: "section", .second: nullptr, .third: nullptr, .id: PRAGMA_OMP_SECTION,
3335 .kind: C_OMP_DIR_CONSTRUCT, .simd: false },
3336 { .first: "sections", .second: nullptr, .third: nullptr, .id: PRAGMA_OMP_SECTIONS,
3337 .kind: C_OMP_DIR_CONSTRUCT, .simd: false },
3338 { .first: "simd", .second: nullptr, .third: nullptr, .id: PRAGMA_OMP_SIMD,
3339 .kind: C_OMP_DIR_CONSTRUCT, .simd: true },
3340 { .first: "single", .second: nullptr, .third: nullptr, .id: PRAGMA_OMP_SINGLE,
3341 .kind: C_OMP_DIR_CONSTRUCT, .simd: false },
3342 { .first: "target", .second: "data", .third: nullptr, .id: PRAGMA_OMP_TARGET,
3343 .kind: C_OMP_DIR_CONSTRUCT, .simd: false },
3344 { .first: "target", .second: "enter", .third: "data", .id: PRAGMA_OMP_TARGET,
3345 .kind: C_OMP_DIR_STANDALONE, .simd: false },
3346 { .first: "target", .second: "exit", .third: "data", .id: PRAGMA_OMP_TARGET,
3347 .kind: C_OMP_DIR_STANDALONE, .simd: false },
3348 { .first: "target", .second: "update", .third: nullptr, .id: PRAGMA_OMP_TARGET,
3349 .kind: C_OMP_DIR_STANDALONE, .simd: false },
3350 { .first: "target", .second: nullptr, .third: nullptr, .id: PRAGMA_OMP_TARGET,
3351 .kind: C_OMP_DIR_CONSTRUCT, .simd: true },
3352 { .first: "task", .second: nullptr, .third: nullptr, .id: PRAGMA_OMP_TASK,
3353 .kind: C_OMP_DIR_CONSTRUCT, .simd: false },
3354 { .first: "taskgroup", .second: nullptr, .third: nullptr, .id: PRAGMA_OMP_TASKGROUP,
3355 .kind: C_OMP_DIR_CONSTRUCT, .simd: false },
3356 { .first: "taskloop", .second: nullptr, .third: nullptr, .id: PRAGMA_OMP_TASKLOOP,
3357 .kind: C_OMP_DIR_CONSTRUCT, .simd: true },
3358 { .first: "taskwait", .second: nullptr, .third: nullptr, .id: PRAGMA_OMP_TASKWAIT,
3359 .kind: C_OMP_DIR_STANDALONE, .simd: false },
3360 { .first: "taskyield", .second: nullptr, .third: nullptr, .id: PRAGMA_OMP_TASKYIELD,
3361 .kind: C_OMP_DIR_STANDALONE, .simd: false },
3362 /* { "tile", nullptr, nullptr, PRAGMA_OMP_TILE,
3363 C_OMP_DIR_CONSTRUCT, false }, */
3364 { .first: "teams", .second: nullptr, .third: nullptr, .id: PRAGMA_OMP_TEAMS,
3365 .kind: C_OMP_DIR_CONSTRUCT, .simd: true },
3366 { .first: "threadprivate", .second: nullptr, .third: nullptr, .id: PRAGMA_OMP_THREADPRIVATE,
3367 .kind: C_OMP_DIR_DECLARATIVE, .simd: false }
3368 /* { "unroll", nullptr, nullptr, PRAGMA_OMP_UNROLL,
3369 C_OMP_DIR_CONSTRUCT, false }, */
3370};
3371
3372/* Find (non-combined/composite) OpenMP directive (if any) which starts
3373 with FIRST keyword and for multi-word directives has SECOND and
3374 THIRD keyword after it. */
3375
3376const struct c_omp_directive *
3377c_omp_categorize_directive (const char *first, const char *second,
3378 const char *third)
3379{
3380 const size_t n_omp_directives = ARRAY_SIZE (c_omp_directives);
3381 for (size_t i = 0; i < n_omp_directives; i++)
3382 {
3383 if ((unsigned char) c_omp_directives[i].first[0]
3384 < (unsigned char) first[0])
3385 continue;
3386 if ((unsigned char) c_omp_directives[i].first[0]
3387 > (unsigned char) first[0])
3388 break;
3389 if (strcmp (s1: c_omp_directives[i].first, s2: first))
3390 continue;
3391 if (!c_omp_directives[i].second)
3392 return &c_omp_directives[i];
3393 if (!second || strcmp (s1: c_omp_directives[i].second, s2: second))
3394 continue;
3395 if (!c_omp_directives[i].third)
3396 return &c_omp_directives[i];
3397 if (!third || strcmp (s1: c_omp_directives[i].third, s2: third))
3398 continue;
3399 return &c_omp_directives[i];
3400 }
3401 return NULL;
3402}
3403

source code of gcc/c-family/c-omp.cc