Daily bump.
[official-gcc.git] / gcc / c / c-array-notation.c
blobe6a1539cda951c8c3e6f30371437dc9af5ac1235
1 /* This file is part of the Intel(R) Cilk(TM) Plus support
2 This file contains routines to handle Array Notation expression
3 handling routines in the C Compiler.
4 Copyright (C) 2013-2015 Free Software Foundation, Inc.
5 Contributed by Balaji V. Iyer <balaji.v.iyer@intel.com>,
6 Intel Corporation.
8 This file is part of GCC.
10 GCC is free software; you can redistribute it and/or modify it
11 under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3, or (at your option)
13 any later version.
15 GCC is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
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/>. */
24 /* The Array Notation Transformation Technique:
26 An array notation expression has 4 major components:
27 1. The array name
28 2. Start Index
29 3. Number of elements we need to acess (we call it length)
30 4. Stride
32 For example, A[0:5:2], implies that we are accessing A[0], A[2], A[4],
33 A[6] and A[8]. The user is responsible to make sure the access length does
34 not step outside the array's size.
36 In this section, I highlight the overall method on how array notations are
37 broken up into C/C++ code. Almost all the functions follows this overall
38 technique:
40 Let's say we have an array notation in a statement like this:
42 A[St1:Ln:Str1] = B[St2:Ln:Str2] + <NON ARRAY_NOTATION_STMT>
44 where St{1,2} = Starting index,
45 Ln = Number of elements we need to access,
46 and Str{1,2} = the stride.
47 Note: The length of both the array notation expressions must be the same.
49 The above expression is broken into the following
50 (with the help of c_finish_loop function from c-typeck.c):
52 Tmp_Var = 0;
53 goto compare_label:
54 body_label:
56 A[St1+Tmp_Var*Str1] = B[St1+Tmp_Var*Str2] + <NON ARRAY_NOTATION_STMT>;
57 Tmp_Var++;
59 compare_label:
60 if (Tmp_Var < Ln)
61 goto body_label;
62 else
63 goto exit_label;
64 exit_label:
68 #include "config.h"
69 #include "system.h"
70 #include "coretypes.h"
71 #include "symtab.h"
72 #include "alias.h"
73 #include "flags.h"
74 #include "tree.h"
75 #include "c-tree.h"
76 #include "gimple-expr.h"
77 #include "tree-iterator.h"
78 #include "opts.h"
79 #include "c-family/c-common.h"
81 /* If *VALUE is not of type INTEGER_CST, PARM_DECL or VAR_DECL, then map it
82 to a variable and then set *VALUE to the new variable. */
84 static inline void
85 make_triplet_val_inv (location_t loc, tree *value)
87 tree var, new_exp;
88 if (TREE_CODE (*value) != INTEGER_CST
89 && TREE_CODE (*value) != PARM_DECL
90 && !VAR_P (*value))
92 var = build_decl (loc, VAR_DECL, NULL_TREE, integer_type_node);
93 new_exp = build_modify_expr (loc, var, TREE_TYPE (var), NOP_EXPR, loc,
94 *value, TREE_TYPE (*value));
95 add_stmt (new_exp);
96 *value = var;
100 /* Populates the INCR and CMP vectors with the increment (of type POSTINCREMENT
101 or POSTDECREMENT) and comparison (of TYPE GT_EXPR or LT_EXPR) expressions,
102 using data from LENGTH, COUNT_DOWN, and VAR. INCR and CMP vectors are of
103 size RANK. */
105 static void
106 create_cmp_incr (location_t loc, vec<an_loop_parts> *node, size_t rank,
107 vec<vec<an_parts> > an_info)
109 for (size_t ii = 0; ii < rank; ii++)
111 tree var = (*node)[ii].var;
112 tree length = an_info[0][ii].length;
113 (*node)[ii].incr = build_unary_op (loc, POSTINCREMENT_EXPR, var, 0);
114 (*node)[ii].cmp = build2 (LT_EXPR, boolean_type_node, var, length);
118 /* Returns a vector of size RANK that contains an array ref that is derived from
119 array notation triplet parameters stored in VALUE, START, STRIDE. IS_VECTOR
120 is used to check if the data stored at its corresponding location is an
121 array notation. VAR is the induction variable passed in by the caller.
123 For example: For an array notation A[5:10:2], the vector start will be
124 of size 1 holding '5', stride of same size as start but holding the value of
125 as 2, is_vector as true and count_down as false. Let's assume VAR is 'x'
126 This function returns a vector of size 1 with the following data:
127 A[5 + (x * 2)] .
130 static vec<tree, va_gc> *
131 create_array_refs (location_t loc, vec<vec<an_parts> > an_info,
132 vec<an_loop_parts> an_loop_info, size_t size, size_t rank)
134 tree ind_mult, ind_incr;
135 vec<tree, va_gc> *array_operand = NULL;
136 for (size_t ii = 0; ii < size; ii++)
137 if (an_info[ii][0].is_vector)
139 tree array_opr = an_info[ii][rank - 1].value;
140 for (int s_jj = rank - 1; s_jj >= 0; s_jj--)
142 tree var = an_loop_info[s_jj].var;
143 tree stride = an_info[ii][s_jj].stride;
144 tree start = an_info[ii][s_jj].start;
145 ind_mult = build2 (MULT_EXPR, TREE_TYPE (var), var, stride);
146 ind_incr = build2 (PLUS_EXPR, TREE_TYPE (var), start, ind_mult);
147 array_opr = build_array_ref (loc, array_opr, ind_incr);
149 vec_safe_push (array_operand, array_opr);
151 else
152 /* This is just a dummy node to make sure both the list sizes for both
153 array list and array operand list are the same. */
154 vec_safe_push (array_operand, integer_one_node);
155 return array_operand;
158 /* Replaces all the scalar expressions in *NODE. Returns a STATEMENT_LIST that
159 holds the NODE along with variables that holds the results of the invariant
160 expressions. */
162 tree
163 replace_invariant_exprs (tree *node)
165 size_t ix = 0;
166 tree node_list = NULL_TREE;
167 tree t = NULL_TREE, new_var = NULL_TREE, new_node;
168 struct inv_list data;
170 data.list_values = NULL;
171 data.replacement = NULL;
172 data.additional_tcodes = NULL;
173 walk_tree (node, find_inv_trees, (void *)&data, NULL);
175 if (vec_safe_length (data.list_values))
177 node_list = push_stmt_list ();
178 for (ix = 0; vec_safe_iterate (data.list_values, ix, &t); ix++)
180 new_var = build_decl (EXPR_LOCATION (t), VAR_DECL, NULL_TREE,
181 TREE_TYPE (t));
182 gcc_assert (new_var != NULL_TREE && new_var != error_mark_node);
183 new_node = build2 (MODIFY_EXPR, TREE_TYPE (t), new_var, t);
184 add_stmt (new_node);
185 vec_safe_push (data.replacement, new_var);
187 walk_tree (node, replace_inv_trees, (void *)&data, NULL);
188 node_list = pop_stmt_list (node_list);
190 return node_list;
193 /* Given a CALL_EXPR to an array notation built-in function in
194 AN_BUILTIN_FN, replace the call with the appropriate loop and
195 computation. Return the computation in *NEW_VAR.
197 The return value in *NEW_VAR will always be a scalar. If the
198 built-in is __sec_reduce_mutating, *NEW_VAR is set to NULL_TREE. */
200 static tree
201 fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var)
203 tree new_var_type = NULL_TREE, func_parm, new_expr, new_yes_expr, new_no_expr;
204 tree array_ind_value = NULL_TREE, new_no_ind, new_yes_ind, new_no_list;
205 tree new_yes_list, new_cond_expr, new_var_init = NULL_TREE;
206 tree new_exp_init = NULL_TREE;
207 vec<tree, va_gc> *array_list = NULL, *array_operand = NULL;
208 size_t list_size = 0, rank = 0, ii = 0;
209 tree loop_init, array_op0;
210 tree identity_value = NULL_TREE, call_fn = NULL_TREE, new_call_expr, body;
211 location_t location = UNKNOWN_LOCATION;
212 tree loop_with_init = alloc_stmt_list ();
213 vec<vec<an_parts> > an_info = vNULL;
214 vec<an_loop_parts> an_loop_info = vNULL;
215 enum built_in_function an_type =
216 is_cilkplus_reduce_builtin (CALL_EXPR_FN (an_builtin_fn));
217 if (an_type == BUILT_IN_NONE)
218 return NULL_TREE;
220 /* Builtin call should contain at least one argument. */
221 if (call_expr_nargs (an_builtin_fn) == 0)
223 error_at (EXPR_LOCATION (an_builtin_fn), "Invalid builtin arguments");
224 return error_mark_node;
227 if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE
228 || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING)
230 call_fn = CALL_EXPR_ARG (an_builtin_fn, 2);
231 if (TREE_CODE (call_fn) == ADDR_EXPR)
232 call_fn = TREE_OPERAND (call_fn, 0);
233 identity_value = CALL_EXPR_ARG (an_builtin_fn, 0);
234 func_parm = CALL_EXPR_ARG (an_builtin_fn, 1);
236 else
237 func_parm = CALL_EXPR_ARG (an_builtin_fn, 0);
239 /* Fully fold any EXCESSIVE_PRECISION EXPR that can occur in the function
240 parameter. */
241 func_parm = c_fully_fold (func_parm, false, NULL);
242 if (func_parm == error_mark_node)
243 return error_mark_node;
245 location = EXPR_LOCATION (an_builtin_fn);
247 if (!find_rank (location, an_builtin_fn, an_builtin_fn, true, &rank))
248 return error_mark_node;
250 if (rank == 0)
252 error_at (location, "Invalid builtin arguments");
253 return error_mark_node;
255 else if (rank > 1
256 && (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
257 || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND))
259 error_at (location, "__sec_reduce_min_ind or __sec_reduce_max_ind cannot"
260 " have arrays with dimension greater than 1");
261 return error_mark_node;
264 extract_array_notation_exprs (func_parm, true, &array_list);
265 list_size = vec_safe_length (array_list);
266 switch (an_type)
268 case BUILT_IN_CILKPLUS_SEC_REDUCE_ADD:
269 case BUILT_IN_CILKPLUS_SEC_REDUCE_MUL:
270 case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX:
271 case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN:
272 new_var_type = TREE_TYPE ((*array_list)[0]);
273 break;
274 case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_ZERO:
275 case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_NONZERO:
276 case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO:
277 case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_NONZERO:
278 new_var_type = integer_type_node;
279 break;
280 case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND:
281 case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND:
282 new_var_type = integer_type_node;
283 break;
284 case BUILT_IN_CILKPLUS_SEC_REDUCE:
285 if (call_fn && identity_value)
286 new_var_type = TREE_TYPE ((*array_list)[0]);
287 break;
288 case BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING:
289 new_var_type = NULL_TREE;
290 break;
291 default:
292 gcc_unreachable ();
295 an_loop_info.safe_grow_cleared (rank);
296 cilkplus_extract_an_triplets (array_list, list_size, rank, &an_info);
297 loop_init = alloc_stmt_list ();
299 for (ii = 0; ii < rank; ii++)
301 an_loop_info[ii].var = create_tmp_var (integer_type_node);
302 an_loop_info[ii].ind_init =
303 build_modify_expr (location, an_loop_info[ii].var,
304 TREE_TYPE (an_loop_info[ii].var), NOP_EXPR,
305 location,
306 build_int_cst (TREE_TYPE (an_loop_info[ii].var), 0),
307 TREE_TYPE (an_loop_info[ii].var));
309 array_operand = create_array_refs (location, an_info, an_loop_info,
310 list_size, rank);
311 replace_array_notations (&func_parm, true, array_list, array_operand);
313 create_cmp_incr (location, &an_loop_info, rank, an_info);
314 if (an_type != BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING)
316 *new_var = build_decl (location, VAR_DECL, NULL_TREE, new_var_type);
317 gcc_assert (*new_var && *new_var != error_mark_node);
319 else
320 *new_var = NULL_TREE;
322 if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
323 || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND)
324 array_ind_value = build_decl (location, VAR_DECL, NULL_TREE,
325 TREE_TYPE (func_parm));
326 array_op0 = (*array_operand)[0];
327 if (INDIRECT_REF_P (array_op0))
328 array_op0 = TREE_OPERAND (array_op0, 0);
329 switch (an_type)
331 case BUILT_IN_CILKPLUS_SEC_REDUCE_ADD:
332 new_var_init = build_modify_expr
333 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
334 location, build_zero_cst (new_var_type), new_var_type);
335 new_expr = build_modify_expr
336 (location, *new_var, TREE_TYPE (*new_var), PLUS_EXPR,
337 location, func_parm, TREE_TYPE (func_parm));
338 break;
339 case BUILT_IN_CILKPLUS_SEC_REDUCE_MUL:
340 new_var_init = build_modify_expr
341 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
342 location, build_one_cst (new_var_type), new_var_type);
343 new_expr = build_modify_expr
344 (location, *new_var, TREE_TYPE (*new_var), MULT_EXPR,
345 location, func_parm, TREE_TYPE (func_parm));
346 break;
347 case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_ZERO:
348 new_var_init = build_modify_expr
349 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
350 location, build_one_cst (new_var_type), new_var_type);
351 /* Initially you assume everything is zero, now if we find a case where
352 it is NOT true, then we set the result to false. Otherwise
353 we just keep the previous value. */
354 new_yes_expr = build_modify_expr
355 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
356 location, build_zero_cst (TREE_TYPE (*new_var)),
357 TREE_TYPE (*new_var));
358 new_no_expr = build_modify_expr
359 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
360 location, *new_var, TREE_TYPE (*new_var));
361 new_cond_expr = build2 (NE_EXPR, TREE_TYPE (func_parm), func_parm,
362 build_zero_cst (TREE_TYPE (func_parm)));
363 new_expr = build_conditional_expr
364 (location, new_cond_expr, false, new_yes_expr,
365 TREE_TYPE (new_yes_expr), new_no_expr, TREE_TYPE (new_no_expr));
366 break;
367 case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_NONZERO:
368 new_var_init = build_modify_expr
369 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
370 location, build_one_cst (new_var_type), new_var_type);
371 /* Initially you assume everything is non-zero, now if we find a case
372 where it is NOT true, then we set the result to false. Otherwise
373 we just keep the previous value. */
374 new_yes_expr = build_modify_expr
375 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
376 location, build_zero_cst (TREE_TYPE (*new_var)),
377 TREE_TYPE (*new_var));
378 new_no_expr = build_modify_expr
379 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
380 location, *new_var, TREE_TYPE (*new_var));
381 new_cond_expr = build2 (EQ_EXPR, TREE_TYPE (func_parm), func_parm,
382 build_zero_cst (TREE_TYPE (func_parm)));
383 new_expr = build_conditional_expr
384 (location, new_cond_expr, false, new_yes_expr,
385 TREE_TYPE (new_yes_expr), new_no_expr, TREE_TYPE (new_no_expr));
386 break;
387 case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO:
388 new_var_init = build_modify_expr
389 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
390 location, build_zero_cst (new_var_type), new_var_type);
391 /* Initially we assume there are NO zeros in the list. When we find
392 a non-zero, we keep the previous value. If we find a zero, we
393 set the value to true. */
394 new_yes_expr = build_modify_expr
395 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
396 location, build_one_cst (new_var_type), new_var_type);
397 new_no_expr = build_modify_expr
398 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
399 location, *new_var, TREE_TYPE (*new_var));
400 new_cond_expr = build2 (EQ_EXPR, TREE_TYPE (func_parm), func_parm,
401 build_zero_cst (TREE_TYPE (func_parm)));
402 new_expr = build_conditional_expr
403 (location, new_cond_expr, false, new_yes_expr,
404 TREE_TYPE (new_yes_expr), new_no_expr, TREE_TYPE (new_no_expr));
405 break;
406 case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_NONZERO:
407 new_var_init = build_modify_expr
408 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
409 location, build_zero_cst (new_var_type), new_var_type);
410 /* Initially we assume there are NO non-zeros in the list. When we find
411 a zero, we keep the previous value. If we find a non-zero, we set
412 the value to true. */
413 new_yes_expr = build_modify_expr
414 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
415 location, build_one_cst (new_var_type), new_var_type);
416 new_no_expr = build_modify_expr
417 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
418 location, *new_var, TREE_TYPE (*new_var));
419 new_cond_expr = build2 (NE_EXPR, TREE_TYPE (func_parm), func_parm,
420 build_zero_cst (TREE_TYPE (func_parm)));
421 new_expr = build_conditional_expr
422 (location, new_cond_expr, false, new_yes_expr,
423 TREE_TYPE (new_yes_expr), new_no_expr, TREE_TYPE (new_no_expr));
424 break;
425 case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX:
426 if (TYPE_MIN_VALUE (new_var_type))
427 new_var_init = build_modify_expr
428 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
429 location, TYPE_MIN_VALUE (new_var_type), new_var_type);
430 else
431 new_var_init = build_modify_expr
432 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
433 location, func_parm, new_var_type);
434 new_no_expr = build_modify_expr
435 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
436 location, *new_var, TREE_TYPE (*new_var));
437 new_yes_expr = build_modify_expr
438 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
439 location, func_parm, TREE_TYPE (*new_var));
440 new_expr = build_conditional_expr
441 (location,
442 build2 (LT_EXPR, TREE_TYPE (*new_var), *new_var, func_parm), false,
443 new_yes_expr, TREE_TYPE (*new_var), new_no_expr, TREE_TYPE (*new_var));
444 break;
445 case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN:
446 if (TYPE_MAX_VALUE (new_var_type))
447 new_var_init = build_modify_expr
448 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
449 location, TYPE_MAX_VALUE (new_var_type), new_var_type);
450 else
451 new_var_init = build_modify_expr
452 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
453 location, func_parm, new_var_type);
454 new_no_expr = build_modify_expr
455 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
456 location, *new_var, TREE_TYPE (*new_var));
457 new_yes_expr = build_modify_expr
458 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
459 location, func_parm, TREE_TYPE (*new_var));
460 new_expr = build_conditional_expr
461 (location,
462 build2 (GT_EXPR, TREE_TYPE (*new_var), *new_var, func_parm), false,
463 new_yes_expr, TREE_TYPE (*new_var), new_no_expr, TREE_TYPE (*new_var));
464 break;
465 case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND:
466 new_var_init = build_modify_expr
467 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
468 location, build_zero_cst (new_var_type), new_var_type);
469 new_exp_init = build_modify_expr
470 (location, array_ind_value, TREE_TYPE (array_ind_value),
471 NOP_EXPR, location, func_parm, TREE_TYPE (func_parm));
472 new_no_ind = build_modify_expr
473 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
474 location, *new_var, TREE_TYPE (*new_var));
475 new_no_expr = build_modify_expr
476 (location, array_ind_value, TREE_TYPE (array_ind_value),
477 NOP_EXPR,
478 location, array_ind_value, TREE_TYPE (array_ind_value));
479 if (list_size > 1)
481 new_yes_ind = build_modify_expr
482 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
483 location, an_loop_info[0].var, TREE_TYPE (an_loop_info[0].var));
484 new_yes_expr = build_modify_expr
485 (location, array_ind_value, TREE_TYPE (array_ind_value),
486 NOP_EXPR,
487 location, func_parm, TREE_TYPE ((*array_operand)[0]));
489 else
491 new_yes_ind = build_modify_expr
492 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
493 location, TREE_OPERAND (array_op0, 1),
494 TREE_TYPE (TREE_OPERAND (array_op0, 1)));
495 new_yes_expr = build_modify_expr
496 (location, array_ind_value, TREE_TYPE (array_ind_value),
497 NOP_EXPR,
498 location, func_parm, TREE_OPERAND (array_op0, 1));
500 new_yes_list = alloc_stmt_list ();
501 append_to_statement_list (new_yes_ind, &new_yes_list);
502 append_to_statement_list (new_yes_expr, &new_yes_list);
504 new_no_list = alloc_stmt_list ();
505 append_to_statement_list (new_no_ind, &new_no_list);
506 append_to_statement_list (new_no_expr, &new_no_list);
508 new_expr = build_conditional_expr
509 (location,
510 build2 (LE_EXPR, TREE_TYPE (array_ind_value), array_ind_value,
511 func_parm),
512 false,
513 new_yes_list, TREE_TYPE (*new_var), new_no_list, TREE_TYPE (*new_var));
514 break;
515 case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND:
516 new_var_init = build_modify_expr
517 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
518 location, build_zero_cst (new_var_type), new_var_type);
519 new_exp_init = build_modify_expr
520 (location, array_ind_value, TREE_TYPE (array_ind_value),
521 NOP_EXPR, location, func_parm, TREE_TYPE (func_parm));
522 new_no_ind = build_modify_expr
523 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
524 location, *new_var, TREE_TYPE (*new_var));
525 new_no_expr = build_modify_expr
526 (location, array_ind_value, TREE_TYPE (array_ind_value),
527 NOP_EXPR,
528 location, array_ind_value, TREE_TYPE (array_ind_value));
529 if (list_size > 1)
531 new_yes_ind = build_modify_expr
532 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
533 location, an_loop_info[0].var, TREE_TYPE (an_loop_info[0].var));
534 new_yes_expr = build_modify_expr
535 (location, array_ind_value, TREE_TYPE (array_ind_value),
536 NOP_EXPR,
537 location, func_parm, TREE_TYPE (array_op0));
539 else
541 new_yes_ind = build_modify_expr
542 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
543 location, TREE_OPERAND (array_op0, 1),
544 TREE_TYPE (TREE_OPERAND (array_op0, 1)));
545 new_yes_expr = build_modify_expr
546 (location, array_ind_value, TREE_TYPE (array_ind_value),
547 NOP_EXPR,
548 location, func_parm, TREE_OPERAND (array_op0, 1));
550 new_yes_list = alloc_stmt_list ();
551 append_to_statement_list (new_yes_ind, &new_yes_list);
552 append_to_statement_list (new_yes_expr, &new_yes_list);
554 new_no_list = alloc_stmt_list ();
555 append_to_statement_list (new_no_ind, &new_no_list);
556 append_to_statement_list (new_no_expr, &new_no_list);
558 new_expr = build_conditional_expr
559 (location,
560 build2 (GE_EXPR, TREE_TYPE (array_ind_value), array_ind_value,
561 func_parm),
562 false,
563 new_yes_list, TREE_TYPE (*new_var), new_no_list, TREE_TYPE (*new_var));
564 break;
565 case BUILT_IN_CILKPLUS_SEC_REDUCE:
566 new_var_init = build_modify_expr
567 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
568 location, identity_value, new_var_type);
569 new_call_expr = build_call_expr (call_fn, 2, *new_var, func_parm);
570 new_expr = build_modify_expr
571 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
572 location, new_call_expr, TREE_TYPE (*new_var));
573 break;
574 case BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING:
575 new_expr = build_call_expr (call_fn, 2, identity_value, func_parm);
576 break;
577 default:
578 gcc_unreachable ();
579 break;
582 for (ii = 0; ii < rank; ii++)
583 append_to_statement_list (an_loop_info[ii].ind_init, &loop_init);
585 if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
586 || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND)
587 append_to_statement_list (new_exp_init, &loop_init);
588 if (an_type != BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING)
589 append_to_statement_list (new_var_init, &loop_init);
591 append_to_statement_list_force (loop_init, &loop_with_init);
592 body = new_expr;
593 for (ii = 0; ii < rank; ii++)
595 tree new_loop = push_stmt_list ();
596 c_finish_loop (location, an_loop_info[ii].cmp, an_loop_info[ii].incr,
597 body, NULL_TREE, NULL_TREE, true);
598 body = pop_stmt_list (new_loop);
600 append_to_statement_list_force (body, &loop_with_init);
602 an_info.release ();
603 an_loop_info.release ();
605 return loop_with_init;
608 /* Returns a loop with ARRAY_REF inside it with an appropriate modify expr.
609 The LHS and/or RHS will be array notation expressions that have a MODIFYCODE
610 Their locations are specified by LHS_LOC, RHS_LOC. The location of the
611 modify expression is location. The original type of LHS and RHS are passed
612 in LHS_ORIGTYPE and RHS_ORIGTYPE. */
614 tree
615 build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype,
616 enum tree_code modifycode, location_t rhs_loc,
617 tree rhs, tree rhs_origtype)
619 bool found_builtin_fn = false;
620 tree array_expr_lhs = NULL_TREE, array_expr_rhs = NULL_TREE;
621 tree array_expr = NULL_TREE;
622 tree an_init = NULL_TREE;
623 vec<tree> cond_expr = vNULL;
624 tree body, loop_with_init = alloc_stmt_list();
625 tree scalar_mods = NULL_TREE;
626 vec<tree, va_gc> *rhs_array_operand = NULL, *lhs_array_operand = NULL;
627 size_t lhs_rank = 0, rhs_rank = 0;
628 size_t ii = 0;
629 vec<tree, va_gc> *lhs_list = NULL, *rhs_list = NULL;
630 tree new_modify_expr, new_var = NULL_TREE, builtin_loop = NULL_TREE;
631 size_t rhs_list_size = 0, lhs_list_size = 0;
632 vec<vec<an_parts> > lhs_an_info = vNULL, rhs_an_info = vNULL;
633 vec<an_loop_parts> lhs_an_loop_info = vNULL, rhs_an_loop_info = vNULL;
635 /* If either of this is true, an error message must have been send out
636 already. Not necessary to send out multiple error messages. */
637 if (lhs == error_mark_node || rhs == error_mark_node)
638 return error_mark_node;
640 if (!find_rank (location, rhs, rhs, false, &rhs_rank))
641 return error_mark_node;
643 extract_array_notation_exprs (rhs, false, &rhs_list);
644 rhs_list_size = vec_safe_length (rhs_list);
645 an_init = push_stmt_list ();
646 if (rhs_rank)
648 scalar_mods = replace_invariant_exprs (&rhs);
649 if (scalar_mods)
650 add_stmt (scalar_mods);
652 for (ii = 0; ii < rhs_list_size; ii++)
654 tree rhs_node = (*rhs_list)[ii];
655 if (TREE_CODE (rhs_node) == CALL_EXPR)
657 builtin_loop = fix_builtin_array_notation_fn (rhs_node, &new_var);
658 if (builtin_loop == error_mark_node)
660 pop_stmt_list (an_init);
661 return error_mark_node;
663 else if (builtin_loop)
665 add_stmt (builtin_loop);
666 found_builtin_fn = true;
667 if (new_var)
669 vec<tree, va_gc> *rhs_sub_list = NULL, *new_var_list = NULL;
670 vec_safe_push (rhs_sub_list, rhs_node);
671 vec_safe_push (new_var_list, new_var);
672 replace_array_notations (&rhs, false, rhs_sub_list,
673 new_var_list);
679 lhs_rank = 0;
680 rhs_rank = 0;
681 if (!find_rank (location, lhs, lhs, true, &lhs_rank))
683 pop_stmt_list (an_init);
684 return error_mark_node;
687 if (!find_rank (location, rhs, rhs, true, &rhs_rank))
689 pop_stmt_list (an_init);
690 return error_mark_node;
693 if (lhs_rank == 0 && rhs_rank == 0)
695 if (found_builtin_fn)
697 new_modify_expr = build_modify_expr (location, lhs, lhs_origtype,
698 modifycode, rhs_loc, rhs,
699 rhs_origtype);
700 add_stmt (new_modify_expr);
701 pop_stmt_list (an_init);
702 return an_init;
704 else
706 pop_stmt_list (an_init);
707 return NULL_TREE;
710 rhs_list_size = 0;
711 rhs_list = NULL;
712 extract_array_notation_exprs (rhs, true, &rhs_list);
713 extract_array_notation_exprs (lhs, true, &lhs_list);
714 rhs_list_size = vec_safe_length (rhs_list);
715 lhs_list_size = vec_safe_length (lhs_list);
717 if (lhs_rank == 0 && rhs_rank != 0)
719 tree rhs_base = rhs;
720 if (TREE_CODE (rhs_base) == ARRAY_NOTATION_REF)
722 for (ii = 0; ii < (size_t) rhs_rank; ii++)
723 rhs_base = ARRAY_NOTATION_ARRAY (rhs);
725 error_at (location, "%qE cannot be scalar when %qE is not", lhs,
726 rhs_base);
727 return error_mark_node;
729 else
731 error_at (location, "%qE cannot be scalar when %qE is not", lhs,
732 rhs_base);
733 return error_mark_node;
736 if (lhs_rank != 0 && rhs_rank != 0 && lhs_rank != rhs_rank)
738 error_at (location, "rank mismatch between %qE and %qE", lhs, rhs);
739 pop_stmt_list (an_init);
740 return error_mark_node;
743 /* Here we assign the array notation components to variable so that we can
744 satisfy the exec once rule. */
745 for (ii = 0; ii < lhs_list_size; ii++)
747 tree array_node = (*lhs_list)[ii];
748 make_triplet_val_inv (location, &ARRAY_NOTATION_START (array_node));
749 make_triplet_val_inv (location, &ARRAY_NOTATION_LENGTH (array_node));
750 make_triplet_val_inv (location, &ARRAY_NOTATION_STRIDE (array_node));
752 for (ii = 0; ii < rhs_list_size; ii++)
753 if ((*rhs_list)[ii] && TREE_CODE ((*rhs_list)[ii]) == ARRAY_NOTATION_REF)
755 tree array_node = (*rhs_list)[ii];
756 make_triplet_val_inv (location, &ARRAY_NOTATION_START (array_node));
757 make_triplet_val_inv (location, &ARRAY_NOTATION_LENGTH (array_node));
758 make_triplet_val_inv (location, &ARRAY_NOTATION_STRIDE (array_node));
761 cond_expr.safe_grow_cleared (MAX (lhs_rank, rhs_rank));
763 lhs_an_loop_info.safe_grow_cleared (lhs_rank);
764 if (rhs_rank)
765 rhs_an_loop_info.safe_grow_cleared (rhs_rank);
767 cilkplus_extract_an_triplets (lhs_list, lhs_list_size, lhs_rank,
768 &lhs_an_info);
769 if (rhs_rank)
771 rhs_an_loop_info.safe_grow_cleared (rhs_rank);
772 cilkplus_extract_an_triplets (rhs_list, rhs_list_size, rhs_rank,
773 &rhs_an_info);
775 if (length_mismatch_in_expr_p (EXPR_LOCATION (lhs), lhs_an_info)
776 || (rhs_rank
777 && length_mismatch_in_expr_p (EXPR_LOCATION (rhs), rhs_an_info)))
779 pop_stmt_list (an_init);
780 return error_mark_node;
782 if (lhs_list_size > 0 && rhs_list_size > 0 && lhs_rank > 0 && rhs_rank > 0
783 && TREE_CODE (lhs_an_info[0][0].length) == INTEGER_CST
784 && rhs_an_info[0][0].length
785 && TREE_CODE (rhs_an_info[0][0].length) == INTEGER_CST)
787 HOST_WIDE_INT l_length = int_cst_value (lhs_an_info[0][0].length);
788 HOST_WIDE_INT r_length = int_cst_value (rhs_an_info[0][0].length);
789 /* Length can be negative or positive. As long as the magnitude is OK,
790 then the array notation is valid. */
791 if (absu_hwi (l_length) != absu_hwi (r_length))
793 error_at (location, "length mismatch between LHS and RHS");
794 pop_stmt_list (an_init);
795 return error_mark_node;
798 for (ii = 0; ii < lhs_rank; ii++)
799 if (lhs_an_info[0][ii].is_vector)
801 lhs_an_loop_info[ii].var = create_tmp_var (integer_type_node);
802 lhs_an_loop_info[ii].ind_init = build_modify_expr
803 (location, lhs_an_loop_info[ii].var,
804 TREE_TYPE (lhs_an_loop_info[ii].var), NOP_EXPR,
805 location, build_zero_cst (TREE_TYPE (lhs_an_loop_info[ii].var)),
806 TREE_TYPE (lhs_an_loop_info[ii].var));
808 for (ii = 0; ii < rhs_rank; ii++)
810 /* When we have a polynomial, we assume that the indices are of type
811 integer. */
812 rhs_an_loop_info[ii].var = create_tmp_var (integer_type_node);
813 rhs_an_loop_info[ii].ind_init = build_modify_expr
814 (location, rhs_an_loop_info[ii].var,
815 TREE_TYPE (rhs_an_loop_info[ii].var), NOP_EXPR,
816 location, build_int_cst (TREE_TYPE (rhs_an_loop_info[ii].var), 0),
817 TREE_TYPE (rhs_an_loop_info[ii].var));
819 if (lhs_rank)
821 lhs_array_operand = create_array_refs
822 (location, lhs_an_info, lhs_an_loop_info, lhs_list_size, lhs_rank);
823 replace_array_notations (&lhs, true, lhs_list, lhs_array_operand);
824 array_expr_lhs = lhs;
826 if (rhs_array_operand)
827 vec_safe_truncate (rhs_array_operand, 0);
828 if (rhs_rank)
830 rhs_array_operand = create_array_refs
831 (location, rhs_an_info, rhs_an_loop_info, rhs_list_size, rhs_rank);
832 replace_array_notations (&rhs, true, rhs_list, rhs_array_operand);
833 vec_safe_truncate (rhs_array_operand, 0);
834 rhs_array_operand = fix_sec_implicit_args (location, rhs_list,
835 rhs_an_loop_info, rhs_rank,
836 rhs);
837 if (!rhs_array_operand)
838 return error_mark_node;
839 replace_array_notations (&rhs, true, rhs_list, rhs_array_operand);
841 else if (rhs_list_size > 0)
843 rhs_array_operand = fix_sec_implicit_args (location, rhs_list,
844 lhs_an_loop_info, lhs_rank,
845 lhs);
846 if (!rhs_array_operand)
847 return error_mark_node;
848 replace_array_notations (&rhs, true, rhs_list, rhs_array_operand);
850 array_expr_lhs = lhs;
851 array_expr_rhs = rhs;
852 array_expr = build_modify_expr (location, array_expr_lhs, lhs_origtype,
853 modifycode, rhs_loc, array_expr_rhs,
854 rhs_origtype);
855 create_cmp_incr (location, &lhs_an_loop_info, lhs_rank, lhs_an_info);
856 if (rhs_rank)
857 create_cmp_incr (location, &rhs_an_loop_info, rhs_rank, rhs_an_info);
859 for (ii = 0; ii < MAX (lhs_rank, rhs_rank); ii++)
860 if (ii < lhs_rank && ii < rhs_rank)
861 cond_expr[ii] = build2 (TRUTH_ANDIF_EXPR, boolean_type_node,
862 lhs_an_loop_info[ii].cmp,
863 rhs_an_loop_info[ii].cmp);
864 else if (ii < lhs_rank && ii >= rhs_rank)
865 cond_expr[ii] = lhs_an_loop_info[ii].cmp;
866 else
867 gcc_unreachable ();
869 an_init = pop_stmt_list (an_init);
870 append_to_statement_list_force (an_init, &loop_with_init);
871 body = array_expr;
872 for (ii = 0; ii < MAX (lhs_rank, rhs_rank); ii++)
874 tree incr_list = alloc_stmt_list ();
875 tree new_loop = push_stmt_list ();
876 if (lhs_rank)
877 add_stmt (lhs_an_loop_info[ii].ind_init);
878 if (rhs_rank)
879 add_stmt (rhs_an_loop_info[ii].ind_init);
880 if (lhs_rank)
881 append_to_statement_list_force (lhs_an_loop_info[ii].incr, &incr_list);
882 if (rhs_rank && rhs_an_loop_info[ii].incr)
883 append_to_statement_list_force (rhs_an_loop_info[ii].incr, &incr_list);
884 c_finish_loop (location, cond_expr[ii], incr_list, body, NULL_TREE,
885 NULL_TREE, true);
886 body = pop_stmt_list (new_loop);
888 append_to_statement_list_force (body, &loop_with_init);
890 lhs_an_info.release ();
891 lhs_an_loop_info.release ();
892 if (rhs_rank)
894 rhs_an_info.release ();
895 rhs_an_loop_info.release ();
897 cond_expr.release ();
898 return loop_with_init;
901 /* Helper function for fix_conditional_array_notations. Encloses the
902 conditional statement passed in STMT with a loop around it
903 and replaces the condition in STMT with a ARRAY_REF tree-node to the array.
904 The condition must have an ARRAY_NOTATION_REF tree. An expansion of array
905 notation in STMT is returned in a STATEMENT_LIST. */
907 static tree
908 fix_conditional_array_notations_1 (tree stmt)
910 vec<tree, va_gc> *array_list = NULL, *array_operand = NULL;
911 size_t list_size = 0;
912 tree cond = NULL_TREE, builtin_loop = NULL_TREE, new_var = NULL_TREE;
913 size_t rank = 0, ii = 0;
914 tree loop_init;
915 location_t location = EXPR_LOCATION (stmt);
916 tree body = NULL_TREE, loop_with_init = alloc_stmt_list ();
917 vec<vec<an_parts> > an_info = vNULL;
918 vec<an_loop_parts> an_loop_info = vNULL;
920 if (TREE_CODE (stmt) == COND_EXPR)
921 cond = COND_EXPR_COND (stmt);
922 else if (TREE_CODE (stmt) == SWITCH_EXPR)
923 cond = SWITCH_COND (stmt);
924 else if (truth_value_p (TREE_CODE (stmt)))
925 cond = TREE_OPERAND (stmt, 0);
926 else
927 /* Otherwise dont even touch the statement. */
928 return stmt;
930 if (!find_rank (location, cond, cond, false, &rank))
931 return error_mark_node;
933 extract_array_notation_exprs (stmt, false, &array_list);
934 loop_init = push_stmt_list ();
935 for (ii = 0; ii < vec_safe_length (array_list); ii++)
937 tree array_node = (*array_list)[ii];
938 if (TREE_CODE (array_node) == CALL_EXPR)
940 builtin_loop = fix_builtin_array_notation_fn (array_node, &new_var);
941 if (builtin_loop == error_mark_node)
943 add_stmt (error_mark_node);
944 pop_stmt_list (loop_init);
945 return loop_init;
947 else if (builtin_loop)
949 vec <tree, va_gc>* sub_list = NULL, *new_var_list = NULL;
950 vec_safe_push (sub_list, array_node);
951 vec_safe_push (new_var_list, new_var);
952 add_stmt (builtin_loop);
953 replace_array_notations (&stmt, false, sub_list, new_var_list);
957 if (!find_rank (location, stmt, stmt, true, &rank))
959 pop_stmt_list (loop_init);
960 return error_mark_node;
962 if (rank == 0)
964 add_stmt (stmt);
965 pop_stmt_list (loop_init);
966 return loop_init;
968 extract_array_notation_exprs (stmt, true, &array_list);
970 if (vec_safe_length (array_list) == 0)
971 return stmt;
973 list_size = vec_safe_length (array_list);
974 an_loop_info.safe_grow_cleared (rank);
976 for (ii = 0; ii < list_size; ii++)
977 if ((*array_list)[ii]
978 && TREE_CODE ((*array_list)[ii]) == ARRAY_NOTATION_REF)
980 tree array_node = (*array_list)[ii];
981 make_triplet_val_inv (location, &ARRAY_NOTATION_START (array_node));
982 make_triplet_val_inv (location, &ARRAY_NOTATION_LENGTH (array_node));
983 make_triplet_val_inv (location, &ARRAY_NOTATION_STRIDE (array_node));
985 cilkplus_extract_an_triplets (array_list, list_size, rank, &an_info);
986 for (ii = 0; ii < rank; ii++)
988 an_loop_info[ii].var = create_tmp_var (integer_type_node);
989 an_loop_info[ii].ind_init =
990 build_modify_expr (location, an_loop_info[ii].var,
991 TREE_TYPE (an_loop_info[ii].var), NOP_EXPR,
992 location,
993 build_int_cst (TREE_TYPE (an_loop_info[ii].var), 0),
994 TREE_TYPE (an_loop_info[ii].var));
996 array_operand = create_array_refs (location, an_info, an_loop_info,
997 list_size, rank);
998 replace_array_notations (&stmt, true, array_list, array_operand);
999 create_cmp_incr (location, &an_loop_info, rank, an_info);
1001 loop_init = pop_stmt_list (loop_init);
1002 body = stmt;
1003 append_to_statement_list_force (loop_init, &loop_with_init);
1005 for (ii = 0; ii < rank; ii++)
1007 tree new_loop = push_stmt_list ();
1008 add_stmt (an_loop_info[ii].ind_init);
1009 c_finish_loop (location, an_loop_info[ii].cmp, an_loop_info[ii].incr,
1010 body, NULL_TREE, NULL_TREE, true);
1011 body = pop_stmt_list (new_loop);
1013 append_to_statement_list_force (body, &loop_with_init);
1015 an_loop_info.release ();
1016 an_info.release ();
1018 return loop_with_init;
1021 /* Top-level function to replace ARRAY_NOTATION_REF in a conditional statement
1022 in STMT. An expansion of array notation in STMT is returned as a
1023 STATEMENT_LIST. */
1025 tree
1026 fix_conditional_array_notations (tree stmt)
1028 if (TREE_CODE (stmt) == STATEMENT_LIST)
1030 tree_stmt_iterator tsi;
1031 for (tsi = tsi_start (stmt); !tsi_end_p (tsi); tsi_next (&tsi))
1033 tree single_stmt = *tsi_stmt_ptr (tsi);
1034 *tsi_stmt_ptr (tsi) =
1035 fix_conditional_array_notations_1 (single_stmt);
1037 return stmt;
1039 else
1040 return fix_conditional_array_notations_1 (stmt);
1043 /* Create a struct c_expr that contains a loop with ARRAY_REF expr at location
1044 LOCATION with the tree_code CODE and the array notation expr is
1045 passed in ARG. Returns the fixed c_expr in ARG itself. */
1047 struct c_expr
1048 fix_array_notation_expr (location_t location, enum tree_code code,
1049 struct c_expr arg)
1052 vec<tree, va_gc> *array_list = NULL, *array_operand = NULL;
1053 size_t list_size = 0, rank = 0, ii = 0;
1054 tree loop_init;
1055 tree body, loop_with_init = alloc_stmt_list ();
1056 vec<vec<an_parts> > an_info = vNULL;
1057 vec<an_loop_parts> an_loop_info = vNULL;
1059 if (!find_rank (location, arg.value, arg.value, false, &rank))
1061 /* If this function returns a NULL, we convert the tree value in the
1062 structure to error_mark_node and the parser should take care of the
1063 rest. */
1064 arg.value = error_mark_node;
1065 return arg;
1068 if (rank == 0)
1069 return arg;
1071 extract_array_notation_exprs (arg.value, true, &array_list);
1073 if (vec_safe_length (array_list) == 0)
1074 return arg;
1076 list_size = vec_safe_length (array_list);
1078 an_loop_info.safe_grow_cleared (rank);
1079 cilkplus_extract_an_triplets (array_list, list_size, rank, &an_info);
1081 loop_init = push_stmt_list ();
1082 for (ii = 0; ii < rank; ii++)
1084 an_loop_info[ii].var = create_tmp_var (integer_type_node);
1085 an_loop_info[ii].ind_init =
1086 build_modify_expr (location, an_loop_info[ii].var,
1087 TREE_TYPE (an_loop_info[ii].var), NOP_EXPR,
1088 location,
1089 build_int_cst (TREE_TYPE (an_loop_info[ii].var), 0),
1090 TREE_TYPE (an_loop_info[ii].var));;
1093 array_operand = create_array_refs (location, an_info, an_loop_info,
1094 list_size, rank);
1095 replace_array_notations (&arg.value, true, array_list, array_operand);
1096 create_cmp_incr (location, &an_loop_info, rank, an_info);
1098 arg = default_function_array_read_conversion (location, arg);
1099 if (code == POSTINCREMENT_EXPR || code == POSTDECREMENT_EXPR)
1100 arg.value = build_unary_op (location, code, arg.value, 0);
1101 else if (code == PREINCREMENT_EXPR || code == PREDECREMENT_EXPR)
1102 arg = parser_build_unary_op (location, code, arg);
1104 loop_init = pop_stmt_list (loop_init);
1105 append_to_statement_list_force (loop_init, &loop_with_init);
1106 body = arg.value;
1108 for (ii = 0; ii < rank; ii++)
1110 tree new_loop = push_stmt_list ();
1111 add_stmt (an_loop_info[ii].ind_init);
1112 c_finish_loop (location, an_loop_info[ii].cmp,
1113 an_loop_info[ii].incr, body, NULL_TREE,
1114 NULL_TREE, true);
1115 body = pop_stmt_list (new_loop);
1117 append_to_statement_list_force (body, &loop_with_init);
1118 arg.value = loop_with_init;
1119 an_info.release ();
1120 an_loop_info.release ();
1121 return arg;
1124 /* Replaces array notations in a void function call arguments in ARG and returns
1125 a STATEMENT_LIST. */
1127 static tree
1128 fix_array_notation_call_expr (tree arg)
1130 vec<tree, va_gc> *array_list = NULL, *array_operand = NULL;
1131 tree new_var = NULL_TREE;
1132 size_t list_size = 0, rank = 0, ii = 0;
1133 tree loop_init;
1134 tree body, loop_with_init = alloc_stmt_list ();
1135 location_t location = UNKNOWN_LOCATION;
1136 vec<vec<an_parts> > an_info = vNULL;
1137 vec<an_loop_parts> an_loop_info = vNULL;
1139 if (TREE_CODE (arg) == CALL_EXPR
1140 && is_cilkplus_reduce_builtin (CALL_EXPR_FN (arg)))
1142 loop_init = fix_builtin_array_notation_fn (arg, &new_var);
1143 /* We are ignoring the new var because either the user does not want to
1144 capture it OR he is using sec_reduce_mutating function. */
1145 return loop_init;
1147 if (!find_rank (location, arg, arg, false, &rank))
1148 return error_mark_node;
1150 if (rank == 0)
1151 return arg;
1153 extract_array_notation_exprs (arg, true, &array_list);
1154 if (vec_safe_length (array_list) == 0)
1155 return arg;
1157 list_size = vec_safe_length (array_list);
1158 location = EXPR_LOCATION (arg);
1159 an_loop_info.safe_grow_cleared (rank);
1161 loop_init = push_stmt_list ();
1162 for (ii = 0; ii < list_size; ii++)
1163 if ((*array_list)[ii]
1164 && TREE_CODE ((*array_list)[ii]) == ARRAY_NOTATION_REF)
1166 tree array_node = (*array_list)[ii];
1167 make_triplet_val_inv (location, &ARRAY_NOTATION_START (array_node));
1168 make_triplet_val_inv (location, &ARRAY_NOTATION_LENGTH (array_node));
1169 make_triplet_val_inv (location, &ARRAY_NOTATION_STRIDE (array_node));
1171 cilkplus_extract_an_triplets (array_list, list_size, rank, &an_info);
1172 if (length_mismatch_in_expr_p (location, an_info))
1174 pop_stmt_list (loop_init);
1175 return error_mark_node;
1177 for (ii = 0; ii < rank; ii++)
1179 an_loop_info[ii].var = create_tmp_var (integer_type_node);
1180 an_loop_info[ii].ind_init =
1181 build_modify_expr (location, an_loop_info[ii].var,
1182 TREE_TYPE (an_loop_info[ii].var), NOP_EXPR, location,
1183 build_int_cst (TREE_TYPE (an_loop_info[ii].var), 0),
1184 TREE_TYPE (an_loop_info[ii].var));
1187 array_operand = create_array_refs (location, an_info, an_loop_info,
1188 list_size, rank);
1189 replace_array_notations (&arg, true, array_list, array_operand);
1190 create_cmp_incr (location, &an_loop_info, rank, an_info);
1191 loop_init = pop_stmt_list (loop_init);
1192 append_to_statement_list_force (loop_init, &loop_with_init);
1193 body = arg;
1194 for (ii = 0; ii < rank; ii++)
1196 tree new_loop = push_stmt_list ();
1197 add_stmt (an_loop_info[ii].ind_init);
1198 c_finish_loop (location, an_loop_info[ii].cmp, an_loop_info[ii].incr,
1199 body, NULL_TREE, NULL_TREE, true);
1200 body = pop_stmt_list (new_loop);
1202 append_to_statement_list_force (body, &loop_with_init);
1203 an_loop_info.release ();
1204 an_info.release ();
1205 return loop_with_init;
1208 /* Expands the built-in functions in a return. EXPR is a RETURN_EXPR with
1209 a built-in reduction function. This function returns the expansion code for
1210 the built-in function. */
1212 static tree
1213 fix_return_expr (tree expr)
1215 tree new_mod_list, new_var, new_mod, retval_expr, retval_type;
1216 location_t loc = EXPR_LOCATION (expr);
1218 new_mod_list = alloc_stmt_list ();
1219 retval_expr = TREE_OPERAND (expr, 0);
1220 retval_type = TREE_TYPE (TREE_OPERAND (retval_expr, 1));
1221 new_var = build_decl (loc, VAR_DECL, NULL_TREE, TREE_TYPE (retval_expr));
1222 new_mod = build_array_notation_expr (loc, new_var, TREE_TYPE (new_var),
1223 NOP_EXPR, loc,
1224 TREE_OPERAND (retval_expr, 1),
1225 retval_type);
1226 TREE_OPERAND (retval_expr, 1) = new_var;
1227 TREE_OPERAND (expr, 0) = retval_expr;
1228 append_to_statement_list_force (new_mod, &new_mod_list);
1229 append_to_statement_list_force (expr, &new_mod_list);
1230 return new_mod_list;
1233 /* Callback for walk_tree. Expands all array notations in *TP. *WALK_SUBTREES
1234 is set to 1 unless *TP contains no array notation expressions. */
1236 static tree
1237 expand_array_notations (tree *tp, int *walk_subtrees, void *)
1239 if (!contains_array_notation_expr (*tp))
1241 *walk_subtrees = 0;
1242 return NULL_TREE;
1244 *walk_subtrees = 1;
1246 switch (TREE_CODE (*tp))
1248 case TRUTH_ORIF_EXPR:
1249 case TRUTH_ANDIF_EXPR:
1250 case TRUTH_OR_EXPR:
1251 case TRUTH_AND_EXPR:
1252 case TRUTH_XOR_EXPR:
1253 case TRUTH_NOT_EXPR:
1254 case COND_EXPR:
1255 *tp = fix_conditional_array_notations (*tp);
1256 break;
1257 case MODIFY_EXPR:
1259 location_t loc = EXPR_HAS_LOCATION (*tp) ? EXPR_LOCATION (*tp) :
1260 UNKNOWN_LOCATION;
1261 tree lhs = TREE_OPERAND (*tp, 0);
1262 tree rhs = TREE_OPERAND (*tp, 1);
1263 location_t rhs_loc = EXPR_HAS_LOCATION (rhs) ? EXPR_LOCATION (rhs) :
1264 UNKNOWN_LOCATION;
1265 *tp = build_array_notation_expr (loc, lhs, TREE_TYPE (lhs), NOP_EXPR,
1266 rhs_loc, rhs, TREE_TYPE (rhs));
1268 break;
1269 case DECL_EXPR:
1271 tree x = DECL_EXPR_DECL (*tp);
1272 if (DECL_INITIAL (x))
1274 location_t loc = DECL_SOURCE_LOCATION (x);
1275 tree lhs = x;
1276 tree rhs = DECL_INITIAL (x);
1277 DECL_INITIAL (x) = NULL;
1278 tree new_modify_expr = build_modify_expr (loc, lhs,
1279 TREE_TYPE (lhs),
1280 NOP_EXPR,
1281 loc, rhs,
1282 TREE_TYPE(rhs));
1283 expand_array_notations (&new_modify_expr, walk_subtrees, NULL);
1284 *tp = new_modify_expr;
1287 break;
1288 case CALL_EXPR:
1289 *tp = fix_array_notation_call_expr (*tp);
1290 break;
1291 case RETURN_EXPR:
1292 *tp = fix_return_expr (*tp);
1293 break;
1294 case COMPOUND_EXPR:
1295 if (TREE_CODE (TREE_OPERAND (*tp, 0)) == SAVE_EXPR)
1297 /* In here we are calling expand_array_notations because
1298 we need to be able to catch the return value and check if
1299 it is an error_mark_node. */
1300 expand_array_notations (&TREE_OPERAND (*tp, 1), walk_subtrees, NULL);
1302 /* SAVE_EXPR cannot have an error_mark_node inside it. This check
1303 will make sure that if there is an error in expanding of
1304 array notations (e.g. rank mismatch) then replace the entire
1305 SAVE_EXPR with an error_mark_node. */
1306 if (TREE_OPERAND (*tp, 1) == error_mark_node)
1307 *tp = error_mark_node;
1309 break;
1310 case ARRAY_NOTATION_REF:
1311 /* If we are here, then we are dealing with cases like this:
1312 A[:];
1313 A[x:y:z];
1314 A[x:y];
1315 Replace those with just void zero node. */
1316 *tp = void_node;
1317 default:
1318 break;
1320 return NULL_TREE;
1323 /* Walks through tree node T and expands all array notations in its subtrees.
1324 The return value is the same type as T but with all array notations
1325 replaced with appropriate ARRAY_REFS with a loop around it. */
1327 tree
1328 expand_array_notation_exprs (tree t)
1330 walk_tree (&t, expand_array_notations, NULL, NULL);
1331 return t;
1334 /* This handles expression of the form "a[i:j:k]" or "a[:]" or "a[i:j]," which
1335 denotes an array notation expression. If a is a variable or a member, then
1336 we generate a ARRAY_NOTATION_REF front-end tree and return it.
1337 This tree is broken down to ARRAY_REF toward the end of parsing.
1338 ARRAY_NOTATION_REF tree holds the START_INDEX, LENGTH, STRIDE and the TYPE
1339 of ARRAY_REF. Restrictions on START_INDEX, LENGTH and STRIDE is same as that
1340 of the index field passed into ARRAY_REF. The only additional restriction
1341 is that, unlike index in ARRAY_REF, stride, length and start_index cannot
1342 contain ARRAY_NOTATIONS. */
1344 tree
1345 build_array_notation_ref (location_t loc, tree array, tree start_index,
1346 tree length, tree stride, tree type)
1348 tree array_ntn_tree = NULL_TREE;
1349 size_t stride_rank = 0, length_rank = 0, start_rank = 0;
1351 if (!INTEGRAL_TYPE_P (TREE_TYPE (start_index)))
1353 error_at (loc,
1354 "start-index of array notation triplet is not an integer");
1355 return error_mark_node;
1357 if (!INTEGRAL_TYPE_P (TREE_TYPE (length)))
1359 error_at (loc, "length of array notation triplet is not an integer");
1360 return error_mark_node;
1363 /* The stride is an optional field. */
1364 if (stride && !INTEGRAL_TYPE_P (TREE_TYPE (stride)))
1366 error_at (loc, "stride of array notation triplet is not an integer");
1367 return error_mark_node;
1369 if (!stride)
1371 if (TREE_CONSTANT (start_index) && TREE_CONSTANT (length)
1372 && tree_int_cst_lt (length, start_index))
1373 stride = build_int_cst (TREE_TYPE (start_index), -1);
1374 else
1375 stride = build_int_cst (TREE_TYPE (start_index), 1);
1378 if (!find_rank (loc, start_index, start_index, false, &start_rank))
1379 return error_mark_node;
1380 if (!find_rank (loc, length, length, false, &length_rank))
1381 return error_mark_node;
1382 if (!find_rank (loc, stride, stride, false, &stride_rank))
1383 return error_mark_node;
1385 if (start_rank != 0)
1387 error_at (loc, "rank of an array notation triplet's start-index is not "
1388 "zero");
1389 return error_mark_node;
1391 if (length_rank != 0)
1393 error_at (loc, "rank of an array notation triplet's length is not zero");
1394 return error_mark_node;
1396 if (stride_rank != 0)
1398 error_at (loc, "rank of array notation triplet's stride is not zero");
1399 return error_mark_node;
1401 array_ntn_tree = build4 (ARRAY_NOTATION_REF, NULL_TREE, NULL_TREE, NULL_TREE,
1402 NULL_TREE, NULL_TREE);
1403 ARRAY_NOTATION_ARRAY (array_ntn_tree) = array;
1404 ARRAY_NOTATION_START (array_ntn_tree) = start_index;
1405 ARRAY_NOTATION_LENGTH (array_ntn_tree) = length;
1406 ARRAY_NOTATION_STRIDE (array_ntn_tree) = stride;
1407 TREE_TYPE (array_ntn_tree) = type;
1409 return array_ntn_tree;