Branch data Line data Source code
1 : : /* This file contains routines to construct OpenACC and OpenMP constructs,
2 : : called from parsing in the C and C++ front ends.
3 : :
4 : : Copyright (C) 2005-2025 Free Software Foundation, Inc.
5 : : Contributed by Richard Henderson <rth@redhat.com>,
6 : : Diego Novillo <dnovillo@redhat.com>.
7 : :
8 : : This file is part of GCC.
9 : :
10 : : GCC is free software; you can redistribute it and/or modify it under
11 : : the terms of the GNU General Public License as published by the Free
12 : : Software Foundation; either version 3, or (at your option) any later
13 : : version.
14 : :
15 : : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
16 : : WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 : : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 : : for more details.
19 : :
20 : : You should have received a copy of the GNU General Public License
21 : : along with GCC; see the file COPYING3. If not see
22 : : <http://www.gnu.org/licenses/>. */
23 : :
24 : : #include "config.h"
25 : : #include "system.h"
26 : : #include "coretypes.h"
27 : : #include "options.h"
28 : : #include "c-common.h"
29 : : #include "gimple-expr.h"
30 : : #include "c-pragma.h"
31 : : #include "stringpool.h"
32 : : #include "omp-general.h"
33 : : #include "gomp-constants.h"
34 : : #include "memmodel.h"
35 : : #include "attribs.h"
36 : : #include "gimplify.h"
37 : : #include "langhooks.h"
38 : : #include "bitmap.h"
39 : : #include "tree-iterator.h"
40 : :
41 : :
42 : : /* Complete a #pragma oacc wait construct. LOC is the location of
43 : : the #pragma. */
44 : :
45 : : tree
46 : 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 : 730 : c_finish_omp_master (location_t loc, tree stmt)
89 : : {
90 : 730 : tree t = add_stmt (build1 (OMP_MASTER, void_type_node, stmt));
91 : 730 : SET_EXPR_LOCATION (t, loc);
92 : 730 : 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 : 377 : c_finish_omp_masked (location_t loc, tree body, tree clauses)
100 : : {
101 : 377 : tree stmt = make_node (OMP_MASKED);
102 : 377 : TREE_TYPE (stmt) = void_type_node;
103 : 377 : OMP_MASKED_BODY (stmt) = body;
104 : 377 : OMP_MASKED_CLAUSES (stmt) = clauses;
105 : 377 : SET_EXPR_LOCATION (stmt, loc);
106 : 377 : 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 : 1558 : c_finish_omp_ordered (location_t loc, tree clauses, tree stmt)
155 : : {
156 : 1558 : tree t = make_node (OMP_ORDERED);
157 : 1558 : TREE_TYPE (t) = void_type_node;
158 : 1558 : OMP_ORDERED_BODY (t) = stmt;
159 : 1558 : if (!flag_openmp /* flag_openmp_simd */
160 : 1598 : && (OMP_CLAUSE_CODE (clauses) != OMP_CLAUSE_SIMD
161 : 40 : || OMP_CLAUSE_CHAIN (clauses)))
162 : 4 : clauses = build_omp_clause (loc, OMP_CLAUSE_SIMD);
163 : 1558 : OMP_ORDERED_CLAUSES (t) = clauses;
164 : 1558 : SET_EXPR_LOCATION (t, loc);
165 : 1558 : 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 : 348 : c_finish_omp_barrier (location_t loc)
174 : : {
175 : 348 : tree x;
176 : :
177 : 348 : x = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER);
178 : 348 : x = build_call_expr_loc (loc, x, 0);
179 : 348 : add_stmt (x);
180 : 348 : }
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 : 4592 : 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 : 4592 : tree x, type, addr, pre = NULL_TREE, rtmp = NULL_TREE, vtmp = NULL_TREE;
229 : 4592 : HOST_WIDE_INT bitpos = 0, bitsize = 0;
230 : 4592 : enum tree_code orig_opcode = opcode;
231 : :
232 : 4592 : if (lhs == error_mark_node || rhs == error_mark_node
233 : 4592 : || v == error_mark_node || lhs1 == error_mark_node
234 : 4592 : || 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 : 4592 : type = TREE_TYPE (lhs);
242 : 4592 : 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 : 4585 : if (TYPE_ATOMIC (type))
250 : : {
251 : 8 : error_at (loc, "%<_Atomic%> expression in %<#pragma omp atomic%>");
252 : 8 : return error_mark_node;
253 : : }
254 : 4577 : 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 : 4573 : if (opcode == RDIV_EXPR)
262 : 0 : opcode = TRUNC_DIV_EXPR;
263 : :
264 : : /* ??? Validate that rhs does not overlap lhs. */
265 : 4573 : tree blhs = NULL;
266 : 4573 : 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 : 4623 : && 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 : 4573 : addr = build_unary_op (loc, ADDR_EXPR, lhs, false);
292 : 4573 : if (addr == error_mark_node)
293 : : return error_mark_node;
294 : 4564 : if (!test)
295 : 4351 : addr = save_expr (addr);
296 : 4351 : if (!test
297 : 4351 : && TREE_CODE (addr) != SAVE_EXPR
298 : 3756 : && (TREE_CODE (addr) != ADDR_EXPR
299 : 3577 : || !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 : 4564 : tree orig_lhs = lhs;
308 : 4564 : lhs = build_indirect_ref (loc, addr, RO_NULL);
309 : 4564 : tree new_lhs = lhs;
310 : :
311 : 4564 : 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 : 3814 : 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 : 3766 : 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 : 3432 : else if (swapped)
355 : : {
356 : 124 : rhs = build_binary_op (loc, opcode, rhs, lhs, true);
357 : 124 : opcode = NOP_EXPR;
358 : : }
359 : 3814 : bool save = in_late_binary_op;
360 : 3814 : in_late_binary_op = true;
361 : 3814 : if ((opcode == MIN_EXPR || opcode == MAX_EXPR)
362 : 4102 : && build_binary_op (loc, LT_EXPR, blhs ? blhs : lhs, rhs,
363 : 288 : true) == error_mark_node)
364 : : x = error_mark_node;
365 : : else
366 : 7572 : x = build_modify_expr (loc, blhs ? blhs : lhs, NULL_TREE, opcode,
367 : : loc, rhs, NULL_TREE);
368 : 3814 : in_late_binary_op = save;
369 : 3814 : if (x == error_mark_node)
370 : : return error_mark_node;
371 : 3794 : 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 : 3794 : gcc_assert (TREE_CODE (x) == MODIFY_EXPR);
378 : 3794 : rhs = TREE_OPERAND (x, 1);
379 : :
380 : 3794 : if (blhs)
381 : 48 : rhs = build3_loc (loc, BIT_INSERT_EXPR, type, new_lhs,
382 : 48 : rhs, bitsize_int (bitpos));
383 : 3794 : 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 : 3794 : if (code == OMP_ATOMIC)
530 : 2528 : type = void_type_node;
531 : 3794 : x = build2 (code, type, addr, rhs);
532 : 3794 : SET_EXPR_LOCATION (x, loc);
533 : 3794 : OMP_ATOMIC_MEMORY_ORDER (x) = memory_order;
534 : 3794 : 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 : 3794 : 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 : 3794 : if (lhs1
554 : 3794 : && 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 : 3806 : && 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 : 3794 : 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 : 3810 : && 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 : 3794 : 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 : 2528 : 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 : 3789 : if (pre)
645 : 14 : x = omit_one_operand_loc (loc, type, x, pre);
646 : 3789 : 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 : 3789 : 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 : 61 : c_finish_omp_flush (location_t loc, int mo)
848 : : {
849 : 61 : tree x;
850 : :
851 : 61 : if (mo == MEMMODEL_LAST || mo == MEMMODEL_SEQ_CST)
852 : : {
853 : 43 : x = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
854 : 43 : 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 : 61 : add_stmt (x);
863 : 61 : }
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 : 31940 : c_omp_for_incr_canonicalize_ptr (location_t loc, tree decl, tree incr)
938 : : {
939 : 61873 : if (POINTER_TYPE_P (TREE_TYPE (decl))
940 : 31940 : && 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 : 31940 : 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 : 31903 : 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 : 31903 : location_t elocus;
971 : 31903 : bool fail = false;
972 : 31903 : int i;
973 : :
974 : 31903 : gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (initv));
975 : 31903 : gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (condv));
976 : 31903 : gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (incrv));
977 : 73790 : for (i = 0; i < TREE_VEC_LENGTH (declv); i++)
978 : : {
979 : 43265 : tree decl = TREE_VEC_ELT (declv, i);
980 : 43265 : tree init = TREE_VEC_ELT (initv, i);
981 : 43265 : tree cond = TREE_VEC_ELT (condv, i);
982 : 43265 : tree incr = TREE_VEC_ELT (incrv, i);
983 : :
984 : 43265 : 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 : 41887 : elocus = locus;
998 : 41887 : if (EXPR_HAS_LOCATION (init))
999 : 37211 : elocus = EXPR_LOCATION (init);
1000 : :
1001 : : /* Validate the iteration variable. */
1002 : 83774 : if (!INTEGRAL_TYPE_P (TREE_TYPE (decl))
1003 : 44757 : && 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 : 41886 : 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 : 41871 : if (init == decl)
1020 : : {
1021 : 4660 : elocus = DECL_SOURCE_LOCATION (decl);
1022 : :
1023 : 4660 : init = DECL_INITIAL (decl);
1024 : 4660 : 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 : 4660 : DECL_INITIAL (decl) = NULL_TREE;
1031 : :
1032 : 4660 : 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 : 41871 : if (init != error_mark_node)
1040 : : {
1041 : 41871 : gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
1042 : 41871 : gcc_assert (TREE_OPERAND (init, 0) == decl);
1043 : : }
1044 : :
1045 : 41871 : if (cond == NULL_TREE)
1046 : : {
1047 : 2 : error_at (elocus, "missing controlling predicate");
1048 : 2 : fail = true;
1049 : : }
1050 : : else
1051 : : {
1052 : 41869 : 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 : 41869 : while (TREE_CODE (cond) == COMPOUND_EXPR)
1058 : 0 : cond = TREE_OPERAND (cond, 1);
1059 : :
1060 : 41869 : if (EXPR_HAS_LOCATION (cond))
1061 : 41741 : elocus = EXPR_LOCATION (cond);
1062 : :
1063 : 41869 : if (TREE_CODE (cond) == LT_EXPR
1064 : : || TREE_CODE (cond) == LE_EXPR
1065 : : || TREE_CODE (cond) == GT_EXPR
1066 : 41869 : || TREE_CODE (cond) == GE_EXPR
1067 : 5587 : || TREE_CODE (cond) == NE_EXPR
1068 : 31 : || TREE_CODE (cond) == EQ_EXPR)
1069 : : {
1070 : 41838 : tree op0 = TREE_OPERAND (cond, 0);
1071 : 41838 : 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 : 41838 : if (TREE_CODE (op0) == NOP_EXPR
1086 : 41838 : && 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 : 41780 : else if (TREE_CODE (op1) == NOP_EXPR
1094 : 41780 : && 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 : 41838 : 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 : 41838 : if (TREE_CODE (cond) == NE_EXPR
1114 : 41838 : || 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 : 41838 : 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 : 41838 : if (!cond_ok)
1152 : : {
1153 : 32 : error_at (elocus, "invalid controlling predicate");
1154 : 32 : fail = true;
1155 : : }
1156 : : }
1157 : :
1158 : 41871 : if (incr == NULL_TREE)
1159 : : {
1160 : 0 : error_at (elocus, "missing increment expression");
1161 : 0 : fail = true;
1162 : : }
1163 : : else
1164 : : {
1165 : 41871 : bool incr_ok = false;
1166 : :
1167 : 41871 : if (EXPR_HAS_LOCATION (incr))
1168 : 40978 : 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 : 41871 : switch (TREE_CODE (incr))
1173 : : {
1174 : 31946 : case POSTINCREMENT_EXPR:
1175 : 31946 : case PREINCREMENT_EXPR:
1176 : 31946 : case POSTDECREMENT_EXPR:
1177 : 31946 : case PREDECREMENT_EXPR:
1178 : 31946 : if (TREE_OPERAND (incr, 0) != decl)
1179 : : break;
1180 : :
1181 : 31940 : incr_ok = true;
1182 : 31940 : if (!fail
1183 : 31915 : && 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 : 32759 : && (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 : 31940 : incr = c_omp_for_incr_canonicalize_ptr (elocus, decl, incr);
1198 : 31940 : 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 : 9909 : case MODIFY_EXPR:
1208 : 9909 : if (TREE_OPERAND (incr, 0) != decl)
1209 : : break;
1210 : 9909 : if (TREE_OPERAND (incr, 1) == decl)
1211 : : break;
1212 : 9909 : if (TREE_CODE (TREE_OPERAND (incr, 1)) == PLUS_EXPR
1213 : 9909 : && (TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl
1214 : 286 : || TREE_OPERAND (TREE_OPERAND (incr, 1), 1) == decl))
1215 : : incr_ok = true;
1216 : 2065 : else if ((TREE_CODE (TREE_OPERAND (incr, 1)) == MINUS_EXPR
1217 : 1041 : || (TREE_CODE (TREE_OPERAND (incr, 1))
1218 : : == POINTER_PLUS_EXPR))
1219 : 2926 : && 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 : 9909 : if (!fail
1234 : 9909 : && incr_ok
1235 : 9891 : && 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 : 41849 : if (!incr_ok)
1291 : : {
1292 : 34 : error_at (elocus, "invalid increment expression");
1293 : 34 : fail = true;
1294 : : }
1295 : : }
1296 : :
1297 : 41871 : TREE_VEC_ELT (initv, i) = init;
1298 : 41871 : TREE_VEC_ELT (incrv, i) = incr;
1299 : : }
1300 : :
1301 : 31903 : if (fail)
1302 : : return NULL;
1303 : : else
1304 : : {
1305 : 31618 : tree t = make_node (code);
1306 : :
1307 : 31618 : TREE_TYPE (t) = void_type_node;
1308 : 31618 : OMP_FOR_INIT (t) = initv;
1309 : 31618 : OMP_FOR_COND (t) = condv;
1310 : 31618 : OMP_FOR_INCR (t) = incrv;
1311 : 31618 : OMP_FOR_BODY (t) = body;
1312 : 31618 : OMP_FOR_PRE_BODY (t) = pre_body;
1313 : 31618 : OMP_FOR_ORIG_DECLS (t) = orig_declv;
1314 : :
1315 : 31618 : SET_EXPR_LOCATION (t, locus);
1316 : 31618 : 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 : 41988 : c_omp_is_loop_iterator (tree decl, struct c_omp_check_loop_iv_data *d)
1342 : : {
1343 : 133075 : for (int i = 0; i < TREE_VEC_LENGTH (d->declv); i++)
1344 : 105584 : if (TREE_VEC_ELT (d->declv, i) == NULL_TREE)
1345 : 253 : continue;
1346 : 105331 : else if (decl == TREE_VEC_ELT (d->declv, i)
1347 : 105331 : || (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 : 90915 : else if (TREE_CODE (TREE_VEC_ELT (d->declv, i)) == TREE_LIST
1351 : 2223 : && TREE_CHAIN (TREE_VEC_ELT (d->declv, i))
1352 : 91954 : && (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 : 169793 : c_omp_check_loop_iv_r (tree *tp, int *walk_subtrees, void *data)
1367 : : {
1368 : 169793 : struct c_omp_check_loop_iv_data *d
1369 : : = (struct c_omp_check_loop_iv_data *) data;
1370 : 169793 : if (DECL_P (*tp))
1371 : : {
1372 : 28528 : int idx = c_omp_is_loop_iterator (*tp, d);
1373 : 28528 : 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 : 141265 : 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 : 17115 : *walk_subtrees = 0;
1415 : 17115 : d->kind &= 3;
1416 : 17115 : walk_tree_1 (tp, c_omp_check_loop_iv_r, data, NULL, d->lh);
1417 : 17115 : d->kind |= 4;
1418 : 17115 : return NULL_TREE;
1419 : : }
1420 : 124150 : else if (d->ppset->add (*tp))
1421 : 17848 : *walk_subtrees = 0;
1422 : : /* Don't walk dtors added by C++ wrap_cleanups_r. */
1423 : 106302 : else if (TREE_CODE (*tp) == TRY_CATCH_EXPR
1424 : 106302 : && 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 : 10060 : c_find_nested_loop_xform_r (tree *tp, int *walk_subtrees, void *)
1630 : : {
1631 : 10060 : *walk_subtrees = 0;
1632 : 10060 : switch (TREE_CODE (*tp))
1633 : : {
1634 : : case OMP_TILE:
1635 : : case OMP_UNROLL:
1636 : : return *tp;
1637 : 2817 : case BIND_EXPR:
1638 : 2817 : *walk_subtrees = 1;
1639 : 2817 : 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 : 31618 : c_omp_check_loop_iv (tree stmt, tree declv, walk_tree_lh lh)
1694 : : {
1695 : 31618 : hash_set<tree> pset;
1696 : 31618 : struct c_omp_check_loop_iv_data data;
1697 : 31618 : int i, k = 0;
1698 : :
1699 : 31618 : data.declv = declv;
1700 : 31618 : data.fail = false;
1701 : 31618 : data.maybe_nonrect = false;
1702 : 31618 : data.stmt_loc = EXPR_LOCATION (stmt);
1703 : 31618 : data.lh = lh;
1704 : 31618 : data.ppset = &pset;
1705 : 74865 : for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (stmt)); i++)
1706 : : {
1707 : 43247 : tree this_stmt = stmt;
1708 : 43247 : int j = i;
1709 : 43247 : tree init = TREE_VEC_ELT (OMP_FOR_INIT (stmt), i);
1710 : 43247 : 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 : 43247 : gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
1720 : 43247 : tree decl = TREE_OPERAND (init, 0);
1721 : 43247 : tree cond = TREE_VEC_ELT (OMP_FOR_COND (this_stmt), j);
1722 : 43247 : gcc_assert (COMPARISON_CLASS_P (cond));
1723 : 43247 : gcc_assert (TREE_OPERAND (cond, 0) == decl);
1724 : 43247 : tree incr = TREE_VEC_ELT (OMP_FOR_INCR (this_stmt), j);
1725 : 43247 : data.expr_loc = EXPR_LOCATION (TREE_OPERAND (init, 1));
1726 : 43247 : tree vec_outer1 = NULL_TREE, vec_outer2 = NULL_TREE;
1727 : 43247 : int kind = 0;
1728 : 43247 : if (i > 0
1729 : 43247 : && (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 : 43247 : if (TREE_CODE (stmt) != OACC_LOOP && i > 0)
1740 : 43247 : kind = 4;
1741 : 43247 : data.kind = kind;
1742 : 43247 : data.idx = i;
1743 : 43247 : walk_tree_1 (&TREE_OPERAND (init, 1),
1744 : : c_omp_check_loop_iv_r, &data, NULL, lh);
1745 : 43247 : 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 : 43247 : if (decl == TREE_VEC_ELT (data.declv, i)
1753 : 43247 : || (TREE_CODE (TREE_VEC_ELT (data.declv, i)) == TREE_LIST
1754 : 933 : && decl == TREE_PURPOSE (TREE_VEC_ELT (data.declv, i))))
1755 : : {
1756 : 42314 : data.expr_loc = EXPR_LOCATION (cond);
1757 : 42314 : data.kind = kind | 1;
1758 : 42314 : walk_tree_1 (&TREE_OPERAND (cond, 1),
1759 : : c_omp_check_loop_iv_r, &data, NULL, lh);
1760 : 42314 : if (data.maybe_nonrect)
1761 : 387 : vec_outer2 = c_omp_check_nonrect_loop_iv (&TREE_OPERAND (cond, 1),
1762 : : &data, lh);
1763 : : }
1764 : 43247 : 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 : 43239 : 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 : 43247 : if (vec_outer1 || vec_outer2)
1783 : 474 : OMP_FOR_NON_RECTANGULAR (stmt) = 1;
1784 : 43247 : if (TREE_CODE (incr) == MODIFY_EXPR)
1785 : : {
1786 : 11740 : gcc_assert (TREE_OPERAND (incr, 0) == decl);
1787 : 11740 : incr = TREE_OPERAND (incr, 1);
1788 : 11740 : data.kind = 2;
1789 : 11740 : if (TREE_CODE (incr) == PLUS_EXPR
1790 : 11740 : && 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 : 11441 : data.expr_loc = EXPR_LOCATION (TREE_OPERAND (incr, 1));
1799 : 11441 : walk_tree_1 (&TREE_OPERAND (incr, 1),
1800 : : c_omp_check_loop_iv_r, &data, NULL, lh);
1801 : : }
1802 : : }
1803 : : }
1804 : 31618 : return !data.fail;
1805 : 31618 : }
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 : 3909 : find_binding_in_body (tree decl, tree body)
1862 : : {
1863 : 5367 : if (!body)
1864 : : return NULL_TREE;
1865 : :
1866 : 5367 : switch (TREE_CODE (body))
1867 : : {
1868 : 365 : case BIND_EXPR:
1869 : 502 : for (tree b = BIND_EXPR_VARS (body); b; b = DECL_CHAIN (b))
1870 : 165 : if (b == decl)
1871 : : return body;
1872 : 337 : 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 : 1016 : case STATEMENT_LIST:
1880 : 4509 : for (tree_stmt_iterator si = tsi_start (body); !tsi_end_p (si);
1881 : 3493 : tsi_next (&si))
1882 : : {
1883 : 3521 : tree b = find_binding_in_body (decl, tsi_stmt (si));
1884 : 3521 : if (b)
1885 : 28 : return b;
1886 : : }
1887 : 988 : return NULL_TREE;
1888 : :
1889 : 1121 : case OMP_STRUCTURED_BLOCK:
1890 : 1121 : 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 : 808 : check_loop_binding_expr_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
1904 : : void *data)
1905 : : {
1906 : 808 : tree body = *(tree *)data;
1907 : :
1908 : 808 : 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 : 622 : check_loop_binding_expr (tree expr, tree body, location_t loc,
1931 : : check_loop_binding_expr_ctx ctx)
1932 : : {
1933 : 622 : tree bad = walk_tree (&expr, check_loop_binding_expr_r, (void *)&body, NULL);
1934 : :
1935 : 622 : 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 : 173 : c_omp_check_loop_binding_exprs (tree stmt, vec<tree> *orig_inits)
1969 : : {
1970 : 173 : bool ok = true;
1971 : 173 : location_t loc = EXPR_LOCATION (stmt);
1972 : 173 : tree body = OMP_FOR_BODY (stmt);
1973 : 308 : int orig_init_length = orig_inits ? orig_inits->length () : 0;
1974 : :
1975 : 376 : for (int i = 1; i < TREE_VEC_LENGTH (OMP_FOR_INIT (stmt)); i++)
1976 : : {
1977 : 203 : tree init = TREE_VEC_ELT (OMP_FOR_INIT (stmt), i);
1978 : 203 : 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 : 187 : tree cond = TREE_VEC_ELT (OMP_FOR_COND (stmt), i);
1985 : 187 : tree incr = TREE_VEC_ELT (OMP_FOR_INCR (stmt), i);
1986 : 187 : gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
1987 : 187 : tree decl = TREE_OPERAND (init, 0);
1988 : 187 : tree orig_init = i < orig_init_length ? (*orig_inits)[i] : NULL_TREE;
1989 : 187 : tree e;
1990 : 187 : location_t eloc;
1991 : :
1992 : 187 : e = TREE_OPERAND (init, 1);
1993 : 187 : eloc = LOCATION_OR (EXPR_LOCATION (init), loc);
1994 : 187 : if (!check_loop_binding_expr (decl, body, eloc,
1995 : : CHECK_LOOP_BINDING_EXPR_CTX_LOOP_VAR))
1996 : 14 : ok = false;
1997 : 187 : if (!check_loop_binding_expr (e, body, eloc,
1998 : : CHECK_LOOP_BINDING_EXPR_CTX_IN_INIT))
1999 : 15 : ok = false;
2000 : 187 : if (orig_init
2001 : 187 : && !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 : 187 : if (cond)
2008 : : {
2009 : 187 : eloc = LOCATION_OR (EXPR_LOCATION (cond), loc);
2010 : 187 : if (COMPARISON_CLASS_P (cond) && TREE_OPERAND (cond, 0) == decl)
2011 : 185 : 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 : 187 : if (!check_loop_binding_expr (e, body, eloc,
2017 : : CHECK_LOOP_BINDING_EXPR_CTX_END_TEST))
2018 : 187 : ok = false;
2019 : : }
2020 : :
2021 : 187 : if (incr)
2022 : : {
2023 : 185 : 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 : 185 : if (TREE_CODE (incr) == MODIFY_EXPR
2028 : 185 : && !check_loop_binding_expr (TREE_OPERAND (incr, 1), body, eloc,
2029 : : CHECK_LOOP_BINDING_EXPR_CTX_INCR))
2030 : : ok = false;
2031 : : }
2032 : : }
2033 : :
2034 : 173 : 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 : 1832 : c_oacc_split_loop_clauses (tree clauses, tree *not_loop_clauses,
2044 : : bool is_parallel)
2045 : : {
2046 : 1832 : tree next, loop_clauses, nc;
2047 : :
2048 : 1832 : loop_clauses = *not_loop_clauses = NULL_TREE;
2049 : 3616 : for (; clauses ; clauses = next)
2050 : : {
2051 : 1784 : next = OMP_CLAUSE_CHAIN (clauses);
2052 : :
2053 : 1784 : 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 : 496 : default:
2088 : 496 : OMP_CLAUSE_CHAIN (clauses) = *not_loop_clauses;
2089 : 496 : *not_loop_clauses = clauses;
2090 : 496 : break;
2091 : : }
2092 : : }
2093 : :
2094 : 1832 : 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 : 15816 : c_omp_split_clauses (location_t loc, enum tree_code code,
2143 : : omp_clause_mask mask, tree clauses, tree *cclauses)
2144 : : {
2145 : 15816 : tree next, c;
2146 : 15816 : enum c_omp_clause_split s;
2147 : 15816 : int i;
2148 : 15816 : bool has_dup_allocate = false;
2149 : :
2150 : 110712 : for (i = 0; i < C_OMP_CLAUSE_SPLIT_COUNT; i++)
2151 : 94896 : cclauses[i] = NULL;
2152 : : /* Add implicit nowait clause on
2153 : : #pragma omp parallel {for,for simd,sections}. */
2154 : 15816 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0)
2155 : 10943 : switch (code)
2156 : : {
2157 : 10285 : case OMP_FOR:
2158 : 10285 : case OMP_SIMD:
2159 : 25919 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0)
2160 : 10103 : cclauses[C_OMP_CLAUSE_SPLIT_FOR]
2161 : 10103 : = 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 : 55628 : for (; clauses ; clauses = next)
2172 : : {
2173 : 39812 : next = OMP_CLAUSE_CHAIN (clauses);
2174 : :
2175 : 39812 : 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_MAP:
2180 : : case OMP_CLAUSE_IS_DEVICE_PTR:
2181 : : case OMP_CLAUSE_HAS_DEVICE_ADDR:
2182 : : case OMP_CLAUSE_DEFAULTMAP:
2183 : : case OMP_CLAUSE_DEPEND:
2184 : : s = C_OMP_CLAUSE_SPLIT_TARGET;
2185 : : break;
2186 : 4 : case OMP_CLAUSE_DOACROSS:
2187 : : /* This can happen with invalid depend(source) or
2188 : : depend(sink:vec) on target combined with other constructs. */
2189 : 4 : gcc_assert (OMP_CLAUSE_DOACROSS_DEPEND (clauses));
2190 : : s = C_OMP_CLAUSE_SPLIT_TARGET;
2191 : : break;
2192 : : case OMP_CLAUSE_NUM_TEAMS:
2193 : 2454 : s = C_OMP_CLAUSE_SPLIT_TEAMS;
2194 : : break;
2195 : : case OMP_CLAUSE_DIST_SCHEDULE:
2196 : 6925 : s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE;
2197 : : break;
2198 : : case OMP_CLAUSE_COPYIN:
2199 : : case OMP_CLAUSE_NUM_THREADS:
2200 : : case OMP_CLAUSE_PROC_BIND:
2201 : 7732 : s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2202 : : break;
2203 : : case OMP_CLAUSE_ORDERED:
2204 : 13075 : s = C_OMP_CLAUSE_SPLIT_FOR;
2205 : : break;
2206 : 6075 : case OMP_CLAUSE_SCHEDULE:
2207 : 6075 : s = C_OMP_CLAUSE_SPLIT_FOR;
2208 : 6075 : if (code != OMP_SIMD)
2209 : 3076 : OMP_CLAUSE_SCHEDULE_SIMD (clauses) = 0;
2210 : : break;
2211 : : case OMP_CLAUSE_SAFELEN:
2212 : : case OMP_CLAUSE_SIMDLEN:
2213 : : case OMP_CLAUSE_ALIGNED:
2214 : : case OMP_CLAUSE_NONTEMPORAL:
2215 : 5337 : s = C_OMP_CLAUSE_SPLIT_SIMD;
2216 : : break;
2217 : : case OMP_CLAUSE_GRAINSIZE:
2218 : : case OMP_CLAUSE_NUM_TASKS:
2219 : : case OMP_CLAUSE_FINAL:
2220 : : case OMP_CLAUSE_UNTIED:
2221 : : case OMP_CLAUSE_MERGEABLE:
2222 : : case OMP_CLAUSE_NOGROUP:
2223 : : case OMP_CLAUSE_PRIORITY:
2224 : 13075 : s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
2225 : : break;
2226 : : case OMP_CLAUSE_BIND:
2227 : 13075 : s = C_OMP_CLAUSE_SPLIT_LOOP;
2228 : : break;
2229 : : case OMP_CLAUSE_FILTER:
2230 : 6925 : s = C_OMP_CLAUSE_SPLIT_MASKED;
2231 : : break;
2232 : : /* Duplicate this to all of taskloop, distribute, for, simd and
2233 : : loop. */
2234 : 5056 : case OMP_CLAUSE_COLLAPSE:
2235 : 5056 : if (code == OMP_SIMD)
2236 : : {
2237 : 2575 : if ((mask & ((OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)
2238 : 2575 : | (OMP_CLAUSE_MASK_1
2239 : 2575 : << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)
2240 : 2575 : | (OMP_CLAUSE_MASK_1
2241 : 2575 : << PRAGMA_OMP_CLAUSE_NOGROUP))) != 0)
2242 : : {
2243 : 2527 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2244 : : OMP_CLAUSE_COLLAPSE);
2245 : 2527 : OMP_CLAUSE_COLLAPSE_EXPR (c)
2246 : 2527 : = OMP_CLAUSE_COLLAPSE_EXPR (clauses);
2247 : 2527 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_SIMD];
2248 : 2527 : cclauses[C_OMP_CLAUSE_SPLIT_SIMD] = c;
2249 : : }
2250 : : else
2251 : : {
2252 : : /* This must be #pragma omp target simd */
2253 : : s = C_OMP_CLAUSE_SPLIT_SIMD;
2254 : : break;
2255 : : }
2256 : : }
2257 : 5008 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0)
2258 : : {
2259 : 3908 : if ((mask & (OMP_CLAUSE_MASK_1
2260 : 3908 : << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0)
2261 : : {
2262 : 2621 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2263 : : OMP_CLAUSE_COLLAPSE);
2264 : 2621 : OMP_CLAUSE_COLLAPSE_EXPR (c)
2265 : 2621 : = OMP_CLAUSE_COLLAPSE_EXPR (clauses);
2266 : 2621 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_FOR];
2267 : 2621 : cclauses[C_OMP_CLAUSE_SPLIT_FOR] = c;
2268 : 2621 : s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE;
2269 : : }
2270 : : else
2271 : : s = C_OMP_CLAUSE_SPLIT_FOR;
2272 : : }
2273 : 1100 : else if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP))
2274 : 13761 : != 0)
2275 : : s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
2276 : 686 : else if (code == OMP_LOOP)
2277 : : s = C_OMP_CLAUSE_SPLIT_LOOP;
2278 : : else
2279 : 6925 : s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE;
2280 : : break;
2281 : : /* Private clause is supported on all constructs but master/masked,
2282 : : it is enough to put it on the innermost one other than
2283 : : master/masked. For #pragma omp {for,sections} put it on parallel
2284 : : though, as that's what we did for OpenMP 3.1. */
2285 : 1293 : case OMP_CLAUSE_PRIVATE:
2286 : 1293 : switch (code)
2287 : : {
2288 : : case OMP_SIMD: s = C_OMP_CLAUSE_SPLIT_SIMD; break;
2289 : : case OMP_FOR: case OMP_SECTIONS:
2290 : 7732 : case OMP_PARALLEL: s = C_OMP_CLAUSE_SPLIT_PARALLEL; break;
2291 : 6925 : case OMP_DISTRIBUTE: s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE; break;
2292 : 2454 : case OMP_TEAMS: s = C_OMP_CLAUSE_SPLIT_TEAMS; break;
2293 : 7732 : case OMP_MASTER: s = C_OMP_CLAUSE_SPLIT_PARALLEL; break;
2294 : 7732 : case OMP_MASKED: s = C_OMP_CLAUSE_SPLIT_PARALLEL; break;
2295 : 13075 : case OMP_TASKLOOP: s = C_OMP_CLAUSE_SPLIT_TASKLOOP; break;
2296 : 13075 : case OMP_LOOP: s = C_OMP_CLAUSE_SPLIT_LOOP; break;
2297 : 0 : default: gcc_unreachable ();
2298 : : }
2299 : : break;
2300 : : /* Firstprivate clause is supported on all constructs but
2301 : : simd, master, masked and loop. Put it on the outermost of those
2302 : : and duplicate on teams and parallel. */
2303 : 1741 : case OMP_CLAUSE_FIRSTPRIVATE:
2304 : 1741 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP))
2305 : 2101 : != 0)
2306 : : {
2307 : 388 : if (code == OMP_SIMD
2308 : 388 : && (mask & ((OMP_CLAUSE_MASK_1
2309 : 134 : << PRAGMA_OMP_CLAUSE_NUM_THREADS)
2310 : 134 : | (OMP_CLAUSE_MASK_1
2311 : 134 : << PRAGMA_OMP_CLAUSE_NUM_TEAMS))) == 0)
2312 : : {
2313 : : /* This must be #pragma omp target simd. */
2314 : 28 : s = C_OMP_CLAUSE_SPLIT_TARGET;
2315 : 28 : OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (clauses) = 1;
2316 : 28 : OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT_TARGET (clauses) = 1;
2317 : 28 : break;
2318 : : }
2319 : 360 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2320 : : OMP_CLAUSE_FIRSTPRIVATE);
2321 : : /* firstprivate should not be applied to target if it is
2322 : : also lastprivate or on the combined/composite construct,
2323 : : or if it is mentioned in map clause. OMP_CLAUSE_DECLs
2324 : : may need to go through FE handling though (instantiation,
2325 : : C++ non-static data members, array section lowering), so
2326 : : add the clause with OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT and
2327 : : let *finish_omp_clauses and the gimplifier handle it
2328 : : right. */
2329 : 360 : OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c) = 1;
2330 : 360 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2331 : 360 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
2332 : 360 : cclauses[C_OMP_CLAUSE_SPLIT_TARGET] = c;
2333 : : }
2334 : 1713 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS))
2335 : 1713 : != 0)
2336 : : {
2337 : 1105 : if ((mask & ((OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS)
2338 : 1105 : | (OMP_CLAUSE_MASK_1
2339 : 1105 : << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE))) != 0)
2340 : : {
2341 : 465 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2342 : : OMP_CLAUSE_FIRSTPRIVATE);
2343 : 465 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2344 : 465 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL];
2345 : 465 : cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL] = c;
2346 : 465 : if ((mask & (OMP_CLAUSE_MASK_1
2347 : 465 : << PRAGMA_OMP_CLAUSE_NUM_TEAMS)) != 0)
2348 : : s = C_OMP_CLAUSE_SPLIT_TEAMS;
2349 : : else
2350 : 6925 : s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE;
2351 : : }
2352 : 640 : else if ((mask & (OMP_CLAUSE_MASK_1
2353 : 640 : << PRAGMA_OMP_CLAUSE_NOGROUP)) != 0)
2354 : : /* This must be
2355 : : #pragma omp parallel mas{ked,ter} taskloop{, simd}. */
2356 : : s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
2357 : : else
2358 : : /* This must be
2359 : : #pragma omp parallel{, for{, simd}, sections,loop}
2360 : : or
2361 : : #pragma omp target parallel. */
2362 : 7732 : s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2363 : : }
2364 : 608 : else if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS))
2365 : 608 : != 0)
2366 : : {
2367 : : /* This must be one of
2368 : : #pragma omp {,target }teams {distribute,loop}
2369 : : #pragma omp target teams
2370 : : #pragma omp {,target }teams distribute simd. */
2371 : 276 : gcc_assert (code == OMP_DISTRIBUTE
2372 : : || code == OMP_LOOP
2373 : : || code == OMP_TEAMS
2374 : : || code == OMP_SIMD);
2375 : : s = C_OMP_CLAUSE_SPLIT_TEAMS;
2376 : : }
2377 : 332 : else if ((mask & (OMP_CLAUSE_MASK_1
2378 : 332 : << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0)
2379 : : {
2380 : : /* This must be #pragma omp distribute simd. */
2381 : 76 : gcc_assert (code == OMP_SIMD);
2382 : : s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE;
2383 : : }
2384 : 256 : else if ((mask & (OMP_CLAUSE_MASK_1
2385 : 256 : << PRAGMA_OMP_CLAUSE_NOGROUP)) != 0)
2386 : : {
2387 : : /* This must be
2388 : : #pragma omp {,{,parallel }mas{ked,ter} }taskloop simd
2389 : : or
2390 : : #pragma omp {,parallel }mas{ked,ter} taskloop. */
2391 : 228 : gcc_assert (code == OMP_SIMD || code == OMP_TASKLOOP);
2392 : : s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
2393 : : }
2394 : : else
2395 : : {
2396 : : /* This must be #pragma omp for simd. */
2397 : 28 : gcc_assert (code == OMP_SIMD);
2398 : : s = C_OMP_CLAUSE_SPLIT_FOR;
2399 : : }
2400 : : break;
2401 : : /* Lastprivate is allowed on distribute, for, sections, taskloop, loop
2402 : : and simd. In parallel {for{, simd},sections} we actually want to
2403 : : put it on parallel rather than for or sections. */
2404 : 1955 : case OMP_CLAUSE_LASTPRIVATE:
2405 : 1955 : if (code == OMP_DISTRIBUTE)
2406 : : {
2407 : : s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE;
2408 : : break;
2409 : : }
2410 : 1947 : if ((mask & (OMP_CLAUSE_MASK_1
2411 : 1947 : << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0)
2412 : : {
2413 : 548 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2414 : : OMP_CLAUSE_LASTPRIVATE);
2415 : 548 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2416 : 548 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE];
2417 : 1096 : OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c)
2418 : 548 : = OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (clauses);
2419 : 548 : cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE] = c;
2420 : : }
2421 : 1947 : if (code == OMP_FOR || code == OMP_SECTIONS)
2422 : : {
2423 : 823 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS))
2424 : 20807 : != 0)
2425 : : s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2426 : : else
2427 : 13075 : s = C_OMP_CLAUSE_SPLIT_FOR;
2428 : : break;
2429 : : }
2430 : : if (code == OMP_TASKLOOP)
2431 : : {
2432 : : s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
2433 : : break;
2434 : : }
2435 : : if (code == OMP_LOOP)
2436 : : {
2437 : : s = C_OMP_CLAUSE_SPLIT_LOOP;
2438 : : break;
2439 : : }
2440 : 0 : gcc_assert (code == OMP_SIMD);
2441 : 812 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0)
2442 : : {
2443 : 423 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2444 : : OMP_CLAUSE_LASTPRIVATE);
2445 : 423 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2446 : 846 : OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c)
2447 : 423 : = OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (clauses);
2448 : 423 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS))
2449 : 498 : != 0)
2450 : : s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2451 : : else
2452 : 75 : s = C_OMP_CLAUSE_SPLIT_FOR;
2453 : 423 : OMP_CLAUSE_CHAIN (c) = cclauses[s];
2454 : 423 : cclauses[s] = c;
2455 : : }
2456 : 812 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP)) != 0)
2457 : : {
2458 : 253 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2459 : : OMP_CLAUSE_LASTPRIVATE);
2460 : 253 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2461 : 506 : OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c)
2462 : 253 : = OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (clauses);
2463 : 253 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP];
2464 : 253 : cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP] = c;
2465 : : }
2466 : : s = C_OMP_CLAUSE_SPLIT_SIMD;
2467 : : break;
2468 : : /* Shared and default clauses are allowed on parallel, teams and
2469 : : taskloop. */
2470 : 3559 : case OMP_CLAUSE_SHARED:
2471 : 3559 : case OMP_CLAUSE_DEFAULT:
2472 : 3559 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP))
2473 : 3559 : != 0)
2474 : : {
2475 : 890 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS))
2476 : 13431 : != 0)
2477 : : {
2478 : 712 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2479 : 356 : OMP_CLAUSE_CODE (clauses));
2480 : 356 : if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_SHARED)
2481 : 128 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2482 : : else
2483 : 456 : OMP_CLAUSE_DEFAULT_KIND (c)
2484 : 228 : = OMP_CLAUSE_DEFAULT_KIND (clauses);
2485 : 356 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL];
2486 : 356 : cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL] = c;
2487 : : }
2488 : : s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
2489 : : break;
2490 : : }
2491 : 2669 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS))
2492 : 9027 : != 0)
2493 : : {
2494 : 1295 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS))
2495 : 3062 : == 0)
2496 : : {
2497 : : s = C_OMP_CLAUSE_SPLIT_TEAMS;
2498 : : break;
2499 : : }
2500 : 1216 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2501 : 608 : OMP_CLAUSE_CODE (clauses));
2502 : 608 : if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_SHARED)
2503 : 284 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2504 : : else
2505 : 648 : OMP_CLAUSE_DEFAULT_KIND (c)
2506 : 324 : = OMP_CLAUSE_DEFAULT_KIND (clauses);
2507 : 608 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
2508 : 608 : cclauses[C_OMP_CLAUSE_SPLIT_TEAMS] = c;
2509 : : }
2510 : : s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2511 : : break;
2512 : : /* order clauses are allowed on distribute, for, simd and loop. */
2513 : 880 : case OMP_CLAUSE_ORDER:
2514 : 880 : if ((mask & (OMP_CLAUSE_MASK_1
2515 : 880 : << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0)
2516 : : {
2517 : 332 : if (code == OMP_DISTRIBUTE)
2518 : : {
2519 : : s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE;
2520 : : break;
2521 : : }
2522 : 288 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2523 : : OMP_CLAUSE_ORDER);
2524 : 576 : OMP_CLAUSE_ORDER_UNCONSTRAINED (c)
2525 : 288 : = OMP_CLAUSE_ORDER_UNCONSTRAINED (clauses);
2526 : 576 : OMP_CLAUSE_ORDER_REPRODUCIBLE (c)
2527 : 288 : = OMP_CLAUSE_ORDER_REPRODUCIBLE (clauses);
2528 : 288 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE];
2529 : 288 : cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE] = c;
2530 : : }
2531 : 836 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0)
2532 : : {
2533 : 465 : if (code == OMP_SIMD)
2534 : : {
2535 : 317 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2536 : : OMP_CLAUSE_ORDER);
2537 : 634 : OMP_CLAUSE_ORDER_UNCONSTRAINED (c)
2538 : 317 : = OMP_CLAUSE_ORDER_UNCONSTRAINED (clauses);
2539 : 634 : OMP_CLAUSE_ORDER_REPRODUCIBLE (c)
2540 : 317 : = OMP_CLAUSE_ORDER_REPRODUCIBLE (clauses);
2541 : 317 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_FOR];
2542 : 317 : cclauses[C_OMP_CLAUSE_SPLIT_FOR] = c;
2543 : 317 : s = C_OMP_CLAUSE_SPLIT_SIMD;
2544 : : }
2545 : : else
2546 : : s = C_OMP_CLAUSE_SPLIT_FOR;
2547 : : }
2548 : 371 : else if (code == OMP_LOOP)
2549 : : s = C_OMP_CLAUSE_SPLIT_LOOP;
2550 : : else
2551 : 5337 : s = C_OMP_CLAUSE_SPLIT_SIMD;
2552 : : break;
2553 : : /* Reduction is allowed on simd, for, parallel, sections, taskloop,
2554 : : teams and loop. Duplicate it on all of them, but omit on for or
2555 : : sections if parallel is present (unless inscan, in that case
2556 : : omit on parallel). If taskloop or loop is combined with
2557 : : parallel, omit it on parallel. */
2558 : 2905 : case OMP_CLAUSE_REDUCTION:
2559 : 2905 : if (OMP_CLAUSE_REDUCTION_TASK (clauses))
2560 : : {
2561 : 56 : if (code == OMP_SIMD || code == OMP_LOOP)
2562 : : {
2563 : 16 : error_at (OMP_CLAUSE_LOCATION (clauses),
2564 : : "invalid %<task%> reduction modifier on construct "
2565 : : "combined with %<simd%> or %<loop%>");
2566 : 16 : OMP_CLAUSE_REDUCTION_TASK (clauses) = 0;
2567 : : }
2568 : 40 : else if (code != OMP_SECTIONS
2569 : 34 : && (mask & (OMP_CLAUSE_MASK_1
2570 : 34 : << PRAGMA_OMP_CLAUSE_NUM_THREADS)) == 0
2571 : 40 : && (mask & (OMP_CLAUSE_MASK_1
2572 : 4 : << PRAGMA_OMP_CLAUSE_SCHEDULE)) == 0)
2573 : : {
2574 : 4 : error_at (OMP_CLAUSE_LOCATION (clauses),
2575 : : "invalid %<task%> reduction modifier on construct "
2576 : : "not combined with %<parallel%>, %<for%> or "
2577 : : "%<sections%>");
2578 : 4 : OMP_CLAUSE_REDUCTION_TASK (clauses) = 0;
2579 : : }
2580 : : }
2581 : 2905 : if (OMP_CLAUSE_REDUCTION_INSCAN (clauses)
2582 : 2905 : && ((mask & ((OMP_CLAUSE_MASK_1
2583 : 196 : << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)
2584 : 196 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)))
2585 : 2917 : != 0))
2586 : : {
2587 : 12 : error_at (OMP_CLAUSE_LOCATION (clauses),
2588 : : "%<inscan%> %<reduction%> clause on construct other "
2589 : : "than %<for%>, %<simd%>, %<for simd%>, "
2590 : : "%<parallel for%>, %<parallel for simd%>");
2591 : 12 : OMP_CLAUSE_REDUCTION_INSCAN (clauses) = 0;
2592 : : }
2593 : 2905 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)) != 0)
2594 : : {
2595 : 572 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2596 : : OMP_CLAUSE_MAP);
2597 : 572 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2598 : 572 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_TOFROM);
2599 : 572 : OMP_CLAUSE_MAP_IMPLICIT (c) = 1;
2600 : 572 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
2601 : 572 : cclauses[C_OMP_CLAUSE_SPLIT_TARGET] = c;
2602 : : }
2603 : 2905 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0)
2604 : : {
2605 : 1748 : if (code == OMP_SIMD)
2606 : : {
2607 : 561 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2608 : : OMP_CLAUSE_REDUCTION);
2609 : 561 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2610 : 1122 : OMP_CLAUSE_REDUCTION_CODE (c)
2611 : 561 : = OMP_CLAUSE_REDUCTION_CODE (clauses);
2612 : 561 : OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
2613 : 561 : = OMP_CLAUSE_REDUCTION_PLACEHOLDER (clauses);
2614 : 561 : OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c)
2615 : 561 : = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clauses);
2616 : 1122 : OMP_CLAUSE_REDUCTION_INSCAN (c)
2617 : 561 : = OMP_CLAUSE_REDUCTION_INSCAN (clauses);
2618 : 561 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_SIMD];
2619 : 561 : cclauses[C_OMP_CLAUSE_SPLIT_SIMD] = c;
2620 : : }
2621 : 1748 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS))
2622 : 1748 : != 0)
2623 : : {
2624 : 464 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2625 : : OMP_CLAUSE_REDUCTION);
2626 : 464 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2627 : 928 : OMP_CLAUSE_REDUCTION_CODE (c)
2628 : 464 : = OMP_CLAUSE_REDUCTION_CODE (clauses);
2629 : 464 : OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
2630 : 464 : = OMP_CLAUSE_REDUCTION_PLACEHOLDER (clauses);
2631 : 464 : OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c)
2632 : 464 : = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clauses);
2633 : 928 : OMP_CLAUSE_REDUCTION_INSCAN (c)
2634 : 464 : = OMP_CLAUSE_REDUCTION_INSCAN (clauses);
2635 : 464 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
2636 : 464 : cclauses[C_OMP_CLAUSE_SPLIT_TEAMS] = c;
2637 : 464 : s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2638 : : }
2639 : 1284 : else if ((mask & (OMP_CLAUSE_MASK_1
2640 : 1284 : << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0
2641 : 1195 : && !OMP_CLAUSE_REDUCTION_INSCAN (clauses))
2642 : : s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2643 : : else
2644 : 13075 : s = C_OMP_CLAUSE_SPLIT_FOR;
2645 : : }
2646 : 1157 : else if (code == OMP_SECTIONS
2647 : 1157 : || code == OMP_PARALLEL
2648 : : || code == OMP_MASTER
2649 : : || code == OMP_MASKED)
2650 : : s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2651 : : else if (code == OMP_TASKLOOP)
2652 : : s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
2653 : : else if (code == OMP_LOOP)
2654 : : s = C_OMP_CLAUSE_SPLIT_LOOP;
2655 : : else if (code == OMP_SIMD)
2656 : : {
2657 : 437 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP))
2658 : 437 : != 0)
2659 : : {
2660 : 247 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2661 : : OMP_CLAUSE_REDUCTION);
2662 : 247 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2663 : 494 : OMP_CLAUSE_REDUCTION_CODE (c)
2664 : 247 : = OMP_CLAUSE_REDUCTION_CODE (clauses);
2665 : 247 : OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
2666 : 247 : = OMP_CLAUSE_REDUCTION_PLACEHOLDER (clauses);
2667 : 247 : OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c)
2668 : 247 : = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clauses);
2669 : 494 : OMP_CLAUSE_REDUCTION_INSCAN (c)
2670 : 247 : = OMP_CLAUSE_REDUCTION_INSCAN (clauses);
2671 : 247 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP];
2672 : 247 : cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP] = c;
2673 : : }
2674 : 190 : else if ((mask & (OMP_CLAUSE_MASK_1
2675 : 190 : << PRAGMA_OMP_CLAUSE_NUM_TEAMS)) != 0)
2676 : : {
2677 : 90 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2678 : : OMP_CLAUSE_REDUCTION);
2679 : 90 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2680 : 180 : OMP_CLAUSE_REDUCTION_CODE (c)
2681 : 90 : = OMP_CLAUSE_REDUCTION_CODE (clauses);
2682 : 90 : OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
2683 : 90 : = OMP_CLAUSE_REDUCTION_PLACEHOLDER (clauses);
2684 : 90 : OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c)
2685 : 90 : = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clauses);
2686 : 180 : OMP_CLAUSE_REDUCTION_INSCAN (c)
2687 : 90 : = OMP_CLAUSE_REDUCTION_INSCAN (clauses);
2688 : 90 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
2689 : 90 : cclauses[C_OMP_CLAUSE_SPLIT_TEAMS] = c;
2690 : : }
2691 : : s = C_OMP_CLAUSE_SPLIT_SIMD;
2692 : : }
2693 : : else
2694 : : s = C_OMP_CLAUSE_SPLIT_TEAMS;
2695 : : break;
2696 : 396 : case OMP_CLAUSE_IN_REDUCTION:
2697 : 396 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)) != 0)
2698 : : {
2699 : : /* When on target, map(always, tofrom: item) is added as
2700 : : well. For non-combined target it is added in the FEs. */
2701 : 228 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2702 : : OMP_CLAUSE_MAP);
2703 : 228 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2704 : 228 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_ALWAYS_TOFROM);
2705 : 228 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
2706 : 228 : cclauses[C_OMP_CLAUSE_SPLIT_TARGET] = c;
2707 : 228 : s = C_OMP_CLAUSE_SPLIT_TARGET;
2708 : 228 : break;
2709 : : }
2710 : : /* in_reduction on taskloop simd becomes reduction on the simd
2711 : : and keeps being in_reduction on taskloop. */
2712 : 168 : if (code == OMP_SIMD)
2713 : : {
2714 : 108 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2715 : : OMP_CLAUSE_REDUCTION);
2716 : 108 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses);
2717 : 216 : OMP_CLAUSE_REDUCTION_CODE (c)
2718 : 108 : = OMP_CLAUSE_REDUCTION_CODE (clauses);
2719 : 108 : OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
2720 : 108 : = OMP_CLAUSE_REDUCTION_PLACEHOLDER (clauses);
2721 : 108 : OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c)
2722 : 108 : = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clauses);
2723 : 108 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_SIMD];
2724 : 108 : cclauses[C_OMP_CLAUSE_SPLIT_SIMD] = c;
2725 : : }
2726 : : s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
2727 : : break;
2728 : 1613 : case OMP_CLAUSE_IF:
2729 : 1613 : if (OMP_CLAUSE_IF_MODIFIER (clauses) != ERROR_MARK)
2730 : : {
2731 : 1188 : s = C_OMP_CLAUSE_SPLIT_COUNT;
2732 : 1188 : switch (OMP_CLAUSE_IF_MODIFIER (clauses))
2733 : : {
2734 : 510 : case OMP_PARALLEL:
2735 : 510 : if ((mask & (OMP_CLAUSE_MASK_1
2736 : 510 : << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0)
2737 : : s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2738 : : break;
2739 : 280 : case OMP_SIMD:
2740 : 280 : if (code == OMP_SIMD)
2741 : : s = C_OMP_CLAUSE_SPLIT_SIMD;
2742 : : break;
2743 : 168 : case OMP_TASKLOOP:
2744 : 168 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP))
2745 : 13083 : != 0)
2746 : : s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
2747 : : break;
2748 : 222 : case OMP_TARGET:
2749 : 222 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP))
2750 : 3144 : != 0)
2751 : : s = C_OMP_CLAUSE_SPLIT_TARGET;
2752 : : break;
2753 : : default:
2754 : : break;
2755 : : }
2756 : : if (s != C_OMP_CLAUSE_SPLIT_COUNT)
2757 : : break;
2758 : : /* Error-recovery here, invalid if-modifier specified, add the
2759 : : clause to just one construct. */
2760 : 8 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)) != 0)
2761 : : s = C_OMP_CLAUSE_SPLIT_TARGET;
2762 : 4 : else if ((mask & (OMP_CLAUSE_MASK_1
2763 : 4 : << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0)
2764 : : s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2765 : 0 : else if ((mask & (OMP_CLAUSE_MASK_1
2766 : 0 : << PRAGMA_OMP_CLAUSE_NOGROUP)) != 0)
2767 : : s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
2768 : 0 : else if (code == OMP_SIMD)
2769 : : s = C_OMP_CLAUSE_SPLIT_SIMD;
2770 : : else
2771 : 0 : gcc_unreachable ();
2772 : : break;
2773 : : }
2774 : : /* Otherwise, duplicate if clause to all constructs. */
2775 : 425 : if (code == OMP_SIMD)
2776 : : {
2777 : 266 : if ((mask & ((OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)
2778 : 266 : | (OMP_CLAUSE_MASK_1
2779 : 266 : << PRAGMA_OMP_CLAUSE_NUM_THREADS)
2780 : 266 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP)))
2781 : 5337 : != 0)
2782 : : {
2783 : 176 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2784 : : OMP_CLAUSE_IF);
2785 : 352 : OMP_CLAUSE_IF_MODIFIER (c)
2786 : 176 : = OMP_CLAUSE_IF_MODIFIER (clauses);
2787 : 176 : OMP_CLAUSE_IF_EXPR (c) = OMP_CLAUSE_IF_EXPR (clauses);
2788 : 176 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_SIMD];
2789 : 176 : cclauses[C_OMP_CLAUSE_SPLIT_SIMD] = c;
2790 : : }
2791 : : else
2792 : : {
2793 : : s = C_OMP_CLAUSE_SPLIT_SIMD;
2794 : : break;
2795 : : }
2796 : : }
2797 : 335 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP))
2798 : 335 : != 0)
2799 : : {
2800 : 144 : if ((mask & (OMP_CLAUSE_MASK_1
2801 : 144 : << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0)
2802 : : {
2803 : 64 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2804 : : OMP_CLAUSE_IF);
2805 : 128 : OMP_CLAUSE_IF_MODIFIER (c)
2806 : 64 : = OMP_CLAUSE_IF_MODIFIER (clauses);
2807 : 64 : OMP_CLAUSE_IF_EXPR (c) = OMP_CLAUSE_IF_EXPR (clauses);
2808 : 64 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP];
2809 : 64 : cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP] = c;
2810 : 64 : s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2811 : : }
2812 : : else
2813 : : s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
2814 : : }
2815 : 191 : else if ((mask & (OMP_CLAUSE_MASK_1
2816 : 191 : << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0)
2817 : : {
2818 : 119 : if ((mask & (OMP_CLAUSE_MASK_1
2819 : 7752 : << PRAGMA_OMP_CLAUSE_MAP)) != 0)
2820 : : {
2821 : 20 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2822 : : OMP_CLAUSE_IF);
2823 : 40 : OMP_CLAUSE_IF_MODIFIER (c)
2824 : 20 : = OMP_CLAUSE_IF_MODIFIER (clauses);
2825 : 20 : OMP_CLAUSE_IF_EXPR (c) = OMP_CLAUSE_IF_EXPR (clauses);
2826 : 20 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
2827 : 20 : cclauses[C_OMP_CLAUSE_SPLIT_TARGET] = c;
2828 : 20 : s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2829 : : }
2830 : : else
2831 : : s = C_OMP_CLAUSE_SPLIT_PARALLEL;
2832 : : }
2833 : : else
2834 : : s = C_OMP_CLAUSE_SPLIT_TARGET;
2835 : : break;
2836 : 800 : case OMP_CLAUSE_LINEAR:
2837 : : /* Linear clause is allowed on simd and for. Put it on the
2838 : : innermost construct. */
2839 : 800 : if (code == OMP_SIMD)
2840 : : s = C_OMP_CLAUSE_SPLIT_SIMD;
2841 : : else
2842 : 13075 : s = C_OMP_CLAUSE_SPLIT_FOR;
2843 : : break;
2844 : 247 : case OMP_CLAUSE_NOWAIT:
2845 : : /* Nowait clause is allowed on target, for and sections, but
2846 : : is not allowed on parallel for or parallel sections. Therefore,
2847 : : put it on target construct if present, because that can only
2848 : : be combined with parallel for{, simd} and not with for{, simd},
2849 : : otherwise to the worksharing construct. */
2850 : 247 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP))
2851 : 16211 : != 0)
2852 : : s = C_OMP_CLAUSE_SPLIT_TARGET;
2853 : : else
2854 : 13075 : s = C_OMP_CLAUSE_SPLIT_FOR;
2855 : : break;
2856 : : /* thread_limit is allowed on target and teams. Distribute it
2857 : : to all. */
2858 : 443 : case OMP_CLAUSE_THREAD_LIMIT:
2859 : 443 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP))
2860 : 2454 : != 0)
2861 : : {
2862 : 231 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS))
2863 : 3136 : != 0)
2864 : : {
2865 : 229 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2866 : : OMP_CLAUSE_THREAD_LIMIT);
2867 : 229 : OMP_CLAUSE_THREAD_LIMIT_EXPR (c)
2868 : 229 : = OMP_CLAUSE_THREAD_LIMIT_EXPR (clauses);
2869 : 229 : OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
2870 : 229 : cclauses[C_OMP_CLAUSE_SPLIT_TARGET] = c;
2871 : : }
2872 : : else
2873 : : {
2874 : : s = C_OMP_CLAUSE_SPLIT_TARGET;
2875 : : break;
2876 : : }
2877 : : }
2878 : : s = C_OMP_CLAUSE_SPLIT_TEAMS;
2879 : : break;
2880 : : /* Allocate clause is allowed on target, teams, distribute, parallel,
2881 : : for, sections and taskloop. Distribute it to all. */
2882 : : case OMP_CLAUSE_ALLOCATE:
2883 : : s = C_OMP_CLAUSE_SPLIT_COUNT;
2884 : 8071 : for (i = 0; i < C_OMP_CLAUSE_SPLIT_COUNT; i++)
2885 : : {
2886 : 6918 : switch (i)
2887 : : {
2888 : 1153 : case C_OMP_CLAUSE_SPLIT_TARGET:
2889 : 2046 : if ((mask & (OMP_CLAUSE_MASK_1
2890 : 1153 : << PRAGMA_OMP_CLAUSE_MAP)) == 0)
2891 : 893 : continue;
2892 : : break;
2893 : 1153 : case C_OMP_CLAUSE_SPLIT_TEAMS:
2894 : 1872 : if ((mask & (OMP_CLAUSE_MASK_1
2895 : 1153 : << PRAGMA_OMP_CLAUSE_NUM_TEAMS)) == 0)
2896 : 719 : continue;
2897 : : break;
2898 : 1153 : case C_OMP_CLAUSE_SPLIT_DISTRIBUTE:
2899 : 1824 : if ((mask & (OMP_CLAUSE_MASK_1
2900 : 1153 : << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) == 0)
2901 : 671 : continue;
2902 : : break;
2903 : 1153 : case C_OMP_CLAUSE_SPLIT_PARALLEL:
2904 : 1525 : if ((mask & (OMP_CLAUSE_MASK_1
2905 : 1153 : << PRAGMA_OMP_CLAUSE_NUM_THREADS)) == 0)
2906 : 372 : continue;
2907 : : break;
2908 : 1153 : case C_OMP_CLAUSE_SPLIT_FOR:
2909 : 1153 : STATIC_ASSERT (C_OMP_CLAUSE_SPLIT_SECTIONS
2910 : : == C_OMP_CLAUSE_SPLIT_FOR
2911 : : && (C_OMP_CLAUSE_SPLIT_TASKLOOP
2912 : : == C_OMP_CLAUSE_SPLIT_FOR)
2913 : : && (C_OMP_CLAUSE_SPLIT_LOOP
2914 : : == C_OMP_CLAUSE_SPLIT_FOR));
2915 : 1153 : if (code == OMP_SECTIONS)
2916 : : break;
2917 : 1137 : if ((mask & (OMP_CLAUSE_MASK_1
2918 : 1137 : << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0)
2919 : : break;
2920 : 602 : if ((mask & (OMP_CLAUSE_MASK_1
2921 : 602 : << PRAGMA_OMP_CLAUSE_NOGROUP)) != 0)
2922 : : break;
2923 : 322 : continue;
2924 : 1153 : case C_OMP_CLAUSE_SPLIT_SIMD:
2925 : 1153 : continue;
2926 : : default:
2927 : : gcc_unreachable ();
2928 : : }
2929 : 2788 : if (s != C_OMP_CLAUSE_SPLIT_COUNT)
2930 : : {
2931 : 1635 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses),
2932 : : OMP_CLAUSE_ALLOCATE);
2933 : 3270 : OMP_CLAUSE_DECL (c)
2934 : 1635 : = OMP_CLAUSE_DECL (clauses);
2935 : 1635 : OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)
2936 : 1635 : = OMP_CLAUSE_ALLOCATE_ALLOCATOR (clauses);
2937 : 1635 : OMP_CLAUSE_ALLOCATE_ALIGN (c)
2938 : 1635 : = OMP_CLAUSE_ALLOCATE_ALIGN (clauses);
2939 : 1635 : OMP_CLAUSE_CHAIN (c) = cclauses[s];
2940 : 1635 : cclauses[s] = c;
2941 : 1635 : has_dup_allocate = true;
2942 : : }
2943 : 2788 : s = (enum c_omp_clause_split) i;
2944 : : }
2945 : 1153 : gcc_assert (s != C_OMP_CLAUSE_SPLIT_COUNT);
2946 : : break;
2947 : 0 : default:
2948 : 0 : gcc_unreachable ();
2949 : : }
2950 : 39812 : OMP_CLAUSE_CHAIN (clauses) = cclauses[s];
2951 : 39812 : cclauses[s] = clauses;
2952 : : }
2953 : :
2954 : 15816 : if (has_dup_allocate)
2955 : : {
2956 : 783 : bool need_prune = false;
2957 : 783 : bitmap_obstack_initialize (NULL);
2958 : 8948 : for (i = 0; i < C_OMP_CLAUSE_SPLIT_SIMD - (code == OMP_LOOP); i++)
2959 : 3851 : if (cclauses[i])
2960 : : {
2961 : 2350 : bitmap_head allocate_head;
2962 : 2350 : bitmap_initialize (&allocate_head, &bitmap_default_obstack);
2963 : 17746 : for (c = cclauses[i]; c; c = OMP_CLAUSE_CHAIN (c))
2964 : 15396 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_ALLOCATE
2965 : 15396 : && DECL_P (OMP_CLAUSE_DECL (c)))
2966 : 4956 : bitmap_set_bit (&allocate_head,
2967 : 2478 : DECL_UID (OMP_CLAUSE_DECL (c)));
2968 : 17746 : for (c = cclauses[i]; c; c = OMP_CLAUSE_CHAIN (c))
2969 : 15396 : switch (OMP_CLAUSE_CODE (c))
2970 : : {
2971 : 1159 : case OMP_CLAUSE_REDUCTION:
2972 : 1159 : case OMP_CLAUSE_IN_REDUCTION:
2973 : 1159 : case OMP_CLAUSE_TASK_REDUCTION:
2974 : 1159 : if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
2975 : : {
2976 : 0 : tree t = TREE_OPERAND (OMP_CLAUSE_DECL (c), 0);
2977 : 0 : if (TREE_CODE (t) == POINTER_PLUS_EXPR)
2978 : 0 : t = TREE_OPERAND (t, 0);
2979 : 0 : if (TREE_CODE (t) == ADDR_EXPR
2980 : 0 : || INDIRECT_REF_P (t))
2981 : 0 : t = TREE_OPERAND (t, 0);
2982 : 0 : if (DECL_P (t))
2983 : 0 : bitmap_clear_bit (&allocate_head, DECL_UID (t));
2984 : : break;
2985 : : }
2986 : 1159 : else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == TREE_LIST)
2987 : : {
2988 : : /* TODO: This can go away once we transition all uses of
2989 : : TREE_LIST for representing OMP array sections to
2990 : : OMP_ARRAY_SECTION. */
2991 : 0 : tree t;
2992 : 0 : for (t = OMP_CLAUSE_DECL (c);
2993 : 0 : TREE_CODE (t) == TREE_LIST; t = TREE_CHAIN (t))
2994 : : ;
2995 : 0 : if (DECL_P (t))
2996 : 0 : bitmap_clear_bit (&allocate_head, DECL_UID (t));
2997 : : break;
2998 : : }
2999 : 1159 : else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == OMP_ARRAY_SECTION)
3000 : : {
3001 : 152 : tree t;
3002 : 152 : for (t = OMP_CLAUSE_DECL (c);
3003 : 304 : TREE_CODE (t) == OMP_ARRAY_SECTION;
3004 : 152 : t = TREE_OPERAND (t, 0))
3005 : : ;
3006 : 152 : if (DECL_P (t))
3007 : 152 : bitmap_clear_bit (&allocate_head, DECL_UID (t));
3008 : : break;
3009 : : }
3010 : : /* FALLTHRU */
3011 : 3261 : case OMP_CLAUSE_PRIVATE:
3012 : 3261 : case OMP_CLAUSE_FIRSTPRIVATE:
3013 : 3261 : case OMP_CLAUSE_LASTPRIVATE:
3014 : 3261 : case OMP_CLAUSE_LINEAR:
3015 : 3261 : if (DECL_P (OMP_CLAUSE_DECL (c)))
3016 : 6522 : bitmap_clear_bit (&allocate_head,
3017 : 3261 : DECL_UID (OMP_CLAUSE_DECL (c)));
3018 : : break;
3019 : : default:
3020 : : break;
3021 : : }
3022 : 17746 : for (c = cclauses[i]; c; c = OMP_CLAUSE_CHAIN (c))
3023 : 15396 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_ALLOCATE
3024 : 2478 : && DECL_P (OMP_CLAUSE_DECL (c))
3025 : 17874 : && bitmap_bit_p (&allocate_head,
3026 : 2478 : DECL_UID (OMP_CLAUSE_DECL (c))))
3027 : : {
3028 : : /* Mark allocate clauses which don't have corresponding
3029 : : explicit data sharing clause. */
3030 : 1089 : OMP_CLAUSE_ALLOCATE_COMBINED (c) = 1;
3031 : 1089 : need_prune = true;
3032 : : }
3033 : : }
3034 : 783 : bitmap_obstack_release (NULL);
3035 : 783 : if (need_prune)
3036 : : {
3037 : : /* At least one allocate clause has been marked. Walk all the
3038 : : duplicated allocate clauses in sync. If it is marked in all
3039 : : constituent constructs, diagnose it as invalid and remove
3040 : : them. Otherwise, remove all marked inner clauses inside
3041 : : a construct that doesn't have them marked. Keep the outer
3042 : : marked ones, because some clause duplication is done only
3043 : : during gimplification. */
3044 : : tree *p[C_OMP_CLAUSE_SPLIT_COUNT];
3045 : 4809 : for (i = 0; i < C_OMP_CLAUSE_SPLIT_COUNT; i++)
3046 : 4122 : if (cclauses[i] == NULL_TREE
3047 : 2418 : || i == C_OMP_CLAUSE_SPLIT_SIMD
3048 : 2158 : || (i == C_OMP_CLAUSE_SPLIT_LOOP && code == OMP_LOOP))
3049 : 1964 : p[i] = NULL;
3050 : : else
3051 : 2158 : p[i] = &cclauses[i];
3052 : 1370 : do
3053 : : {
3054 : 1370 : int j = -1;
3055 : 1370 : tree seen = NULL_TREE;
3056 : 6443 : for (i = C_OMP_CLAUSE_SPLIT_COUNT - 1; i >= 0; i--)
3057 : 5760 : if (p[i])
3058 : : {
3059 : 13697 : while (*p[i]
3060 : 13697 : && OMP_CLAUSE_CODE (*p[i]) != OMP_CLAUSE_ALLOCATE)
3061 : 10724 : p[i] = &OMP_CLAUSE_CHAIN (*p[i]);
3062 : 2973 : if (*p[i] == NULL_TREE)
3063 : : {
3064 : : i = C_OMP_CLAUSE_SPLIT_COUNT;
3065 : : break;
3066 : : }
3067 : 2286 : if (!OMP_CLAUSE_ALLOCATE_COMBINED (*p[i]) && j == -1)
3068 : 5073 : j = i;
3069 : : seen = *p[i];
3070 : : }
3071 : 1370 : if (i == C_OMP_CLAUSE_SPLIT_COUNT)
3072 : : break;
3073 : 683 : if (j == -1)
3074 : 8 : error_at (OMP_CLAUSE_LOCATION (seen),
3075 : : "%qD specified in %<allocate%> clause but not in "
3076 : : "an explicit privatization clause",
3077 : 4 : OMP_CLAUSE_DECL (seen));
3078 : 4781 : for (i = 0; i < C_OMP_CLAUSE_SPLIT_COUNT; i++)
3079 : 4098 : if (p[i])
3080 : : {
3081 : 2158 : if (i > j)
3082 : : /* Remove. */
3083 : 610 : *p[i] = OMP_CLAUSE_CHAIN (*p[i]);
3084 : : else
3085 : : /* Keep. */
3086 : 1548 : p[i] = &OMP_CLAUSE_CHAIN (*p[i]);
3087 : : }
3088 : : }
3089 : : while (1);
3090 : : }
3091 : : }
3092 : :
3093 : 15816 : if (!flag_checking)
3094 : : return;
3095 : :
3096 : 15816 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)) == 0)
3097 : 10652 : gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_TARGET] == NULL_TREE);
3098 : 15816 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS)) == 0)
3099 : 8963 : gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_TEAMS] == NULL_TREE);
3100 : 15816 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) == 0
3101 : 8514 : && (mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FILTER)) == 0)
3102 : 8268 : gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE] == NULL_TREE);
3103 : 15816 : if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS)) == 0)
3104 : 4873 : gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL] == NULL_TREE);
3105 : 15816 : if ((mask & ((OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)
3106 : 15816 : | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP))) == 0
3107 : 4092 : && code != OMP_SECTIONS
3108 : 4092 : && code != OMP_LOOP)
3109 : 3632 : gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_FOR] == NULL_TREE);
3110 : 15816 : if (code != OMP_SIMD)
3111 : 9310 : gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_SIMD] == NULL_TREE);
3112 : : }
3113 : :
3114 : :
3115 : : /* qsort callback to compare #pragma omp declare simd clauses. */
3116 : :
3117 : : static int
3118 : 12176 : c_omp_declare_simd_clause_cmp (const void *p, const void *q)
3119 : : {
3120 : 12176 : tree a = *(const tree *) p;
3121 : 12176 : tree b = *(const tree *) q;
3122 : 12176 : if (OMP_CLAUSE_CODE (a) != OMP_CLAUSE_CODE (b))
3123 : : {
3124 : 10701 : if (OMP_CLAUSE_CODE (a) > OMP_CLAUSE_CODE (b))
3125 : : return -1;
3126 : 4474 : return 1;
3127 : : }
3128 : 1475 : if (OMP_CLAUSE_CODE (a) != OMP_CLAUSE_SIMDLEN
3129 : : && OMP_CLAUSE_CODE (a) != OMP_CLAUSE_INBRANCH
3130 : : && OMP_CLAUSE_CODE (a) != OMP_CLAUSE_NOTINBRANCH)
3131 : : {
3132 : 1451 : int c = tree_to_shwi (OMP_CLAUSE_DECL (a));
3133 : 1451 : int d = tree_to_shwi (OMP_CLAUSE_DECL (b));
3134 : 1451 : if (c < d)
3135 : : return 1;
3136 : 670 : if (c > d)
3137 : 670 : return -1;
3138 : : }
3139 : : return 0;
3140 : : }
3141 : :
3142 : : /* Change PARM_DECLs in OMP_CLAUSE_DECL of #pragma omp declare simd
3143 : : CLAUSES on FNDECL into argument indexes and sort them. */
3144 : :
3145 : : tree
3146 : 1396 : c_omp_declare_simd_clauses_to_numbers (tree parms, tree clauses)
3147 : : {
3148 : 1396 : tree c;
3149 : 1396 : vec<tree> clvec = vNULL;
3150 : :
3151 : 4443 : for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
3152 : : {
3153 : 3047 : if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_SIMDLEN
3154 : : && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_INBRANCH
3155 : : && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_NOTINBRANCH)
3156 : : {
3157 : 1692 : tree decl = OMP_CLAUSE_DECL (c);
3158 : 1692 : tree arg;
3159 : 1692 : int idx;
3160 : 3785 : for (arg = parms, idx = 0; arg;
3161 : 2093 : arg = TREE_CHAIN (arg), idx++)
3162 : 3785 : if (arg == decl)
3163 : : break;
3164 : 1692 : if (arg == NULL_TREE)
3165 : : {
3166 : 0 : error_at (OMP_CLAUSE_LOCATION (c),
3167 : : "%qD is not a function argument", decl);
3168 : 3047 : continue;
3169 : : }
3170 : 1692 : OMP_CLAUSE_DECL (c) = build_int_cst (integer_type_node, idx);
3171 : 1692 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3172 : 1692 : && OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (c))
3173 : : {
3174 : 43 : decl = OMP_CLAUSE_LINEAR_STEP (c);
3175 : 121 : for (arg = parms, idx = 0; arg;
3176 : 78 : arg = TREE_CHAIN (arg), idx++)
3177 : 121 : if (arg == decl)
3178 : : break;
3179 : 43 : if (arg == NULL_TREE)
3180 : : {
3181 : 0 : error_at (OMP_CLAUSE_LOCATION (c),
3182 : : "%qD is not a function argument", decl);
3183 : 0 : continue;
3184 : : }
3185 : 43 : OMP_CLAUSE_LINEAR_STEP (c)
3186 : 86 : = build_int_cst (integer_type_node, idx);
3187 : : }
3188 : : }
3189 : 3047 : clvec.safe_push (c);
3190 : : }
3191 : 1396 : if (!clvec.is_empty ())
3192 : : {
3193 : 1287 : unsigned int len = clvec.length (), i;
3194 : 1287 : clvec.qsort (c_omp_declare_simd_clause_cmp);
3195 : 1287 : clauses = clvec[0];
3196 : 4334 : for (i = 0; i < len; i++)
3197 : 3047 : OMP_CLAUSE_CHAIN (clvec[i]) = (i < len - 1) ? clvec[i + 1] : NULL_TREE;
3198 : : }
3199 : : else
3200 : : clauses = NULL_TREE;
3201 : 1396 : clvec.release ();
3202 : 1396 : return clauses;
3203 : : }
3204 : :
3205 : : /* Change argument indexes in CLAUSES of FNDECL back to PARM_DECLs. */
3206 : :
3207 : : void
3208 : 105 : c_omp_declare_simd_clauses_to_decls (tree fndecl, tree clauses)
3209 : : {
3210 : 105 : tree c;
3211 : :
3212 : 393 : for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
3213 : 288 : if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_SIMDLEN
3214 : : && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_INBRANCH
3215 : : && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_NOTINBRANCH)
3216 : : {
3217 : 189 : int idx = tree_to_shwi (OMP_CLAUSE_DECL (c)), i;
3218 : 189 : tree arg;
3219 : 369 : for (arg = DECL_ARGUMENTS (fndecl), i = 0; arg;
3220 : 180 : arg = TREE_CHAIN (arg), i++)
3221 : 369 : if (i == idx)
3222 : : break;
3223 : 0 : gcc_assert (arg);
3224 : 189 : OMP_CLAUSE_DECL (c) = arg;
3225 : 189 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3226 : 189 : && OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (c))
3227 : : {
3228 : 0 : idx = tree_to_shwi (OMP_CLAUSE_LINEAR_STEP (c));
3229 : 0 : for (arg = DECL_ARGUMENTS (fndecl), i = 0; arg;
3230 : 0 : arg = TREE_CHAIN (arg), i++)
3231 : 0 : if (i == idx)
3232 : : break;
3233 : 0 : gcc_assert (arg);
3234 : 0 : OMP_CLAUSE_LINEAR_STEP (c) = arg;
3235 : : }
3236 : : }
3237 : 105 : }
3238 : :
3239 : : /* Return true for __func__ and similar function-local predefined
3240 : : variables (which are in OpenMP predetermined shared, allowed in
3241 : : shared/firstprivate clauses). */
3242 : :
3243 : : bool
3244 : 65371 : c_omp_predefined_variable (tree decl)
3245 : : {
3246 : 65371 : if (VAR_P (decl)
3247 : 34214 : && DECL_ARTIFICIAL (decl)
3248 : 306 : && TREE_STATIC (decl)
3249 : 65662 : && DECL_NAME (decl))
3250 : : {
3251 : 291 : if (TREE_READONLY (decl)
3252 : 291 : && (DECL_NAME (decl) == ridpointers[RID_C99_FUNCTION_NAME]
3253 : 223 : || DECL_NAME (decl) == ridpointers[RID_FUNCTION_NAME]
3254 : 179 : || DECL_NAME (decl) == ridpointers[RID_PRETTY_FUNCTION_NAME]))
3255 : : return true;
3256 : : /* For UBSan handle the same also ubsan_create_data created
3257 : : variables. There is no magic flag for those, but user variables
3258 : : shouldn't be DECL_ARTIFICIAL or have TYPE_ARTIFICIAL type with
3259 : : such names. */
3260 : 139 : if ((flag_sanitize & (SANITIZE_UNDEFINED
3261 : : | SANITIZE_UNDEFINED_NONDEFAULT)) != 0
3262 : 36 : && DECL_IGNORED_P (decl)
3263 : 36 : && !TREE_READONLY (decl)
3264 : 30 : && TREE_CODE (DECL_NAME (decl)) == IDENTIFIER_NODE
3265 : 30 : && TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE
3266 : 30 : && TYPE_ARTIFICIAL (TREE_TYPE (decl))
3267 : 30 : && TYPE_NAME (TREE_TYPE (decl))
3268 : 30 : && TREE_CODE (TYPE_NAME (TREE_TYPE (decl))) == TYPE_DECL
3269 : 30 : && DECL_NAME (TYPE_NAME (TREE_TYPE (decl)))
3270 : 169 : && (TREE_CODE (DECL_NAME (TYPE_NAME (TREE_TYPE (decl))))
3271 : : == IDENTIFIER_NODE))
3272 : : {
3273 : 30 : tree id1 = DECL_NAME (decl);
3274 : 30 : tree id2 = DECL_NAME (TYPE_NAME (TREE_TYPE (decl)));
3275 : 30 : if (IDENTIFIER_LENGTH (id1) >= sizeof ("ubsan_data") - 1
3276 : 30 : && IDENTIFIER_LENGTH (id2) >= sizeof ("__ubsan__data")
3277 : 30 : && !memcmp (IDENTIFIER_POINTER (id2), "__ubsan_",
3278 : : sizeof ("__ubsan_") - 1)
3279 : 30 : && !memcmp (IDENTIFIER_POINTER (id2) + IDENTIFIER_LENGTH (id2)
3280 : 30 : - sizeof ("_data") + 1, "_data",
3281 : : sizeof ("_data") - 1)
3282 : 60 : && strstr (IDENTIFIER_POINTER (id1), "ubsan_data"))
3283 : 30 : return true;
3284 : : }
3285 : : }
3286 : : return false;
3287 : : }
3288 : :
3289 : : /* OMP_CLAUSE_DEFAULT_UNSPECIFIED unless OpenMP sharing attribute of DECL
3290 : : is predetermined. */
3291 : :
3292 : : enum omp_clause_default_kind
3293 : 27945 : c_omp_predetermined_sharing (tree decl)
3294 : : {
3295 : : /* Predetermine artificial variables holding integral values, those
3296 : : are usually result of gimplify_one_sizepos or SAVE_EXPR
3297 : : gimplification. */
3298 : 27945 : if (VAR_P (decl)
3299 : 17176 : && DECL_ARTIFICIAL (decl)
3300 : 28584 : && INTEGRAL_TYPE_P (TREE_TYPE (decl)))
3301 : : return OMP_CLAUSE_DEFAULT_SHARED;
3302 : :
3303 : 27397 : if (c_omp_predefined_variable (decl))
3304 : : return OMP_CLAUSE_DEFAULT_SHARED;
3305 : :
3306 : : return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
3307 : : }
3308 : :
3309 : : /* OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED unless OpenMP mapping attribute
3310 : : of DECL is predetermined. */
3311 : :
3312 : : enum omp_clause_defaultmap_kind
3313 : 5140 : c_omp_predetermined_mapping (tree decl)
3314 : : {
3315 : : /* Predetermine artificial variables holding integral values, those
3316 : : are usually result of gimplify_one_sizepos or SAVE_EXPR
3317 : : gimplification. */
3318 : 5140 : if (VAR_P (decl)
3319 : 949 : && DECL_ARTIFICIAL (decl)
3320 : 5172 : && INTEGRAL_TYPE_P (TREE_TYPE (decl)))
3321 : : return OMP_CLAUSE_DEFAULTMAP_FIRSTPRIVATE;
3322 : :
3323 : 5112 : if (c_omp_predefined_variable (decl))
3324 : 2 : return OMP_CLAUSE_DEFAULTMAP_TO;
3325 : :
3326 : : return OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED;
3327 : : }
3328 : :
3329 : :
3330 : : /* Used to merge map clause information in c_omp_adjust_map_clauses. */
3331 : : struct map_clause
3332 : : {
3333 : : tree clause;
3334 : : bool firstprivate_ptr_p;
3335 : : bool decl_mapped;
3336 : : bool omp_declare_target;
3337 : 3320 : map_clause (void) : clause (NULL_TREE), firstprivate_ptr_p (false),
3338 : 3320 : decl_mapped (false), omp_declare_target (false) { }
3339 : : };
3340 : :
3341 : : /* Adjust map clauses after normal clause parsing, mainly to mark specific
3342 : : base-pointer map cases addressable that may be turned into attach/detach
3343 : : operations during gimplification. */
3344 : : void
3345 : 12145 : c_omp_adjust_map_clauses (tree clauses, bool is_target)
3346 : : {
3347 : 12145 : if (!is_target)
3348 : : {
3349 : : /* If this is not a target construct, just turn firstprivate pointers
3350 : : into attach/detach, the runtime will check and do the rest. */
3351 : :
3352 : 4110 : for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
3353 : 2774 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
3354 : 2313 : && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
3355 : 0 : && DECL_P (OMP_CLAUSE_DECL (c))
3356 : 2774 : && POINTER_TYPE_P (TREE_TYPE (OMP_CLAUSE_DECL (c))))
3357 : : {
3358 : 0 : tree ptr = OMP_CLAUSE_DECL (c);
3359 : 0 : c_common_mark_addressable_vec (ptr);
3360 : : }
3361 : 1336 : return;
3362 : : }
3363 : :
3364 : 10809 : hash_map<tree, map_clause> maps;
3365 : :
3366 : 23483 : for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
3367 : 12674 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
3368 : 12674 : && DECL_P (OMP_CLAUSE_DECL (c)))
3369 : : {
3370 : : /* If this is for a target construct, the firstprivate pointer
3371 : : is marked addressable if either is true:
3372 : : (1) the base-pointer is mapped in this same construct, or
3373 : : (2) the base-pointer is a variable place on the device by
3374 : : "declare target" directives.
3375 : :
3376 : : Here we iterate through all map clauses collecting these cases,
3377 : : and merge them with a hash_map to process below. */
3378 : :
3379 : 3900 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
3380 : 3900 : && POINTER_TYPE_P (TREE_TYPE (OMP_CLAUSE_DECL (c))))
3381 : : {
3382 : 330 : tree ptr = OMP_CLAUSE_DECL (c);
3383 : 330 : map_clause &mc = maps.get_or_insert (ptr);
3384 : 330 : if (mc.clause == NULL_TREE)
3385 : 330 : mc.clause = c;
3386 : 330 : mc.firstprivate_ptr_p = true;
3387 : :
3388 : 330 : if (is_global_var (ptr)
3389 : 378 : && lookup_attribute ("omp declare target",
3390 : 48 : DECL_ATTRIBUTES (ptr)))
3391 : 0 : mc.omp_declare_target = true;
3392 : : }
3393 : 3570 : else if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALLOC
3394 : 3491 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_TO
3395 : 3035 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FROM
3396 : 2153 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_TOFROM
3397 : 981 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_TO
3398 : 919 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_FROM
3399 : 4488 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_TOFROM)
3400 : : {
3401 : 3013 : map_clause &mc = maps.get_or_insert (OMP_CLAUSE_DECL (c));
3402 : 3013 : mc.decl_mapped = true;
3403 : : }
3404 : : }
3405 : :
3406 : 14129 : for (hash_map<tree, map_clause>::iterator i = maps.begin ();
3407 : 28258 : i != maps.end (); ++i)
3408 : : {
3409 : 3320 : map_clause &mc = (*i).second;
3410 : :
3411 : 3320 : if (mc.firstprivate_ptr_p
3412 : 330 : && (mc.decl_mapped || mc.omp_declare_target))
3413 : 23 : c_common_mark_addressable_vec (OMP_CLAUSE_DECL (mc.clause));
3414 : : }
3415 : 10809 : }
3416 : :
3417 : : /* Maybe strip off an indirection from a "converted" reference, then find the
3418 : : origin of a pointer (i.e. without any offset). */
3419 : :
3420 : : tree
3421 : 70284 : c_omp_address_inspector::unconverted_ref_origin ()
3422 : : {
3423 : 70284 : tree t = orig;
3424 : :
3425 : : /* We may have a reference-typed component access at the outermost level
3426 : : that has had convert_from_reference called on it. Get the un-dereferenced
3427 : : reference itself. */
3428 : 70284 : t = maybe_unconvert_ref (t);
3429 : :
3430 : : /* Find base pointer for POINTER_PLUS_EXPR, etc. */
3431 : 70284 : t = get_origin (t);
3432 : :
3433 : 70284 : return t;
3434 : : }
3435 : :
3436 : : /* Return TRUE if the address is a component access. */
3437 : :
3438 : : bool
3439 : 12526 : c_omp_address_inspector::component_access_p ()
3440 : : {
3441 : 12526 : tree t = maybe_unconvert_ref (orig);
3442 : :
3443 : 12526 : t = get_origin (t);
3444 : :
3445 : 12526 : return TREE_CODE (t) == COMPONENT_REF;
3446 : : }
3447 : :
3448 : : /* Perform various checks on the address, as described by clause CLAUSE (we
3449 : : only use its code and location here). */
3450 : :
3451 : : bool
3452 : 32833 : c_omp_address_inspector::check_clause (tree clause)
3453 : : {
3454 : 32833 : tree t = unconverted_ref_origin ();
3455 : :
3456 : 32833 : if (TREE_CODE (t) != COMPONENT_REF)
3457 : : return true;
3458 : :
3459 : 4541 : if (TREE_CODE (TREE_OPERAND (t, 1)) == FIELD_DECL
3460 : 4541 : && DECL_BIT_FIELD (TREE_OPERAND (t, 1)))
3461 : : {
3462 : 24 : error_at (OMP_CLAUSE_LOCATION (clause),
3463 : : "bit-field %qE in %qs clause",
3464 : 24 : t, omp_clause_code_name[OMP_CLAUSE_CODE (clause)]);
3465 : 24 : return false;
3466 : : }
3467 : 4517 : else if (!processing_template_decl_p ()
3468 : 4517 : && !omp_mappable_type (TREE_TYPE (t)))
3469 : : {
3470 : 0 : error_at (OMP_CLAUSE_LOCATION (clause),
3471 : : "%qE does not have a mappable type in %qs clause",
3472 : 0 : t, omp_clause_code_name[OMP_CLAUSE_CODE (clause)]);
3473 : 0 : emit_unmappable_type_notes (TREE_TYPE (t));
3474 : 0 : return false;
3475 : : }
3476 : 4517 : else if (TREE_TYPE (t) && TYPE_ATOMIC (TREE_TYPE (t)))
3477 : : {
3478 : 2 : error_at (OMP_CLAUSE_LOCATION (clause),
3479 : : "%<_Atomic%> %qE in %qs clause", t,
3480 : 2 : omp_clause_code_name[OMP_CLAUSE_CODE (clause)]);
3481 : 2 : return false;
3482 : : }
3483 : :
3484 : : return true;
3485 : : }
3486 : :
3487 : : /* Find the "root term" for the address. This is the innermost decl, etc.
3488 : : of the access. */
3489 : :
3490 : : tree
3491 : 1690 : c_omp_address_inspector::get_root_term (bool checking)
3492 : : {
3493 : 1690 : if (root_term && !checking)
3494 : : return root_term;
3495 : :
3496 : 1690 : tree t = unconverted_ref_origin ();
3497 : :
3498 : 5734 : while (TREE_CODE (t) == COMPONENT_REF)
3499 : : {
3500 : 2354 : if (checking
3501 : 2354 : && TREE_TYPE (TREE_OPERAND (t, 0))
3502 : 4520 : && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == UNION_TYPE)
3503 : : {
3504 : 0 : error_at (loc, "%qE is a member of a union", t);
3505 : 0 : return error_mark_node;
3506 : : }
3507 : 2354 : t = TREE_OPERAND (t, 0);
3508 : 2354 : while (TREE_CODE (t) == MEM_REF
3509 : 3773 : || TREE_CODE (t) == INDIRECT_REF
3510 : 3773 : || TREE_CODE (t) == ARRAY_REF)
3511 : : {
3512 : 1419 : if (TREE_CODE (t) == MEM_REF
3513 : : || TREE_CODE (t) == INDIRECT_REF)
3514 : 1275 : indirections = true;
3515 : 1419 : t = TREE_OPERAND (t, 0);
3516 : 1419 : STRIP_NOPS (t);
3517 : 1419 : if (TREE_CODE (t) == POINTER_PLUS_EXPR)
3518 : 102 : t = TREE_OPERAND (t, 0);
3519 : : }
3520 : : }
3521 : :
3522 : 1690 : root_term = t;
3523 : :
3524 : 1690 : return t;
3525 : : }
3526 : :
3527 : : /* Return TRUE if the address is supported in mapping clauses. At present,
3528 : : this means that the innermost expression is a DECL_P, but could be extended
3529 : : to other types of expression in the future. */
3530 : :
3531 : : bool
3532 : 24925 : c_omp_address_inspector::map_supported_p ()
3533 : : {
3534 : : /* If we've already decided if the mapped address is supported, return
3535 : : that. */
3536 : 24925 : if (map_supported != -1)
3537 : 0 : return map_supported;
3538 : :
3539 : 24925 : tree t = unconverted_ref_origin ();
3540 : :
3541 : 24925 : STRIP_NOPS (t);
3542 : :
3543 : 24925 : while (TREE_CODE (t) == INDIRECT_REF
3544 : 40708 : || TREE_CODE (t) == MEM_REF
3545 : : || TREE_CODE (t) == ARRAY_REF
3546 : : || TREE_CODE (t) == COMPONENT_REF
3547 : : || TREE_CODE (t) == COMPOUND_EXPR
3548 : : || TREE_CODE (t) == SAVE_EXPR
3549 : : || TREE_CODE (t) == POINTER_PLUS_EXPR
3550 : : || TREE_CODE (t) == NON_LVALUE_EXPR
3551 : : || TREE_CODE (t) == OMP_ARRAY_SECTION
3552 : 40708 : || TREE_CODE (t) == NOP_EXPR)
3553 : 15783 : if (TREE_CODE (t) == COMPOUND_EXPR)
3554 : 27 : t = TREE_OPERAND (t, 1);
3555 : : else
3556 : 15756 : t = TREE_OPERAND (t, 0);
3557 : :
3558 : 24925 : STRIP_NOPS (t);
3559 : :
3560 : 24925 : map_supported = DECL_P (t);
3561 : :
3562 : 24925 : return map_supported;
3563 : : }
3564 : :
3565 : : /* Get the origin of an address T, stripping off offsets and some other
3566 : : bits. */
3567 : :
3568 : : tree
3569 : 82810 : c_omp_address_inspector::get_origin (tree t)
3570 : : {
3571 : 83347 : while (1)
3572 : : {
3573 : 83347 : if (TREE_CODE (t) == COMPOUND_EXPR)
3574 : : {
3575 : 10 : t = TREE_OPERAND (t, 1);
3576 : 10 : STRIP_NOPS (t);
3577 : : }
3578 : 83337 : else if (TREE_CODE (t) == POINTER_PLUS_EXPR
3579 : 83337 : || TREE_CODE (t) == SAVE_EXPR)
3580 : 500 : t = TREE_OPERAND (t, 0);
3581 : 82837 : else if (!processing_template_decl_p ()
3582 : 75888 : && TREE_CODE (t) == INDIRECT_REF
3583 : 85437 : && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == REFERENCE_TYPE)
3584 : 27 : t = TREE_OPERAND (t, 0);
3585 : : else
3586 : : break;
3587 : : }
3588 : 82810 : STRIP_NOPS (t);
3589 : 82810 : return t;
3590 : : }
3591 : :
3592 : : /* For an address T that might be a reference that has had
3593 : : "convert_from_reference" called on it, return the actual reference without
3594 : : any indirection. */
3595 : :
3596 : : tree
3597 : 92374 : c_omp_address_inspector::maybe_unconvert_ref (tree t)
3598 : : {
3599 : : /* Be careful not to dereference the type if we're processing a
3600 : : template decl, else it might be NULL. */
3601 : 92374 : if (!processing_template_decl_p ()
3602 : 83363 : && TREE_CODE (t) == INDIRECT_REF
3603 : 95495 : && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == REFERENCE_TYPE)
3604 : 587 : return TREE_OPERAND (t, 0);
3605 : :
3606 : : return t;
3607 : : }
3608 : :
3609 : : /* Return TRUE if CLAUSE might describe a zero-length array section. */
3610 : :
3611 : : bool
3612 : 5427 : c_omp_address_inspector::maybe_zero_length_array_section (tree clause)
3613 : : {
3614 : 5427 : switch (OMP_CLAUSE_MAP_KIND (clause))
3615 : : {
3616 : : case GOMP_MAP_ALLOC:
3617 : : case GOMP_MAP_IF_PRESENT:
3618 : : case GOMP_MAP_TO:
3619 : : case GOMP_MAP_FROM:
3620 : : case GOMP_MAP_TOFROM:
3621 : : case GOMP_MAP_ALWAYS_TO:
3622 : : case GOMP_MAP_ALWAYS_FROM:
3623 : : case GOMP_MAP_ALWAYS_TOFROM:
3624 : : case GOMP_MAP_PRESENT_ALLOC:
3625 : : case GOMP_MAP_PRESENT_TO:
3626 : : case GOMP_MAP_PRESENT_FROM:
3627 : : case GOMP_MAP_PRESENT_TOFROM:
3628 : : case GOMP_MAP_ALWAYS_PRESENT_TO:
3629 : : case GOMP_MAP_ALWAYS_PRESENT_FROM:
3630 : : case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
3631 : : case GOMP_MAP_RELEASE:
3632 : : case GOMP_MAP_DELETE:
3633 : : case GOMP_MAP_FORCE_TO:
3634 : : case GOMP_MAP_FORCE_FROM:
3635 : : case GOMP_MAP_FORCE_TOFROM:
3636 : : case GOMP_MAP_FORCE_PRESENT:
3637 : : return true;
3638 : 28 : default:
3639 : 28 : return false;
3640 : : }
3641 : : }
3642 : :
3643 : : /* Expand a chained access. We only expect to see a quite limited range of
3644 : : expression types here, because e.g. you can't have an array of
3645 : : references. */
3646 : :
3647 : : static tree
3648 : 75 : omp_expand_access_chain (tree c, tree expr, vec<omp_addr_token *> &addr_tokens,
3649 : : unsigned *idx, c_omp_region_type ort)
3650 : : {
3651 : 83 : using namespace omp_addr_tokenizer;
3652 : 83 : location_t loc = OMP_CLAUSE_LOCATION (c);
3653 : 83 : unsigned i = *idx;
3654 : 83 : tree c2 = NULL_TREE;
3655 : 83 : gomp_map_kind kind;
3656 : :
3657 : 83 : if ((ort & C_ORT_EXIT_DATA) != 0
3658 : 71 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FROM
3659 : 154 : || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
3660 : 71 : && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FROM
3661 : 71 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DELETE
3662 : 71 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_RELEASE
3663 : 71 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_FROM
3664 : 71 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FORCE_FROM
3665 : 71 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_PRESENT_FROM
3666 : 71 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_PRESENT_FROM)))
3667 : : kind = GOMP_MAP_DETACH;
3668 : : else
3669 : : kind = GOMP_MAP_ATTACH;
3670 : :
3671 : 83 : switch (addr_tokens[i]->u.access_kind)
3672 : : {
3673 : 83 : case ACCESS_POINTER:
3674 : 83 : case ACCESS_POINTER_OFFSET:
3675 : 83 : {
3676 : 83 : tree virtual_origin
3677 : 83 : = fold_convert_loc (loc, ptrdiff_type_node, addr_tokens[i]->expr);
3678 : 83 : tree data_addr = omp_accessed_addr (addr_tokens, i, expr);
3679 : 83 : c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
3680 : 83 : OMP_CLAUSE_SET_MAP_KIND (c2, kind);
3681 : 83 : OMP_CLAUSE_DECL (c2) = addr_tokens[i]->expr;
3682 : 83 : OMP_CLAUSE_SIZE (c2)
3683 : 83 : = fold_build2_loc (loc, MINUS_EXPR, ptrdiff_type_node,
3684 : : fold_convert_loc (loc, ptrdiff_type_node,
3685 : : data_addr),
3686 : : virtual_origin);
3687 : : }
3688 : 83 : break;
3689 : :
3690 : : case ACCESS_INDEXED_ARRAY:
3691 : : break;
3692 : :
3693 : 0 : default:
3694 : 0 : return error_mark_node;
3695 : : }
3696 : :
3697 : 83 : if (c2)
3698 : : {
3699 : 83 : OMP_CLAUSE_CHAIN (c2) = OMP_CLAUSE_CHAIN (c);
3700 : 83 : OMP_CLAUSE_CHAIN (c) = c2;
3701 : 83 : c = c2;
3702 : : }
3703 : :
3704 : 83 : *idx = ++i;
3705 : :
3706 : 83 : if (i < addr_tokens.length ()
3707 : 91 : && addr_tokens[i]->type == ACCESS_METHOD)
3708 : : return omp_expand_access_chain (c, expr, addr_tokens, idx, ort);
3709 : :
3710 : : return c;
3711 : : }
3712 : :
3713 : : /* Translate "array_base_decl access_method" to OMP mapping clauses. */
3714 : :
3715 : : tree
3716 : 17894 : c_omp_address_inspector::expand_array_base (tree c,
3717 : : vec<omp_addr_token *> &addr_tokens,
3718 : : tree expr, unsigned *idx,
3719 : : c_omp_region_type ort)
3720 : : {
3721 : 17894 : using namespace omp_addr_tokenizer;
3722 : 17894 : location_t loc = OMP_CLAUSE_LOCATION (c);
3723 : 17894 : int i = *idx;
3724 : 17894 : tree decl = addr_tokens[i + 1]->expr;
3725 : 17894 : bool decl_p = DECL_P (decl);
3726 : 17894 : bool declare_target_p = (decl_p
3727 : 17885 : && is_global_var (decl)
3728 : 25369 : && lookup_attribute ("omp declare target",
3729 : 7475 : DECL_ATTRIBUTES (decl)));
3730 : 17894 : bool map_p = OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP;
3731 : 17894 : bool implicit_p = map_p && OMP_CLAUSE_MAP_IMPLICIT (c);
3732 : 17894 : bool chain_p = omp_access_chain_p (addr_tokens, i + 1);
3733 : 17894 : tree c2 = NULL_TREE, c3 = NULL_TREE;
3734 : 17894 : unsigned consume_tokens = 2;
3735 : 17894 : bool target_p = (ort & C_ORT_TARGET) != 0;
3736 : 17894 : bool openmp_p = (ort & C_ORT_OMP) != 0;
3737 : :
3738 : 17894 : gcc_assert (i == 0);
3739 : :
3740 : 17894 : if (!openmp_p
3741 : 17894 : && map_p
3742 : 17894 : && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH
3743 : 6753 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DETACH))
3744 : : {
3745 : 28 : i += 2;
3746 : 28 : *idx = i;
3747 : 28 : return c;
3748 : : }
3749 : :
3750 : 17866 : switch (addr_tokens[i + 1]->u.access_kind)
3751 : : {
3752 : 13624 : case ACCESS_DIRECT:
3753 : 13624 : if (decl_p && !target_p)
3754 : 8563 : c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
3755 : : break;
3756 : :
3757 : 150 : case ACCESS_REF:
3758 : 150 : {
3759 : : /* Copy the referenced object. Note that we do this even for !MAP_P
3760 : : clauses. */
3761 : 150 : tree obj = convert_from_reference (addr_tokens[i + 1]->expr);
3762 : 150 : if (TREE_CODE (TREE_TYPE (obj)) == ARRAY_TYPE)
3763 : : /* We have a ref to array: add a [0] element as the ME expects. */
3764 : 43 : OMP_CLAUSE_DECL (c) = build_array_ref (loc, obj, integer_zero_node);
3765 : : else
3766 : 107 : OMP_CLAUSE_DECL (c) = obj;
3767 : 150 : OMP_CLAUSE_SIZE (c) = TYPE_SIZE_UNIT (TREE_TYPE (obj));
3768 : :
3769 : 150 : if (!map_p)
3770 : : {
3771 : 6 : if (decl_p)
3772 : 6 : c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
3773 : : break;
3774 : : }
3775 : :
3776 : 144 : if (!target_p)
3777 : : break;
3778 : :
3779 : : /* If we have a reference to a pointer, avoid using
3780 : : FIRSTPRIVATE_REFERENCE here in case the pointer is modified in the
3781 : : offload region (we can only do that if the pointer does not point
3782 : : to a mapped block). We could avoid doing this if we don't have a
3783 : : FROM mapping... */
3784 : 84 : bool ref_to_ptr = TREE_CODE (TREE_TYPE (obj)) == POINTER_TYPE;
3785 : :
3786 : 84 : c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
3787 : 84 : if (!ref_to_ptr
3788 : 84 : && !declare_target_p
3789 : 50 : && decl_p)
3790 : 50 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_FIRSTPRIVATE_REFERENCE);
3791 : : else
3792 : : {
3793 : 34 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
3794 : 34 : if (decl_p)
3795 : 34 : c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
3796 : : }
3797 : 84 : OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
3798 : 84 : OMP_CLAUSE_SIZE (c2) = size_zero_node;
3799 : :
3800 : 84 : if (ref_to_ptr)
3801 : : {
3802 : 34 : c3 = c2;
3803 : 34 : c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
3804 : 34 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ALLOC);
3805 : 34 : OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
3806 : 68 : OMP_CLAUSE_SIZE (c2)
3807 : 34 : = TYPE_SIZE_UNIT (TREE_TYPE (OMP_CLAUSE_DECL (c2)));
3808 : : }
3809 : : }
3810 : : break;
3811 : :
3812 : 83 : case ACCESS_INDEXED_REF_TO_ARRAY:
3813 : 83 : {
3814 : 83 : if (!map_p)
3815 : : {
3816 : 0 : if (decl_p)
3817 : 0 : c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
3818 : : break;
3819 : : }
3820 : :
3821 : 83 : if (!target_p)
3822 : : break;
3823 : :
3824 : 64 : tree virtual_origin
3825 : 64 : = convert_from_reference (addr_tokens[i + 1]->expr);
3826 : 64 : virtual_origin = build_fold_addr_expr (virtual_origin);
3827 : 64 : virtual_origin = fold_convert_loc (loc, ptrdiff_type_node,
3828 : : virtual_origin);
3829 : 64 : tree data_addr = omp_accessed_addr (addr_tokens, i + 1, expr);
3830 : 64 : c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
3831 : 64 : if (decl_p && target_p && !declare_target_p)
3832 : : {
3833 : : /* It appears that omp-low.cc mishandles cases where we have a
3834 : : [reference to an] array of pointers such as:
3835 : :
3836 : : int *arr[N]; (or "int *(&arr)[N] = ...")
3837 : : #pragma omp target map(arr[a][b:c])
3838 : : { ... }
3839 : :
3840 : : in such cases chain_p will be true. For now, fall back to
3841 : : GOMP_MAP_POINTER. */
3842 : 61 : enum gomp_map_kind k = chain_p ? GOMP_MAP_POINTER
3843 : : : GOMP_MAP_FIRSTPRIVATE_REFERENCE;
3844 : 61 : OMP_CLAUSE_SET_MAP_KIND (c2, k);
3845 : 61 : }
3846 : : else
3847 : : {
3848 : 3 : if (decl_p)
3849 : 0 : c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
3850 : 3 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
3851 : : }
3852 : 64 : OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
3853 : 64 : OMP_CLAUSE_SIZE (c2)
3854 : 64 : = fold_build2_loc (loc, MINUS_EXPR, ptrdiff_type_node,
3855 : : fold_convert_loc (loc, ptrdiff_type_node,
3856 : : data_addr),
3857 : : virtual_origin);
3858 : : }
3859 : 64 : break;
3860 : :
3861 : 1310 : case ACCESS_INDEXED_ARRAY:
3862 : 1310 : {
3863 : 1310 : if (!map_p)
3864 : : {
3865 : 0 : if (decl_p)
3866 : 0 : c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
3867 : : break;
3868 : : }
3869 : :
3870 : : /* The code handling "firstprivatize_array_bases" in gimplify.cc is
3871 : : relevant here. What do we need to create for arrays at this
3872 : : stage? (This condition doesn't feel quite right. FIXME?) */
3873 : 1310 : if (!target_p
3874 : 1310 : && (TREE_CODE (TREE_TYPE (addr_tokens[i + 1]->expr))
3875 : : == ARRAY_TYPE))
3876 : : break;
3877 : :
3878 : 653 : tree virtual_origin
3879 : 653 : = build_fold_addr_expr (addr_tokens[i + 1]->expr);
3880 : 653 : virtual_origin = fold_convert_loc (loc, ptrdiff_type_node,
3881 : : virtual_origin);
3882 : 653 : tree data_addr = omp_accessed_addr (addr_tokens, i + 1, expr);
3883 : 653 : c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
3884 : 653 : if (decl_p && target_p)
3885 : : {
3886 : : /* See comment for ACCESS_INDEXED_REF_TO_ARRAY above. */
3887 : 653 : enum gomp_map_kind k = chain_p ? GOMP_MAP_POINTER
3888 : : : GOMP_MAP_FIRSTPRIVATE_POINTER;
3889 : 653 : OMP_CLAUSE_SET_MAP_KIND (c2, k);
3890 : : }
3891 : : else
3892 : : {
3893 : 0 : if (decl_p)
3894 : 0 : c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
3895 : 0 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
3896 : : }
3897 : 653 : OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
3898 : 653 : OMP_CLAUSE_SIZE (c2)
3899 : 653 : = fold_build2_loc (loc, MINUS_EXPR, ptrdiff_type_node,
3900 : : fold_convert_loc (loc, ptrdiff_type_node,
3901 : : data_addr),
3902 : : virtual_origin);
3903 : : }
3904 : 653 : break;
3905 : :
3906 : 2625 : case ACCESS_POINTER:
3907 : 2625 : case ACCESS_POINTER_OFFSET:
3908 : 2625 : {
3909 : 2625 : if (!map_p)
3910 : : {
3911 : 0 : if (decl_p)
3912 : 0 : c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
3913 : : break;
3914 : : }
3915 : :
3916 : 2625 : unsigned last_access = i + 1;
3917 : 2625 : tree virtual_origin;
3918 : :
3919 : 2625 : if (chain_p
3920 : 151 : && addr_tokens[i + 2]->type == ACCESS_METHOD
3921 : 2776 : && addr_tokens[i + 2]->u.access_kind == ACCESS_INDEXED_ARRAY)
3922 : : {
3923 : : /* !!! This seems wrong for ACCESS_POINTER_OFFSET. */
3924 : 117 : consume_tokens = 3;
3925 : 117 : chain_p = omp_access_chain_p (addr_tokens, i + 2);
3926 : 117 : last_access = i + 2;
3927 : 117 : virtual_origin
3928 : 117 : = build_array_ref (loc, addr_tokens[last_access]->expr,
3929 : : integer_zero_node);
3930 : 117 : virtual_origin = build_fold_addr_expr (virtual_origin);
3931 : 117 : virtual_origin = fold_convert_loc (loc, ptrdiff_type_node,
3932 : : virtual_origin);
3933 : : }
3934 : : else
3935 : 2508 : virtual_origin = fold_convert_loc (loc, ptrdiff_type_node,
3936 : 2508 : addr_tokens[last_access]->expr);
3937 : 2625 : tree data_addr = omp_accessed_addr (addr_tokens, last_access, expr);
3938 : 2625 : c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
3939 : : /* For OpenACC, use FIRSTPRIVATE_POINTER for decls even on non-compute
3940 : : regions (e.g. "acc data" constructs). It'll be removed anyway in
3941 : : gimplify.cc, but doing it this way maintains diagnostic
3942 : : behaviour. */
3943 : 2625 : if (decl_p && (target_p || !openmp_p) && !chain_p && !declare_target_p)
3944 : 2436 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_FIRSTPRIVATE_POINTER);
3945 : : else
3946 : : {
3947 : 186 : if (decl_p)
3948 : 186 : c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
3949 : 189 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
3950 : : }
3951 : 2625 : OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
3952 : 2625 : OMP_CLAUSE_SIZE (c2)
3953 : 2625 : = fold_build2_loc (loc, MINUS_EXPR, ptrdiff_type_node,
3954 : : fold_convert_loc (loc, ptrdiff_type_node,
3955 : : data_addr),
3956 : : virtual_origin);
3957 : : }
3958 : 2625 : break;
3959 : :
3960 : 74 : case ACCESS_REF_TO_POINTER:
3961 : 74 : case ACCESS_REF_TO_POINTER_OFFSET:
3962 : 74 : {
3963 : 74 : if (!map_p)
3964 : : {
3965 : 0 : if (decl_p)
3966 : 0 : c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
3967 : : break;
3968 : : }
3969 : :
3970 : 74 : unsigned last_access = i + 1;
3971 : 74 : tree virtual_origin;
3972 : :
3973 : 74 : if (chain_p
3974 : 6 : && addr_tokens[i + 2]->type == ACCESS_METHOD
3975 : 80 : && addr_tokens[i + 2]->u.access_kind == ACCESS_INDEXED_ARRAY)
3976 : : {
3977 : : /* !!! This seems wrong for ACCESS_POINTER_OFFSET. */
3978 : 2 : consume_tokens = 3;
3979 : 2 : chain_p = omp_access_chain_p (addr_tokens, i + 2);
3980 : 2 : last_access = i + 2;
3981 : 2 : virtual_origin
3982 : 2 : = build_array_ref (loc, addr_tokens[last_access]->expr,
3983 : : integer_zero_node);
3984 : 2 : virtual_origin = build_fold_addr_expr (virtual_origin);
3985 : 2 : virtual_origin = fold_convert_loc (loc, ptrdiff_type_node,
3986 : : virtual_origin);
3987 : : }
3988 : : else
3989 : : {
3990 : 72 : virtual_origin
3991 : 72 : = convert_from_reference (addr_tokens[last_access]->expr);
3992 : 72 : virtual_origin = fold_convert_loc (loc, ptrdiff_type_node,
3993 : : virtual_origin);
3994 : : }
3995 : :
3996 : 74 : tree data_addr = omp_accessed_addr (addr_tokens, last_access, expr);
3997 : 74 : c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
3998 : 74 : if (decl_p && target_p && !chain_p && !declare_target_p)
3999 : : {
4000 : 58 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_FIRSTPRIVATE_REFERENCE);
4001 : 58 : OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
4002 : : }
4003 : : else
4004 : : {
4005 : 16 : if (decl_p)
4006 : 16 : c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
4007 : 16 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
4008 : 16 : OMP_CLAUSE_DECL (c2)
4009 : 32 : = convert_from_reference (addr_tokens[i + 1]->expr);
4010 : : }
4011 : 74 : OMP_CLAUSE_SIZE (c2)
4012 : 74 : = fold_build2_loc (loc, MINUS_EXPR, ptrdiff_type_node,
4013 : : fold_convert_loc (loc, ptrdiff_type_node,
4014 : : data_addr),
4015 : : virtual_origin);
4016 : : }
4017 : 74 : break;
4018 : :
4019 : 0 : default:
4020 : 0 : *idx = i + consume_tokens;
4021 : 0 : return error_mark_node;
4022 : : }
4023 : :
4024 : 11985 : if (c3)
4025 : : {
4026 : 34 : OMP_CLAUSE_CHAIN (c3) = OMP_CLAUSE_CHAIN (c);
4027 : 34 : OMP_CLAUSE_CHAIN (c2) = c3;
4028 : 34 : OMP_CLAUSE_CHAIN (c) = c2;
4029 : 34 : if (implicit_p)
4030 : : {
4031 : 0 : OMP_CLAUSE_MAP_IMPLICIT (c2) = 1;
4032 : 0 : OMP_CLAUSE_MAP_IMPLICIT (c3) = 1;
4033 : : }
4034 : : c = c3;
4035 : : }
4036 : 17832 : else if (c2)
4037 : : {
4038 : 3466 : OMP_CLAUSE_CHAIN (c2) = OMP_CLAUSE_CHAIN (c);
4039 : 3466 : OMP_CLAUSE_CHAIN (c) = c2;
4040 : 3466 : if (implicit_p)
4041 : 116 : OMP_CLAUSE_MAP_IMPLICIT (c2) = 1;
4042 : : c = c2;
4043 : : }
4044 : :
4045 : 17866 : i += consume_tokens;
4046 : 17866 : *idx = i;
4047 : :
4048 : 17866 : if (chain_p && map_p)
4049 : 53 : return omp_expand_access_chain (c, expr, addr_tokens, idx, ort);
4050 : :
4051 : : return c;
4052 : : }
4053 : :
4054 : : /* Translate "component_selector access_method" to OMP mapping clauses. */
4055 : :
4056 : : tree
4057 : 2894 : c_omp_address_inspector::expand_component_selector (tree c,
4058 : : vec<omp_addr_token *>
4059 : : &addr_tokens,
4060 : : tree expr, unsigned *idx,
4061 : : c_omp_region_type ort)
4062 : : {
4063 : 2894 : using namespace omp_addr_tokenizer;
4064 : 2894 : location_t loc = OMP_CLAUSE_LOCATION (c);
4065 : 2894 : unsigned i = *idx;
4066 : 2894 : tree c2 = NULL_TREE, c3 = NULL_TREE;
4067 : 2894 : bool chain_p = omp_access_chain_p (addr_tokens, i + 1);
4068 : 2894 : bool map_p = OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP;
4069 : :
4070 : 2894 : switch (addr_tokens[i + 1]->u.access_kind)
4071 : : {
4072 : : case ACCESS_DIRECT:
4073 : : case ACCESS_INDEXED_ARRAY:
4074 : : break;
4075 : :
4076 : 479 : case ACCESS_REF:
4077 : 479 : {
4078 : : /* Copy the referenced object. Note that we also do this for !MAP_P
4079 : : clauses. */
4080 : 479 : tree obj = convert_from_reference (addr_tokens[i + 1]->expr);
4081 : 479 : OMP_CLAUSE_DECL (c) = obj;
4082 : 479 : OMP_CLAUSE_SIZE (c) = TYPE_SIZE_UNIT (TREE_TYPE (obj));
4083 : :
4084 : 479 : if (!map_p)
4085 : : break;
4086 : :
4087 : 461 : c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
4088 : 461 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
4089 : 461 : OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
4090 : 461 : OMP_CLAUSE_SIZE (c2) = size_zero_node;
4091 : : }
4092 : 461 : break;
4093 : :
4094 : 92 : case ACCESS_INDEXED_REF_TO_ARRAY:
4095 : 92 : {
4096 : 92 : if (!map_p)
4097 : : break;
4098 : :
4099 : 92 : tree virtual_origin
4100 : 92 : = convert_from_reference (addr_tokens[i + 1]->expr);
4101 : 92 : virtual_origin = build_fold_addr_expr (virtual_origin);
4102 : 92 : virtual_origin = fold_convert_loc (loc, ptrdiff_type_node,
4103 : : virtual_origin);
4104 : 92 : tree data_addr = omp_accessed_addr (addr_tokens, i + 1, expr);
4105 : :
4106 : 92 : c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
4107 : 92 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
4108 : 92 : OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
4109 : 92 : OMP_CLAUSE_SIZE (c2)
4110 : 92 : = fold_build2_loc (loc, MINUS_EXPR, ptrdiff_type_node,
4111 : : fold_convert_loc (loc, ptrdiff_type_node,
4112 : : data_addr),
4113 : : virtual_origin);
4114 : : }
4115 : 92 : break;
4116 : :
4117 : 778 : case ACCESS_POINTER:
4118 : 778 : case ACCESS_POINTER_OFFSET:
4119 : 778 : {
4120 : 778 : if (!map_p)
4121 : : break;
4122 : :
4123 : 778 : tree virtual_origin
4124 : 1556 : = fold_convert_loc (loc, ptrdiff_type_node,
4125 : 778 : addr_tokens[i + 1]->expr);
4126 : 778 : tree data_addr = omp_accessed_addr (addr_tokens, i + 1, expr);
4127 : :
4128 : 778 : c2 = build_omp_clause (loc, OMP_CLAUSE_MAP);
4129 : 778 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
4130 : 778 : OMP_CLAUSE_DECL (c2) = addr_tokens[i + 1]->expr;
4131 : 778 : OMP_CLAUSE_SIZE (c2)
4132 : 778 : = fold_build2_loc (loc, MINUS_EXPR, ptrdiff_type_node,
4133 : : fold_convert_loc (loc, ptrdiff_type_node,
4134 : : data_addr),
4135 : : virtual_origin);
4136 : : }
4137 : 778 : break;
4138 : :
4139 : 185 : case ACCESS_REF_TO_POINTER:
4140 : 185 : case ACCESS_REF_TO_POINTER_OFFSET:
4141 : 185 : {
4142 : 185 : if (!map_p)
4143 : : break;
4144 : :
4145 : 185 : tree ptr = convert_from_reference (addr_tokens[i + 1]->expr);
4146 : 185 : tree virtual_origin = fold_convert_loc (loc, ptrdiff_type_node,
4147 : : ptr);
4148 : 185 : tree data_addr = omp_accessed_addr (addr_tokens, i + 1, expr);
4149 : :
4150 : : /* Attach the pointer... */
4151 : 185 : c2 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
4152 : 185 : OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
4153 : 185 : OMP_CLAUSE_DECL (c2) = ptr;
4154 : 185 : OMP_CLAUSE_SIZE (c2)
4155 : 185 : = fold_build2_loc (loc, MINUS_EXPR, ptrdiff_type_node,
4156 : : fold_convert_loc (loc, ptrdiff_type_node,
4157 : : data_addr),
4158 : : virtual_origin);
4159 : :
4160 : : /* ...and also the reference. */
4161 : 185 : c3 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
4162 : 185 : OMP_CLAUSE_SET_MAP_KIND (c3, GOMP_MAP_ATTACH_DETACH);
4163 : 185 : OMP_CLAUSE_DECL (c3) = addr_tokens[i + 1]->expr;
4164 : 185 : OMP_CLAUSE_SIZE (c3) = size_zero_node;
4165 : : }
4166 : 185 : break;
4167 : :
4168 : 0 : default:
4169 : 0 : *idx = i + 2;
4170 : 0 : return error_mark_node;
4171 : : }
4172 : :
4173 : 1331 : if (c3)
4174 : : {
4175 : 185 : OMP_CLAUSE_CHAIN (c3) = OMP_CLAUSE_CHAIN (c);
4176 : 185 : OMP_CLAUSE_CHAIN (c2) = c3;
4177 : 185 : OMP_CLAUSE_CHAIN (c) = c2;
4178 : 185 : c = c3;
4179 : : }
4180 : 2709 : else if (c2)
4181 : : {
4182 : 1331 : OMP_CLAUSE_CHAIN (c2) = OMP_CLAUSE_CHAIN (c);
4183 : 1331 : OMP_CLAUSE_CHAIN (c) = c2;
4184 : 1331 : c = c2;
4185 : : }
4186 : :
4187 : 2894 : i += 2;
4188 : 2894 : *idx = i;
4189 : :
4190 : 2894 : if (chain_p && map_p)
4191 : 22 : return omp_expand_access_chain (c, expr, addr_tokens, idx, ort);
4192 : :
4193 : : return c;
4194 : : }
4195 : :
4196 : : /* Expand a map clause into a group of mapping clauses, creating nodes to
4197 : : attach/detach pointers and so forth as necessary. */
4198 : :
4199 : : tree
4200 : 20788 : c_omp_address_inspector::expand_map_clause (tree c, tree expr,
4201 : : vec<omp_addr_token *> &addr_tokens,
4202 : : c_omp_region_type ort)
4203 : : {
4204 : 20788 : using namespace omp_addr_tokenizer;
4205 : 20788 : unsigned i, length = addr_tokens.length ();
4206 : :
4207 : 45165 : for (i = 0; i < length;)
4208 : : {
4209 : 24377 : int remaining = length - i;
4210 : :
4211 : 24377 : if (remaining >= 2
4212 : 24377 : && addr_tokens[i]->type == ARRAY_BASE
4213 : 17894 : && addr_tokens[i]->u.structure_base_kind == BASE_DECL
4214 : 42262 : && addr_tokens[i + 1]->type == ACCESS_METHOD)
4215 : : {
4216 : 17885 : c = expand_array_base (c, addr_tokens, expr, &i, ort);
4217 : 17885 : if (c == error_mark_node)
4218 : : return error_mark_node;
4219 : : }
4220 : 6492 : else if (remaining >= 2
4221 : 6492 : && addr_tokens[i]->type == ARRAY_BASE
4222 : 9 : && addr_tokens[i]->u.structure_base_kind == BASE_ARBITRARY_EXPR
4223 : 6501 : && addr_tokens[i + 1]->type == ACCESS_METHOD)
4224 : : {
4225 : 9 : c = expand_array_base (c, addr_tokens, expr, &i, ort);
4226 : 9 : if (c == error_mark_node)
4227 : : return error_mark_node;
4228 : : }
4229 : 6483 : else if (remaining >= 2
4230 : 6483 : && addr_tokens[i]->type == STRUCTURE_BASE
4231 : 2894 : && addr_tokens[i]->u.structure_base_kind == BASE_DECL
4232 : 9374 : && addr_tokens[i + 1]->type == ACCESS_METHOD)
4233 : : {
4234 : 2891 : if (addr_tokens[i + 1]->u.access_kind == ACCESS_DIRECT)
4235 : 1422 : c_common_mark_addressable_vec (addr_tokens[i + 1]->expr);
4236 : 2891 : i += 2;
4237 : 3051 : while (addr_tokens[i]->type == ACCESS_METHOD)
4238 : 160 : i++;
4239 : : }
4240 : 3592 : else if (remaining >= 2
4241 : 3592 : && addr_tokens[i]->type == STRUCTURE_BASE
4242 : 3 : && addr_tokens[i]->u.structure_base_kind == BASE_ARBITRARY_EXPR
4243 : 3595 : && addr_tokens[i + 1]->type == ACCESS_METHOD)
4244 : : {
4245 : 3 : switch (addr_tokens[i + 1]->u.access_kind)
4246 : : {
4247 : 3 : case ACCESS_DIRECT:
4248 : 3 : case ACCESS_POINTER:
4249 : 3 : i += 2;
4250 : 3 : while (addr_tokens[i]->type == ACCESS_METHOD)
4251 : 0 : i++;
4252 : : break;
4253 : 0 : default:
4254 : 0 : return error_mark_node;
4255 : : }
4256 : : }
4257 : 3589 : else if (remaining >= 2
4258 : 3589 : && addr_tokens[i]->type == COMPONENT_SELECTOR
4259 : 7178 : && addr_tokens[i + 1]->type == ACCESS_METHOD)
4260 : : {
4261 : 2894 : c = expand_component_selector (c, addr_tokens, expr, &i, ort);
4262 : : /* We used 'expr', so these must have been the last tokens. */
4263 : 2894 : gcc_assert (i == length);
4264 : 2894 : if (c == error_mark_node)
4265 : : return error_mark_node;
4266 : : }
4267 : 695 : else if (remaining >= 3
4268 : 695 : && addr_tokens[i]->type == COMPONENT_SELECTOR
4269 : 695 : && addr_tokens[i + 1]->type == STRUCTURE_BASE
4270 : 695 : && (addr_tokens[i + 1]->u.structure_base_kind
4271 : : == BASE_COMPONENT_EXPR)
4272 : 1390 : && addr_tokens[i + 2]->type == ACCESS_METHOD)
4273 : : {
4274 : 695 : i += 3;
4275 : 719 : while (addr_tokens[i]->type == ACCESS_METHOD)
4276 : 24 : i++;
4277 : : }
4278 : : else
4279 : : break;
4280 : : }
4281 : :
4282 : 20788 : if (i == length)
4283 : : return c;
4284 : :
4285 : 0 : return error_mark_node;
4286 : : }
4287 : :
4288 : : /* Given a mapper function MAPPER_FN, recursively scan through the map clauses
4289 : : for that mapper, and if any of those should use a (named or unnamed) mapper
4290 : : themselves, add it to MLIST. */
4291 : :
4292 : : void
4293 : 130 : c_omp_find_nested_mappers (omp_mapper_list<tree> *mlist, tree mapper_fn)
4294 : : {
4295 : 130 : tree mapper = lang_hooks.decls.omp_extract_mapper_directive (mapper_fn);
4296 : 130 : tree mapper_name = NULL_TREE;
4297 : :
4298 : 130 : if (mapper == error_mark_node)
4299 : : return;
4300 : :
4301 : 130 : gcc_assert (TREE_CODE (mapper) == OMP_DECLARE_MAPPER);
4302 : :
4303 : 410 : for (tree clause = OMP_DECLARE_MAPPER_CLAUSES (mapper);
4304 : 410 : clause;
4305 : 280 : clause = OMP_CLAUSE_CHAIN (clause))
4306 : : {
4307 : 280 : tree expr = OMP_CLAUSE_DECL (clause);
4308 : 280 : enum gomp_map_kind clause_kind = OMP_CLAUSE_MAP_KIND (clause);
4309 : 280 : tree elem_type;
4310 : :
4311 : 280 : if (clause_kind == GOMP_MAP_PUSH_MAPPER_NAME)
4312 : : {
4313 : 0 : mapper_name = expr;
4314 : 0 : continue;
4315 : : }
4316 : 280 : else if (clause_kind == GOMP_MAP_POP_MAPPER_NAME)
4317 : : {
4318 : 0 : mapper_name = NULL_TREE;
4319 : 0 : continue;
4320 : : }
4321 : :
4322 : 280 : gcc_assert (TREE_CODE (expr) != TREE_LIST);
4323 : 280 : if (TREE_CODE (expr) == OMP_ARRAY_SECTION)
4324 : : {
4325 : 220 : while (TREE_CODE (expr) == OMP_ARRAY_SECTION)
4326 : 110 : expr = TREE_OPERAND (expr, 0);
4327 : :
4328 : 110 : elem_type = TREE_TYPE (expr);
4329 : : }
4330 : : else
4331 : 170 : elem_type = TREE_TYPE (expr);
4332 : :
4333 : : /* This might be too much... or not enough? */
4334 : 478 : while (TREE_CODE (elem_type) == ARRAY_TYPE
4335 : 472 : || TREE_CODE (elem_type) == POINTER_TYPE
4336 : 758 : || TREE_CODE (elem_type) == REFERENCE_TYPE)
4337 : 198 : elem_type = TREE_TYPE (elem_type);
4338 : :
4339 : 280 : elem_type = TYPE_MAIN_VARIANT (elem_type);
4340 : :
4341 : 280 : if (RECORD_OR_UNION_TYPE_P (elem_type)
4342 : 280 : && !mlist->contains (mapper_name, elem_type))
4343 : : {
4344 : 5 : tree nested_mapper_fn
4345 : 5 : = lang_hooks.decls.omp_mapper_lookup (mapper_name, elem_type);
4346 : :
4347 : 5 : if (nested_mapper_fn)
4348 : : {
4349 : 5 : mlist->add_mapper (mapper_name, elem_type, nested_mapper_fn);
4350 : 5 : c_omp_find_nested_mappers (mlist, nested_mapper_fn);
4351 : : }
4352 : 0 : else if (mapper_name)
4353 : : {
4354 : 0 : error ("mapper %qE not found for type %qT", mapper_name,
4355 : : elem_type);
4356 : 0 : continue;
4357 : : }
4358 : : }
4359 : : }
4360 : : }
4361 : :
4362 : : struct remap_mapper_decl_info
4363 : : {
4364 : : tree dummy_var;
4365 : : tree expr;
4366 : : };
4367 : :
4368 : : /* Helper for rewriting DUMMY_VAR into EXPR in a map clause decl. */
4369 : :
4370 : : static tree
4371 : 1072 : remap_mapper_decl_1 (tree *tp, int *walk_subtrees, void *data)
4372 : : {
4373 : 1072 : remap_mapper_decl_info *map_info = (remap_mapper_decl_info *) data;
4374 : :
4375 : 1072 : if (operand_equal_p (*tp, map_info->dummy_var))
4376 : : {
4377 : 251 : *tp = map_info->expr;
4378 : 251 : *walk_subtrees = 0;
4379 : : }
4380 : :
4381 : 1072 : return NULL_TREE;
4382 : : }
4383 : :
4384 : : /* Instantiate a mapper MAPPER for expression EXPR, adding new clauses to
4385 : : OUTLIST. OUTER_KIND is the mapping kind to use if not already specified in
4386 : : the mapper declaration. */
4387 : :
4388 : : static tree *
4389 : 49 : omp_instantiate_mapper (tree *outlist, tree mapper, tree expr,
4390 : : enum gomp_map_kind outer_kind)
4391 : : {
4392 : 49 : tree clauses = OMP_DECLARE_MAPPER_CLAUSES (mapper);
4393 : 49 : tree dummy_var = OMP_DECLARE_MAPPER_DECL (mapper);
4394 : 49 : tree mapper_name = NULL_TREE;
4395 : :
4396 : 49 : remap_mapper_decl_info map_info;
4397 : 49 : map_info.dummy_var = dummy_var;
4398 : 49 : map_info.expr = expr;
4399 : :
4400 : 163 : for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
4401 : : {
4402 : 114 : tree unshared = unshare_expr (c);
4403 : 114 : enum gomp_map_kind clause_kind = OMP_CLAUSE_MAP_KIND (c);
4404 : 114 : tree t = OMP_CLAUSE_DECL (unshared);
4405 : 114 : tree type = NULL_TREE;
4406 : 114 : bool nonunit_array_with_mapper = false;
4407 : :
4408 : 114 : if (clause_kind == GOMP_MAP_PUSH_MAPPER_NAME)
4409 : : {
4410 : 0 : mapper_name = t;
4411 : 2 : continue;
4412 : : }
4413 : 114 : else if (clause_kind == GOMP_MAP_POP_MAPPER_NAME)
4414 : : {
4415 : 0 : mapper_name = NULL_TREE;
4416 : 0 : continue;
4417 : : }
4418 : :
4419 : 114 : if (TREE_CODE (t) == OMP_ARRAY_SECTION)
4420 : : {
4421 : 41 : location_t loc = OMP_CLAUSE_LOCATION (c);
4422 : 41 : tree t2 = lang_hooks.decls.omp_map_array_section (loc, t);
4423 : :
4424 : 41 : if (t2 == t)
4425 : : {
4426 : 40 : nonunit_array_with_mapper = true;
4427 : : /* We'd want use the mapper for the element type if this worked:
4428 : : look that one up. */
4429 : 40 : type = TREE_TYPE (TREE_TYPE (t));
4430 : : }
4431 : : else
4432 : : {
4433 : 1 : t = t2;
4434 : 1 : type = TREE_TYPE (t);
4435 : : }
4436 : : }
4437 : : else
4438 : 73 : type = TREE_TYPE (t);
4439 : :
4440 : 114 : gcc_assert (type);
4441 : :
4442 : 114 : if (type == error_mark_node)
4443 : 0 : continue;
4444 : :
4445 : 114 : walk_tree (&unshared, remap_mapper_decl_1, &map_info, NULL);
4446 : :
4447 : 114 : if (OMP_CLAUSE_MAP_KIND (unshared) == GOMP_MAP_UNSET)
4448 : 56 : OMP_CLAUSE_SET_MAP_KIND (unshared, outer_kind);
4449 : :
4450 : 114 : type = TYPE_MAIN_VARIANT (type);
4451 : :
4452 : 114 : tree mapper_fn = lang_hooks.decls.omp_mapper_lookup (mapper_name, type);
4453 : :
4454 : 114 : if (mapper_fn && nonunit_array_with_mapper)
4455 : : {
4456 : 0 : sorry ("user-defined mapper with non-unit length array section");
4457 : 0 : continue;
4458 : : }
4459 : 114 : else if (mapper_fn)
4460 : : {
4461 : 12 : tree nested_mapper
4462 : 12 : = lang_hooks.decls.omp_extract_mapper_directive (mapper_fn);
4463 : 12 : if (nested_mapper != mapper)
4464 : : {
4465 : 2 : if (clause_kind == GOMP_MAP_UNSET)
4466 : 0 : clause_kind = outer_kind;
4467 : :
4468 : 2 : outlist = omp_instantiate_mapper (outlist, nested_mapper,
4469 : : t, clause_kind);
4470 : 2 : continue;
4471 : : }
4472 : : }
4473 : 102 : else if (mapper_name)
4474 : : {
4475 : 0 : error ("mapper %qE not found for type %qT", mapper_name, type);
4476 : 0 : continue;
4477 : : }
4478 : :
4479 : 112 : *outlist = unshared;
4480 : 112 : outlist = &OMP_CLAUSE_CHAIN (unshared);
4481 : : }
4482 : :
4483 : 49 : return outlist;
4484 : : }
4485 : :
4486 : : /* Given a list of CLAUSES, scan each clause and invoke a user-defined mapper
4487 : : appropriate to the type of the data in that clause, if such a mapper is
4488 : : visible in the current parsing context. */
4489 : :
4490 : : tree
4491 : 5802 : c_omp_instantiate_mappers (tree clauses)
4492 : : {
4493 : 5802 : tree c, *pc, mapper_name = NULL_TREE;
4494 : :
4495 : 12218 : for (pc = &clauses, c = clauses; c; c = *pc)
4496 : : {
4497 : 6416 : bool using_mapper = false;
4498 : :
4499 : 6416 : switch (OMP_CLAUSE_CODE (c))
4500 : : {
4501 : 4673 : case OMP_CLAUSE_MAP:
4502 : 4673 : {
4503 : 4673 : tree t = OMP_CLAUSE_DECL (c);
4504 : 4673 : tree type = NULL_TREE;
4505 : 4673 : bool nonunit_array_with_mapper = false;
4506 : :
4507 : 4673 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_PUSH_MAPPER_NAME
4508 : 4673 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POP_MAPPER_NAME)
4509 : : {
4510 : 38 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_PUSH_MAPPER_NAME)
4511 : 19 : mapper_name = OMP_CLAUSE_DECL (c);
4512 : : else
4513 : : mapper_name = NULL_TREE;
4514 : 38 : pc = &OMP_CLAUSE_CHAIN (c);
4515 : 38 : continue;
4516 : : }
4517 : :
4518 : 4635 : if (TREE_CODE (t) == OMP_ARRAY_SECTION)
4519 : : {
4520 : 1771 : location_t loc = OMP_CLAUSE_LOCATION (c);
4521 : 1771 : tree t2 = lang_hooks.decls.omp_map_array_section (loc, t);
4522 : :
4523 : 1771 : if (t2 == t)
4524 : : {
4525 : : /* !!! Array sections of size >1 with mappers for elements
4526 : : are hard to support. Do something here. */
4527 : 1486 : nonunit_array_with_mapper = true;
4528 : 1486 : type = TREE_TYPE (TREE_TYPE (t));
4529 : : }
4530 : : else
4531 : : {
4532 : 285 : t = t2;
4533 : 285 : type = TREE_TYPE (t);
4534 : : }
4535 : : }
4536 : : else
4537 : 2864 : type = TREE_TYPE (t);
4538 : :
4539 : 4635 : if (type == NULL_TREE || type == error_mark_node)
4540 : : {
4541 : 56 : pc = &OMP_CLAUSE_CHAIN (c);
4542 : 56 : continue;
4543 : : }
4544 : :
4545 : 4579 : enum gomp_map_kind kind = OMP_CLAUSE_MAP_KIND (c);
4546 : 4579 : if (kind == GOMP_MAP_UNSET)
4547 : 0 : kind = GOMP_MAP_TOFROM;
4548 : :
4549 : 4579 : type = TYPE_MAIN_VARIANT (type);
4550 : :
4551 : 4579 : tree mapper_fn
4552 : 4579 : = lang_hooks.decls.omp_mapper_lookup (mapper_name, type);
4553 : :
4554 : 4579 : if (mapper_fn && nonunit_array_with_mapper)
4555 : : {
4556 : 0 : sorry ("user-defined mapper with non-unit length "
4557 : : "array section");
4558 : 0 : using_mapper = true;
4559 : : }
4560 : 4579 : else if (mapper_fn)
4561 : : {
4562 : 47 : tree mapper
4563 : 47 : = lang_hooks.decls.omp_extract_mapper_directive (mapper_fn);
4564 : 47 : pc = omp_instantiate_mapper (pc, mapper, t, kind);
4565 : 47 : using_mapper = true;
4566 : : }
4567 : 4532 : else if (mapper_name)
4568 : : {
4569 : 0 : error ("mapper %qE not found for type %qT", mapper_name, type);
4570 : 0 : using_mapper = true;
4571 : : }
4572 : : }
4573 : : break;
4574 : :
4575 : 47 : default:
4576 : 47 : ;
4577 : : }
4578 : :
4579 : 47 : if (using_mapper)
4580 : 47 : *pc = OMP_CLAUSE_CHAIN (c);
4581 : : else
4582 : 6275 : pc = &OMP_CLAUSE_CHAIN (c);
4583 : : }
4584 : :
4585 : 5802 : return clauses;
4586 : : }
4587 : :
4588 : : const struct c_omp_directive c_omp_directives[] = {
4589 : : /* Keep this alphabetically sorted by the first word. Non-null second/third
4590 : : if any should precede null ones. */
4591 : : { "allocate", nullptr, nullptr, PRAGMA_OMP_ALLOCATE,
4592 : : C_OMP_DIR_DECLARATIVE, false },
4593 : : { "assume", nullptr, nullptr, PRAGMA_OMP_ASSUME,
4594 : : C_OMP_DIR_INFORMATIONAL, false },
4595 : : { "assumes", nullptr, nullptr, PRAGMA_OMP_ASSUMES,
4596 : : C_OMP_DIR_INFORMATIONAL, false },
4597 : : { "atomic", nullptr, nullptr, PRAGMA_OMP_ATOMIC,
4598 : : C_OMP_DIR_CONSTRUCT, false },
4599 : : { "barrier", nullptr, nullptr, PRAGMA_OMP_BARRIER,
4600 : : C_OMP_DIR_STANDALONE, false },
4601 : : { "begin", "assumes", nullptr, PRAGMA_OMP_BEGIN,
4602 : : C_OMP_DIR_INFORMATIONAL, false },
4603 : : { "begin", "declare", "target", PRAGMA_OMP_BEGIN,
4604 : : C_OMP_DIR_DECLARATIVE, false },
4605 : : /* { "begin", "declare", "variant", PRAGMA_OMP_BEGIN,
4606 : : C_OMP_DIR_DECLARATIVE, false }, */
4607 : : /* { "begin", "metadirective", nullptr, PRAGMA_OMP_BEGIN,
4608 : : C_OMP_DIR_META, false }, */
4609 : : { "cancel", nullptr, nullptr, PRAGMA_OMP_CANCEL,
4610 : : C_OMP_DIR_STANDALONE, false },
4611 : : { "cancellation", "point", nullptr, PRAGMA_OMP_CANCELLATION_POINT,
4612 : : C_OMP_DIR_STANDALONE, false },
4613 : : { "critical", nullptr, nullptr, PRAGMA_OMP_CRITICAL,
4614 : : C_OMP_DIR_CONSTRUCT, false },
4615 : : /* { "declare", "mapper", nullptr, PRAGMA_OMP_DECLARE,
4616 : : C_OMP_DIR_DECLARATIVE, false }, */
4617 : : { "declare", "reduction", nullptr, PRAGMA_OMP_DECLARE,
4618 : : C_OMP_DIR_DECLARATIVE, true },
4619 : : { "declare", "simd", nullptr, PRAGMA_OMP_DECLARE,
4620 : : C_OMP_DIR_DECLARATIVE, true },
4621 : : { "declare", "target", nullptr, PRAGMA_OMP_DECLARE,
4622 : : C_OMP_DIR_DECLARATIVE, false },
4623 : : { "declare", "variant", nullptr, PRAGMA_OMP_DECLARE,
4624 : : C_OMP_DIR_DECLARATIVE, false },
4625 : : { "depobj", nullptr, nullptr, PRAGMA_OMP_DEPOBJ,
4626 : : C_OMP_DIR_STANDALONE, false },
4627 : : { "dispatch", nullptr, nullptr, PRAGMA_OMP_DISPATCH,
4628 : : C_OMP_DIR_DECLARATIVE, false },
4629 : : { "distribute", nullptr, nullptr, PRAGMA_OMP_DISTRIBUTE,
4630 : : C_OMP_DIR_CONSTRUCT, true },
4631 : : { "end", "assumes", nullptr, PRAGMA_OMP_END,
4632 : : C_OMP_DIR_INFORMATIONAL, false },
4633 : : { "end", "declare", "target", PRAGMA_OMP_END,
4634 : : C_OMP_DIR_DECLARATIVE, false },
4635 : : /* { "end", "declare", "variant", PRAGMA_OMP_END,
4636 : : C_OMP_DIR_DECLARATIVE, false }, */
4637 : : /* { "end", "metadirective", nullptr, PRAGMA_OMP_END,
4638 : : C_OMP_DIR_META, false }, */
4639 : : /* error with at(execution) is C_OMP_DIR_STANDALONE. */
4640 : : { "error", nullptr, nullptr, PRAGMA_OMP_ERROR,
4641 : : C_OMP_DIR_UTILITY, false },
4642 : : { "flush", nullptr, nullptr, PRAGMA_OMP_FLUSH,
4643 : : C_OMP_DIR_STANDALONE, false },
4644 : : { "for", nullptr, nullptr, PRAGMA_OMP_FOR,
4645 : : C_OMP_DIR_CONSTRUCT, true },
4646 : : /* { "groupprivate", nullptr, nullptr, PRAGMA_OMP_GROUPPRIVATE,
4647 : : C_OMP_DIR_DECLARATIVE, false }, */
4648 : : { "interop", nullptr, nullptr, PRAGMA_OMP_INTEROP,
4649 : : C_OMP_DIR_STANDALONE, false },
4650 : : { "loop", nullptr, nullptr, PRAGMA_OMP_LOOP,
4651 : : C_OMP_DIR_CONSTRUCT, true },
4652 : : { "masked", nullptr, nullptr, PRAGMA_OMP_MASKED,
4653 : : C_OMP_DIR_CONSTRUCT, true },
4654 : : { "master", nullptr, nullptr, PRAGMA_OMP_MASTER,
4655 : : C_OMP_DIR_CONSTRUCT, true },
4656 : : { "metadirective", nullptr, nullptr, PRAGMA_OMP_METADIRECTIVE,
4657 : : C_OMP_DIR_META, false },
4658 : : { "nothing", nullptr, nullptr, PRAGMA_OMP_NOTHING,
4659 : : C_OMP_DIR_UTILITY, false },
4660 : : /* ordered with depend clause is C_OMP_DIR_STANDALONE. */
4661 : : { "ordered", nullptr, nullptr, PRAGMA_OMP_ORDERED,
4662 : : C_OMP_DIR_CONSTRUCT, true },
4663 : : { "parallel", nullptr, nullptr, PRAGMA_OMP_PARALLEL,
4664 : : C_OMP_DIR_CONSTRUCT, true },
4665 : : { "requires", nullptr, nullptr, PRAGMA_OMP_REQUIRES,
4666 : : C_OMP_DIR_INFORMATIONAL, false },
4667 : : { "scan", nullptr, nullptr, PRAGMA_OMP_SCAN,
4668 : : C_OMP_DIR_CONSTRUCT, true },
4669 : : { "scope", nullptr, nullptr, PRAGMA_OMP_SCOPE,
4670 : : C_OMP_DIR_CONSTRUCT, false },
4671 : : { "section", nullptr, nullptr, PRAGMA_OMP_SECTION,
4672 : : C_OMP_DIR_CONSTRUCT, false },
4673 : : { "sections", nullptr, nullptr, PRAGMA_OMP_SECTIONS,
4674 : : C_OMP_DIR_CONSTRUCT, false },
4675 : : { "simd", nullptr, nullptr, PRAGMA_OMP_SIMD,
4676 : : C_OMP_DIR_CONSTRUCT, true },
4677 : : { "single", nullptr, nullptr, PRAGMA_OMP_SINGLE,
4678 : : C_OMP_DIR_CONSTRUCT, false },
4679 : : { "target", "data", nullptr, PRAGMA_OMP_TARGET,
4680 : : C_OMP_DIR_CONSTRUCT, false },
4681 : : { "target", "enter", "data", PRAGMA_OMP_TARGET,
4682 : : C_OMP_DIR_STANDALONE, false },
4683 : : { "target", "exit", "data", PRAGMA_OMP_TARGET,
4684 : : C_OMP_DIR_STANDALONE, false },
4685 : : { "target", "update", nullptr, PRAGMA_OMP_TARGET,
4686 : : C_OMP_DIR_STANDALONE, false },
4687 : : { "target", nullptr, nullptr, PRAGMA_OMP_TARGET,
4688 : : C_OMP_DIR_CONSTRUCT, true },
4689 : : { "task", nullptr, nullptr, PRAGMA_OMP_TASK,
4690 : : C_OMP_DIR_CONSTRUCT, false },
4691 : : { "taskgroup", nullptr, nullptr, PRAGMA_OMP_TASKGROUP,
4692 : : C_OMP_DIR_CONSTRUCT, false },
4693 : : { "taskloop", nullptr, nullptr, PRAGMA_OMP_TASKLOOP,
4694 : : C_OMP_DIR_CONSTRUCT, true },
4695 : : { "taskwait", nullptr, nullptr, PRAGMA_OMP_TASKWAIT,
4696 : : C_OMP_DIR_STANDALONE, false },
4697 : : { "taskyield", nullptr, nullptr, PRAGMA_OMP_TASKYIELD,
4698 : : C_OMP_DIR_STANDALONE, false },
4699 : : { "tile", nullptr, nullptr, PRAGMA_OMP_TILE,
4700 : : C_OMP_DIR_CONSTRUCT, false },
4701 : : { "teams", nullptr, nullptr, PRAGMA_OMP_TEAMS,
4702 : : C_OMP_DIR_CONSTRUCT, true },
4703 : : { "threadprivate", nullptr, nullptr, PRAGMA_OMP_THREADPRIVATE,
4704 : : C_OMP_DIR_DECLARATIVE, false },
4705 : : { "unroll", nullptr, nullptr, PRAGMA_OMP_UNROLL,
4706 : : C_OMP_DIR_CONSTRUCT, false },
4707 : : };
4708 : :
4709 : : /* Find (non-combined/composite) OpenMP directive (if any) which starts
4710 : : with FIRST keyword and for multi-word directives has SECOND and
4711 : : THIRD keyword after it. */
4712 : :
4713 : : const struct c_omp_directive *
4714 : 6534 : c_omp_categorize_directive (const char *first, const char *second,
4715 : : const char *third)
4716 : : {
4717 : 6534 : const size_t n_omp_directives = ARRAY_SIZE (c_omp_directives);
4718 : 187941 : for (size_t i = 0; i < n_omp_directives; i++)
4719 : : {
4720 : 350536 : if ((unsigned char) c_omp_directives[i].first[0]
4721 : 187941 : < (unsigned char) first[0])
4722 : 162595 : continue;
4723 : 25346 : if ((unsigned char) c_omp_directives[i].first[0]
4724 : : > (unsigned char) first[0])
4725 : : break;
4726 : 25259 : if (strcmp (c_omp_directives[i].first, first))
4727 : 15566 : continue;
4728 : 9693 : if (!c_omp_directives[i].second)
4729 : 5072 : return &c_omp_directives[i];
4730 : 4621 : if (!second || strcmp (c_omp_directives[i].second, second))
4731 : 3234 : continue;
4732 : 1387 : if (!c_omp_directives[i].third)
4733 : 1099 : return &c_omp_directives[i];
4734 : 288 : if (!third || strcmp (c_omp_directives[i].third, third))
4735 : 12 : continue;
4736 : 276 : return &c_omp_directives[i];
4737 : : }
4738 : : return NULL;
4739 : : }
4740 : :
4741 : : /* Auxilliary helper function for c_omp_expand_variant_construct. */
4742 : :
4743 : : static tree
4744 : 462 : c_omp_expand_variant_construct_r (vec<struct omp_variant> &candidates,
4745 : : hash_map<tree, tree> &body_labels,
4746 : : unsigned index)
4747 : : {
4748 : 462 : struct omp_variant &candidate = candidates[index];
4749 : 462 : tree if_block = push_stmt_list ();
4750 : 462 : if (candidate.alternative != NULL_TREE)
4751 : 462 : add_stmt (candidate.alternative);
4752 : 462 : if (candidate.body != NULL_TREE)
4753 : : {
4754 : 138 : tree *label = body_labels.get (candidate.body);
4755 : 138 : if (label != NULL)
4756 : 0 : add_stmt (build1 (GOTO_EXPR, void_type_node, *label));
4757 : : else
4758 : : {
4759 : 138 : tree body_label = create_artificial_label (UNKNOWN_LOCATION);
4760 : 138 : add_stmt (build1 (LABEL_EXPR, void_type_node, body_label));
4761 : 138 : add_stmt (candidate.body);
4762 : 138 : body_labels.put (candidate.body, body_label);
4763 : : }
4764 : : }
4765 : 462 : if_block = pop_stmt_list (if_block);
4766 : :
4767 : 924 : if (index == candidates.length () - 1)
4768 : : return if_block;
4769 : :
4770 : 154 : tree cond = omp_dynamic_cond (candidate.selector, NULL_TREE);
4771 : 154 : gcc_assert (cond != NULL_TREE);
4772 : :
4773 : 154 : tree else_block = c_omp_expand_variant_construct_r (candidates, body_labels,
4774 : : index + 1);
4775 : 154 : tree ret = push_stmt_list ();
4776 : 154 : tree stmt = build3 (COND_EXPR, void_type_node, cond, if_block, else_block);
4777 : 154 : add_stmt (stmt);
4778 : 154 : ret = pop_stmt_list (ret);
4779 : :
4780 : 154 : return ret;
4781 : : }
4782 : :
4783 : : /* Resolve the vector of metadirective variant CANDIDATES to a parse tree
4784 : : structure. */
4785 : :
4786 : : tree
4787 : 308 : c_omp_expand_variant_construct (vec<struct omp_variant> &candidates)
4788 : : {
4789 : 308 : hash_map<tree, tree> body_labels;
4790 : 308 : return c_omp_expand_variant_construct_r (candidates, body_labels, 0);
4791 : 308 : }
|