Moved array notation helper functions from c/ to c-family/ files.
[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 /* Replaces all the scalar expressions in *NODE. Returns a STATEMENT_LIST that
78 holds the NODE along with variables that holds the results of the invariant
79 expressions. */
80
81 tree
82 replace_invariant_exprs (tree *node)
83 {
84 size_t ix = 0;
85 tree node_list = NULL_TREE;
86 tree t = NULL_TREE, new_var = NULL_TREE, new_node;
87 struct inv_list data;
88
89 data.list_values = NULL;
90 data.replacement = NULL;
91 data.additional_tcodes = NULL;
92 walk_tree (node, find_inv_trees, (void *)&data, NULL);
93
94 if (vec_safe_length (data.list_values))
95 {
96 node_list = push_stmt_list ();
97 for (ix = 0; vec_safe_iterate (data.list_values, ix, &t); ix++)
98 {
99 new_var = build_decl (EXPR_LOCATION (t), VAR_DECL, NULL_TREE,
100 TREE_TYPE (t));
101 gcc_assert (new_var != NULL_TREE && new_var != error_mark_node);
102 new_node = build2 (MODIFY_EXPR, TREE_TYPE (t), new_var, t);
103 add_stmt (new_node);
104 vec_safe_push (data.replacement, new_var);
105 }
106 walk_tree (node, replace_inv_trees, (void *)&data, NULL);
107 node_list = pop_stmt_list (node_list);
108 }
109 return node_list;
110 }
111
112 /* Given a CALL_EXPR to an array notation built-in function in
113 AN_BUILTIN_FN, replace the call with the appropriate loop and
114 computation. Return the computation in *NEW_VAR.
115
116 The return value in *NEW_VAR will always be a scalar. If the
117 built-in is __sec_reduce_mutating, *NEW_VAR is set to NULL_TREE. */
118
119 static tree
120 fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var)
121 {
122 tree new_var_type = NULL_TREE, func_parm, new_expr, new_yes_expr, new_no_expr;
123 tree array_ind_value = NULL_TREE, new_no_ind, new_yes_ind, new_no_list;
124 tree new_yes_list, new_cond_expr, new_var_init = NULL_TREE;
125 tree new_exp_init = NULL_TREE;
126 vec<tree, va_gc> *array_list = NULL, *array_operand = NULL;
127 size_t list_size = 0, rank = 0, ii = 0, jj = 0;
128 int s_jj = 0;
129 tree **array_ops, *array_var, jj_tree, loop_init, array_op0;
130 tree **array_value, **array_stride, **array_length, **array_start;
131 tree *compare_expr, *expr_incr, *ind_init;
132 tree identity_value = NULL_TREE, call_fn = NULL_TREE, new_call_expr, body;
133 bool **count_down, **array_vector;
134 location_t location = UNKNOWN_LOCATION;
135 tree loop_with_init = alloc_stmt_list ();
136
137 enum built_in_function an_type =
138 is_cilkplus_reduce_builtin (CALL_EXPR_FN (an_builtin_fn));
139 if (an_type == BUILT_IN_NONE)
140 return NULL_TREE;
141
142 if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE
143 || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING)
144 {
145 call_fn = CALL_EXPR_ARG (an_builtin_fn, 2);
146 while (TREE_CODE (call_fn) == CONVERT_EXPR
147 || TREE_CODE (call_fn) == NOP_EXPR)
148 call_fn = TREE_OPERAND (call_fn, 0);
149 call_fn = TREE_OPERAND (call_fn, 0);
150
151 identity_value = CALL_EXPR_ARG (an_builtin_fn, 0);
152 while (TREE_CODE (identity_value) == CONVERT_EXPR
153 || TREE_CODE (identity_value) == NOP_EXPR)
154 identity_value = TREE_OPERAND (identity_value, 0);
155 func_parm = CALL_EXPR_ARG (an_builtin_fn, 1);
156 }
157 else
158 func_parm = CALL_EXPR_ARG (an_builtin_fn, 0);
159
160 while (TREE_CODE (func_parm) == CONVERT_EXPR
161 || TREE_CODE (func_parm) == EXCESS_PRECISION_EXPR
162 || TREE_CODE (func_parm) == NOP_EXPR)
163 func_parm = TREE_OPERAND (func_parm, 0);
164
165 location = EXPR_LOCATION (an_builtin_fn);
166
167 if (!find_rank (location, an_builtin_fn, an_builtin_fn, true, &rank))
168 return error_mark_node;
169
170 if (rank == 0)
171 return an_builtin_fn;
172 else if (rank > 1
173 && (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
174 || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND))
175 {
176 error_at (location, "__sec_reduce_min_ind or __sec_reduce_max_ind cannot"
177 " have arrays with dimension greater than 1");
178 return error_mark_node;
179 }
180
181 extract_array_notation_exprs (func_parm, true, &array_list);
182 list_size = vec_safe_length (array_list);
183 switch (an_type)
184 {
185 case BUILT_IN_CILKPLUS_SEC_REDUCE_ADD:
186 case BUILT_IN_CILKPLUS_SEC_REDUCE_MUL:
187 case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX:
188 case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN:
189 new_var_type = TREE_TYPE ((*array_list)[0]);
190 break;
191 case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_ZERO:
192 case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_NONZERO:
193 case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO:
194 case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_NONZERO:
195 new_var_type = integer_type_node;
196 break;
197 case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND:
198 case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND:
199 new_var_type = integer_type_node;
200 break;
201 case BUILT_IN_CILKPLUS_SEC_REDUCE:
202 if (call_fn && identity_value)
203 new_var_type = TREE_TYPE ((*array_list)[0]);
204 break;
205 case BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING:
206 new_var_type = NULL_TREE;
207 break;
208 default:
209 gcc_unreachable ();
210 }
211
212 array_ops = XNEWVEC (tree *, list_size);
213 for (ii = 0; ii < list_size; ii++)
214 array_ops[ii] = XNEWVEC (tree, rank);
215
216 array_vector = XNEWVEC (bool *, list_size);
217 for (ii = 0; ii < list_size; ii++)
218 array_vector[ii] = XNEWVEC (bool, rank);
219
220 array_value = XNEWVEC (tree *, list_size);
221 array_stride = XNEWVEC (tree *, list_size);
222 array_length = XNEWVEC (tree *, list_size);
223 array_start = XNEWVEC (tree *, list_size);
224
225 for (ii = 0; ii < list_size; ii++)
226 {
227 array_value[ii] = XNEWVEC (tree, rank);
228 array_stride[ii] = XNEWVEC (tree, rank);
229 array_length[ii] = XNEWVEC (tree, rank);
230 array_start[ii] = XNEWVEC (tree, rank);
231 }
232
233 compare_expr = XNEWVEC (tree, rank);
234 expr_incr = XNEWVEC (tree, rank);
235 ind_init = XNEWVEC (tree, rank);
236
237 count_down = XNEWVEC (bool *, list_size);
238 for (ii = 0; ii < list_size; ii++)
239 count_down[ii] = XNEWVEC (bool, rank);
240
241 array_var = XNEWVEC (tree, rank);
242
243 for (ii = 0; ii < list_size; ii++)
244 {
245 jj = 0;
246 for (jj_tree = (*array_list)[ii];
247 jj_tree && TREE_CODE (jj_tree) == ARRAY_NOTATION_REF;
248 jj_tree = ARRAY_NOTATION_ARRAY (jj_tree))
249 {
250 array_ops[ii][jj] = jj_tree;
251 jj++;
252 }
253 }
254
255 for (ii = 0; ii < list_size; ii++)
256 {
257 tree array_node = (*array_list)[ii];
258 if (TREE_CODE (array_node) == ARRAY_NOTATION_REF)
259 {
260 for (jj = 0; jj < rank; jj++)
261 {
262 if (TREE_CODE (array_ops[ii][jj]) == ARRAY_NOTATION_REF)
263 {
264 array_value[ii][jj] =
265 ARRAY_NOTATION_ARRAY (array_ops[ii][jj]);
266 array_start[ii][jj] =
267 ARRAY_NOTATION_START (array_ops[ii][jj]);
268 array_length[ii][jj] =
269 fold_build1 (CONVERT_EXPR, integer_type_node,
270 ARRAY_NOTATION_LENGTH (array_ops[ii][jj]));
271 array_stride[ii][jj] =
272 fold_build1 (CONVERT_EXPR, integer_type_node,
273 ARRAY_NOTATION_STRIDE (array_ops[ii][jj]));
274 array_vector[ii][jj] = true;
275
276 if (!TREE_CONSTANT (array_length[ii][jj]))
277 count_down[ii][jj] = false;
278 else if (tree_int_cst_lt
279 (array_length[ii][jj],
280 build_int_cst (TREE_TYPE (array_length[ii][jj]),
281 0)))
282 count_down[ii][jj] = true;
283 else
284 count_down[ii][jj] = false;
285 }
286 else
287 array_vector[ii][jj] = false;
288 }
289 }
290 }
291
292 loop_init = alloc_stmt_list ();
293
294 for (ii = 0; ii < rank; ii++)
295 {
296 array_var[ii] = build_decl (location, VAR_DECL, NULL_TREE,
297 integer_type_node);
298 ind_init[ii] =
299 build_modify_expr (location, array_var[ii],
300 TREE_TYPE (array_var[ii]), NOP_EXPR,
301 location,
302 build_int_cst (TREE_TYPE (array_var[ii]), 0),
303 TREE_TYPE (array_var[ii]));
304 }
305 for (ii = 0; ii < list_size; ii++)
306 {
307 if (array_vector[ii][0])
308 {
309 tree array_opr_node = array_value[ii][rank - 1];
310 for (s_jj = rank - 1; s_jj >= 0; s_jj--)
311 {
312 if (count_down[ii][s_jj])
313 {
314 /* Array[start_index - (induction_var * stride)] */
315 array_opr_node = build_array_ref
316 (location, array_opr_node,
317 build2 (MINUS_EXPR, TREE_TYPE (array_var[s_jj]),
318 array_start[ii][s_jj],
319 build2 (MULT_EXPR, TREE_TYPE (array_var[s_jj]),
320 array_var[s_jj], array_stride[ii][s_jj])));
321 }
322 else
323 {
324 /* Array[start_index + (induction_var * stride)] */
325 array_opr_node = build_array_ref
326 (location, array_opr_node,
327 build2 (PLUS_EXPR, TREE_TYPE (array_var[s_jj]),
328 array_start[ii][s_jj],
329 build2 (MULT_EXPR, TREE_TYPE (array_var[s_jj]),
330 array_var[s_jj], array_stride[ii][s_jj])));
331 }
332 }
333 vec_safe_push (array_operand, array_opr_node);
334 }
335 else
336 /* This is just a dummy node to make sure the list sizes for both
337 array list and array operand list are the same. */
338 vec_safe_push (array_operand, integer_one_node);
339 }
340 replace_array_notations (&func_parm, true, array_list, array_operand);
341 for (ii = 0; ii < rank; ii++)
342 expr_incr[ii] =
343 build2 (MODIFY_EXPR, void_type_node, array_var[ii],
344 build2 (PLUS_EXPR, TREE_TYPE (array_var[ii]), array_var[ii],
345 build_int_cst (TREE_TYPE (array_var[ii]), 1)));
346 for (jj = 0; jj < rank; jj++)
347 {
348 if (rank && expr_incr[jj])
349 {
350 if (count_down[0][jj])
351 compare_expr[jj] =
352 build2 (LT_EXPR, boolean_type_node, array_var[jj],
353 build2 (MULT_EXPR, TREE_TYPE (array_var[jj]),
354 array_length[0][jj],
355 build_int_cst (TREE_TYPE (array_var[jj]), -1)));
356 else
357 compare_expr[jj] = build2 (LT_EXPR, boolean_type_node,
358 array_var[jj], array_length[0][jj]);
359 }
360 }
361
362 if (an_type != BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING)
363 {
364 *new_var = build_decl (location, VAR_DECL, NULL_TREE, new_var_type);
365 gcc_assert (*new_var && *new_var != error_mark_node);
366 }
367 else
368 *new_var = NULL_TREE;
369
370 if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
371 || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND)
372 array_ind_value = build_decl (location, VAR_DECL, NULL_TREE,
373 TREE_TYPE (func_parm));
374 array_op0 = (*array_operand)[0];
375 switch (an_type)
376 {
377 case BUILT_IN_CILKPLUS_SEC_REDUCE_ADD:
378 new_var_init = build_modify_expr
379 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
380 location, build_zero_cst (new_var_type), new_var_type);
381 new_expr = build_modify_expr
382 (location, *new_var, TREE_TYPE (*new_var), PLUS_EXPR,
383 location, func_parm, TREE_TYPE (func_parm));
384 break;
385 case BUILT_IN_CILKPLUS_SEC_REDUCE_MUL:
386 new_var_init = build_modify_expr
387 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
388 location, build_one_cst (new_var_type), new_var_type);
389 new_expr = build_modify_expr
390 (location, *new_var, TREE_TYPE (*new_var), MULT_EXPR,
391 location, func_parm, TREE_TYPE (func_parm));
392 break;
393 case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_ZERO:
394 new_var_init = build_modify_expr
395 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
396 location, build_one_cst (new_var_type), new_var_type);
397 /* Initially you assume everything is zero, now if we find a case where
398 it is NOT true, then we set the result to false. Otherwise
399 we just keep the previous value. */
400 new_yes_expr = build_modify_expr
401 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
402 location, build_zero_cst (TREE_TYPE (*new_var)),
403 TREE_TYPE (*new_var));
404 new_no_expr = build_modify_expr
405 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
406 location, *new_var, TREE_TYPE (*new_var));
407 new_cond_expr = build2 (NE_EXPR, TREE_TYPE (func_parm), func_parm,
408 build_zero_cst (TREE_TYPE (func_parm)));
409 new_expr = build_conditional_expr
410 (location, new_cond_expr, false, new_yes_expr,
411 TREE_TYPE (new_yes_expr), new_no_expr, TREE_TYPE (new_no_expr));
412 break;
413 case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_NONZERO:
414 new_var_init = build_modify_expr
415 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
416 location, build_one_cst (new_var_type), new_var_type);
417 /* Initially you assume everything is non-zero, now if we find a case
418 where it is NOT true, then we set the result to false. Otherwise
419 we just keep the previous value. */
420 new_yes_expr = build_modify_expr
421 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
422 location, build_zero_cst (TREE_TYPE (*new_var)),
423 TREE_TYPE (*new_var));
424 new_no_expr = build_modify_expr
425 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
426 location, *new_var, TREE_TYPE (*new_var));
427 new_cond_expr = build2 (EQ_EXPR, TREE_TYPE (func_parm), func_parm,
428 build_zero_cst (TREE_TYPE (func_parm)));
429 new_expr = build_conditional_expr
430 (location, new_cond_expr, false, new_yes_expr,
431 TREE_TYPE (new_yes_expr), new_no_expr, TREE_TYPE (new_no_expr));
432 break;
433 case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO:
434 new_var_init = build_modify_expr
435 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
436 location, build_zero_cst (new_var_type), new_var_type);
437 /* Initially we assume there are NO zeros in the list. When we find
438 a non-zero, we keep the previous value. If we find a zero, we
439 set the value to true. */
440 new_yes_expr = build_modify_expr
441 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
442 location, build_one_cst (new_var_type), new_var_type);
443 new_no_expr = build_modify_expr
444 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
445 location, *new_var, TREE_TYPE (*new_var));
446 new_cond_expr = build2 (EQ_EXPR, TREE_TYPE (func_parm), func_parm,
447 build_zero_cst (TREE_TYPE (func_parm)));
448 new_expr = build_conditional_expr
449 (location, new_cond_expr, false, new_yes_expr,
450 TREE_TYPE (new_yes_expr), new_no_expr, TREE_TYPE (new_no_expr));
451 break;
452 case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_NONZERO:
453 new_var_init = build_modify_expr
454 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
455 location, build_zero_cst (new_var_type), new_var_type);
456 /* Initially we assume there are NO non-zeros in the list. When we find
457 a zero, we keep the previous value. If we find a non-zero, we set
458 the value to true. */
459 new_yes_expr = build_modify_expr
460 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
461 location, build_one_cst (new_var_type), new_var_type);
462 new_no_expr = build_modify_expr
463 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
464 location, *new_var, TREE_TYPE (*new_var));
465 new_cond_expr = build2 (NE_EXPR, TREE_TYPE (func_parm), func_parm,
466 build_zero_cst (TREE_TYPE (func_parm)));
467 new_expr = build_conditional_expr
468 (location, new_cond_expr, false, new_yes_expr,
469 TREE_TYPE (new_yes_expr), new_no_expr, TREE_TYPE (new_no_expr));
470 break;
471 case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX:
472 if (TYPE_MIN_VALUE (new_var_type))
473 new_var_init = build_modify_expr
474 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
475 location, TYPE_MIN_VALUE (new_var_type), new_var_type);
476 else
477 new_var_init = build_modify_expr
478 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
479 location, func_parm, new_var_type);
480 new_no_expr = build_modify_expr
481 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
482 location, *new_var, TREE_TYPE (*new_var));
483 new_yes_expr = build_modify_expr
484 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
485 location, func_parm, TREE_TYPE (*new_var));
486 new_expr = build_conditional_expr
487 (location,
488 build2 (LT_EXPR, TREE_TYPE (*new_var), *new_var, func_parm), false,
489 new_yes_expr, TREE_TYPE (*new_var), new_no_expr, TREE_TYPE (*new_var));
490 break;
491 case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN:
492 if (TYPE_MAX_VALUE (new_var_type))
493 new_var_init = build_modify_expr
494 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
495 location, TYPE_MAX_VALUE (new_var_type), new_var_type);
496 else
497 new_var_init = build_modify_expr
498 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
499 location, func_parm, new_var_type);
500 new_no_expr = build_modify_expr
501 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
502 location, *new_var, TREE_TYPE (*new_var));
503 new_yes_expr = build_modify_expr
504 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
505 location, func_parm, TREE_TYPE (*new_var));
506 new_expr = build_conditional_expr
507 (location,
508 build2 (GT_EXPR, TREE_TYPE (*new_var), *new_var, func_parm), false,
509 new_yes_expr, TREE_TYPE (*new_var), new_no_expr, TREE_TYPE (*new_var));
510 break;
511 case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND:
512 new_var_init = build_modify_expr
513 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
514 location, build_zero_cst (new_var_type), new_var_type);
515 new_exp_init = build_modify_expr
516 (location, array_ind_value, TREE_TYPE (array_ind_value),
517 NOP_EXPR, location, func_parm, TREE_TYPE (func_parm));
518 new_no_ind = build_modify_expr
519 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
520 location, *new_var, TREE_TYPE (*new_var));
521 new_no_expr = build_modify_expr
522 (location, array_ind_value, TREE_TYPE (array_ind_value),
523 NOP_EXPR,
524 location, array_ind_value, TREE_TYPE (array_ind_value));
525 if (list_size > 1)
526 {
527 new_yes_ind = build_modify_expr
528 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
529 location, array_var[0], TREE_TYPE (array_var[0]));
530 new_yes_expr = build_modify_expr
531 (location, array_ind_value, TREE_TYPE (array_ind_value),
532 NOP_EXPR,
533 location, func_parm, TREE_TYPE ((*array_operand)[0]));
534 }
535 else
536 {
537 new_yes_ind = build_modify_expr
538 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
539 location, TREE_OPERAND (array_op0, 1),
540 TREE_TYPE (TREE_OPERAND (array_op0, 1)));
541 new_yes_expr = build_modify_expr
542 (location, array_ind_value, TREE_TYPE (array_ind_value),
543 NOP_EXPR,
544 location, func_parm, TREE_OPERAND (array_op0, 1));
545 }
546 new_yes_list = alloc_stmt_list ();
547 append_to_statement_list (new_yes_ind, &new_yes_list);
548 append_to_statement_list (new_yes_expr, &new_yes_list);
549
550 new_no_list = alloc_stmt_list ();
551 append_to_statement_list (new_no_ind, &new_no_list);
552 append_to_statement_list (new_no_expr, &new_no_list);
553
554 new_expr = build_conditional_expr
555 (location,
556 build2 (LE_EXPR, TREE_TYPE (array_ind_value), array_ind_value,
557 func_parm),
558 false,
559 new_yes_list, TREE_TYPE (*new_var), new_no_list, TREE_TYPE (*new_var));
560 break;
561 case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND:
562 new_var_init = build_modify_expr
563 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
564 location, build_zero_cst (new_var_type), new_var_type);
565 new_exp_init = build_modify_expr
566 (location, array_ind_value, TREE_TYPE (array_ind_value),
567 NOP_EXPR, location, func_parm, TREE_TYPE (func_parm));
568 new_no_ind = build_modify_expr
569 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
570 location, *new_var, TREE_TYPE (*new_var));
571 new_no_expr = build_modify_expr
572 (location, array_ind_value, TREE_TYPE (array_ind_value),
573 NOP_EXPR,
574 location, array_ind_value, TREE_TYPE (array_ind_value));
575 if (list_size > 1)
576 {
577 new_yes_ind = build_modify_expr
578 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
579 location, array_var[0], TREE_TYPE (array_var[0]));
580 new_yes_expr = build_modify_expr
581 (location, array_ind_value, TREE_TYPE (array_ind_value),
582 NOP_EXPR,
583 location, func_parm, TREE_TYPE (array_op0));
584 }
585 else
586 {
587 new_yes_ind = build_modify_expr
588 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
589 location, TREE_OPERAND (array_op0, 1),
590 TREE_TYPE (TREE_OPERAND (array_op0, 1)));
591 new_yes_expr = build_modify_expr
592 (location, array_ind_value, TREE_TYPE (array_ind_value),
593 NOP_EXPR,
594 location, func_parm, TREE_OPERAND (array_op0, 1));
595 }
596 new_yes_list = alloc_stmt_list ();
597 append_to_statement_list (new_yes_ind, &new_yes_list);
598 append_to_statement_list (new_yes_expr, &new_yes_list);
599
600 new_no_list = alloc_stmt_list ();
601 append_to_statement_list (new_no_ind, &new_no_list);
602 append_to_statement_list (new_no_expr, &new_no_list);
603
604 new_expr = build_conditional_expr
605 (location,
606 build2 (GE_EXPR, TREE_TYPE (array_ind_value), array_ind_value,
607 func_parm),
608 false,
609 new_yes_list, TREE_TYPE (*new_var), new_no_list, TREE_TYPE (*new_var));
610 break;
611 case BUILT_IN_CILKPLUS_SEC_REDUCE:
612 new_var_init = build_modify_expr
613 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
614 location, identity_value, new_var_type);
615 new_call_expr = build_call_expr (call_fn, 2, *new_var, func_parm);
616 new_expr = build_modify_expr
617 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
618 location, new_call_expr, TREE_TYPE (*new_var));
619 break;
620 case BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING:
621 new_expr = build_call_expr (call_fn, 2, identity_value, func_parm);
622 break;
623 default:
624 gcc_unreachable ();
625 break;
626 }
627
628 for (ii = 0; ii < rank; ii++)
629 append_to_statement_list (ind_init [ii], &loop_init);
630
631 if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
632 || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND)
633 append_to_statement_list (new_exp_init, &loop_init);
634 if (an_type != BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING)
635 append_to_statement_list (new_var_init, &loop_init);
636
637 append_to_statement_list_force (loop_init, &loop_with_init);
638 body = new_expr;
639 for (ii = 0; ii < rank; ii++)
640 {
641 tree new_loop = push_stmt_list ();
642 c_finish_loop (location, compare_expr[ii], expr_incr[ii], body, NULL_TREE,
643 NULL_TREE, true);
644 body = pop_stmt_list (new_loop);
645 }
646 append_to_statement_list_force (body, &loop_with_init);
647
648 XDELETEVEC (compare_expr);
649 XDELETEVEC (expr_incr);
650 XDELETEVEC (ind_init);
651 XDELETEVEC (array_var);
652 for (ii = 0; ii < list_size; ii++)
653 {
654 XDELETEVEC (count_down[ii]);
655 XDELETEVEC (array_value[ii]);
656 XDELETEVEC (array_stride[ii]);
657 XDELETEVEC (array_length[ii]);
658 XDELETEVEC (array_start[ii]);
659 XDELETEVEC (array_ops[ii]);
660 XDELETEVEC (array_vector[ii]);
661 }
662 XDELETEVEC (count_down);
663 XDELETEVEC (array_value);
664 XDELETEVEC (array_stride);
665 XDELETEVEC (array_length);
666 XDELETEVEC (array_start);
667 XDELETEVEC (array_ops);
668 XDELETEVEC (array_vector);
669
670 return loop_with_init;
671 }
672
673 /* Returns a loop with ARRAY_REF inside it with an appropriate modify expr.
674 The LHS and/or RHS will be array notation expressions that have a MODIFYCODE
675 Their locations are specified by LHS_LOC, RHS_LOC. The location of the
676 modify expression is location. The original type of LHS and RHS are passed
677 in LHS_ORIGTYPE and RHS_ORIGTYPE. */
678
679 tree
680 build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype,
681 enum tree_code modifycode, location_t rhs_loc,
682 tree rhs, tree rhs_origtype)
683 {
684 bool **lhs_vector = NULL, **rhs_vector = NULL, found_builtin_fn = false;
685 tree **lhs_array = NULL, **rhs_array = NULL;
686 tree array_expr_lhs = NULL_TREE, array_expr_rhs = NULL_TREE;
687 tree array_expr = NULL_TREE;
688 tree **lhs_value = NULL, **rhs_value = NULL;
689 tree **lhs_stride = NULL, **lhs_length = NULL, **lhs_start = NULL;
690 tree **rhs_stride = NULL, **rhs_length = NULL, **rhs_start = NULL;
691 tree an_init = NULL_TREE, *lhs_var = NULL, *rhs_var = NULL;
692 tree *cond_expr = NULL;
693 tree body, loop_with_init = alloc_stmt_list();
694 tree scalar_mods = NULL_TREE;
695 tree *lhs_expr_incr = NULL, *rhs_expr_incr = NULL;
696 tree *lhs_ind_init = NULL, *rhs_ind_init = NULL;
697 bool **lhs_count_down = NULL, **rhs_count_down = NULL;
698 tree *lhs_compare = NULL, *rhs_compare = NULL;
699 vec<tree, va_gc> *rhs_array_operand = NULL, *lhs_array_operand = NULL;
700 size_t lhs_rank = 0, rhs_rank = 0;
701 size_t ii = 0, jj = 0;
702 int s_jj = 0;
703 tree ii_tree = NULL_TREE, new_modify_expr;
704 vec<tree, va_gc> *lhs_list = NULL, *rhs_list = NULL;
705 tree new_var = NULL_TREE, builtin_loop = NULL_TREE;
706 tree begin_var, lngth_var, strde_var;
707 size_t rhs_list_size = 0, lhs_list_size = 0;
708
709 /* If either of this is true, an error message must have been send out
710 already. Not necessary to send out multiple error messages. */
711 if (lhs == error_mark_node || rhs == error_mark_node)
712 return error_mark_node;
713
714 if (!find_rank (location, rhs, rhs, false, &rhs_rank))
715 return error_mark_node;
716
717 extract_array_notation_exprs (rhs, false, &rhs_list);
718 rhs_list_size = vec_safe_length (rhs_list);
719 an_init = push_stmt_list ();
720 if (rhs_rank)
721 {
722 scalar_mods = replace_invariant_exprs (&rhs);
723 if (scalar_mods)
724 add_stmt (scalar_mods);
725 }
726 for (ii = 0; ii < rhs_list_size; ii++)
727 {
728 tree rhs_node = (*rhs_list)[ii];
729 if (TREE_CODE (rhs_node) == CALL_EXPR)
730 {
731 builtin_loop = fix_builtin_array_notation_fn (rhs_node, &new_var);
732 if (builtin_loop == error_mark_node)
733 {
734 pop_stmt_list (an_init);
735 return error_mark_node;
736 }
737 else if (builtin_loop)
738 {
739 add_stmt (builtin_loop);
740 found_builtin_fn = true;
741 if (new_var)
742 {
743 vec<tree, va_gc> *rhs_sub_list = NULL, *new_var_list = NULL;
744 vec_safe_push (rhs_sub_list, rhs_node);
745 vec_safe_push (new_var_list, new_var);
746 replace_array_notations (&rhs, false, rhs_sub_list,
747 new_var_list);
748 }
749 }
750 }
751 }
752
753 lhs_rank = 0;
754 rhs_rank = 0;
755 if (!find_rank (location, lhs, lhs, true, &lhs_rank))
756 {
757 pop_stmt_list (an_init);
758 return error_mark_node;
759 }
760
761 if (!find_rank (location, rhs, rhs, true, &rhs_rank))
762 {
763 pop_stmt_list (an_init);
764 return error_mark_node;
765 }
766
767 if (lhs_rank == 0 && rhs_rank == 0)
768 {
769 if (found_builtin_fn)
770 {
771 new_modify_expr = build_modify_expr (location, lhs, lhs_origtype,
772 modifycode, rhs_loc, rhs,
773 rhs_origtype);
774 add_stmt (new_modify_expr);
775 pop_stmt_list (an_init);
776 return an_init;
777 }
778 else
779 {
780 pop_stmt_list (an_init);
781 return NULL_TREE;
782 }
783 }
784 rhs_list_size = 0;
785 rhs_list = NULL;
786 extract_array_notation_exprs (rhs, true, &rhs_list);
787 extract_array_notation_exprs (lhs, true, &lhs_list);
788 rhs_list_size = vec_safe_length (rhs_list);
789 lhs_list_size = vec_safe_length (lhs_list);
790
791 if (lhs_rank == 0 && rhs_rank != 0 && TREE_CODE (rhs) != CALL_EXPR)
792 {
793 tree rhs_base = rhs;
794 if (TREE_CODE (rhs_base) == ARRAY_NOTATION_REF)
795 {
796 for (ii = 0; ii < (size_t) rhs_rank; ii++)
797 rhs_base = ARRAY_NOTATION_ARRAY (rhs);
798
799 error_at (location, "%qE cannot be scalar when %qE is not", lhs,
800 rhs_base);
801 return error_mark_node;
802 }
803 else
804 {
805 error_at (location, "%qE cannot be scalar when %qE is not", lhs,
806 rhs_base);
807 return error_mark_node;
808 }
809 }
810 if (lhs_rank != 0 && rhs_rank != 0 && lhs_rank != rhs_rank)
811 {
812 tree lhs_base = lhs;
813 tree rhs_base = rhs;
814
815 for (ii = 0; ii < lhs_rank; ii++)
816 lhs_base = ARRAY_NOTATION_ARRAY (lhs_base);
817
818 while (rhs_base && TREE_CODE (rhs_base) != ARRAY_NOTATION_REF)
819 rhs_base = TREE_OPERAND (rhs_base, 0);
820 for (ii = 0; ii < rhs_rank; ii++)
821 rhs_base = ARRAY_NOTATION_ARRAY (rhs_base);
822
823 error_at (location, "rank mismatch between %qE and %qE", lhs, rhs);
824 pop_stmt_list (an_init);
825 return error_mark_node;
826 }
827
828 /* Here we assign the array notation components to variable so that we can
829 satisfy the exec once rule. */
830 for (ii = 0; ii < lhs_list_size; ii++)
831 {
832 tree array_node = (*lhs_list)[ii];
833 tree array_begin = ARRAY_NOTATION_START (array_node);
834 tree array_lngth = ARRAY_NOTATION_LENGTH (array_node);
835 tree array_strde = ARRAY_NOTATION_STRIDE (array_node);
836
837 if (TREE_CODE (array_begin) != INTEGER_CST)
838 {
839 begin_var = build_decl (location, VAR_DECL, NULL_TREE,
840 integer_type_node);
841 add_stmt (build_modify_expr (location, begin_var,
842 TREE_TYPE (begin_var),
843 NOP_EXPR, location, array_begin,
844 TREE_TYPE (array_begin)));
845 ARRAY_NOTATION_START (array_node) = begin_var;
846 }
847
848 if (TREE_CODE (array_lngth) != INTEGER_CST)
849 {
850 lngth_var = build_decl (location, VAR_DECL, NULL_TREE,
851 integer_type_node);
852 add_stmt (build_modify_expr (location, lngth_var,
853 TREE_TYPE (lngth_var),
854 NOP_EXPR, location, array_lngth,
855 TREE_TYPE (array_lngth)));
856 ARRAY_NOTATION_LENGTH (array_node) = lngth_var;
857 }
858 if (TREE_CODE (array_strde) != INTEGER_CST)
859 {
860 strde_var = build_decl (location, VAR_DECL, NULL_TREE,
861 integer_type_node);
862
863 add_stmt (build_modify_expr (location, strde_var,
864 TREE_TYPE (strde_var),
865 NOP_EXPR, location, array_strde,
866 TREE_TYPE (array_strde)));
867 ARRAY_NOTATION_STRIDE (array_node) = strde_var;
868 }
869 }
870 for (ii = 0; ii < rhs_list_size; ii++)
871 {
872 tree array_node = (*rhs_list)[ii];
873 if (array_node && TREE_CODE (array_node) == ARRAY_NOTATION_REF)
874 {
875 tree array_begin = ARRAY_NOTATION_START (array_node);
876 tree array_lngth = ARRAY_NOTATION_LENGTH (array_node);
877 tree array_strde = ARRAY_NOTATION_STRIDE (array_node);
878
879 if (TREE_CODE (array_begin) != INTEGER_CST)
880 {
881 begin_var = build_decl (location, VAR_DECL, NULL_TREE,
882 integer_type_node);
883 add_stmt (build_modify_expr (location, begin_var,
884 TREE_TYPE (begin_var),
885 NOP_EXPR, location, array_begin,
886 TREE_TYPE (array_begin)));
887 ARRAY_NOTATION_START (array_node) = begin_var;
888 }
889 if (TREE_CODE (array_lngth) != INTEGER_CST)
890 {
891 lngth_var = build_decl (location, VAR_DECL, NULL_TREE,
892 integer_type_node);
893 add_stmt (build_modify_expr (location, lngth_var,
894 TREE_TYPE (lngth_var),
895 NOP_EXPR, location, array_lngth,
896 TREE_TYPE (array_lngth)));
897 ARRAY_NOTATION_LENGTH (array_node) = lngth_var;
898 }
899 if (TREE_CODE (array_strde) != INTEGER_CST)
900 {
901 strde_var = build_decl (location, VAR_DECL, NULL_TREE,
902 integer_type_node);
903
904 add_stmt (build_modify_expr (location, strde_var,
905 TREE_TYPE (strde_var),
906 NOP_EXPR, location, array_strde,
907 TREE_TYPE (array_strde)));
908 ARRAY_NOTATION_STRIDE (array_node) = strde_var;
909 }
910 }
911 }
912
913 lhs_vector = XNEWVEC (bool *, lhs_list_size);
914 for (ii = 0; ii < lhs_list_size; ii++)
915 lhs_vector[ii] = XNEWVEC (bool, lhs_rank);
916
917 rhs_vector = XNEWVEC (bool *, rhs_list_size);
918 for (ii = 0; ii < rhs_list_size; ii++)
919 rhs_vector[ii] = XNEWVEC (bool, rhs_rank);
920
921 lhs_array = XNEWVEC (tree *, lhs_list_size);
922 for (ii = 0; ii < lhs_list_size; ii++)
923 lhs_array[ii] = XNEWVEC (tree, lhs_rank);
924
925 rhs_array = XNEWVEC (tree *, rhs_list_size);
926 for (ii = 0; ii < rhs_list_size; ii++)
927 rhs_array[ii] = XNEWVEC (tree, rhs_rank);
928
929 lhs_value = XNEWVEC (tree *, lhs_list_size);
930 for (ii = 0; ii < lhs_list_size; ii++)
931 lhs_value[ii] = XNEWVEC (tree, lhs_rank);
932
933 rhs_value = XNEWVEC (tree *, rhs_list_size);
934 for (ii = 0; ii < rhs_list_size; ii++)
935 rhs_value[ii] = XNEWVEC (tree, rhs_rank);
936
937 lhs_stride = XNEWVEC (tree *, lhs_list_size);
938 for (ii = 0; ii < lhs_list_size; ii++)
939 lhs_stride[ii] = XNEWVEC (tree, lhs_rank);
940
941 rhs_stride = XNEWVEC (tree *, rhs_list_size);
942 for (ii = 0; ii < rhs_list_size; ii++)
943 rhs_stride[ii] = XNEWVEC (tree, rhs_rank);
944
945 lhs_length = XNEWVEC (tree *, lhs_list_size);
946 for (ii = 0; ii < lhs_list_size; ii++)
947 lhs_length[ii] = XNEWVEC (tree, lhs_rank);
948
949 rhs_length = XNEWVEC (tree *, rhs_list_size);
950 for (ii = 0; ii < rhs_list_size; ii++)
951 rhs_length[ii] = XNEWVEC (tree, rhs_rank);
952
953 lhs_start = XNEWVEC (tree *, lhs_list_size);
954 for (ii = 0; ii < lhs_list_size; ii++)
955 lhs_start[ii] = XNEWVEC (tree, lhs_rank);
956
957 rhs_start = XNEWVEC (tree *, rhs_list_size);
958 for (ii = 0; ii < rhs_list_size; ii++)
959 rhs_start[ii] = XNEWVEC (tree, rhs_rank);
960
961 lhs_var = XNEWVEC (tree, lhs_rank);
962 rhs_var = XNEWVEC (tree, rhs_rank);
963 cond_expr = XNEWVEC (tree, MAX (lhs_rank, rhs_rank));
964
965 lhs_expr_incr = XNEWVEC (tree, lhs_rank);
966 rhs_expr_incr =XNEWVEC (tree, rhs_rank);
967
968 lhs_ind_init = XNEWVEC (tree, lhs_rank);
969 rhs_ind_init = XNEWVEC (tree, rhs_rank);
970
971 lhs_count_down = XNEWVEC (bool *, lhs_list_size);
972 for (ii = 0; ii < lhs_list_size; ii++)
973 lhs_count_down[ii] = XNEWVEC (bool, lhs_rank);
974
975 rhs_count_down = XNEWVEC (bool *, rhs_list_size);
976 for (ii = 0; ii < rhs_list_size; ii++)
977 rhs_count_down[ii] = XNEWVEC (bool, rhs_rank);
978
979 lhs_compare = XNEWVEC (tree, lhs_rank);
980 rhs_compare = XNEWVEC (tree, rhs_rank);
981
982 if (lhs_rank)
983 {
984 for (ii = 0; ii < lhs_list_size; ii++)
985 {
986 jj = 0;
987 ii_tree = (*lhs_list)[ii];
988 while (ii_tree)
989 {
990 if (TREE_CODE (ii_tree) == ARRAY_NOTATION_REF)
991 {
992 lhs_array[ii][jj] = ii_tree;
993 jj++;
994 ii_tree = ARRAY_NOTATION_ARRAY (ii_tree);
995 }
996 else if (TREE_CODE (ii_tree) == ARRAY_REF)
997 ii_tree = TREE_OPERAND (ii_tree, 0);
998 else if (TREE_CODE (ii_tree) == VAR_DECL
999 || TREE_CODE (ii_tree) == PARM_DECL)
1000 break;
1001 }
1002 }
1003 }
1004 else
1005 lhs_array[0][0] = NULL_TREE;
1006
1007 if (rhs_rank)
1008 {
1009 for (ii = 0; ii < rhs_list_size; ii++)
1010 {
1011 jj = 0;
1012 ii_tree = (*rhs_list)[ii];
1013 while (ii_tree)
1014 {
1015 if (TREE_CODE (ii_tree) == ARRAY_NOTATION_REF)
1016 {
1017 rhs_array[ii][jj] = ii_tree;
1018 jj++;
1019 ii_tree = ARRAY_NOTATION_ARRAY (ii_tree);
1020 }
1021 else if (TREE_CODE (ii_tree) == ARRAY_REF)
1022 ii_tree = TREE_OPERAND (ii_tree, 0);
1023 else if (TREE_CODE (ii_tree) == VAR_DECL
1024 || TREE_CODE (ii_tree) == PARM_DECL
1025 || TREE_CODE (ii_tree) == CALL_EXPR)
1026 break;
1027 }
1028 }
1029 }
1030
1031 for (ii = 0; ii < lhs_list_size; ii++)
1032 {
1033 tree lhs_node = (*lhs_list)[ii];
1034 if (TREE_CODE (lhs_node) == ARRAY_NOTATION_REF)
1035 {
1036 for (jj = 0; jj < lhs_rank; jj++)
1037 {
1038 if (TREE_CODE (lhs_array[ii][jj]) == ARRAY_NOTATION_REF)
1039 {
1040 lhs_value[ii][jj] = ARRAY_NOTATION_ARRAY (lhs_array[ii][jj]);
1041 lhs_start[ii][jj] = ARRAY_NOTATION_START (lhs_array[ii][jj]);
1042 lhs_length[ii][jj] =
1043 fold_build1 (CONVERT_EXPR, integer_type_node,
1044 ARRAY_NOTATION_LENGTH (lhs_array[ii][jj]));
1045 lhs_stride[ii][jj] =
1046 fold_build1 (CONVERT_EXPR, integer_type_node,
1047 ARRAY_NOTATION_STRIDE (lhs_array[ii][jj]));
1048 lhs_vector[ii][jj] = true;
1049 /* IF the stride value is variable (i.e. not constant) then
1050 assume that the length is positive. */
1051 if (!TREE_CONSTANT (lhs_length[ii][jj]))
1052 lhs_count_down[ii][jj] = false;
1053 else if (tree_int_cst_lt
1054 (lhs_length[ii][jj],
1055 build_zero_cst (TREE_TYPE (lhs_length[ii][jj]))))
1056 lhs_count_down[ii][jj] = true;
1057 else
1058 lhs_count_down[ii][jj] = false;
1059 }
1060 else
1061 lhs_vector[ii][jj] = false;
1062 }
1063 }
1064 }
1065 for (ii = 0; ii < rhs_list_size; ii++)
1066 {
1067 if (TREE_CODE ((*rhs_list)[ii]) == ARRAY_NOTATION_REF)
1068 {
1069 for (jj = 0; jj < rhs_rank; jj++)
1070 {
1071 if (TREE_CODE (rhs_array[ii][jj]) == ARRAY_NOTATION_REF)
1072 {
1073 rhs_value[ii][jj] = ARRAY_NOTATION_ARRAY (rhs_array[ii][jj]);
1074 rhs_start[ii][jj] = ARRAY_NOTATION_START (rhs_array[ii][jj]);
1075 rhs_length[ii][jj] =
1076 fold_build1 (CONVERT_EXPR, integer_type_node,
1077 ARRAY_NOTATION_LENGTH (rhs_array[ii][jj]));
1078 rhs_stride[ii][jj] =
1079 fold_build1 (CONVERT_EXPR, integer_type_node,
1080 ARRAY_NOTATION_STRIDE (rhs_array[ii][jj]));
1081 rhs_vector[ii][jj] = true;
1082 /* If the stride value is variable (i.e. not constant) then
1083 assume that the length is positive. */
1084 if (!TREE_CONSTANT (rhs_length[ii][jj]))
1085 rhs_count_down[ii][jj] = false;
1086 else if (tree_int_cst_lt
1087 (rhs_length[ii][jj],
1088 build_int_cst (TREE_TYPE (rhs_length[ii][jj]), 0)))
1089 rhs_count_down[ii][jj] = true;
1090 else
1091 rhs_count_down[ii][jj] = false;
1092 }
1093 else
1094 rhs_vector[ii][jj] = false;
1095 }
1096 }
1097 else
1098 for (jj = 0; jj < rhs_rank; jj++)
1099 {
1100 rhs_vector[ii][jj] = false;
1101 rhs_length[ii][jj] = NULL_TREE;
1102 }
1103 }
1104
1105 if (length_mismatch_in_expr_p (EXPR_LOCATION (lhs), lhs_length,
1106 lhs_list_size, lhs_rank)
1107 || length_mismatch_in_expr_p (EXPR_LOCATION (rhs), rhs_length,
1108 rhs_list_size, rhs_rank))
1109 {
1110 pop_stmt_list (an_init);
1111 return error_mark_node;
1112 }
1113
1114 if (lhs_list_size > 0 && rhs_list_size > 0 && lhs_rank > 0 && rhs_rank > 0
1115 && TREE_CODE (lhs_length[0][0]) == INTEGER_CST
1116 && rhs_length[0][0]
1117 && TREE_CODE (rhs_length[0][0]) == INTEGER_CST)
1118 {
1119 HOST_WIDE_INT l_length = int_cst_value (lhs_length[0][0]);
1120 HOST_WIDE_INT r_length = int_cst_value (rhs_length[0][0]);
1121 /* Length can be negative or positive. As long as the magnitude is OK,
1122 then the array notation is valid. */
1123 if (absu_hwi (l_length) != absu_hwi (r_length))
1124 {
1125 error_at (location, "length mismatch between LHS and RHS");
1126 pop_stmt_list (an_init);
1127 return error_mark_node;
1128 }
1129 }
1130 for (ii = 0; ii < lhs_rank; ii++)
1131 {
1132 if (lhs_vector[0][ii])
1133 {
1134 lhs_var[ii] = build_decl (location, VAR_DECL, NULL_TREE,
1135 integer_type_node);
1136 lhs_ind_init[ii] = build_modify_expr
1137 (location, lhs_var[ii], TREE_TYPE (lhs_var[ii]),
1138 NOP_EXPR,
1139 location, build_zero_cst (TREE_TYPE (lhs_var[ii])),
1140 TREE_TYPE (lhs_var[ii]));
1141 }
1142 }
1143
1144 for (ii = 0; ii < rhs_rank; ii++)
1145 {
1146 /* When we have a polynomial, we assume that the indices are of type
1147 integer. */
1148 rhs_var[ii] = build_decl (location, VAR_DECL, NULL_TREE,
1149 integer_type_node);
1150 rhs_ind_init[ii] = build_modify_expr
1151 (location, rhs_var[ii], TREE_TYPE (rhs_var[ii]),
1152 NOP_EXPR,
1153 location, build_int_cst (TREE_TYPE (rhs_var[ii]), 0),
1154 TREE_TYPE (rhs_var[ii]));
1155 }
1156 if (lhs_rank)
1157 {
1158 for (ii = 0; ii < lhs_list_size; ii++)
1159 {
1160 if (lhs_vector[ii][0])
1161 {
1162 /* The last ARRAY_NOTATION element's ARRAY component should be
1163 the array's base value. */
1164 tree lhs_array_opr = lhs_value[ii][lhs_rank - 1];
1165 for (s_jj = lhs_rank - 1; s_jj >= 0; s_jj--)
1166 {
1167 if (lhs_count_down[ii][s_jj])
1168 /* Array[start_index + (induction_var * stride)]. */
1169 lhs_array_opr = build_array_ref
1170 (location, lhs_array_opr,
1171 build2 (MINUS_EXPR, TREE_TYPE (lhs_var[s_jj]),
1172 lhs_start[ii][s_jj],
1173 build2 (MULT_EXPR, TREE_TYPE (lhs_var[s_jj]),
1174 lhs_var[s_jj],
1175 lhs_stride[ii][s_jj])));
1176 else
1177 lhs_array_opr = build_array_ref
1178 (location, lhs_array_opr,
1179 build2 (PLUS_EXPR, TREE_TYPE (lhs_var[s_jj]),
1180 lhs_start[ii][s_jj],
1181 build2 (MULT_EXPR, TREE_TYPE (lhs_var[s_jj]),
1182 lhs_var[s_jj],
1183 lhs_stride[ii][s_jj])));
1184 }
1185 vec_safe_push (lhs_array_operand, lhs_array_opr);
1186 }
1187 else
1188 vec_safe_push (lhs_array_operand, integer_one_node);
1189 }
1190 replace_array_notations (&lhs, true, lhs_list, lhs_array_operand);
1191 array_expr_lhs = lhs;
1192 }
1193
1194 if (rhs_rank)
1195 {
1196 for (ii = 0; ii < rhs_list_size; ii++)
1197 {
1198 if (rhs_vector[ii][0])
1199 {
1200 tree rhs_array_opr = rhs_value[ii][rhs_rank - 1];
1201 for (s_jj = rhs_rank - 1; s_jj >= 0; s_jj--)
1202 {
1203 if (rhs_count_down[ii][s_jj])
1204 /* Array[start_index - (induction_var * stride)] */
1205 rhs_array_opr = build_array_ref
1206 (location, rhs_array_opr,
1207 build2 (MINUS_EXPR, TREE_TYPE (rhs_var[s_jj]),
1208 rhs_start[ii][s_jj],
1209 build2 (MULT_EXPR, TREE_TYPE (rhs_var[s_jj]),
1210 rhs_var[s_jj],
1211 rhs_stride[ii][s_jj])));
1212 else
1213 /* Array[start_index + (induction_var * stride)] */
1214 rhs_array_opr = build_array_ref
1215 (location, rhs_array_opr,
1216 build2 (PLUS_EXPR, TREE_TYPE (rhs_var[s_jj]),
1217 rhs_start[ii][s_jj],
1218 build2 (MULT_EXPR, TREE_TYPE (rhs_var[s_jj]),
1219 rhs_var[s_jj],
1220 rhs_stride[ii][s_jj])));
1221 }
1222 vec_safe_push (rhs_array_operand, rhs_array_opr);
1223 }
1224 else
1225 /* This is just a dummy node to make sure the list sizes for both
1226 array list and array operand list are the same. */
1227 vec_safe_push (rhs_array_operand, integer_one_node);
1228 }
1229
1230 for (ii = 0; ii < rhs_list_size; ii++)
1231 {
1232 tree rhs_node = (*rhs_list)[ii];
1233 if (TREE_CODE (rhs_node) == CALL_EXPR)
1234 {
1235 int idx_value = 0;
1236 tree func_name = CALL_EXPR_FN (rhs_node);
1237 if (TREE_CODE (func_name) == ADDR_EXPR)
1238 if (is_sec_implicit_index_fn (func_name))
1239 {
1240 idx_value =
1241 extract_sec_implicit_index_arg (location, rhs_node);
1242 if (idx_value == -1) /* This means we have an error. */
1243 return error_mark_node;
1244 else if (idx_value < (int) lhs_rank && idx_value >= 0)
1245 vec_safe_push (rhs_array_operand, lhs_var[idx_value]);
1246 else
1247 {
1248 size_t ee = 0;
1249 tree lhs_base = (*lhs_list)[ii];
1250 for (ee = 0; ee < lhs_rank; ee++)
1251 lhs_base = ARRAY_NOTATION_ARRAY (lhs_base);
1252 error_at (location, "__sec_implicit_index argument %d "
1253 "must be less than rank of %qD", idx_value,
1254 lhs_base);
1255 return error_mark_node;
1256 }
1257 }
1258 }
1259 }
1260 replace_array_notations (&rhs, true, rhs_list, rhs_array_operand);
1261 array_expr_rhs = rhs;
1262 }
1263 else
1264 {
1265 for (ii = 0; ii < rhs_list_size; ii++)
1266 {
1267 tree rhs_node = (*rhs_list)[ii];
1268 if (TREE_CODE (rhs_node) == CALL_EXPR)
1269 {
1270 int idx_value = 0;
1271 tree func_name = CALL_EXPR_FN (rhs_node);
1272 if (TREE_CODE (func_name) == ADDR_EXPR)
1273 if (is_sec_implicit_index_fn (func_name))
1274 {
1275 idx_value =
1276 extract_sec_implicit_index_arg (location, rhs_node);
1277 if (idx_value == -1) /* This means we have an error. */
1278 return error_mark_node;
1279 else if (idx_value < (int) lhs_rank && idx_value >= 0)
1280 vec_safe_push (rhs_array_operand, lhs_var[idx_value]);
1281 else
1282 {
1283 size_t ee = 0;
1284 tree lhs_base = (*lhs_list)[ii];
1285 for (ee = 0; ee < lhs_rank; ee++)
1286 lhs_base = ARRAY_NOTATION_ARRAY (lhs_base);
1287 error_at (location, "__sec_implicit_index argument %d "
1288 "must be less than rank of %qD", idx_value,
1289 lhs_base);
1290 return error_mark_node;
1291 }
1292 }
1293 }
1294 }
1295 replace_array_notations (&rhs, true, rhs_list, rhs_array_operand);
1296 array_expr_rhs = rhs;
1297 rhs_expr_incr[0] = NULL_TREE;
1298 }
1299
1300 for (ii = 0; ii < rhs_rank; ii++)
1301 rhs_expr_incr[ii] = build2 (MODIFY_EXPR, void_type_node, rhs_var[ii],
1302 build2
1303 (PLUS_EXPR, TREE_TYPE (rhs_var[ii]),
1304 rhs_var[ii],
1305 build_one_cst (TREE_TYPE (rhs_var[ii]))));
1306
1307 for (ii = 0; ii < lhs_rank; ii++)
1308 lhs_expr_incr[ii] = build2
1309 (MODIFY_EXPR, void_type_node, lhs_var[ii],
1310 build2 (PLUS_EXPR, TREE_TYPE (lhs_var[ii]), lhs_var[ii],
1311 build_one_cst (TREE_TYPE (lhs_var[ii]))));
1312
1313 /* If array_expr_lhs is NULL, then we have function that returns void or
1314 its return value is ignored. */
1315 if (!array_expr_lhs)
1316 array_expr_lhs = lhs;
1317
1318 array_expr = build_modify_expr (location, array_expr_lhs, lhs_origtype,
1319 modifycode, rhs_loc, array_expr_rhs,
1320 rhs_origtype);
1321
1322 for (jj = 0; jj < MAX (lhs_rank, rhs_rank); jj++)
1323 {
1324 if (rhs_rank && rhs_expr_incr[jj])
1325 {
1326 size_t iii = 0;
1327 if (lhs_rank == 0)
1328 lhs_compare[jj] = integer_one_node;
1329 else if (lhs_count_down[0][jj])
1330 lhs_compare[jj] = build2
1331 (GT_EXPR, boolean_type_node, lhs_var[jj], lhs_length[0][jj]);
1332 else
1333 lhs_compare[jj] = build2
1334 (LT_EXPR, boolean_type_node, lhs_var[jj], lhs_length[0][jj]);
1335
1336
1337 /* The reason why we have this here is for the following case:
1338 Array[:][:] = function_call(something) + Array2[:][:];
1339
1340 So, we will skip the first operand of RHS and then go to the
1341 2nd to find whether we should count up or down. */
1342
1343 for (iii = 0; iii < rhs_list_size; iii++)
1344 if (rhs_vector[iii][jj])
1345 break;
1346
1347 /* What we are doing here is this:
1348 We always count up, so:
1349 if (length is negative ==> which means we count down)
1350 we multiply length by -1 and count up => ii < -LENGTH
1351 else
1352 we just count up, so we compare for ii < LENGTH
1353 */
1354 if (rhs_count_down[iii][jj])
1355 /* We use iii for rhs_length because that is the correct countdown
1356 we have to use. */
1357 rhs_compare[jj] = build2
1358 (LT_EXPR, boolean_type_node, rhs_var[jj],
1359 build2 (MULT_EXPR, TREE_TYPE (rhs_var[jj]),
1360 rhs_length[iii][jj],
1361 build_int_cst (TREE_TYPE (rhs_var[jj]), -1)));
1362 else
1363 rhs_compare[jj] = build2 (LT_EXPR, boolean_type_node, rhs_var[jj],
1364 rhs_length[iii][jj]);
1365 if (lhs_compare[ii] != integer_one_node)
1366 cond_expr[jj] = build2 (TRUTH_ANDIF_EXPR, void_type_node,
1367 lhs_compare[jj], rhs_compare[jj]);
1368 else
1369 cond_expr[jj] = rhs_compare[jj];
1370 }
1371 else
1372 {
1373 if (lhs_count_down[0][jj])
1374 cond_expr[jj] = build2
1375 (GT_EXPR, boolean_type_node, lhs_var[jj], lhs_length[0][jj]);
1376 else
1377 cond_expr[jj] = build2
1378 (LT_EXPR, boolean_type_node, lhs_var[jj], lhs_length[0][jj]);
1379 }
1380 }
1381
1382 an_init = pop_stmt_list (an_init);
1383 append_to_statement_list_force (an_init, &loop_with_init);
1384 body = array_expr;
1385 for (ii = 0; ii < MAX (lhs_rank, rhs_rank); ii++)
1386 {
1387 tree incr_list = alloc_stmt_list ();
1388 tree new_loop = push_stmt_list ();
1389 if (lhs_rank)
1390 add_stmt (lhs_ind_init[ii]);
1391 if (rhs_rank)
1392 add_stmt (rhs_ind_init[ii]);
1393 if (lhs_rank)
1394 append_to_statement_list_force (lhs_expr_incr[ii], &incr_list);
1395 if (rhs_rank && rhs_expr_incr[ii])
1396 append_to_statement_list_force (rhs_expr_incr[ii], &incr_list);
1397 c_finish_loop (location, cond_expr[ii], incr_list, body, NULL_TREE,
1398 NULL_TREE, true);
1399 body = pop_stmt_list (new_loop);
1400 }
1401 append_to_statement_list_force (body, &loop_with_init);
1402 return loop_with_init;
1403 }
1404
1405 /* Helper function for fix_conditional_array_notations. Encloses the
1406 conditional statement passed in STMT with a loop around it
1407 and replaces the condition in STMT with a ARRAY_REF tree-node to the array.
1408 The condition must have an ARRAY_NOTATION_REF tree. An expansion of array
1409 notation in STMT is returned in a STATEMENT_LIST. */
1410
1411 static tree
1412 fix_conditional_array_notations_1 (tree stmt)
1413 {
1414 vec<tree, va_gc> *array_list = NULL, *array_operand = NULL;
1415 size_t list_size = 0;
1416 tree cond = NULL_TREE, builtin_loop = NULL_TREE, new_var = NULL_TREE;
1417 size_t rank = 0, ii = 0, jj = 0;
1418 int s_jj = 0;
1419 tree **array_ops, *array_var, jj_tree, loop_init;
1420 tree **array_value, **array_stride, **array_length, **array_start;
1421 tree *compare_expr, *expr_incr, *ind_init;
1422 bool **count_down, **array_vector;
1423 tree begin_var, lngth_var, strde_var;
1424 location_t location = EXPR_LOCATION (stmt);
1425 tree body = NULL_TREE, loop_with_init = alloc_stmt_list ();
1426 if (TREE_CODE (stmt) == COND_EXPR)
1427 cond = COND_EXPR_COND (stmt);
1428 else if (TREE_CODE (stmt) == SWITCH_EXPR)
1429 cond = SWITCH_COND (stmt);
1430 else
1431 /* Otherwise dont even touch the statement. */
1432 return stmt;
1433
1434 if (!find_rank (location, cond, cond, false, &rank))
1435 return error_mark_node;
1436
1437 extract_array_notation_exprs (stmt, false, &array_list);
1438 loop_init = push_stmt_list ();
1439 for (ii = 0; ii < vec_safe_length (array_list); ii++)
1440 {
1441 tree array_node = (*array_list)[ii];
1442 if (TREE_CODE (array_node) == CALL_EXPR)
1443 {
1444 builtin_loop = fix_builtin_array_notation_fn (array_node, &new_var);
1445 if (builtin_loop == error_mark_node)
1446 {
1447 add_stmt (error_mark_node);
1448 pop_stmt_list (loop_init);
1449 return loop_init;
1450 }
1451 else if (builtin_loop)
1452 {
1453 vec <tree, va_gc>* sub_list = NULL, *new_var_list = NULL;
1454 vec_safe_push (sub_list, array_node);
1455 vec_safe_push (new_var_list, new_var);
1456 add_stmt (builtin_loop);
1457 replace_array_notations (&stmt, false, sub_list, new_var_list);
1458 }
1459 }
1460 }
1461
1462 if (!find_rank (location, stmt, stmt, true, &rank))
1463 {
1464 pop_stmt_list (loop_init);
1465 return error_mark_node;
1466 }
1467 if (rank == 0)
1468 {
1469 add_stmt (stmt);
1470 pop_stmt_list (loop_init);
1471 return loop_init;
1472 }
1473 extract_array_notation_exprs (stmt, true, &array_list);
1474
1475 if (vec_safe_length (array_list) == 0)
1476 return stmt;
1477
1478 list_size = vec_safe_length (array_list);
1479
1480 array_ops = XNEWVEC (tree *, list_size);
1481 for (ii = 0; ii < list_size; ii++)
1482 array_ops[ii] = XNEWVEC (tree, rank);
1483
1484 array_vector = XNEWVEC (bool *, list_size);
1485 for (ii = 0; ii < list_size; ii++)
1486 array_vector[ii] = XNEWVEC (bool, rank);
1487
1488 array_value = XNEWVEC (tree *, list_size);
1489 array_stride = XNEWVEC (tree *, list_size);
1490 array_length = XNEWVEC (tree *, list_size);
1491 array_start = XNEWVEC (tree *, list_size);
1492
1493 for (ii = 0; ii < list_size; ii++)
1494 {
1495 array_value[ii] = XNEWVEC (tree, rank);
1496 array_stride[ii] = XNEWVEC (tree, rank);
1497 array_length[ii] = XNEWVEC (tree, rank);
1498 array_start[ii] = XNEWVEC (tree, rank);
1499 }
1500
1501 compare_expr = XNEWVEC (tree, rank);
1502 expr_incr = XNEWVEC (tree, rank);
1503 ind_init = XNEWVEC (tree, rank);
1504
1505 count_down = XNEWVEC (bool *, list_size);
1506 for (ii = 0; ii < list_size; ii++)
1507 count_down[ii] = XNEWVEC (bool, rank);
1508
1509 array_var = XNEWVEC (tree, rank);
1510
1511 for (ii = 0; ii < list_size; ii++)
1512 {
1513 tree array_node = (*array_list)[ii];
1514 if (array_node && TREE_CODE (array_node) == ARRAY_NOTATION_REF)
1515 {
1516 tree array_begin = ARRAY_NOTATION_START (array_node);
1517 tree array_lngth = ARRAY_NOTATION_LENGTH (array_node);
1518 tree array_strde = ARRAY_NOTATION_STRIDE (array_node);
1519
1520 if (TREE_CODE (array_begin) != INTEGER_CST)
1521 {
1522 begin_var = build_decl (location, VAR_DECL, NULL_TREE,
1523 integer_type_node);
1524 add_stmt (build_modify_expr (location, begin_var,
1525 TREE_TYPE (begin_var),
1526 NOP_EXPR, location, array_begin,
1527 TREE_TYPE (array_begin)));
1528 ARRAY_NOTATION_START (array_node) = begin_var;
1529 }
1530 if (TREE_CODE (array_lngth) != INTEGER_CST)
1531 {
1532 lngth_var = build_decl (location, VAR_DECL, NULL_TREE,
1533 integer_type_node);
1534 add_stmt (build_modify_expr (location, lngth_var,
1535 TREE_TYPE (lngth_var),
1536 NOP_EXPR, location, array_lngth,
1537 TREE_TYPE (array_lngth)));
1538 ARRAY_NOTATION_LENGTH (array_node) = lngth_var;
1539 }
1540 if (TREE_CODE (array_strde) != INTEGER_CST)
1541 {
1542 strde_var = build_decl (location, VAR_DECL, NULL_TREE,
1543 integer_type_node);
1544 add_stmt (build_modify_expr (location, strde_var,
1545 TREE_TYPE (strde_var),
1546 NOP_EXPR, location, array_strde,
1547 TREE_TYPE (array_strde)));
1548 ARRAY_NOTATION_STRIDE (array_node) = strde_var;
1549 }
1550 }
1551 }
1552 for (ii = 0; ii < list_size; ii++)
1553 {
1554 tree array_node = (*array_list)[ii];
1555 jj = 0;
1556 for (jj_tree = array_node;
1557 jj_tree && TREE_CODE (jj_tree) == ARRAY_NOTATION_REF;
1558 jj_tree = ARRAY_NOTATION_ARRAY (jj_tree))
1559 {
1560 array_ops[ii][jj] = jj_tree;
1561 jj++;
1562 }
1563 }
1564 for (ii = 0; ii < list_size; ii++)
1565 {
1566 tree array_node = (*array_list)[ii];
1567 if (TREE_CODE (array_node) == ARRAY_NOTATION_REF)
1568 {
1569 for (jj = 0; jj < rank; jj++)
1570 {
1571 if (TREE_CODE (array_ops[ii][jj]) == ARRAY_NOTATION_REF)
1572 {
1573 array_value[ii][jj] =
1574 ARRAY_NOTATION_ARRAY (array_ops[ii][jj]);
1575 array_start[ii][jj] =
1576 ARRAY_NOTATION_START (array_ops[ii][jj]);
1577 array_length[ii][jj] =
1578 fold_build1 (CONVERT_EXPR, integer_type_node,
1579 ARRAY_NOTATION_LENGTH (array_ops[ii][jj]));
1580 array_stride[ii][jj] =
1581 fold_build1 (CONVERT_EXPR, integer_type_node,
1582 ARRAY_NOTATION_STRIDE (array_ops[ii][jj]));
1583 array_vector[ii][jj] = true;
1584
1585 if (!TREE_CONSTANT (array_length[ii][jj]))
1586 count_down[ii][jj] = false;
1587 else if (tree_int_cst_lt
1588 (array_length[ii][jj],
1589 build_int_cst (TREE_TYPE (array_length[ii][jj]),
1590 0)))
1591 count_down[ii][jj] = true;
1592 else
1593 count_down[ii][jj] = false;
1594 }
1595 else
1596 array_vector[ii][jj] = false;
1597 }
1598 }
1599 }
1600
1601 for (ii = 0; ii < rank; ii++)
1602 {
1603 array_var[ii] = build_decl (location, VAR_DECL, NULL_TREE,
1604 integer_type_node);
1605 ind_init[ii] =
1606 build_modify_expr (location, array_var[ii],
1607 TREE_TYPE (array_var[ii]), NOP_EXPR,
1608 location,
1609 build_int_cst (TREE_TYPE (array_var[ii]), 0),
1610 TREE_TYPE (array_var[ii]));
1611 }
1612
1613 for (ii = 0; ii < list_size; ii++)
1614 {
1615 if (array_vector[ii][0])
1616 {
1617 tree array_opr = array_value[ii][rank - 1];
1618 for (s_jj = rank - 1; s_jj >= 0; s_jj--)
1619 {
1620 if (count_down[ii][s_jj])
1621 /* Array[start_index - (induction_var * stride)] */
1622 array_opr = build_array_ref
1623 (location, array_opr,
1624 build2 (MINUS_EXPR, TREE_TYPE (array_var[s_jj]),
1625 array_start[ii][s_jj],
1626 build2 (MULT_EXPR, TREE_TYPE (array_var[s_jj]),
1627 array_var[s_jj], array_stride[ii][s_jj])));
1628 else
1629 /* Array[start_index + (induction_var * stride)] */
1630 array_opr = build_array_ref
1631 (location, array_opr,
1632 build2 (PLUS_EXPR, TREE_TYPE (array_var[s_jj]),
1633 array_start[ii][s_jj],
1634 build2 (MULT_EXPR, TREE_TYPE (array_var[s_jj]),
1635 array_var[s_jj], array_stride[ii][s_jj])));
1636 }
1637 vec_safe_push (array_operand, array_opr);
1638 }
1639 else
1640 /* This is just a dummy node to make sure the list sizes for both
1641 array list and array operand list are the same. */
1642 vec_safe_push (array_operand, integer_one_node);
1643 }
1644 replace_array_notations (&stmt, true, array_list, array_operand);
1645 for (ii = 0; ii < rank; ii++)
1646 expr_incr[ii] = build2 (MODIFY_EXPR, void_type_node, array_var[ii],
1647 build2 (PLUS_EXPR, TREE_TYPE (array_var[ii]),
1648 array_var[ii],
1649 build_int_cst (TREE_TYPE (array_var[ii]),
1650 1)));
1651 for (jj = 0; jj < rank; jj++)
1652 {
1653 if (rank && expr_incr[jj])
1654 {
1655 if (count_down[0][jj])
1656 compare_expr[jj] =
1657 build2 (LT_EXPR, boolean_type_node, array_var[jj],
1658 build2 (MULT_EXPR, TREE_TYPE (array_var[jj]),
1659 array_length[0][jj],
1660 build_int_cst (TREE_TYPE (array_var[jj]), -1)));
1661 else
1662 compare_expr[jj] = build2 (LT_EXPR, boolean_type_node,
1663 array_var[jj], array_length[0][jj]);
1664 }
1665 }
1666
1667 loop_init = pop_stmt_list (loop_init);
1668 body = stmt;
1669 append_to_statement_list_force (loop_init, &loop_with_init);
1670
1671 for (ii = 0; ii < rank; ii++)
1672 {
1673 tree new_loop = push_stmt_list ();
1674 add_stmt (ind_init[ii]);
1675 c_finish_loop (location, compare_expr[ii], expr_incr[ii], body, NULL_TREE,
1676 NULL_TREE, true);
1677 body = pop_stmt_list (new_loop);
1678 }
1679 append_to_statement_list_force (body, &loop_with_init);
1680 XDELETEVEC (expr_incr);
1681 XDELETEVEC (ind_init);
1682
1683 for (ii = 0; ii < list_size; ii++)
1684 {
1685 XDELETEVEC (count_down[ii]);
1686 XDELETEVEC (array_value[ii]);
1687 XDELETEVEC (array_stride[ii]);
1688 XDELETEVEC (array_length[ii]);
1689 XDELETEVEC (array_start[ii]);
1690 XDELETEVEC (array_ops[ii]);
1691 XDELETEVEC (array_vector[ii]);
1692 }
1693
1694 XDELETEVEC (count_down);
1695 XDELETEVEC (array_value);
1696 XDELETEVEC (array_stride);
1697 XDELETEVEC (array_length);
1698 XDELETEVEC (array_start);
1699 XDELETEVEC (array_ops);
1700 XDELETEVEC (array_vector);
1701
1702 return loop_with_init;
1703 }
1704
1705 /* Top-level function to replace ARRAY_NOTATION_REF in a conditional statement
1706 in STMT. An expansion of array notation in STMT is returned as a
1707 STATEMENT_LIST. */
1708
1709 tree
1710 fix_conditional_array_notations (tree stmt)
1711 {
1712 if (TREE_CODE (stmt) == STATEMENT_LIST)
1713 {
1714 tree_stmt_iterator tsi;
1715 for (tsi = tsi_start (stmt); !tsi_end_p (tsi); tsi_next (&tsi))
1716 {
1717 tree single_stmt = *tsi_stmt_ptr (tsi);
1718 *tsi_stmt_ptr (tsi) =
1719 fix_conditional_array_notations_1 (single_stmt);
1720 }
1721 return stmt;
1722 }
1723 else
1724 return fix_conditional_array_notations_1 (stmt);
1725 }
1726
1727 /* Create a struct c_expr that contains a loop with ARRAY_REF expr at location
1728 LOCATION with the tree_code CODE and the array notation expr is
1729 passed in ARG. Returns the fixed c_expr in ARG itself. */
1730
1731 struct c_expr
1732 fix_array_notation_expr (location_t location, enum tree_code code,
1733 struct c_expr arg)
1734 {
1735
1736 vec<tree, va_gc> *array_list = NULL, *array_operand = NULL;
1737 size_t list_size = 0, rank = 0, ii = 0, jj = 0;
1738 int s_jj = 0;
1739 tree **array_ops, *array_var, jj_tree, loop_init;
1740 tree **array_value, **array_stride, **array_length, **array_start;
1741 tree *compare_expr, *expr_incr, *ind_init;
1742 tree body, loop_with_init = alloc_stmt_list ();
1743 bool **count_down, **array_vector;
1744
1745 if (!find_rank (location, arg.value, arg.value, false, &rank))
1746 {
1747 /* If this function returns a NULL, we convert the tree value in the
1748 structure to error_mark_node and the parser should take care of the
1749 rest. */
1750 arg.value = error_mark_node;
1751 return arg;
1752 }
1753
1754 if (rank == 0)
1755 return arg;
1756
1757 extract_array_notation_exprs (arg.value, true, &array_list);
1758
1759 if (vec_safe_length (array_list) == 0)
1760 return arg;
1761
1762 list_size = vec_safe_length (array_list);
1763
1764 array_ops = XNEWVEC (tree *, list_size);
1765 for (ii = 0; ii < list_size; ii++)
1766 array_ops[ii] = XNEWVEC (tree, rank);
1767
1768 array_vector = XNEWVEC (bool *, list_size);
1769 for (ii = 0; ii < list_size; ii++)
1770 array_vector[ii] = XNEWVEC (bool, rank);
1771
1772 array_value = XNEWVEC (tree *, list_size);
1773 array_stride = XNEWVEC (tree *, list_size);
1774 array_length = XNEWVEC (tree *, list_size);
1775 array_start = XNEWVEC (tree *, list_size);
1776
1777 for (ii = 0; ii < list_size; ii++)
1778 {
1779 array_value[ii] = XNEWVEC (tree, rank);
1780 array_stride[ii] = XNEWVEC (tree, rank);
1781 array_length[ii] = XNEWVEC (tree, rank);
1782 array_start[ii] = XNEWVEC (tree, rank);
1783 }
1784
1785 compare_expr = XNEWVEC (tree, rank);
1786 expr_incr = XNEWVEC (tree, rank);
1787 ind_init = XNEWVEC (tree, rank);
1788
1789 count_down = XNEWVEC (bool *, list_size);
1790 for (ii = 0; ii < list_size; ii++)
1791 count_down[ii] = XNEWVEC (bool, rank);
1792 array_var = XNEWVEC (tree, rank);
1793
1794 for (ii = 0; ii < list_size; ii++)
1795 {
1796 jj = 0;
1797 for (jj_tree = (*array_list)[ii];
1798 jj_tree && TREE_CODE (jj_tree) == ARRAY_NOTATION_REF;
1799 jj_tree = ARRAY_NOTATION_ARRAY (jj_tree))
1800 {
1801 array_ops[ii][jj] = jj_tree;
1802 jj++;
1803 }
1804 }
1805
1806 loop_init = push_stmt_list ();
1807
1808 for (ii = 0; ii < list_size; ii++)
1809 {
1810 tree array_node = (*array_list)[ii];
1811 if (TREE_CODE (array_node) == ARRAY_NOTATION_REF)
1812 {
1813 for (jj = 0; jj < rank; jj++)
1814 {
1815 if (TREE_CODE (array_ops[ii][jj]) == ARRAY_NOTATION_REF)
1816 {
1817 array_value[ii][jj] =
1818 ARRAY_NOTATION_ARRAY (array_ops[ii][jj]);
1819 array_start[ii][jj] =
1820 ARRAY_NOTATION_START (array_ops[ii][jj]);
1821 array_length[ii][jj] =
1822 fold_build1 (CONVERT_EXPR, integer_type_node,
1823 ARRAY_NOTATION_LENGTH (array_ops[ii][jj]));
1824 array_stride[ii][jj] =
1825 fold_build1 (CONVERT_EXPR, integer_type_node,
1826 ARRAY_NOTATION_STRIDE (array_ops[ii][jj]));
1827 array_vector[ii][jj] = true;
1828
1829 if (!TREE_CONSTANT (array_length[ii][jj]))
1830 count_down[ii][jj] = false;
1831 else if (tree_int_cst_lt
1832 (array_length[ii][jj],
1833 build_int_cst (TREE_TYPE (array_length[ii][jj]),
1834 0)))
1835 count_down[ii][jj] = true;
1836 else
1837 count_down[ii][jj] = false;
1838 }
1839 else
1840 array_vector[ii][jj] = false;
1841 }
1842 }
1843 }
1844
1845 for (ii = 0; ii < rank; ii++)
1846 {
1847 array_var[ii] = build_decl (location, VAR_DECL, NULL_TREE,
1848 integer_type_node);
1849 ind_init[ii] =
1850 build_modify_expr (location, array_var[ii],
1851 TREE_TYPE (array_var[ii]), NOP_EXPR,
1852 location,
1853 build_int_cst (TREE_TYPE (array_var[ii]), 0),
1854 TREE_TYPE (array_var[ii]));
1855
1856 }
1857 for (ii = 0; ii < list_size; ii++)
1858 {
1859 if (array_vector[ii][0])
1860 {
1861 tree array_opr = array_value[ii][rank - 1];
1862 for (s_jj = rank - 1; s_jj >= 0; s_jj--)
1863 {
1864 if (count_down[ii][s_jj])
1865 /* Array[start_index - (induction_var * stride)] */
1866 array_opr = build_array_ref
1867 (location, array_opr,
1868 build2 (MINUS_EXPR, TREE_TYPE (array_var[s_jj]),
1869 array_start[ii][s_jj],
1870 build2 (MULT_EXPR, TREE_TYPE (array_var[s_jj]),
1871 array_var[s_jj], array_stride[ii][s_jj])));
1872 else
1873 /* Array[start_index + (induction_var * stride)] */
1874 array_opr = build_array_ref
1875 (location, array_opr,
1876 build2 (PLUS_EXPR, TREE_TYPE (array_var[s_jj]),
1877 array_start[ii][s_jj],
1878 build2 (MULT_EXPR, TREE_TYPE (array_var[s_jj]),
1879 array_var[s_jj], array_stride[ii][s_jj])));
1880 }
1881 vec_safe_push (array_operand, array_opr);
1882 }
1883 else
1884 /* This is just a dummy node to make sure the list sizes for both
1885 array list and array operand list are the same. */
1886 vec_safe_push (array_operand, integer_one_node);
1887 }
1888 replace_array_notations (&arg.value, true, array_list, array_operand);
1889
1890 for (ii = 0; ii < rank; ii++)
1891 expr_incr[ii] =
1892 build2 (MODIFY_EXPR, void_type_node, array_var[ii],
1893 build2 (PLUS_EXPR, TREE_TYPE (array_var[ii]), array_var[ii],
1894 build_int_cst (TREE_TYPE (array_var[ii]), 1)));
1895
1896 for (jj = 0; jj < rank; jj++)
1897 {
1898 if (rank && expr_incr[jj])
1899 {
1900 if (count_down[0][jj])
1901 compare_expr[jj] =
1902 build2 (LT_EXPR, boolean_type_node, array_var[jj],
1903 build2 (MULT_EXPR, TREE_TYPE (array_var[jj]),
1904 array_length[0][jj],
1905 build_int_cst (TREE_TYPE (array_var[jj]), -1)));
1906 else
1907 compare_expr[jj] = build2 (LT_EXPR, boolean_type_node,
1908 array_var[jj], array_length[0][jj]);
1909 }
1910 }
1911
1912 if (code == POSTINCREMENT_EXPR || code == POSTDECREMENT_EXPR)
1913 {
1914 arg = default_function_array_read_conversion (location, arg);
1915 arg.value = build_unary_op (location, code, arg.value, 0);
1916 }
1917 else if (code == PREINCREMENT_EXPR || code == PREDECREMENT_EXPR)
1918 {
1919 arg = default_function_array_read_conversion (location, arg);
1920 arg = parser_build_unary_op (location, code, arg);
1921 }
1922
1923 loop_init = pop_stmt_list (loop_init);
1924 append_to_statement_list_force (loop_init, &loop_with_init);
1925 body = arg.value;
1926
1927 for (ii = 0; ii < rank; ii++)
1928 {
1929 tree new_loop = push_stmt_list ();
1930 add_stmt (ind_init[ii]);
1931 c_finish_loop (location, compare_expr[ii], expr_incr[ii], body, NULL_TREE,
1932 NULL_TREE, true);
1933 body = pop_stmt_list (new_loop);
1934 }
1935 append_to_statement_list_force (body, &loop_with_init);
1936 XDELETEVEC (expr_incr);
1937 XDELETEVEC (ind_init);
1938 XDELETEVEC (array_var);
1939
1940 for (ii = 0; ii < list_size; ii++)
1941 {
1942 XDELETEVEC (count_down[ii]);
1943 XDELETEVEC (array_value[ii]);
1944 XDELETEVEC (array_stride[ii]);
1945 XDELETEVEC (array_length[ii]);
1946 XDELETEVEC (array_start[ii]);
1947 XDELETEVEC (array_ops[ii]);
1948 XDELETEVEC (array_vector[ii]);
1949 }
1950
1951 XDELETEVEC (count_down);
1952 XDELETEVEC (array_value);
1953 XDELETEVEC (array_stride);
1954 XDELETEVEC (array_length);
1955 XDELETEVEC (array_start);
1956 XDELETEVEC (array_ops);
1957 XDELETEVEC (array_vector);
1958
1959 arg.value = loop_with_init;
1960 return arg;
1961 }
1962
1963 /* Replaces array notations in a void function call arguments in ARG and returns
1964 a STATEMENT_LIST. */
1965
1966 static tree
1967 fix_array_notation_call_expr (tree arg)
1968 {
1969 vec<tree, va_gc> *array_list = NULL, *array_operand = NULL;
1970 tree new_var = NULL_TREE;
1971 size_t list_size = 0, rank = 0, ii = 0, jj = 0;
1972 int s_jj = 0;
1973 tree **array_ops, *array_var, jj_tree, loop_init;
1974 tree **array_value, **array_stride, **array_length, **array_start;
1975 tree body, loop_with_init = alloc_stmt_list ();
1976 tree *compare_expr, *expr_incr, *ind_init;
1977 bool **count_down, **array_vector;
1978 tree begin_var, lngth_var, strde_var;
1979 location_t location = UNKNOWN_LOCATION;
1980
1981 if (TREE_CODE (arg) == CALL_EXPR
1982 && is_cilkplus_reduce_builtin (CALL_EXPR_FN (arg)))
1983 {
1984 loop_init = fix_builtin_array_notation_fn (arg, &new_var);
1985 /* We are ignoring the new var because either the user does not want to
1986 capture it OR he is using sec_reduce_mutating function. */
1987 return loop_init;
1988 }
1989
1990 if (!find_rank (location, arg, arg, false, &rank))
1991 return error_mark_node;
1992
1993 if (rank == 0)
1994 return arg;
1995
1996 extract_array_notation_exprs (arg, true, &array_list);
1997 if (vec_safe_length (array_list) == 0)
1998 return arg;
1999
2000 list_size = vec_safe_length (array_list);
2001 location = EXPR_LOCATION (arg);
2002
2003 array_ops = XNEWVEC (tree *, list_size);
2004 for (ii = 0; ii < list_size; ii++)
2005 array_ops[ii] = XNEWVEC (tree, rank);
2006
2007 array_vector = XNEWVEC (bool *, list_size);
2008 for (ii = 0; ii < list_size; ii++)
2009 array_vector[ii] = (bool *) XNEWVEC (bool, rank);
2010
2011 array_value = XNEWVEC (tree *, list_size);
2012 array_stride = XNEWVEC (tree *, list_size);
2013 array_length = XNEWVEC (tree *, list_size);
2014 array_start = XNEWVEC (tree *, list_size);
2015
2016 for (ii = 0; ii < list_size; ii++)
2017 {
2018 array_value[ii] = XNEWVEC (tree, rank);
2019 array_stride[ii] = XNEWVEC (tree, rank);
2020 array_length[ii] = XNEWVEC (tree, rank);
2021 array_start[ii] = XNEWVEC (tree, rank);
2022 }
2023
2024 compare_expr = XNEWVEC (tree, rank);
2025 expr_incr = XNEWVEC (tree, rank);
2026 ind_init = XNEWVEC (tree, rank);
2027
2028 count_down = XNEWVEC (bool *, list_size);
2029 for (ii = 0; ii < list_size; ii++)
2030 count_down[ii] = XNEWVEC (bool, rank);
2031
2032 array_var = XNEWVEC (tree, rank);
2033
2034 loop_init = push_stmt_list ();
2035 for (ii = 0; ii < list_size; ii++)
2036 {
2037 tree array_node = (*array_list)[ii];
2038 if (array_node && TREE_CODE (array_node) == ARRAY_NOTATION_REF)
2039 {
2040 tree array_begin = ARRAY_NOTATION_START (array_node);
2041 tree array_lngth = ARRAY_NOTATION_LENGTH (array_node);
2042 tree array_strde = ARRAY_NOTATION_STRIDE (array_node);
2043
2044 if (TREE_CODE (array_begin) != INTEGER_CST)
2045 {
2046 begin_var = build_decl (location, VAR_DECL, NULL_TREE,
2047 integer_type_node);
2048 add_stmt (build_modify_expr (location, begin_var,
2049 TREE_TYPE (begin_var),
2050 NOP_EXPR, location, array_begin,
2051 TREE_TYPE (array_begin)));
2052 ARRAY_NOTATION_START (array_node) = begin_var;
2053 }
2054 if (TREE_CODE (array_lngth) != INTEGER_CST)
2055 {
2056 lngth_var = build_decl (location, VAR_DECL, NULL_TREE,
2057 integer_type_node);
2058 add_stmt (build_modify_expr (location, lngth_var,
2059 TREE_TYPE (lngth_var),
2060 NOP_EXPR, location, array_lngth,
2061 TREE_TYPE (array_lngth)));
2062 ARRAY_NOTATION_LENGTH (array_node) = lngth_var;
2063 }
2064 if (TREE_CODE (array_strde) != INTEGER_CST)
2065 {
2066 strde_var = build_decl (location, VAR_DECL, NULL_TREE,
2067 integer_type_node);
2068 add_stmt (build_modify_expr (location, strde_var,
2069 TREE_TYPE (strde_var),
2070 NOP_EXPR, location, array_strde,
2071 TREE_TYPE (array_strde)));
2072 ARRAY_NOTATION_STRIDE (array_node) = strde_var;
2073 }
2074 }
2075 }
2076 for (ii = 0; ii < list_size; ii++)
2077 {
2078 jj = 0;
2079 for (jj_tree = (*array_list)[ii];
2080 jj_tree && TREE_CODE (jj_tree) == ARRAY_NOTATION_REF;
2081 jj_tree = ARRAY_NOTATION_ARRAY (jj_tree))
2082 {
2083 array_ops[ii][jj] = jj_tree;
2084 jj++;
2085 }
2086 }
2087
2088 for (ii = 0; ii < list_size; ii++)
2089 {
2090 tree array_node = (*array_list)[ii];
2091 if (TREE_CODE (array_node) == ARRAY_NOTATION_REF)
2092 {
2093 for (jj = 0; jj < rank; jj++)
2094 {
2095 if (TREE_CODE (array_ops[ii][jj]) == ARRAY_NOTATION_REF)
2096 {
2097 array_value[ii][jj] =
2098 ARRAY_NOTATION_ARRAY (array_ops[ii][jj]);
2099 array_start[ii][jj] =
2100 ARRAY_NOTATION_START (array_ops[ii][jj]);
2101 array_length[ii][jj] =
2102 fold_build1 (CONVERT_EXPR, integer_type_node,
2103 ARRAY_NOTATION_LENGTH (array_ops[ii][jj]));
2104 array_stride[ii][jj] =
2105 fold_build1 (CONVERT_EXPR, integer_type_node,
2106 ARRAY_NOTATION_STRIDE (array_ops[ii][jj]));
2107 array_vector[ii][jj] = true;
2108
2109 if (!TREE_CONSTANT (array_length[ii][jj]))
2110 count_down[ii][jj] = false;
2111 else if (tree_int_cst_lt
2112 (array_length[ii][jj],
2113 build_int_cst (TREE_TYPE (array_length[ii][jj]),
2114 0)))
2115 count_down[ii][jj] = true;
2116 else
2117 count_down[ii][jj] = false;
2118 }
2119 else
2120 array_vector[ii][jj] = false;
2121 }
2122 }
2123 }
2124
2125 if (length_mismatch_in_expr_p (location, array_length, list_size, rank))
2126 {
2127 pop_stmt_list (loop_init);
2128 return error_mark_node;
2129 }
2130
2131 for (ii = 0; ii < rank; ii++)
2132 {
2133 array_var[ii] = build_decl (location, VAR_DECL, NULL_TREE,
2134 integer_type_node);
2135 ind_init[ii] =
2136 build_modify_expr (location, array_var[ii],
2137 TREE_TYPE (array_var[ii]), NOP_EXPR,
2138 location,
2139 build_int_cst (TREE_TYPE (array_var[ii]), 0),
2140 TREE_TYPE (array_var[ii]));
2141
2142 }
2143 for (ii = 0; ii < list_size; ii++)
2144 {
2145 if (array_vector[ii][0])
2146 {
2147 tree array_opr_node = array_value[ii][rank - 1];
2148 for (s_jj = rank - 1; s_jj >= 0; s_jj--)
2149 {
2150 if (count_down[ii][s_jj])
2151 /* Array[start_index - (induction_var * stride)] */
2152 array_opr_node = build_array_ref
2153 (location, array_opr_node,
2154 build2 (MINUS_EXPR, TREE_TYPE (array_var[s_jj]),
2155 array_start[ii][s_jj],
2156 build2 (MULT_EXPR, TREE_TYPE (array_var[s_jj]),
2157 array_var[s_jj], array_stride[ii][s_jj])));
2158 else
2159 /* Array[start_index + (induction_var * stride)] */
2160 array_opr_node = build_array_ref
2161 (location, array_opr_node,
2162 build2 (PLUS_EXPR, TREE_TYPE (array_var[s_jj]),
2163 array_start[ii][s_jj],
2164 build2 (MULT_EXPR, TREE_TYPE (array_var[s_jj]),
2165 array_var[s_jj], array_stride[ii][s_jj])));
2166 }
2167 vec_safe_push (array_operand, array_opr_node);
2168 }
2169 else
2170 /* This is just a dummy node to make sure the list sizes for both
2171 array list and array operand list are the same. */
2172 vec_safe_push (array_operand, integer_one_node);
2173 }
2174 replace_array_notations (&arg, true, array_list, array_operand);
2175 for (ii = 0; ii < rank; ii++)
2176 expr_incr[ii] =
2177 build2 (MODIFY_EXPR, void_type_node, array_var[ii],
2178 build2 (PLUS_EXPR, TREE_TYPE (array_var[ii]), array_var[ii],
2179 build_int_cst (TREE_TYPE (array_var[ii]), 1)));
2180
2181 for (jj = 0; jj < rank; jj++)
2182 {
2183 if (rank && expr_incr[jj])
2184 {
2185 if (count_down[0][jj])
2186 compare_expr[jj] =
2187 build2 (LT_EXPR, boolean_type_node, array_var[jj],
2188 build2 (MULT_EXPR, TREE_TYPE (array_var[jj]),
2189 array_length[0][jj],
2190 build_int_cst (TREE_TYPE (array_var[jj]), -1)));
2191 else
2192 compare_expr[jj] = build2 (LT_EXPR, boolean_type_node,
2193 array_var[jj], array_length[0][jj]);
2194 }
2195 }
2196
2197 loop_init = pop_stmt_list (loop_init);
2198 append_to_statement_list_force (loop_init, &loop_with_init);
2199 body = arg;
2200 for (ii = 0; ii < rank; ii++)
2201 {
2202 tree new_loop = push_stmt_list ();
2203 add_stmt (ind_init[ii]);
2204 c_finish_loop (location, compare_expr[ii], expr_incr[ii], body, NULL_TREE,
2205 NULL_TREE, true);
2206 body = pop_stmt_list (new_loop);
2207 }
2208 append_to_statement_list_force (body, &loop_with_init);
2209 XDELETEVEC (compare_expr);
2210 XDELETEVEC (expr_incr);
2211 XDELETEVEC (ind_init);
2212 XDELETEVEC (array_var);
2213
2214 for (ii = 0; ii < list_size; ii++)
2215 {
2216 XDELETEVEC (count_down[ii]);
2217 XDELETEVEC (array_value[ii]);
2218 XDELETEVEC (array_stride[ii]);
2219 XDELETEVEC (array_length[ii]);
2220 XDELETEVEC (array_start[ii]);
2221 XDELETEVEC (array_ops[ii]);
2222 XDELETEVEC (array_vector[ii]);
2223 }
2224
2225 XDELETEVEC (count_down);
2226 XDELETEVEC (array_value);
2227 XDELETEVEC (array_stride);
2228 XDELETEVEC (array_length);
2229 XDELETEVEC (array_start);
2230 XDELETEVEC (array_ops);
2231 XDELETEVEC (array_vector);
2232
2233 return loop_with_init;
2234 }
2235
2236 /* Expands the built-in functions in a return. EXPR is a RETURN_EXPR with
2237 a built-in reduction function. This function returns the expansion code for
2238 the built-in function. */
2239
2240 static tree
2241 fix_return_expr (tree expr)
2242 {
2243 tree new_mod_list, new_var, new_mod, retval_expr, retval_type;
2244 location_t loc = EXPR_LOCATION (expr);
2245
2246 new_mod_list = alloc_stmt_list ();
2247 retval_expr = TREE_OPERAND (expr, 0);
2248 retval_type = TREE_TYPE (TREE_OPERAND (retval_expr, 1));
2249 new_var = build_decl (loc, VAR_DECL, NULL_TREE, TREE_TYPE (retval_expr));
2250 new_mod = build_array_notation_expr (loc, new_var, TREE_TYPE (new_var),
2251 NOP_EXPR, loc,
2252 TREE_OPERAND (retval_expr, 1),
2253 retval_type);
2254 TREE_OPERAND (retval_expr, 1) = new_var;
2255 TREE_OPERAND (expr, 0) = retval_expr;
2256 append_to_statement_list_force (new_mod, &new_mod_list);
2257 append_to_statement_list_force (expr, &new_mod_list);
2258 return new_mod_list;
2259 }
2260
2261 /* Walks through tree node T and find all the call-statements that do not return
2262 anything and fix up any array notations they may carry. The return value
2263 is the same type as T but with all array notations replaced with appropriate
2264 STATEMENT_LISTS. */
2265
2266 tree
2267 expand_array_notation_exprs (tree t)
2268 {
2269 if (!contains_array_notation_expr (t))
2270 return t;
2271
2272 switch (TREE_CODE (t))
2273 {
2274 case BIND_EXPR:
2275 t = expand_array_notation_exprs (BIND_EXPR_BODY (t));
2276 return t;
2277 case COND_EXPR:
2278 t = fix_conditional_array_notations (t);
2279
2280 /* After the expansion if they are still a COND_EXPR, we go into its
2281 subtrees. */
2282 if (TREE_CODE (t) == COND_EXPR)
2283 {
2284 if (COND_EXPR_THEN (t))
2285 COND_EXPR_THEN (t) =
2286 expand_array_notation_exprs (COND_EXPR_THEN (t));
2287 if (COND_EXPR_ELSE (t))
2288 COND_EXPR_ELSE (t) =
2289 expand_array_notation_exprs (COND_EXPR_ELSE (t));
2290 }
2291 else
2292 t = expand_array_notation_exprs (t);
2293 return t;
2294 case STATEMENT_LIST:
2295 {
2296 tree_stmt_iterator ii_tsi;
2297 for (ii_tsi = tsi_start (t); !tsi_end_p (ii_tsi); tsi_next (&ii_tsi))
2298 *tsi_stmt_ptr (ii_tsi) =
2299 expand_array_notation_exprs (*tsi_stmt_ptr (ii_tsi));
2300 }
2301 return t;
2302 case MODIFY_EXPR:
2303 {
2304 location_t loc = EXPR_HAS_LOCATION (t) ? EXPR_LOCATION (t) :
2305 UNKNOWN_LOCATION;
2306 tree lhs = TREE_OPERAND (t, 0);
2307 tree rhs = TREE_OPERAND (t, 1);
2308 location_t rhs_loc = EXPR_HAS_LOCATION (rhs) ? EXPR_LOCATION (rhs) :
2309 UNKNOWN_LOCATION;
2310 t = build_array_notation_expr (loc, lhs, TREE_TYPE (lhs), NOP_EXPR,
2311 rhs_loc, rhs, TREE_TYPE (rhs));
2312 return t;
2313 }
2314 case CALL_EXPR:
2315 t = fix_array_notation_call_expr (t);
2316 return t;
2317 case RETURN_EXPR:
2318 if (contains_array_notation_expr (t))
2319 t = fix_return_expr (t);
2320 default:
2321 return t;
2322 }
2323 return t;
2324 }
2325
2326 /* This handles expression of the form "a[i:j:k]" or "a[:]" or "a[i:j]," which
2327 denotes an array notation expression. If a is a variable or a member, then
2328 we generate a ARRAY_NOTATION_REF front-end tree and return it.
2329 This tree is broken down to ARRAY_REF toward the end of parsing.
2330 ARRAY_NOTATION_REF tree holds the START_INDEX, LENGTH, STRIDE and the TYPE
2331 of ARRAY_REF. Restrictions on START_INDEX, LENGTH and STRIDE is same as that
2332 of the index field passed into ARRAY_REF. The only additional restriction
2333 is that, unlike index in ARRAY_REF, stride, length and start_index cannot
2334 contain ARRAY_NOTATIONS. */
2335
2336 tree
2337 build_array_notation_ref (location_t loc, tree array, tree start_index,
2338 tree length, tree stride, tree type)
2339 {
2340 tree array_ntn_tree = NULL_TREE;
2341 size_t stride_rank = 0, length_rank = 0, start_rank = 0;
2342
2343 if (!INTEGRAL_TYPE_P (TREE_TYPE (start_index)))
2344 {
2345 error_at (loc,
2346 "start-index of array notation triplet is not an integer");
2347 return error_mark_node;
2348 }
2349 if (!INTEGRAL_TYPE_P (TREE_TYPE (length)))
2350 {
2351 error_at (loc, "length of array notation triplet is not an integer");
2352 return error_mark_node;
2353 }
2354
2355 /* The stride is an optional field. */
2356 if (stride && !INTEGRAL_TYPE_P (TREE_TYPE (stride)))
2357 {
2358 error_at (loc, "stride of array notation triplet is not an integer");
2359 return error_mark_node;
2360 }
2361 if (!stride)
2362 {
2363 if (TREE_CONSTANT (start_index) && TREE_CONSTANT (length)
2364 && tree_int_cst_lt (length, start_index))
2365 stride = build_int_cst (TREE_TYPE (start_index), -1);
2366 else
2367 stride = build_int_cst (TREE_TYPE (start_index), 1);
2368 }
2369
2370 if (!find_rank (loc, start_index, start_index, false, &start_rank))
2371 return error_mark_node;
2372 if (!find_rank (loc, length, length, false, &length_rank))
2373 return error_mark_node;
2374 if (!find_rank (loc, stride, stride, false, &stride_rank))
2375 return error_mark_node;
2376
2377 if (start_rank != 0)
2378 {
2379 error_at (loc, "rank of an array notation triplet's start-index is not "
2380 "zero");
2381 return error_mark_node;
2382 }
2383 if (length_rank != 0)
2384 {
2385 error_at (loc, "rank of an array notation triplet's length is not zero");
2386 return error_mark_node;
2387 }
2388 if (stride_rank != 0)
2389 {
2390 error_at (loc, "rank of array notation triplet's stride is not zero");
2391 return error_mark_node;
2392 }
2393 array_ntn_tree = build4 (ARRAY_NOTATION_REF, NULL_TREE, NULL_TREE, NULL_TREE,
2394 NULL_TREE, NULL_TREE);
2395 ARRAY_NOTATION_ARRAY (array_ntn_tree) = array;
2396 ARRAY_NOTATION_START (array_ntn_tree) = start_index;
2397 ARRAY_NOTATION_LENGTH (array_ntn_tree) = length;
2398 ARRAY_NOTATION_STRIDE (array_ntn_tree) = stride;
2399 TREE_TYPE (array_ntn_tree) = type;
2400
2401 return array_ntn_tree;
2402 }
2403