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)
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
)
805 error_at (location
, "rank mismatch between %qE and %qE", lhs
, rhs
);
806 pop_stmt_list (an_init
);
807 return error_mark_node
;
810 /* Here we assign the array notation components to variable so that we can
811 satisfy the exec once rule. */
812 for (ii
= 0; ii
< lhs_list_size
; ii
++)
814 tree array_node
= (*lhs_list
)[ii
];
815 tree array_begin
= ARRAY_NOTATION_START (array_node
);
816 tree array_lngth
= ARRAY_NOTATION_LENGTH (array_node
);
817 tree array_strde
= ARRAY_NOTATION_STRIDE (array_node
);
819 if (TREE_CODE (array_begin
) != INTEGER_CST
)
821 begin_var
= build_decl (location
, VAR_DECL
, NULL_TREE
,
823 add_stmt (build_modify_expr (location
, begin_var
,
824 TREE_TYPE (begin_var
),
825 NOP_EXPR
, location
, array_begin
,
826 TREE_TYPE (array_begin
)));
827 ARRAY_NOTATION_START (array_node
) = begin_var
;
830 if (TREE_CODE (array_lngth
) != INTEGER_CST
)
832 lngth_var
= build_decl (location
, VAR_DECL
, NULL_TREE
,
834 add_stmt (build_modify_expr (location
, lngth_var
,
835 TREE_TYPE (lngth_var
),
836 NOP_EXPR
, location
, array_lngth
,
837 TREE_TYPE (array_lngth
)));
838 ARRAY_NOTATION_LENGTH (array_node
) = lngth_var
;
840 if (TREE_CODE (array_strde
) != INTEGER_CST
)
842 strde_var
= build_decl (location
, VAR_DECL
, NULL_TREE
,
845 add_stmt (build_modify_expr (location
, strde_var
,
846 TREE_TYPE (strde_var
),
847 NOP_EXPR
, location
, array_strde
,
848 TREE_TYPE (array_strde
)));
849 ARRAY_NOTATION_STRIDE (array_node
) = strde_var
;
852 for (ii
= 0; ii
< rhs_list_size
; ii
++)
854 tree array_node
= (*rhs_list
)[ii
];
855 if (array_node
&& TREE_CODE (array_node
) == ARRAY_NOTATION_REF
)
857 tree array_begin
= ARRAY_NOTATION_START (array_node
);
858 tree array_lngth
= ARRAY_NOTATION_LENGTH (array_node
);
859 tree array_strde
= ARRAY_NOTATION_STRIDE (array_node
);
861 if (TREE_CODE (array_begin
) != INTEGER_CST
)
863 begin_var
= build_decl (location
, VAR_DECL
, NULL_TREE
,
865 add_stmt (build_modify_expr (location
, begin_var
,
866 TREE_TYPE (begin_var
),
867 NOP_EXPR
, location
, array_begin
,
868 TREE_TYPE (array_begin
)));
869 ARRAY_NOTATION_START (array_node
) = begin_var
;
871 if (TREE_CODE (array_lngth
) != INTEGER_CST
)
873 lngth_var
= build_decl (location
, VAR_DECL
, NULL_TREE
,
875 add_stmt (build_modify_expr (location
, lngth_var
,
876 TREE_TYPE (lngth_var
),
877 NOP_EXPR
, location
, array_lngth
,
878 TREE_TYPE (array_lngth
)));
879 ARRAY_NOTATION_LENGTH (array_node
) = lngth_var
;
881 if (TREE_CODE (array_strde
) != INTEGER_CST
)
883 strde_var
= build_decl (location
, VAR_DECL
, NULL_TREE
,
886 add_stmt (build_modify_expr (location
, strde_var
,
887 TREE_TYPE (strde_var
),
888 NOP_EXPR
, location
, array_strde
,
889 TREE_TYPE (array_strde
)));
890 ARRAY_NOTATION_STRIDE (array_node
) = strde_var
;
895 lhs_vector
= XNEWVEC (bool *, lhs_list_size
);
896 for (ii
= 0; ii
< lhs_list_size
; ii
++)
897 lhs_vector
[ii
] = XNEWVEC (bool, lhs_rank
);
899 rhs_vector
= XNEWVEC (bool *, rhs_list_size
);
900 for (ii
= 0; ii
< rhs_list_size
; ii
++)
901 rhs_vector
[ii
] = XNEWVEC (bool, rhs_rank
);
903 lhs_array
= XNEWVEC (tree
*, lhs_list_size
);
904 for (ii
= 0; ii
< lhs_list_size
; ii
++)
905 lhs_array
[ii
] = XNEWVEC (tree
, lhs_rank
);
907 rhs_array
= XNEWVEC (tree
*, rhs_list_size
);
908 for (ii
= 0; ii
< rhs_list_size
; ii
++)
909 rhs_array
[ii
] = XNEWVEC (tree
, rhs_rank
);
911 lhs_value
= XNEWVEC (tree
*, lhs_list_size
);
912 for (ii
= 0; ii
< lhs_list_size
; ii
++)
913 lhs_value
[ii
] = XNEWVEC (tree
, lhs_rank
);
915 rhs_value
= XNEWVEC (tree
*, rhs_list_size
);
916 for (ii
= 0; ii
< rhs_list_size
; ii
++)
917 rhs_value
[ii
] = XNEWVEC (tree
, rhs_rank
);
919 lhs_stride
= XNEWVEC (tree
*, lhs_list_size
);
920 for (ii
= 0; ii
< lhs_list_size
; ii
++)
921 lhs_stride
[ii
] = XNEWVEC (tree
, lhs_rank
);
923 rhs_stride
= XNEWVEC (tree
*, rhs_list_size
);
924 for (ii
= 0; ii
< rhs_list_size
; ii
++)
925 rhs_stride
[ii
] = XNEWVEC (tree
, rhs_rank
);
927 lhs_length
= XNEWVEC (tree
*, lhs_list_size
);
928 for (ii
= 0; ii
< lhs_list_size
; ii
++)
929 lhs_length
[ii
] = XNEWVEC (tree
, lhs_rank
);
931 rhs_length
= XNEWVEC (tree
*, rhs_list_size
);
932 for (ii
= 0; ii
< rhs_list_size
; ii
++)
933 rhs_length
[ii
] = XNEWVEC (tree
, rhs_rank
);
935 lhs_start
= XNEWVEC (tree
*, lhs_list_size
);
936 for (ii
= 0; ii
< lhs_list_size
; ii
++)
937 lhs_start
[ii
] = XNEWVEC (tree
, lhs_rank
);
939 rhs_start
= XNEWVEC (tree
*, rhs_list_size
);
940 for (ii
= 0; ii
< rhs_list_size
; ii
++)
941 rhs_start
[ii
] = XNEWVEC (tree
, rhs_rank
);
943 lhs_var
= XNEWVEC (tree
, lhs_rank
);
944 rhs_var
= XNEWVEC (tree
, rhs_rank
);
945 cond_expr
= XNEWVEC (tree
, MAX (lhs_rank
, rhs_rank
));
947 lhs_expr_incr
= XNEWVEC (tree
, lhs_rank
);
948 rhs_expr_incr
=XNEWVEC (tree
, rhs_rank
);
950 lhs_ind_init
= XNEWVEC (tree
, lhs_rank
);
951 rhs_ind_init
= XNEWVEC (tree
, rhs_rank
);
953 lhs_count_down
= XNEWVEC (bool *, lhs_list_size
);
954 for (ii
= 0; ii
< lhs_list_size
; ii
++)
955 lhs_count_down
[ii
] = XNEWVEC (bool, lhs_rank
);
957 rhs_count_down
= XNEWVEC (bool *, rhs_list_size
);
958 for (ii
= 0; ii
< rhs_list_size
; ii
++)
959 rhs_count_down
[ii
] = XNEWVEC (bool, rhs_rank
);
961 lhs_compare
= XNEWVEC (tree
, lhs_rank
);
962 rhs_compare
= XNEWVEC (tree
, rhs_rank
);
966 for (ii
= 0; ii
< lhs_list_size
; ii
++)
969 ii_tree
= (*lhs_list
)[ii
];
972 if (TREE_CODE (ii_tree
) == ARRAY_NOTATION_REF
)
974 lhs_array
[ii
][jj
] = ii_tree
;
976 ii_tree
= ARRAY_NOTATION_ARRAY (ii_tree
);
978 else if (TREE_CODE (ii_tree
) == ARRAY_REF
)
979 ii_tree
= TREE_OPERAND (ii_tree
, 0);
980 else if (TREE_CODE (ii_tree
) == VAR_DECL
981 || TREE_CODE (ii_tree
) == PARM_DECL
)
987 lhs_array
[0][0] = NULL_TREE
;
991 for (ii
= 0; ii
< rhs_list_size
; ii
++)
994 ii_tree
= (*rhs_list
)[ii
];
997 if (TREE_CODE (ii_tree
) == ARRAY_NOTATION_REF
)
999 rhs_array
[ii
][jj
] = ii_tree
;
1001 ii_tree
= ARRAY_NOTATION_ARRAY (ii_tree
);
1003 else if (TREE_CODE (ii_tree
) == ARRAY_REF
)
1004 ii_tree
= TREE_OPERAND (ii_tree
, 0);
1005 else if (TREE_CODE (ii_tree
) == VAR_DECL
1006 || TREE_CODE (ii_tree
) == PARM_DECL
1007 || TREE_CODE (ii_tree
) == CALL_EXPR
)
1013 for (ii
= 0; ii
< lhs_list_size
; ii
++)
1015 tree lhs_node
= (*lhs_list
)[ii
];
1016 if (TREE_CODE (lhs_node
) == ARRAY_NOTATION_REF
)
1018 for (jj
= 0; jj
< lhs_rank
; jj
++)
1020 if (TREE_CODE (lhs_array
[ii
][jj
]) == ARRAY_NOTATION_REF
)
1022 lhs_value
[ii
][jj
] = ARRAY_NOTATION_ARRAY (lhs_array
[ii
][jj
]);
1023 lhs_start
[ii
][jj
] = ARRAY_NOTATION_START (lhs_array
[ii
][jj
]);
1024 lhs_length
[ii
][jj
] =
1025 fold_build1 (CONVERT_EXPR
, integer_type_node
,
1026 ARRAY_NOTATION_LENGTH (lhs_array
[ii
][jj
]));
1027 lhs_stride
[ii
][jj
] =
1028 fold_build1 (CONVERT_EXPR
, integer_type_node
,
1029 ARRAY_NOTATION_STRIDE (lhs_array
[ii
][jj
]));
1030 lhs_vector
[ii
][jj
] = true;
1031 /* IF the stride value is variable (i.e. not constant) then
1032 assume that the length is positive. */
1033 if (!TREE_CONSTANT (lhs_length
[ii
][jj
]))
1034 lhs_count_down
[ii
][jj
] = false;
1035 else if (tree_int_cst_lt
1036 (lhs_length
[ii
][jj
],
1037 build_zero_cst (TREE_TYPE (lhs_length
[ii
][jj
]))))
1038 lhs_count_down
[ii
][jj
] = true;
1040 lhs_count_down
[ii
][jj
] = false;
1043 lhs_vector
[ii
][jj
] = false;
1047 for (ii
= 0; ii
< rhs_list_size
; ii
++)
1049 if (TREE_CODE ((*rhs_list
)[ii
]) == ARRAY_NOTATION_REF
)
1051 for (jj
= 0; jj
< rhs_rank
; jj
++)
1053 if (TREE_CODE (rhs_array
[ii
][jj
]) == ARRAY_NOTATION_REF
)
1055 rhs_value
[ii
][jj
] = ARRAY_NOTATION_ARRAY (rhs_array
[ii
][jj
]);
1056 rhs_start
[ii
][jj
] = ARRAY_NOTATION_START (rhs_array
[ii
][jj
]);
1057 rhs_length
[ii
][jj
] =
1058 fold_build1 (CONVERT_EXPR
, integer_type_node
,
1059 ARRAY_NOTATION_LENGTH (rhs_array
[ii
][jj
]));
1060 rhs_stride
[ii
][jj
] =
1061 fold_build1 (CONVERT_EXPR
, integer_type_node
,
1062 ARRAY_NOTATION_STRIDE (rhs_array
[ii
][jj
]));
1063 rhs_vector
[ii
][jj
] = true;
1064 /* If the stride value is variable (i.e. not constant) then
1065 assume that the length is positive. */
1066 if (!TREE_CONSTANT (rhs_length
[ii
][jj
]))
1067 rhs_count_down
[ii
][jj
] = false;
1068 else if (tree_int_cst_lt
1069 (rhs_length
[ii
][jj
],
1070 build_int_cst (TREE_TYPE (rhs_length
[ii
][jj
]), 0)))
1071 rhs_count_down
[ii
][jj
] = true;
1073 rhs_count_down
[ii
][jj
] = false;
1076 rhs_vector
[ii
][jj
] = false;
1080 for (jj
= 0; jj
< rhs_rank
; jj
++)
1082 rhs_vector
[ii
][jj
] = false;
1083 rhs_length
[ii
][jj
] = NULL_TREE
;
1087 if (length_mismatch_in_expr_p (EXPR_LOCATION (lhs
), lhs_length
,
1088 lhs_list_size
, lhs_rank
)
1089 || length_mismatch_in_expr_p (EXPR_LOCATION (rhs
), rhs_length
,
1090 rhs_list_size
, rhs_rank
))
1092 pop_stmt_list (an_init
);
1093 return error_mark_node
;
1096 if (lhs_list_size
> 0 && rhs_list_size
> 0 && lhs_rank
> 0 && rhs_rank
> 0
1097 && TREE_CODE (lhs_length
[0][0]) == INTEGER_CST
1099 && TREE_CODE (rhs_length
[0][0]) == INTEGER_CST
)
1101 HOST_WIDE_INT l_length
= int_cst_value (lhs_length
[0][0]);
1102 HOST_WIDE_INT r_length
= int_cst_value (rhs_length
[0][0]);
1103 /* Length can be negative or positive. As long as the magnitude is OK,
1104 then the array notation is valid. */
1105 if (absu_hwi (l_length
) != absu_hwi (r_length
))
1107 error_at (location
, "length mismatch between LHS and RHS");
1108 pop_stmt_list (an_init
);
1109 return error_mark_node
;
1112 for (ii
= 0; ii
< lhs_rank
; ii
++)
1114 if (lhs_vector
[0][ii
])
1116 lhs_var
[ii
] = build_decl (location
, VAR_DECL
, NULL_TREE
,
1118 lhs_ind_init
[ii
] = build_modify_expr
1119 (location
, lhs_var
[ii
], TREE_TYPE (lhs_var
[ii
]),
1121 location
, build_zero_cst (TREE_TYPE (lhs_var
[ii
])),
1122 TREE_TYPE (lhs_var
[ii
]));
1126 for (ii
= 0; ii
< rhs_rank
; ii
++)
1128 /* When we have a polynomial, we assume that the indices are of type
1130 rhs_var
[ii
] = build_decl (location
, VAR_DECL
, NULL_TREE
,
1132 rhs_ind_init
[ii
] = build_modify_expr
1133 (location
, rhs_var
[ii
], TREE_TYPE (rhs_var
[ii
]),
1135 location
, build_int_cst (TREE_TYPE (rhs_var
[ii
]), 0),
1136 TREE_TYPE (rhs_var
[ii
]));
1140 for (ii
= 0; ii
< lhs_list_size
; ii
++)
1142 if (lhs_vector
[ii
][0])
1144 /* The last ARRAY_NOTATION element's ARRAY component should be
1145 the array's base value. */
1146 tree lhs_array_opr
= lhs_value
[ii
][lhs_rank
- 1];
1147 for (s_jj
= lhs_rank
- 1; s_jj
>= 0; s_jj
--)
1149 if (lhs_count_down
[ii
][s_jj
])
1150 /* Array[start_index + (induction_var * stride)]. */
1151 lhs_array_opr
= build_array_ref
1152 (location
, lhs_array_opr
,
1153 build2 (MINUS_EXPR
, TREE_TYPE (lhs_var
[s_jj
]),
1154 lhs_start
[ii
][s_jj
],
1155 build2 (MULT_EXPR
, TREE_TYPE (lhs_var
[s_jj
]),
1157 lhs_stride
[ii
][s_jj
])));
1159 lhs_array_opr
= build_array_ref
1160 (location
, lhs_array_opr
,
1161 build2 (PLUS_EXPR
, TREE_TYPE (lhs_var
[s_jj
]),
1162 lhs_start
[ii
][s_jj
],
1163 build2 (MULT_EXPR
, TREE_TYPE (lhs_var
[s_jj
]),
1165 lhs_stride
[ii
][s_jj
])));
1167 vec_safe_push (lhs_array_operand
, lhs_array_opr
);
1170 vec_safe_push (lhs_array_operand
, integer_one_node
);
1172 replace_array_notations (&lhs
, true, lhs_list
, lhs_array_operand
);
1173 array_expr_lhs
= lhs
;
1178 for (ii
= 0; ii
< rhs_list_size
; ii
++)
1180 if (rhs_vector
[ii
][0])
1182 tree rhs_array_opr
= rhs_value
[ii
][rhs_rank
- 1];
1183 for (s_jj
= rhs_rank
- 1; s_jj
>= 0; s_jj
--)
1185 if (rhs_count_down
[ii
][s_jj
])
1186 /* Array[start_index - (induction_var * stride)] */
1187 rhs_array_opr
= build_array_ref
1188 (location
, rhs_array_opr
,
1189 build2 (MINUS_EXPR
, TREE_TYPE (rhs_var
[s_jj
]),
1190 rhs_start
[ii
][s_jj
],
1191 build2 (MULT_EXPR
, TREE_TYPE (rhs_var
[s_jj
]),
1193 rhs_stride
[ii
][s_jj
])));
1195 /* Array[start_index + (induction_var * stride)] */
1196 rhs_array_opr
= build_array_ref
1197 (location
, rhs_array_opr
,
1198 build2 (PLUS_EXPR
, TREE_TYPE (rhs_var
[s_jj
]),
1199 rhs_start
[ii
][s_jj
],
1200 build2 (MULT_EXPR
, TREE_TYPE (rhs_var
[s_jj
]),
1202 rhs_stride
[ii
][s_jj
])));
1204 vec_safe_push (rhs_array_operand
, rhs_array_opr
);
1207 /* This is just a dummy node to make sure the list sizes for both
1208 array list and array operand list are the same. */
1209 vec_safe_push (rhs_array_operand
, integer_one_node
);
1212 for (ii
= 0; ii
< rhs_list_size
; ii
++)
1214 tree rhs_node
= (*rhs_list
)[ii
];
1215 if (TREE_CODE (rhs_node
) == CALL_EXPR
)
1218 tree func_name
= CALL_EXPR_FN (rhs_node
);
1219 if (TREE_CODE (func_name
) == ADDR_EXPR
)
1220 if (is_sec_implicit_index_fn (func_name
))
1223 extract_sec_implicit_index_arg (location
, rhs_node
);
1224 if (idx_value
== -1) /* This means we have an error. */
1225 return error_mark_node
;
1226 else if (idx_value
< (int) lhs_rank
&& idx_value
>= 0)
1227 vec_safe_push (rhs_array_operand
, lhs_var
[idx_value
]);
1231 tree lhs_base
= (*lhs_list
)[ii
];
1232 for (ee
= 0; ee
< lhs_rank
; ee
++)
1233 lhs_base
= ARRAY_NOTATION_ARRAY (lhs_base
);
1234 error_at (location
, "__sec_implicit_index argument %d "
1235 "must be less than rank of %qD", idx_value
,
1237 return error_mark_node
;
1242 replace_array_notations (&rhs
, true, rhs_list
, rhs_array_operand
);
1243 array_expr_rhs
= rhs
;
1247 for (ii
= 0; ii
< rhs_list_size
; ii
++)
1249 tree rhs_node
= (*rhs_list
)[ii
];
1250 if (TREE_CODE (rhs_node
) == CALL_EXPR
)
1253 tree func_name
= CALL_EXPR_FN (rhs_node
);
1254 if (TREE_CODE (func_name
) == ADDR_EXPR
)
1255 if (is_sec_implicit_index_fn (func_name
))
1258 extract_sec_implicit_index_arg (location
, rhs_node
);
1259 if (idx_value
== -1) /* This means we have an error. */
1260 return error_mark_node
;
1261 else if (idx_value
< (int) lhs_rank
&& idx_value
>= 0)
1262 vec_safe_push (rhs_array_operand
, lhs_var
[idx_value
]);
1266 tree lhs_base
= (*lhs_list
)[ii
];
1267 for (ee
= 0; ee
< lhs_rank
; ee
++)
1268 lhs_base
= ARRAY_NOTATION_ARRAY (lhs_base
);
1269 error_at (location
, "__sec_implicit_index argument %d "
1270 "must be less than rank of %qD", idx_value
,
1272 return error_mark_node
;
1277 replace_array_notations (&rhs
, true, rhs_list
, rhs_array_operand
);
1278 array_expr_rhs
= rhs
;
1279 rhs_expr_incr
[0] = NULL_TREE
;
1282 for (ii
= 0; ii
< rhs_rank
; ii
++)
1283 rhs_expr_incr
[ii
] = build2 (MODIFY_EXPR
, void_type_node
, rhs_var
[ii
],
1285 (PLUS_EXPR
, TREE_TYPE (rhs_var
[ii
]),
1287 build_one_cst (TREE_TYPE (rhs_var
[ii
]))));
1289 for (ii
= 0; ii
< lhs_rank
; ii
++)
1290 lhs_expr_incr
[ii
] = build2
1291 (MODIFY_EXPR
, void_type_node
, lhs_var
[ii
],
1292 build2 (PLUS_EXPR
, TREE_TYPE (lhs_var
[ii
]), lhs_var
[ii
],
1293 build_one_cst (TREE_TYPE (lhs_var
[ii
]))));
1295 /* If array_expr_lhs is NULL, then we have function that returns void or
1296 its return value is ignored. */
1297 if (!array_expr_lhs
)
1298 array_expr_lhs
= lhs
;
1300 array_expr
= build_modify_expr (location
, array_expr_lhs
, lhs_origtype
,
1301 modifycode
, rhs_loc
, array_expr_rhs
,
1304 for (jj
= 0; jj
< MAX (lhs_rank
, rhs_rank
); jj
++)
1306 if (rhs_rank
&& rhs_expr_incr
[jj
])
1310 lhs_compare
[jj
] = integer_one_node
;
1311 else if (lhs_count_down
[0][jj
])
1312 lhs_compare
[jj
] = build2
1313 (GT_EXPR
, boolean_type_node
, lhs_var
[jj
], lhs_length
[0][jj
]);
1315 lhs_compare
[jj
] = build2
1316 (LT_EXPR
, boolean_type_node
, lhs_var
[jj
], lhs_length
[0][jj
]);
1319 /* The reason why we have this here is for the following case:
1320 Array[:][:] = function_call(something) + Array2[:][:];
1322 So, we will skip the first operand of RHS and then go to the
1323 2nd to find whether we should count up or down. */
1325 for (iii
= 0; iii
< rhs_list_size
; iii
++)
1326 if (rhs_vector
[iii
][jj
])
1329 /* What we are doing here is this:
1330 We always count up, so:
1331 if (length is negative ==> which means we count down)
1332 we multiply length by -1 and count up => ii < -LENGTH
1334 we just count up, so we compare for ii < LENGTH
1336 if (rhs_count_down
[iii
][jj
])
1337 /* We use iii for rhs_length because that is the correct countdown
1339 rhs_compare
[jj
] = build2
1340 (LT_EXPR
, boolean_type_node
, rhs_var
[jj
],
1341 build2 (MULT_EXPR
, TREE_TYPE (rhs_var
[jj
]),
1342 rhs_length
[iii
][jj
],
1343 build_int_cst (TREE_TYPE (rhs_var
[jj
]), -1)));
1345 rhs_compare
[jj
] = build2 (LT_EXPR
, boolean_type_node
, rhs_var
[jj
],
1346 rhs_length
[iii
][jj
]);
1347 if (lhs_compare
[ii
] != integer_one_node
)
1348 cond_expr
[jj
] = build2 (TRUTH_ANDIF_EXPR
, void_type_node
,
1349 lhs_compare
[jj
], rhs_compare
[jj
]);
1351 cond_expr
[jj
] = rhs_compare
[jj
];
1355 if (lhs_count_down
[0][jj
])
1356 cond_expr
[jj
] = build2
1357 (GT_EXPR
, boolean_type_node
, lhs_var
[jj
], lhs_length
[0][jj
]);
1359 cond_expr
[jj
] = build2
1360 (LT_EXPR
, boolean_type_node
, lhs_var
[jj
], lhs_length
[0][jj
]);
1364 an_init
= pop_stmt_list (an_init
);
1365 append_to_statement_list_force (an_init
, &loop_with_init
);
1367 for (ii
= 0; ii
< MAX (lhs_rank
, rhs_rank
); ii
++)
1369 tree incr_list
= alloc_stmt_list ();
1370 tree new_loop
= push_stmt_list ();
1372 add_stmt (lhs_ind_init
[ii
]);
1374 add_stmt (rhs_ind_init
[ii
]);
1376 append_to_statement_list_force (lhs_expr_incr
[ii
], &incr_list
);
1377 if (rhs_rank
&& rhs_expr_incr
[ii
])
1378 append_to_statement_list_force (rhs_expr_incr
[ii
], &incr_list
);
1379 c_finish_loop (location
, cond_expr
[ii
], incr_list
, body
, NULL_TREE
,
1381 body
= pop_stmt_list (new_loop
);
1383 append_to_statement_list_force (body
, &loop_with_init
);
1384 return loop_with_init
;
1387 /* Helper function for fix_conditional_array_notations. Encloses the
1388 conditional statement passed in STMT with a loop around it
1389 and replaces the condition in STMT with a ARRAY_REF tree-node to the array.
1390 The condition must have an ARRAY_NOTATION_REF tree. An expansion of array
1391 notation in STMT is returned in a STATEMENT_LIST. */
1394 fix_conditional_array_notations_1 (tree stmt
)
1396 vec
<tree
, va_gc
> *array_list
= NULL
, *array_operand
= NULL
;
1397 size_t list_size
= 0;
1398 tree cond
= NULL_TREE
, builtin_loop
= NULL_TREE
, new_var
= NULL_TREE
;
1399 size_t rank
= 0, ii
= 0, jj
= 0;
1401 tree
**array_ops
, *array_var
, jj_tree
, loop_init
;
1402 tree
**array_value
, **array_stride
, **array_length
, **array_start
;
1403 tree
*compare_expr
, *expr_incr
, *ind_init
;
1404 bool **count_down
, **array_vector
;
1405 tree begin_var
, lngth_var
, strde_var
;
1406 location_t location
= EXPR_LOCATION (stmt
);
1407 tree body
= NULL_TREE
, loop_with_init
= alloc_stmt_list ();
1408 if (TREE_CODE (stmt
) == COND_EXPR
)
1409 cond
= COND_EXPR_COND (stmt
);
1410 else if (TREE_CODE (stmt
) == SWITCH_EXPR
)
1411 cond
= SWITCH_COND (stmt
);
1413 /* Otherwise dont even touch the statement. */
1416 if (!find_rank (location
, cond
, cond
, false, &rank
))
1417 return error_mark_node
;
1419 extract_array_notation_exprs (stmt
, false, &array_list
);
1420 loop_init
= push_stmt_list ();
1421 for (ii
= 0; ii
< vec_safe_length (array_list
); ii
++)
1423 tree array_node
= (*array_list
)[ii
];
1424 if (TREE_CODE (array_node
) == CALL_EXPR
)
1426 builtin_loop
= fix_builtin_array_notation_fn (array_node
, &new_var
);
1427 if (builtin_loop
== error_mark_node
)
1429 add_stmt (error_mark_node
);
1430 pop_stmt_list (loop_init
);
1433 else if (builtin_loop
)
1435 vec
<tree
, va_gc
>* sub_list
= NULL
, *new_var_list
= NULL
;
1436 vec_safe_push (sub_list
, array_node
);
1437 vec_safe_push (new_var_list
, new_var
);
1438 add_stmt (builtin_loop
);
1439 replace_array_notations (&stmt
, false, sub_list
, new_var_list
);
1444 if (!find_rank (location
, stmt
, stmt
, true, &rank
))
1446 pop_stmt_list (loop_init
);
1447 return error_mark_node
;
1452 pop_stmt_list (loop_init
);
1455 extract_array_notation_exprs (stmt
, true, &array_list
);
1457 if (vec_safe_length (array_list
) == 0)
1460 list_size
= vec_safe_length (array_list
);
1462 array_ops
= XNEWVEC (tree
*, list_size
);
1463 for (ii
= 0; ii
< list_size
; ii
++)
1464 array_ops
[ii
] = XNEWVEC (tree
, rank
);
1466 array_vector
= XNEWVEC (bool *, list_size
);
1467 for (ii
= 0; ii
< list_size
; ii
++)
1468 array_vector
[ii
] = XNEWVEC (bool, rank
);
1470 array_value
= XNEWVEC (tree
*, list_size
);
1471 array_stride
= XNEWVEC (tree
*, list_size
);
1472 array_length
= XNEWVEC (tree
*, list_size
);
1473 array_start
= XNEWVEC (tree
*, list_size
);
1475 for (ii
= 0; ii
< list_size
; ii
++)
1477 array_value
[ii
] = XNEWVEC (tree
, rank
);
1478 array_stride
[ii
] = XNEWVEC (tree
, rank
);
1479 array_length
[ii
] = XNEWVEC (tree
, rank
);
1480 array_start
[ii
] = XNEWVEC (tree
, rank
);
1483 compare_expr
= XNEWVEC (tree
, rank
);
1484 expr_incr
= XNEWVEC (tree
, rank
);
1485 ind_init
= XNEWVEC (tree
, rank
);
1487 count_down
= XNEWVEC (bool *, list_size
);
1488 for (ii
= 0; ii
< list_size
; ii
++)
1489 count_down
[ii
] = XNEWVEC (bool, rank
);
1491 array_var
= XNEWVEC (tree
, rank
);
1493 for (ii
= 0; ii
< list_size
; ii
++)
1495 tree array_node
= (*array_list
)[ii
];
1496 if (array_node
&& TREE_CODE (array_node
) == ARRAY_NOTATION_REF
)
1498 tree array_begin
= ARRAY_NOTATION_START (array_node
);
1499 tree array_lngth
= ARRAY_NOTATION_LENGTH (array_node
);
1500 tree array_strde
= ARRAY_NOTATION_STRIDE (array_node
);
1502 if (TREE_CODE (array_begin
) != INTEGER_CST
)
1504 begin_var
= build_decl (location
, VAR_DECL
, NULL_TREE
,
1506 add_stmt (build_modify_expr (location
, begin_var
,
1507 TREE_TYPE (begin_var
),
1508 NOP_EXPR
, location
, array_begin
,
1509 TREE_TYPE (array_begin
)));
1510 ARRAY_NOTATION_START (array_node
) = begin_var
;
1512 if (TREE_CODE (array_lngth
) != INTEGER_CST
)
1514 lngth_var
= build_decl (location
, VAR_DECL
, NULL_TREE
,
1516 add_stmt (build_modify_expr (location
, lngth_var
,
1517 TREE_TYPE (lngth_var
),
1518 NOP_EXPR
, location
, array_lngth
,
1519 TREE_TYPE (array_lngth
)));
1520 ARRAY_NOTATION_LENGTH (array_node
) = lngth_var
;
1522 if (TREE_CODE (array_strde
) != INTEGER_CST
)
1524 strde_var
= build_decl (location
, VAR_DECL
, NULL_TREE
,
1526 add_stmt (build_modify_expr (location
, strde_var
,
1527 TREE_TYPE (strde_var
),
1528 NOP_EXPR
, location
, array_strde
,
1529 TREE_TYPE (array_strde
)));
1530 ARRAY_NOTATION_STRIDE (array_node
) = strde_var
;
1534 for (ii
= 0; ii
< list_size
; ii
++)
1536 tree array_node
= (*array_list
)[ii
];
1538 for (jj_tree
= array_node
;
1539 jj_tree
&& TREE_CODE (jj_tree
) == ARRAY_NOTATION_REF
;
1540 jj_tree
= ARRAY_NOTATION_ARRAY (jj_tree
))
1542 array_ops
[ii
][jj
] = jj_tree
;
1546 for (ii
= 0; ii
< list_size
; ii
++)
1548 tree array_node
= (*array_list
)[ii
];
1549 if (TREE_CODE (array_node
) == ARRAY_NOTATION_REF
)
1551 for (jj
= 0; jj
< rank
; jj
++)
1553 if (TREE_CODE (array_ops
[ii
][jj
]) == ARRAY_NOTATION_REF
)
1555 array_value
[ii
][jj
] =
1556 ARRAY_NOTATION_ARRAY (array_ops
[ii
][jj
]);
1557 array_start
[ii
][jj
] =
1558 ARRAY_NOTATION_START (array_ops
[ii
][jj
]);
1559 array_length
[ii
][jj
] =
1560 fold_build1 (CONVERT_EXPR
, integer_type_node
,
1561 ARRAY_NOTATION_LENGTH (array_ops
[ii
][jj
]));
1562 array_stride
[ii
][jj
] =
1563 fold_build1 (CONVERT_EXPR
, integer_type_node
,
1564 ARRAY_NOTATION_STRIDE (array_ops
[ii
][jj
]));
1565 array_vector
[ii
][jj
] = true;
1567 if (!TREE_CONSTANT (array_length
[ii
][jj
]))
1568 count_down
[ii
][jj
] = false;
1569 else if (tree_int_cst_lt
1570 (array_length
[ii
][jj
],
1571 build_int_cst (TREE_TYPE (array_length
[ii
][jj
]),
1573 count_down
[ii
][jj
] = true;
1575 count_down
[ii
][jj
] = false;
1578 array_vector
[ii
][jj
] = false;
1583 for (ii
= 0; ii
< rank
; ii
++)
1585 array_var
[ii
] = build_decl (location
, VAR_DECL
, NULL_TREE
,
1588 build_modify_expr (location
, array_var
[ii
],
1589 TREE_TYPE (array_var
[ii
]), NOP_EXPR
,
1591 build_int_cst (TREE_TYPE (array_var
[ii
]), 0),
1592 TREE_TYPE (array_var
[ii
]));
1595 for (ii
= 0; ii
< list_size
; ii
++)
1597 if (array_vector
[ii
][0])
1599 tree array_opr
= array_value
[ii
][rank
- 1];
1600 for (s_jj
= rank
- 1; s_jj
>= 0; s_jj
--)
1602 if (count_down
[ii
][s_jj
])
1603 /* Array[start_index - (induction_var * stride)] */
1604 array_opr
= build_array_ref
1605 (location
, array_opr
,
1606 build2 (MINUS_EXPR
, TREE_TYPE (array_var
[s_jj
]),
1607 array_start
[ii
][s_jj
],
1608 build2 (MULT_EXPR
, TREE_TYPE (array_var
[s_jj
]),
1609 array_var
[s_jj
], array_stride
[ii
][s_jj
])));
1611 /* Array[start_index + (induction_var * stride)] */
1612 array_opr
= build_array_ref
1613 (location
, array_opr
,
1614 build2 (PLUS_EXPR
, TREE_TYPE (array_var
[s_jj
]),
1615 array_start
[ii
][s_jj
],
1616 build2 (MULT_EXPR
, TREE_TYPE (array_var
[s_jj
]),
1617 array_var
[s_jj
], array_stride
[ii
][s_jj
])));
1619 vec_safe_push (array_operand
, array_opr
);
1622 /* This is just a dummy node to make sure the list sizes for both
1623 array list and array operand list are the same. */
1624 vec_safe_push (array_operand
, integer_one_node
);
1626 replace_array_notations (&stmt
, true, array_list
, array_operand
);
1627 for (ii
= 0; ii
< rank
; ii
++)
1628 expr_incr
[ii
] = build2 (MODIFY_EXPR
, void_type_node
, array_var
[ii
],
1629 build2 (PLUS_EXPR
, TREE_TYPE (array_var
[ii
]),
1631 build_int_cst (TREE_TYPE (array_var
[ii
]),
1633 for (jj
= 0; jj
< rank
; jj
++)
1635 if (rank
&& expr_incr
[jj
])
1637 if (count_down
[0][jj
])
1639 build2 (LT_EXPR
, boolean_type_node
, array_var
[jj
],
1640 build2 (MULT_EXPR
, TREE_TYPE (array_var
[jj
]),
1641 array_length
[0][jj
],
1642 build_int_cst (TREE_TYPE (array_var
[jj
]), -1)));
1644 compare_expr
[jj
] = build2 (LT_EXPR
, boolean_type_node
,
1645 array_var
[jj
], array_length
[0][jj
]);
1649 loop_init
= pop_stmt_list (loop_init
);
1651 append_to_statement_list_force (loop_init
, &loop_with_init
);
1653 for (ii
= 0; ii
< rank
; ii
++)
1655 tree new_loop
= push_stmt_list ();
1656 add_stmt (ind_init
[ii
]);
1657 c_finish_loop (location
, compare_expr
[ii
], expr_incr
[ii
], body
, NULL_TREE
,
1659 body
= pop_stmt_list (new_loop
);
1661 append_to_statement_list_force (body
, &loop_with_init
);
1662 XDELETEVEC (expr_incr
);
1663 XDELETEVEC (ind_init
);
1665 for (ii
= 0; ii
< list_size
; ii
++)
1667 XDELETEVEC (count_down
[ii
]);
1668 XDELETEVEC (array_value
[ii
]);
1669 XDELETEVEC (array_stride
[ii
]);
1670 XDELETEVEC (array_length
[ii
]);
1671 XDELETEVEC (array_start
[ii
]);
1672 XDELETEVEC (array_ops
[ii
]);
1673 XDELETEVEC (array_vector
[ii
]);
1676 XDELETEVEC (count_down
);
1677 XDELETEVEC (array_value
);
1678 XDELETEVEC (array_stride
);
1679 XDELETEVEC (array_length
);
1680 XDELETEVEC (array_start
);
1681 XDELETEVEC (array_ops
);
1682 XDELETEVEC (array_vector
);
1684 return loop_with_init
;
1687 /* Top-level function to replace ARRAY_NOTATION_REF in a conditional statement
1688 in STMT. An expansion of array notation in STMT is returned as a
1692 fix_conditional_array_notations (tree stmt
)
1694 if (TREE_CODE (stmt
) == STATEMENT_LIST
)
1696 tree_stmt_iterator tsi
;
1697 for (tsi
= tsi_start (stmt
); !tsi_end_p (tsi
); tsi_next (&tsi
))
1699 tree single_stmt
= *tsi_stmt_ptr (tsi
);
1700 *tsi_stmt_ptr (tsi
) =
1701 fix_conditional_array_notations_1 (single_stmt
);
1706 return fix_conditional_array_notations_1 (stmt
);
1709 /* Create a struct c_expr that contains a loop with ARRAY_REF expr at location
1710 LOCATION with the tree_code CODE and the array notation expr is
1711 passed in ARG. Returns the fixed c_expr in ARG itself. */
1714 fix_array_notation_expr (location_t location
, enum tree_code code
,
1718 vec
<tree
, va_gc
> *array_list
= NULL
, *array_operand
= NULL
;
1719 size_t list_size
= 0, rank
= 0, ii
= 0, jj
= 0;
1721 tree
**array_ops
, *array_var
, jj_tree
, loop_init
;
1722 tree
**array_value
, **array_stride
, **array_length
, **array_start
;
1723 tree
*compare_expr
, *expr_incr
, *ind_init
;
1724 tree body
, loop_with_init
= alloc_stmt_list ();
1725 bool **count_down
, **array_vector
;
1727 if (!find_rank (location
, arg
.value
, arg
.value
, false, &rank
))
1729 /* If this function returns a NULL, we convert the tree value in the
1730 structure to error_mark_node and the parser should take care of the
1732 arg
.value
= error_mark_node
;
1739 extract_array_notation_exprs (arg
.value
, true, &array_list
);
1741 if (vec_safe_length (array_list
) == 0)
1744 list_size
= vec_safe_length (array_list
);
1746 array_ops
= XNEWVEC (tree
*, list_size
);
1747 for (ii
= 0; ii
< list_size
; ii
++)
1748 array_ops
[ii
] = XNEWVEC (tree
, rank
);
1750 array_vector
= XNEWVEC (bool *, list_size
);
1751 for (ii
= 0; ii
< list_size
; ii
++)
1752 array_vector
[ii
] = XNEWVEC (bool, rank
);
1754 array_value
= XNEWVEC (tree
*, list_size
);
1755 array_stride
= XNEWVEC (tree
*, list_size
);
1756 array_length
= XNEWVEC (tree
*, list_size
);
1757 array_start
= XNEWVEC (tree
*, list_size
);
1759 for (ii
= 0; ii
< list_size
; ii
++)
1761 array_value
[ii
] = XNEWVEC (tree
, rank
);
1762 array_stride
[ii
] = XNEWVEC (tree
, rank
);
1763 array_length
[ii
] = XNEWVEC (tree
, rank
);
1764 array_start
[ii
] = XNEWVEC (tree
, rank
);
1767 compare_expr
= XNEWVEC (tree
, rank
);
1768 expr_incr
= XNEWVEC (tree
, rank
);
1769 ind_init
= XNEWVEC (tree
, rank
);
1771 count_down
= XNEWVEC (bool *, list_size
);
1772 for (ii
= 0; ii
< list_size
; ii
++)
1773 count_down
[ii
] = XNEWVEC (bool, rank
);
1774 array_var
= XNEWVEC (tree
, rank
);
1776 for (ii
= 0; ii
< list_size
; ii
++)
1779 for (jj_tree
= (*array_list
)[ii
];
1780 jj_tree
&& TREE_CODE (jj_tree
) == ARRAY_NOTATION_REF
;
1781 jj_tree
= ARRAY_NOTATION_ARRAY (jj_tree
))
1783 array_ops
[ii
][jj
] = jj_tree
;
1788 loop_init
= push_stmt_list ();
1790 for (ii
= 0; ii
< list_size
; ii
++)
1792 tree array_node
= (*array_list
)[ii
];
1793 if (TREE_CODE (array_node
) == ARRAY_NOTATION_REF
)
1795 for (jj
= 0; jj
< rank
; jj
++)
1797 if (TREE_CODE (array_ops
[ii
][jj
]) == ARRAY_NOTATION_REF
)
1799 array_value
[ii
][jj
] =
1800 ARRAY_NOTATION_ARRAY (array_ops
[ii
][jj
]);
1801 array_start
[ii
][jj
] =
1802 ARRAY_NOTATION_START (array_ops
[ii
][jj
]);
1803 array_length
[ii
][jj
] =
1804 fold_build1 (CONVERT_EXPR
, integer_type_node
,
1805 ARRAY_NOTATION_LENGTH (array_ops
[ii
][jj
]));
1806 array_stride
[ii
][jj
] =
1807 fold_build1 (CONVERT_EXPR
, integer_type_node
,
1808 ARRAY_NOTATION_STRIDE (array_ops
[ii
][jj
]));
1809 array_vector
[ii
][jj
] = true;
1811 if (!TREE_CONSTANT (array_length
[ii
][jj
]))
1812 count_down
[ii
][jj
] = false;
1813 else if (tree_int_cst_lt
1814 (array_length
[ii
][jj
],
1815 build_int_cst (TREE_TYPE (array_length
[ii
][jj
]),
1817 count_down
[ii
][jj
] = true;
1819 count_down
[ii
][jj
] = false;
1822 array_vector
[ii
][jj
] = false;
1827 for (ii
= 0; ii
< rank
; ii
++)
1829 array_var
[ii
] = build_decl (location
, VAR_DECL
, NULL_TREE
,
1832 build_modify_expr (location
, array_var
[ii
],
1833 TREE_TYPE (array_var
[ii
]), NOP_EXPR
,
1835 build_int_cst (TREE_TYPE (array_var
[ii
]), 0),
1836 TREE_TYPE (array_var
[ii
]));
1839 for (ii
= 0; ii
< list_size
; ii
++)
1841 if (array_vector
[ii
][0])
1843 tree array_opr
= array_value
[ii
][rank
- 1];
1844 for (s_jj
= rank
- 1; s_jj
>= 0; s_jj
--)
1846 if (count_down
[ii
][s_jj
])
1847 /* Array[start_index - (induction_var * stride)] */
1848 array_opr
= build_array_ref
1849 (location
, array_opr
,
1850 build2 (MINUS_EXPR
, TREE_TYPE (array_var
[s_jj
]),
1851 array_start
[ii
][s_jj
],
1852 build2 (MULT_EXPR
, TREE_TYPE (array_var
[s_jj
]),
1853 array_var
[s_jj
], array_stride
[ii
][s_jj
])));
1855 /* Array[start_index + (induction_var * stride)] */
1856 array_opr
= build_array_ref
1857 (location
, array_opr
,
1858 build2 (PLUS_EXPR
, TREE_TYPE (array_var
[s_jj
]),
1859 array_start
[ii
][s_jj
],
1860 build2 (MULT_EXPR
, TREE_TYPE (array_var
[s_jj
]),
1861 array_var
[s_jj
], array_stride
[ii
][s_jj
])));
1863 vec_safe_push (array_operand
, array_opr
);
1866 /* This is just a dummy node to make sure the list sizes for both
1867 array list and array operand list are the same. */
1868 vec_safe_push (array_operand
, integer_one_node
);
1870 replace_array_notations (&arg
.value
, true, array_list
, array_operand
);
1872 for (ii
= 0; ii
< rank
; ii
++)
1874 build2 (MODIFY_EXPR
, void_type_node
, array_var
[ii
],
1875 build2 (PLUS_EXPR
, TREE_TYPE (array_var
[ii
]), array_var
[ii
],
1876 build_int_cst (TREE_TYPE (array_var
[ii
]), 1)));
1878 for (jj
= 0; jj
< rank
; jj
++)
1880 if (rank
&& expr_incr
[jj
])
1882 if (count_down
[0][jj
])
1884 build2 (LT_EXPR
, boolean_type_node
, array_var
[jj
],
1885 build2 (MULT_EXPR
, TREE_TYPE (array_var
[jj
]),
1886 array_length
[0][jj
],
1887 build_int_cst (TREE_TYPE (array_var
[jj
]), -1)));
1889 compare_expr
[jj
] = build2 (LT_EXPR
, boolean_type_node
,
1890 array_var
[jj
], array_length
[0][jj
]);
1894 if (code
== POSTINCREMENT_EXPR
|| code
== POSTDECREMENT_EXPR
)
1896 arg
= default_function_array_read_conversion (location
, arg
);
1897 arg
.value
= build_unary_op (location
, code
, arg
.value
, 0);
1899 else if (code
== PREINCREMENT_EXPR
|| code
== PREDECREMENT_EXPR
)
1901 arg
= default_function_array_read_conversion (location
, arg
);
1902 arg
= parser_build_unary_op (location
, code
, arg
);
1905 loop_init
= pop_stmt_list (loop_init
);
1906 append_to_statement_list_force (loop_init
, &loop_with_init
);
1909 for (ii
= 0; ii
< rank
; ii
++)
1911 tree new_loop
= push_stmt_list ();
1912 add_stmt (ind_init
[ii
]);
1913 c_finish_loop (location
, compare_expr
[ii
], expr_incr
[ii
], body
, NULL_TREE
,
1915 body
= pop_stmt_list (new_loop
);
1917 append_to_statement_list_force (body
, &loop_with_init
);
1918 XDELETEVEC (expr_incr
);
1919 XDELETEVEC (ind_init
);
1920 XDELETEVEC (array_var
);
1922 for (ii
= 0; ii
< list_size
; ii
++)
1924 XDELETEVEC (count_down
[ii
]);
1925 XDELETEVEC (array_value
[ii
]);
1926 XDELETEVEC (array_stride
[ii
]);
1927 XDELETEVEC (array_length
[ii
]);
1928 XDELETEVEC (array_start
[ii
]);
1929 XDELETEVEC (array_ops
[ii
]);
1930 XDELETEVEC (array_vector
[ii
]);
1933 XDELETEVEC (count_down
);
1934 XDELETEVEC (array_value
);
1935 XDELETEVEC (array_stride
);
1936 XDELETEVEC (array_length
);
1937 XDELETEVEC (array_start
);
1938 XDELETEVEC (array_ops
);
1939 XDELETEVEC (array_vector
);
1941 arg
.value
= loop_with_init
;
1945 /* Replaces array notations in a void function call arguments in ARG and returns
1946 a STATEMENT_LIST. */
1949 fix_array_notation_call_expr (tree arg
)
1951 vec
<tree
, va_gc
> *array_list
= NULL
, *array_operand
= NULL
;
1952 tree new_var
= NULL_TREE
;
1953 size_t list_size
= 0, rank
= 0, ii
= 0, jj
= 0;
1955 tree
**array_ops
, *array_var
, jj_tree
, loop_init
;
1956 tree
**array_value
, **array_stride
, **array_length
, **array_start
;
1957 tree body
, loop_with_init
= alloc_stmt_list ();
1958 tree
*compare_expr
, *expr_incr
, *ind_init
;
1959 bool **count_down
, **array_vector
;
1960 tree begin_var
, lngth_var
, strde_var
;
1961 location_t location
= UNKNOWN_LOCATION
;
1963 if (TREE_CODE (arg
) == CALL_EXPR
1964 && is_cilkplus_reduce_builtin (CALL_EXPR_FN (arg
)))
1966 loop_init
= fix_builtin_array_notation_fn (arg
, &new_var
);
1967 /* We are ignoring the new var because either the user does not want to
1968 capture it OR he is using sec_reduce_mutating function. */
1972 if (!find_rank (location
, arg
, arg
, false, &rank
))
1973 return error_mark_node
;
1978 extract_array_notation_exprs (arg
, true, &array_list
);
1979 if (vec_safe_length (array_list
) == 0)
1982 list_size
= vec_safe_length (array_list
);
1983 location
= EXPR_LOCATION (arg
);
1985 array_ops
= XNEWVEC (tree
*, list_size
);
1986 for (ii
= 0; ii
< list_size
; ii
++)
1987 array_ops
[ii
] = XNEWVEC (tree
, rank
);
1989 array_vector
= XNEWVEC (bool *, list_size
);
1990 for (ii
= 0; ii
< list_size
; ii
++)
1991 array_vector
[ii
] = (bool *) XNEWVEC (bool, rank
);
1993 array_value
= XNEWVEC (tree
*, list_size
);
1994 array_stride
= XNEWVEC (tree
*, list_size
);
1995 array_length
= XNEWVEC (tree
*, list_size
);
1996 array_start
= XNEWVEC (tree
*, list_size
);
1998 for (ii
= 0; ii
< list_size
; ii
++)
2000 array_value
[ii
] = XNEWVEC (tree
, rank
);
2001 array_stride
[ii
] = XNEWVEC (tree
, rank
);
2002 array_length
[ii
] = XNEWVEC (tree
, rank
);
2003 array_start
[ii
] = XNEWVEC (tree
, rank
);
2006 compare_expr
= XNEWVEC (tree
, rank
);
2007 expr_incr
= XNEWVEC (tree
, rank
);
2008 ind_init
= XNEWVEC (tree
, rank
);
2010 count_down
= XNEWVEC (bool *, list_size
);
2011 for (ii
= 0; ii
< list_size
; ii
++)
2012 count_down
[ii
] = XNEWVEC (bool, rank
);
2014 array_var
= XNEWVEC (tree
, rank
);
2016 loop_init
= push_stmt_list ();
2017 for (ii
= 0; ii
< list_size
; ii
++)
2019 tree array_node
= (*array_list
)[ii
];
2020 if (array_node
&& TREE_CODE (array_node
) == ARRAY_NOTATION_REF
)
2022 tree array_begin
= ARRAY_NOTATION_START (array_node
);
2023 tree array_lngth
= ARRAY_NOTATION_LENGTH (array_node
);
2024 tree array_strde
= ARRAY_NOTATION_STRIDE (array_node
);
2026 if (TREE_CODE (array_begin
) != INTEGER_CST
)
2028 begin_var
= build_decl (location
, VAR_DECL
, NULL_TREE
,
2030 add_stmt (build_modify_expr (location
, begin_var
,
2031 TREE_TYPE (begin_var
),
2032 NOP_EXPR
, location
, array_begin
,
2033 TREE_TYPE (array_begin
)));
2034 ARRAY_NOTATION_START (array_node
) = begin_var
;
2036 if (TREE_CODE (array_lngth
) != INTEGER_CST
)
2038 lngth_var
= build_decl (location
, VAR_DECL
, NULL_TREE
,
2040 add_stmt (build_modify_expr (location
, lngth_var
,
2041 TREE_TYPE (lngth_var
),
2042 NOP_EXPR
, location
, array_lngth
,
2043 TREE_TYPE (array_lngth
)));
2044 ARRAY_NOTATION_LENGTH (array_node
) = lngth_var
;
2046 if (TREE_CODE (array_strde
) != INTEGER_CST
)
2048 strde_var
= build_decl (location
, VAR_DECL
, NULL_TREE
,
2050 add_stmt (build_modify_expr (location
, strde_var
,
2051 TREE_TYPE (strde_var
),
2052 NOP_EXPR
, location
, array_strde
,
2053 TREE_TYPE (array_strde
)));
2054 ARRAY_NOTATION_STRIDE (array_node
) = strde_var
;
2058 for (ii
= 0; ii
< list_size
; ii
++)
2061 for (jj_tree
= (*array_list
)[ii
];
2062 jj_tree
&& TREE_CODE (jj_tree
) == ARRAY_NOTATION_REF
;
2063 jj_tree
= ARRAY_NOTATION_ARRAY (jj_tree
))
2065 array_ops
[ii
][jj
] = jj_tree
;
2070 for (ii
= 0; ii
< list_size
; ii
++)
2072 tree array_node
= (*array_list
)[ii
];
2073 if (TREE_CODE (array_node
) == ARRAY_NOTATION_REF
)
2075 for (jj
= 0; jj
< rank
; jj
++)
2077 if (TREE_CODE (array_ops
[ii
][jj
]) == ARRAY_NOTATION_REF
)
2079 array_value
[ii
][jj
] =
2080 ARRAY_NOTATION_ARRAY (array_ops
[ii
][jj
]);
2081 array_start
[ii
][jj
] =
2082 ARRAY_NOTATION_START (array_ops
[ii
][jj
]);
2083 array_length
[ii
][jj
] =
2084 fold_build1 (CONVERT_EXPR
, integer_type_node
,
2085 ARRAY_NOTATION_LENGTH (array_ops
[ii
][jj
]));
2086 array_stride
[ii
][jj
] =
2087 fold_build1 (CONVERT_EXPR
, integer_type_node
,
2088 ARRAY_NOTATION_STRIDE (array_ops
[ii
][jj
]));
2089 array_vector
[ii
][jj
] = true;
2091 if (!TREE_CONSTANT (array_length
[ii
][jj
]))
2092 count_down
[ii
][jj
] = false;
2093 else if (tree_int_cst_lt
2094 (array_length
[ii
][jj
],
2095 build_int_cst (TREE_TYPE (array_length
[ii
][jj
]),
2097 count_down
[ii
][jj
] = true;
2099 count_down
[ii
][jj
] = false;
2102 array_vector
[ii
][jj
] = false;
2107 if (length_mismatch_in_expr_p (location
, array_length
, list_size
, rank
))
2109 pop_stmt_list (loop_init
);
2110 return error_mark_node
;
2113 for (ii
= 0; ii
< rank
; ii
++)
2115 array_var
[ii
] = build_decl (location
, VAR_DECL
, NULL_TREE
,
2118 build_modify_expr (location
, array_var
[ii
],
2119 TREE_TYPE (array_var
[ii
]), NOP_EXPR
,
2121 build_int_cst (TREE_TYPE (array_var
[ii
]), 0),
2122 TREE_TYPE (array_var
[ii
]));
2125 for (ii
= 0; ii
< list_size
; ii
++)
2127 if (array_vector
[ii
][0])
2129 tree array_opr_node
= array_value
[ii
][rank
- 1];
2130 for (s_jj
= rank
- 1; s_jj
>= 0; s_jj
--)
2132 if (count_down
[ii
][s_jj
])
2133 /* Array[start_index - (induction_var * stride)] */
2134 array_opr_node
= build_array_ref
2135 (location
, array_opr_node
,
2136 build2 (MINUS_EXPR
, TREE_TYPE (array_var
[s_jj
]),
2137 array_start
[ii
][s_jj
],
2138 build2 (MULT_EXPR
, TREE_TYPE (array_var
[s_jj
]),
2139 array_var
[s_jj
], array_stride
[ii
][s_jj
])));
2141 /* Array[start_index + (induction_var * stride)] */
2142 array_opr_node
= build_array_ref
2143 (location
, array_opr_node
,
2144 build2 (PLUS_EXPR
, TREE_TYPE (array_var
[s_jj
]),
2145 array_start
[ii
][s_jj
],
2146 build2 (MULT_EXPR
, TREE_TYPE (array_var
[s_jj
]),
2147 array_var
[s_jj
], array_stride
[ii
][s_jj
])));
2149 vec_safe_push (array_operand
, array_opr_node
);
2152 /* This is just a dummy node to make sure the list sizes for both
2153 array list and array operand list are the same. */
2154 vec_safe_push (array_operand
, integer_one_node
);
2156 replace_array_notations (&arg
, true, array_list
, array_operand
);
2157 for (ii
= 0; ii
< rank
; ii
++)
2159 build2 (MODIFY_EXPR
, void_type_node
, array_var
[ii
],
2160 build2 (PLUS_EXPR
, TREE_TYPE (array_var
[ii
]), array_var
[ii
],
2161 build_int_cst (TREE_TYPE (array_var
[ii
]), 1)));
2163 for (jj
= 0; jj
< rank
; jj
++)
2165 if (rank
&& expr_incr
[jj
])
2167 if (count_down
[0][jj
])
2169 build2 (LT_EXPR
, boolean_type_node
, array_var
[jj
],
2170 build2 (MULT_EXPR
, TREE_TYPE (array_var
[jj
]),
2171 array_length
[0][jj
],
2172 build_int_cst (TREE_TYPE (array_var
[jj
]), -1)));
2174 compare_expr
[jj
] = build2 (LT_EXPR
, boolean_type_node
,
2175 array_var
[jj
], array_length
[0][jj
]);
2179 loop_init
= pop_stmt_list (loop_init
);
2180 append_to_statement_list_force (loop_init
, &loop_with_init
);
2182 for (ii
= 0; ii
< rank
; ii
++)
2184 tree new_loop
= push_stmt_list ();
2185 add_stmt (ind_init
[ii
]);
2186 c_finish_loop (location
, compare_expr
[ii
], expr_incr
[ii
], body
, NULL_TREE
,
2188 body
= pop_stmt_list (new_loop
);
2190 append_to_statement_list_force (body
, &loop_with_init
);
2191 XDELETEVEC (compare_expr
);
2192 XDELETEVEC (expr_incr
);
2193 XDELETEVEC (ind_init
);
2194 XDELETEVEC (array_var
);
2196 for (ii
= 0; ii
< list_size
; ii
++)
2198 XDELETEVEC (count_down
[ii
]);
2199 XDELETEVEC (array_value
[ii
]);
2200 XDELETEVEC (array_stride
[ii
]);
2201 XDELETEVEC (array_length
[ii
]);
2202 XDELETEVEC (array_start
[ii
]);
2203 XDELETEVEC (array_ops
[ii
]);
2204 XDELETEVEC (array_vector
[ii
]);
2207 XDELETEVEC (count_down
);
2208 XDELETEVEC (array_value
);
2209 XDELETEVEC (array_stride
);
2210 XDELETEVEC (array_length
);
2211 XDELETEVEC (array_start
);
2212 XDELETEVEC (array_ops
);
2213 XDELETEVEC (array_vector
);
2215 return loop_with_init
;
2218 /* Expands the built-in functions in a return. EXPR is a RETURN_EXPR with
2219 a built-in reduction function. This function returns the expansion code for
2220 the built-in function. */
2223 fix_return_expr (tree expr
)
2225 tree new_mod_list
, new_var
, new_mod
, retval_expr
, retval_type
;
2226 location_t loc
= EXPR_LOCATION (expr
);
2228 new_mod_list
= alloc_stmt_list ();
2229 retval_expr
= TREE_OPERAND (expr
, 0);
2230 retval_type
= TREE_TYPE (TREE_OPERAND (retval_expr
, 1));
2231 new_var
= build_decl (loc
, VAR_DECL
, NULL_TREE
, TREE_TYPE (retval_expr
));
2232 new_mod
= build_array_notation_expr (loc
, new_var
, TREE_TYPE (new_var
),
2234 TREE_OPERAND (retval_expr
, 1),
2236 TREE_OPERAND (retval_expr
, 1) = new_var
;
2237 TREE_OPERAND (expr
, 0) = retval_expr
;
2238 append_to_statement_list_force (new_mod
, &new_mod_list
);
2239 append_to_statement_list_force (expr
, &new_mod_list
);
2240 return new_mod_list
;
2243 /* Walks through tree node T and find all the call-statements that do not return
2244 anything and fix up any array notations they may carry. The return value
2245 is the same type as T but with all array notations replaced with appropriate
2249 expand_array_notation_exprs (tree t
)
2251 if (!contains_array_notation_expr (t
))
2254 switch (TREE_CODE (t
))
2257 t
= expand_array_notation_exprs (BIND_EXPR_BODY (t
));
2260 t
= fix_conditional_array_notations (t
);
2262 /* After the expansion if they are still a COND_EXPR, we go into its
2264 if (TREE_CODE (t
) == COND_EXPR
)
2266 if (COND_EXPR_THEN (t
))
2267 COND_EXPR_THEN (t
) =
2268 expand_array_notation_exprs (COND_EXPR_THEN (t
));
2269 if (COND_EXPR_ELSE (t
))
2270 COND_EXPR_ELSE (t
) =
2271 expand_array_notation_exprs (COND_EXPR_ELSE (t
));
2274 t
= expand_array_notation_exprs (t
);
2276 case STATEMENT_LIST
:
2278 tree_stmt_iterator ii_tsi
;
2279 for (ii_tsi
= tsi_start (t
); !tsi_end_p (ii_tsi
); tsi_next (&ii_tsi
))
2280 *tsi_stmt_ptr (ii_tsi
) =
2281 expand_array_notation_exprs (*tsi_stmt_ptr (ii_tsi
));
2286 location_t loc
= EXPR_HAS_LOCATION (t
) ? EXPR_LOCATION (t
) :
2288 tree lhs
= TREE_OPERAND (t
, 0);
2289 tree rhs
= TREE_OPERAND (t
, 1);
2290 location_t rhs_loc
= EXPR_HAS_LOCATION (rhs
) ? EXPR_LOCATION (rhs
) :
2292 t
= build_array_notation_expr (loc
, lhs
, TREE_TYPE (lhs
), NOP_EXPR
,
2293 rhs_loc
, rhs
, TREE_TYPE (rhs
));
2297 t
= fix_array_notation_call_expr (t
);
2300 if (contains_array_notation_expr (t
))
2301 t
= fix_return_expr (t
);
2303 case ARRAY_NOTATION_REF
:
2304 /* IF we are here, then we are dealing with cases like this:
2308 Replace those with just void zero node. */
2316 /* This handles expression of the form "a[i:j:k]" or "a[:]" or "a[i:j]," which
2317 denotes an array notation expression. If a is a variable or a member, then
2318 we generate a ARRAY_NOTATION_REF front-end tree and return it.
2319 This tree is broken down to ARRAY_REF toward the end of parsing.
2320 ARRAY_NOTATION_REF tree holds the START_INDEX, LENGTH, STRIDE and the TYPE
2321 of ARRAY_REF. Restrictions on START_INDEX, LENGTH and STRIDE is same as that
2322 of the index field passed into ARRAY_REF. The only additional restriction
2323 is that, unlike index in ARRAY_REF, stride, length and start_index cannot
2324 contain ARRAY_NOTATIONS. */
2327 build_array_notation_ref (location_t loc
, tree array
, tree start_index
,
2328 tree length
, tree stride
, tree type
)
2330 tree array_ntn_tree
= NULL_TREE
;
2331 size_t stride_rank
= 0, length_rank
= 0, start_rank
= 0;
2333 if (!INTEGRAL_TYPE_P (TREE_TYPE (start_index
)))
2336 "start-index of array notation triplet is not an integer");
2337 return error_mark_node
;
2339 if (!INTEGRAL_TYPE_P (TREE_TYPE (length
)))
2341 error_at (loc
, "length of array notation triplet is not an integer");
2342 return error_mark_node
;
2345 /* The stride is an optional field. */
2346 if (stride
&& !INTEGRAL_TYPE_P (TREE_TYPE (stride
)))
2348 error_at (loc
, "stride of array notation triplet is not an integer");
2349 return error_mark_node
;
2353 if (TREE_CONSTANT (start_index
) && TREE_CONSTANT (length
)
2354 && tree_int_cst_lt (length
, start_index
))
2355 stride
= build_int_cst (TREE_TYPE (start_index
), -1);
2357 stride
= build_int_cst (TREE_TYPE (start_index
), 1);
2360 if (!find_rank (loc
, start_index
, start_index
, false, &start_rank
))
2361 return error_mark_node
;
2362 if (!find_rank (loc
, length
, length
, false, &length_rank
))
2363 return error_mark_node
;
2364 if (!find_rank (loc
, stride
, stride
, false, &stride_rank
))
2365 return error_mark_node
;
2367 if (start_rank
!= 0)
2369 error_at (loc
, "rank of an array notation triplet's start-index is not "
2371 return error_mark_node
;
2373 if (length_rank
!= 0)
2375 error_at (loc
, "rank of an array notation triplet's length is not zero");
2376 return error_mark_node
;
2378 if (stride_rank
!= 0)
2380 error_at (loc
, "rank of array notation triplet's stride is not zero");
2381 return error_mark_node
;
2383 array_ntn_tree
= build4 (ARRAY_NOTATION_REF
, NULL_TREE
, NULL_TREE
, NULL_TREE
,
2384 NULL_TREE
, NULL_TREE
);
2385 ARRAY_NOTATION_ARRAY (array_ntn_tree
) = array
;
2386 ARRAY_NOTATION_START (array_ntn_tree
) = start_index
;
2387 ARRAY_NOTATION_LENGTH (array_ntn_tree
) = length
;
2388 ARRAY_NOTATION_STRIDE (array_ntn_tree
) = stride
;
2389 TREE_TYPE (array_ntn_tree
) = type
;
2391 return array_ntn_tree
;