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