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