re PR c/57474 (FAIL: c-c++-common/cilk-plus/AN/sec_implicit2?.c -fcilkplus (internal...
[gcc.git] / gcc / c / c-array-notation.c
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 Free Software Foundation, Inc.
5 Contributed by Balaji V. Iyer <balaji.v.iyer@intel.com>,
6 Intel Corporation.
7
8 This file is part of GCC.
9
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.
14
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.
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 /* The Array Notation Transformation Technique:
25
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
31
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.
35
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:
39
40 Let's say we have an array notation in a statement like this:
41
42 A[St1:Ln:Str1] = B[St2:Ln:Str2] + <NON ARRAY_NOTATION_STMT>
43
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.
48
49 The above expression is broken into the following
50 (with the help of c_finish_loop function from c-typeck.c):
51
52 Tmp_Var = 0;
53 goto compare_label:
54 body_label:
55
56 A[St1+Tmp_Var*Str1] = B[St1+Tmp_Var*Str2] + <NON ARRAY_NOTATION_STMT>;
57 Tmp_Var++;
58
59 compare_label:
60 if (Tmp_Var < Ln)
61 goto body_label;
62 else
63 goto exit_label;
64 exit_label:
65
66 */
67
68 #include "config.h"
69 #include "system.h"
70 #include "coretypes.h"
71 #include "tree.h"
72 #include "c-tree.h"
73 #include "tree-iterator.h"
74 #include "opts.h"
75 #include "c-family/c-common.h"
76
77 static void replace_array_notations (tree *, bool, vec<tree, va_gc> *,
78 vec<tree, va_gc> *);
79 static void extract_array_notation_exprs (tree, bool, vec<tree, va_gc> **);
80
81 /* This structure holds all the scalar values and its appropriate variable
82 replacment. It is mainly used by the function that pulls all the invariant
83 parts that should be executed only once, which comes with array notation
84 expressions. */
85 struct inv_list
86 {
87 vec<tree, va_gc> *list_values;
88 vec<tree, va_gc> *replacement;
89 };
90
91 /* Returns true if there is length mismatch among expressions
92 on the same dimension and on the same side of the equal sign. The
93 expressions (or ARRAY_NOTATION lengths) are passed in through 2-D array
94 **LIST where X and Y indicate first and second dimension sizes of LIST,
95 respectively. */
96
97 static bool
98 length_mismatch_in_expr_p (location_t loc, tree **list, size_t x, size_t y)
99 {
100 size_t ii, jj;
101 tree start = NULL_TREE;
102 HOST_WIDE_INT l_start, l_node;
103 for (jj = 0; jj < y; jj++)
104 {
105 start = NULL_TREE;
106 for (ii = 0; ii < x; ii++)
107 {
108 if (!start)
109 start = list[ii][jj];
110 else if (TREE_CODE (start) == INTEGER_CST)
111 {
112 /* If start is a INTEGER, and list[ii][jj] is an integer then
113 check if they are equal. If they are not equal then return
114 true. */
115 if (TREE_CODE (list[ii][jj]) == INTEGER_CST)
116 {
117 l_node = int_cst_value (list[ii][jj]);
118 l_start = int_cst_value (start);
119 if (absu_hwi (l_start) != absu_hwi (l_node))
120 {
121 error_at (loc, "length mismatch in expression");
122 return true;
123 }
124 }
125 }
126 else
127 /* We set the start node as the current node just in case it turns
128 out to be an integer. */
129 start = list[ii][jj];
130 }
131 }
132 return false;
133 }
134
135
136 /* Given an FNDECL of type FUNCTION_DECL or ADDR_EXPR, return the corresponding
137 BUILT_IN_CILKPLUS_SEC_REDUCE_* being called. If none, return
138 BUILT_IN_NONE. */
139
140 enum built_in_function
141 is_cilkplus_reduce_builtin (tree fndecl)
142 {
143 if (TREE_CODE (fndecl) == ADDR_EXPR)
144 fndecl = TREE_OPERAND (fndecl, 0);
145
146 if (TREE_CODE (fndecl) == FUNCTION_DECL
147 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
148 switch (DECL_FUNCTION_CODE (fndecl))
149 {
150 case BUILT_IN_CILKPLUS_SEC_REDUCE_ADD:
151 case BUILT_IN_CILKPLUS_SEC_REDUCE_MUL:
152 case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_ZERO:
153 case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO:
154 case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX:
155 case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN:
156 case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND:
157 case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND:
158 case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_NONZERO:
159 case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_NONZERO:
160 case BUILT_IN_CILKPLUS_SEC_REDUCE:
161 case BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING:
162 return DECL_FUNCTION_CODE (fndecl);
163 default:
164 break;
165 }
166
167 return BUILT_IN_NONE;
168 }
169
170 /* This function will recurse into EXPR finding any
171 ARRAY_NOTATION_EXPRs and calculate the overall rank of EXPR,
172 storing it in *RANK. LOC is the location of the original expression.
173
174 ORIG_EXPR is the original expression used to display if any rank
175 mismatch errors are found.
176
177 Upon entry, *RANK must be either 0, or the rank of a parent
178 expression that must have the same rank as the one being
179 calculated. It is illegal to have multiple array notation with different
180 rank in the same expression (see examples below for clarification).
181
182 If there were any rank mismatches while calculating the rank, an
183 error will be issued, and FALSE will be returned. Otherwise, TRUE
184 is returned.
185
186 If IGNORE_BUILTIN_FN is TRUE, ignore array notation specific
187 built-in functions (__sec_reduce_*, etc).
188
189 Here are some examples of array notations and their rank:
190
191 Expression RANK
192 5 0
193 X (a variable) 0
194 *Y (a pointer) 0
195 A[5] 0
196 B[5][10] 0
197 A[:] 1
198 B[0:10] 1
199 C[0:10:2] 1
200 D[5][0:10:2] 1 (since D[5] is considered "scalar")
201 D[5][:][10] 1
202 E[:] + 5 1
203 F[:][:][:] + 5 + X 3
204 F[:][:][:] + E[:] + 5 + X RANKMISMATCH-ERROR since rank (E[:]) = 1 and
205 rank (F[:][:][:]) = 3. They must be equal
206 or have a rank of zero.
207 F[:][5][10] + E[:] * 5 + *Y 1
208
209 int func (int);
210 func (A[:]) 1
211 func (B[:][:][:][:]) 4
212
213 int func2 (int, int)
214 func2 (A[:], B[:][:][:][:]) RANKMISMATCH-ERROR -- Since Rank (A[:]) = 1
215 and Rank (B[:][:][:][:]) = 4
216
217 A[:] + func (B[:][:][:][:]) RANKMISMATCH-ERROR
218 func2 (A[:], B[:]) + func (A) 1
219
220 */
221
222 bool
223 find_rank (location_t loc, tree orig_expr, tree expr, bool ignore_builtin_fn,
224 size_t *rank)
225 {
226 tree ii_tree;
227 size_t ii = 0, current_rank = 0;
228
229 if (TREE_CODE (expr) == ARRAY_NOTATION_REF)
230 {
231 ii_tree = expr;
232 while (ii_tree)
233 {
234 if (TREE_CODE (ii_tree) == ARRAY_NOTATION_REF)
235 {
236 current_rank++;
237 ii_tree = ARRAY_NOTATION_ARRAY (ii_tree);
238 }
239 else if (TREE_CODE (ii_tree) == ARRAY_REF)
240 ii_tree = TREE_OPERAND (ii_tree, 0);
241 else if (TREE_CODE (ii_tree) == PARM_DECL
242 || TREE_CODE (ii_tree) == VAR_DECL)
243 break;
244 }
245 if (*rank == 0)
246 /* In this case, all the expressions this function has encountered thus
247 far have been scalars or expressions with zero rank. Please see
248 header comment for examples of such expression. */
249 *rank = current_rank;
250 else if (*rank != current_rank)
251 {
252 /* In this case, find rank is being recursed through a set of
253 expression of the form A <OPERATION> B, where A and B both have
254 array notations in them and the rank of A is not equal to rank of
255 B.
256 A simple example of such case is the following: X[:] + Y[:][:] */
257 *rank = current_rank;
258 return false;
259 }
260 }
261 else if (TREE_CODE (expr) == STATEMENT_LIST)
262 {
263 tree_stmt_iterator ii_tsi;
264 for (ii_tsi = tsi_start (expr); !tsi_end_p (ii_tsi);
265 tsi_next (&ii_tsi))
266 if (!find_rank (loc, orig_expr, *tsi_stmt_ptr (ii_tsi),
267 ignore_builtin_fn, rank))
268 return false;
269 }
270 else
271 {
272 if (TREE_CODE (expr) == CALL_EXPR)
273 {
274 tree func_name = CALL_EXPR_FN (expr);
275 tree prev_arg = NULL_TREE, arg;
276 call_expr_arg_iterator iter;
277 size_t prev_rank = 0;
278 if (TREE_CODE (func_name) == ADDR_EXPR)
279 if (!ignore_builtin_fn)
280 if (is_cilkplus_reduce_builtin (func_name))
281 /* If it is a built-in function, then we know it returns a
282 scalar. */
283 return true;
284 FOR_EACH_CALL_EXPR_ARG (arg, iter, expr)
285 {
286 if (!find_rank (loc, orig_expr, arg, ignore_builtin_fn, rank))
287 {
288 if (prev_arg && EXPR_HAS_LOCATION (prev_arg)
289 && prev_rank != *rank)
290 error_at (EXPR_LOCATION (prev_arg),
291 "rank mismatch between %qE and %qE", prev_arg,
292 arg);
293 else if (prev_arg && prev_rank != *rank)
294 /* Here the original expression is printed as a "heads-up"
295 to the programmer. This is because since there is no
296 location information for the offending argument, the
297 error could be in some internally generated code that is
298 not visible for the programmer. Thus, the correct fix
299 may lie in the original expression. */
300 error_at (loc, "rank mismatch in expression %qE",
301 orig_expr);
302 return false;
303 }
304 prev_arg = arg;
305 prev_rank = *rank;
306 }
307 }
308 else
309 {
310 tree prev_arg = NULL_TREE;
311 for (ii = 0; ii < TREE_CODE_LENGTH (TREE_CODE (expr)); ii++)
312 {
313 if (TREE_OPERAND (expr, ii)
314 && !find_rank (loc, orig_expr, TREE_OPERAND (expr, ii),
315 ignore_builtin_fn, rank))
316 {
317 if (prev_arg && EXPR_HAS_LOCATION (prev_arg))
318 error_at (EXPR_LOCATION (prev_arg),
319 "rank mismatch between %qE and %qE", prev_arg,
320 TREE_OPERAND (expr, ii));
321 else if (prev_arg)
322 error_at (loc, "rank mismatch in expression %qE",
323 orig_expr);
324 return false;
325 }
326 prev_arg = TREE_OPERAND (expr, ii);
327 }
328 }
329 }
330 return true;
331 }
332
333 /* Extracts all array notations in NODE and stores them in ARRAY_LIST. If
334 IGNORE_BUILTIN_FN is set, then array notations inside array notation
335 specific built-in functions are ignored. The NODE can be constants,
336 VAR_DECL, PARM_DECLS, STATEMENT_LISTS or full expressions. */
337
338 static void
339 extract_array_notation_exprs (tree node, bool ignore_builtin_fn,
340 vec<tree, va_gc> **array_list)
341 {
342 size_t ii = 0;
343 if (TREE_CODE (node) == ARRAY_NOTATION_REF)
344 {
345 vec_safe_push (*array_list, node);
346 return;
347 }
348 else if (TREE_CODE (node) == STATEMENT_LIST)
349 {
350 tree_stmt_iterator ii_tsi;
351 for (ii_tsi = tsi_start (node); !tsi_end_p (ii_tsi); tsi_next (&ii_tsi))
352 extract_array_notation_exprs (*tsi_stmt_ptr (ii_tsi),
353 ignore_builtin_fn, array_list);
354 }
355 else if (TREE_CODE (node) == CALL_EXPR)
356 {
357 tree arg;
358 call_expr_arg_iterator iter;
359 if (is_cilkplus_reduce_builtin (CALL_EXPR_FN (node)))
360 {
361 if (ignore_builtin_fn)
362 return;
363 else
364 {
365 vec_safe_push (*array_list, node);
366 return;
367 }
368 }
369 if (is_sec_implicit_index_fn (CALL_EXPR_FN (node)))
370 {
371 vec_safe_push (*array_list, node);
372 return;
373 }
374 FOR_EACH_CALL_EXPR_ARG (arg, iter, node)
375 extract_array_notation_exprs (arg, ignore_builtin_fn, array_list);
376 }
377 else
378 for (ii = 0; ii < TREE_CODE_LENGTH (TREE_CODE (node)); ii++)
379 if (TREE_OPERAND (node, ii))
380 extract_array_notation_exprs (TREE_OPERAND (node, ii),
381 ignore_builtin_fn, array_list);
382 return;
383 }
384
385 /* LIST contains all the array notations found in *ORIG and ARRAY_OPERAND
386 contains the expanded ARRAY_REF. E.g., if LIST[<some_index>] contains
387 an array_notation expression, then ARRAY_OPERAND[<some_index>] contains its
388 expansion. If *ORIG matches LIST[<some_index>] then *ORIG is set to
389 ARRAY_OPERAND[<some_index>]. This function recursively steps through
390 all the sub-trees of *ORIG, if it is larger than a single
391 ARRAY_NOTATION_REF. */
392
393 static void
394 replace_array_notations (tree *orig, bool ignore_builtin_fn,
395 vec<tree, va_gc> *list,
396 vec<tree, va_gc> *array_operand)
397 {
398 size_t ii = 0;
399 tree node = NULL_TREE, node_replacement = NULL_TREE;
400
401 if (vec_safe_length (list) == 0)
402 return;
403
404 if (TREE_CODE (*orig) == ARRAY_NOTATION_REF)
405 {
406 for (ii = 0; vec_safe_iterate (list, ii, &node); ii++)
407 if (*orig == node)
408 {
409 node_replacement = (*array_operand)[ii];
410 *orig = node_replacement;
411 }
412 }
413 else if (TREE_CODE (*orig) == STATEMENT_LIST)
414 {
415 tree_stmt_iterator ii_tsi;
416 for (ii_tsi = tsi_start (*orig); !tsi_end_p (ii_tsi); tsi_next (&ii_tsi))
417 replace_array_notations (tsi_stmt_ptr (ii_tsi), ignore_builtin_fn, list,
418 array_operand);
419 }
420 else if (TREE_CODE (*orig) == CALL_EXPR)
421 {
422 tree arg;
423 call_expr_arg_iterator iter;
424 if (is_cilkplus_reduce_builtin (CALL_EXPR_FN (*orig)))
425 {
426 if (!ignore_builtin_fn)
427 {
428 for (ii = 0; vec_safe_iterate (list, ii, &node); ii++)
429 if (*orig == node)
430 {
431 node_replacement = (*array_operand)[ii];
432 *orig = node_replacement;
433 }
434 }
435 return;
436 }
437 if (is_sec_implicit_index_fn (CALL_EXPR_FN (*orig)))
438 {
439 for (ii = 0; vec_safe_iterate (list, ii, &node); ii++)
440 if (*orig == node)
441 {
442 node_replacement = (*array_operand)[ii];
443 *orig = node_replacement;
444 }
445 return;
446 }
447 ii = 0;
448 FOR_EACH_CALL_EXPR_ARG (arg, iter, *orig)
449 {
450 replace_array_notations (&arg, ignore_builtin_fn, list,
451 array_operand);
452 CALL_EXPR_ARG (*orig, ii) = arg;
453 ii++;
454 }
455 }
456 else
457 {
458 for (ii = 0; ii < (size_t) TREE_CODE_LENGTH (TREE_CODE (*orig)); ii++)
459 if (TREE_OPERAND (*orig, ii))
460 replace_array_notations (&TREE_OPERAND (*orig, ii), ignore_builtin_fn,
461 list, array_operand);
462 }
463 return;
464 }
465
466 /* Callback for walk_tree. Find all the scalar expressions in *TP and push
467 them in DATA struct, typecasted to (void *). If *WALK_SUBTREES is set to 0
468 then do not go into the *TP's subtrees. Since this function steps through
469 all the subtrees, *TP and TP can be NULL_TREE and NULL, respectively. The
470 function returns NULL_TREE unconditionally. */
471
472 static tree
473 find_inv_trees (tree *tp, int *walk_subtrees, void *data)
474 {
475 struct inv_list *i_list = (struct inv_list *) data;
476
477 if (!tp || !*tp)
478 return NULL_TREE;
479 if (TREE_CONSTANT (*tp))
480 return NULL_TREE; /* No need to save constant to a variable. */
481 if (TREE_CODE (*tp) != COMPOUND_EXPR && !contains_array_notation_expr (*tp))
482 {
483 vec_safe_push (i_list->list_values, *tp);
484 *walk_subtrees = 0;
485 }
486 else if (TREE_CODE (*tp) == ARRAY_NOTATION_REF
487 || TREE_CODE (*tp) == ARRAY_REF
488 || TREE_CODE (*tp) == CALL_EXPR)
489 /* No need to step through the internals of array notation. */
490 *walk_subtrees = 0;
491 else
492 *walk_subtrees = 1;
493 return NULL_TREE;
494 }
495
496 /* Callback for walk_tree. Replace all the scalar expressions in *TP with the
497 appropriate replacement stored in the struct *DATA (typecasted to void*).
498 The subtrees are not touched if *WALK_SUBTREES is set to zero. */
499
500 static tree
501 replace_inv_trees (tree *tp, int *walk_subtrees, void *data)
502 {
503 size_t ii = 0;
504 tree t, r;
505 struct inv_list *i_list = (struct inv_list *) data;
506
507 if (vec_safe_length (i_list->list_values))
508 {
509 for (ii = 0; vec_safe_iterate (i_list->list_values, ii, &t); ii++)
510 if (simple_cst_equal (*tp, t) == 1)
511 {
512 vec_safe_iterate (i_list->replacement, ii, &r);
513 gcc_assert (r != NULL_TREE);
514 *tp = r;
515 *walk_subtrees = 0;
516 }
517 }
518 else
519 *walk_subtrees = 0;
520 return NULL_TREE;
521 }
522
523 /* Replaces all the scalar expressions in *NODE. Returns a STATEMENT_LIST that
524 holds the NODE along with variables that holds the results of the invariant
525 expressions. */
526
527 tree
528 replace_invariant_exprs (tree *node)
529 {
530 size_t ix = 0;
531 tree node_list = NULL_TREE;
532 tree t = NULL_TREE, new_var = NULL_TREE, new_node;
533 struct inv_list data;
534
535 data.list_values = NULL;
536 data.replacement = NULL;
537 walk_tree (node, find_inv_trees, (void *)&data, NULL);
538
539 if (vec_safe_length (data.list_values))
540 {
541 node_list = push_stmt_list ();
542 for (ix = 0; vec_safe_iterate (data.list_values, ix, &t); ix++)
543 {
544 new_var = build_decl (EXPR_LOCATION (t), VAR_DECL, NULL_TREE,
545 TREE_TYPE (t));
546 gcc_assert (new_var != NULL_TREE && new_var != error_mark_node);
547 new_node = build2 (MODIFY_EXPR, TREE_TYPE (t), new_var, t);
548 add_stmt (new_node);
549 vec_safe_push (data.replacement, new_var);
550 }
551 walk_tree (node, replace_inv_trees, (void *)&data, NULL);
552 node_list = pop_stmt_list (node_list);
553 }
554 return node_list;
555 }
556
557 /* Given a CALL_EXPR to an array notation built-in function in
558 AN_BUILTIN_FN, replace the call with the appropriate loop and
559 computation. Return the computation in *NEW_VAR.
560
561 The return value in *NEW_VAR will always be a scalar. If the
562 built-in is __sec_reduce_mutating, *NEW_VAR is set to NULL_TREE. */
563
564 static tree
565 fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var)
566 {
567 tree new_var_type = NULL_TREE, func_parm, new_expr, new_yes_expr, new_no_expr;
568 tree array_ind_value = NULL_TREE, new_no_ind, new_yes_ind, new_no_list;
569 tree new_yes_list, new_cond_expr, new_var_init = NULL_TREE;
570 tree new_exp_init = NULL_TREE;
571 vec<tree, va_gc> *array_list = NULL, *array_operand = NULL;
572 size_t list_size = 0, rank = 0, ii = 0, jj = 0;
573 int s_jj = 0;
574 tree **array_ops, *array_var, jj_tree, loop_init, array_op0;
575 tree **array_value, **array_stride, **array_length, **array_start;
576 tree *compare_expr, *expr_incr, *ind_init;
577 tree identity_value = NULL_TREE, call_fn = NULL_TREE, new_call_expr, body;
578 bool **count_down, **array_vector;
579 location_t location = UNKNOWN_LOCATION;
580 tree loop_with_init = alloc_stmt_list ();
581
582 enum built_in_function an_type =
583 is_cilkplus_reduce_builtin (CALL_EXPR_FN (an_builtin_fn));
584 if (an_type == BUILT_IN_NONE)
585 return NULL_TREE;
586
587 if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE
588 || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING)
589 {
590 call_fn = CALL_EXPR_ARG (an_builtin_fn, 2);
591 while (TREE_CODE (call_fn) == CONVERT_EXPR
592 || TREE_CODE (call_fn) == NOP_EXPR)
593 call_fn = TREE_OPERAND (call_fn, 0);
594 call_fn = TREE_OPERAND (call_fn, 0);
595
596 identity_value = CALL_EXPR_ARG (an_builtin_fn, 0);
597 while (TREE_CODE (identity_value) == CONVERT_EXPR
598 || TREE_CODE (identity_value) == NOP_EXPR)
599 identity_value = TREE_OPERAND (identity_value, 0);
600 func_parm = CALL_EXPR_ARG (an_builtin_fn, 1);
601 }
602 else
603 func_parm = CALL_EXPR_ARG (an_builtin_fn, 0);
604
605 while (TREE_CODE (func_parm) == CONVERT_EXPR
606 || TREE_CODE (func_parm) == EXCESS_PRECISION_EXPR
607 || TREE_CODE (func_parm) == NOP_EXPR)
608 func_parm = TREE_OPERAND (func_parm, 0);
609
610 location = EXPR_LOCATION (an_builtin_fn);
611
612 if (!find_rank (location, an_builtin_fn, an_builtin_fn, true, &rank))
613 return error_mark_node;
614
615 if (rank == 0)
616 return an_builtin_fn;
617 else if (rank > 1
618 && (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
619 || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND))
620 {
621 error_at (location, "__sec_reduce_min_ind or __sec_reduce_max_ind cannot"
622 " have arrays with dimension greater than 1");
623 return error_mark_node;
624 }
625
626 extract_array_notation_exprs (func_parm, true, &array_list);
627 list_size = vec_safe_length (array_list);
628 switch (an_type)
629 {
630 case BUILT_IN_CILKPLUS_SEC_REDUCE_ADD:
631 case BUILT_IN_CILKPLUS_SEC_REDUCE_MUL:
632 case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX:
633 case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN:
634 new_var_type = TREE_TYPE ((*array_list)[0]);
635 break;
636 case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_ZERO:
637 case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_NONZERO:
638 case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO:
639 case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_NONZERO:
640 new_var_type = integer_type_node;
641 break;
642 case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND:
643 case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND:
644 new_var_type = integer_type_node;
645 break;
646 case BUILT_IN_CILKPLUS_SEC_REDUCE:
647 if (call_fn && identity_value)
648 new_var_type = TREE_TYPE ((*array_list)[0]);
649 break;
650 case BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING:
651 new_var_type = NULL_TREE;
652 break;
653 default:
654 gcc_unreachable ();
655 }
656
657 array_ops = XNEWVEC (tree *, list_size);
658 for (ii = 0; ii < list_size; ii++)
659 array_ops[ii] = XNEWVEC (tree, rank);
660
661 array_vector = XNEWVEC (bool *, list_size);
662 for (ii = 0; ii < list_size; ii++)
663 array_vector[ii] = XNEWVEC (bool, rank);
664
665 array_value = XNEWVEC (tree *, list_size);
666 array_stride = XNEWVEC (tree *, list_size);
667 array_length = XNEWVEC (tree *, list_size);
668 array_start = XNEWVEC (tree *, list_size);
669
670 for (ii = 0; ii < list_size; ii++)
671 {
672 array_value[ii] = XNEWVEC (tree, rank);
673 array_stride[ii] = XNEWVEC (tree, rank);
674 array_length[ii] = XNEWVEC (tree, rank);
675 array_start[ii] = XNEWVEC (tree, rank);
676 }
677
678 compare_expr = XNEWVEC (tree, rank);
679 expr_incr = XNEWVEC (tree, rank);
680 ind_init = XNEWVEC (tree, rank);
681
682 count_down = XNEWVEC (bool *, list_size);
683 for (ii = 0; ii < list_size; ii++)
684 count_down[ii] = XNEWVEC (bool, rank);
685
686 array_var = XNEWVEC (tree, rank);
687
688 for (ii = 0; ii < list_size; ii++)
689 {
690 jj = 0;
691 for (jj_tree = (*array_list)[ii];
692 jj_tree && TREE_CODE (jj_tree) == ARRAY_NOTATION_REF;
693 jj_tree = ARRAY_NOTATION_ARRAY (jj_tree))
694 {
695 array_ops[ii][jj] = jj_tree;
696 jj++;
697 }
698 }
699
700 for (ii = 0; ii < list_size; ii++)
701 {
702 tree array_node = (*array_list)[ii];
703 if (TREE_CODE (array_node) == ARRAY_NOTATION_REF)
704 {
705 for (jj = 0; jj < rank; jj++)
706 {
707 if (TREE_CODE (array_ops[ii][jj]) == ARRAY_NOTATION_REF)
708 {
709 array_value[ii][jj] =
710 ARRAY_NOTATION_ARRAY (array_ops[ii][jj]);
711 array_start[ii][jj] =
712 ARRAY_NOTATION_START (array_ops[ii][jj]);
713 array_length[ii][jj] =
714 fold_build1 (CONVERT_EXPR, integer_type_node,
715 ARRAY_NOTATION_LENGTH (array_ops[ii][jj]));
716 array_stride[ii][jj] =
717 fold_build1 (CONVERT_EXPR, integer_type_node,
718 ARRAY_NOTATION_STRIDE (array_ops[ii][jj]));
719 array_vector[ii][jj] = true;
720
721 if (!TREE_CONSTANT (array_length[ii][jj]))
722 count_down[ii][jj] = false;
723 else if (tree_int_cst_lt
724 (array_length[ii][jj],
725 build_int_cst (TREE_TYPE (array_length[ii][jj]),
726 0)))
727 count_down[ii][jj] = true;
728 else
729 count_down[ii][jj] = false;
730 }
731 else
732 array_vector[ii][jj] = false;
733 }
734 }
735 }
736
737 loop_init = alloc_stmt_list ();
738
739 for (ii = 0; ii < rank; ii++)
740 {
741 array_var[ii] = build_decl (location, VAR_DECL, NULL_TREE,
742 integer_type_node);
743 ind_init[ii] =
744 build_modify_expr (location, array_var[ii],
745 TREE_TYPE (array_var[ii]), NOP_EXPR,
746 location,
747 build_int_cst (TREE_TYPE (array_var[ii]), 0),
748 TREE_TYPE (array_var[ii]));
749 }
750 for (ii = 0; ii < list_size; ii++)
751 {
752 if (array_vector[ii][0])
753 {
754 tree array_opr_node = array_value[ii][rank - 1];
755 for (s_jj = rank - 1; s_jj >= 0; s_jj--)
756 {
757 if (count_down[ii][s_jj])
758 {
759 /* Array[start_index - (induction_var * stride)] */
760 array_opr_node = build_array_ref
761 (location, array_opr_node,
762 build2 (MINUS_EXPR, TREE_TYPE (array_var[s_jj]),
763 array_start[ii][s_jj],
764 build2 (MULT_EXPR, TREE_TYPE (array_var[s_jj]),
765 array_var[s_jj], array_stride[ii][s_jj])));
766 }
767 else
768 {
769 /* Array[start_index + (induction_var * stride)] */
770 array_opr_node = build_array_ref
771 (location, array_opr_node,
772 build2 (PLUS_EXPR, TREE_TYPE (array_var[s_jj]),
773 array_start[ii][s_jj],
774 build2 (MULT_EXPR, TREE_TYPE (array_var[s_jj]),
775 array_var[s_jj], array_stride[ii][s_jj])));
776 }
777 }
778 vec_safe_push (array_operand, array_opr_node);
779 }
780 else
781 /* This is just a dummy node to make sure the list sizes for both
782 array list and array operand list are the same. */
783 vec_safe_push (array_operand, integer_one_node);
784 }
785 replace_array_notations (&func_parm, true, array_list, array_operand);
786 for (ii = 0; ii < rank; ii++)
787 expr_incr[ii] =
788 build2 (MODIFY_EXPR, void_type_node, array_var[ii],
789 build2 (PLUS_EXPR, TREE_TYPE (array_var[ii]), array_var[ii],
790 build_int_cst (TREE_TYPE (array_var[ii]), 1)));
791 for (jj = 0; jj < rank; jj++)
792 {
793 if (rank && expr_incr[jj])
794 {
795 if (count_down[0][jj])
796 compare_expr[jj] =
797 build2 (LT_EXPR, boolean_type_node, array_var[jj],
798 build2 (MULT_EXPR, TREE_TYPE (array_var[jj]),
799 array_length[0][jj],
800 build_int_cst (TREE_TYPE (array_var[jj]), -1)));
801 else
802 compare_expr[jj] = build2 (LT_EXPR, boolean_type_node,
803 array_var[jj], array_length[0][jj]);
804 }
805 }
806
807 if (an_type != BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING)
808 {
809 *new_var = build_decl (location, VAR_DECL, NULL_TREE, new_var_type);
810 gcc_assert (*new_var && *new_var != error_mark_node);
811 }
812 else
813 *new_var = NULL_TREE;
814
815 if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
816 || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND)
817 array_ind_value = build_decl (location, VAR_DECL, NULL_TREE,
818 TREE_TYPE (func_parm));
819 array_op0 = (*array_operand)[0];
820 switch (an_type)
821 {
822 case BUILT_IN_CILKPLUS_SEC_REDUCE_ADD:
823 new_var_init = build_modify_expr
824 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
825 location, build_zero_cst (new_var_type), new_var_type);
826 new_expr = build_modify_expr
827 (location, *new_var, TREE_TYPE (*new_var), PLUS_EXPR,
828 location, func_parm, TREE_TYPE (func_parm));
829 break;
830 case BUILT_IN_CILKPLUS_SEC_REDUCE_MUL:
831 new_var_init = build_modify_expr
832 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
833 location, build_one_cst (new_var_type), new_var_type);
834 new_expr = build_modify_expr
835 (location, *new_var, TREE_TYPE (*new_var), MULT_EXPR,
836 location, func_parm, TREE_TYPE (func_parm));
837 break;
838 case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_ZERO:
839 new_var_init = build_modify_expr
840 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
841 location, build_one_cst (new_var_type), new_var_type);
842 /* Initially you assume everything is zero, now if we find a case where
843 it is NOT true, then we set the result to false. Otherwise
844 we just keep the previous value. */
845 new_yes_expr = build_modify_expr
846 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
847 location, build_zero_cst (TREE_TYPE (*new_var)),
848 TREE_TYPE (*new_var));
849 new_no_expr = build_modify_expr
850 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
851 location, *new_var, TREE_TYPE (*new_var));
852 new_cond_expr = build2 (NE_EXPR, TREE_TYPE (func_parm), func_parm,
853 build_zero_cst (TREE_TYPE (func_parm)));
854 new_expr = build_conditional_expr
855 (location, new_cond_expr, false, new_yes_expr,
856 TREE_TYPE (new_yes_expr), new_no_expr, TREE_TYPE (new_no_expr));
857 break;
858 case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_NONZERO:
859 new_var_init = build_modify_expr
860 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
861 location, build_one_cst (new_var_type), new_var_type);
862 /* Initially you assume everything is non-zero, now if we find a case
863 where it is NOT true, then we set the result to false. Otherwise
864 we just keep the previous value. */
865 new_yes_expr = build_modify_expr
866 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
867 location, build_zero_cst (TREE_TYPE (*new_var)),
868 TREE_TYPE (*new_var));
869 new_no_expr = build_modify_expr
870 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
871 location, *new_var, TREE_TYPE (*new_var));
872 new_cond_expr = build2 (EQ_EXPR, TREE_TYPE (func_parm), func_parm,
873 build_zero_cst (TREE_TYPE (func_parm)));
874 new_expr = build_conditional_expr
875 (location, new_cond_expr, false, new_yes_expr,
876 TREE_TYPE (new_yes_expr), new_no_expr, TREE_TYPE (new_no_expr));
877 break;
878 case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO:
879 new_var_init = build_modify_expr
880 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
881 location, build_zero_cst (new_var_type), new_var_type);
882 /* Initially we assume there are NO zeros in the list. When we find
883 a non-zero, we keep the previous value. If we find a zero, we
884 set the value to true. */
885 new_yes_expr = build_modify_expr
886 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
887 location, build_one_cst (new_var_type), new_var_type);
888 new_no_expr = build_modify_expr
889 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
890 location, *new_var, TREE_TYPE (*new_var));
891 new_cond_expr = build2 (EQ_EXPR, TREE_TYPE (func_parm), func_parm,
892 build_zero_cst (TREE_TYPE (func_parm)));
893 new_expr = build_conditional_expr
894 (location, new_cond_expr, false, new_yes_expr,
895 TREE_TYPE (new_yes_expr), new_no_expr, TREE_TYPE (new_no_expr));
896 break;
897 case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_NONZERO:
898 new_var_init = build_modify_expr
899 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
900 location, build_zero_cst (new_var_type), new_var_type);
901 /* Initially we assume there are NO non-zeros in the list. When we find
902 a zero, we keep the previous value. If we find a non-zero, we set
903 the value to true. */
904 new_yes_expr = build_modify_expr
905 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
906 location, build_one_cst (new_var_type), new_var_type);
907 new_no_expr = build_modify_expr
908 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
909 location, *new_var, TREE_TYPE (*new_var));
910 new_cond_expr = build2 (NE_EXPR, TREE_TYPE (func_parm), func_parm,
911 build_zero_cst (TREE_TYPE (func_parm)));
912 new_expr = build_conditional_expr
913 (location, new_cond_expr, false, new_yes_expr,
914 TREE_TYPE (new_yes_expr), new_no_expr, TREE_TYPE (new_no_expr));
915 break;
916 case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX:
917 if (TYPE_MIN_VALUE (new_var_type))
918 new_var_init = build_modify_expr
919 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
920 location, TYPE_MIN_VALUE (new_var_type), new_var_type);
921 else
922 new_var_init = build_modify_expr
923 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
924 location, func_parm, new_var_type);
925 new_no_expr = build_modify_expr
926 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
927 location, *new_var, TREE_TYPE (*new_var));
928 new_yes_expr = build_modify_expr
929 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
930 location, func_parm, TREE_TYPE (*new_var));
931 new_expr = build_conditional_expr
932 (location,
933 build2 (LT_EXPR, TREE_TYPE (*new_var), *new_var, func_parm), false,
934 new_yes_expr, TREE_TYPE (*new_var), new_no_expr, TREE_TYPE (*new_var));
935 break;
936 case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN:
937 if (TYPE_MAX_VALUE (new_var_type))
938 new_var_init = build_modify_expr
939 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
940 location, TYPE_MAX_VALUE (new_var_type), new_var_type);
941 else
942 new_var_init = build_modify_expr
943 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
944 location, func_parm, new_var_type);
945 new_no_expr = build_modify_expr
946 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
947 location, *new_var, TREE_TYPE (*new_var));
948 new_yes_expr = build_modify_expr
949 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
950 location, func_parm, TREE_TYPE (*new_var));
951 new_expr = build_conditional_expr
952 (location,
953 build2 (GT_EXPR, TREE_TYPE (*new_var), *new_var, func_parm), false,
954 new_yes_expr, TREE_TYPE (*new_var), new_no_expr, TREE_TYPE (*new_var));
955 break;
956 case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND:
957 new_var_init = build_modify_expr
958 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
959 location, build_zero_cst (new_var_type), new_var_type);
960 new_exp_init = build_modify_expr
961 (location, array_ind_value, TREE_TYPE (array_ind_value),
962 NOP_EXPR, location, func_parm, TREE_TYPE (func_parm));
963 new_no_ind = build_modify_expr
964 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
965 location, *new_var, TREE_TYPE (*new_var));
966 new_no_expr = build_modify_expr
967 (location, array_ind_value, TREE_TYPE (array_ind_value),
968 NOP_EXPR,
969 location, array_ind_value, TREE_TYPE (array_ind_value));
970 if (list_size > 1)
971 {
972 new_yes_ind = build_modify_expr
973 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
974 location, array_var[0], TREE_TYPE (array_var[0]));
975 new_yes_expr = build_modify_expr
976 (location, array_ind_value, TREE_TYPE (array_ind_value),
977 NOP_EXPR,
978 location, func_parm, TREE_TYPE ((*array_operand)[0]));
979 }
980 else
981 {
982 new_yes_ind = build_modify_expr
983 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
984 location, TREE_OPERAND (array_op0, 1),
985 TREE_TYPE (TREE_OPERAND (array_op0, 1)));
986 new_yes_expr = build_modify_expr
987 (location, array_ind_value, TREE_TYPE (array_ind_value),
988 NOP_EXPR,
989 location, func_parm, TREE_OPERAND (array_op0, 1));
990 }
991 new_yes_list = alloc_stmt_list ();
992 append_to_statement_list (new_yes_ind, &new_yes_list);
993 append_to_statement_list (new_yes_expr, &new_yes_list);
994
995 new_no_list = alloc_stmt_list ();
996 append_to_statement_list (new_no_ind, &new_no_list);
997 append_to_statement_list (new_no_expr, &new_no_list);
998
999 new_expr = build_conditional_expr
1000 (location,
1001 build2 (LE_EXPR, TREE_TYPE (array_ind_value), array_ind_value,
1002 func_parm),
1003 false,
1004 new_yes_list, TREE_TYPE (*new_var), new_no_list, TREE_TYPE (*new_var));
1005 break;
1006 case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND:
1007 new_var_init = build_modify_expr
1008 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
1009 location, build_zero_cst (new_var_type), new_var_type);
1010 new_exp_init = build_modify_expr
1011 (location, array_ind_value, TREE_TYPE (array_ind_value),
1012 NOP_EXPR, location, func_parm, TREE_TYPE (func_parm));
1013 new_no_ind = build_modify_expr
1014 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
1015 location, *new_var, TREE_TYPE (*new_var));
1016 new_no_expr = build_modify_expr
1017 (location, array_ind_value, TREE_TYPE (array_ind_value),
1018 NOP_EXPR,
1019 location, array_ind_value, TREE_TYPE (array_ind_value));
1020 if (list_size > 1)
1021 {
1022 new_yes_ind = build_modify_expr
1023 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
1024 location, array_var[0], TREE_TYPE (array_var[0]));
1025 new_yes_expr = build_modify_expr
1026 (location, array_ind_value, TREE_TYPE (array_ind_value),
1027 NOP_EXPR,
1028 location, func_parm, TREE_TYPE (array_op0));
1029 }
1030 else
1031 {
1032 new_yes_ind = build_modify_expr
1033 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
1034 location, TREE_OPERAND (array_op0, 1),
1035 TREE_TYPE (TREE_OPERAND (array_op0, 1)));
1036 new_yes_expr = build_modify_expr
1037 (location, array_ind_value, TREE_TYPE (array_ind_value),
1038 NOP_EXPR,
1039 location, func_parm, TREE_OPERAND (array_op0, 1));
1040 }
1041 new_yes_list = alloc_stmt_list ();
1042 append_to_statement_list (new_yes_ind, &new_yes_list);
1043 append_to_statement_list (new_yes_expr, &new_yes_list);
1044
1045 new_no_list = alloc_stmt_list ();
1046 append_to_statement_list (new_no_ind, &new_no_list);
1047 append_to_statement_list (new_no_expr, &new_no_list);
1048
1049 new_expr = build_conditional_expr
1050 (location,
1051 build2 (GE_EXPR, TREE_TYPE (array_ind_value), array_ind_value,
1052 func_parm),
1053 false,
1054 new_yes_list, TREE_TYPE (*new_var), new_no_list, TREE_TYPE (*new_var));
1055 break;
1056 case BUILT_IN_CILKPLUS_SEC_REDUCE:
1057 new_var_init = build_modify_expr
1058 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
1059 location, identity_value, new_var_type);
1060 new_call_expr = build_call_expr (call_fn, 2, *new_var, func_parm);
1061 new_expr = build_modify_expr
1062 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
1063 location, new_call_expr, TREE_TYPE (*new_var));
1064 break;
1065 case BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING:
1066 new_expr = build_call_expr (call_fn, 2, identity_value, func_parm);
1067 break;
1068 default:
1069 gcc_unreachable ();
1070 break;
1071 }
1072
1073 for (ii = 0; ii < rank; ii++)
1074 append_to_statement_list (ind_init [ii], &loop_init);
1075
1076 if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
1077 || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND)
1078 append_to_statement_list (new_exp_init, &loop_init);
1079 if (an_type != BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING)
1080 append_to_statement_list (new_var_init, &loop_init);
1081
1082 append_to_statement_list_force (loop_init, &loop_with_init);
1083 body = new_expr;
1084 for (ii = 0; ii < rank; ii++)
1085 {
1086 tree new_loop = push_stmt_list ();
1087 c_finish_loop (location, compare_expr[ii], expr_incr[ii], body, NULL_TREE,
1088 NULL_TREE, true);
1089 body = pop_stmt_list (new_loop);
1090 }
1091 append_to_statement_list_force (body, &loop_with_init);
1092
1093 XDELETEVEC (compare_expr);
1094 XDELETEVEC (expr_incr);
1095 XDELETEVEC (ind_init);
1096 XDELETEVEC (array_var);
1097 for (ii = 0; ii < list_size; ii++)
1098 {
1099 XDELETEVEC (count_down[ii]);
1100 XDELETEVEC (array_value[ii]);
1101 XDELETEVEC (array_stride[ii]);
1102 XDELETEVEC (array_length[ii]);
1103 XDELETEVEC (array_start[ii]);
1104 XDELETEVEC (array_ops[ii]);
1105 XDELETEVEC (array_vector[ii]);
1106 }
1107 XDELETEVEC (count_down);
1108 XDELETEVEC (array_value);
1109 XDELETEVEC (array_stride);
1110 XDELETEVEC (array_length);
1111 XDELETEVEC (array_start);
1112 XDELETEVEC (array_ops);
1113 XDELETEVEC (array_vector);
1114
1115 return loop_with_init;
1116 }
1117
1118 /* Returns a loop with ARRAY_REF inside it with an appropriate modify expr.
1119 The LHS and/or RHS will be array notation expressions that have a MODIFYCODE
1120 Their locations are specified by LHS_LOC, RHS_LOC. The location of the
1121 modify expression is location. The original type of LHS and RHS are passed
1122 in LHS_ORIGTYPE and RHS_ORIGTYPE. */
1123
1124 tree
1125 build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype,
1126 enum tree_code modifycode, location_t rhs_loc,
1127 tree rhs, tree rhs_origtype)
1128 {
1129 bool **lhs_vector = NULL, **rhs_vector = NULL, found_builtin_fn = false;
1130 tree **lhs_array = NULL, **rhs_array = NULL;
1131 tree array_expr_lhs = NULL_TREE, array_expr_rhs = NULL_TREE;
1132 tree array_expr = NULL_TREE;
1133 tree **lhs_value = NULL, **rhs_value = NULL;
1134 tree **lhs_stride = NULL, **lhs_length = NULL, **lhs_start = NULL;
1135 tree **rhs_stride = NULL, **rhs_length = NULL, **rhs_start = NULL;
1136 tree an_init = NULL_TREE, *lhs_var = NULL, *rhs_var = NULL;
1137 tree *cond_expr = NULL;
1138 tree body, loop_with_init = alloc_stmt_list();
1139 tree scalar_mods = NULL_TREE;
1140 tree *lhs_expr_incr = NULL, *rhs_expr_incr = NULL;
1141 tree *lhs_ind_init = NULL, *rhs_ind_init = NULL;
1142 bool **lhs_count_down = NULL, **rhs_count_down = NULL;
1143 tree *lhs_compare = NULL, *rhs_compare = NULL;
1144 vec<tree, va_gc> *rhs_array_operand = NULL, *lhs_array_operand = NULL;
1145 size_t lhs_rank = 0, rhs_rank = 0;
1146 size_t ii = 0, jj = 0;
1147 int s_jj = 0;
1148 tree ii_tree = NULL_TREE, new_modify_expr;
1149 vec<tree, va_gc> *lhs_list = NULL, *rhs_list = NULL;
1150 tree new_var = NULL_TREE, builtin_loop = NULL_TREE;
1151 tree begin_var, lngth_var, strde_var;
1152 size_t rhs_list_size = 0, lhs_list_size = 0;
1153
1154 /* If either of this is true, an error message must have been send out
1155 already. Not necessary to send out multiple error messages. */
1156 if (lhs == error_mark_node || rhs == error_mark_node)
1157 return error_mark_node;
1158
1159 if (!find_rank (location, rhs, rhs, false, &rhs_rank))
1160 return error_mark_node;
1161
1162 extract_array_notation_exprs (rhs, false, &rhs_list);
1163 rhs_list_size = vec_safe_length (rhs_list);
1164 an_init = push_stmt_list ();
1165 if (rhs_rank)
1166 {
1167 scalar_mods = replace_invariant_exprs (&rhs);
1168 if (scalar_mods)
1169 add_stmt (scalar_mods);
1170 }
1171 for (ii = 0; ii < rhs_list_size; ii++)
1172 {
1173 tree rhs_node = (*rhs_list)[ii];
1174 if (TREE_CODE (rhs_node) == CALL_EXPR)
1175 {
1176 builtin_loop = fix_builtin_array_notation_fn (rhs_node, &new_var);
1177 if (builtin_loop == error_mark_node)
1178 {
1179 pop_stmt_list (an_init);
1180 return error_mark_node;
1181 }
1182 else if (builtin_loop)
1183 {
1184 add_stmt (builtin_loop);
1185 found_builtin_fn = true;
1186 if (new_var)
1187 {
1188 vec<tree, va_gc> *rhs_sub_list = NULL, *new_var_list = NULL;
1189 vec_safe_push (rhs_sub_list, rhs_node);
1190 vec_safe_push (new_var_list, new_var);
1191 replace_array_notations (&rhs, false, rhs_sub_list,
1192 new_var_list);
1193 }
1194 }
1195 }
1196 }
1197
1198 lhs_rank = 0;
1199 rhs_rank = 0;
1200 if (!find_rank (location, lhs, lhs, true, &lhs_rank))
1201 {
1202 pop_stmt_list (an_init);
1203 return error_mark_node;
1204 }
1205
1206 if (!find_rank (location, rhs, rhs, true, &rhs_rank))
1207 {
1208 pop_stmt_list (an_init);
1209 return error_mark_node;
1210 }
1211
1212 if (lhs_rank == 0 && rhs_rank == 0)
1213 {
1214 if (found_builtin_fn)
1215 {
1216 new_modify_expr = build_modify_expr (location, lhs, lhs_origtype,
1217 modifycode, rhs_loc, rhs,
1218 rhs_origtype);
1219 add_stmt (new_modify_expr);
1220 pop_stmt_list (an_init);
1221 return an_init;
1222 }
1223 else
1224 {
1225 pop_stmt_list (an_init);
1226 return NULL_TREE;
1227 }
1228 }
1229 rhs_list_size = 0;
1230 rhs_list = NULL;
1231 extract_array_notation_exprs (rhs, true, &rhs_list);
1232 extract_array_notation_exprs (lhs, true, &lhs_list);
1233 rhs_list_size = vec_safe_length (rhs_list);
1234 lhs_list_size = vec_safe_length (lhs_list);
1235
1236 if (lhs_rank == 0 && rhs_rank != 0 && TREE_CODE (rhs) != CALL_EXPR)
1237 {
1238 tree rhs_base = rhs;
1239 if (TREE_CODE (rhs_base) == ARRAY_NOTATION_REF)
1240 {
1241 for (ii = 0; ii < (size_t) rhs_rank; ii++)
1242 rhs_base = ARRAY_NOTATION_ARRAY (rhs);
1243
1244 error_at (location, "%qE cannot be scalar when %qE is not", lhs,
1245 rhs_base);
1246 return error_mark_node;
1247 }
1248 else
1249 {
1250 error_at (location, "%qE cannot be scalar when %qE is not", lhs,
1251 rhs_base);
1252 return error_mark_node;
1253 }
1254 }
1255 if (lhs_rank != 0 && rhs_rank != 0 && lhs_rank != rhs_rank)
1256 {
1257 tree lhs_base = lhs;
1258 tree rhs_base = rhs;
1259
1260 for (ii = 0; ii < lhs_rank; ii++)
1261 lhs_base = ARRAY_NOTATION_ARRAY (lhs_base);
1262
1263 while (rhs_base && TREE_CODE (rhs_base) != ARRAY_NOTATION_REF)
1264 rhs_base = TREE_OPERAND (rhs_base, 0);
1265 for (ii = 0; ii < rhs_rank; ii++)
1266 rhs_base = ARRAY_NOTATION_ARRAY (rhs_base);
1267
1268 error_at (location, "rank mismatch between %qE and %qE", lhs, rhs);
1269 pop_stmt_list (an_init);
1270 return error_mark_node;
1271 }
1272
1273 /* Here we assign the array notation components to variable so that we can
1274 satisfy the exec once rule. */
1275 for (ii = 0; ii < lhs_list_size; ii++)
1276 {
1277 tree array_node = (*lhs_list)[ii];
1278 tree array_begin = ARRAY_NOTATION_START (array_node);
1279 tree array_lngth = ARRAY_NOTATION_LENGTH (array_node);
1280 tree array_strde = ARRAY_NOTATION_STRIDE (array_node);
1281
1282 if (TREE_CODE (array_begin) != INTEGER_CST)
1283 {
1284 begin_var = build_decl (location, VAR_DECL, NULL_TREE,
1285 integer_type_node);
1286 add_stmt (build_modify_expr (location, begin_var,
1287 TREE_TYPE (begin_var),
1288 NOP_EXPR, location, array_begin,
1289 TREE_TYPE (array_begin)));
1290 ARRAY_NOTATION_START (array_node) = begin_var;
1291 }
1292
1293 if (TREE_CODE (array_lngth) != INTEGER_CST)
1294 {
1295 lngth_var = build_decl (location, VAR_DECL, NULL_TREE,
1296 integer_type_node);
1297 add_stmt (build_modify_expr (location, lngth_var,
1298 TREE_TYPE (lngth_var),
1299 NOP_EXPR, location, array_lngth,
1300 TREE_TYPE (array_lngth)));
1301 ARRAY_NOTATION_LENGTH (array_node) = lngth_var;
1302 }
1303 if (TREE_CODE (array_strde) != INTEGER_CST)
1304 {
1305 strde_var = build_decl (location, VAR_DECL, NULL_TREE,
1306 integer_type_node);
1307
1308 add_stmt (build_modify_expr (location, strde_var,
1309 TREE_TYPE (strde_var),
1310 NOP_EXPR, location, array_strde,
1311 TREE_TYPE (array_strde)));
1312 ARRAY_NOTATION_STRIDE (array_node) = strde_var;
1313 }
1314 }
1315 for (ii = 0; ii < rhs_list_size; ii++)
1316 {
1317 tree array_node = (*rhs_list)[ii];
1318 if (array_node && TREE_CODE (array_node) == ARRAY_NOTATION_REF)
1319 {
1320 tree array_begin = ARRAY_NOTATION_START (array_node);
1321 tree array_lngth = ARRAY_NOTATION_LENGTH (array_node);
1322 tree array_strde = ARRAY_NOTATION_STRIDE (array_node);
1323
1324 if (TREE_CODE (array_begin) != INTEGER_CST)
1325 {
1326 begin_var = build_decl (location, VAR_DECL, NULL_TREE,
1327 integer_type_node);
1328 add_stmt (build_modify_expr (location, begin_var,
1329 TREE_TYPE (begin_var),
1330 NOP_EXPR, location, array_begin,
1331 TREE_TYPE (array_begin)));
1332 ARRAY_NOTATION_START (array_node) = begin_var;
1333 }
1334 if (TREE_CODE (array_lngth) != INTEGER_CST)
1335 {
1336 lngth_var = build_decl (location, VAR_DECL, NULL_TREE,
1337 integer_type_node);
1338 add_stmt (build_modify_expr (location, lngth_var,
1339 TREE_TYPE (lngth_var),
1340 NOP_EXPR, location, array_lngth,
1341 TREE_TYPE (array_lngth)));
1342 ARRAY_NOTATION_LENGTH (array_node) = lngth_var;
1343 }
1344 if (TREE_CODE (array_strde) != INTEGER_CST)
1345 {
1346 strde_var = build_decl (location, VAR_DECL, NULL_TREE,
1347 integer_type_node);
1348
1349 add_stmt (build_modify_expr (location, strde_var,
1350 TREE_TYPE (strde_var),
1351 NOP_EXPR, location, array_strde,
1352 TREE_TYPE (array_strde)));
1353 ARRAY_NOTATION_STRIDE (array_node) = strde_var;
1354 }
1355 }
1356 }
1357
1358 lhs_vector = XNEWVEC (bool *, lhs_list_size);
1359 for (ii = 0; ii < lhs_list_size; ii++)
1360 lhs_vector[ii] = XNEWVEC (bool, lhs_rank);
1361
1362 rhs_vector = XNEWVEC (bool *, rhs_list_size);
1363 for (ii = 0; ii < rhs_list_size; ii++)
1364 rhs_vector[ii] = XNEWVEC (bool, rhs_rank);
1365
1366 lhs_array = XNEWVEC (tree *, lhs_list_size);
1367 for (ii = 0; ii < lhs_list_size; ii++)
1368 lhs_array[ii] = XNEWVEC (tree, lhs_rank);
1369
1370 rhs_array = XNEWVEC (tree *, rhs_list_size);
1371 for (ii = 0; ii < rhs_list_size; ii++)
1372 rhs_array[ii] = XNEWVEC (tree, rhs_rank);
1373
1374 lhs_value = XNEWVEC (tree *, lhs_list_size);
1375 for (ii = 0; ii < lhs_list_size; ii++)
1376 lhs_value[ii] = XNEWVEC (tree, lhs_rank);
1377
1378 rhs_value = XNEWVEC (tree *, rhs_list_size);
1379 for (ii = 0; ii < rhs_list_size; ii++)
1380 rhs_value[ii] = XNEWVEC (tree, rhs_rank);
1381
1382 lhs_stride = XNEWVEC (tree *, lhs_list_size);
1383 for (ii = 0; ii < lhs_list_size; ii++)
1384 lhs_stride[ii] = XNEWVEC (tree, lhs_rank);
1385
1386 rhs_stride = XNEWVEC (tree *, rhs_list_size);
1387 for (ii = 0; ii < rhs_list_size; ii++)
1388 rhs_stride[ii] = XNEWVEC (tree, rhs_rank);
1389
1390 lhs_length = XNEWVEC (tree *, lhs_list_size);
1391 for (ii = 0; ii < lhs_list_size; ii++)
1392 lhs_length[ii] = XNEWVEC (tree, lhs_rank);
1393
1394 rhs_length = XNEWVEC (tree *, rhs_list_size);
1395 for (ii = 0; ii < rhs_list_size; ii++)
1396 rhs_length[ii] = XNEWVEC (tree, rhs_rank);
1397
1398 lhs_start = XNEWVEC (tree *, lhs_list_size);
1399 for (ii = 0; ii < lhs_list_size; ii++)
1400 lhs_start[ii] = XNEWVEC (tree, lhs_rank);
1401
1402 rhs_start = XNEWVEC (tree *, rhs_list_size);
1403 for (ii = 0; ii < rhs_list_size; ii++)
1404 rhs_start[ii] = XNEWVEC (tree, rhs_rank);
1405
1406 lhs_var = XNEWVEC (tree, lhs_rank);
1407 rhs_var = XNEWVEC (tree, rhs_rank);
1408 cond_expr = XNEWVEC (tree, MAX (lhs_rank, rhs_rank));
1409
1410 lhs_expr_incr = XNEWVEC (tree, lhs_rank);
1411 rhs_expr_incr =XNEWVEC (tree, rhs_rank);
1412
1413 lhs_ind_init = XNEWVEC (tree, lhs_rank);
1414 rhs_ind_init = XNEWVEC (tree, rhs_rank);
1415
1416 lhs_count_down = XNEWVEC (bool *, lhs_list_size);
1417 for (ii = 0; ii < lhs_list_size; ii++)
1418 lhs_count_down[ii] = XNEWVEC (bool, lhs_rank);
1419
1420 rhs_count_down = XNEWVEC (bool *, rhs_list_size);
1421 for (ii = 0; ii < rhs_list_size; ii++)
1422 rhs_count_down[ii] = XNEWVEC (bool, rhs_rank);
1423
1424 lhs_compare = XNEWVEC (tree, lhs_rank);
1425 rhs_compare = XNEWVEC (tree, rhs_rank);
1426
1427 if (lhs_rank)
1428 {
1429 for (ii = 0; ii < lhs_list_size; ii++)
1430 {
1431 jj = 0;
1432 ii_tree = (*lhs_list)[ii];
1433 while (ii_tree)
1434 {
1435 if (TREE_CODE (ii_tree) == ARRAY_NOTATION_REF)
1436 {
1437 lhs_array[ii][jj] = ii_tree;
1438 jj++;
1439 ii_tree = ARRAY_NOTATION_ARRAY (ii_tree);
1440 }
1441 else if (TREE_CODE (ii_tree) == ARRAY_REF)
1442 ii_tree = TREE_OPERAND (ii_tree, 0);
1443 else if (TREE_CODE (ii_tree) == VAR_DECL
1444 || TREE_CODE (ii_tree) == PARM_DECL)
1445 break;
1446 }
1447 }
1448 }
1449 else
1450 lhs_array[0][0] = NULL_TREE;
1451
1452 if (rhs_rank)
1453 {
1454 for (ii = 0; ii < rhs_list_size; ii++)
1455 {
1456 jj = 0;
1457 ii_tree = (*rhs_list)[ii];
1458 while (ii_tree)
1459 {
1460 if (TREE_CODE (ii_tree) == ARRAY_NOTATION_REF)
1461 {
1462 rhs_array[ii][jj] = ii_tree;
1463 jj++;
1464 ii_tree = ARRAY_NOTATION_ARRAY (ii_tree);
1465 }
1466 else if (TREE_CODE (ii_tree) == ARRAY_REF)
1467 ii_tree = TREE_OPERAND (ii_tree, 0);
1468 else if (TREE_CODE (ii_tree) == VAR_DECL
1469 || TREE_CODE (ii_tree) == PARM_DECL
1470 || TREE_CODE (ii_tree) == CALL_EXPR)
1471 break;
1472 }
1473 }
1474 }
1475
1476 for (ii = 0; ii < lhs_list_size; ii++)
1477 {
1478 tree lhs_node = (*lhs_list)[ii];
1479 if (TREE_CODE (lhs_node) == ARRAY_NOTATION_REF)
1480 {
1481 for (jj = 0; jj < lhs_rank; jj++)
1482 {
1483 if (TREE_CODE (lhs_array[ii][jj]) == ARRAY_NOTATION_REF)
1484 {
1485 lhs_value[ii][jj] = ARRAY_NOTATION_ARRAY (lhs_array[ii][jj]);
1486 lhs_start[ii][jj] = ARRAY_NOTATION_START (lhs_array[ii][jj]);
1487 lhs_length[ii][jj] =
1488 fold_build1 (CONVERT_EXPR, integer_type_node,
1489 ARRAY_NOTATION_LENGTH (lhs_array[ii][jj]));
1490 lhs_stride[ii][jj] =
1491 fold_build1 (CONVERT_EXPR, integer_type_node,
1492 ARRAY_NOTATION_STRIDE (lhs_array[ii][jj]));
1493 lhs_vector[ii][jj] = true;
1494 /* IF the stride value is variable (i.e. not constant) then
1495 assume that the length is positive. */
1496 if (!TREE_CONSTANT (lhs_length[ii][jj]))
1497 lhs_count_down[ii][jj] = false;
1498 else if (tree_int_cst_lt
1499 (lhs_length[ii][jj],
1500 build_zero_cst (TREE_TYPE (lhs_length[ii][jj]))))
1501 lhs_count_down[ii][jj] = true;
1502 else
1503 lhs_count_down[ii][jj] = false;
1504 }
1505 else
1506 lhs_vector[ii][jj] = false;
1507 }
1508 }
1509 }
1510 for (ii = 0; ii < rhs_list_size; ii++)
1511 {
1512 if (TREE_CODE ((*rhs_list)[ii]) == ARRAY_NOTATION_REF)
1513 {
1514 for (jj = 0; jj < rhs_rank; jj++)
1515 {
1516 if (TREE_CODE (rhs_array[ii][jj]) == ARRAY_NOTATION_REF)
1517 {
1518 rhs_value[ii][jj] = ARRAY_NOTATION_ARRAY (rhs_array[ii][jj]);
1519 rhs_start[ii][jj] = ARRAY_NOTATION_START (rhs_array[ii][jj]);
1520 rhs_length[ii][jj] =
1521 fold_build1 (CONVERT_EXPR, integer_type_node,
1522 ARRAY_NOTATION_LENGTH (rhs_array[ii][jj]));
1523 rhs_stride[ii][jj] =
1524 fold_build1 (CONVERT_EXPR, integer_type_node,
1525 ARRAY_NOTATION_STRIDE (rhs_array[ii][jj]));
1526 rhs_vector[ii][jj] = true;
1527 /* If the stride value is variable (i.e. not constant) then
1528 assume that the length is positive. */
1529 if (!TREE_CONSTANT (rhs_length[ii][jj]))
1530 rhs_count_down[ii][jj] = false;
1531 else if (tree_int_cst_lt
1532 (rhs_length[ii][jj],
1533 build_int_cst (TREE_TYPE (rhs_length[ii][jj]), 0)))
1534 rhs_count_down[ii][jj] = true;
1535 else
1536 rhs_count_down[ii][jj] = false;
1537 }
1538 else
1539 rhs_vector[ii][jj] = false;
1540 }
1541 }
1542 else
1543 for (jj = 0; jj < rhs_rank; jj++)
1544 {
1545 rhs_vector[ii][jj] = false;
1546 rhs_length[ii][jj] = NULL_TREE;
1547 }
1548 }
1549
1550 if (length_mismatch_in_expr_p (EXPR_LOCATION (lhs), lhs_length,
1551 lhs_list_size, lhs_rank)
1552 || length_mismatch_in_expr_p (EXPR_LOCATION (rhs), rhs_length,
1553 rhs_list_size, rhs_rank))
1554 {
1555 pop_stmt_list (an_init);
1556 return error_mark_node;
1557 }
1558
1559 if (lhs_list_size > 0 && rhs_list_size > 0 && lhs_rank > 0 && rhs_rank > 0
1560 && TREE_CODE (lhs_length[0][0]) == INTEGER_CST
1561 && rhs_length[0][0]
1562 && TREE_CODE (rhs_length[0][0]) == INTEGER_CST)
1563 {
1564 HOST_WIDE_INT l_length = int_cst_value (lhs_length[0][0]);
1565 HOST_WIDE_INT r_length = int_cst_value (rhs_length[0][0]);
1566 /* Length can be negative or positive. As long as the magnitude is OK,
1567 then the array notation is valid. */
1568 if (absu_hwi (l_length) != absu_hwi (r_length))
1569 {
1570 error_at (location, "length mismatch between LHS and RHS");
1571 pop_stmt_list (an_init);
1572 return error_mark_node;
1573 }
1574 }
1575 for (ii = 0; ii < lhs_rank; ii++)
1576 {
1577 if (lhs_vector[0][ii])
1578 {
1579 lhs_var[ii] = build_decl (location, VAR_DECL, NULL_TREE,
1580 integer_type_node);
1581 lhs_ind_init[ii] = build_modify_expr
1582 (location, lhs_var[ii], TREE_TYPE (lhs_var[ii]),
1583 NOP_EXPR,
1584 location, build_zero_cst (TREE_TYPE (lhs_var[ii])),
1585 TREE_TYPE (lhs_var[ii]));
1586 }
1587 }
1588
1589 for (ii = 0; ii < rhs_rank; ii++)
1590 {
1591 /* When we have a polynomial, we assume that the indices are of type
1592 integer. */
1593 rhs_var[ii] = build_decl (location, VAR_DECL, NULL_TREE,
1594 integer_type_node);
1595 rhs_ind_init[ii] = build_modify_expr
1596 (location, rhs_var[ii], TREE_TYPE (rhs_var[ii]),
1597 NOP_EXPR,
1598 location, build_int_cst (TREE_TYPE (rhs_var[ii]), 0),
1599 TREE_TYPE (rhs_var[ii]));
1600 }
1601 if (lhs_rank)
1602 {
1603 for (ii = 0; ii < lhs_list_size; ii++)
1604 {
1605 if (lhs_vector[ii][0])
1606 {
1607 /* The last ARRAY_NOTATION element's ARRAY component should be
1608 the array's base value. */
1609 tree lhs_array_opr = lhs_value[ii][lhs_rank - 1];
1610 for (s_jj = lhs_rank - 1; s_jj >= 0; s_jj--)
1611 {
1612 if (lhs_count_down[ii][s_jj])
1613 /* Array[start_index + (induction_var * stride)]. */
1614 lhs_array_opr = build_array_ref
1615 (location, lhs_array_opr,
1616 build2 (MINUS_EXPR, TREE_TYPE (lhs_var[s_jj]),
1617 lhs_start[ii][s_jj],
1618 build2 (MULT_EXPR, TREE_TYPE (lhs_var[s_jj]),
1619 lhs_var[s_jj],
1620 lhs_stride[ii][s_jj])));
1621 else
1622 lhs_array_opr = build_array_ref
1623 (location, lhs_array_opr,
1624 build2 (PLUS_EXPR, TREE_TYPE (lhs_var[s_jj]),
1625 lhs_start[ii][s_jj],
1626 build2 (MULT_EXPR, TREE_TYPE (lhs_var[s_jj]),
1627 lhs_var[s_jj],
1628 lhs_stride[ii][s_jj])));
1629 }
1630 vec_safe_push (lhs_array_operand, lhs_array_opr);
1631 }
1632 else
1633 vec_safe_push (lhs_array_operand, integer_one_node);
1634 }
1635 replace_array_notations (&lhs, true, lhs_list, lhs_array_operand);
1636 array_expr_lhs = lhs;
1637 }
1638
1639 if (rhs_rank)
1640 {
1641 for (ii = 0; ii < rhs_list_size; ii++)
1642 {
1643 if (rhs_vector[ii][0])
1644 {
1645 tree rhs_array_opr = rhs_value[ii][rhs_rank - 1];
1646 for (s_jj = rhs_rank - 1; s_jj >= 0; s_jj--)
1647 {
1648 if (rhs_count_down[ii][s_jj])
1649 /* Array[start_index - (induction_var * stride)] */
1650 rhs_array_opr = build_array_ref
1651 (location, rhs_array_opr,
1652 build2 (MINUS_EXPR, TREE_TYPE (rhs_var[s_jj]),
1653 rhs_start[ii][s_jj],
1654 build2 (MULT_EXPR, TREE_TYPE (rhs_var[s_jj]),
1655 rhs_var[s_jj],
1656 rhs_stride[ii][s_jj])));
1657 else
1658 /* Array[start_index + (induction_var * stride)] */
1659 rhs_array_opr = build_array_ref
1660 (location, rhs_array_opr,
1661 build2 (PLUS_EXPR, TREE_TYPE (rhs_var[s_jj]),
1662 rhs_start[ii][s_jj],
1663 build2 (MULT_EXPR, TREE_TYPE (rhs_var[s_jj]),
1664 rhs_var[s_jj],
1665 rhs_stride[ii][s_jj])));
1666 }
1667 vec_safe_push (rhs_array_operand, rhs_array_opr);
1668 }
1669 else
1670 /* This is just a dummy node to make sure the list sizes for both
1671 array list and array operand list are the same. */
1672 vec_safe_push (rhs_array_operand, integer_one_node);
1673 }
1674
1675 for (ii = 0; ii < rhs_list_size; ii++)
1676 {
1677 tree rhs_node = (*rhs_list)[ii];
1678 if (TREE_CODE (rhs_node) == CALL_EXPR)
1679 {
1680 int idx_value = 0;
1681 tree func_name = CALL_EXPR_FN (rhs_node);
1682 if (TREE_CODE (func_name) == ADDR_EXPR)
1683 if (is_sec_implicit_index_fn (func_name))
1684 {
1685 idx_value =
1686 extract_sec_implicit_index_arg (location, rhs_node);
1687 if (idx_value == -1) /* This means we have an error. */
1688 return error_mark_node;
1689 else if (idx_value < (int) lhs_rank && idx_value >= 0)
1690 vec_safe_push (rhs_array_operand, lhs_var[idx_value]);
1691 else
1692 {
1693 size_t ee = 0;
1694 tree lhs_base = (*lhs_list)[ii];
1695 for (ee = 0; ee < lhs_rank; ee++)
1696 lhs_base = ARRAY_NOTATION_ARRAY (lhs_base);
1697 error_at (location, "__sec_implicit_index argument %d "
1698 "must be less than rank of %qD", idx_value,
1699 lhs_base);
1700 return error_mark_node;
1701 }
1702 }
1703 }
1704 }
1705 replace_array_notations (&rhs, true, rhs_list, rhs_array_operand);
1706 array_expr_rhs = rhs;
1707 }
1708 else
1709 {
1710 for (ii = 0; ii < rhs_list_size; ii++)
1711 {
1712 tree rhs_node = (*rhs_list)[ii];
1713 if (TREE_CODE (rhs_node) == CALL_EXPR)
1714 {
1715 int idx_value = 0;
1716 tree func_name = CALL_EXPR_FN (rhs_node);
1717 if (TREE_CODE (func_name) == ADDR_EXPR)
1718 if (is_sec_implicit_index_fn (func_name))
1719 {
1720 idx_value =
1721 extract_sec_implicit_index_arg (location, rhs_node);
1722 if (idx_value == -1) /* This means we have an error. */
1723 return error_mark_node;
1724 else if (idx_value < (int) lhs_rank && idx_value >= 0)
1725 vec_safe_push (rhs_array_operand, lhs_var[idx_value]);
1726 else
1727 {
1728 size_t ee = 0;
1729 tree lhs_base = (*lhs_list)[ii];
1730 for (ee = 0; ee < lhs_rank; ee++)
1731 lhs_base = ARRAY_NOTATION_ARRAY (lhs_base);
1732 error_at (location, "__sec_implicit_index argument %d "
1733 "must be less than rank of %qD", idx_value,
1734 lhs_base);
1735 return error_mark_node;
1736 }
1737 }
1738 }
1739 }
1740 replace_array_notations (&rhs, true, rhs_list, rhs_array_operand);
1741 array_expr_rhs = rhs;
1742 rhs_expr_incr[0] = NULL_TREE;
1743 }
1744
1745 for (ii = 0; ii < rhs_rank; ii++)
1746 rhs_expr_incr[ii] = build2 (MODIFY_EXPR, void_type_node, rhs_var[ii],
1747 build2
1748 (PLUS_EXPR, TREE_TYPE (rhs_var[ii]),
1749 rhs_var[ii],
1750 build_one_cst (TREE_TYPE (rhs_var[ii]))));
1751
1752 for (ii = 0; ii < lhs_rank; ii++)
1753 lhs_expr_incr[ii] = build2
1754 (MODIFY_EXPR, void_type_node, lhs_var[ii],
1755 build2 (PLUS_EXPR, TREE_TYPE (lhs_var[ii]), lhs_var[ii],
1756 build_one_cst (TREE_TYPE (lhs_var[ii]))));
1757
1758 /* If array_expr_lhs is NULL, then we have function that returns void or
1759 its return value is ignored. */
1760 if (!array_expr_lhs)
1761 array_expr_lhs = lhs;
1762
1763 array_expr = build_modify_expr (location, array_expr_lhs, lhs_origtype,
1764 modifycode, rhs_loc, array_expr_rhs,
1765 rhs_origtype);
1766
1767 for (jj = 0; jj < MAX (lhs_rank, rhs_rank); jj++)
1768 {
1769 if (rhs_rank && rhs_expr_incr[jj])
1770 {
1771 size_t iii = 0;
1772 if (lhs_rank == 0)
1773 lhs_compare[jj] = integer_one_node;
1774 else if (lhs_count_down[0][jj])
1775 lhs_compare[jj] = build2
1776 (GT_EXPR, boolean_type_node, lhs_var[jj], lhs_length[0][jj]);
1777 else
1778 lhs_compare[jj] = build2
1779 (LT_EXPR, boolean_type_node, lhs_var[jj], lhs_length[0][jj]);
1780
1781
1782 /* The reason why we have this here is for the following case:
1783 Array[:][:] = function_call(something) + Array2[:][:];
1784
1785 So, we will skip the first operand of RHS and then go to the
1786 2nd to find whether we should count up or down. */
1787
1788 for (iii = 0; iii < rhs_list_size; iii++)
1789 if (rhs_vector[iii][jj])
1790 break;
1791
1792 /* What we are doing here is this:
1793 We always count up, so:
1794 if (length is negative ==> which means we count down)
1795 we multiply length by -1 and count up => ii < -LENGTH
1796 else
1797 we just count up, so we compare for ii < LENGTH
1798 */
1799 if (rhs_count_down[iii][jj])
1800 /* We use iii for rhs_length because that is the correct countdown
1801 we have to use. */
1802 rhs_compare[jj] = build2
1803 (LT_EXPR, boolean_type_node, rhs_var[jj],
1804 build2 (MULT_EXPR, TREE_TYPE (rhs_var[jj]),
1805 rhs_length[iii][jj],
1806 build_int_cst (TREE_TYPE (rhs_var[jj]), -1)));
1807 else
1808 rhs_compare[jj] = build2 (LT_EXPR, boolean_type_node, rhs_var[jj],
1809 rhs_length[iii][jj]);
1810 if (lhs_compare[ii] != integer_one_node)
1811 cond_expr[jj] = build2 (TRUTH_ANDIF_EXPR, void_type_node,
1812 lhs_compare[jj], rhs_compare[jj]);
1813 else
1814 cond_expr[jj] = rhs_compare[jj];
1815 }
1816 else
1817 {
1818 if (lhs_count_down[0][jj])
1819 cond_expr[jj] = build2
1820 (GT_EXPR, boolean_type_node, lhs_var[jj], lhs_length[0][jj]);
1821 else
1822 cond_expr[jj] = build2
1823 (LT_EXPR, boolean_type_node, lhs_var[jj], lhs_length[0][jj]);
1824 }
1825 }
1826
1827 an_init = pop_stmt_list (an_init);
1828 append_to_statement_list_force (an_init, &loop_with_init);
1829 body = array_expr;
1830 for (ii = 0; ii < MAX (lhs_rank, rhs_rank); ii++)
1831 {
1832 tree incr_list = alloc_stmt_list ();
1833 tree new_loop = push_stmt_list ();
1834 if (lhs_rank)
1835 add_stmt (lhs_ind_init[ii]);
1836 if (rhs_rank)
1837 add_stmt (rhs_ind_init[ii]);
1838 if (lhs_rank)
1839 append_to_statement_list_force (lhs_expr_incr[ii], &incr_list);
1840 if (rhs_rank && rhs_expr_incr[ii])
1841 append_to_statement_list_force (rhs_expr_incr[ii], &incr_list);
1842 c_finish_loop (location, cond_expr[ii], incr_list, body, NULL_TREE,
1843 NULL_TREE, true);
1844 body = pop_stmt_list (new_loop);
1845 }
1846 append_to_statement_list_force (body, &loop_with_init);
1847 return loop_with_init;
1848 }
1849
1850 /* Helper function for fix_conditional_array_notations. Encloses the
1851 conditional statement passed in STMT with a loop around it
1852 and replaces the condition in STMT with a ARRAY_REF tree-node to the array.
1853 The condition must have an ARRAY_NOTATION_REF tree. An expansion of array
1854 notation in STMT is returned in a STATEMENT_LIST. */
1855
1856 static tree
1857 fix_conditional_array_notations_1 (tree stmt)
1858 {
1859 vec<tree, va_gc> *array_list = NULL, *array_operand = NULL;
1860 size_t list_size = 0;
1861 tree cond = NULL_TREE, builtin_loop = NULL_TREE, new_var = NULL_TREE;
1862 size_t rank = 0, ii = 0, jj = 0;
1863 int s_jj = 0;
1864 tree **array_ops, *array_var, jj_tree, loop_init;
1865 tree **array_value, **array_stride, **array_length, **array_start;
1866 tree *compare_expr, *expr_incr, *ind_init;
1867 bool **count_down, **array_vector;
1868 tree begin_var, lngth_var, strde_var;
1869 location_t location = EXPR_LOCATION (stmt);
1870 tree body = NULL_TREE, loop_with_init = alloc_stmt_list ();
1871 if (TREE_CODE (stmt) == COND_EXPR)
1872 cond = COND_EXPR_COND (stmt);
1873 else if (TREE_CODE (stmt) == SWITCH_EXPR)
1874 cond = SWITCH_COND (stmt);
1875 else
1876 /* Otherwise dont even touch the statement. */
1877 return stmt;
1878
1879 if (!find_rank (location, cond, cond, false, &rank))
1880 return error_mark_node;
1881
1882 extract_array_notation_exprs (cond, false, &array_list);
1883 loop_init = push_stmt_list ();
1884 for (ii = 0; ii < vec_safe_length (array_list); ii++)
1885 {
1886 tree array_node = (*array_list)[ii];
1887 if (TREE_CODE (array_node) == CALL_EXPR)
1888 {
1889 builtin_loop = fix_builtin_array_notation_fn (array_node, &new_var);
1890 if (builtin_loop == error_mark_node)
1891 {
1892 add_stmt (error_mark_node);
1893 pop_stmt_list (loop_init);
1894 return loop_init;
1895 }
1896 else if (builtin_loop)
1897 {
1898 vec <tree, va_gc>* sub_list = NULL, *new_var_list = NULL;
1899 vec_safe_push (sub_list, array_node);
1900 vec_safe_push (new_var_list, new_var);
1901 add_stmt (builtin_loop);
1902 replace_array_notations (&cond, false, sub_list, new_var_list);
1903 }
1904 }
1905 }
1906
1907 if (!find_rank (location, cond, cond, true, &rank))
1908 {
1909 pop_stmt_list (loop_init);
1910 return error_mark_node;
1911 }
1912 if (rank == 0)
1913 {
1914 add_stmt (stmt);
1915 pop_stmt_list (loop_init);
1916 return loop_init;
1917 }
1918 extract_array_notation_exprs (cond, true, &array_list);
1919
1920 if (vec_safe_length (array_list) == 0)
1921 return stmt;
1922
1923 list_size = vec_safe_length (array_list);
1924
1925 array_ops = XNEWVEC (tree *, list_size);
1926 for (ii = 0; ii < list_size; ii++)
1927 array_ops[ii] = XNEWVEC (tree, rank);
1928
1929 array_vector = XNEWVEC (bool *, list_size);
1930 for (ii = 0; ii < list_size; ii++)
1931 array_vector[ii] = XNEWVEC (bool, rank);
1932
1933 array_value = XNEWVEC (tree *, list_size);
1934 array_stride = XNEWVEC (tree *, list_size);
1935 array_length = XNEWVEC (tree *, list_size);
1936 array_start = XNEWVEC (tree *, list_size);
1937
1938 for (ii = 0; ii < list_size; ii++)
1939 {
1940 array_value[ii] = XNEWVEC (tree, rank);
1941 array_stride[ii] = XNEWVEC (tree, rank);
1942 array_length[ii] = XNEWVEC (tree, rank);
1943 array_start[ii] = XNEWVEC (tree, rank);
1944 }
1945
1946 compare_expr = XNEWVEC (tree, rank);
1947 expr_incr = XNEWVEC (tree, rank);
1948 ind_init = XNEWVEC (tree, rank);
1949
1950 count_down = XNEWVEC (bool *, list_size);
1951 for (ii = 0; ii < list_size; ii++)
1952 count_down[ii] = XNEWVEC (bool, rank);
1953
1954 array_var = XNEWVEC (tree, rank);
1955
1956 for (ii = 0; ii < list_size; ii++)
1957 {
1958 tree array_node = (*array_list)[ii];
1959 if (array_node && TREE_CODE (array_node) == ARRAY_NOTATION_REF)
1960 {
1961 tree array_begin = ARRAY_NOTATION_START (array_node);
1962 tree array_lngth = ARRAY_NOTATION_LENGTH (array_node);
1963 tree array_strde = ARRAY_NOTATION_STRIDE (array_node);
1964
1965 if (TREE_CODE (array_begin) != INTEGER_CST)
1966 {
1967 begin_var = build_decl (location, VAR_DECL, NULL_TREE,
1968 integer_type_node);
1969 add_stmt (build_modify_expr (location, begin_var,
1970 TREE_TYPE (begin_var),
1971 NOP_EXPR, location, array_begin,
1972 TREE_TYPE (array_begin)));
1973 ARRAY_NOTATION_START (array_node) = begin_var;
1974 }
1975 if (TREE_CODE (array_lngth) != INTEGER_CST)
1976 {
1977 lngth_var = build_decl (location, VAR_DECL, NULL_TREE,
1978 integer_type_node);
1979 add_stmt (build_modify_expr (location, lngth_var,
1980 TREE_TYPE (lngth_var),
1981 NOP_EXPR, location, array_lngth,
1982 TREE_TYPE (array_lngth)));
1983 ARRAY_NOTATION_LENGTH (array_node) = lngth_var;
1984 }
1985 if (TREE_CODE (array_strde) != INTEGER_CST)
1986 {
1987 strde_var = build_decl (location, VAR_DECL, NULL_TREE,
1988 integer_type_node);
1989 add_stmt (build_modify_expr (location, strde_var,
1990 TREE_TYPE (strde_var),
1991 NOP_EXPR, location, array_strde,
1992 TREE_TYPE (array_strde)));
1993 ARRAY_NOTATION_STRIDE (array_node) = strde_var;
1994 }
1995 }
1996 }
1997 for (ii = 0; ii < list_size; ii++)
1998 {
1999 tree array_node = (*array_list)[ii];
2000 jj = 0;
2001 for (jj_tree = array_node;
2002 jj_tree && TREE_CODE (jj_tree) == ARRAY_NOTATION_REF;
2003 jj_tree = ARRAY_NOTATION_ARRAY (jj_tree))
2004 {
2005 array_ops[ii][jj] = jj_tree;
2006 jj++;
2007 }
2008 }
2009 for (ii = 0; ii < list_size; ii++)
2010 {
2011 tree array_node = (*array_list)[ii];
2012 if (TREE_CODE (array_node) == ARRAY_NOTATION_REF)
2013 {
2014 for (jj = 0; jj < rank; jj++)
2015 {
2016 if (TREE_CODE (array_ops[ii][jj]) == ARRAY_NOTATION_REF)
2017 {
2018 array_value[ii][jj] =
2019 ARRAY_NOTATION_ARRAY (array_ops[ii][jj]);
2020 array_start[ii][jj] =
2021 ARRAY_NOTATION_START (array_ops[ii][jj]);
2022 array_length[ii][jj] =
2023 fold_build1 (CONVERT_EXPR, integer_type_node,
2024 ARRAY_NOTATION_LENGTH (array_ops[ii][jj]));
2025 array_stride[ii][jj] =
2026 fold_build1 (CONVERT_EXPR, integer_type_node,
2027 ARRAY_NOTATION_STRIDE (array_ops[ii][jj]));
2028 array_vector[ii][jj] = true;
2029
2030 if (!TREE_CONSTANT (array_length[ii][jj]))
2031 count_down[ii][jj] = false;
2032 else if (tree_int_cst_lt
2033 (array_length[ii][jj],
2034 build_int_cst (TREE_TYPE (array_length[ii][jj]),
2035 0)))
2036 count_down[ii][jj] = true;
2037 else
2038 count_down[ii][jj] = false;
2039 }
2040 else
2041 array_vector[ii][jj] = false;
2042 }
2043 }
2044 }
2045
2046 for (ii = 0; ii < rank; ii++)
2047 {
2048 array_var[ii] = build_decl (location, VAR_DECL, NULL_TREE,
2049 integer_type_node);
2050 ind_init[ii] =
2051 build_modify_expr (location, array_var[ii],
2052 TREE_TYPE (array_var[ii]), NOP_EXPR,
2053 location,
2054 build_int_cst (TREE_TYPE (array_var[ii]), 0),
2055 TREE_TYPE (array_var[ii]));
2056 }
2057
2058 for (ii = 0; ii < list_size; ii++)
2059 {
2060 if (array_vector[ii][0])
2061 {
2062 tree array_opr = array_value[ii][rank - 1];
2063 for (s_jj = rank - 1; s_jj >= 0; s_jj--)
2064 {
2065 if (count_down[ii][s_jj])
2066 /* Array[start_index - (induction_var * stride)] */
2067 array_opr = build_array_ref
2068 (location, array_opr,
2069 build2 (MINUS_EXPR, TREE_TYPE (array_var[s_jj]),
2070 array_start[ii][s_jj],
2071 build2 (MULT_EXPR, TREE_TYPE (array_var[s_jj]),
2072 array_var[s_jj], array_stride[ii][s_jj])));
2073 else
2074 /* Array[start_index + (induction_var * stride)] */
2075 array_opr = build_array_ref
2076 (location, array_opr,
2077 build2 (PLUS_EXPR, TREE_TYPE (array_var[s_jj]),
2078 array_start[ii][s_jj],
2079 build2 (MULT_EXPR, TREE_TYPE (array_var[s_jj]),
2080 array_var[s_jj], array_stride[ii][s_jj])));
2081 }
2082 vec_safe_push (array_operand, array_opr);
2083 }
2084 else
2085 /* This is just a dummy node to make sure the list sizes for both
2086 array list and array operand list are the same. */
2087 vec_safe_push (array_operand, integer_one_node);
2088 }
2089 replace_array_notations (&stmt, true, array_list, array_operand);
2090 for (ii = 0; ii < rank; ii++)
2091 expr_incr[ii] = build2 (MODIFY_EXPR, void_type_node, array_var[ii],
2092 build2 (PLUS_EXPR, TREE_TYPE (array_var[ii]),
2093 array_var[ii],
2094 build_int_cst (TREE_TYPE (array_var[ii]),
2095 1)));
2096 for (jj = 0; jj < rank; jj++)
2097 {
2098 if (rank && expr_incr[jj])
2099 {
2100 if (count_down[0][jj])
2101 compare_expr[jj] =
2102 build2 (LT_EXPR, boolean_type_node, array_var[jj],
2103 build2 (MULT_EXPR, TREE_TYPE (array_var[jj]),
2104 array_length[0][jj],
2105 build_int_cst (TREE_TYPE (array_var[jj]), -1)));
2106 else
2107 compare_expr[jj] = build2 (LT_EXPR, boolean_type_node,
2108 array_var[jj], array_length[0][jj]);
2109 }
2110 }
2111
2112 loop_init = pop_stmt_list (loop_init);
2113 body = stmt;
2114 append_to_statement_list_force (loop_init, &loop_with_init);
2115
2116 for (ii = 0; ii < rank; ii++)
2117 {
2118 tree new_loop = push_stmt_list ();
2119 add_stmt (ind_init[ii]);
2120 c_finish_loop (location, compare_expr[ii], expr_incr[ii], body, NULL_TREE,
2121 NULL_TREE, true);
2122 body = pop_stmt_list (new_loop);
2123 }
2124 append_to_statement_list_force (body, &loop_with_init);
2125 XDELETEVEC (expr_incr);
2126 XDELETEVEC (ind_init);
2127
2128 for (ii = 0; ii < list_size; ii++)
2129 {
2130 XDELETEVEC (count_down[ii]);
2131 XDELETEVEC (array_value[ii]);
2132 XDELETEVEC (array_stride[ii]);
2133 XDELETEVEC (array_length[ii]);
2134 XDELETEVEC (array_start[ii]);
2135 XDELETEVEC (array_ops[ii]);
2136 XDELETEVEC (array_vector[ii]);
2137 }
2138
2139 XDELETEVEC (count_down);
2140 XDELETEVEC (array_value);
2141 XDELETEVEC (array_stride);
2142 XDELETEVEC (array_length);
2143 XDELETEVEC (array_start);
2144 XDELETEVEC (array_ops);
2145 XDELETEVEC (array_vector);
2146
2147 return loop_with_init;
2148 }
2149
2150 /* Top-level function to replace ARRAY_NOTATION_REF in a conditional statement
2151 in STMT. An expansion of array notation in STMT is returned as a
2152 STATEMENT_LIST. */
2153
2154 tree
2155 fix_conditional_array_notations (tree stmt)
2156 {
2157 if (TREE_CODE (stmt) == STATEMENT_LIST)
2158 {
2159 tree_stmt_iterator tsi;
2160 for (tsi = tsi_start (stmt); !tsi_end_p (tsi); tsi_next (&tsi))
2161 {
2162 tree single_stmt = *tsi_stmt_ptr (tsi);
2163 *tsi_stmt_ptr (tsi) =
2164 fix_conditional_array_notations_1 (single_stmt);
2165 }
2166 return stmt;
2167 }
2168 else
2169 return fix_conditional_array_notations_1 (stmt);
2170 }
2171
2172 /* Create a struct c_expr that contains a loop with ARRAY_REF expr at location
2173 LOCATION with the tree_code CODE and the array notation expr is
2174 passed in ARG. Returns the fixed c_expr in ARG itself. */
2175
2176 struct c_expr
2177 fix_array_notation_expr (location_t location, enum tree_code code,
2178 struct c_expr arg)
2179 {
2180
2181 vec<tree, va_gc> *array_list = NULL, *array_operand = NULL;
2182 size_t list_size = 0, rank = 0, ii = 0, jj = 0;
2183 int s_jj = 0;
2184 tree **array_ops, *array_var, jj_tree, loop_init;
2185 tree **array_value, **array_stride, **array_length, **array_start;
2186 tree *compare_expr, *expr_incr, *ind_init;
2187 tree body, loop_with_init = alloc_stmt_list ();
2188 bool **count_down, **array_vector;
2189
2190 if (!find_rank (location, arg.value, arg.value, false, &rank))
2191 {
2192 /* If this function returns a NULL, we convert the tree value in the
2193 structure to error_mark_node and the parser should take care of the
2194 rest. */
2195 arg.value = error_mark_node;
2196 return arg;
2197 }
2198
2199 if (rank == 0)
2200 return arg;
2201
2202 extract_array_notation_exprs (arg.value, true, &array_list);
2203
2204 if (vec_safe_length (array_list) == 0)
2205 return arg;
2206
2207 list_size = vec_safe_length (array_list);
2208
2209 array_ops = XNEWVEC (tree *, list_size);
2210 for (ii = 0; ii < list_size; ii++)
2211 array_ops[ii] = XNEWVEC (tree, rank);
2212
2213 array_vector = XNEWVEC (bool *, list_size);
2214 for (ii = 0; ii < list_size; ii++)
2215 array_vector[ii] = XNEWVEC (bool, rank);
2216
2217 array_value = XNEWVEC (tree *, list_size);
2218 array_stride = XNEWVEC (tree *, list_size);
2219 array_length = XNEWVEC (tree *, list_size);
2220 array_start = XNEWVEC (tree *, list_size);
2221
2222 for (ii = 0; ii < list_size; ii++)
2223 {
2224 array_value[ii] = XNEWVEC (tree, rank);
2225 array_stride[ii] = XNEWVEC (tree, rank);
2226 array_length[ii] = XNEWVEC (tree, rank);
2227 array_start[ii] = XNEWVEC (tree, rank);
2228 }
2229
2230 compare_expr = XNEWVEC (tree, rank);
2231 expr_incr = XNEWVEC (tree, rank);
2232 ind_init = XNEWVEC (tree, rank);
2233
2234 count_down = XNEWVEC (bool *, list_size);
2235 for (ii = 0; ii < list_size; ii++)
2236 count_down[ii] = XNEWVEC (bool, rank);
2237 array_var = XNEWVEC (tree, rank);
2238
2239 for (ii = 0; ii < list_size; ii++)
2240 {
2241 jj = 0;
2242 for (jj_tree = (*array_list)[ii];
2243 jj_tree && TREE_CODE (jj_tree) == ARRAY_NOTATION_REF;
2244 jj_tree = ARRAY_NOTATION_ARRAY (jj_tree))
2245 {
2246 array_ops[ii][jj] = jj_tree;
2247 jj++;
2248 }
2249 }
2250
2251 loop_init = push_stmt_list ();
2252
2253 for (ii = 0; ii < list_size; ii++)
2254 {
2255 tree array_node = (*array_list)[ii];
2256 if (TREE_CODE (array_node) == ARRAY_NOTATION_REF)
2257 {
2258 for (jj = 0; jj < rank; jj++)
2259 {
2260 if (TREE_CODE (array_ops[ii][jj]) == ARRAY_NOTATION_REF)
2261 {
2262 array_value[ii][jj] =
2263 ARRAY_NOTATION_ARRAY (array_ops[ii][jj]);
2264 array_start[ii][jj] =
2265 ARRAY_NOTATION_START (array_ops[ii][jj]);
2266 array_length[ii][jj] =
2267 fold_build1 (CONVERT_EXPR, integer_type_node,
2268 ARRAY_NOTATION_LENGTH (array_ops[ii][jj]));
2269 array_stride[ii][jj] =
2270 fold_build1 (CONVERT_EXPR, integer_type_node,
2271 ARRAY_NOTATION_STRIDE (array_ops[ii][jj]));
2272 array_vector[ii][jj] = true;
2273
2274 if (!TREE_CONSTANT (array_length[ii][jj]))
2275 count_down[ii][jj] = false;
2276 else if (tree_int_cst_lt
2277 (array_length[ii][jj],
2278 build_int_cst (TREE_TYPE (array_length[ii][jj]),
2279 0)))
2280 count_down[ii][jj] = true;
2281 else
2282 count_down[ii][jj] = false;
2283 }
2284 else
2285 array_vector[ii][jj] = false;
2286 }
2287 }
2288 }
2289
2290 for (ii = 0; ii < rank; ii++)
2291 {
2292 array_var[ii] = build_decl (location, VAR_DECL, NULL_TREE,
2293 integer_type_node);
2294 ind_init[ii] =
2295 build_modify_expr (location, array_var[ii],
2296 TREE_TYPE (array_var[ii]), NOP_EXPR,
2297 location,
2298 build_int_cst (TREE_TYPE (array_var[ii]), 0),
2299 TREE_TYPE (array_var[ii]));
2300
2301 }
2302 for (ii = 0; ii < list_size; ii++)
2303 {
2304 if (array_vector[ii][0])
2305 {
2306 tree array_opr = array_value[ii][rank - 1];
2307 for (s_jj = rank - 1; s_jj >= 0; s_jj--)
2308 {
2309 if (count_down[ii][s_jj])
2310 /* Array[start_index - (induction_var * stride)] */
2311 array_opr = build_array_ref
2312 (location, array_opr,
2313 build2 (MINUS_EXPR, TREE_TYPE (array_var[s_jj]),
2314 array_start[ii][s_jj],
2315 build2 (MULT_EXPR, TREE_TYPE (array_var[s_jj]),
2316 array_var[s_jj], array_stride[ii][s_jj])));
2317 else
2318 /* Array[start_index + (induction_var * stride)] */
2319 array_opr = build_array_ref
2320 (location, array_opr,
2321 build2 (PLUS_EXPR, TREE_TYPE (array_var[s_jj]),
2322 array_start[ii][s_jj],
2323 build2 (MULT_EXPR, TREE_TYPE (array_var[s_jj]),
2324 array_var[s_jj], array_stride[ii][s_jj])));
2325 }
2326 vec_safe_push (array_operand, array_opr);
2327 }
2328 else
2329 /* This is just a dummy node to make sure the list sizes for both
2330 array list and array operand list are the same. */
2331 vec_safe_push (array_operand, integer_one_node);
2332 }
2333 replace_array_notations (&arg.value, true, array_list, array_operand);
2334
2335 for (ii = 0; ii < rank; ii++)
2336 expr_incr[ii] =
2337 build2 (MODIFY_EXPR, void_type_node, array_var[ii],
2338 build2 (PLUS_EXPR, TREE_TYPE (array_var[ii]), array_var[ii],
2339 build_int_cst (TREE_TYPE (array_var[ii]), 1)));
2340
2341 for (jj = 0; jj < rank; jj++)
2342 {
2343 if (rank && expr_incr[jj])
2344 {
2345 if (count_down[0][jj])
2346 compare_expr[jj] =
2347 build2 (LT_EXPR, boolean_type_node, array_var[jj],
2348 build2 (MULT_EXPR, TREE_TYPE (array_var[jj]),
2349 array_length[0][jj],
2350 build_int_cst (TREE_TYPE (array_var[jj]), -1)));
2351 else
2352 compare_expr[jj] = build2 (LT_EXPR, boolean_type_node,
2353 array_var[jj], array_length[0][jj]);
2354 }
2355 }
2356
2357 if (code == POSTINCREMENT_EXPR || code == POSTDECREMENT_EXPR)
2358 {
2359 arg = default_function_array_read_conversion (location, arg);
2360 arg.value = build_unary_op (location, code, arg.value, 0);
2361 }
2362 else if (code == PREINCREMENT_EXPR || code == PREDECREMENT_EXPR)
2363 {
2364 arg = default_function_array_read_conversion (location, arg);
2365 arg = parser_build_unary_op (location, code, arg);
2366 }
2367
2368 loop_init = pop_stmt_list (loop_init);
2369 append_to_statement_list_force (loop_init, &loop_with_init);
2370 body = arg.value;
2371
2372 for (ii = 0; ii < rank; ii++)
2373 {
2374 tree new_loop = push_stmt_list ();
2375 add_stmt (ind_init[ii]);
2376 c_finish_loop (location, compare_expr[ii], expr_incr[ii], body, NULL_TREE,
2377 NULL_TREE, true);
2378 body = pop_stmt_list (new_loop);
2379 }
2380 append_to_statement_list_force (body, &loop_with_init);
2381 XDELETEVEC (expr_incr);
2382 XDELETEVEC (ind_init);
2383 XDELETEVEC (array_var);
2384
2385 for (ii = 0; ii < list_size; ii++)
2386 {
2387 XDELETEVEC (count_down[ii]);
2388 XDELETEVEC (array_value[ii]);
2389 XDELETEVEC (array_stride[ii]);
2390 XDELETEVEC (array_length[ii]);
2391 XDELETEVEC (array_start[ii]);
2392 XDELETEVEC (array_ops[ii]);
2393 XDELETEVEC (array_vector[ii]);
2394 }
2395
2396 XDELETEVEC (count_down);
2397 XDELETEVEC (array_value);
2398 XDELETEVEC (array_stride);
2399 XDELETEVEC (array_length);
2400 XDELETEVEC (array_start);
2401 XDELETEVEC (array_ops);
2402 XDELETEVEC (array_vector);
2403
2404 arg.value = loop_with_init;
2405 return arg;
2406 }
2407
2408 /* Returns true if EXPR or any of its subtrees contain ARRAY_NOTATION_EXPR
2409 node. */
2410
2411 bool
2412 contains_array_notation_expr (tree expr)
2413 {
2414 vec<tree, va_gc> *array_list = NULL;
2415
2416 if (!expr)
2417 return false;
2418 if (TREE_CODE (expr) == FUNCTION_DECL)
2419 if (is_cilkplus_reduce_builtin (expr))
2420 return true;
2421
2422 extract_array_notation_exprs (expr, false, &array_list);
2423 if (vec_safe_length (array_list) == 0)
2424 return false;
2425 else
2426 return true;
2427 }
2428
2429 /* Replaces array notations in a void function call arguments in ARG and returns
2430 a STATEMENT_LIST. */
2431
2432 static tree
2433 fix_array_notation_call_expr (tree arg)
2434 {
2435 vec<tree, va_gc> *array_list = NULL, *array_operand = NULL;
2436 tree new_var = NULL_TREE;
2437 size_t list_size = 0, rank = 0, ii = 0, jj = 0;
2438 int s_jj = 0;
2439 tree **array_ops, *array_var, jj_tree, loop_init;
2440 tree **array_value, **array_stride, **array_length, **array_start;
2441 tree body, loop_with_init = alloc_stmt_list ();
2442 tree *compare_expr, *expr_incr, *ind_init;
2443 bool **count_down, **array_vector;
2444 tree begin_var, lngth_var, strde_var;
2445 location_t location = UNKNOWN_LOCATION;
2446
2447 if (TREE_CODE (arg) == CALL_EXPR
2448 && is_cilkplus_reduce_builtin (CALL_EXPR_FN (arg)))
2449 {
2450 loop_init = fix_builtin_array_notation_fn (arg, &new_var);
2451 /* We are ignoring the new var because either the user does not want to
2452 capture it OR he is using sec_reduce_mutating function. */
2453 return loop_init;
2454 }
2455
2456 if (!find_rank (location, arg, arg, false, &rank))
2457 return error_mark_node;
2458
2459 if (rank == 0)
2460 return arg;
2461
2462 extract_array_notation_exprs (arg, true, &array_list);
2463 if (vec_safe_length (array_list) == 0)
2464 return arg;
2465
2466 list_size = vec_safe_length (array_list);
2467 location = EXPR_LOCATION (arg);
2468
2469 array_ops = XNEWVEC (tree *, list_size);
2470 for (ii = 0; ii < list_size; ii++)
2471 array_ops[ii] = XNEWVEC (tree, rank);
2472
2473 array_vector = XNEWVEC (bool *, list_size);
2474 for (ii = 0; ii < list_size; ii++)
2475 array_vector[ii] = (bool *) XNEWVEC (bool, rank);
2476
2477 array_value = XNEWVEC (tree *, list_size);
2478 array_stride = XNEWVEC (tree *, list_size);
2479 array_length = XNEWVEC (tree *, list_size);
2480 array_start = XNEWVEC (tree *, list_size);
2481
2482 for (ii = 0; ii < list_size; ii++)
2483 {
2484 array_value[ii] = XNEWVEC (tree, rank);
2485 array_stride[ii] = XNEWVEC (tree, rank);
2486 array_length[ii] = XNEWVEC (tree, rank);
2487 array_start[ii] = XNEWVEC (tree, rank);
2488 }
2489
2490 compare_expr = XNEWVEC (tree, rank);
2491 expr_incr = XNEWVEC (tree, rank);
2492 ind_init = XNEWVEC (tree, rank);
2493
2494 count_down = XNEWVEC (bool *, list_size);
2495 for (ii = 0; ii < list_size; ii++)
2496 count_down[ii] = XNEWVEC (bool, rank);
2497
2498 array_var = XNEWVEC (tree, rank);
2499
2500 loop_init = push_stmt_list ();
2501 for (ii = 0; ii < list_size; ii++)
2502 {
2503 tree array_node = (*array_list)[ii];
2504 if (array_node && TREE_CODE (array_node) == ARRAY_NOTATION_REF)
2505 {
2506 tree array_begin = ARRAY_NOTATION_START (array_node);
2507 tree array_lngth = ARRAY_NOTATION_LENGTH (array_node);
2508 tree array_strde = ARRAY_NOTATION_STRIDE (array_node);
2509
2510 if (TREE_CODE (array_begin) != INTEGER_CST)
2511 {
2512 begin_var = build_decl (location, VAR_DECL, NULL_TREE,
2513 integer_type_node);
2514 add_stmt (build_modify_expr (location, begin_var,
2515 TREE_TYPE (begin_var),
2516 NOP_EXPR, location, array_begin,
2517 TREE_TYPE (array_begin)));
2518 ARRAY_NOTATION_START (array_node) = begin_var;
2519 }
2520 if (TREE_CODE (array_lngth) != INTEGER_CST)
2521 {
2522 lngth_var = build_decl (location, VAR_DECL, NULL_TREE,
2523 integer_type_node);
2524 add_stmt (build_modify_expr (location, lngth_var,
2525 TREE_TYPE (lngth_var),
2526 NOP_EXPR, location, array_lngth,
2527 TREE_TYPE (array_lngth)));
2528 ARRAY_NOTATION_LENGTH (array_node) = lngth_var;
2529 }
2530 if (TREE_CODE (array_strde) != INTEGER_CST)
2531 {
2532 strde_var = build_decl (location, VAR_DECL, NULL_TREE,
2533 integer_type_node);
2534 add_stmt (build_modify_expr (location, strde_var,
2535 TREE_TYPE (strde_var),
2536 NOP_EXPR, location, array_strde,
2537 TREE_TYPE (array_strde)));
2538 ARRAY_NOTATION_STRIDE (array_node) = strde_var;
2539 }
2540 }
2541 }
2542 for (ii = 0; ii < list_size; ii++)
2543 {
2544 jj = 0;
2545 for (jj_tree = (*array_list)[ii];
2546 jj_tree && TREE_CODE (jj_tree) == ARRAY_NOTATION_REF;
2547 jj_tree = ARRAY_NOTATION_ARRAY (jj_tree))
2548 {
2549 array_ops[ii][jj] = jj_tree;
2550 jj++;
2551 }
2552 }
2553
2554 for (ii = 0; ii < list_size; ii++)
2555 {
2556 tree array_node = (*array_list)[ii];
2557 if (TREE_CODE (array_node) == ARRAY_NOTATION_REF)
2558 {
2559 for (jj = 0; jj < rank; jj++)
2560 {
2561 if (TREE_CODE (array_ops[ii][jj]) == ARRAY_NOTATION_REF)
2562 {
2563 array_value[ii][jj] =
2564 ARRAY_NOTATION_ARRAY (array_ops[ii][jj]);
2565 array_start[ii][jj] =
2566 ARRAY_NOTATION_START (array_ops[ii][jj]);
2567 array_length[ii][jj] =
2568 fold_build1 (CONVERT_EXPR, integer_type_node,
2569 ARRAY_NOTATION_LENGTH (array_ops[ii][jj]));
2570 array_stride[ii][jj] =
2571 fold_build1 (CONVERT_EXPR, integer_type_node,
2572 ARRAY_NOTATION_STRIDE (array_ops[ii][jj]));
2573 array_vector[ii][jj] = true;
2574
2575 if (!TREE_CONSTANT (array_length[ii][jj]))
2576 count_down[ii][jj] = false;
2577 else if (tree_int_cst_lt
2578 (array_length[ii][jj],
2579 build_int_cst (TREE_TYPE (array_length[ii][jj]),
2580 0)))
2581 count_down[ii][jj] = true;
2582 else
2583 count_down[ii][jj] = false;
2584 }
2585 else
2586 array_vector[ii][jj] = false;
2587 }
2588 }
2589 }
2590
2591 if (length_mismatch_in_expr_p (location, array_length, list_size, rank))
2592 {
2593 pop_stmt_list (loop_init);
2594 return error_mark_node;
2595 }
2596
2597 for (ii = 0; ii < rank; ii++)
2598 {
2599 array_var[ii] = build_decl (location, VAR_DECL, NULL_TREE,
2600 integer_type_node);
2601 ind_init[ii] =
2602 build_modify_expr (location, array_var[ii],
2603 TREE_TYPE (array_var[ii]), NOP_EXPR,
2604 location,
2605 build_int_cst (TREE_TYPE (array_var[ii]), 0),
2606 TREE_TYPE (array_var[ii]));
2607
2608 }
2609 for (ii = 0; ii < list_size; ii++)
2610 {
2611 if (array_vector[ii][0])
2612 {
2613 tree array_opr_node = array_value[ii][rank - 1];
2614 for (s_jj = rank - 1; s_jj >= 0; s_jj--)
2615 {
2616 if (count_down[ii][s_jj])
2617 /* Array[start_index - (induction_var * stride)] */
2618 array_opr_node = build_array_ref
2619 (location, array_opr_node,
2620 build2 (MINUS_EXPR, TREE_TYPE (array_var[s_jj]),
2621 array_start[ii][s_jj],
2622 build2 (MULT_EXPR, TREE_TYPE (array_var[s_jj]),
2623 array_var[s_jj], array_stride[ii][s_jj])));
2624 else
2625 /* Array[start_index + (induction_var * stride)] */
2626 array_opr_node = build_array_ref
2627 (location, array_opr_node,
2628 build2 (PLUS_EXPR, TREE_TYPE (array_var[s_jj]),
2629 array_start[ii][s_jj],
2630 build2 (MULT_EXPR, TREE_TYPE (array_var[s_jj]),
2631 array_var[s_jj], array_stride[ii][s_jj])));
2632 }
2633 vec_safe_push (array_operand, array_opr_node);
2634 }
2635 else
2636 /* This is just a dummy node to make sure the list sizes for both
2637 array list and array operand list are the same. */
2638 vec_safe_push (array_operand, integer_one_node);
2639 }
2640 replace_array_notations (&arg, true, array_list, array_operand);
2641 for (ii = 0; ii < rank; ii++)
2642 expr_incr[ii] =
2643 build2 (MODIFY_EXPR, void_type_node, array_var[ii],
2644 build2 (PLUS_EXPR, TREE_TYPE (array_var[ii]), array_var[ii],
2645 build_int_cst (TREE_TYPE (array_var[ii]), 1)));
2646
2647 for (jj = 0; jj < rank; jj++)
2648 {
2649 if (rank && expr_incr[jj])
2650 {
2651 if (count_down[0][jj])
2652 compare_expr[jj] =
2653 build2 (LT_EXPR, boolean_type_node, array_var[jj],
2654 build2 (MULT_EXPR, TREE_TYPE (array_var[jj]),
2655 array_length[0][jj],
2656 build_int_cst (TREE_TYPE (array_var[jj]), -1)));
2657 else
2658 compare_expr[jj] = build2 (LT_EXPR, boolean_type_node,
2659 array_var[jj], array_length[0][jj]);
2660 }
2661 }
2662
2663 loop_init = pop_stmt_list (loop_init);
2664 append_to_statement_list_force (loop_init, &loop_with_init);
2665 body = arg;
2666 for (ii = 0; ii < rank; ii++)
2667 {
2668 tree new_loop = push_stmt_list ();
2669 add_stmt (ind_init[ii]);
2670 c_finish_loop (location, compare_expr[ii], expr_incr[ii], body, NULL_TREE,
2671 NULL_TREE, true);
2672 body = pop_stmt_list (new_loop);
2673 }
2674 append_to_statement_list_force (body, &loop_with_init);
2675 XDELETEVEC (compare_expr);
2676 XDELETEVEC (expr_incr);
2677 XDELETEVEC (ind_init);
2678 XDELETEVEC (array_var);
2679
2680 for (ii = 0; ii < list_size; ii++)
2681 {
2682 XDELETEVEC (count_down[ii]);
2683 XDELETEVEC (array_value[ii]);
2684 XDELETEVEC (array_stride[ii]);
2685 XDELETEVEC (array_length[ii]);
2686 XDELETEVEC (array_start[ii]);
2687 XDELETEVEC (array_ops[ii]);
2688 XDELETEVEC (array_vector[ii]);
2689 }
2690
2691 XDELETEVEC (count_down);
2692 XDELETEVEC (array_value);
2693 XDELETEVEC (array_stride);
2694 XDELETEVEC (array_length);
2695 XDELETEVEC (array_start);
2696 XDELETEVEC (array_ops);
2697 XDELETEVEC (array_vector);
2698
2699 return loop_with_init;
2700 }
2701
2702 /* Expands the built-in functions in a return. EXPR is a RETURN_EXPR with
2703 a built-in reduction function. This function returns the expansion code for
2704 the built-in function. */
2705
2706 static tree
2707 fix_return_expr (tree expr)
2708 {
2709 tree new_mod_list, new_var, new_mod, retval_expr, retval_type;
2710 location_t loc = EXPR_LOCATION (expr);
2711
2712 new_mod_list = alloc_stmt_list ();
2713 retval_expr = TREE_OPERAND (expr, 0);
2714 retval_type = TREE_TYPE (TREE_OPERAND (retval_expr, 1));
2715 new_var = build_decl (loc, VAR_DECL, NULL_TREE, TREE_TYPE (retval_expr));
2716 new_mod = build_array_notation_expr (loc, new_var, TREE_TYPE (new_var),
2717 NOP_EXPR, loc,
2718 TREE_OPERAND (retval_expr, 1),
2719 retval_type);
2720 TREE_OPERAND (retval_expr, 1) = new_var;
2721 TREE_OPERAND (expr, 0) = retval_expr;
2722 append_to_statement_list_force (new_mod, &new_mod_list);
2723 append_to_statement_list_force (expr, &new_mod_list);
2724 return new_mod_list;
2725 }
2726
2727 /* Walks through tree node T and find all the call-statements that do not return
2728 anything and fix up any array notations they may carry. The return value
2729 is the same type as T but with all array notations replaced with appropriate
2730 STATEMENT_LISTS. */
2731
2732 tree
2733 expand_array_notation_exprs (tree t)
2734 {
2735 if (!contains_array_notation_expr (t))
2736 return t;
2737
2738 switch (TREE_CODE (t))
2739 {
2740 case BIND_EXPR:
2741 t = expand_array_notation_exprs (BIND_EXPR_BODY (t));
2742 return t;
2743 case COND_EXPR:
2744 t = fix_conditional_array_notations (t);
2745
2746 /* After the expansion if they are still a COND_EXPR, we go into its
2747 subtrees. */
2748 if (TREE_CODE (t) == COND_EXPR)
2749 {
2750 if (COND_EXPR_THEN (t))
2751 COND_EXPR_THEN (t) =
2752 expand_array_notation_exprs (COND_EXPR_THEN (t));
2753 if (COND_EXPR_ELSE (t))
2754 COND_EXPR_ELSE (t) =
2755 expand_array_notation_exprs (COND_EXPR_ELSE (t));
2756 }
2757 else
2758 t = expand_array_notation_exprs (t);
2759 return t;
2760 case STATEMENT_LIST:
2761 {
2762 tree_stmt_iterator ii_tsi;
2763 for (ii_tsi = tsi_start (t); !tsi_end_p (ii_tsi); tsi_next (&ii_tsi))
2764 *tsi_stmt_ptr (ii_tsi) =
2765 expand_array_notation_exprs (*tsi_stmt_ptr (ii_tsi));
2766 }
2767 return t;
2768 case CALL_EXPR:
2769 t = fix_array_notation_call_expr (t);
2770 return t;
2771 case RETURN_EXPR:
2772 if (contains_array_notation_expr (t))
2773 t = fix_return_expr (t);
2774 default:
2775 return t;
2776 }
2777 return t;
2778 }
2779
2780 /* This handles expression of the form "a[i:j:k]" or "a[:]" or "a[i:j]," which
2781 denotes an array notation expression. If a is a variable or a member, then
2782 we generate a ARRAY_NOTATION_REF front-end tree and return it.
2783 This tree is broken down to ARRAY_REF toward the end of parsing.
2784 ARRAY_NOTATION_REF tree holds the START_INDEX, LENGTH, STRIDE and the TYPE
2785 of ARRAY_REF. Restrictions on START_INDEX, LENGTH and STRIDE is same as that
2786 of the index field passed into ARRAY_REF. The only additional restriction
2787 is that, unlike index in ARRAY_REF, stride, length and start_index cannot
2788 contain ARRAY_NOTATIONS. */
2789
2790 tree
2791 build_array_notation_ref (location_t loc, tree array, tree start_index,
2792 tree length, tree stride, tree type)
2793 {
2794 tree array_ntn_tree = NULL_TREE;
2795 size_t stride_rank = 0, length_rank = 0, start_rank = 0;
2796
2797 if (!INTEGRAL_TYPE_P (TREE_TYPE (start_index)))
2798 {
2799 error_at (loc,
2800 "start-index of array notation triplet is not an integer");
2801 return error_mark_node;
2802 }
2803 if (!INTEGRAL_TYPE_P (TREE_TYPE (length)))
2804 {
2805 error_at (loc, "length of array notation triplet is not an integer");
2806 return error_mark_node;
2807 }
2808
2809 /* The stride is an optional field. */
2810 if (stride && !INTEGRAL_TYPE_P (TREE_TYPE (stride)))
2811 {
2812 error_at (loc, "stride of array notation triplet is not an integer");
2813 return error_mark_node;
2814 }
2815 if (!stride)
2816 {
2817 if (TREE_CONSTANT (start_index) && TREE_CONSTANT (length)
2818 && tree_int_cst_lt (length, start_index))
2819 stride = build_int_cst (TREE_TYPE (start_index), -1);
2820 else
2821 stride = build_int_cst (TREE_TYPE (start_index), 1);
2822 }
2823
2824 if (!find_rank (loc, start_index, start_index, false, &start_rank))
2825 return error_mark_node;
2826 if (!find_rank (loc, length, length, false, &length_rank))
2827 return error_mark_node;
2828 if (!find_rank (loc, stride, stride, false, &stride_rank))
2829 return error_mark_node;
2830
2831 if (start_rank != 0)
2832 {
2833 error_at (loc, "rank of an array notation triplet's start-index is not "
2834 "zero");
2835 return error_mark_node;
2836 }
2837 if (length_rank != 0)
2838 {
2839 error_at (loc, "rank of an array notation triplet's length is not zero");
2840 return error_mark_node;
2841 }
2842 if (stride_rank != 0)
2843 {
2844 error_at (loc, "rank of array notation triplet's stride is not zero");
2845 return error_mark_node;
2846 }
2847 array_ntn_tree = build4 (ARRAY_NOTATION_REF, NULL_TREE, NULL_TREE, NULL_TREE,
2848 NULL_TREE, NULL_TREE);
2849 ARRAY_NOTATION_ARRAY (array_ntn_tree) = array;
2850 ARRAY_NOTATION_START (array_ntn_tree) = start_index;
2851 ARRAY_NOTATION_LENGTH (array_ntn_tree) = length;
2852 ARRAY_NOTATION_STRIDE (array_ntn_tree) = stride;
2853 TREE_TYPE (array_ntn_tree) = type;
2854
2855 return array_ntn_tree;
2856 }
2857
2858 /* This function will check if OP is a CALL_EXPR that is a built-in array
2859 notation function. If so, then we will return its type to be the type of
2860 the array notation inside. */
2861
2862 tree
2863 find_correct_array_notation_type (tree op)
2864 {
2865 tree fn_arg, return_type = NULL_TREE;
2866
2867 if (op)
2868 {
2869 return_type = TREE_TYPE (op); /* This is the default case. */
2870 if (TREE_CODE (op) == CALL_EXPR)
2871 if (is_cilkplus_reduce_builtin (CALL_EXPR_FN (op)))
2872 {
2873 fn_arg = CALL_EXPR_ARG (op, 0);
2874 if (fn_arg)
2875 return_type = TREE_TYPE (fn_arg);
2876 }
2877 }
2878 return return_type;
2879 }