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 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);
152 func_parm
= CALL_EXPR_ARG (an_builtin_fn
, 0);
154 /* Fully fold any EXCESSIVE_PRECISION EXPR that can occur in the function
156 func_parm
= c_fully_fold (func_parm
, false, NULL
);
158 location
= EXPR_LOCATION (an_builtin_fn
);
160 if (!find_rank (location
, an_builtin_fn
, an_builtin_fn
, true, &rank
))
161 return error_mark_node
;
164 return an_builtin_fn
;
166 && (an_type
== BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
167 || an_type
== BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND
))
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
;
174 extract_array_notation_exprs (func_parm
, true, &array_list
);
175 list_size
= vec_safe_length (array_list
);
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]);
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
;
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
;
194 case BUILT_IN_CILKPLUS_SEC_REDUCE
:
195 if (call_fn
&& identity_value
)
196 new_var_type
= TREE_TYPE ((*array_list
)[0]);
198 case BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING
:
199 new_var_type
= NULL_TREE
;
205 array_ops
= XNEWVEC (tree
*, list_size
);
206 for (ii
= 0; ii
< list_size
; ii
++)
207 array_ops
[ii
] = XNEWVEC (tree
, rank
);
209 array_vector
= XNEWVEC (bool *, list_size
);
210 for (ii
= 0; ii
< list_size
; ii
++)
211 array_vector
[ii
] = XNEWVEC (bool, rank
);
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
);
218 for (ii
= 0; ii
< list_size
; ii
++)
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
);
226 compare_expr
= XNEWVEC (tree
, rank
);
227 expr_incr
= XNEWVEC (tree
, rank
);
228 ind_init
= XNEWVEC (tree
, rank
);
230 count_down
= XNEWVEC (bool *, list_size
);
231 for (ii
= 0; ii
< list_size
; ii
++)
232 count_down
[ii
] = XNEWVEC (bool, rank
);
234 array_var
= XNEWVEC (tree
, rank
);
236 for (ii
= 0; ii
< list_size
; ii
++)
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
))
243 array_ops
[ii
][jj
] = jj_tree
;
248 for (ii
= 0; ii
< list_size
; ii
++)
250 tree array_node
= (*array_list
)[ii
];
251 if (TREE_CODE (array_node
) == ARRAY_NOTATION_REF
)
253 for (jj
= 0; jj
< rank
; jj
++)
255 if (TREE_CODE (array_ops
[ii
][jj
]) == ARRAY_NOTATION_REF
)
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;
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
]),
275 count_down
[ii
][jj
] = true;
277 count_down
[ii
][jj
] = false;
280 array_vector
[ii
][jj
] = false;
285 loop_init
= alloc_stmt_list ();
287 for (ii
= 0; ii
< rank
; ii
++)
289 array_var
[ii
] = build_decl (location
, VAR_DECL
, NULL_TREE
,
292 build_modify_expr (location
, array_var
[ii
],
293 TREE_TYPE (array_var
[ii
]), NOP_EXPR
,
295 build_int_cst (TREE_TYPE (array_var
[ii
]), 0),
296 TREE_TYPE (array_var
[ii
]));
298 for (ii
= 0; ii
< list_size
; ii
++)
300 if (array_vector
[ii
][0])
302 tree array_opr_node
= array_value
[ii
][rank
- 1];
303 for (s_jj
= rank
- 1; s_jj
>= 0; s_jj
--)
305 if (count_down
[ii
][s_jj
])
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
])));
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
])));
326 vec_safe_push (array_operand
, array_opr_node
);
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
);
333 replace_array_notations (&func_parm
, true, array_list
, array_operand
);
334 for (ii
= 0; ii
< rank
; 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
++)
341 if (rank
&& expr_incr
[jj
])
343 if (count_down
[0][jj
])
345 build2 (LT_EXPR
, boolean_type_node
, array_var
[jj
],
346 build2 (MULT_EXPR
, TREE_TYPE (array_var
[jj
]),
348 build_int_cst (TREE_TYPE (array_var
[jj
]), -1)));
350 compare_expr
[jj
] = build2 (LT_EXPR
, boolean_type_node
,
351 array_var
[jj
], array_length
[0][jj
]);
355 if (an_type
!= BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING
)
357 *new_var
= build_decl (location
, VAR_DECL
, NULL_TREE
, new_var_type
);
358 gcc_assert (*new_var
&& *new_var
!= error_mark_node
);
361 *new_var
= NULL_TREE
;
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];
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
));
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
));
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
));
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
));
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
));
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
));
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
);
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
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
));
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
);
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
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
));
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
),
517 location
, array_ind_value
, TREE_TYPE (array_ind_value
));
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
),
526 location
, func_parm
, TREE_TYPE ((*array_operand
)[0]));
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
),
537 location
, func_parm
, TREE_OPERAND (array_op0
, 1));
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
);
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
);
547 new_expr
= build_conditional_expr
549 build2 (LE_EXPR
, TREE_TYPE (array_ind_value
), array_ind_value
,
552 new_yes_list
, TREE_TYPE (*new_var
), new_no_list
, TREE_TYPE (*new_var
));
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
),
567 location
, array_ind_value
, TREE_TYPE (array_ind_value
));
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
),
576 location
, func_parm
, TREE_TYPE (array_op0
));
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
),
587 location
, func_parm
, TREE_OPERAND (array_op0
, 1));
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
);
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
);
597 new_expr
= build_conditional_expr
599 build2 (GE_EXPR
, TREE_TYPE (array_ind_value
), array_ind_value
,
602 new_yes_list
, TREE_TYPE (*new_var
), new_no_list
, TREE_TYPE (*new_var
));
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
));
613 case BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING
:
614 new_expr
= build_call_expr (call_fn
, 2, identity_value
, func_parm
);
621 for (ii
= 0; ii
< rank
; ii
++)
622 append_to_statement_list (ind_init
[ii
], &loop_init
);
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
);
630 append_to_statement_list_force (loop_init
, &loop_with_init
);
632 for (ii
= 0; ii
< rank
; ii
++)
634 tree new_loop
= push_stmt_list ();
635 c_finish_loop (location
, compare_expr
[ii
], expr_incr
[ii
], body
, NULL_TREE
,
637 body
= pop_stmt_list (new_loop
);
639 append_to_statement_list_force (body
, &loop_with_init
);
641 XDELETEVEC (compare_expr
);
642 XDELETEVEC (expr_incr
);
643 XDELETEVEC (ind_init
);
644 XDELETEVEC (array_var
);
645 for (ii
= 0; ii
< list_size
; ii
++)
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
]);
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
);
663 return loop_with_init
;
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. */
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
)
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;
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;
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
;
707 if (!find_rank (location
, rhs
, rhs
, false, &rhs_rank
))
708 return error_mark_node
;
710 extract_array_notation_exprs (rhs
, false, &rhs_list
);
711 rhs_list_size
= vec_safe_length (rhs_list
);
712 an_init
= push_stmt_list ();
715 scalar_mods
= replace_invariant_exprs (&rhs
);
717 add_stmt (scalar_mods
);
719 for (ii
= 0; ii
< rhs_list_size
; ii
++)
721 tree rhs_node
= (*rhs_list
)[ii
];
722 if (TREE_CODE (rhs_node
) == CALL_EXPR
)
724 builtin_loop
= fix_builtin_array_notation_fn (rhs_node
, &new_var
);
725 if (builtin_loop
== error_mark_node
)
727 pop_stmt_list (an_init
);
728 return error_mark_node
;
730 else if (builtin_loop
)
732 add_stmt (builtin_loop
);
733 found_builtin_fn
= true;
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
,
748 if (!find_rank (location
, lhs
, lhs
, true, &lhs_rank
))
750 pop_stmt_list (an_init
);
751 return error_mark_node
;
754 if (!find_rank (location
, rhs
, rhs
, true, &rhs_rank
))
756 pop_stmt_list (an_init
);
757 return error_mark_node
;
760 if (lhs_rank
== 0 && rhs_rank
== 0)
762 if (found_builtin_fn
)
764 new_modify_expr
= build_modify_expr (location
, lhs
, lhs_origtype
,
765 modifycode
, rhs_loc
, rhs
,
767 add_stmt (new_modify_expr
);
768 pop_stmt_list (an_init
);
773 pop_stmt_list (an_init
);
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
);
784 if (lhs_rank
== 0 && rhs_rank
!= 0 && TREE_CODE (rhs
) != CALL_EXPR
)
787 if (TREE_CODE (rhs_base
) == ARRAY_NOTATION_REF
)
789 for (ii
= 0; ii
< (size_t) rhs_rank
; ii
++)
790 rhs_base
= ARRAY_NOTATION_ARRAY (rhs
);
792 error_at (location
, "%qE cannot be scalar when %qE is not", lhs
,
794 return error_mark_node
;
798 error_at (location
, "%qE cannot be scalar when %qE is not", lhs
,
800 return error_mark_node
;
803 if (lhs_rank
!= 0 && rhs_rank
!= 0 && lhs_rank
!= rhs_rank
)
808 for (ii
= 0; ii
< lhs_rank
; ii
++)
809 lhs_base
= ARRAY_NOTATION_ARRAY (lhs_base
);
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
);
816 error_at (location
, "rank mismatch between %qE and %qE", lhs
, rhs
);
817 pop_stmt_list (an_init
);
818 return error_mark_node
;
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
++)
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
);
830 if (TREE_CODE (array_begin
) != INTEGER_CST
)
832 begin_var
= build_decl (location
, VAR_DECL
, NULL_TREE
,
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
;
841 if (TREE_CODE (array_lngth
) != INTEGER_CST
)
843 lngth_var
= build_decl (location
, VAR_DECL
, NULL_TREE
,
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
;
851 if (TREE_CODE (array_strde
) != INTEGER_CST
)
853 strde_var
= build_decl (location
, VAR_DECL
, NULL_TREE
,
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
;
863 for (ii
= 0; ii
< rhs_list_size
; ii
++)
865 tree array_node
= (*rhs_list
)[ii
];
866 if (array_node
&& TREE_CODE (array_node
) == ARRAY_NOTATION_REF
)
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
);
872 if (TREE_CODE (array_begin
) != INTEGER_CST
)
874 begin_var
= build_decl (location
, VAR_DECL
, NULL_TREE
,
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
;
882 if (TREE_CODE (array_lngth
) != INTEGER_CST
)
884 lngth_var
= build_decl (location
, VAR_DECL
, NULL_TREE
,
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
;
892 if (TREE_CODE (array_strde
) != INTEGER_CST
)
894 strde_var
= build_decl (location
, VAR_DECL
, NULL_TREE
,
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
;
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
954 lhs_var
= XNEWVEC (tree
, lhs_rank
);
955 rhs_var
= XNEWVEC (tree
, rhs_rank
);
956 cond_expr
= XNEWVEC (tree
, MAX (lhs_rank
, rhs_rank
));
958 lhs_expr_incr
= XNEWVEC (tree
, lhs_rank
);
959 rhs_expr_incr
=XNEWVEC (tree
, rhs_rank
);
961 lhs_ind_init
= XNEWVEC (tree
, lhs_rank
);
962 rhs_ind_init
= XNEWVEC (tree
, rhs_rank
);
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
);
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
);
972 lhs_compare
= XNEWVEC (tree
, lhs_rank
);
973 rhs_compare
= XNEWVEC (tree
, rhs_rank
);
977 for (ii
= 0; ii
< lhs_list_size
; ii
++)
980 ii_tree
= (*lhs_list
)[ii
];
983 if (TREE_CODE (ii_tree
) == ARRAY_NOTATION_REF
)
985 lhs_array
[ii
][jj
] = ii_tree
;
987 ii_tree
= ARRAY_NOTATION_ARRAY (ii_tree
);
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
)
998 lhs_array
[0][0] = NULL_TREE
;
1002 for (ii
= 0; ii
< rhs_list_size
; ii
++)
1005 ii_tree
= (*rhs_list
)[ii
];
1008 if (TREE_CODE (ii_tree
) == ARRAY_NOTATION_REF
)
1010 rhs_array
[ii
][jj
] = ii_tree
;
1012 ii_tree
= ARRAY_NOTATION_ARRAY (ii_tree
);
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
)
1024 for (ii
= 0; ii
< lhs_list_size
; ii
++)
1026 tree lhs_node
= (*lhs_list
)[ii
];
1027 if (TREE_CODE (lhs_node
) == ARRAY_NOTATION_REF
)
1029 for (jj
= 0; jj
< lhs_rank
; jj
++)
1031 if (TREE_CODE (lhs_array
[ii
][jj
]) == ARRAY_NOTATION_REF
)
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;
1051 lhs_count_down
[ii
][jj
] = false;
1054 lhs_vector
[ii
][jj
] = false;
1058 for (ii
= 0; ii
< rhs_list_size
; ii
++)
1060 if (TREE_CODE ((*rhs_list
)[ii
]) == ARRAY_NOTATION_REF
)
1062 for (jj
= 0; jj
< rhs_rank
; jj
++)
1064 if (TREE_CODE (rhs_array
[ii
][jj
]) == ARRAY_NOTATION_REF
)
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;
1084 rhs_count_down
[ii
][jj
] = false;
1087 rhs_vector
[ii
][jj
] = false;
1091 for (jj
= 0; jj
< rhs_rank
; jj
++)
1093 rhs_vector
[ii
][jj
] = false;
1094 rhs_length
[ii
][jj
] = NULL_TREE
;
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
))
1103 pop_stmt_list (an_init
);
1104 return error_mark_node
;
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
1110 && TREE_CODE (rhs_length
[0][0]) == INTEGER_CST
)
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
))
1118 error_at (location
, "length mismatch between LHS and RHS");
1119 pop_stmt_list (an_init
);
1120 return error_mark_node
;
1123 for (ii
= 0; ii
< lhs_rank
; ii
++)
1125 if (lhs_vector
[0][ii
])
1127 lhs_var
[ii
] = build_decl (location
, VAR_DECL
, NULL_TREE
,
1129 lhs_ind_init
[ii
] = build_modify_expr
1130 (location
, lhs_var
[ii
], TREE_TYPE (lhs_var
[ii
]),
1132 location
, build_zero_cst (TREE_TYPE (lhs_var
[ii
])),
1133 TREE_TYPE (lhs_var
[ii
]));
1137 for (ii
= 0; ii
< rhs_rank
; ii
++)
1139 /* When we have a polynomial, we assume that the indices are of type
1141 rhs_var
[ii
] = build_decl (location
, VAR_DECL
, NULL_TREE
,
1143 rhs_ind_init
[ii
] = build_modify_expr
1144 (location
, rhs_var
[ii
], TREE_TYPE (rhs_var
[ii
]),
1146 location
, build_int_cst (TREE_TYPE (rhs_var
[ii
]), 0),
1147 TREE_TYPE (rhs_var
[ii
]));
1151 for (ii
= 0; ii
< lhs_list_size
; ii
++)
1153 if (lhs_vector
[ii
][0])
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
--)
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
]),
1168 lhs_stride
[ii
][s_jj
])));
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
]),
1176 lhs_stride
[ii
][s_jj
])));
1178 vec_safe_push (lhs_array_operand
, lhs_array_opr
);
1181 vec_safe_push (lhs_array_operand
, integer_one_node
);
1183 replace_array_notations (&lhs
, true, lhs_list
, lhs_array_operand
);
1184 array_expr_lhs
= lhs
;
1189 for (ii
= 0; ii
< rhs_list_size
; ii
++)
1191 if (rhs_vector
[ii
][0])
1193 tree rhs_array_opr
= rhs_value
[ii
][rhs_rank
- 1];
1194 for (s_jj
= rhs_rank
- 1; s_jj
>= 0; s_jj
--)
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
]),
1204 rhs_stride
[ii
][s_jj
])));
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
]),
1213 rhs_stride
[ii
][s_jj
])));
1215 vec_safe_push (rhs_array_operand
, rhs_array_opr
);
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
);
1223 for (ii
= 0; ii
< rhs_list_size
; ii
++)
1225 tree rhs_node
= (*rhs_list
)[ii
];
1226 if (TREE_CODE (rhs_node
) == CALL_EXPR
)
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
))
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
]);
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
,
1248 return error_mark_node
;
1253 replace_array_notations (&rhs
, true, rhs_list
, rhs_array_operand
);
1254 array_expr_rhs
= rhs
;
1258 for (ii
= 0; ii
< rhs_list_size
; ii
++)
1260 tree rhs_node
= (*rhs_list
)[ii
];
1261 if (TREE_CODE (rhs_node
) == CALL_EXPR
)
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
))
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
]);
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
,
1283 return error_mark_node
;
1288 replace_array_notations (&rhs
, true, rhs_list
, rhs_array_operand
);
1289 array_expr_rhs
= rhs
;
1290 rhs_expr_incr
[0] = NULL_TREE
;
1293 for (ii
= 0; ii
< rhs_rank
; ii
++)
1294 rhs_expr_incr
[ii
] = build2 (MODIFY_EXPR
, void_type_node
, rhs_var
[ii
],
1296 (PLUS_EXPR
, TREE_TYPE (rhs_var
[ii
]),
1298 build_one_cst (TREE_TYPE (rhs_var
[ii
]))));
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
]))));
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
;
1311 array_expr
= build_modify_expr (location
, array_expr_lhs
, lhs_origtype
,
1312 modifycode
, rhs_loc
, array_expr_rhs
,
1315 for (jj
= 0; jj
< MAX (lhs_rank
, rhs_rank
); jj
++)
1317 if (rhs_rank
&& rhs_expr_incr
[jj
])
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
]);
1326 lhs_compare
[jj
] = build2
1327 (LT_EXPR
, boolean_type_node
, lhs_var
[jj
], lhs_length
[0][jj
]);
1330 /* The reason why we have this here is for the following case:
1331 Array[:][:] = function_call(something) + Array2[:][:];
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. */
1336 for (iii
= 0; iii
< rhs_list_size
; iii
++)
1337 if (rhs_vector
[iii
][jj
])
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
1345 we just count up, so we compare for ii < LENGTH
1347 if (rhs_count_down
[iii
][jj
])
1348 /* We use iii for rhs_length because that is the correct countdown
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)));
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
]);
1362 cond_expr
[jj
] = rhs_compare
[jj
];
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
]);
1370 cond_expr
[jj
] = build2
1371 (LT_EXPR
, boolean_type_node
, lhs_var
[jj
], lhs_length
[0][jj
]);
1375 an_init
= pop_stmt_list (an_init
);
1376 append_to_statement_list_force (an_init
, &loop_with_init
);
1378 for (ii
= 0; ii
< MAX (lhs_rank
, rhs_rank
); ii
++)
1380 tree incr_list
= alloc_stmt_list ();
1381 tree new_loop
= push_stmt_list ();
1383 add_stmt (lhs_ind_init
[ii
]);
1385 add_stmt (rhs_ind_init
[ii
]);
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
,
1392 body
= pop_stmt_list (new_loop
);
1394 append_to_statement_list_force (body
, &loop_with_init
);
1395 return loop_with_init
;
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. */
1405 fix_conditional_array_notations_1 (tree stmt
)
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;
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
);
1424 /* Otherwise dont even touch the statement. */
1427 if (!find_rank (location
, cond
, cond
, false, &rank
))
1428 return error_mark_node
;
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
++)
1434 tree array_node
= (*array_list
)[ii
];
1435 if (TREE_CODE (array_node
) == CALL_EXPR
)
1437 builtin_loop
= fix_builtin_array_notation_fn (array_node
, &new_var
);
1438 if (builtin_loop
== error_mark_node
)
1440 add_stmt (error_mark_node
);
1441 pop_stmt_list (loop_init
);
1444 else if (builtin_loop
)
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
);
1455 if (!find_rank (location
, stmt
, stmt
, true, &rank
))
1457 pop_stmt_list (loop_init
);
1458 return error_mark_node
;
1463 pop_stmt_list (loop_init
);
1466 extract_array_notation_exprs (stmt
, true, &array_list
);
1468 if (vec_safe_length (array_list
) == 0)
1471 list_size
= vec_safe_length (array_list
);
1473 array_ops
= XNEWVEC (tree
*, list_size
);
1474 for (ii
= 0; ii
< list_size
; ii
++)
1475 array_ops
[ii
] = XNEWVEC (tree
, rank
);
1477 array_vector
= XNEWVEC (bool *, list_size
);
1478 for (ii
= 0; ii
< list_size
; ii
++)
1479 array_vector
[ii
] = XNEWVEC (bool, rank
);
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
);
1486 for (ii
= 0; ii
< list_size
; ii
++)
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
);
1494 compare_expr
= XNEWVEC (tree
, rank
);
1495 expr_incr
= XNEWVEC (tree
, rank
);
1496 ind_init
= XNEWVEC (tree
, rank
);
1498 count_down
= XNEWVEC (bool *, list_size
);
1499 for (ii
= 0; ii
< list_size
; ii
++)
1500 count_down
[ii
] = XNEWVEC (bool, rank
);
1502 array_var
= XNEWVEC (tree
, rank
);
1504 for (ii
= 0; ii
< list_size
; ii
++)
1506 tree array_node
= (*array_list
)[ii
];
1507 if (array_node
&& TREE_CODE (array_node
) == ARRAY_NOTATION_REF
)
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
);
1513 if (TREE_CODE (array_begin
) != INTEGER_CST
)
1515 begin_var
= build_decl (location
, VAR_DECL
, NULL_TREE
,
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
;
1523 if (TREE_CODE (array_lngth
) != INTEGER_CST
)
1525 lngth_var
= build_decl (location
, VAR_DECL
, NULL_TREE
,
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
;
1533 if (TREE_CODE (array_strde
) != INTEGER_CST
)
1535 strde_var
= build_decl (location
, VAR_DECL
, NULL_TREE
,
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
;
1545 for (ii
= 0; ii
< list_size
; ii
++)
1547 tree array_node
= (*array_list
)[ii
];
1549 for (jj_tree
= array_node
;
1550 jj_tree
&& TREE_CODE (jj_tree
) == ARRAY_NOTATION_REF
;
1551 jj_tree
= ARRAY_NOTATION_ARRAY (jj_tree
))
1553 array_ops
[ii
][jj
] = jj_tree
;
1557 for (ii
= 0; ii
< list_size
; ii
++)
1559 tree array_node
= (*array_list
)[ii
];
1560 if (TREE_CODE (array_node
) == ARRAY_NOTATION_REF
)
1562 for (jj
= 0; jj
< rank
; jj
++)
1564 if (TREE_CODE (array_ops
[ii
][jj
]) == ARRAY_NOTATION_REF
)
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;
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
]),
1584 count_down
[ii
][jj
] = true;
1586 count_down
[ii
][jj
] = false;
1589 array_vector
[ii
][jj
] = false;
1594 for (ii
= 0; ii
< rank
; ii
++)
1596 array_var
[ii
] = build_decl (location
, VAR_DECL
, NULL_TREE
,
1599 build_modify_expr (location
, array_var
[ii
],
1600 TREE_TYPE (array_var
[ii
]), NOP_EXPR
,
1602 build_int_cst (TREE_TYPE (array_var
[ii
]), 0),
1603 TREE_TYPE (array_var
[ii
]));
1606 for (ii
= 0; ii
< list_size
; ii
++)
1608 if (array_vector
[ii
][0])
1610 tree array_opr
= array_value
[ii
][rank
- 1];
1611 for (s_jj
= rank
- 1; s_jj
>= 0; s_jj
--)
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
])));
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
])));
1630 vec_safe_push (array_operand
, array_opr
);
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
);
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
]),
1642 build_int_cst (TREE_TYPE (array_var
[ii
]),
1644 for (jj
= 0; jj
< rank
; jj
++)
1646 if (rank
&& expr_incr
[jj
])
1648 if (count_down
[0][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)));
1655 compare_expr
[jj
] = build2 (LT_EXPR
, boolean_type_node
,
1656 array_var
[jj
], array_length
[0][jj
]);
1660 loop_init
= pop_stmt_list (loop_init
);
1662 append_to_statement_list_force (loop_init
, &loop_with_init
);
1664 for (ii
= 0; ii
< rank
; ii
++)
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
,
1670 body
= pop_stmt_list (new_loop
);
1672 append_to_statement_list_force (body
, &loop_with_init
);
1673 XDELETEVEC (expr_incr
);
1674 XDELETEVEC (ind_init
);
1676 for (ii
= 0; ii
< list_size
; ii
++)
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
]);
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
);
1695 return loop_with_init
;
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
1703 fix_conditional_array_notations (tree stmt
)
1705 if (TREE_CODE (stmt
) == STATEMENT_LIST
)
1707 tree_stmt_iterator tsi
;
1708 for (tsi
= tsi_start (stmt
); !tsi_end_p (tsi
); tsi_next (&tsi
))
1710 tree single_stmt
= *tsi_stmt_ptr (tsi
);
1711 *tsi_stmt_ptr (tsi
) =
1712 fix_conditional_array_notations_1 (single_stmt
);
1717 return fix_conditional_array_notations_1 (stmt
);
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. */
1725 fix_array_notation_expr (location_t location
, enum tree_code code
,
1729 vec
<tree
, va_gc
> *array_list
= NULL
, *array_operand
= NULL
;
1730 size_t list_size
= 0, rank
= 0, ii
= 0, 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
;
1738 if (!find_rank (location
, arg
.value
, arg
.value
, false, &rank
))
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
1743 arg
.value
= error_mark_node
;
1750 extract_array_notation_exprs (arg
.value
, true, &array_list
);
1752 if (vec_safe_length (array_list
) == 0)
1755 list_size
= vec_safe_length (array_list
);
1757 array_ops
= XNEWVEC (tree
*, list_size
);
1758 for (ii
= 0; ii
< list_size
; ii
++)
1759 array_ops
[ii
] = XNEWVEC (tree
, rank
);
1761 array_vector
= XNEWVEC (bool *, list_size
);
1762 for (ii
= 0; ii
< list_size
; ii
++)
1763 array_vector
[ii
] = XNEWVEC (bool, rank
);
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
);
1770 for (ii
= 0; ii
< list_size
; ii
++)
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
);
1778 compare_expr
= XNEWVEC (tree
, rank
);
1779 expr_incr
= XNEWVEC (tree
, rank
);
1780 ind_init
= XNEWVEC (tree
, rank
);
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
);
1787 for (ii
= 0; ii
< list_size
; ii
++)
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
))
1794 array_ops
[ii
][jj
] = jj_tree
;
1799 loop_init
= push_stmt_list ();
1801 for (ii
= 0; ii
< list_size
; ii
++)
1803 tree array_node
= (*array_list
)[ii
];
1804 if (TREE_CODE (array_node
) == ARRAY_NOTATION_REF
)
1806 for (jj
= 0; jj
< rank
; jj
++)
1808 if (TREE_CODE (array_ops
[ii
][jj
]) == ARRAY_NOTATION_REF
)
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;
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
]),
1828 count_down
[ii
][jj
] = true;
1830 count_down
[ii
][jj
] = false;
1833 array_vector
[ii
][jj
] = false;
1838 for (ii
= 0; ii
< rank
; ii
++)
1840 array_var
[ii
] = build_decl (location
, VAR_DECL
, NULL_TREE
,
1843 build_modify_expr (location
, array_var
[ii
],
1844 TREE_TYPE (array_var
[ii
]), NOP_EXPR
,
1846 build_int_cst (TREE_TYPE (array_var
[ii
]), 0),
1847 TREE_TYPE (array_var
[ii
]));
1850 for (ii
= 0; ii
< list_size
; ii
++)
1852 if (array_vector
[ii
][0])
1854 tree array_opr
= array_value
[ii
][rank
- 1];
1855 for (s_jj
= rank
- 1; s_jj
>= 0; s_jj
--)
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
])));
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
])));
1874 vec_safe_push (array_operand
, array_opr
);
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
);
1881 replace_array_notations (&arg
.value
, true, array_list
, array_operand
);
1883 for (ii
= 0; ii
< rank
; 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)));
1889 for (jj
= 0; jj
< rank
; jj
++)
1891 if (rank
&& expr_incr
[jj
])
1893 if (count_down
[0][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)));
1900 compare_expr
[jj
] = build2 (LT_EXPR
, boolean_type_node
,
1901 array_var
[jj
], array_length
[0][jj
]);
1905 if (code
== POSTINCREMENT_EXPR
|| code
== POSTDECREMENT_EXPR
)
1907 arg
= default_function_array_read_conversion (location
, arg
);
1908 arg
.value
= build_unary_op (location
, code
, arg
.value
, 0);
1910 else if (code
== PREINCREMENT_EXPR
|| code
== PREDECREMENT_EXPR
)
1912 arg
= default_function_array_read_conversion (location
, arg
);
1913 arg
= parser_build_unary_op (location
, code
, arg
);
1916 loop_init
= pop_stmt_list (loop_init
);
1917 append_to_statement_list_force (loop_init
, &loop_with_init
);
1920 for (ii
= 0; ii
< rank
; ii
++)
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
,
1926 body
= pop_stmt_list (new_loop
);
1928 append_to_statement_list_force (body
, &loop_with_init
);
1929 XDELETEVEC (expr_incr
);
1930 XDELETEVEC (ind_init
);
1931 XDELETEVEC (array_var
);
1933 for (ii
= 0; ii
< list_size
; ii
++)
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
]);
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
);
1952 arg
.value
= loop_with_init
;
1956 /* Replaces array notations in a void function call arguments in ARG and returns
1957 a STATEMENT_LIST. */
1960 fix_array_notation_call_expr (tree arg
)
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;
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
;
1974 if (TREE_CODE (arg
) == CALL_EXPR
1975 && is_cilkplus_reduce_builtin (CALL_EXPR_FN (arg
)))
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. */
1983 if (!find_rank (location
, arg
, arg
, false, &rank
))
1984 return error_mark_node
;
1989 extract_array_notation_exprs (arg
, true, &array_list
);
1990 if (vec_safe_length (array_list
) == 0)
1993 list_size
= vec_safe_length (array_list
);
1994 location
= EXPR_LOCATION (arg
);
1996 array_ops
= XNEWVEC (tree
*, list_size
);
1997 for (ii
= 0; ii
< list_size
; ii
++)
1998 array_ops
[ii
] = XNEWVEC (tree
, rank
);
2000 array_vector
= XNEWVEC (bool *, list_size
);
2001 for (ii
= 0; ii
< list_size
; ii
++)
2002 array_vector
[ii
] = (bool *) XNEWVEC (bool, rank
);
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
);
2009 for (ii
= 0; ii
< list_size
; ii
++)
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
);
2017 compare_expr
= XNEWVEC (tree
, rank
);
2018 expr_incr
= XNEWVEC (tree
, rank
);
2019 ind_init
= XNEWVEC (tree
, rank
);
2021 count_down
= XNEWVEC (bool *, list_size
);
2022 for (ii
= 0; ii
< list_size
; ii
++)
2023 count_down
[ii
] = XNEWVEC (bool, rank
);
2025 array_var
= XNEWVEC (tree
, rank
);
2027 loop_init
= push_stmt_list ();
2028 for (ii
= 0; ii
< list_size
; ii
++)
2030 tree array_node
= (*array_list
)[ii
];
2031 if (array_node
&& TREE_CODE (array_node
) == ARRAY_NOTATION_REF
)
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
);
2037 if (TREE_CODE (array_begin
) != INTEGER_CST
)
2039 begin_var
= build_decl (location
, VAR_DECL
, NULL_TREE
,
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
;
2047 if (TREE_CODE (array_lngth
) != INTEGER_CST
)
2049 lngth_var
= build_decl (location
, VAR_DECL
, NULL_TREE
,
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
;
2057 if (TREE_CODE (array_strde
) != INTEGER_CST
)
2059 strde_var
= build_decl (location
, VAR_DECL
, NULL_TREE
,
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
;
2069 for (ii
= 0; ii
< list_size
; ii
++)
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
))
2076 array_ops
[ii
][jj
] = jj_tree
;
2081 for (ii
= 0; ii
< list_size
; ii
++)
2083 tree array_node
= (*array_list
)[ii
];
2084 if (TREE_CODE (array_node
) == ARRAY_NOTATION_REF
)
2086 for (jj
= 0; jj
< rank
; jj
++)
2088 if (TREE_CODE (array_ops
[ii
][jj
]) == ARRAY_NOTATION_REF
)
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;
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
]),
2108 count_down
[ii
][jj
] = true;
2110 count_down
[ii
][jj
] = false;
2113 array_vector
[ii
][jj
] = false;
2118 if (length_mismatch_in_expr_p (location
, array_length
, list_size
, rank
))
2120 pop_stmt_list (loop_init
);
2121 return error_mark_node
;
2124 for (ii
= 0; ii
< rank
; ii
++)
2126 array_var
[ii
] = build_decl (location
, VAR_DECL
, NULL_TREE
,
2129 build_modify_expr (location
, array_var
[ii
],
2130 TREE_TYPE (array_var
[ii
]), NOP_EXPR
,
2132 build_int_cst (TREE_TYPE (array_var
[ii
]), 0),
2133 TREE_TYPE (array_var
[ii
]));
2136 for (ii
= 0; ii
< list_size
; ii
++)
2138 if (array_vector
[ii
][0])
2140 tree array_opr_node
= array_value
[ii
][rank
- 1];
2141 for (s_jj
= rank
- 1; s_jj
>= 0; s_jj
--)
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
])));
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
])));
2160 vec_safe_push (array_operand
, array_opr_node
);
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
);
2167 replace_array_notations (&arg
, true, array_list
, array_operand
);
2168 for (ii
= 0; ii
< rank
; 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)));
2174 for (jj
= 0; jj
< rank
; jj
++)
2176 if (rank
&& expr_incr
[jj
])
2178 if (count_down
[0][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)));
2185 compare_expr
[jj
] = build2 (LT_EXPR
, boolean_type_node
,
2186 array_var
[jj
], array_length
[0][jj
]);
2190 loop_init
= pop_stmt_list (loop_init
);
2191 append_to_statement_list_force (loop_init
, &loop_with_init
);
2193 for (ii
= 0; ii
< rank
; ii
++)
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
,
2199 body
= pop_stmt_list (new_loop
);
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
);
2207 for (ii
= 0; ii
< list_size
; ii
++)
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
]);
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
);
2226 return loop_with_init
;
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. */
2234 fix_return_expr (tree expr
)
2236 tree new_mod_list
, new_var
, new_mod
, retval_expr
, retval_type
;
2237 location_t loc
= EXPR_LOCATION (expr
);
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
),
2245 TREE_OPERAND (retval_expr
, 1),
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
;
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
2260 expand_array_notation_exprs (tree t
)
2262 if (!contains_array_notation_expr (t
))
2265 switch (TREE_CODE (t
))
2268 t
= expand_array_notation_exprs (BIND_EXPR_BODY (t
));
2271 t
= fix_conditional_array_notations (t
);
2273 /* After the expansion if they are still a COND_EXPR, we go into its
2275 if (TREE_CODE (t
) == COND_EXPR
)
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
));
2285 t
= expand_array_notation_exprs (t
);
2287 case STATEMENT_LIST
:
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
));
2297 location_t loc
= EXPR_HAS_LOCATION (t
) ? EXPR_LOCATION (t
) :
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
) :
2303 t
= build_array_notation_expr (loc
, lhs
, TREE_TYPE (lhs
), NOP_EXPR
,
2304 rhs_loc
, rhs
, TREE_TYPE (rhs
));
2308 t
= fix_array_notation_call_expr (t
);
2311 if (contains_array_notation_expr (t
))
2312 t
= fix_return_expr (t
);
2314 case ARRAY_NOTATION_REF
:
2315 /* IF we are here, then we are dealing with cases like this:
2319 Replace those with just void zero node. */
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. */
2338 build_array_notation_ref (location_t loc
, tree array
, tree start_index
,
2339 tree length
, tree stride
, tree type
)
2341 tree array_ntn_tree
= NULL_TREE
;
2342 size_t stride_rank
= 0, length_rank
= 0, start_rank
= 0;
2344 if (!INTEGRAL_TYPE_P (TREE_TYPE (start_index
)))
2347 "start-index of array notation triplet is not an integer");
2348 return error_mark_node
;
2350 if (!INTEGRAL_TYPE_P (TREE_TYPE (length
)))
2352 error_at (loc
, "length of array notation triplet is not an integer");
2353 return error_mark_node
;
2356 /* The stride is an optional field. */
2357 if (stride
&& !INTEGRAL_TYPE_P (TREE_TYPE (stride
)))
2359 error_at (loc
, "stride of array notation triplet is not an integer");
2360 return error_mark_node
;
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);
2368 stride
= build_int_cst (TREE_TYPE (start_index
), 1);
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
;
2378 if (start_rank
!= 0)
2380 error_at (loc
, "rank of an array notation triplet's start-index is not "
2382 return error_mark_node
;
2384 if (length_rank
!= 0)
2386 error_at (loc
, "rank of an array notation triplet's length is not zero");
2387 return error_mark_node
;
2389 if (stride_rank
!= 0)
2391 error_at (loc
, "rank of array notation triplet's stride is not zero");
2392 return error_mark_node
;
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
;
2402 return array_ntn_tree
;