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