re PR c/57563 (Lots of Cilk+ failures on i686-linux)
[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 && TREE_CODE (rhs) != CALL_EXPR)
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 tree lhs_base = lhs;
806 tree rhs_base = rhs;
807
808 for (ii = 0; ii < lhs_rank; ii++)
809 lhs_base = ARRAY_NOTATION_ARRAY (lhs_base);
810
811 while (rhs_base && TREE_CODE (rhs_base) != ARRAY_NOTATION_REF)
812 rhs_base = TREE_OPERAND (rhs_base, 0);
813 for (ii = 0; ii < rhs_rank; ii++)
814 rhs_base = ARRAY_NOTATION_ARRAY (rhs_base);
815
816 error_at (location, "rank mismatch between %qE and %qE", lhs, rhs);
817 pop_stmt_list (an_init);
818 return error_mark_node;
819 }
820
821 /* Here we assign the array notation components to variable so that we can
822 satisfy the exec once rule. */
823 for (ii = 0; ii < lhs_list_size; ii++)
824 {
825 tree array_node = (*lhs_list)[ii];
826 tree array_begin = ARRAY_NOTATION_START (array_node);
827 tree array_lngth = ARRAY_NOTATION_LENGTH (array_node);
828 tree array_strde = ARRAY_NOTATION_STRIDE (array_node);
829
830 if (TREE_CODE (array_begin) != INTEGER_CST)
831 {
832 begin_var = build_decl (location, VAR_DECL, NULL_TREE,
833 integer_type_node);
834 add_stmt (build_modify_expr (location, begin_var,
835 TREE_TYPE (begin_var),
836 NOP_EXPR, location, array_begin,
837 TREE_TYPE (array_begin)));
838 ARRAY_NOTATION_START (array_node) = begin_var;
839 }
840
841 if (TREE_CODE (array_lngth) != INTEGER_CST)
842 {
843 lngth_var = build_decl (location, VAR_DECL, NULL_TREE,
844 integer_type_node);
845 add_stmt (build_modify_expr (location, lngth_var,
846 TREE_TYPE (lngth_var),
847 NOP_EXPR, location, array_lngth,
848 TREE_TYPE (array_lngth)));
849 ARRAY_NOTATION_LENGTH (array_node) = lngth_var;
850 }
851 if (TREE_CODE (array_strde) != INTEGER_CST)
852 {
853 strde_var = build_decl (location, VAR_DECL, NULL_TREE,
854 integer_type_node);
855
856 add_stmt (build_modify_expr (location, strde_var,
857 TREE_TYPE (strde_var),
858 NOP_EXPR, location, array_strde,
859 TREE_TYPE (array_strde)));
860 ARRAY_NOTATION_STRIDE (array_node) = strde_var;
861 }
862 }
863 for (ii = 0; ii < rhs_list_size; ii++)
864 {
865 tree array_node = (*rhs_list)[ii];
866 if (array_node && TREE_CODE (array_node) == ARRAY_NOTATION_REF)
867 {
868 tree array_begin = ARRAY_NOTATION_START (array_node);
869 tree array_lngth = ARRAY_NOTATION_LENGTH (array_node);
870 tree array_strde = ARRAY_NOTATION_STRIDE (array_node);
871
872 if (TREE_CODE (array_begin) != INTEGER_CST)
873 {
874 begin_var = build_decl (location, VAR_DECL, NULL_TREE,
875 integer_type_node);
876 add_stmt (build_modify_expr (location, begin_var,
877 TREE_TYPE (begin_var),
878 NOP_EXPR, location, array_begin,
879 TREE_TYPE (array_begin)));
880 ARRAY_NOTATION_START (array_node) = begin_var;
881 }
882 if (TREE_CODE (array_lngth) != INTEGER_CST)
883 {
884 lngth_var = build_decl (location, VAR_DECL, NULL_TREE,
885 integer_type_node);
886 add_stmt (build_modify_expr (location, lngth_var,
887 TREE_TYPE (lngth_var),
888 NOP_EXPR, location, array_lngth,
889 TREE_TYPE (array_lngth)));
890 ARRAY_NOTATION_LENGTH (array_node) = lngth_var;
891 }
892 if (TREE_CODE (array_strde) != INTEGER_CST)
893 {
894 strde_var = build_decl (location, VAR_DECL, NULL_TREE,
895 integer_type_node);
896
897 add_stmt (build_modify_expr (location, strde_var,
898 TREE_TYPE (strde_var),
899 NOP_EXPR, location, array_strde,
900 TREE_TYPE (array_strde)));
901 ARRAY_NOTATION_STRIDE (array_node) = strde_var;
902 }
903 }
904 }
905
906 lhs_vector = XNEWVEC (bool *, lhs_list_size);
907 for (ii = 0; ii < lhs_list_size; ii++)
908 lhs_vector[ii] = XNEWVEC (bool, lhs_rank);
909
910 rhs_vector = XNEWVEC (bool *, rhs_list_size);
911 for (ii = 0; ii < rhs_list_size; ii++)
912 rhs_vector[ii] = XNEWVEC (bool, rhs_rank);
913
914 lhs_array = XNEWVEC (tree *, lhs_list_size);
915 for (ii = 0; ii < lhs_list_size; ii++)
916 lhs_array[ii] = XNEWVEC (tree, lhs_rank);
917
918 rhs_array = XNEWVEC (tree *, rhs_list_size);
919 for (ii = 0; ii < rhs_list_size; ii++)
920 rhs_array[ii] = XNEWVEC (tree, rhs_rank);
921
922 lhs_value = XNEWVEC (tree *, lhs_list_size);
923 for (ii = 0; ii < lhs_list_size; ii++)
924 lhs_value[ii] = XNEWVEC (tree, lhs_rank);
925
926 rhs_value = XNEWVEC (tree *, rhs_list_size);
927 for (ii = 0; ii < rhs_list_size; ii++)
928 rhs_value[ii] = XNEWVEC (tree, rhs_rank);
929
930 lhs_stride = XNEWVEC (tree *, lhs_list_size);
931 for (ii = 0; ii < lhs_list_size; ii++)
932 lhs_stride[ii] = XNEWVEC (tree, lhs_rank);
933
934 rhs_stride = XNEWVEC (tree *, rhs_list_size);
935 for (ii = 0; ii < rhs_list_size; ii++)
936 rhs_stride[ii] = XNEWVEC (tree, rhs_rank);
937
938 lhs_length = XNEWVEC (tree *, lhs_list_size);
939 for (ii = 0; ii < lhs_list_size; ii++)
940 lhs_length[ii] = XNEWVEC (tree, lhs_rank);
941
942 rhs_length = XNEWVEC (tree *, rhs_list_size);
943 for (ii = 0; ii < rhs_list_size; ii++)
944 rhs_length[ii] = XNEWVEC (tree, rhs_rank);
945
946 lhs_start = XNEWVEC (tree *, lhs_list_size);
947 for (ii = 0; ii < lhs_list_size; ii++)
948 lhs_start[ii] = XNEWVEC (tree, lhs_rank);
949
950 rhs_start = XNEWVEC (tree *, rhs_list_size);
951 for (ii = 0; ii < rhs_list_size; ii++)
952 rhs_start[ii] = XNEWVEC (tree, rhs_rank);
953
954 lhs_var = XNEWVEC (tree, lhs_rank);
955 rhs_var = XNEWVEC (tree, rhs_rank);
956 cond_expr = XNEWVEC (tree, MAX (lhs_rank, rhs_rank));
957
958 lhs_expr_incr = XNEWVEC (tree, lhs_rank);
959 rhs_expr_incr =XNEWVEC (tree, rhs_rank);
960
961 lhs_ind_init = XNEWVEC (tree, lhs_rank);
962 rhs_ind_init = XNEWVEC (tree, rhs_rank);
963
964 lhs_count_down = XNEWVEC (bool *, lhs_list_size);
965 for (ii = 0; ii < lhs_list_size; ii++)
966 lhs_count_down[ii] = XNEWVEC (bool, lhs_rank);
967
968 rhs_count_down = XNEWVEC (bool *, rhs_list_size);
969 for (ii = 0; ii < rhs_list_size; ii++)
970 rhs_count_down[ii] = XNEWVEC (bool, rhs_rank);
971
972 lhs_compare = XNEWVEC (tree, lhs_rank);
973 rhs_compare = XNEWVEC (tree, rhs_rank);
974
975 if (lhs_rank)
976 {
977 for (ii = 0; ii < lhs_list_size; ii++)
978 {
979 jj = 0;
980 ii_tree = (*lhs_list)[ii];
981 while (ii_tree)
982 {
983 if (TREE_CODE (ii_tree) == ARRAY_NOTATION_REF)
984 {
985 lhs_array[ii][jj] = ii_tree;
986 jj++;
987 ii_tree = ARRAY_NOTATION_ARRAY (ii_tree);
988 }
989 else if (TREE_CODE (ii_tree) == ARRAY_REF)
990 ii_tree = TREE_OPERAND (ii_tree, 0);
991 else if (TREE_CODE (ii_tree) == VAR_DECL
992 || TREE_CODE (ii_tree) == PARM_DECL)
993 break;
994 }
995 }
996 }
997 else
998 lhs_array[0][0] = NULL_TREE;
999
1000 if (rhs_rank)
1001 {
1002 for (ii = 0; ii < rhs_list_size; ii++)
1003 {
1004 jj = 0;
1005 ii_tree = (*rhs_list)[ii];
1006 while (ii_tree)
1007 {
1008 if (TREE_CODE (ii_tree) == ARRAY_NOTATION_REF)
1009 {
1010 rhs_array[ii][jj] = ii_tree;
1011 jj++;
1012 ii_tree = ARRAY_NOTATION_ARRAY (ii_tree);
1013 }
1014 else if (TREE_CODE (ii_tree) == ARRAY_REF)
1015 ii_tree = TREE_OPERAND (ii_tree, 0);
1016 else if (TREE_CODE (ii_tree) == VAR_DECL
1017 || TREE_CODE (ii_tree) == PARM_DECL
1018 || TREE_CODE (ii_tree) == CALL_EXPR)
1019 break;
1020 }
1021 }
1022 }
1023
1024 for (ii = 0; ii < lhs_list_size; ii++)
1025 {
1026 tree lhs_node = (*lhs_list)[ii];
1027 if (TREE_CODE (lhs_node) == ARRAY_NOTATION_REF)
1028 {
1029 for (jj = 0; jj < lhs_rank; jj++)
1030 {
1031 if (TREE_CODE (lhs_array[ii][jj]) == ARRAY_NOTATION_REF)
1032 {
1033 lhs_value[ii][jj] = ARRAY_NOTATION_ARRAY (lhs_array[ii][jj]);
1034 lhs_start[ii][jj] = ARRAY_NOTATION_START (lhs_array[ii][jj]);
1035 lhs_length[ii][jj] =
1036 fold_build1 (CONVERT_EXPR, integer_type_node,
1037 ARRAY_NOTATION_LENGTH (lhs_array[ii][jj]));
1038 lhs_stride[ii][jj] =
1039 fold_build1 (CONVERT_EXPR, integer_type_node,
1040 ARRAY_NOTATION_STRIDE (lhs_array[ii][jj]));
1041 lhs_vector[ii][jj] = true;
1042 /* IF the stride value is variable (i.e. not constant) then
1043 assume that the length is positive. */
1044 if (!TREE_CONSTANT (lhs_length[ii][jj]))
1045 lhs_count_down[ii][jj] = false;
1046 else if (tree_int_cst_lt
1047 (lhs_length[ii][jj],
1048 build_zero_cst (TREE_TYPE (lhs_length[ii][jj]))))
1049 lhs_count_down[ii][jj] = true;
1050 else
1051 lhs_count_down[ii][jj] = false;
1052 }
1053 else
1054 lhs_vector[ii][jj] = false;
1055 }
1056 }
1057 }
1058 for (ii = 0; ii < rhs_list_size; ii++)
1059 {
1060 if (TREE_CODE ((*rhs_list)[ii]) == ARRAY_NOTATION_REF)
1061 {
1062 for (jj = 0; jj < rhs_rank; jj++)
1063 {
1064 if (TREE_CODE (rhs_array[ii][jj]) == ARRAY_NOTATION_REF)
1065 {
1066 rhs_value[ii][jj] = ARRAY_NOTATION_ARRAY (rhs_array[ii][jj]);
1067 rhs_start[ii][jj] = ARRAY_NOTATION_START (rhs_array[ii][jj]);
1068 rhs_length[ii][jj] =
1069 fold_build1 (CONVERT_EXPR, integer_type_node,
1070 ARRAY_NOTATION_LENGTH (rhs_array[ii][jj]));
1071 rhs_stride[ii][jj] =
1072 fold_build1 (CONVERT_EXPR, integer_type_node,
1073 ARRAY_NOTATION_STRIDE (rhs_array[ii][jj]));
1074 rhs_vector[ii][jj] = true;
1075 /* If the stride value is variable (i.e. not constant) then
1076 assume that the length is positive. */
1077 if (!TREE_CONSTANT (rhs_length[ii][jj]))
1078 rhs_count_down[ii][jj] = false;
1079 else if (tree_int_cst_lt
1080 (rhs_length[ii][jj],
1081 build_int_cst (TREE_TYPE (rhs_length[ii][jj]), 0)))
1082 rhs_count_down[ii][jj] = true;
1083 else
1084 rhs_count_down[ii][jj] = false;
1085 }
1086 else
1087 rhs_vector[ii][jj] = false;
1088 }
1089 }
1090 else
1091 for (jj = 0; jj < rhs_rank; jj++)
1092 {
1093 rhs_vector[ii][jj] = false;
1094 rhs_length[ii][jj] = NULL_TREE;
1095 }
1096 }
1097
1098 if (length_mismatch_in_expr_p (EXPR_LOCATION (lhs), lhs_length,
1099 lhs_list_size, lhs_rank)
1100 || length_mismatch_in_expr_p (EXPR_LOCATION (rhs), rhs_length,
1101 rhs_list_size, rhs_rank))
1102 {
1103 pop_stmt_list (an_init);
1104 return error_mark_node;
1105 }
1106
1107 if (lhs_list_size > 0 && rhs_list_size > 0 && lhs_rank > 0 && rhs_rank > 0
1108 && TREE_CODE (lhs_length[0][0]) == INTEGER_CST
1109 && rhs_length[0][0]
1110 && TREE_CODE (rhs_length[0][0]) == INTEGER_CST)
1111 {
1112 HOST_WIDE_INT l_length = int_cst_value (lhs_length[0][0]);
1113 HOST_WIDE_INT r_length = int_cst_value (rhs_length[0][0]);
1114 /* Length can be negative or positive. As long as the magnitude is OK,
1115 then the array notation is valid. */
1116 if (absu_hwi (l_length) != absu_hwi (r_length))
1117 {
1118 error_at (location, "length mismatch between LHS and RHS");
1119 pop_stmt_list (an_init);
1120 return error_mark_node;
1121 }
1122 }
1123 for (ii = 0; ii < lhs_rank; ii++)
1124 {
1125 if (lhs_vector[0][ii])
1126 {
1127 lhs_var[ii] = build_decl (location, VAR_DECL, NULL_TREE,
1128 integer_type_node);
1129 lhs_ind_init[ii] = build_modify_expr
1130 (location, lhs_var[ii], TREE_TYPE (lhs_var[ii]),
1131 NOP_EXPR,
1132 location, build_zero_cst (TREE_TYPE (lhs_var[ii])),
1133 TREE_TYPE (lhs_var[ii]));
1134 }
1135 }
1136
1137 for (ii = 0; ii < rhs_rank; ii++)
1138 {
1139 /* When we have a polynomial, we assume that the indices are of type
1140 integer. */
1141 rhs_var[ii] = build_decl (location, VAR_DECL, NULL_TREE,
1142 integer_type_node);
1143 rhs_ind_init[ii] = build_modify_expr
1144 (location, rhs_var[ii], TREE_TYPE (rhs_var[ii]),
1145 NOP_EXPR,
1146 location, build_int_cst (TREE_TYPE (rhs_var[ii]), 0),
1147 TREE_TYPE (rhs_var[ii]));
1148 }
1149 if (lhs_rank)
1150 {
1151 for (ii = 0; ii < lhs_list_size; ii++)
1152 {
1153 if (lhs_vector[ii][0])
1154 {
1155 /* The last ARRAY_NOTATION element's ARRAY component should be
1156 the array's base value. */
1157 tree lhs_array_opr = lhs_value[ii][lhs_rank - 1];
1158 for (s_jj = lhs_rank - 1; s_jj >= 0; s_jj--)
1159 {
1160 if (lhs_count_down[ii][s_jj])
1161 /* Array[start_index + (induction_var * stride)]. */
1162 lhs_array_opr = build_array_ref
1163 (location, lhs_array_opr,
1164 build2 (MINUS_EXPR, TREE_TYPE (lhs_var[s_jj]),
1165 lhs_start[ii][s_jj],
1166 build2 (MULT_EXPR, TREE_TYPE (lhs_var[s_jj]),
1167 lhs_var[s_jj],
1168 lhs_stride[ii][s_jj])));
1169 else
1170 lhs_array_opr = build_array_ref
1171 (location, lhs_array_opr,
1172 build2 (PLUS_EXPR, TREE_TYPE (lhs_var[s_jj]),
1173 lhs_start[ii][s_jj],
1174 build2 (MULT_EXPR, TREE_TYPE (lhs_var[s_jj]),
1175 lhs_var[s_jj],
1176 lhs_stride[ii][s_jj])));
1177 }
1178 vec_safe_push (lhs_array_operand, lhs_array_opr);
1179 }
1180 else
1181 vec_safe_push (lhs_array_operand, integer_one_node);
1182 }
1183 replace_array_notations (&lhs, true, lhs_list, lhs_array_operand);
1184 array_expr_lhs = lhs;
1185 }
1186
1187 if (rhs_rank)
1188 {
1189 for (ii = 0; ii < rhs_list_size; ii++)
1190 {
1191 if (rhs_vector[ii][0])
1192 {
1193 tree rhs_array_opr = rhs_value[ii][rhs_rank - 1];
1194 for (s_jj = rhs_rank - 1; s_jj >= 0; s_jj--)
1195 {
1196 if (rhs_count_down[ii][s_jj])
1197 /* Array[start_index - (induction_var * stride)] */
1198 rhs_array_opr = build_array_ref
1199 (location, rhs_array_opr,
1200 build2 (MINUS_EXPR, TREE_TYPE (rhs_var[s_jj]),
1201 rhs_start[ii][s_jj],
1202 build2 (MULT_EXPR, TREE_TYPE (rhs_var[s_jj]),
1203 rhs_var[s_jj],
1204 rhs_stride[ii][s_jj])));
1205 else
1206 /* Array[start_index + (induction_var * stride)] */
1207 rhs_array_opr = build_array_ref
1208 (location, rhs_array_opr,
1209 build2 (PLUS_EXPR, TREE_TYPE (rhs_var[s_jj]),
1210 rhs_start[ii][s_jj],
1211 build2 (MULT_EXPR, TREE_TYPE (rhs_var[s_jj]),
1212 rhs_var[s_jj],
1213 rhs_stride[ii][s_jj])));
1214 }
1215 vec_safe_push (rhs_array_operand, rhs_array_opr);
1216 }
1217 else
1218 /* This is just a dummy node to make sure the list sizes for both
1219 array list and array operand list are the same. */
1220 vec_safe_push (rhs_array_operand, integer_one_node);
1221 }
1222
1223 for (ii = 0; ii < rhs_list_size; ii++)
1224 {
1225 tree rhs_node = (*rhs_list)[ii];
1226 if (TREE_CODE (rhs_node) == CALL_EXPR)
1227 {
1228 int idx_value = 0;
1229 tree func_name = CALL_EXPR_FN (rhs_node);
1230 if (TREE_CODE (func_name) == ADDR_EXPR)
1231 if (is_sec_implicit_index_fn (func_name))
1232 {
1233 idx_value =
1234 extract_sec_implicit_index_arg (location, rhs_node);
1235 if (idx_value == -1) /* This means we have an error. */
1236 return error_mark_node;
1237 else if (idx_value < (int) lhs_rank && idx_value >= 0)
1238 vec_safe_push (rhs_array_operand, lhs_var[idx_value]);
1239 else
1240 {
1241 size_t ee = 0;
1242 tree lhs_base = (*lhs_list)[ii];
1243 for (ee = 0; ee < lhs_rank; ee++)
1244 lhs_base = ARRAY_NOTATION_ARRAY (lhs_base);
1245 error_at (location, "__sec_implicit_index argument %d "
1246 "must be less than rank of %qD", idx_value,
1247 lhs_base);
1248 return error_mark_node;
1249 }
1250 }
1251 }
1252 }
1253 replace_array_notations (&rhs, true, rhs_list, rhs_array_operand);
1254 array_expr_rhs = rhs;
1255 }
1256 else
1257 {
1258 for (ii = 0; ii < rhs_list_size; ii++)
1259 {
1260 tree rhs_node = (*rhs_list)[ii];
1261 if (TREE_CODE (rhs_node) == CALL_EXPR)
1262 {
1263 int idx_value = 0;
1264 tree func_name = CALL_EXPR_FN (rhs_node);
1265 if (TREE_CODE (func_name) == ADDR_EXPR)
1266 if (is_sec_implicit_index_fn (func_name))
1267 {
1268 idx_value =
1269 extract_sec_implicit_index_arg (location, rhs_node);
1270 if (idx_value == -1) /* This means we have an error. */
1271 return error_mark_node;
1272 else if (idx_value < (int) lhs_rank && idx_value >= 0)
1273 vec_safe_push (rhs_array_operand, lhs_var[idx_value]);
1274 else
1275 {
1276 size_t ee = 0;
1277 tree lhs_base = (*lhs_list)[ii];
1278 for (ee = 0; ee < lhs_rank; ee++)
1279 lhs_base = ARRAY_NOTATION_ARRAY (lhs_base);
1280 error_at (location, "__sec_implicit_index argument %d "
1281 "must be less than rank of %qD", idx_value,
1282 lhs_base);
1283 return error_mark_node;
1284 }
1285 }
1286 }
1287 }
1288 replace_array_notations (&rhs, true, rhs_list, rhs_array_operand);
1289 array_expr_rhs = rhs;
1290 rhs_expr_incr[0] = NULL_TREE;
1291 }
1292
1293 for (ii = 0; ii < rhs_rank; ii++)
1294 rhs_expr_incr[ii] = build2 (MODIFY_EXPR, void_type_node, rhs_var[ii],
1295 build2
1296 (PLUS_EXPR, TREE_TYPE (rhs_var[ii]),
1297 rhs_var[ii],
1298 build_one_cst (TREE_TYPE (rhs_var[ii]))));
1299
1300 for (ii = 0; ii < lhs_rank; ii++)
1301 lhs_expr_incr[ii] = build2
1302 (MODIFY_EXPR, void_type_node, lhs_var[ii],
1303 build2 (PLUS_EXPR, TREE_TYPE (lhs_var[ii]), lhs_var[ii],
1304 build_one_cst (TREE_TYPE (lhs_var[ii]))));
1305
1306 /* If array_expr_lhs is NULL, then we have function that returns void or
1307 its return value is ignored. */
1308 if (!array_expr_lhs)
1309 array_expr_lhs = lhs;
1310
1311 array_expr = build_modify_expr (location, array_expr_lhs, lhs_origtype,
1312 modifycode, rhs_loc, array_expr_rhs,
1313 rhs_origtype);
1314
1315 for (jj = 0; jj < MAX (lhs_rank, rhs_rank); jj++)
1316 {
1317 if (rhs_rank && rhs_expr_incr[jj])
1318 {
1319 size_t iii = 0;
1320 if (lhs_rank == 0)
1321 lhs_compare[jj] = integer_one_node;
1322 else if (lhs_count_down[0][jj])
1323 lhs_compare[jj] = build2
1324 (GT_EXPR, boolean_type_node, lhs_var[jj], lhs_length[0][jj]);
1325 else
1326 lhs_compare[jj] = build2
1327 (LT_EXPR, boolean_type_node, lhs_var[jj], lhs_length[0][jj]);
1328
1329
1330 /* The reason why we have this here is for the following case:
1331 Array[:][:] = function_call(something) + Array2[:][:];
1332
1333 So, we will skip the first operand of RHS and then go to the
1334 2nd to find whether we should count up or down. */
1335
1336 for (iii = 0; iii < rhs_list_size; iii++)
1337 if (rhs_vector[iii][jj])
1338 break;
1339
1340 /* What we are doing here is this:
1341 We always count up, so:
1342 if (length is negative ==> which means we count down)
1343 we multiply length by -1 and count up => ii < -LENGTH
1344 else
1345 we just count up, so we compare for ii < LENGTH
1346 */
1347 if (rhs_count_down[iii][jj])
1348 /* We use iii for rhs_length because that is the correct countdown
1349 we have to use. */
1350 rhs_compare[jj] = build2
1351 (LT_EXPR, boolean_type_node, rhs_var[jj],
1352 build2 (MULT_EXPR, TREE_TYPE (rhs_var[jj]),
1353 rhs_length[iii][jj],
1354 build_int_cst (TREE_TYPE (rhs_var[jj]), -1)));
1355 else
1356 rhs_compare[jj] = build2 (LT_EXPR, boolean_type_node, rhs_var[jj],
1357 rhs_length[iii][jj]);
1358 if (lhs_compare[ii] != integer_one_node)
1359 cond_expr[jj] = build2 (TRUTH_ANDIF_EXPR, void_type_node,
1360 lhs_compare[jj], rhs_compare[jj]);
1361 else
1362 cond_expr[jj] = rhs_compare[jj];
1363 }
1364 else
1365 {
1366 if (lhs_count_down[0][jj])
1367 cond_expr[jj] = build2
1368 (GT_EXPR, boolean_type_node, lhs_var[jj], lhs_length[0][jj]);
1369 else
1370 cond_expr[jj] = build2
1371 (LT_EXPR, boolean_type_node, lhs_var[jj], lhs_length[0][jj]);
1372 }
1373 }
1374
1375 an_init = pop_stmt_list (an_init);
1376 append_to_statement_list_force (an_init, &loop_with_init);
1377 body = array_expr;
1378 for (ii = 0; ii < MAX (lhs_rank, rhs_rank); ii++)
1379 {
1380 tree incr_list = alloc_stmt_list ();
1381 tree new_loop = push_stmt_list ();
1382 if (lhs_rank)
1383 add_stmt (lhs_ind_init[ii]);
1384 if (rhs_rank)
1385 add_stmt (rhs_ind_init[ii]);
1386 if (lhs_rank)
1387 append_to_statement_list_force (lhs_expr_incr[ii], &incr_list);
1388 if (rhs_rank && rhs_expr_incr[ii])
1389 append_to_statement_list_force (rhs_expr_incr[ii], &incr_list);
1390 c_finish_loop (location, cond_expr[ii], incr_list, body, NULL_TREE,
1391 NULL_TREE, true);
1392 body = pop_stmt_list (new_loop);
1393 }
1394 append_to_statement_list_force (body, &loop_with_init);
1395 return loop_with_init;
1396 }
1397
1398 /* Helper function for fix_conditional_array_notations. Encloses the
1399 conditional statement passed in STMT with a loop around it
1400 and replaces the condition in STMT with a ARRAY_REF tree-node to the array.
1401 The condition must have an ARRAY_NOTATION_REF tree. An expansion of array
1402 notation in STMT is returned in a STATEMENT_LIST. */
1403
1404 static tree
1405 fix_conditional_array_notations_1 (tree stmt)
1406 {
1407 vec<tree, va_gc> *array_list = NULL, *array_operand = NULL;
1408 size_t list_size = 0;
1409 tree cond = NULL_TREE, builtin_loop = NULL_TREE, new_var = NULL_TREE;
1410 size_t rank = 0, ii = 0, jj = 0;
1411 int s_jj = 0;
1412 tree **array_ops, *array_var, jj_tree, loop_init;
1413 tree **array_value, **array_stride, **array_length, **array_start;
1414 tree *compare_expr, *expr_incr, *ind_init;
1415 bool **count_down, **array_vector;
1416 tree begin_var, lngth_var, strde_var;
1417 location_t location = EXPR_LOCATION (stmt);
1418 tree body = NULL_TREE, loop_with_init = alloc_stmt_list ();
1419 if (TREE_CODE (stmt) == COND_EXPR)
1420 cond = COND_EXPR_COND (stmt);
1421 else if (TREE_CODE (stmt) == SWITCH_EXPR)
1422 cond = SWITCH_COND (stmt);
1423 else
1424 /* Otherwise dont even touch the statement. */
1425 return stmt;
1426
1427 if (!find_rank (location, cond, cond, false, &rank))
1428 return error_mark_node;
1429
1430 extract_array_notation_exprs (stmt, false, &array_list);
1431 loop_init = push_stmt_list ();
1432 for (ii = 0; ii < vec_safe_length (array_list); ii++)
1433 {
1434 tree array_node = (*array_list)[ii];
1435 if (TREE_CODE (array_node) == CALL_EXPR)
1436 {
1437 builtin_loop = fix_builtin_array_notation_fn (array_node, &new_var);
1438 if (builtin_loop == error_mark_node)
1439 {
1440 add_stmt (error_mark_node);
1441 pop_stmt_list (loop_init);
1442 return loop_init;
1443 }
1444 else if (builtin_loop)
1445 {
1446 vec <tree, va_gc>* sub_list = NULL, *new_var_list = NULL;
1447 vec_safe_push (sub_list, array_node);
1448 vec_safe_push (new_var_list, new_var);
1449 add_stmt (builtin_loop);
1450 replace_array_notations (&stmt, false, sub_list, new_var_list);
1451 }
1452 }
1453 }
1454
1455 if (!find_rank (location, stmt, stmt, true, &rank))
1456 {
1457 pop_stmt_list (loop_init);
1458 return error_mark_node;
1459 }
1460 if (rank == 0)
1461 {
1462 add_stmt (stmt);
1463 pop_stmt_list (loop_init);
1464 return loop_init;
1465 }
1466 extract_array_notation_exprs (stmt, true, &array_list);
1467
1468 if (vec_safe_length (array_list) == 0)
1469 return stmt;
1470
1471 list_size = vec_safe_length (array_list);
1472
1473 array_ops = XNEWVEC (tree *, list_size);
1474 for (ii = 0; ii < list_size; ii++)
1475 array_ops[ii] = XNEWVEC (tree, rank);
1476
1477 array_vector = XNEWVEC (bool *, list_size);
1478 for (ii = 0; ii < list_size; ii++)
1479 array_vector[ii] = XNEWVEC (bool, rank);
1480
1481 array_value = XNEWVEC (tree *, list_size);
1482 array_stride = XNEWVEC (tree *, list_size);
1483 array_length = XNEWVEC (tree *, list_size);
1484 array_start = XNEWVEC (tree *, list_size);
1485
1486 for (ii = 0; ii < list_size; ii++)
1487 {
1488 array_value[ii] = XNEWVEC (tree, rank);
1489 array_stride[ii] = XNEWVEC (tree, rank);
1490 array_length[ii] = XNEWVEC (tree, rank);
1491 array_start[ii] = XNEWVEC (tree, rank);
1492 }
1493
1494 compare_expr = XNEWVEC (tree, rank);
1495 expr_incr = XNEWVEC (tree, rank);
1496 ind_init = XNEWVEC (tree, rank);
1497
1498 count_down = XNEWVEC (bool *, list_size);
1499 for (ii = 0; ii < list_size; ii++)
1500 count_down[ii] = XNEWVEC (bool, rank);
1501
1502 array_var = XNEWVEC (tree, rank);
1503
1504 for (ii = 0; ii < list_size; ii++)
1505 {
1506 tree array_node = (*array_list)[ii];
1507 if (array_node && TREE_CODE (array_node) == ARRAY_NOTATION_REF)
1508 {
1509 tree array_begin = ARRAY_NOTATION_START (array_node);
1510 tree array_lngth = ARRAY_NOTATION_LENGTH (array_node);
1511 tree array_strde = ARRAY_NOTATION_STRIDE (array_node);
1512
1513 if (TREE_CODE (array_begin) != INTEGER_CST)
1514 {
1515 begin_var = build_decl (location, VAR_DECL, NULL_TREE,
1516 integer_type_node);
1517 add_stmt (build_modify_expr (location, begin_var,
1518 TREE_TYPE (begin_var),
1519 NOP_EXPR, location, array_begin,
1520 TREE_TYPE (array_begin)));
1521 ARRAY_NOTATION_START (array_node) = begin_var;
1522 }
1523 if (TREE_CODE (array_lngth) != INTEGER_CST)
1524 {
1525 lngth_var = build_decl (location, VAR_DECL, NULL_TREE,
1526 integer_type_node);
1527 add_stmt (build_modify_expr (location, lngth_var,
1528 TREE_TYPE (lngth_var),
1529 NOP_EXPR, location, array_lngth,
1530 TREE_TYPE (array_lngth)));
1531 ARRAY_NOTATION_LENGTH (array_node) = lngth_var;
1532 }
1533 if (TREE_CODE (array_strde) != INTEGER_CST)
1534 {
1535 strde_var = build_decl (location, VAR_DECL, NULL_TREE,
1536 integer_type_node);
1537 add_stmt (build_modify_expr (location, strde_var,
1538 TREE_TYPE (strde_var),
1539 NOP_EXPR, location, array_strde,
1540 TREE_TYPE (array_strde)));
1541 ARRAY_NOTATION_STRIDE (array_node) = strde_var;
1542 }
1543 }
1544 }
1545 for (ii = 0; ii < list_size; ii++)
1546 {
1547 tree array_node = (*array_list)[ii];
1548 jj = 0;
1549 for (jj_tree = array_node;
1550 jj_tree && TREE_CODE (jj_tree) == ARRAY_NOTATION_REF;
1551 jj_tree = ARRAY_NOTATION_ARRAY (jj_tree))
1552 {
1553 array_ops[ii][jj] = jj_tree;
1554 jj++;
1555 }
1556 }
1557 for (ii = 0; ii < list_size; ii++)
1558 {
1559 tree array_node = (*array_list)[ii];
1560 if (TREE_CODE (array_node) == ARRAY_NOTATION_REF)
1561 {
1562 for (jj = 0; jj < rank; jj++)
1563 {
1564 if (TREE_CODE (array_ops[ii][jj]) == ARRAY_NOTATION_REF)
1565 {
1566 array_value[ii][jj] =
1567 ARRAY_NOTATION_ARRAY (array_ops[ii][jj]);
1568 array_start[ii][jj] =
1569 ARRAY_NOTATION_START (array_ops[ii][jj]);
1570 array_length[ii][jj] =
1571 fold_build1 (CONVERT_EXPR, integer_type_node,
1572 ARRAY_NOTATION_LENGTH (array_ops[ii][jj]));
1573 array_stride[ii][jj] =
1574 fold_build1 (CONVERT_EXPR, integer_type_node,
1575 ARRAY_NOTATION_STRIDE (array_ops[ii][jj]));
1576 array_vector[ii][jj] = true;
1577
1578 if (!TREE_CONSTANT (array_length[ii][jj]))
1579 count_down[ii][jj] = false;
1580 else if (tree_int_cst_lt
1581 (array_length[ii][jj],
1582 build_int_cst (TREE_TYPE (array_length[ii][jj]),
1583 0)))
1584 count_down[ii][jj] = true;
1585 else
1586 count_down[ii][jj] = false;
1587 }
1588 else
1589 array_vector[ii][jj] = false;
1590 }
1591 }
1592 }
1593
1594 for (ii = 0; ii < rank; ii++)
1595 {
1596 array_var[ii] = build_decl (location, VAR_DECL, NULL_TREE,
1597 integer_type_node);
1598 ind_init[ii] =
1599 build_modify_expr (location, array_var[ii],
1600 TREE_TYPE (array_var[ii]), NOP_EXPR,
1601 location,
1602 build_int_cst (TREE_TYPE (array_var[ii]), 0),
1603 TREE_TYPE (array_var[ii]));
1604 }
1605
1606 for (ii = 0; ii < list_size; ii++)
1607 {
1608 if (array_vector[ii][0])
1609 {
1610 tree array_opr = array_value[ii][rank - 1];
1611 for (s_jj = rank - 1; s_jj >= 0; s_jj--)
1612 {
1613 if (count_down[ii][s_jj])
1614 /* Array[start_index - (induction_var * stride)] */
1615 array_opr = build_array_ref
1616 (location, array_opr,
1617 build2 (MINUS_EXPR, TREE_TYPE (array_var[s_jj]),
1618 array_start[ii][s_jj],
1619 build2 (MULT_EXPR, TREE_TYPE (array_var[s_jj]),
1620 array_var[s_jj], array_stride[ii][s_jj])));
1621 else
1622 /* Array[start_index + (induction_var * stride)] */
1623 array_opr = build_array_ref
1624 (location, array_opr,
1625 build2 (PLUS_EXPR, TREE_TYPE (array_var[s_jj]),
1626 array_start[ii][s_jj],
1627 build2 (MULT_EXPR, TREE_TYPE (array_var[s_jj]),
1628 array_var[s_jj], array_stride[ii][s_jj])));
1629 }
1630 vec_safe_push (array_operand, array_opr);
1631 }
1632 else
1633 /* This is just a dummy node to make sure the list sizes for both
1634 array list and array operand list are the same. */
1635 vec_safe_push (array_operand, integer_one_node);
1636 }
1637 replace_array_notations (&stmt, true, array_list, array_operand);
1638 for (ii = 0; ii < rank; ii++)
1639 expr_incr[ii] = build2 (MODIFY_EXPR, void_type_node, array_var[ii],
1640 build2 (PLUS_EXPR, TREE_TYPE (array_var[ii]),
1641 array_var[ii],
1642 build_int_cst (TREE_TYPE (array_var[ii]),
1643 1)));
1644 for (jj = 0; jj < rank; jj++)
1645 {
1646 if (rank && expr_incr[jj])
1647 {
1648 if (count_down[0][jj])
1649 compare_expr[jj] =
1650 build2 (LT_EXPR, boolean_type_node, array_var[jj],
1651 build2 (MULT_EXPR, TREE_TYPE (array_var[jj]),
1652 array_length[0][jj],
1653 build_int_cst (TREE_TYPE (array_var[jj]), -1)));
1654 else
1655 compare_expr[jj] = build2 (LT_EXPR, boolean_type_node,
1656 array_var[jj], array_length[0][jj]);
1657 }
1658 }
1659
1660 loop_init = pop_stmt_list (loop_init);
1661 body = stmt;
1662 append_to_statement_list_force (loop_init, &loop_with_init);
1663
1664 for (ii = 0; ii < rank; ii++)
1665 {
1666 tree new_loop = push_stmt_list ();
1667 add_stmt (ind_init[ii]);
1668 c_finish_loop (location, compare_expr[ii], expr_incr[ii], body, NULL_TREE,
1669 NULL_TREE, true);
1670 body = pop_stmt_list (new_loop);
1671 }
1672 append_to_statement_list_force (body, &loop_with_init);
1673 XDELETEVEC (expr_incr);
1674 XDELETEVEC (ind_init);
1675
1676 for (ii = 0; ii < list_size; ii++)
1677 {
1678 XDELETEVEC (count_down[ii]);
1679 XDELETEVEC (array_value[ii]);
1680 XDELETEVEC (array_stride[ii]);
1681 XDELETEVEC (array_length[ii]);
1682 XDELETEVEC (array_start[ii]);
1683 XDELETEVEC (array_ops[ii]);
1684 XDELETEVEC (array_vector[ii]);
1685 }
1686
1687 XDELETEVEC (count_down);
1688 XDELETEVEC (array_value);
1689 XDELETEVEC (array_stride);
1690 XDELETEVEC (array_length);
1691 XDELETEVEC (array_start);
1692 XDELETEVEC (array_ops);
1693 XDELETEVEC (array_vector);
1694
1695 return loop_with_init;
1696 }
1697
1698 /* Top-level function to replace ARRAY_NOTATION_REF in a conditional statement
1699 in STMT. An expansion of array notation in STMT is returned as a
1700 STATEMENT_LIST. */
1701
1702 tree
1703 fix_conditional_array_notations (tree stmt)
1704 {
1705 if (TREE_CODE (stmt) == STATEMENT_LIST)
1706 {
1707 tree_stmt_iterator tsi;
1708 for (tsi = tsi_start (stmt); !tsi_end_p (tsi); tsi_next (&tsi))
1709 {
1710 tree single_stmt = *tsi_stmt_ptr (tsi);
1711 *tsi_stmt_ptr (tsi) =
1712 fix_conditional_array_notations_1 (single_stmt);
1713 }
1714 return stmt;
1715 }
1716 else
1717 return fix_conditional_array_notations_1 (stmt);
1718 }
1719
1720 /* Create a struct c_expr that contains a loop with ARRAY_REF expr at location
1721 LOCATION with the tree_code CODE and the array notation expr is
1722 passed in ARG. Returns the fixed c_expr in ARG itself. */
1723
1724 struct c_expr
1725 fix_array_notation_expr (location_t location, enum tree_code code,
1726 struct c_expr arg)
1727 {
1728
1729 vec<tree, va_gc> *array_list = NULL, *array_operand = NULL;
1730 size_t list_size = 0, rank = 0, ii = 0, jj = 0;
1731 int s_jj = 0;
1732 tree **array_ops, *array_var, jj_tree, loop_init;
1733 tree **array_value, **array_stride, **array_length, **array_start;
1734 tree *compare_expr, *expr_incr, *ind_init;
1735 tree body, loop_with_init = alloc_stmt_list ();
1736 bool **count_down, **array_vector;
1737
1738 if (!find_rank (location, arg.value, arg.value, false, &rank))
1739 {
1740 /* If this function returns a NULL, we convert the tree value in the
1741 structure to error_mark_node and the parser should take care of the
1742 rest. */
1743 arg.value = error_mark_node;
1744 return arg;
1745 }
1746
1747 if (rank == 0)
1748 return arg;
1749
1750 extract_array_notation_exprs (arg.value, true, &array_list);
1751
1752 if (vec_safe_length (array_list) == 0)
1753 return arg;
1754
1755 list_size = vec_safe_length (array_list);
1756
1757 array_ops = XNEWVEC (tree *, list_size);
1758 for (ii = 0; ii < list_size; ii++)
1759 array_ops[ii] = XNEWVEC (tree, rank);
1760
1761 array_vector = XNEWVEC (bool *, list_size);
1762 for (ii = 0; ii < list_size; ii++)
1763 array_vector[ii] = XNEWVEC (bool, rank);
1764
1765 array_value = XNEWVEC (tree *, list_size);
1766 array_stride = XNEWVEC (tree *, list_size);
1767 array_length = XNEWVEC (tree *, list_size);
1768 array_start = XNEWVEC (tree *, list_size);
1769
1770 for (ii = 0; ii < list_size; ii++)
1771 {
1772 array_value[ii] = XNEWVEC (tree, rank);
1773 array_stride[ii] = XNEWVEC (tree, rank);
1774 array_length[ii] = XNEWVEC (tree, rank);
1775 array_start[ii] = XNEWVEC (tree, rank);
1776 }
1777
1778 compare_expr = XNEWVEC (tree, rank);
1779 expr_incr = XNEWVEC (tree, rank);
1780 ind_init = XNEWVEC (tree, rank);
1781
1782 count_down = XNEWVEC (bool *, list_size);
1783 for (ii = 0; ii < list_size; ii++)
1784 count_down[ii] = XNEWVEC (bool, rank);
1785 array_var = XNEWVEC (tree, rank);
1786
1787 for (ii = 0; ii < list_size; ii++)
1788 {
1789 jj = 0;
1790 for (jj_tree = (*array_list)[ii];
1791 jj_tree && TREE_CODE (jj_tree) == ARRAY_NOTATION_REF;
1792 jj_tree = ARRAY_NOTATION_ARRAY (jj_tree))
1793 {
1794 array_ops[ii][jj] = jj_tree;
1795 jj++;
1796 }
1797 }
1798
1799 loop_init = push_stmt_list ();
1800
1801 for (ii = 0; ii < list_size; ii++)
1802 {
1803 tree array_node = (*array_list)[ii];
1804 if (TREE_CODE (array_node) == ARRAY_NOTATION_REF)
1805 {
1806 for (jj = 0; jj < rank; jj++)
1807 {
1808 if (TREE_CODE (array_ops[ii][jj]) == ARRAY_NOTATION_REF)
1809 {
1810 array_value[ii][jj] =
1811 ARRAY_NOTATION_ARRAY (array_ops[ii][jj]);
1812 array_start[ii][jj] =
1813 ARRAY_NOTATION_START (array_ops[ii][jj]);
1814 array_length[ii][jj] =
1815 fold_build1 (CONVERT_EXPR, integer_type_node,
1816 ARRAY_NOTATION_LENGTH (array_ops[ii][jj]));
1817 array_stride[ii][jj] =
1818 fold_build1 (CONVERT_EXPR, integer_type_node,
1819 ARRAY_NOTATION_STRIDE (array_ops[ii][jj]));
1820 array_vector[ii][jj] = true;
1821
1822 if (!TREE_CONSTANT (array_length[ii][jj]))
1823 count_down[ii][jj] = false;
1824 else if (tree_int_cst_lt
1825 (array_length[ii][jj],
1826 build_int_cst (TREE_TYPE (array_length[ii][jj]),
1827 0)))
1828 count_down[ii][jj] = true;
1829 else
1830 count_down[ii][jj] = false;
1831 }
1832 else
1833 array_vector[ii][jj] = false;
1834 }
1835 }
1836 }
1837
1838 for (ii = 0; ii < rank; ii++)
1839 {
1840 array_var[ii] = build_decl (location, VAR_DECL, NULL_TREE,
1841 integer_type_node);
1842 ind_init[ii] =
1843 build_modify_expr (location, array_var[ii],
1844 TREE_TYPE (array_var[ii]), NOP_EXPR,
1845 location,
1846 build_int_cst (TREE_TYPE (array_var[ii]), 0),
1847 TREE_TYPE (array_var[ii]));
1848
1849 }
1850 for (ii = 0; ii < list_size; ii++)
1851 {
1852 if (array_vector[ii][0])
1853 {
1854 tree array_opr = array_value[ii][rank - 1];
1855 for (s_jj = rank - 1; s_jj >= 0; s_jj--)
1856 {
1857 if (count_down[ii][s_jj])
1858 /* Array[start_index - (induction_var * stride)] */
1859 array_opr = build_array_ref
1860 (location, array_opr,
1861 build2 (MINUS_EXPR, TREE_TYPE (array_var[s_jj]),
1862 array_start[ii][s_jj],
1863 build2 (MULT_EXPR, TREE_TYPE (array_var[s_jj]),
1864 array_var[s_jj], array_stride[ii][s_jj])));
1865 else
1866 /* Array[start_index + (induction_var * stride)] */
1867 array_opr = build_array_ref
1868 (location, array_opr,
1869 build2 (PLUS_EXPR, TREE_TYPE (array_var[s_jj]),
1870 array_start[ii][s_jj],
1871 build2 (MULT_EXPR, TREE_TYPE (array_var[s_jj]),
1872 array_var[s_jj], array_stride[ii][s_jj])));
1873 }
1874 vec_safe_push (array_operand, array_opr);
1875 }
1876 else
1877 /* This is just a dummy node to make sure the list sizes for both
1878 array list and array operand list are the same. */
1879 vec_safe_push (array_operand, integer_one_node);
1880 }
1881 replace_array_notations (&arg.value, true, array_list, array_operand);
1882
1883 for (ii = 0; ii < rank; ii++)
1884 expr_incr[ii] =
1885 build2 (MODIFY_EXPR, void_type_node, array_var[ii],
1886 build2 (PLUS_EXPR, TREE_TYPE (array_var[ii]), array_var[ii],
1887 build_int_cst (TREE_TYPE (array_var[ii]), 1)));
1888
1889 for (jj = 0; jj < rank; jj++)
1890 {
1891 if (rank && expr_incr[jj])
1892 {
1893 if (count_down[0][jj])
1894 compare_expr[jj] =
1895 build2 (LT_EXPR, boolean_type_node, array_var[jj],
1896 build2 (MULT_EXPR, TREE_TYPE (array_var[jj]),
1897 array_length[0][jj],
1898 build_int_cst (TREE_TYPE (array_var[jj]), -1)));
1899 else
1900 compare_expr[jj] = build2 (LT_EXPR, boolean_type_node,
1901 array_var[jj], array_length[0][jj]);
1902 }
1903 }
1904
1905 if (code == POSTINCREMENT_EXPR || code == POSTDECREMENT_EXPR)
1906 {
1907 arg = default_function_array_read_conversion (location, arg);
1908 arg.value = build_unary_op (location, code, arg.value, 0);
1909 }
1910 else if (code == PREINCREMENT_EXPR || code == PREDECREMENT_EXPR)
1911 {
1912 arg = default_function_array_read_conversion (location, arg);
1913 arg = parser_build_unary_op (location, code, arg);
1914 }
1915
1916 loop_init = pop_stmt_list (loop_init);
1917 append_to_statement_list_force (loop_init, &loop_with_init);
1918 body = arg.value;
1919
1920 for (ii = 0; ii < rank; ii++)
1921 {
1922 tree new_loop = push_stmt_list ();
1923 add_stmt (ind_init[ii]);
1924 c_finish_loop (location, compare_expr[ii], expr_incr[ii], body, NULL_TREE,
1925 NULL_TREE, true);
1926 body = pop_stmt_list (new_loop);
1927 }
1928 append_to_statement_list_force (body, &loop_with_init);
1929 XDELETEVEC (expr_incr);
1930 XDELETEVEC (ind_init);
1931 XDELETEVEC (array_var);
1932
1933 for (ii = 0; ii < list_size; ii++)
1934 {
1935 XDELETEVEC (count_down[ii]);
1936 XDELETEVEC (array_value[ii]);
1937 XDELETEVEC (array_stride[ii]);
1938 XDELETEVEC (array_length[ii]);
1939 XDELETEVEC (array_start[ii]);
1940 XDELETEVEC (array_ops[ii]);
1941 XDELETEVEC (array_vector[ii]);
1942 }
1943
1944 XDELETEVEC (count_down);
1945 XDELETEVEC (array_value);
1946 XDELETEVEC (array_stride);
1947 XDELETEVEC (array_length);
1948 XDELETEVEC (array_start);
1949 XDELETEVEC (array_ops);
1950 XDELETEVEC (array_vector);
1951
1952 arg.value = loop_with_init;
1953 return arg;
1954 }
1955
1956 /* Replaces array notations in a void function call arguments in ARG and returns
1957 a STATEMENT_LIST. */
1958
1959 static tree
1960 fix_array_notation_call_expr (tree arg)
1961 {
1962 vec<tree, va_gc> *array_list = NULL, *array_operand = NULL;
1963 tree new_var = NULL_TREE;
1964 size_t list_size = 0, rank = 0, ii = 0, jj = 0;
1965 int s_jj = 0;
1966 tree **array_ops, *array_var, jj_tree, loop_init;
1967 tree **array_value, **array_stride, **array_length, **array_start;
1968 tree body, loop_with_init = alloc_stmt_list ();
1969 tree *compare_expr, *expr_incr, *ind_init;
1970 bool **count_down, **array_vector;
1971 tree begin_var, lngth_var, strde_var;
1972 location_t location = UNKNOWN_LOCATION;
1973
1974 if (TREE_CODE (arg) == CALL_EXPR
1975 && is_cilkplus_reduce_builtin (CALL_EXPR_FN (arg)))
1976 {
1977 loop_init = fix_builtin_array_notation_fn (arg, &new_var);
1978 /* We are ignoring the new var because either the user does not want to
1979 capture it OR he is using sec_reduce_mutating function. */
1980 return loop_init;
1981 }
1982
1983 if (!find_rank (location, arg, arg, false, &rank))
1984 return error_mark_node;
1985
1986 if (rank == 0)
1987 return arg;
1988
1989 extract_array_notation_exprs (arg, true, &array_list);
1990 if (vec_safe_length (array_list) == 0)
1991 return arg;
1992
1993 list_size = vec_safe_length (array_list);
1994 location = EXPR_LOCATION (arg);
1995
1996 array_ops = XNEWVEC (tree *, list_size);
1997 for (ii = 0; ii < list_size; ii++)
1998 array_ops[ii] = XNEWVEC (tree, rank);
1999
2000 array_vector = XNEWVEC (bool *, list_size);
2001 for (ii = 0; ii < list_size; ii++)
2002 array_vector[ii] = (bool *) XNEWVEC (bool, rank);
2003
2004 array_value = XNEWVEC (tree *, list_size);
2005 array_stride = XNEWVEC (tree *, list_size);
2006 array_length = XNEWVEC (tree *, list_size);
2007 array_start = XNEWVEC (tree *, list_size);
2008
2009 for (ii = 0; ii < list_size; ii++)
2010 {
2011 array_value[ii] = XNEWVEC (tree, rank);
2012 array_stride[ii] = XNEWVEC (tree, rank);
2013 array_length[ii] = XNEWVEC (tree, rank);
2014 array_start[ii] = XNEWVEC (tree, rank);
2015 }
2016
2017 compare_expr = XNEWVEC (tree, rank);
2018 expr_incr = XNEWVEC (tree, rank);
2019 ind_init = XNEWVEC (tree, rank);
2020
2021 count_down = XNEWVEC (bool *, list_size);
2022 for (ii = 0; ii < list_size; ii++)
2023 count_down[ii] = XNEWVEC (bool, rank);
2024
2025 array_var = XNEWVEC (tree, rank);
2026
2027 loop_init = push_stmt_list ();
2028 for (ii = 0; ii < list_size; ii++)
2029 {
2030 tree array_node = (*array_list)[ii];
2031 if (array_node && TREE_CODE (array_node) == ARRAY_NOTATION_REF)
2032 {
2033 tree array_begin = ARRAY_NOTATION_START (array_node);
2034 tree array_lngth = ARRAY_NOTATION_LENGTH (array_node);
2035 tree array_strde = ARRAY_NOTATION_STRIDE (array_node);
2036
2037 if (TREE_CODE (array_begin) != INTEGER_CST)
2038 {
2039 begin_var = build_decl (location, VAR_DECL, NULL_TREE,
2040 integer_type_node);
2041 add_stmt (build_modify_expr (location, begin_var,
2042 TREE_TYPE (begin_var),
2043 NOP_EXPR, location, array_begin,
2044 TREE_TYPE (array_begin)));
2045 ARRAY_NOTATION_START (array_node) = begin_var;
2046 }
2047 if (TREE_CODE (array_lngth) != INTEGER_CST)
2048 {
2049 lngth_var = build_decl (location, VAR_DECL, NULL_TREE,
2050 integer_type_node);
2051 add_stmt (build_modify_expr (location, lngth_var,
2052 TREE_TYPE (lngth_var),
2053 NOP_EXPR, location, array_lngth,
2054 TREE_TYPE (array_lngth)));
2055 ARRAY_NOTATION_LENGTH (array_node) = lngth_var;
2056 }
2057 if (TREE_CODE (array_strde) != INTEGER_CST)
2058 {
2059 strde_var = build_decl (location, VAR_DECL, NULL_TREE,
2060 integer_type_node);
2061 add_stmt (build_modify_expr (location, strde_var,
2062 TREE_TYPE (strde_var),
2063 NOP_EXPR, location, array_strde,
2064 TREE_TYPE (array_strde)));
2065 ARRAY_NOTATION_STRIDE (array_node) = strde_var;
2066 }
2067 }
2068 }
2069 for (ii = 0; ii < list_size; ii++)
2070 {
2071 jj = 0;
2072 for (jj_tree = (*array_list)[ii];
2073 jj_tree && TREE_CODE (jj_tree) == ARRAY_NOTATION_REF;
2074 jj_tree = ARRAY_NOTATION_ARRAY (jj_tree))
2075 {
2076 array_ops[ii][jj] = jj_tree;
2077 jj++;
2078 }
2079 }
2080
2081 for (ii = 0; ii < list_size; ii++)
2082 {
2083 tree array_node = (*array_list)[ii];
2084 if (TREE_CODE (array_node) == ARRAY_NOTATION_REF)
2085 {
2086 for (jj = 0; jj < rank; jj++)
2087 {
2088 if (TREE_CODE (array_ops[ii][jj]) == ARRAY_NOTATION_REF)
2089 {
2090 array_value[ii][jj] =
2091 ARRAY_NOTATION_ARRAY (array_ops[ii][jj]);
2092 array_start[ii][jj] =
2093 ARRAY_NOTATION_START (array_ops[ii][jj]);
2094 array_length[ii][jj] =
2095 fold_build1 (CONVERT_EXPR, integer_type_node,
2096 ARRAY_NOTATION_LENGTH (array_ops[ii][jj]));
2097 array_stride[ii][jj] =
2098 fold_build1 (CONVERT_EXPR, integer_type_node,
2099 ARRAY_NOTATION_STRIDE (array_ops[ii][jj]));
2100 array_vector[ii][jj] = true;
2101
2102 if (!TREE_CONSTANT (array_length[ii][jj]))
2103 count_down[ii][jj] = false;
2104 else if (tree_int_cst_lt
2105 (array_length[ii][jj],
2106 build_int_cst (TREE_TYPE (array_length[ii][jj]),
2107 0)))
2108 count_down[ii][jj] = true;
2109 else
2110 count_down[ii][jj] = false;
2111 }
2112 else
2113 array_vector[ii][jj] = false;
2114 }
2115 }
2116 }
2117
2118 if (length_mismatch_in_expr_p (location, array_length, list_size, rank))
2119 {
2120 pop_stmt_list (loop_init);
2121 return error_mark_node;
2122 }
2123
2124 for (ii = 0; ii < rank; ii++)
2125 {
2126 array_var[ii] = build_decl (location, VAR_DECL, NULL_TREE,
2127 integer_type_node);
2128 ind_init[ii] =
2129 build_modify_expr (location, array_var[ii],
2130 TREE_TYPE (array_var[ii]), NOP_EXPR,
2131 location,
2132 build_int_cst (TREE_TYPE (array_var[ii]), 0),
2133 TREE_TYPE (array_var[ii]));
2134
2135 }
2136 for (ii = 0; ii < list_size; ii++)
2137 {
2138 if (array_vector[ii][0])
2139 {
2140 tree array_opr_node = array_value[ii][rank - 1];
2141 for (s_jj = rank - 1; s_jj >= 0; s_jj--)
2142 {
2143 if (count_down[ii][s_jj])
2144 /* Array[start_index - (induction_var * stride)] */
2145 array_opr_node = build_array_ref
2146 (location, array_opr_node,
2147 build2 (MINUS_EXPR, TREE_TYPE (array_var[s_jj]),
2148 array_start[ii][s_jj],
2149 build2 (MULT_EXPR, TREE_TYPE (array_var[s_jj]),
2150 array_var[s_jj], array_stride[ii][s_jj])));
2151 else
2152 /* Array[start_index + (induction_var * stride)] */
2153 array_opr_node = build_array_ref
2154 (location, array_opr_node,
2155 build2 (PLUS_EXPR, TREE_TYPE (array_var[s_jj]),
2156 array_start[ii][s_jj],
2157 build2 (MULT_EXPR, TREE_TYPE (array_var[s_jj]),
2158 array_var[s_jj], array_stride[ii][s_jj])));
2159 }
2160 vec_safe_push (array_operand, array_opr_node);
2161 }
2162 else
2163 /* This is just a dummy node to make sure the list sizes for both
2164 array list and array operand list are the same. */
2165 vec_safe_push (array_operand, integer_one_node);
2166 }
2167 replace_array_notations (&arg, true, array_list, array_operand);
2168 for (ii = 0; ii < rank; ii++)
2169 expr_incr[ii] =
2170 build2 (MODIFY_EXPR, void_type_node, array_var[ii],
2171 build2 (PLUS_EXPR, TREE_TYPE (array_var[ii]), array_var[ii],
2172 build_int_cst (TREE_TYPE (array_var[ii]), 1)));
2173
2174 for (jj = 0; jj < rank; jj++)
2175 {
2176 if (rank && expr_incr[jj])
2177 {
2178 if (count_down[0][jj])
2179 compare_expr[jj] =
2180 build2 (LT_EXPR, boolean_type_node, array_var[jj],
2181 build2 (MULT_EXPR, TREE_TYPE (array_var[jj]),
2182 array_length[0][jj],
2183 build_int_cst (TREE_TYPE (array_var[jj]), -1)));
2184 else
2185 compare_expr[jj] = build2 (LT_EXPR, boolean_type_node,
2186 array_var[jj], array_length[0][jj]);
2187 }
2188 }
2189
2190 loop_init = pop_stmt_list (loop_init);
2191 append_to_statement_list_force (loop_init, &loop_with_init);
2192 body = arg;
2193 for (ii = 0; ii < rank; ii++)
2194 {
2195 tree new_loop = push_stmt_list ();
2196 add_stmt (ind_init[ii]);
2197 c_finish_loop (location, compare_expr[ii], expr_incr[ii], body, NULL_TREE,
2198 NULL_TREE, true);
2199 body = pop_stmt_list (new_loop);
2200 }
2201 append_to_statement_list_force (body, &loop_with_init);
2202 XDELETEVEC (compare_expr);
2203 XDELETEVEC (expr_incr);
2204 XDELETEVEC (ind_init);
2205 XDELETEVEC (array_var);
2206
2207 for (ii = 0; ii < list_size; ii++)
2208 {
2209 XDELETEVEC (count_down[ii]);
2210 XDELETEVEC (array_value[ii]);
2211 XDELETEVEC (array_stride[ii]);
2212 XDELETEVEC (array_length[ii]);
2213 XDELETEVEC (array_start[ii]);
2214 XDELETEVEC (array_ops[ii]);
2215 XDELETEVEC (array_vector[ii]);
2216 }
2217
2218 XDELETEVEC (count_down);
2219 XDELETEVEC (array_value);
2220 XDELETEVEC (array_stride);
2221 XDELETEVEC (array_length);
2222 XDELETEVEC (array_start);
2223 XDELETEVEC (array_ops);
2224 XDELETEVEC (array_vector);
2225
2226 return loop_with_init;
2227 }
2228
2229 /* Expands the built-in functions in a return. EXPR is a RETURN_EXPR with
2230 a built-in reduction function. This function returns the expansion code for
2231 the built-in function. */
2232
2233 static tree
2234 fix_return_expr (tree expr)
2235 {
2236 tree new_mod_list, new_var, new_mod, retval_expr, retval_type;
2237 location_t loc = EXPR_LOCATION (expr);
2238
2239 new_mod_list = alloc_stmt_list ();
2240 retval_expr = TREE_OPERAND (expr, 0);
2241 retval_type = TREE_TYPE (TREE_OPERAND (retval_expr, 1));
2242 new_var = build_decl (loc, VAR_DECL, NULL_TREE, TREE_TYPE (retval_expr));
2243 new_mod = build_array_notation_expr (loc, new_var, TREE_TYPE (new_var),
2244 NOP_EXPR, loc,
2245 TREE_OPERAND (retval_expr, 1),
2246 retval_type);
2247 TREE_OPERAND (retval_expr, 1) = new_var;
2248 TREE_OPERAND (expr, 0) = retval_expr;
2249 append_to_statement_list_force (new_mod, &new_mod_list);
2250 append_to_statement_list_force (expr, &new_mod_list);
2251 return new_mod_list;
2252 }
2253
2254 /* Walks through tree node T and find all the call-statements that do not return
2255 anything and fix up any array notations they may carry. The return value
2256 is the same type as T but with all array notations replaced with appropriate
2257 STATEMENT_LISTS. */
2258
2259 tree
2260 expand_array_notation_exprs (tree t)
2261 {
2262 if (!contains_array_notation_expr (t))
2263 return t;
2264
2265 switch (TREE_CODE (t))
2266 {
2267 case BIND_EXPR:
2268 t = expand_array_notation_exprs (BIND_EXPR_BODY (t));
2269 return t;
2270 case COND_EXPR:
2271 t = fix_conditional_array_notations (t);
2272
2273 /* After the expansion if they are still a COND_EXPR, we go into its
2274 subtrees. */
2275 if (TREE_CODE (t) == COND_EXPR)
2276 {
2277 if (COND_EXPR_THEN (t))
2278 COND_EXPR_THEN (t) =
2279 expand_array_notation_exprs (COND_EXPR_THEN (t));
2280 if (COND_EXPR_ELSE (t))
2281 COND_EXPR_ELSE (t) =
2282 expand_array_notation_exprs (COND_EXPR_ELSE (t));
2283 }
2284 else
2285 t = expand_array_notation_exprs (t);
2286 return t;
2287 case STATEMENT_LIST:
2288 {
2289 tree_stmt_iterator ii_tsi;
2290 for (ii_tsi = tsi_start (t); !tsi_end_p (ii_tsi); tsi_next (&ii_tsi))
2291 *tsi_stmt_ptr (ii_tsi) =
2292 expand_array_notation_exprs (*tsi_stmt_ptr (ii_tsi));
2293 }
2294 return t;
2295 case MODIFY_EXPR:
2296 {
2297 location_t loc = EXPR_HAS_LOCATION (t) ? EXPR_LOCATION (t) :
2298 UNKNOWN_LOCATION;
2299 tree lhs = TREE_OPERAND (t, 0);
2300 tree rhs = TREE_OPERAND (t, 1);
2301 location_t rhs_loc = EXPR_HAS_LOCATION (rhs) ? EXPR_LOCATION (rhs) :
2302 UNKNOWN_LOCATION;
2303 t = build_array_notation_expr (loc, lhs, TREE_TYPE (lhs), NOP_EXPR,
2304 rhs_loc, rhs, TREE_TYPE (rhs));
2305 return t;
2306 }
2307 case CALL_EXPR:
2308 t = fix_array_notation_call_expr (t);
2309 return t;
2310 case RETURN_EXPR:
2311 if (contains_array_notation_expr (t))
2312 t = fix_return_expr (t);
2313 return t;
2314 case ARRAY_NOTATION_REF:
2315 /* IF we are here, then we are dealing with cases like this:
2316 A[:];
2317 A[x:y:z];
2318 A[x:y];
2319 Replace those with just void zero node. */
2320 t = void_zero_node;
2321 default:
2322 return t;
2323 }
2324 return t;
2325 }
2326
2327 /* This handles expression of the form "a[i:j:k]" or "a[:]" or "a[i:j]," which
2328 denotes an array notation expression. If a is a variable or a member, then
2329 we generate a ARRAY_NOTATION_REF front-end tree and return it.
2330 This tree is broken down to ARRAY_REF toward the end of parsing.
2331 ARRAY_NOTATION_REF tree holds the START_INDEX, LENGTH, STRIDE and the TYPE
2332 of ARRAY_REF. Restrictions on START_INDEX, LENGTH and STRIDE is same as that
2333 of the index field passed into ARRAY_REF. The only additional restriction
2334 is that, unlike index in ARRAY_REF, stride, length and start_index cannot
2335 contain ARRAY_NOTATIONS. */
2336
2337 tree
2338 build_array_notation_ref (location_t loc, tree array, tree start_index,
2339 tree length, tree stride, tree type)
2340 {
2341 tree array_ntn_tree = NULL_TREE;
2342 size_t stride_rank = 0, length_rank = 0, start_rank = 0;
2343
2344 if (!INTEGRAL_TYPE_P (TREE_TYPE (start_index)))
2345 {
2346 error_at (loc,
2347 "start-index of array notation triplet is not an integer");
2348 return error_mark_node;
2349 }
2350 if (!INTEGRAL_TYPE_P (TREE_TYPE (length)))
2351 {
2352 error_at (loc, "length of array notation triplet is not an integer");
2353 return error_mark_node;
2354 }
2355
2356 /* The stride is an optional field. */
2357 if (stride && !INTEGRAL_TYPE_P (TREE_TYPE (stride)))
2358 {
2359 error_at (loc, "stride of array notation triplet is not an integer");
2360 return error_mark_node;
2361 }
2362 if (!stride)
2363 {
2364 if (TREE_CONSTANT (start_index) && TREE_CONSTANT (length)
2365 && tree_int_cst_lt (length, start_index))
2366 stride = build_int_cst (TREE_TYPE (start_index), -1);
2367 else
2368 stride = build_int_cst (TREE_TYPE (start_index), 1);
2369 }
2370
2371 if (!find_rank (loc, start_index, start_index, false, &start_rank))
2372 return error_mark_node;
2373 if (!find_rank (loc, length, length, false, &length_rank))
2374 return error_mark_node;
2375 if (!find_rank (loc, stride, stride, false, &stride_rank))
2376 return error_mark_node;
2377
2378 if (start_rank != 0)
2379 {
2380 error_at (loc, "rank of an array notation triplet's start-index is not "
2381 "zero");
2382 return error_mark_node;
2383 }
2384 if (length_rank != 0)
2385 {
2386 error_at (loc, "rank of an array notation triplet's length is not zero");
2387 return error_mark_node;
2388 }
2389 if (stride_rank != 0)
2390 {
2391 error_at (loc, "rank of array notation triplet's stride is not zero");
2392 return error_mark_node;
2393 }
2394 array_ntn_tree = build4 (ARRAY_NOTATION_REF, NULL_TREE, NULL_TREE, NULL_TREE,
2395 NULL_TREE, NULL_TREE);
2396 ARRAY_NOTATION_ARRAY (array_ntn_tree) = array;
2397 ARRAY_NOTATION_START (array_ntn_tree) = start_index;
2398 ARRAY_NOTATION_LENGTH (array_ntn_tree) = length;
2399 ARRAY_NOTATION_STRIDE (array_ntn_tree) = stride;
2400 TREE_TYPE (array_ntn_tree) = type;
2401
2402 return array_ntn_tree;
2403 }
2404