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>,
8 This file is part of GCC.
10 GCC is free software; you can redistribute it and/or modify it
11 under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3, or (at your option)
15 GCC is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with GCC; see the file COPYING3. If not see
22 <http://www.gnu.org/licenses/>. */
24 /* The Array Notation Transformation Technique:
26 An array notation expression has 4 major components:
29 3. Number of elements we need to acess (we call it length)
32 For example, A[0:5:2], implies that we are accessing A[0], A[2], A[4],
33 A[6] and A[8]. The user is responsible to make sure the access length does
34 not step outside the array's size.
36 In this section, I highlight the overall method on how array notations are
37 broken up into C/C++ code. Almost all the functions follows this overall
40 Let's say we have an array notation in a statement like this:
42 A[St1:Ln:Str1] = B[St2:Ln:Str2] + <NON ARRAY_NOTATION_STMT>
44 where St{1,2} = Starting index,
45 Ln = Number of elements we need to access,
46 and Str{1,2} = the stride.
47 Note: The length of both the array notation expressions must be the same.
49 The above expression is broken into the following
50 (with the help of c_finish_loop function from c-typeck.c):
56 A[St1+Tmp_Var*Str1] = B[St1+Tmp_Var*Str2] + <NON ARRAY_NOTATION_STMT>;
70 #include "coretypes.h"
73 #include "tree-iterator.h"
75 #include "c-family/c-common.h"
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
82 replace_invariant_exprs (tree
*node
)
85 tree node_list
= NULL_TREE
;
86 tree t
= NULL_TREE
, new_var
= NULL_TREE
, new_node
;
89 data
.list_values
= NULL
;
90 data
.replacement
= NULL
;
91 data
.additional_tcodes
= NULL
;
92 walk_tree (node
, find_inv_trees
, (void *)&data
, NULL
);
94 if (vec_safe_length (data
.list_values
))
96 node_list
= push_stmt_list ();
97 for (ix
= 0; vec_safe_iterate (data
.list_values
, ix
, &t
); ix
++)
99 new_var
= build_decl (EXPR_LOCATION (t
), VAR_DECL
, NULL_TREE
,
101 gcc_assert (new_var
!= NULL_TREE
&& new_var
!= error_mark_node
);
102 new_node
= build2 (MODIFY_EXPR
, TREE_TYPE (t
), new_var
, t
);
104 vec_safe_push (data
.replacement
, new_var
);
106 walk_tree (node
, replace_inv_trees
, (void *)&data
, NULL
);
107 node_list
= pop_stmt_list (node_list
);
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.
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. */
120 fix_builtin_array_notation_fn (tree an_builtin_fn
, tree
*new_var
)
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;
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 ();
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
)
142 if (an_type
== BUILT_IN_CILKPLUS_SEC_REDUCE
143 || an_type
== BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING
)
145 call_fn
= CALL_EXPR_ARG (an_builtin_fn
, 2);
146 while (TREE_CODE (call_fn
) == CONVERT_EXPR
147 || TREE_CODE (call_fn
) == NOP_EXPR
)
148 call_fn
= TREE_OPERAND (call_fn
, 0);
149 call_fn
= TREE_OPERAND (call_fn
, 0);
151 identity_value
= CALL_EXPR_ARG (an_builtin_fn
, 0);
152 while (TREE_CODE (identity_value
) == CONVERT_EXPR
153 || TREE_CODE (identity_value
) == NOP_EXPR
)
154 identity_value
= TREE_OPERAND (identity_value
, 0);
155 func_parm
= CALL_EXPR_ARG (an_builtin_fn
, 1);
158 func_parm
= CALL_EXPR_ARG (an_builtin_fn
, 0);
160 while (TREE_CODE (func_parm
) == CONVERT_EXPR
161 || TREE_CODE (func_parm
) == EXCESS_PRECISION_EXPR
162 || TREE_CODE (func_parm
) == NOP_EXPR
)
163 func_parm
= TREE_OPERAND (func_parm
, 0);
165 location
= EXPR_LOCATION (an_builtin_fn
);
167 if (!find_rank (location
, an_builtin_fn
, an_builtin_fn
, true, &rank
))
168 return error_mark_node
;
171 return an_builtin_fn
;
173 && (an_type
== BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
174 || an_type
== BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND
))
176 error_at (location
, "__sec_reduce_min_ind or __sec_reduce_max_ind cannot"
177 " have arrays with dimension greater than 1");
178 return error_mark_node
;
181 extract_array_notation_exprs (func_parm
, true, &array_list
);
182 list_size
= vec_safe_length (array_list
);
185 case BUILT_IN_CILKPLUS_SEC_REDUCE_ADD
:
186 case BUILT_IN_CILKPLUS_SEC_REDUCE_MUL
:
187 case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX
:
188 case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN
:
189 new_var_type
= TREE_TYPE ((*array_list
)[0]);
191 case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_ZERO
:
192 case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_NONZERO
:
193 case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO
:
194 case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_NONZERO
:
195 new_var_type
= integer_type_node
;
197 case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
:
198 case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND
:
199 new_var_type
= integer_type_node
;
201 case BUILT_IN_CILKPLUS_SEC_REDUCE
:
202 if (call_fn
&& identity_value
)
203 new_var_type
= TREE_TYPE ((*array_list
)[0]);
205 case BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING
:
206 new_var_type
= NULL_TREE
;
212 array_ops
= XNEWVEC (tree
*, list_size
);
213 for (ii
= 0; ii
< list_size
; ii
++)
214 array_ops
[ii
] = XNEWVEC (tree
, rank
);
216 array_vector
= XNEWVEC (bool *, list_size
);
217 for (ii
= 0; ii
< list_size
; ii
++)
218 array_vector
[ii
] = XNEWVEC (bool, rank
);
220 array_value
= XNEWVEC (tree
*, list_size
);
221 array_stride
= XNEWVEC (tree
*, list_size
);
222 array_length
= XNEWVEC (tree
*, list_size
);
223 array_start
= XNEWVEC (tree
*, list_size
);
225 for (ii
= 0; ii
< list_size
; ii
++)
227 array_value
[ii
] = XNEWVEC (tree
, rank
);
228 array_stride
[ii
] = XNEWVEC (tree
, rank
);
229 array_length
[ii
] = XNEWVEC (tree
, rank
);
230 array_start
[ii
] = XNEWVEC (tree
, rank
);
233 compare_expr
= XNEWVEC (tree
, rank
);
234 expr_incr
= XNEWVEC (tree
, rank
);
235 ind_init
= XNEWVEC (tree
, rank
);
237 count_down
= XNEWVEC (bool *, list_size
);
238 for (ii
= 0; ii
< list_size
; ii
++)
239 count_down
[ii
] = XNEWVEC (bool, rank
);
241 array_var
= XNEWVEC (tree
, rank
);
243 for (ii
= 0; ii
< list_size
; ii
++)
246 for (jj_tree
= (*array_list
)[ii
];
247 jj_tree
&& TREE_CODE (jj_tree
) == ARRAY_NOTATION_REF
;
248 jj_tree
= ARRAY_NOTATION_ARRAY (jj_tree
))
250 array_ops
[ii
][jj
] = jj_tree
;
255 for (ii
= 0; ii
< list_size
; ii
++)
257 tree array_node
= (*array_list
)[ii
];
258 if (TREE_CODE (array_node
) == ARRAY_NOTATION_REF
)
260 for (jj
= 0; jj
< rank
; jj
++)
262 if (TREE_CODE (array_ops
[ii
][jj
]) == ARRAY_NOTATION_REF
)
264 array_value
[ii
][jj
] =
265 ARRAY_NOTATION_ARRAY (array_ops
[ii
][jj
]);
266 array_start
[ii
][jj
] =
267 ARRAY_NOTATION_START (array_ops
[ii
][jj
]);
268 array_length
[ii
][jj
] =
269 fold_build1 (CONVERT_EXPR
, integer_type_node
,
270 ARRAY_NOTATION_LENGTH (array_ops
[ii
][jj
]));
271 array_stride
[ii
][jj
] =
272 fold_build1 (CONVERT_EXPR
, integer_type_node
,
273 ARRAY_NOTATION_STRIDE (array_ops
[ii
][jj
]));
274 array_vector
[ii
][jj
] = true;
276 if (!TREE_CONSTANT (array_length
[ii
][jj
]))
277 count_down
[ii
][jj
] = false;
278 else if (tree_int_cst_lt
279 (array_length
[ii
][jj
],
280 build_int_cst (TREE_TYPE (array_length
[ii
][jj
]),
282 count_down
[ii
][jj
] = true;
284 count_down
[ii
][jj
] = false;
287 array_vector
[ii
][jj
] = false;
292 loop_init
= alloc_stmt_list ();
294 for (ii
= 0; ii
< rank
; ii
++)
296 array_var
[ii
] = build_decl (location
, VAR_DECL
, NULL_TREE
,
299 build_modify_expr (location
, array_var
[ii
],
300 TREE_TYPE (array_var
[ii
]), NOP_EXPR
,
302 build_int_cst (TREE_TYPE (array_var
[ii
]), 0),
303 TREE_TYPE (array_var
[ii
]));
305 for (ii
= 0; ii
< list_size
; ii
++)
307 if (array_vector
[ii
][0])
309 tree array_opr_node
= array_value
[ii
][rank
- 1];
310 for (s_jj
= rank
- 1; s_jj
>= 0; s_jj
--)
312 if (count_down
[ii
][s_jj
])
314 /* Array[start_index - (induction_var * stride)] */
315 array_opr_node
= build_array_ref
316 (location
, array_opr_node
,
317 build2 (MINUS_EXPR
, TREE_TYPE (array_var
[s_jj
]),
318 array_start
[ii
][s_jj
],
319 build2 (MULT_EXPR
, TREE_TYPE (array_var
[s_jj
]),
320 array_var
[s_jj
], array_stride
[ii
][s_jj
])));
324 /* Array[start_index + (induction_var * stride)] */
325 array_opr_node
= build_array_ref
326 (location
, array_opr_node
,
327 build2 (PLUS_EXPR
, TREE_TYPE (array_var
[s_jj
]),
328 array_start
[ii
][s_jj
],
329 build2 (MULT_EXPR
, TREE_TYPE (array_var
[s_jj
]),
330 array_var
[s_jj
], array_stride
[ii
][s_jj
])));
333 vec_safe_push (array_operand
, array_opr_node
);
336 /* This is just a dummy node to make sure the list sizes for both
337 array list and array operand list are the same. */
338 vec_safe_push (array_operand
, integer_one_node
);
340 replace_array_notations (&func_parm
, true, array_list
, array_operand
);
341 for (ii
= 0; ii
< rank
; ii
++)
343 build2 (MODIFY_EXPR
, void_type_node
, array_var
[ii
],
344 build2 (PLUS_EXPR
, TREE_TYPE (array_var
[ii
]), array_var
[ii
],
345 build_int_cst (TREE_TYPE (array_var
[ii
]), 1)));
346 for (jj
= 0; jj
< rank
; jj
++)
348 if (rank
&& expr_incr
[jj
])
350 if (count_down
[0][jj
])
352 build2 (LT_EXPR
, boolean_type_node
, array_var
[jj
],
353 build2 (MULT_EXPR
, TREE_TYPE (array_var
[jj
]),
355 build_int_cst (TREE_TYPE (array_var
[jj
]), -1)));
357 compare_expr
[jj
] = build2 (LT_EXPR
, boolean_type_node
,
358 array_var
[jj
], array_length
[0][jj
]);
362 if (an_type
!= BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING
)
364 *new_var
= build_decl (location
, VAR_DECL
, NULL_TREE
, new_var_type
);
365 gcc_assert (*new_var
&& *new_var
!= error_mark_node
);
368 *new_var
= NULL_TREE
;
370 if (an_type
== BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
371 || an_type
== BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND
)
372 array_ind_value
= build_decl (location
, VAR_DECL
, NULL_TREE
,
373 TREE_TYPE (func_parm
));
374 array_op0
= (*array_operand
)[0];
377 case BUILT_IN_CILKPLUS_SEC_REDUCE_ADD
:
378 new_var_init
= build_modify_expr
379 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
380 location
, build_zero_cst (new_var_type
), new_var_type
);
381 new_expr
= build_modify_expr
382 (location
, *new_var
, TREE_TYPE (*new_var
), PLUS_EXPR
,
383 location
, func_parm
, TREE_TYPE (func_parm
));
385 case BUILT_IN_CILKPLUS_SEC_REDUCE_MUL
:
386 new_var_init
= build_modify_expr
387 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
388 location
, build_one_cst (new_var_type
), new_var_type
);
389 new_expr
= build_modify_expr
390 (location
, *new_var
, TREE_TYPE (*new_var
), MULT_EXPR
,
391 location
, func_parm
, TREE_TYPE (func_parm
));
393 case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_ZERO
:
394 new_var_init
= build_modify_expr
395 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
396 location
, build_one_cst (new_var_type
), new_var_type
);
397 /* Initially you assume everything is zero, now if we find a case where
398 it is NOT true, then we set the result to false. Otherwise
399 we just keep the previous value. */
400 new_yes_expr
= build_modify_expr
401 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
402 location
, build_zero_cst (TREE_TYPE (*new_var
)),
403 TREE_TYPE (*new_var
));
404 new_no_expr
= build_modify_expr
405 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
406 location
, *new_var
, TREE_TYPE (*new_var
));
407 new_cond_expr
= build2 (NE_EXPR
, TREE_TYPE (func_parm
), func_parm
,
408 build_zero_cst (TREE_TYPE (func_parm
)));
409 new_expr
= build_conditional_expr
410 (location
, new_cond_expr
, false, new_yes_expr
,
411 TREE_TYPE (new_yes_expr
), new_no_expr
, TREE_TYPE (new_no_expr
));
413 case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_NONZERO
:
414 new_var_init
= build_modify_expr
415 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
416 location
, build_one_cst (new_var_type
), new_var_type
);
417 /* Initially you assume everything is non-zero, now if we find a case
418 where it is NOT true, then we set the result to false. Otherwise
419 we just keep the previous value. */
420 new_yes_expr
= build_modify_expr
421 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
422 location
, build_zero_cst (TREE_TYPE (*new_var
)),
423 TREE_TYPE (*new_var
));
424 new_no_expr
= build_modify_expr
425 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
426 location
, *new_var
, TREE_TYPE (*new_var
));
427 new_cond_expr
= build2 (EQ_EXPR
, TREE_TYPE (func_parm
), func_parm
,
428 build_zero_cst (TREE_TYPE (func_parm
)));
429 new_expr
= build_conditional_expr
430 (location
, new_cond_expr
, false, new_yes_expr
,
431 TREE_TYPE (new_yes_expr
), new_no_expr
, TREE_TYPE (new_no_expr
));
433 case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO
:
434 new_var_init
= build_modify_expr
435 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
436 location
, build_zero_cst (new_var_type
), new_var_type
);
437 /* Initially we assume there are NO zeros in the list. When we find
438 a non-zero, we keep the previous value. If we find a zero, we
439 set the value to true. */
440 new_yes_expr
= build_modify_expr
441 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
442 location
, build_one_cst (new_var_type
), new_var_type
);
443 new_no_expr
= build_modify_expr
444 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
445 location
, *new_var
, TREE_TYPE (*new_var
));
446 new_cond_expr
= build2 (EQ_EXPR
, TREE_TYPE (func_parm
), func_parm
,
447 build_zero_cst (TREE_TYPE (func_parm
)));
448 new_expr
= build_conditional_expr
449 (location
, new_cond_expr
, false, new_yes_expr
,
450 TREE_TYPE (new_yes_expr
), new_no_expr
, TREE_TYPE (new_no_expr
));
452 case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_NONZERO
:
453 new_var_init
= build_modify_expr
454 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
455 location
, build_zero_cst (new_var_type
), new_var_type
);
456 /* Initially we assume there are NO non-zeros in the list. When we find
457 a zero, we keep the previous value. If we find a non-zero, we set
458 the value to true. */
459 new_yes_expr
= build_modify_expr
460 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
461 location
, build_one_cst (new_var_type
), new_var_type
);
462 new_no_expr
= build_modify_expr
463 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
464 location
, *new_var
, TREE_TYPE (*new_var
));
465 new_cond_expr
= build2 (NE_EXPR
, TREE_TYPE (func_parm
), func_parm
,
466 build_zero_cst (TREE_TYPE (func_parm
)));
467 new_expr
= build_conditional_expr
468 (location
, new_cond_expr
, false, new_yes_expr
,
469 TREE_TYPE (new_yes_expr
), new_no_expr
, TREE_TYPE (new_no_expr
));
471 case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX
:
472 if (TYPE_MIN_VALUE (new_var_type
))
473 new_var_init
= build_modify_expr
474 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
475 location
, TYPE_MIN_VALUE (new_var_type
), new_var_type
);
477 new_var_init
= build_modify_expr
478 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
479 location
, func_parm
, new_var_type
);
480 new_no_expr
= build_modify_expr
481 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
482 location
, *new_var
, TREE_TYPE (*new_var
));
483 new_yes_expr
= build_modify_expr
484 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
485 location
, func_parm
, TREE_TYPE (*new_var
));
486 new_expr
= build_conditional_expr
488 build2 (LT_EXPR
, TREE_TYPE (*new_var
), *new_var
, func_parm
), false,
489 new_yes_expr
, TREE_TYPE (*new_var
), new_no_expr
, TREE_TYPE (*new_var
));
491 case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN
:
492 if (TYPE_MAX_VALUE (new_var_type
))
493 new_var_init
= build_modify_expr
494 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
495 location
, TYPE_MAX_VALUE (new_var_type
), new_var_type
);
497 new_var_init
= build_modify_expr
498 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
499 location
, func_parm
, new_var_type
);
500 new_no_expr
= build_modify_expr
501 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
502 location
, *new_var
, TREE_TYPE (*new_var
));
503 new_yes_expr
= build_modify_expr
504 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
505 location
, func_parm
, TREE_TYPE (*new_var
));
506 new_expr
= build_conditional_expr
508 build2 (GT_EXPR
, TREE_TYPE (*new_var
), *new_var
, func_parm
), false,
509 new_yes_expr
, TREE_TYPE (*new_var
), new_no_expr
, TREE_TYPE (*new_var
));
511 case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
:
512 new_var_init
= build_modify_expr
513 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
514 location
, build_zero_cst (new_var_type
), new_var_type
);
515 new_exp_init
= build_modify_expr
516 (location
, array_ind_value
, TREE_TYPE (array_ind_value
),
517 NOP_EXPR
, location
, func_parm
, TREE_TYPE (func_parm
));
518 new_no_ind
= build_modify_expr
519 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
520 location
, *new_var
, TREE_TYPE (*new_var
));
521 new_no_expr
= build_modify_expr
522 (location
, array_ind_value
, TREE_TYPE (array_ind_value
),
524 location
, array_ind_value
, TREE_TYPE (array_ind_value
));
527 new_yes_ind
= build_modify_expr
528 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
529 location
, array_var
[0], TREE_TYPE (array_var
[0]));
530 new_yes_expr
= build_modify_expr
531 (location
, array_ind_value
, TREE_TYPE (array_ind_value
),
533 location
, func_parm
, TREE_TYPE ((*array_operand
)[0]));
537 new_yes_ind
= build_modify_expr
538 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
539 location
, TREE_OPERAND (array_op0
, 1),
540 TREE_TYPE (TREE_OPERAND (array_op0
, 1)));
541 new_yes_expr
= build_modify_expr
542 (location
, array_ind_value
, TREE_TYPE (array_ind_value
),
544 location
, func_parm
, TREE_OPERAND (array_op0
, 1));
546 new_yes_list
= alloc_stmt_list ();
547 append_to_statement_list (new_yes_ind
, &new_yes_list
);
548 append_to_statement_list (new_yes_expr
, &new_yes_list
);
550 new_no_list
= alloc_stmt_list ();
551 append_to_statement_list (new_no_ind
, &new_no_list
);
552 append_to_statement_list (new_no_expr
, &new_no_list
);
554 new_expr
= build_conditional_expr
556 build2 (LE_EXPR
, TREE_TYPE (array_ind_value
), array_ind_value
,
559 new_yes_list
, TREE_TYPE (*new_var
), new_no_list
, TREE_TYPE (*new_var
));
561 case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND
:
562 new_var_init
= build_modify_expr
563 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
564 location
, build_zero_cst (new_var_type
), new_var_type
);
565 new_exp_init
= build_modify_expr
566 (location
, array_ind_value
, TREE_TYPE (array_ind_value
),
567 NOP_EXPR
, location
, func_parm
, TREE_TYPE (func_parm
));
568 new_no_ind
= build_modify_expr
569 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
570 location
, *new_var
, TREE_TYPE (*new_var
));
571 new_no_expr
= build_modify_expr
572 (location
, array_ind_value
, TREE_TYPE (array_ind_value
),
574 location
, array_ind_value
, TREE_TYPE (array_ind_value
));
577 new_yes_ind
= build_modify_expr
578 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
579 location
, array_var
[0], TREE_TYPE (array_var
[0]));
580 new_yes_expr
= build_modify_expr
581 (location
, array_ind_value
, TREE_TYPE (array_ind_value
),
583 location
, func_parm
, TREE_TYPE (array_op0
));
587 new_yes_ind
= build_modify_expr
588 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
589 location
, TREE_OPERAND (array_op0
, 1),
590 TREE_TYPE (TREE_OPERAND (array_op0
, 1)));
591 new_yes_expr
= build_modify_expr
592 (location
, array_ind_value
, TREE_TYPE (array_ind_value
),
594 location
, func_parm
, TREE_OPERAND (array_op0
, 1));
596 new_yes_list
= alloc_stmt_list ();
597 append_to_statement_list (new_yes_ind
, &new_yes_list
);
598 append_to_statement_list (new_yes_expr
, &new_yes_list
);
600 new_no_list
= alloc_stmt_list ();
601 append_to_statement_list (new_no_ind
, &new_no_list
);
602 append_to_statement_list (new_no_expr
, &new_no_list
);
604 new_expr
= build_conditional_expr
606 build2 (GE_EXPR
, TREE_TYPE (array_ind_value
), array_ind_value
,
609 new_yes_list
, TREE_TYPE (*new_var
), new_no_list
, TREE_TYPE (*new_var
));
611 case BUILT_IN_CILKPLUS_SEC_REDUCE
:
612 new_var_init
= build_modify_expr
613 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
614 location
, identity_value
, new_var_type
);
615 new_call_expr
= build_call_expr (call_fn
, 2, *new_var
, func_parm
);
616 new_expr
= build_modify_expr
617 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
618 location
, new_call_expr
, TREE_TYPE (*new_var
));
620 case BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING
:
621 new_expr
= build_call_expr (call_fn
, 2, identity_value
, func_parm
);
628 for (ii
= 0; ii
< rank
; ii
++)
629 append_to_statement_list (ind_init
[ii
], &loop_init
);
631 if (an_type
== BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
632 || an_type
== BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND
)
633 append_to_statement_list (new_exp_init
, &loop_init
);
634 if (an_type
!= BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING
)
635 append_to_statement_list (new_var_init
, &loop_init
);
637 append_to_statement_list_force (loop_init
, &loop_with_init
);
639 for (ii
= 0; ii
< rank
; ii
++)
641 tree new_loop
= push_stmt_list ();
642 c_finish_loop (location
, compare_expr
[ii
], expr_incr
[ii
], body
, NULL_TREE
,
644 body
= pop_stmt_list (new_loop
);
646 append_to_statement_list_force (body
, &loop_with_init
);
648 XDELETEVEC (compare_expr
);
649 XDELETEVEC (expr_incr
);
650 XDELETEVEC (ind_init
);
651 XDELETEVEC (array_var
);
652 for (ii
= 0; ii
< list_size
; ii
++)
654 XDELETEVEC (count_down
[ii
]);
655 XDELETEVEC (array_value
[ii
]);
656 XDELETEVEC (array_stride
[ii
]);
657 XDELETEVEC (array_length
[ii
]);
658 XDELETEVEC (array_start
[ii
]);
659 XDELETEVEC (array_ops
[ii
]);
660 XDELETEVEC (array_vector
[ii
]);
662 XDELETEVEC (count_down
);
663 XDELETEVEC (array_value
);
664 XDELETEVEC (array_stride
);
665 XDELETEVEC (array_length
);
666 XDELETEVEC (array_start
);
667 XDELETEVEC (array_ops
);
668 XDELETEVEC (array_vector
);
670 return loop_with_init
;
673 /* Returns a loop with ARRAY_REF inside it with an appropriate modify expr.
674 The LHS and/or RHS will be array notation expressions that have a MODIFYCODE
675 Their locations are specified by LHS_LOC, RHS_LOC. The location of the
676 modify expression is location. The original type of LHS and RHS are passed
677 in LHS_ORIGTYPE and RHS_ORIGTYPE. */
680 build_array_notation_expr (location_t location
, tree lhs
, tree lhs_origtype
,
681 enum tree_code modifycode
, location_t rhs_loc
,
682 tree rhs
, tree rhs_origtype
)
684 bool **lhs_vector
= NULL
, **rhs_vector
= NULL
, found_builtin_fn
= false;
685 tree
**lhs_array
= NULL
, **rhs_array
= NULL
;
686 tree array_expr_lhs
= NULL_TREE
, array_expr_rhs
= NULL_TREE
;
687 tree array_expr
= NULL_TREE
;
688 tree
**lhs_value
= NULL
, **rhs_value
= NULL
;
689 tree
**lhs_stride
= NULL
, **lhs_length
= NULL
, **lhs_start
= NULL
;
690 tree
**rhs_stride
= NULL
, **rhs_length
= NULL
, **rhs_start
= NULL
;
691 tree an_init
= NULL_TREE
, *lhs_var
= NULL
, *rhs_var
= NULL
;
692 tree
*cond_expr
= NULL
;
693 tree body
, loop_with_init
= alloc_stmt_list();
694 tree scalar_mods
= NULL_TREE
;
695 tree
*lhs_expr_incr
= NULL
, *rhs_expr_incr
= NULL
;
696 tree
*lhs_ind_init
= NULL
, *rhs_ind_init
= NULL
;
697 bool **lhs_count_down
= NULL
, **rhs_count_down
= NULL
;
698 tree
*lhs_compare
= NULL
, *rhs_compare
= NULL
;
699 vec
<tree
, va_gc
> *rhs_array_operand
= NULL
, *lhs_array_operand
= NULL
;
700 size_t lhs_rank
= 0, rhs_rank
= 0;
701 size_t ii
= 0, jj
= 0;
703 tree ii_tree
= NULL_TREE
, new_modify_expr
;
704 vec
<tree
, va_gc
> *lhs_list
= NULL
, *rhs_list
= NULL
;
705 tree new_var
= NULL_TREE
, builtin_loop
= NULL_TREE
;
706 tree begin_var
, lngth_var
, strde_var
;
707 size_t rhs_list_size
= 0, lhs_list_size
= 0;
709 /* If either of this is true, an error message must have been send out
710 already. Not necessary to send out multiple error messages. */
711 if (lhs
== error_mark_node
|| rhs
== error_mark_node
)
712 return error_mark_node
;
714 if (!find_rank (location
, rhs
, rhs
, false, &rhs_rank
))
715 return error_mark_node
;
717 extract_array_notation_exprs (rhs
, false, &rhs_list
);
718 rhs_list_size
= vec_safe_length (rhs_list
);
719 an_init
= push_stmt_list ();
722 scalar_mods
= replace_invariant_exprs (&rhs
);
724 add_stmt (scalar_mods
);
726 for (ii
= 0; ii
< rhs_list_size
; ii
++)
728 tree rhs_node
= (*rhs_list
)[ii
];
729 if (TREE_CODE (rhs_node
) == CALL_EXPR
)
731 builtin_loop
= fix_builtin_array_notation_fn (rhs_node
, &new_var
);
732 if (builtin_loop
== error_mark_node
)
734 pop_stmt_list (an_init
);
735 return error_mark_node
;
737 else if (builtin_loop
)
739 add_stmt (builtin_loop
);
740 found_builtin_fn
= true;
743 vec
<tree
, va_gc
> *rhs_sub_list
= NULL
, *new_var_list
= NULL
;
744 vec_safe_push (rhs_sub_list
, rhs_node
);
745 vec_safe_push (new_var_list
, new_var
);
746 replace_array_notations (&rhs
, false, rhs_sub_list
,
755 if (!find_rank (location
, lhs
, lhs
, true, &lhs_rank
))
757 pop_stmt_list (an_init
);
758 return error_mark_node
;
761 if (!find_rank (location
, rhs
, rhs
, true, &rhs_rank
))
763 pop_stmt_list (an_init
);
764 return error_mark_node
;
767 if (lhs_rank
== 0 && rhs_rank
== 0)
769 if (found_builtin_fn
)
771 new_modify_expr
= build_modify_expr (location
, lhs
, lhs_origtype
,
772 modifycode
, rhs_loc
, rhs
,
774 add_stmt (new_modify_expr
);
775 pop_stmt_list (an_init
);
780 pop_stmt_list (an_init
);
786 extract_array_notation_exprs (rhs
, true, &rhs_list
);
787 extract_array_notation_exprs (lhs
, true, &lhs_list
);
788 rhs_list_size
= vec_safe_length (rhs_list
);
789 lhs_list_size
= vec_safe_length (lhs_list
);
791 if (lhs_rank
== 0 && rhs_rank
!= 0 && TREE_CODE (rhs
) != CALL_EXPR
)
794 if (TREE_CODE (rhs_base
) == ARRAY_NOTATION_REF
)
796 for (ii
= 0; ii
< (size_t) rhs_rank
; ii
++)
797 rhs_base
= ARRAY_NOTATION_ARRAY (rhs
);
799 error_at (location
, "%qE cannot be scalar when %qE is not", lhs
,
801 return error_mark_node
;
805 error_at (location
, "%qE cannot be scalar when %qE is not", lhs
,
807 return error_mark_node
;
810 if (lhs_rank
!= 0 && rhs_rank
!= 0 && lhs_rank
!= rhs_rank
)
815 for (ii
= 0; ii
< lhs_rank
; ii
++)
816 lhs_base
= ARRAY_NOTATION_ARRAY (lhs_base
);
818 while (rhs_base
&& TREE_CODE (rhs_base
) != ARRAY_NOTATION_REF
)
819 rhs_base
= TREE_OPERAND (rhs_base
, 0);
820 for (ii
= 0; ii
< rhs_rank
; ii
++)
821 rhs_base
= ARRAY_NOTATION_ARRAY (rhs_base
);
823 error_at (location
, "rank mismatch between %qE and %qE", lhs
, rhs
);
824 pop_stmt_list (an_init
);
825 return error_mark_node
;
828 /* Here we assign the array notation components to variable so that we can
829 satisfy the exec once rule. */
830 for (ii
= 0; ii
< lhs_list_size
; ii
++)
832 tree array_node
= (*lhs_list
)[ii
];
833 tree array_begin
= ARRAY_NOTATION_START (array_node
);
834 tree array_lngth
= ARRAY_NOTATION_LENGTH (array_node
);
835 tree array_strde
= ARRAY_NOTATION_STRIDE (array_node
);
837 if (TREE_CODE (array_begin
) != INTEGER_CST
)
839 begin_var
= build_decl (location
, VAR_DECL
, NULL_TREE
,
841 add_stmt (build_modify_expr (location
, begin_var
,
842 TREE_TYPE (begin_var
),
843 NOP_EXPR
, location
, array_begin
,
844 TREE_TYPE (array_begin
)));
845 ARRAY_NOTATION_START (array_node
) = begin_var
;
848 if (TREE_CODE (array_lngth
) != INTEGER_CST
)
850 lngth_var
= build_decl (location
, VAR_DECL
, NULL_TREE
,
852 add_stmt (build_modify_expr (location
, lngth_var
,
853 TREE_TYPE (lngth_var
),
854 NOP_EXPR
, location
, array_lngth
,
855 TREE_TYPE (array_lngth
)));
856 ARRAY_NOTATION_LENGTH (array_node
) = lngth_var
;
858 if (TREE_CODE (array_strde
) != INTEGER_CST
)
860 strde_var
= build_decl (location
, VAR_DECL
, NULL_TREE
,
863 add_stmt (build_modify_expr (location
, strde_var
,
864 TREE_TYPE (strde_var
),
865 NOP_EXPR
, location
, array_strde
,
866 TREE_TYPE (array_strde
)));
867 ARRAY_NOTATION_STRIDE (array_node
) = strde_var
;
870 for (ii
= 0; ii
< rhs_list_size
; ii
++)
872 tree array_node
= (*rhs_list
)[ii
];
873 if (array_node
&& TREE_CODE (array_node
) == ARRAY_NOTATION_REF
)
875 tree array_begin
= ARRAY_NOTATION_START (array_node
);
876 tree array_lngth
= ARRAY_NOTATION_LENGTH (array_node
);
877 tree array_strde
= ARRAY_NOTATION_STRIDE (array_node
);
879 if (TREE_CODE (array_begin
) != INTEGER_CST
)
881 begin_var
= build_decl (location
, VAR_DECL
, NULL_TREE
,
883 add_stmt (build_modify_expr (location
, begin_var
,
884 TREE_TYPE (begin_var
),
885 NOP_EXPR
, location
, array_begin
,
886 TREE_TYPE (array_begin
)));
887 ARRAY_NOTATION_START (array_node
) = begin_var
;
889 if (TREE_CODE (array_lngth
) != INTEGER_CST
)
891 lngth_var
= build_decl (location
, VAR_DECL
, NULL_TREE
,
893 add_stmt (build_modify_expr (location
, lngth_var
,
894 TREE_TYPE (lngth_var
),
895 NOP_EXPR
, location
, array_lngth
,
896 TREE_TYPE (array_lngth
)));
897 ARRAY_NOTATION_LENGTH (array_node
) = lngth_var
;
899 if (TREE_CODE (array_strde
) != INTEGER_CST
)
901 strde_var
= build_decl (location
, VAR_DECL
, NULL_TREE
,
904 add_stmt (build_modify_expr (location
, strde_var
,
905 TREE_TYPE (strde_var
),
906 NOP_EXPR
, location
, array_strde
,
907 TREE_TYPE (array_strde
)));
908 ARRAY_NOTATION_STRIDE (array_node
) = strde_var
;
913 lhs_vector
= XNEWVEC (bool *, lhs_list_size
);
914 for (ii
= 0; ii
< lhs_list_size
; ii
++)
915 lhs_vector
[ii
] = XNEWVEC (bool, lhs_rank
);
917 rhs_vector
= XNEWVEC (bool *, rhs_list_size
);
918 for (ii
= 0; ii
< rhs_list_size
; ii
++)
919 rhs_vector
[ii
] = XNEWVEC (bool, rhs_rank
);
921 lhs_array
= XNEWVEC (tree
*, lhs_list_size
);
922 for (ii
= 0; ii
< lhs_list_size
; ii
++)
923 lhs_array
[ii
] = XNEWVEC (tree
, lhs_rank
);
925 rhs_array
= XNEWVEC (tree
*, rhs_list_size
);
926 for (ii
= 0; ii
< rhs_list_size
; ii
++)
927 rhs_array
[ii
] = XNEWVEC (tree
, rhs_rank
);
929 lhs_value
= XNEWVEC (tree
*, lhs_list_size
);
930 for (ii
= 0; ii
< lhs_list_size
; ii
++)
931 lhs_value
[ii
] = XNEWVEC (tree
, lhs_rank
);
933 rhs_value
= XNEWVEC (tree
*, rhs_list_size
);
934 for (ii
= 0; ii
< rhs_list_size
; ii
++)
935 rhs_value
[ii
] = XNEWVEC (tree
, rhs_rank
);
937 lhs_stride
= XNEWVEC (tree
*, lhs_list_size
);
938 for (ii
= 0; ii
< lhs_list_size
; ii
++)
939 lhs_stride
[ii
] = XNEWVEC (tree
, lhs_rank
);
941 rhs_stride
= XNEWVEC (tree
*, rhs_list_size
);
942 for (ii
= 0; ii
< rhs_list_size
; ii
++)
943 rhs_stride
[ii
] = XNEWVEC (tree
, rhs_rank
);
945 lhs_length
= XNEWVEC (tree
*, lhs_list_size
);
946 for (ii
= 0; ii
< lhs_list_size
; ii
++)
947 lhs_length
[ii
] = XNEWVEC (tree
, lhs_rank
);
949 rhs_length
= XNEWVEC (tree
*, rhs_list_size
);
950 for (ii
= 0; ii
< rhs_list_size
; ii
++)
951 rhs_length
[ii
] = XNEWVEC (tree
, rhs_rank
);
953 lhs_start
= XNEWVEC (tree
*, lhs_list_size
);
954 for (ii
= 0; ii
< lhs_list_size
; ii
++)
955 lhs_start
[ii
] = XNEWVEC (tree
, lhs_rank
);
957 rhs_start
= XNEWVEC (tree
*, rhs_list_size
);
958 for (ii
= 0; ii
< rhs_list_size
; ii
++)
959 rhs_start
[ii
] = XNEWVEC (tree
, rhs_rank
);
961 lhs_var
= XNEWVEC (tree
, lhs_rank
);
962 rhs_var
= XNEWVEC (tree
, rhs_rank
);
963 cond_expr
= XNEWVEC (tree
, MAX (lhs_rank
, rhs_rank
));
965 lhs_expr_incr
= XNEWVEC (tree
, lhs_rank
);
966 rhs_expr_incr
=XNEWVEC (tree
, rhs_rank
);
968 lhs_ind_init
= XNEWVEC (tree
, lhs_rank
);
969 rhs_ind_init
= XNEWVEC (tree
, rhs_rank
);
971 lhs_count_down
= XNEWVEC (bool *, lhs_list_size
);
972 for (ii
= 0; ii
< lhs_list_size
; ii
++)
973 lhs_count_down
[ii
] = XNEWVEC (bool, lhs_rank
);
975 rhs_count_down
= XNEWVEC (bool *, rhs_list_size
);
976 for (ii
= 0; ii
< rhs_list_size
; ii
++)
977 rhs_count_down
[ii
] = XNEWVEC (bool, rhs_rank
);
979 lhs_compare
= XNEWVEC (tree
, lhs_rank
);
980 rhs_compare
= XNEWVEC (tree
, rhs_rank
);
984 for (ii
= 0; ii
< lhs_list_size
; ii
++)
987 ii_tree
= (*lhs_list
)[ii
];
990 if (TREE_CODE (ii_tree
) == ARRAY_NOTATION_REF
)
992 lhs_array
[ii
][jj
] = ii_tree
;
994 ii_tree
= ARRAY_NOTATION_ARRAY (ii_tree
);
996 else if (TREE_CODE (ii_tree
) == ARRAY_REF
)
997 ii_tree
= TREE_OPERAND (ii_tree
, 0);
998 else if (TREE_CODE (ii_tree
) == VAR_DECL
999 || TREE_CODE (ii_tree
) == PARM_DECL
)
1005 lhs_array
[0][0] = NULL_TREE
;
1009 for (ii
= 0; ii
< rhs_list_size
; ii
++)
1012 ii_tree
= (*rhs_list
)[ii
];
1015 if (TREE_CODE (ii_tree
) == ARRAY_NOTATION_REF
)
1017 rhs_array
[ii
][jj
] = ii_tree
;
1019 ii_tree
= ARRAY_NOTATION_ARRAY (ii_tree
);
1021 else if (TREE_CODE (ii_tree
) == ARRAY_REF
)
1022 ii_tree
= TREE_OPERAND (ii_tree
, 0);
1023 else if (TREE_CODE (ii_tree
) == VAR_DECL
1024 || TREE_CODE (ii_tree
) == PARM_DECL
1025 || TREE_CODE (ii_tree
) == CALL_EXPR
)
1031 for (ii
= 0; ii
< lhs_list_size
; ii
++)
1033 tree lhs_node
= (*lhs_list
)[ii
];
1034 if (TREE_CODE (lhs_node
) == ARRAY_NOTATION_REF
)
1036 for (jj
= 0; jj
< lhs_rank
; jj
++)
1038 if (TREE_CODE (lhs_array
[ii
][jj
]) == ARRAY_NOTATION_REF
)
1040 lhs_value
[ii
][jj
] = ARRAY_NOTATION_ARRAY (lhs_array
[ii
][jj
]);
1041 lhs_start
[ii
][jj
] = ARRAY_NOTATION_START (lhs_array
[ii
][jj
]);
1042 lhs_length
[ii
][jj
] =
1043 fold_build1 (CONVERT_EXPR
, integer_type_node
,
1044 ARRAY_NOTATION_LENGTH (lhs_array
[ii
][jj
]));
1045 lhs_stride
[ii
][jj
] =
1046 fold_build1 (CONVERT_EXPR
, integer_type_node
,
1047 ARRAY_NOTATION_STRIDE (lhs_array
[ii
][jj
]));
1048 lhs_vector
[ii
][jj
] = true;
1049 /* IF the stride value is variable (i.e. not constant) then
1050 assume that the length is positive. */
1051 if (!TREE_CONSTANT (lhs_length
[ii
][jj
]))
1052 lhs_count_down
[ii
][jj
] = false;
1053 else if (tree_int_cst_lt
1054 (lhs_length
[ii
][jj
],
1055 build_zero_cst (TREE_TYPE (lhs_length
[ii
][jj
]))))
1056 lhs_count_down
[ii
][jj
] = true;
1058 lhs_count_down
[ii
][jj
] = false;
1061 lhs_vector
[ii
][jj
] = false;
1065 for (ii
= 0; ii
< rhs_list_size
; ii
++)
1067 if (TREE_CODE ((*rhs_list
)[ii
]) == ARRAY_NOTATION_REF
)
1069 for (jj
= 0; jj
< rhs_rank
; jj
++)
1071 if (TREE_CODE (rhs_array
[ii
][jj
]) == ARRAY_NOTATION_REF
)
1073 rhs_value
[ii
][jj
] = ARRAY_NOTATION_ARRAY (rhs_array
[ii
][jj
]);
1074 rhs_start
[ii
][jj
] = ARRAY_NOTATION_START (rhs_array
[ii
][jj
]);
1075 rhs_length
[ii
][jj
] =
1076 fold_build1 (CONVERT_EXPR
, integer_type_node
,
1077 ARRAY_NOTATION_LENGTH (rhs_array
[ii
][jj
]));
1078 rhs_stride
[ii
][jj
] =
1079 fold_build1 (CONVERT_EXPR
, integer_type_node
,
1080 ARRAY_NOTATION_STRIDE (rhs_array
[ii
][jj
]));
1081 rhs_vector
[ii
][jj
] = true;
1082 /* If the stride value is variable (i.e. not constant) then
1083 assume that the length is positive. */
1084 if (!TREE_CONSTANT (rhs_length
[ii
][jj
]))
1085 rhs_count_down
[ii
][jj
] = false;
1086 else if (tree_int_cst_lt
1087 (rhs_length
[ii
][jj
],
1088 build_int_cst (TREE_TYPE (rhs_length
[ii
][jj
]), 0)))
1089 rhs_count_down
[ii
][jj
] = true;
1091 rhs_count_down
[ii
][jj
] = false;
1094 rhs_vector
[ii
][jj
] = false;
1098 for (jj
= 0; jj
< rhs_rank
; jj
++)
1100 rhs_vector
[ii
][jj
] = false;
1101 rhs_length
[ii
][jj
] = NULL_TREE
;
1105 if (length_mismatch_in_expr_p (EXPR_LOCATION (lhs
), lhs_length
,
1106 lhs_list_size
, lhs_rank
)
1107 || length_mismatch_in_expr_p (EXPR_LOCATION (rhs
), rhs_length
,
1108 rhs_list_size
, rhs_rank
))
1110 pop_stmt_list (an_init
);
1111 return error_mark_node
;
1114 if (lhs_list_size
> 0 && rhs_list_size
> 0 && lhs_rank
> 0 && rhs_rank
> 0
1115 && TREE_CODE (lhs_length
[0][0]) == INTEGER_CST
1117 && TREE_CODE (rhs_length
[0][0]) == INTEGER_CST
)
1119 HOST_WIDE_INT l_length
= int_cst_value (lhs_length
[0][0]);
1120 HOST_WIDE_INT r_length
= int_cst_value (rhs_length
[0][0]);
1121 /* Length can be negative or positive. As long as the magnitude is OK,
1122 then the array notation is valid. */
1123 if (absu_hwi (l_length
) != absu_hwi (r_length
))
1125 error_at (location
, "length mismatch between LHS and RHS");
1126 pop_stmt_list (an_init
);
1127 return error_mark_node
;
1130 for (ii
= 0; ii
< lhs_rank
; ii
++)
1132 if (lhs_vector
[0][ii
])
1134 lhs_var
[ii
] = build_decl (location
, VAR_DECL
, NULL_TREE
,
1136 lhs_ind_init
[ii
] = build_modify_expr
1137 (location
, lhs_var
[ii
], TREE_TYPE (lhs_var
[ii
]),
1139 location
, build_zero_cst (TREE_TYPE (lhs_var
[ii
])),
1140 TREE_TYPE (lhs_var
[ii
]));
1144 for (ii
= 0; ii
< rhs_rank
; ii
++)
1146 /* When we have a polynomial, we assume that the indices are of type
1148 rhs_var
[ii
] = build_decl (location
, VAR_DECL
, NULL_TREE
,
1150 rhs_ind_init
[ii
] = build_modify_expr
1151 (location
, rhs_var
[ii
], TREE_TYPE (rhs_var
[ii
]),
1153 location
, build_int_cst (TREE_TYPE (rhs_var
[ii
]), 0),
1154 TREE_TYPE (rhs_var
[ii
]));
1158 for (ii
= 0; ii
< lhs_list_size
; ii
++)
1160 if (lhs_vector
[ii
][0])
1162 /* The last ARRAY_NOTATION element's ARRAY component should be
1163 the array's base value. */
1164 tree lhs_array_opr
= lhs_value
[ii
][lhs_rank
- 1];
1165 for (s_jj
= lhs_rank
- 1; s_jj
>= 0; s_jj
--)
1167 if (lhs_count_down
[ii
][s_jj
])
1168 /* Array[start_index + (induction_var * stride)]. */
1169 lhs_array_opr
= build_array_ref
1170 (location
, lhs_array_opr
,
1171 build2 (MINUS_EXPR
, TREE_TYPE (lhs_var
[s_jj
]),
1172 lhs_start
[ii
][s_jj
],
1173 build2 (MULT_EXPR
, TREE_TYPE (lhs_var
[s_jj
]),
1175 lhs_stride
[ii
][s_jj
])));
1177 lhs_array_opr
= build_array_ref
1178 (location
, lhs_array_opr
,
1179 build2 (PLUS_EXPR
, TREE_TYPE (lhs_var
[s_jj
]),
1180 lhs_start
[ii
][s_jj
],
1181 build2 (MULT_EXPR
, TREE_TYPE (lhs_var
[s_jj
]),
1183 lhs_stride
[ii
][s_jj
])));
1185 vec_safe_push (lhs_array_operand
, lhs_array_opr
);
1188 vec_safe_push (lhs_array_operand
, integer_one_node
);
1190 replace_array_notations (&lhs
, true, lhs_list
, lhs_array_operand
);
1191 array_expr_lhs
= lhs
;
1196 for (ii
= 0; ii
< rhs_list_size
; ii
++)
1198 if (rhs_vector
[ii
][0])
1200 tree rhs_array_opr
= rhs_value
[ii
][rhs_rank
- 1];
1201 for (s_jj
= rhs_rank
- 1; s_jj
>= 0; s_jj
--)
1203 if (rhs_count_down
[ii
][s_jj
])
1204 /* Array[start_index - (induction_var * stride)] */
1205 rhs_array_opr
= build_array_ref
1206 (location
, rhs_array_opr
,
1207 build2 (MINUS_EXPR
, TREE_TYPE (rhs_var
[s_jj
]),
1208 rhs_start
[ii
][s_jj
],
1209 build2 (MULT_EXPR
, TREE_TYPE (rhs_var
[s_jj
]),
1211 rhs_stride
[ii
][s_jj
])));
1213 /* Array[start_index + (induction_var * stride)] */
1214 rhs_array_opr
= build_array_ref
1215 (location
, rhs_array_opr
,
1216 build2 (PLUS_EXPR
, TREE_TYPE (rhs_var
[s_jj
]),
1217 rhs_start
[ii
][s_jj
],
1218 build2 (MULT_EXPR
, TREE_TYPE (rhs_var
[s_jj
]),
1220 rhs_stride
[ii
][s_jj
])));
1222 vec_safe_push (rhs_array_operand
, rhs_array_opr
);
1225 /* This is just a dummy node to make sure the list sizes for both
1226 array list and array operand list are the same. */
1227 vec_safe_push (rhs_array_operand
, integer_one_node
);
1230 for (ii
= 0; ii
< rhs_list_size
; ii
++)
1232 tree rhs_node
= (*rhs_list
)[ii
];
1233 if (TREE_CODE (rhs_node
) == CALL_EXPR
)
1236 tree func_name
= CALL_EXPR_FN (rhs_node
);
1237 if (TREE_CODE (func_name
) == ADDR_EXPR
)
1238 if (is_sec_implicit_index_fn (func_name
))
1241 extract_sec_implicit_index_arg (location
, rhs_node
);
1242 if (idx_value
== -1) /* This means we have an error. */
1243 return error_mark_node
;
1244 else if (idx_value
< (int) lhs_rank
&& idx_value
>= 0)
1245 vec_safe_push (rhs_array_operand
, lhs_var
[idx_value
]);
1249 tree lhs_base
= (*lhs_list
)[ii
];
1250 for (ee
= 0; ee
< lhs_rank
; ee
++)
1251 lhs_base
= ARRAY_NOTATION_ARRAY (lhs_base
);
1252 error_at (location
, "__sec_implicit_index argument %d "
1253 "must be less than rank of %qD", idx_value
,
1255 return error_mark_node
;
1260 replace_array_notations (&rhs
, true, rhs_list
, rhs_array_operand
);
1261 array_expr_rhs
= rhs
;
1265 for (ii
= 0; ii
< rhs_list_size
; ii
++)
1267 tree rhs_node
= (*rhs_list
)[ii
];
1268 if (TREE_CODE (rhs_node
) == CALL_EXPR
)
1271 tree func_name
= CALL_EXPR_FN (rhs_node
);
1272 if (TREE_CODE (func_name
) == ADDR_EXPR
)
1273 if (is_sec_implicit_index_fn (func_name
))
1276 extract_sec_implicit_index_arg (location
, rhs_node
);
1277 if (idx_value
== -1) /* This means we have an error. */
1278 return error_mark_node
;
1279 else if (idx_value
< (int) lhs_rank
&& idx_value
>= 0)
1280 vec_safe_push (rhs_array_operand
, lhs_var
[idx_value
]);
1284 tree lhs_base
= (*lhs_list
)[ii
];
1285 for (ee
= 0; ee
< lhs_rank
; ee
++)
1286 lhs_base
= ARRAY_NOTATION_ARRAY (lhs_base
);
1287 error_at (location
, "__sec_implicit_index argument %d "
1288 "must be less than rank of %qD", idx_value
,
1290 return error_mark_node
;
1295 replace_array_notations (&rhs
, true, rhs_list
, rhs_array_operand
);
1296 array_expr_rhs
= rhs
;
1297 rhs_expr_incr
[0] = NULL_TREE
;
1300 for (ii
= 0; ii
< rhs_rank
; ii
++)
1301 rhs_expr_incr
[ii
] = build2 (MODIFY_EXPR
, void_type_node
, rhs_var
[ii
],
1303 (PLUS_EXPR
, TREE_TYPE (rhs_var
[ii
]),
1305 build_one_cst (TREE_TYPE (rhs_var
[ii
]))));
1307 for (ii
= 0; ii
< lhs_rank
; ii
++)
1308 lhs_expr_incr
[ii
] = build2
1309 (MODIFY_EXPR
, void_type_node
, lhs_var
[ii
],
1310 build2 (PLUS_EXPR
, TREE_TYPE (lhs_var
[ii
]), lhs_var
[ii
],
1311 build_one_cst (TREE_TYPE (lhs_var
[ii
]))));
1313 /* If array_expr_lhs is NULL, then we have function that returns void or
1314 its return value is ignored. */
1315 if (!array_expr_lhs
)
1316 array_expr_lhs
= lhs
;
1318 array_expr
= build_modify_expr (location
, array_expr_lhs
, lhs_origtype
,
1319 modifycode
, rhs_loc
, array_expr_rhs
,
1322 for (jj
= 0; jj
< MAX (lhs_rank
, rhs_rank
); jj
++)
1324 if (rhs_rank
&& rhs_expr_incr
[jj
])
1328 lhs_compare
[jj
] = integer_one_node
;
1329 else if (lhs_count_down
[0][jj
])
1330 lhs_compare
[jj
] = build2
1331 (GT_EXPR
, boolean_type_node
, lhs_var
[jj
], lhs_length
[0][jj
]);
1333 lhs_compare
[jj
] = build2
1334 (LT_EXPR
, boolean_type_node
, lhs_var
[jj
], lhs_length
[0][jj
]);
1337 /* The reason why we have this here is for the following case:
1338 Array[:][:] = function_call(something) + Array2[:][:];
1340 So, we will skip the first operand of RHS and then go to the
1341 2nd to find whether we should count up or down. */
1343 for (iii
= 0; iii
< rhs_list_size
; iii
++)
1344 if (rhs_vector
[iii
][jj
])
1347 /* What we are doing here is this:
1348 We always count up, so:
1349 if (length is negative ==> which means we count down)
1350 we multiply length by -1 and count up => ii < -LENGTH
1352 we just count up, so we compare for ii < LENGTH
1354 if (rhs_count_down
[iii
][jj
])
1355 /* We use iii for rhs_length because that is the correct countdown
1357 rhs_compare
[jj
] = build2
1358 (LT_EXPR
, boolean_type_node
, rhs_var
[jj
],
1359 build2 (MULT_EXPR
, TREE_TYPE (rhs_var
[jj
]),
1360 rhs_length
[iii
][jj
],
1361 build_int_cst (TREE_TYPE (rhs_var
[jj
]), -1)));
1363 rhs_compare
[jj
] = build2 (LT_EXPR
, boolean_type_node
, rhs_var
[jj
],
1364 rhs_length
[iii
][jj
]);
1365 if (lhs_compare
[ii
] != integer_one_node
)
1366 cond_expr
[jj
] = build2 (TRUTH_ANDIF_EXPR
, void_type_node
,
1367 lhs_compare
[jj
], rhs_compare
[jj
]);
1369 cond_expr
[jj
] = rhs_compare
[jj
];
1373 if (lhs_count_down
[0][jj
])
1374 cond_expr
[jj
] = build2
1375 (GT_EXPR
, boolean_type_node
, lhs_var
[jj
], lhs_length
[0][jj
]);
1377 cond_expr
[jj
] = build2
1378 (LT_EXPR
, boolean_type_node
, lhs_var
[jj
], lhs_length
[0][jj
]);
1382 an_init
= pop_stmt_list (an_init
);
1383 append_to_statement_list_force (an_init
, &loop_with_init
);
1385 for (ii
= 0; ii
< MAX (lhs_rank
, rhs_rank
); ii
++)
1387 tree incr_list
= alloc_stmt_list ();
1388 tree new_loop
= push_stmt_list ();
1390 add_stmt (lhs_ind_init
[ii
]);
1392 add_stmt (rhs_ind_init
[ii
]);
1394 append_to_statement_list_force (lhs_expr_incr
[ii
], &incr_list
);
1395 if (rhs_rank
&& rhs_expr_incr
[ii
])
1396 append_to_statement_list_force (rhs_expr_incr
[ii
], &incr_list
);
1397 c_finish_loop (location
, cond_expr
[ii
], incr_list
, body
, NULL_TREE
,
1399 body
= pop_stmt_list (new_loop
);
1401 append_to_statement_list_force (body
, &loop_with_init
);
1402 return loop_with_init
;
1405 /* Helper function for fix_conditional_array_notations. Encloses the
1406 conditional statement passed in STMT with a loop around it
1407 and replaces the condition in STMT with a ARRAY_REF tree-node to the array.
1408 The condition must have an ARRAY_NOTATION_REF tree. An expansion of array
1409 notation in STMT is returned in a STATEMENT_LIST. */
1412 fix_conditional_array_notations_1 (tree stmt
)
1414 vec
<tree
, va_gc
> *array_list
= NULL
, *array_operand
= NULL
;
1415 size_t list_size
= 0;
1416 tree cond
= NULL_TREE
, builtin_loop
= NULL_TREE
, new_var
= NULL_TREE
;
1417 size_t rank
= 0, ii
= 0, jj
= 0;
1419 tree
**array_ops
, *array_var
, jj_tree
, loop_init
;
1420 tree
**array_value
, **array_stride
, **array_length
, **array_start
;
1421 tree
*compare_expr
, *expr_incr
, *ind_init
;
1422 bool **count_down
, **array_vector
;
1423 tree begin_var
, lngth_var
, strde_var
;
1424 location_t location
= EXPR_LOCATION (stmt
);
1425 tree body
= NULL_TREE
, loop_with_init
= alloc_stmt_list ();
1426 if (TREE_CODE (stmt
) == COND_EXPR
)
1427 cond
= COND_EXPR_COND (stmt
);
1428 else if (TREE_CODE (stmt
) == SWITCH_EXPR
)
1429 cond
= SWITCH_COND (stmt
);
1431 /* Otherwise dont even touch the statement. */
1434 if (!find_rank (location
, cond
, cond
, false, &rank
))
1435 return error_mark_node
;
1437 extract_array_notation_exprs (stmt
, false, &array_list
);
1438 loop_init
= push_stmt_list ();
1439 for (ii
= 0; ii
< vec_safe_length (array_list
); ii
++)
1441 tree array_node
= (*array_list
)[ii
];
1442 if (TREE_CODE (array_node
) == CALL_EXPR
)
1444 builtin_loop
= fix_builtin_array_notation_fn (array_node
, &new_var
);
1445 if (builtin_loop
== error_mark_node
)
1447 add_stmt (error_mark_node
);
1448 pop_stmt_list (loop_init
);
1451 else if (builtin_loop
)
1453 vec
<tree
, va_gc
>* sub_list
= NULL
, *new_var_list
= NULL
;
1454 vec_safe_push (sub_list
, array_node
);
1455 vec_safe_push (new_var_list
, new_var
);
1456 add_stmt (builtin_loop
);
1457 replace_array_notations (&stmt
, false, sub_list
, new_var_list
);
1462 if (!find_rank (location
, stmt
, stmt
, true, &rank
))
1464 pop_stmt_list (loop_init
);
1465 return error_mark_node
;
1470 pop_stmt_list (loop_init
);
1473 extract_array_notation_exprs (stmt
, true, &array_list
);
1475 if (vec_safe_length (array_list
) == 0)
1478 list_size
= vec_safe_length (array_list
);
1480 array_ops
= XNEWVEC (tree
*, list_size
);
1481 for (ii
= 0; ii
< list_size
; ii
++)
1482 array_ops
[ii
] = XNEWVEC (tree
, rank
);
1484 array_vector
= XNEWVEC (bool *, list_size
);
1485 for (ii
= 0; ii
< list_size
; ii
++)
1486 array_vector
[ii
] = XNEWVEC (bool, rank
);
1488 array_value
= XNEWVEC (tree
*, list_size
);
1489 array_stride
= XNEWVEC (tree
*, list_size
);
1490 array_length
= XNEWVEC (tree
*, list_size
);
1491 array_start
= XNEWVEC (tree
*, list_size
);
1493 for (ii
= 0; ii
< list_size
; ii
++)
1495 array_value
[ii
] = XNEWVEC (tree
, rank
);
1496 array_stride
[ii
] = XNEWVEC (tree
, rank
);
1497 array_length
[ii
] = XNEWVEC (tree
, rank
);
1498 array_start
[ii
] = XNEWVEC (tree
, rank
);
1501 compare_expr
= XNEWVEC (tree
, rank
);
1502 expr_incr
= XNEWVEC (tree
, rank
);
1503 ind_init
= XNEWVEC (tree
, rank
);
1505 count_down
= XNEWVEC (bool *, list_size
);
1506 for (ii
= 0; ii
< list_size
; ii
++)
1507 count_down
[ii
] = XNEWVEC (bool, rank
);
1509 array_var
= XNEWVEC (tree
, rank
);
1511 for (ii
= 0; ii
< list_size
; ii
++)
1513 tree array_node
= (*array_list
)[ii
];
1514 if (array_node
&& TREE_CODE (array_node
) == ARRAY_NOTATION_REF
)
1516 tree array_begin
= ARRAY_NOTATION_START (array_node
);
1517 tree array_lngth
= ARRAY_NOTATION_LENGTH (array_node
);
1518 tree array_strde
= ARRAY_NOTATION_STRIDE (array_node
);
1520 if (TREE_CODE (array_begin
) != INTEGER_CST
)
1522 begin_var
= build_decl (location
, VAR_DECL
, NULL_TREE
,
1524 add_stmt (build_modify_expr (location
, begin_var
,
1525 TREE_TYPE (begin_var
),
1526 NOP_EXPR
, location
, array_begin
,
1527 TREE_TYPE (array_begin
)));
1528 ARRAY_NOTATION_START (array_node
) = begin_var
;
1530 if (TREE_CODE (array_lngth
) != INTEGER_CST
)
1532 lngth_var
= build_decl (location
, VAR_DECL
, NULL_TREE
,
1534 add_stmt (build_modify_expr (location
, lngth_var
,
1535 TREE_TYPE (lngth_var
),
1536 NOP_EXPR
, location
, array_lngth
,
1537 TREE_TYPE (array_lngth
)));
1538 ARRAY_NOTATION_LENGTH (array_node
) = lngth_var
;
1540 if (TREE_CODE (array_strde
) != INTEGER_CST
)
1542 strde_var
= build_decl (location
, VAR_DECL
, NULL_TREE
,
1544 add_stmt (build_modify_expr (location
, strde_var
,
1545 TREE_TYPE (strde_var
),
1546 NOP_EXPR
, location
, array_strde
,
1547 TREE_TYPE (array_strde
)));
1548 ARRAY_NOTATION_STRIDE (array_node
) = strde_var
;
1552 for (ii
= 0; ii
< list_size
; ii
++)
1554 tree array_node
= (*array_list
)[ii
];
1556 for (jj_tree
= array_node
;
1557 jj_tree
&& TREE_CODE (jj_tree
) == ARRAY_NOTATION_REF
;
1558 jj_tree
= ARRAY_NOTATION_ARRAY (jj_tree
))
1560 array_ops
[ii
][jj
] = jj_tree
;
1564 for (ii
= 0; ii
< list_size
; ii
++)
1566 tree array_node
= (*array_list
)[ii
];
1567 if (TREE_CODE (array_node
) == ARRAY_NOTATION_REF
)
1569 for (jj
= 0; jj
< rank
; jj
++)
1571 if (TREE_CODE (array_ops
[ii
][jj
]) == ARRAY_NOTATION_REF
)
1573 array_value
[ii
][jj
] =
1574 ARRAY_NOTATION_ARRAY (array_ops
[ii
][jj
]);
1575 array_start
[ii
][jj
] =
1576 ARRAY_NOTATION_START (array_ops
[ii
][jj
]);
1577 array_length
[ii
][jj
] =
1578 fold_build1 (CONVERT_EXPR
, integer_type_node
,
1579 ARRAY_NOTATION_LENGTH (array_ops
[ii
][jj
]));
1580 array_stride
[ii
][jj
] =
1581 fold_build1 (CONVERT_EXPR
, integer_type_node
,
1582 ARRAY_NOTATION_STRIDE (array_ops
[ii
][jj
]));
1583 array_vector
[ii
][jj
] = true;
1585 if (!TREE_CONSTANT (array_length
[ii
][jj
]))
1586 count_down
[ii
][jj
] = false;
1587 else if (tree_int_cst_lt
1588 (array_length
[ii
][jj
],
1589 build_int_cst (TREE_TYPE (array_length
[ii
][jj
]),
1591 count_down
[ii
][jj
] = true;
1593 count_down
[ii
][jj
] = false;
1596 array_vector
[ii
][jj
] = false;
1601 for (ii
= 0; ii
< rank
; ii
++)
1603 array_var
[ii
] = build_decl (location
, VAR_DECL
, NULL_TREE
,
1606 build_modify_expr (location
, array_var
[ii
],
1607 TREE_TYPE (array_var
[ii
]), NOP_EXPR
,
1609 build_int_cst (TREE_TYPE (array_var
[ii
]), 0),
1610 TREE_TYPE (array_var
[ii
]));
1613 for (ii
= 0; ii
< list_size
; ii
++)
1615 if (array_vector
[ii
][0])
1617 tree array_opr
= array_value
[ii
][rank
- 1];
1618 for (s_jj
= rank
- 1; s_jj
>= 0; s_jj
--)
1620 if (count_down
[ii
][s_jj
])
1621 /* Array[start_index - (induction_var * stride)] */
1622 array_opr
= build_array_ref
1623 (location
, array_opr
,
1624 build2 (MINUS_EXPR
, TREE_TYPE (array_var
[s_jj
]),
1625 array_start
[ii
][s_jj
],
1626 build2 (MULT_EXPR
, TREE_TYPE (array_var
[s_jj
]),
1627 array_var
[s_jj
], array_stride
[ii
][s_jj
])));
1629 /* Array[start_index + (induction_var * stride)] */
1630 array_opr
= build_array_ref
1631 (location
, array_opr
,
1632 build2 (PLUS_EXPR
, TREE_TYPE (array_var
[s_jj
]),
1633 array_start
[ii
][s_jj
],
1634 build2 (MULT_EXPR
, TREE_TYPE (array_var
[s_jj
]),
1635 array_var
[s_jj
], array_stride
[ii
][s_jj
])));
1637 vec_safe_push (array_operand
, array_opr
);
1640 /* This is just a dummy node to make sure the list sizes for both
1641 array list and array operand list are the same. */
1642 vec_safe_push (array_operand
, integer_one_node
);
1644 replace_array_notations (&stmt
, true, array_list
, array_operand
);
1645 for (ii
= 0; ii
< rank
; ii
++)
1646 expr_incr
[ii
] = build2 (MODIFY_EXPR
, void_type_node
, array_var
[ii
],
1647 build2 (PLUS_EXPR
, TREE_TYPE (array_var
[ii
]),
1649 build_int_cst (TREE_TYPE (array_var
[ii
]),
1651 for (jj
= 0; jj
< rank
; jj
++)
1653 if (rank
&& expr_incr
[jj
])
1655 if (count_down
[0][jj
])
1657 build2 (LT_EXPR
, boolean_type_node
, array_var
[jj
],
1658 build2 (MULT_EXPR
, TREE_TYPE (array_var
[jj
]),
1659 array_length
[0][jj
],
1660 build_int_cst (TREE_TYPE (array_var
[jj
]), -1)));
1662 compare_expr
[jj
] = build2 (LT_EXPR
, boolean_type_node
,
1663 array_var
[jj
], array_length
[0][jj
]);
1667 loop_init
= pop_stmt_list (loop_init
);
1669 append_to_statement_list_force (loop_init
, &loop_with_init
);
1671 for (ii
= 0; ii
< rank
; ii
++)
1673 tree new_loop
= push_stmt_list ();
1674 add_stmt (ind_init
[ii
]);
1675 c_finish_loop (location
, compare_expr
[ii
], expr_incr
[ii
], body
, NULL_TREE
,
1677 body
= pop_stmt_list (new_loop
);
1679 append_to_statement_list_force (body
, &loop_with_init
);
1680 XDELETEVEC (expr_incr
);
1681 XDELETEVEC (ind_init
);
1683 for (ii
= 0; ii
< list_size
; ii
++)
1685 XDELETEVEC (count_down
[ii
]);
1686 XDELETEVEC (array_value
[ii
]);
1687 XDELETEVEC (array_stride
[ii
]);
1688 XDELETEVEC (array_length
[ii
]);
1689 XDELETEVEC (array_start
[ii
]);
1690 XDELETEVEC (array_ops
[ii
]);
1691 XDELETEVEC (array_vector
[ii
]);
1694 XDELETEVEC (count_down
);
1695 XDELETEVEC (array_value
);
1696 XDELETEVEC (array_stride
);
1697 XDELETEVEC (array_length
);
1698 XDELETEVEC (array_start
);
1699 XDELETEVEC (array_ops
);
1700 XDELETEVEC (array_vector
);
1702 return loop_with_init
;
1705 /* Top-level function to replace ARRAY_NOTATION_REF in a conditional statement
1706 in STMT. An expansion of array notation in STMT is returned as a
1710 fix_conditional_array_notations (tree stmt
)
1712 if (TREE_CODE (stmt
) == STATEMENT_LIST
)
1714 tree_stmt_iterator tsi
;
1715 for (tsi
= tsi_start (stmt
); !tsi_end_p (tsi
); tsi_next (&tsi
))
1717 tree single_stmt
= *tsi_stmt_ptr (tsi
);
1718 *tsi_stmt_ptr (tsi
) =
1719 fix_conditional_array_notations_1 (single_stmt
);
1724 return fix_conditional_array_notations_1 (stmt
);
1727 /* Create a struct c_expr that contains a loop with ARRAY_REF expr at location
1728 LOCATION with the tree_code CODE and the array notation expr is
1729 passed in ARG. Returns the fixed c_expr in ARG itself. */
1732 fix_array_notation_expr (location_t location
, enum tree_code code
,
1736 vec
<tree
, va_gc
> *array_list
= NULL
, *array_operand
= NULL
;
1737 size_t list_size
= 0, rank
= 0, ii
= 0, jj
= 0;
1739 tree
**array_ops
, *array_var
, jj_tree
, loop_init
;
1740 tree
**array_value
, **array_stride
, **array_length
, **array_start
;
1741 tree
*compare_expr
, *expr_incr
, *ind_init
;
1742 tree body
, loop_with_init
= alloc_stmt_list ();
1743 bool **count_down
, **array_vector
;
1745 if (!find_rank (location
, arg
.value
, arg
.value
, false, &rank
))
1747 /* If this function returns a NULL, we convert the tree value in the
1748 structure to error_mark_node and the parser should take care of the
1750 arg
.value
= error_mark_node
;
1757 extract_array_notation_exprs (arg
.value
, true, &array_list
);
1759 if (vec_safe_length (array_list
) == 0)
1762 list_size
= vec_safe_length (array_list
);
1764 array_ops
= XNEWVEC (tree
*, list_size
);
1765 for (ii
= 0; ii
< list_size
; ii
++)
1766 array_ops
[ii
] = XNEWVEC (tree
, rank
);
1768 array_vector
= XNEWVEC (bool *, list_size
);
1769 for (ii
= 0; ii
< list_size
; ii
++)
1770 array_vector
[ii
] = XNEWVEC (bool, rank
);
1772 array_value
= XNEWVEC (tree
*, list_size
);
1773 array_stride
= XNEWVEC (tree
*, list_size
);
1774 array_length
= XNEWVEC (tree
*, list_size
);
1775 array_start
= XNEWVEC (tree
*, list_size
);
1777 for (ii
= 0; ii
< list_size
; ii
++)
1779 array_value
[ii
] = XNEWVEC (tree
, rank
);
1780 array_stride
[ii
] = XNEWVEC (tree
, rank
);
1781 array_length
[ii
] = XNEWVEC (tree
, rank
);
1782 array_start
[ii
] = XNEWVEC (tree
, rank
);
1785 compare_expr
= XNEWVEC (tree
, rank
);
1786 expr_incr
= XNEWVEC (tree
, rank
);
1787 ind_init
= XNEWVEC (tree
, rank
);
1789 count_down
= XNEWVEC (bool *, list_size
);
1790 for (ii
= 0; ii
< list_size
; ii
++)
1791 count_down
[ii
] = XNEWVEC (bool, rank
);
1792 array_var
= XNEWVEC (tree
, rank
);
1794 for (ii
= 0; ii
< list_size
; ii
++)
1797 for (jj_tree
= (*array_list
)[ii
];
1798 jj_tree
&& TREE_CODE (jj_tree
) == ARRAY_NOTATION_REF
;
1799 jj_tree
= ARRAY_NOTATION_ARRAY (jj_tree
))
1801 array_ops
[ii
][jj
] = jj_tree
;
1806 loop_init
= push_stmt_list ();
1808 for (ii
= 0; ii
< list_size
; ii
++)
1810 tree array_node
= (*array_list
)[ii
];
1811 if (TREE_CODE (array_node
) == ARRAY_NOTATION_REF
)
1813 for (jj
= 0; jj
< rank
; jj
++)
1815 if (TREE_CODE (array_ops
[ii
][jj
]) == ARRAY_NOTATION_REF
)
1817 array_value
[ii
][jj
] =
1818 ARRAY_NOTATION_ARRAY (array_ops
[ii
][jj
]);
1819 array_start
[ii
][jj
] =
1820 ARRAY_NOTATION_START (array_ops
[ii
][jj
]);
1821 array_length
[ii
][jj
] =
1822 fold_build1 (CONVERT_EXPR
, integer_type_node
,
1823 ARRAY_NOTATION_LENGTH (array_ops
[ii
][jj
]));
1824 array_stride
[ii
][jj
] =
1825 fold_build1 (CONVERT_EXPR
, integer_type_node
,
1826 ARRAY_NOTATION_STRIDE (array_ops
[ii
][jj
]));
1827 array_vector
[ii
][jj
] = true;
1829 if (!TREE_CONSTANT (array_length
[ii
][jj
]))
1830 count_down
[ii
][jj
] = false;
1831 else if (tree_int_cst_lt
1832 (array_length
[ii
][jj
],
1833 build_int_cst (TREE_TYPE (array_length
[ii
][jj
]),
1835 count_down
[ii
][jj
] = true;
1837 count_down
[ii
][jj
] = false;
1840 array_vector
[ii
][jj
] = false;
1845 for (ii
= 0; ii
< rank
; ii
++)
1847 array_var
[ii
] = build_decl (location
, VAR_DECL
, NULL_TREE
,
1850 build_modify_expr (location
, array_var
[ii
],
1851 TREE_TYPE (array_var
[ii
]), NOP_EXPR
,
1853 build_int_cst (TREE_TYPE (array_var
[ii
]), 0),
1854 TREE_TYPE (array_var
[ii
]));
1857 for (ii
= 0; ii
< list_size
; ii
++)
1859 if (array_vector
[ii
][0])
1861 tree array_opr
= array_value
[ii
][rank
- 1];
1862 for (s_jj
= rank
- 1; s_jj
>= 0; s_jj
--)
1864 if (count_down
[ii
][s_jj
])
1865 /* Array[start_index - (induction_var * stride)] */
1866 array_opr
= build_array_ref
1867 (location
, array_opr
,
1868 build2 (MINUS_EXPR
, TREE_TYPE (array_var
[s_jj
]),
1869 array_start
[ii
][s_jj
],
1870 build2 (MULT_EXPR
, TREE_TYPE (array_var
[s_jj
]),
1871 array_var
[s_jj
], array_stride
[ii
][s_jj
])));
1873 /* Array[start_index + (induction_var * stride)] */
1874 array_opr
= build_array_ref
1875 (location
, array_opr
,
1876 build2 (PLUS_EXPR
, TREE_TYPE (array_var
[s_jj
]),
1877 array_start
[ii
][s_jj
],
1878 build2 (MULT_EXPR
, TREE_TYPE (array_var
[s_jj
]),
1879 array_var
[s_jj
], array_stride
[ii
][s_jj
])));
1881 vec_safe_push (array_operand
, array_opr
);
1884 /* This is just a dummy node to make sure the list sizes for both
1885 array list and array operand list are the same. */
1886 vec_safe_push (array_operand
, integer_one_node
);
1888 replace_array_notations (&arg
.value
, true, array_list
, array_operand
);
1890 for (ii
= 0; ii
< rank
; ii
++)
1892 build2 (MODIFY_EXPR
, void_type_node
, array_var
[ii
],
1893 build2 (PLUS_EXPR
, TREE_TYPE (array_var
[ii
]), array_var
[ii
],
1894 build_int_cst (TREE_TYPE (array_var
[ii
]), 1)));
1896 for (jj
= 0; jj
< rank
; jj
++)
1898 if (rank
&& expr_incr
[jj
])
1900 if (count_down
[0][jj
])
1902 build2 (LT_EXPR
, boolean_type_node
, array_var
[jj
],
1903 build2 (MULT_EXPR
, TREE_TYPE (array_var
[jj
]),
1904 array_length
[0][jj
],
1905 build_int_cst (TREE_TYPE (array_var
[jj
]), -1)));
1907 compare_expr
[jj
] = build2 (LT_EXPR
, boolean_type_node
,
1908 array_var
[jj
], array_length
[0][jj
]);
1912 if (code
== POSTINCREMENT_EXPR
|| code
== POSTDECREMENT_EXPR
)
1914 arg
= default_function_array_read_conversion (location
, arg
);
1915 arg
.value
= build_unary_op (location
, code
, arg
.value
, 0);
1917 else if (code
== PREINCREMENT_EXPR
|| code
== PREDECREMENT_EXPR
)
1919 arg
= default_function_array_read_conversion (location
, arg
);
1920 arg
= parser_build_unary_op (location
, code
, arg
);
1923 loop_init
= pop_stmt_list (loop_init
);
1924 append_to_statement_list_force (loop_init
, &loop_with_init
);
1927 for (ii
= 0; ii
< rank
; ii
++)
1929 tree new_loop
= push_stmt_list ();
1930 add_stmt (ind_init
[ii
]);
1931 c_finish_loop (location
, compare_expr
[ii
], expr_incr
[ii
], body
, NULL_TREE
,
1933 body
= pop_stmt_list (new_loop
);
1935 append_to_statement_list_force (body
, &loop_with_init
);
1936 XDELETEVEC (expr_incr
);
1937 XDELETEVEC (ind_init
);
1938 XDELETEVEC (array_var
);
1940 for (ii
= 0; ii
< list_size
; ii
++)
1942 XDELETEVEC (count_down
[ii
]);
1943 XDELETEVEC (array_value
[ii
]);
1944 XDELETEVEC (array_stride
[ii
]);
1945 XDELETEVEC (array_length
[ii
]);
1946 XDELETEVEC (array_start
[ii
]);
1947 XDELETEVEC (array_ops
[ii
]);
1948 XDELETEVEC (array_vector
[ii
]);
1951 XDELETEVEC (count_down
);
1952 XDELETEVEC (array_value
);
1953 XDELETEVEC (array_stride
);
1954 XDELETEVEC (array_length
);
1955 XDELETEVEC (array_start
);
1956 XDELETEVEC (array_ops
);
1957 XDELETEVEC (array_vector
);
1959 arg
.value
= loop_with_init
;
1963 /* Replaces array notations in a void function call arguments in ARG and returns
1964 a STATEMENT_LIST. */
1967 fix_array_notation_call_expr (tree arg
)
1969 vec
<tree
, va_gc
> *array_list
= NULL
, *array_operand
= NULL
;
1970 tree new_var
= NULL_TREE
;
1971 size_t list_size
= 0, rank
= 0, ii
= 0, jj
= 0;
1973 tree
**array_ops
, *array_var
, jj_tree
, loop_init
;
1974 tree
**array_value
, **array_stride
, **array_length
, **array_start
;
1975 tree body
, loop_with_init
= alloc_stmt_list ();
1976 tree
*compare_expr
, *expr_incr
, *ind_init
;
1977 bool **count_down
, **array_vector
;
1978 tree begin_var
, lngth_var
, strde_var
;
1979 location_t location
= UNKNOWN_LOCATION
;
1981 if (TREE_CODE (arg
) == CALL_EXPR
1982 && is_cilkplus_reduce_builtin (CALL_EXPR_FN (arg
)))
1984 loop_init
= fix_builtin_array_notation_fn (arg
, &new_var
);
1985 /* We are ignoring the new var because either the user does not want to
1986 capture it OR he is using sec_reduce_mutating function. */
1990 if (!find_rank (location
, arg
, arg
, false, &rank
))
1991 return error_mark_node
;
1996 extract_array_notation_exprs (arg
, true, &array_list
);
1997 if (vec_safe_length (array_list
) == 0)
2000 list_size
= vec_safe_length (array_list
);
2001 location
= EXPR_LOCATION (arg
);
2003 array_ops
= XNEWVEC (tree
*, list_size
);
2004 for (ii
= 0; ii
< list_size
; ii
++)
2005 array_ops
[ii
] = XNEWVEC (tree
, rank
);
2007 array_vector
= XNEWVEC (bool *, list_size
);
2008 for (ii
= 0; ii
< list_size
; ii
++)
2009 array_vector
[ii
] = (bool *) XNEWVEC (bool, rank
);
2011 array_value
= XNEWVEC (tree
*, list_size
);
2012 array_stride
= XNEWVEC (tree
*, list_size
);
2013 array_length
= XNEWVEC (tree
*, list_size
);
2014 array_start
= XNEWVEC (tree
*, list_size
);
2016 for (ii
= 0; ii
< list_size
; ii
++)
2018 array_value
[ii
] = XNEWVEC (tree
, rank
);
2019 array_stride
[ii
] = XNEWVEC (tree
, rank
);
2020 array_length
[ii
] = XNEWVEC (tree
, rank
);
2021 array_start
[ii
] = XNEWVEC (tree
, rank
);
2024 compare_expr
= XNEWVEC (tree
, rank
);
2025 expr_incr
= XNEWVEC (tree
, rank
);
2026 ind_init
= XNEWVEC (tree
, rank
);
2028 count_down
= XNEWVEC (bool *, list_size
);
2029 for (ii
= 0; ii
< list_size
; ii
++)
2030 count_down
[ii
] = XNEWVEC (bool, rank
);
2032 array_var
= XNEWVEC (tree
, rank
);
2034 loop_init
= push_stmt_list ();
2035 for (ii
= 0; ii
< list_size
; ii
++)
2037 tree array_node
= (*array_list
)[ii
];
2038 if (array_node
&& TREE_CODE (array_node
) == ARRAY_NOTATION_REF
)
2040 tree array_begin
= ARRAY_NOTATION_START (array_node
);
2041 tree array_lngth
= ARRAY_NOTATION_LENGTH (array_node
);
2042 tree array_strde
= ARRAY_NOTATION_STRIDE (array_node
);
2044 if (TREE_CODE (array_begin
) != INTEGER_CST
)
2046 begin_var
= build_decl (location
, VAR_DECL
, NULL_TREE
,
2048 add_stmt (build_modify_expr (location
, begin_var
,
2049 TREE_TYPE (begin_var
),
2050 NOP_EXPR
, location
, array_begin
,
2051 TREE_TYPE (array_begin
)));
2052 ARRAY_NOTATION_START (array_node
) = begin_var
;
2054 if (TREE_CODE (array_lngth
) != INTEGER_CST
)
2056 lngth_var
= build_decl (location
, VAR_DECL
, NULL_TREE
,
2058 add_stmt (build_modify_expr (location
, lngth_var
,
2059 TREE_TYPE (lngth_var
),
2060 NOP_EXPR
, location
, array_lngth
,
2061 TREE_TYPE (array_lngth
)));
2062 ARRAY_NOTATION_LENGTH (array_node
) = lngth_var
;
2064 if (TREE_CODE (array_strde
) != INTEGER_CST
)
2066 strde_var
= build_decl (location
, VAR_DECL
, NULL_TREE
,
2068 add_stmt (build_modify_expr (location
, strde_var
,
2069 TREE_TYPE (strde_var
),
2070 NOP_EXPR
, location
, array_strde
,
2071 TREE_TYPE (array_strde
)));
2072 ARRAY_NOTATION_STRIDE (array_node
) = strde_var
;
2076 for (ii
= 0; ii
< list_size
; ii
++)
2079 for (jj_tree
= (*array_list
)[ii
];
2080 jj_tree
&& TREE_CODE (jj_tree
) == ARRAY_NOTATION_REF
;
2081 jj_tree
= ARRAY_NOTATION_ARRAY (jj_tree
))
2083 array_ops
[ii
][jj
] = jj_tree
;
2088 for (ii
= 0; ii
< list_size
; ii
++)
2090 tree array_node
= (*array_list
)[ii
];
2091 if (TREE_CODE (array_node
) == ARRAY_NOTATION_REF
)
2093 for (jj
= 0; jj
< rank
; jj
++)
2095 if (TREE_CODE (array_ops
[ii
][jj
]) == ARRAY_NOTATION_REF
)
2097 array_value
[ii
][jj
] =
2098 ARRAY_NOTATION_ARRAY (array_ops
[ii
][jj
]);
2099 array_start
[ii
][jj
] =
2100 ARRAY_NOTATION_START (array_ops
[ii
][jj
]);
2101 array_length
[ii
][jj
] =
2102 fold_build1 (CONVERT_EXPR
, integer_type_node
,
2103 ARRAY_NOTATION_LENGTH (array_ops
[ii
][jj
]));
2104 array_stride
[ii
][jj
] =
2105 fold_build1 (CONVERT_EXPR
, integer_type_node
,
2106 ARRAY_NOTATION_STRIDE (array_ops
[ii
][jj
]));
2107 array_vector
[ii
][jj
] = true;
2109 if (!TREE_CONSTANT (array_length
[ii
][jj
]))
2110 count_down
[ii
][jj
] = false;
2111 else if (tree_int_cst_lt
2112 (array_length
[ii
][jj
],
2113 build_int_cst (TREE_TYPE (array_length
[ii
][jj
]),
2115 count_down
[ii
][jj
] = true;
2117 count_down
[ii
][jj
] = false;
2120 array_vector
[ii
][jj
] = false;
2125 if (length_mismatch_in_expr_p (location
, array_length
, list_size
, rank
))
2127 pop_stmt_list (loop_init
);
2128 return error_mark_node
;
2131 for (ii
= 0; ii
< rank
; ii
++)
2133 array_var
[ii
] = build_decl (location
, VAR_DECL
, NULL_TREE
,
2136 build_modify_expr (location
, array_var
[ii
],
2137 TREE_TYPE (array_var
[ii
]), NOP_EXPR
,
2139 build_int_cst (TREE_TYPE (array_var
[ii
]), 0),
2140 TREE_TYPE (array_var
[ii
]));
2143 for (ii
= 0; ii
< list_size
; ii
++)
2145 if (array_vector
[ii
][0])
2147 tree array_opr_node
= array_value
[ii
][rank
- 1];
2148 for (s_jj
= rank
- 1; s_jj
>= 0; s_jj
--)
2150 if (count_down
[ii
][s_jj
])
2151 /* Array[start_index - (induction_var * stride)] */
2152 array_opr_node
= build_array_ref
2153 (location
, array_opr_node
,
2154 build2 (MINUS_EXPR
, TREE_TYPE (array_var
[s_jj
]),
2155 array_start
[ii
][s_jj
],
2156 build2 (MULT_EXPR
, TREE_TYPE (array_var
[s_jj
]),
2157 array_var
[s_jj
], array_stride
[ii
][s_jj
])));
2159 /* Array[start_index + (induction_var * stride)] */
2160 array_opr_node
= build_array_ref
2161 (location
, array_opr_node
,
2162 build2 (PLUS_EXPR
, TREE_TYPE (array_var
[s_jj
]),
2163 array_start
[ii
][s_jj
],
2164 build2 (MULT_EXPR
, TREE_TYPE (array_var
[s_jj
]),
2165 array_var
[s_jj
], array_stride
[ii
][s_jj
])));
2167 vec_safe_push (array_operand
, array_opr_node
);
2170 /* This is just a dummy node to make sure the list sizes for both
2171 array list and array operand list are the same. */
2172 vec_safe_push (array_operand
, integer_one_node
);
2174 replace_array_notations (&arg
, true, array_list
, array_operand
);
2175 for (ii
= 0; ii
< rank
; ii
++)
2177 build2 (MODIFY_EXPR
, void_type_node
, array_var
[ii
],
2178 build2 (PLUS_EXPR
, TREE_TYPE (array_var
[ii
]), array_var
[ii
],
2179 build_int_cst (TREE_TYPE (array_var
[ii
]), 1)));
2181 for (jj
= 0; jj
< rank
; jj
++)
2183 if (rank
&& expr_incr
[jj
])
2185 if (count_down
[0][jj
])
2187 build2 (LT_EXPR
, boolean_type_node
, array_var
[jj
],
2188 build2 (MULT_EXPR
, TREE_TYPE (array_var
[jj
]),
2189 array_length
[0][jj
],
2190 build_int_cst (TREE_TYPE (array_var
[jj
]), -1)));
2192 compare_expr
[jj
] = build2 (LT_EXPR
, boolean_type_node
,
2193 array_var
[jj
], array_length
[0][jj
]);
2197 loop_init
= pop_stmt_list (loop_init
);
2198 append_to_statement_list_force (loop_init
, &loop_with_init
);
2200 for (ii
= 0; ii
< rank
; ii
++)
2202 tree new_loop
= push_stmt_list ();
2203 add_stmt (ind_init
[ii
]);
2204 c_finish_loop (location
, compare_expr
[ii
], expr_incr
[ii
], body
, NULL_TREE
,
2206 body
= pop_stmt_list (new_loop
);
2208 append_to_statement_list_force (body
, &loop_with_init
);
2209 XDELETEVEC (compare_expr
);
2210 XDELETEVEC (expr_incr
);
2211 XDELETEVEC (ind_init
);
2212 XDELETEVEC (array_var
);
2214 for (ii
= 0; ii
< list_size
; ii
++)
2216 XDELETEVEC (count_down
[ii
]);
2217 XDELETEVEC (array_value
[ii
]);
2218 XDELETEVEC (array_stride
[ii
]);
2219 XDELETEVEC (array_length
[ii
]);
2220 XDELETEVEC (array_start
[ii
]);
2221 XDELETEVEC (array_ops
[ii
]);
2222 XDELETEVEC (array_vector
[ii
]);
2225 XDELETEVEC (count_down
);
2226 XDELETEVEC (array_value
);
2227 XDELETEVEC (array_stride
);
2228 XDELETEVEC (array_length
);
2229 XDELETEVEC (array_start
);
2230 XDELETEVEC (array_ops
);
2231 XDELETEVEC (array_vector
);
2233 return loop_with_init
;
2236 /* Expands the built-in functions in a return. EXPR is a RETURN_EXPR with
2237 a built-in reduction function. This function returns the expansion code for
2238 the built-in function. */
2241 fix_return_expr (tree expr
)
2243 tree new_mod_list
, new_var
, new_mod
, retval_expr
, retval_type
;
2244 location_t loc
= EXPR_LOCATION (expr
);
2246 new_mod_list
= alloc_stmt_list ();
2247 retval_expr
= TREE_OPERAND (expr
, 0);
2248 retval_type
= TREE_TYPE (TREE_OPERAND (retval_expr
, 1));
2249 new_var
= build_decl (loc
, VAR_DECL
, NULL_TREE
, TREE_TYPE (retval_expr
));
2250 new_mod
= build_array_notation_expr (loc
, new_var
, TREE_TYPE (new_var
),
2252 TREE_OPERAND (retval_expr
, 1),
2254 TREE_OPERAND (retval_expr
, 1) = new_var
;
2255 TREE_OPERAND (expr
, 0) = retval_expr
;
2256 append_to_statement_list_force (new_mod
, &new_mod_list
);
2257 append_to_statement_list_force (expr
, &new_mod_list
);
2258 return new_mod_list
;
2261 /* Walks through tree node T and find all the call-statements that do not return
2262 anything and fix up any array notations they may carry. The return value
2263 is the same type as T but with all array notations replaced with appropriate
2267 expand_array_notation_exprs (tree t
)
2269 if (!contains_array_notation_expr (t
))
2272 switch (TREE_CODE (t
))
2275 t
= expand_array_notation_exprs (BIND_EXPR_BODY (t
));
2278 t
= fix_conditional_array_notations (t
);
2280 /* After the expansion if they are still a COND_EXPR, we go into its
2282 if (TREE_CODE (t
) == COND_EXPR
)
2284 if (COND_EXPR_THEN (t
))
2285 COND_EXPR_THEN (t
) =
2286 expand_array_notation_exprs (COND_EXPR_THEN (t
));
2287 if (COND_EXPR_ELSE (t
))
2288 COND_EXPR_ELSE (t
) =
2289 expand_array_notation_exprs (COND_EXPR_ELSE (t
));
2292 t
= expand_array_notation_exprs (t
);
2294 case STATEMENT_LIST
:
2296 tree_stmt_iterator ii_tsi
;
2297 for (ii_tsi
= tsi_start (t
); !tsi_end_p (ii_tsi
); tsi_next (&ii_tsi
))
2298 *tsi_stmt_ptr (ii_tsi
) =
2299 expand_array_notation_exprs (*tsi_stmt_ptr (ii_tsi
));
2304 location_t loc
= EXPR_HAS_LOCATION (t
) ? EXPR_LOCATION (t
) :
2306 tree lhs
= TREE_OPERAND (t
, 0);
2307 tree rhs
= TREE_OPERAND (t
, 1);
2308 location_t rhs_loc
= EXPR_HAS_LOCATION (rhs
) ? EXPR_LOCATION (rhs
) :
2310 t
= build_array_notation_expr (loc
, lhs
, TREE_TYPE (lhs
), NOP_EXPR
,
2311 rhs_loc
, rhs
, TREE_TYPE (rhs
));
2315 t
= fix_array_notation_call_expr (t
);
2318 if (contains_array_notation_expr (t
))
2319 t
= fix_return_expr (t
);
2326 /* This handles expression of the form "a[i:j:k]" or "a[:]" or "a[i:j]," which
2327 denotes an array notation expression. If a is a variable or a member, then
2328 we generate a ARRAY_NOTATION_REF front-end tree and return it.
2329 This tree is broken down to ARRAY_REF toward the end of parsing.
2330 ARRAY_NOTATION_REF tree holds the START_INDEX, LENGTH, STRIDE and the TYPE
2331 of ARRAY_REF. Restrictions on START_INDEX, LENGTH and STRIDE is same as that
2332 of the index field passed into ARRAY_REF. The only additional restriction
2333 is that, unlike index in ARRAY_REF, stride, length and start_index cannot
2334 contain ARRAY_NOTATIONS. */
2337 build_array_notation_ref (location_t loc
, tree array
, tree start_index
,
2338 tree length
, tree stride
, tree type
)
2340 tree array_ntn_tree
= NULL_TREE
;
2341 size_t stride_rank
= 0, length_rank
= 0, start_rank
= 0;
2343 if (!INTEGRAL_TYPE_P (TREE_TYPE (start_index
)))
2346 "start-index of array notation triplet is not an integer");
2347 return error_mark_node
;
2349 if (!INTEGRAL_TYPE_P (TREE_TYPE (length
)))
2351 error_at (loc
, "length of array notation triplet is not an integer");
2352 return error_mark_node
;
2355 /* The stride is an optional field. */
2356 if (stride
&& !INTEGRAL_TYPE_P (TREE_TYPE (stride
)))
2358 error_at (loc
, "stride of array notation triplet is not an integer");
2359 return error_mark_node
;
2363 if (TREE_CONSTANT (start_index
) && TREE_CONSTANT (length
)
2364 && tree_int_cst_lt (length
, start_index
))
2365 stride
= build_int_cst (TREE_TYPE (start_index
), -1);
2367 stride
= build_int_cst (TREE_TYPE (start_index
), 1);
2370 if (!find_rank (loc
, start_index
, start_index
, false, &start_rank
))
2371 return error_mark_node
;
2372 if (!find_rank (loc
, length
, length
, false, &length_rank
))
2373 return error_mark_node
;
2374 if (!find_rank (loc
, stride
, stride
, false, &stride_rank
))
2375 return error_mark_node
;
2377 if (start_rank
!= 0)
2379 error_at (loc
, "rank of an array notation triplet's start-index is not "
2381 return error_mark_node
;
2383 if (length_rank
!= 0)
2385 error_at (loc
, "rank of an array notation triplet's length is not zero");
2386 return error_mark_node
;
2388 if (stride_rank
!= 0)
2390 error_at (loc
, "rank of array notation triplet's stride is not zero");
2391 return error_mark_node
;
2393 array_ntn_tree
= build4 (ARRAY_NOTATION_REF
, NULL_TREE
, NULL_TREE
, NULL_TREE
,
2394 NULL_TREE
, NULL_TREE
);
2395 ARRAY_NOTATION_ARRAY (array_ntn_tree
) = array
;
2396 ARRAY_NOTATION_START (array_ntn_tree
) = start_index
;
2397 ARRAY_NOTATION_LENGTH (array_ntn_tree
) = length
;
2398 ARRAY_NOTATION_STRIDE (array_ntn_tree
) = stride
;
2399 TREE_TYPE (array_ntn_tree
) = type
;
2401 return array_ntn_tree
;