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-2015 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"
80 #include "gimple-expr.h"
81 #include "tree-iterator.h"
83 #include "c-family/c-common.h"
85 /* If *VALUE is not of type INTEGER_CST, PARM_DECL or VAR_DECL, then map it
86 to a variable and then set *VALUE to the new variable. */
89 make_triplet_val_inv (location_t loc
, tree
*value
)
92 if (TREE_CODE (*value
) != INTEGER_CST
93 && TREE_CODE (*value
) != PARM_DECL
94 && TREE_CODE (*value
) != VAR_DECL
)
96 var
= build_decl (loc
, VAR_DECL
, NULL_TREE
, integer_type_node
);
97 new_exp
= build_modify_expr (loc
, var
, TREE_TYPE (var
), NOP_EXPR
, loc
,
98 *value
, TREE_TYPE (*value
));
104 /* Populates the INCR and CMP vectors with the increment (of type POSTINCREMENT
105 or POSTDECREMENT) and comparison (of TYPE GT_EXPR or LT_EXPR) expressions,
106 using data from LENGTH, COUNT_DOWN, and VAR. INCR and CMP vectors are of
110 create_cmp_incr (location_t loc
, vec
<an_loop_parts
> *node
, size_t rank
,
111 vec
<vec
<an_parts
> > an_info
)
113 for (size_t ii
= 0; ii
< rank
; ii
++)
115 tree var
= (*node
)[ii
].var
;
116 tree length
= an_info
[0][ii
].length
;
117 (*node
)[ii
].incr
= build_unary_op (loc
, POSTINCREMENT_EXPR
, var
, 0);
118 (*node
)[ii
].cmp
= build2 (LT_EXPR
, boolean_type_node
, var
, length
);
122 /* Returns a vector of size RANK that contains an array ref that is derived from
123 array notation triplet parameters stored in VALUE, START, STRIDE. IS_VECTOR
124 is used to check if the data stored at its corresponding location is an
125 array notation. VAR is the induction variable passed in by the caller.
127 For example: For an array notation A[5:10:2], the vector start will be
128 of size 1 holding '5', stride of same size as start but holding the value of
129 as 2, is_vector as true and count_down as false. Let's assume VAR is 'x'
130 This function returns a vector of size 1 with the following data:
134 static vec
<tree
, va_gc
> *
135 create_array_refs (location_t loc
, vec
<vec
<an_parts
> > an_info
,
136 vec
<an_loop_parts
> an_loop_info
, size_t size
, size_t rank
)
138 tree ind_mult
, ind_incr
;
139 vec
<tree
, va_gc
> *array_operand
= NULL
;
140 for (size_t ii
= 0; ii
< size
; ii
++)
141 if (an_info
[ii
][0].is_vector
)
143 tree array_opr
= an_info
[ii
][rank
- 1].value
;
144 for (int s_jj
= rank
- 1; s_jj
>= 0; s_jj
--)
146 tree var
= an_loop_info
[s_jj
].var
;
147 tree stride
= an_info
[ii
][s_jj
].stride
;
148 tree start
= an_info
[ii
][s_jj
].start
;
149 ind_mult
= build2 (MULT_EXPR
, TREE_TYPE (var
), var
, stride
);
150 ind_incr
= build2 (PLUS_EXPR
, TREE_TYPE (var
), start
, ind_mult
);
151 array_opr
= build_array_ref (loc
, array_opr
, ind_incr
);
153 vec_safe_push (array_operand
, array_opr
);
156 /* This is just a dummy node to make sure both the list sizes for both
157 array list and array operand list are the same. */
158 vec_safe_push (array_operand
, integer_one_node
);
159 return array_operand
;
162 /* Replaces all the scalar expressions in *NODE. Returns a STATEMENT_LIST that
163 holds the NODE along with variables that holds the results of the invariant
167 replace_invariant_exprs (tree
*node
)
170 tree node_list
= NULL_TREE
;
171 tree t
= NULL_TREE
, new_var
= NULL_TREE
, new_node
;
172 struct inv_list data
;
174 data
.list_values
= NULL
;
175 data
.replacement
= NULL
;
176 data
.additional_tcodes
= NULL
;
177 walk_tree (node
, find_inv_trees
, (void *)&data
, NULL
);
179 if (vec_safe_length (data
.list_values
))
181 node_list
= push_stmt_list ();
182 for (ix
= 0; vec_safe_iterate (data
.list_values
, ix
, &t
); ix
++)
184 new_var
= build_decl (EXPR_LOCATION (t
), VAR_DECL
, NULL_TREE
,
186 gcc_assert (new_var
!= NULL_TREE
&& new_var
!= error_mark_node
);
187 new_node
= build2 (MODIFY_EXPR
, TREE_TYPE (t
), new_var
, t
);
189 vec_safe_push (data
.replacement
, new_var
);
191 walk_tree (node
, replace_inv_trees
, (void *)&data
, NULL
);
192 node_list
= pop_stmt_list (node_list
);
197 /* Given a CALL_EXPR to an array notation built-in function in
198 AN_BUILTIN_FN, replace the call with the appropriate loop and
199 computation. Return the computation in *NEW_VAR.
201 The return value in *NEW_VAR will always be a scalar. If the
202 built-in is __sec_reduce_mutating, *NEW_VAR is set to NULL_TREE. */
205 fix_builtin_array_notation_fn (tree an_builtin_fn
, tree
*new_var
)
207 tree new_var_type
= NULL_TREE
, func_parm
, new_expr
, new_yes_expr
, new_no_expr
;
208 tree array_ind_value
= NULL_TREE
, new_no_ind
, new_yes_ind
, new_no_list
;
209 tree new_yes_list
, new_cond_expr
, new_var_init
= NULL_TREE
;
210 tree new_exp_init
= NULL_TREE
;
211 vec
<tree
, va_gc
> *array_list
= NULL
, *array_operand
= NULL
;
212 size_t list_size
= 0, rank
= 0, ii
= 0;
213 tree loop_init
, array_op0
;
214 tree identity_value
= NULL_TREE
, call_fn
= NULL_TREE
, new_call_expr
, body
;
215 location_t location
= UNKNOWN_LOCATION
;
216 tree loop_with_init
= alloc_stmt_list ();
217 vec
<vec
<an_parts
> > an_info
= vNULL
;
218 vec
<an_loop_parts
> an_loop_info
= vNULL
;
219 enum built_in_function an_type
=
220 is_cilkplus_reduce_builtin (CALL_EXPR_FN (an_builtin_fn
));
221 if (an_type
== BUILT_IN_NONE
)
224 /* Builtin call should contain at least one argument. */
225 if (call_expr_nargs (an_builtin_fn
) == 0)
227 error_at (EXPR_LOCATION (an_builtin_fn
), "Invalid builtin arguments");
228 return error_mark_node
;
231 if (an_type
== BUILT_IN_CILKPLUS_SEC_REDUCE
232 || an_type
== BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING
)
234 call_fn
= CALL_EXPR_ARG (an_builtin_fn
, 2);
235 if (TREE_CODE (call_fn
) == ADDR_EXPR
)
236 call_fn
= TREE_OPERAND (call_fn
, 0);
237 identity_value
= CALL_EXPR_ARG (an_builtin_fn
, 0);
238 func_parm
= CALL_EXPR_ARG (an_builtin_fn
, 1);
241 func_parm
= CALL_EXPR_ARG (an_builtin_fn
, 0);
243 /* Fully fold any EXCESSIVE_PRECISION EXPR that can occur in the function
245 func_parm
= c_fully_fold (func_parm
, false, NULL
);
246 if (func_parm
== error_mark_node
)
247 return error_mark_node
;
249 location
= EXPR_LOCATION (an_builtin_fn
);
251 if (!find_rank (location
, an_builtin_fn
, an_builtin_fn
, true, &rank
))
252 return error_mark_node
;
256 error_at (location
, "Invalid builtin arguments");
257 return error_mark_node
;
260 && (an_type
== BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
261 || an_type
== BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND
))
263 error_at (location
, "__sec_reduce_min_ind or __sec_reduce_max_ind cannot"
264 " have arrays with dimension greater than 1");
265 return error_mark_node
;
268 extract_array_notation_exprs (func_parm
, true, &array_list
);
269 list_size
= vec_safe_length (array_list
);
272 case BUILT_IN_CILKPLUS_SEC_REDUCE_ADD
:
273 case BUILT_IN_CILKPLUS_SEC_REDUCE_MUL
:
274 case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX
:
275 case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN
:
276 new_var_type
= TREE_TYPE ((*array_list
)[0]);
278 case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_ZERO
:
279 case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_NONZERO
:
280 case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO
:
281 case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_NONZERO
:
282 new_var_type
= integer_type_node
;
284 case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
:
285 case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND
:
286 new_var_type
= integer_type_node
;
288 case BUILT_IN_CILKPLUS_SEC_REDUCE
:
289 if (call_fn
&& identity_value
)
290 new_var_type
= TREE_TYPE ((*array_list
)[0]);
292 case BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING
:
293 new_var_type
= NULL_TREE
;
299 an_loop_info
.safe_grow_cleared (rank
);
300 cilkplus_extract_an_triplets (array_list
, list_size
, rank
, &an_info
);
301 loop_init
= alloc_stmt_list ();
303 for (ii
= 0; ii
< rank
; ii
++)
305 an_loop_info
[ii
].var
= create_tmp_var (integer_type_node
);
306 an_loop_info
[ii
].ind_init
=
307 build_modify_expr (location
, an_loop_info
[ii
].var
,
308 TREE_TYPE (an_loop_info
[ii
].var
), NOP_EXPR
,
310 build_int_cst (TREE_TYPE (an_loop_info
[ii
].var
), 0),
311 TREE_TYPE (an_loop_info
[ii
].var
));
313 array_operand
= create_array_refs (location
, an_info
, an_loop_info
,
315 replace_array_notations (&func_parm
, true, array_list
, array_operand
);
317 create_cmp_incr (location
, &an_loop_info
, rank
, an_info
);
318 if (an_type
!= BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING
)
320 *new_var
= build_decl (location
, VAR_DECL
, NULL_TREE
, new_var_type
);
321 gcc_assert (*new_var
&& *new_var
!= error_mark_node
);
324 *new_var
= NULL_TREE
;
326 if (an_type
== BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
327 || an_type
== BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND
)
328 array_ind_value
= build_decl (location
, VAR_DECL
, NULL_TREE
,
329 TREE_TYPE (func_parm
));
330 array_op0
= (*array_operand
)[0];
331 if (TREE_CODE (array_op0
) == INDIRECT_REF
)
332 array_op0
= TREE_OPERAND (array_op0
, 0);
335 case BUILT_IN_CILKPLUS_SEC_REDUCE_ADD
:
336 new_var_init
= build_modify_expr
337 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
338 location
, build_zero_cst (new_var_type
), new_var_type
);
339 new_expr
= build_modify_expr
340 (location
, *new_var
, TREE_TYPE (*new_var
), PLUS_EXPR
,
341 location
, func_parm
, TREE_TYPE (func_parm
));
343 case BUILT_IN_CILKPLUS_SEC_REDUCE_MUL
:
344 new_var_init
= build_modify_expr
345 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
346 location
, build_one_cst (new_var_type
), new_var_type
);
347 new_expr
= build_modify_expr
348 (location
, *new_var
, TREE_TYPE (*new_var
), MULT_EXPR
,
349 location
, func_parm
, TREE_TYPE (func_parm
));
351 case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_ZERO
:
352 new_var_init
= build_modify_expr
353 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
354 location
, build_one_cst (new_var_type
), new_var_type
);
355 /* Initially you assume everything is zero, now if we find a case where
356 it is NOT true, then we set the result to false. Otherwise
357 we just keep the previous value. */
358 new_yes_expr
= build_modify_expr
359 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
360 location
, build_zero_cst (TREE_TYPE (*new_var
)),
361 TREE_TYPE (*new_var
));
362 new_no_expr
= build_modify_expr
363 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
364 location
, *new_var
, TREE_TYPE (*new_var
));
365 new_cond_expr
= build2 (NE_EXPR
, TREE_TYPE (func_parm
), func_parm
,
366 build_zero_cst (TREE_TYPE (func_parm
)));
367 new_expr
= build_conditional_expr
368 (location
, new_cond_expr
, false, new_yes_expr
,
369 TREE_TYPE (new_yes_expr
), new_no_expr
, TREE_TYPE (new_no_expr
));
371 case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_NONZERO
:
372 new_var_init
= build_modify_expr
373 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
374 location
, build_one_cst (new_var_type
), new_var_type
);
375 /* Initially you assume everything is non-zero, now if we find a case
376 where it is NOT true, then we set the result to false. Otherwise
377 we just keep the previous value. */
378 new_yes_expr
= build_modify_expr
379 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
380 location
, build_zero_cst (TREE_TYPE (*new_var
)),
381 TREE_TYPE (*new_var
));
382 new_no_expr
= build_modify_expr
383 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
384 location
, *new_var
, TREE_TYPE (*new_var
));
385 new_cond_expr
= build2 (EQ_EXPR
, TREE_TYPE (func_parm
), func_parm
,
386 build_zero_cst (TREE_TYPE (func_parm
)));
387 new_expr
= build_conditional_expr
388 (location
, new_cond_expr
, false, new_yes_expr
,
389 TREE_TYPE (new_yes_expr
), new_no_expr
, TREE_TYPE (new_no_expr
));
391 case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO
:
392 new_var_init
= build_modify_expr
393 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
394 location
, build_zero_cst (new_var_type
), new_var_type
);
395 /* Initially we assume there are NO zeros in the list. When we find
396 a non-zero, we keep the previous value. If we find a zero, we
397 set the value to true. */
398 new_yes_expr
= build_modify_expr
399 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
400 location
, build_one_cst (new_var_type
), new_var_type
);
401 new_no_expr
= build_modify_expr
402 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
403 location
, *new_var
, TREE_TYPE (*new_var
));
404 new_cond_expr
= build2 (EQ_EXPR
, TREE_TYPE (func_parm
), func_parm
,
405 build_zero_cst (TREE_TYPE (func_parm
)));
406 new_expr
= build_conditional_expr
407 (location
, new_cond_expr
, false, new_yes_expr
,
408 TREE_TYPE (new_yes_expr
), new_no_expr
, TREE_TYPE (new_no_expr
));
410 case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_NONZERO
:
411 new_var_init
= build_modify_expr
412 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
413 location
, build_zero_cst (new_var_type
), new_var_type
);
414 /* Initially we assume there are NO non-zeros in the list. When we find
415 a zero, we keep the previous value. If we find a non-zero, we set
416 the value to true. */
417 new_yes_expr
= build_modify_expr
418 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
419 location
, build_one_cst (new_var_type
), new_var_type
);
420 new_no_expr
= build_modify_expr
421 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
422 location
, *new_var
, TREE_TYPE (*new_var
));
423 new_cond_expr
= build2 (NE_EXPR
, TREE_TYPE (func_parm
), func_parm
,
424 build_zero_cst (TREE_TYPE (func_parm
)));
425 new_expr
= build_conditional_expr
426 (location
, new_cond_expr
, false, new_yes_expr
,
427 TREE_TYPE (new_yes_expr
), new_no_expr
, TREE_TYPE (new_no_expr
));
429 case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX
:
430 if (TYPE_MIN_VALUE (new_var_type
))
431 new_var_init
= build_modify_expr
432 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
433 location
, TYPE_MIN_VALUE (new_var_type
), new_var_type
);
435 new_var_init
= build_modify_expr
436 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
437 location
, func_parm
, new_var_type
);
438 new_no_expr
= build_modify_expr
439 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
440 location
, *new_var
, TREE_TYPE (*new_var
));
441 new_yes_expr
= build_modify_expr
442 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
443 location
, func_parm
, TREE_TYPE (*new_var
));
444 new_expr
= build_conditional_expr
446 build2 (LT_EXPR
, TREE_TYPE (*new_var
), *new_var
, func_parm
), false,
447 new_yes_expr
, TREE_TYPE (*new_var
), new_no_expr
, TREE_TYPE (*new_var
));
449 case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN
:
450 if (TYPE_MAX_VALUE (new_var_type
))
451 new_var_init
= build_modify_expr
452 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
453 location
, TYPE_MAX_VALUE (new_var_type
), new_var_type
);
455 new_var_init
= build_modify_expr
456 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
457 location
, func_parm
, new_var_type
);
458 new_no_expr
= build_modify_expr
459 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
460 location
, *new_var
, TREE_TYPE (*new_var
));
461 new_yes_expr
= build_modify_expr
462 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
463 location
, func_parm
, TREE_TYPE (*new_var
));
464 new_expr
= build_conditional_expr
466 build2 (GT_EXPR
, TREE_TYPE (*new_var
), *new_var
, func_parm
), false,
467 new_yes_expr
, TREE_TYPE (*new_var
), new_no_expr
, TREE_TYPE (*new_var
));
469 case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
:
470 new_var_init
= build_modify_expr
471 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
472 location
, build_zero_cst (new_var_type
), new_var_type
);
473 new_exp_init
= build_modify_expr
474 (location
, array_ind_value
, TREE_TYPE (array_ind_value
),
475 NOP_EXPR
, location
, func_parm
, TREE_TYPE (func_parm
));
476 new_no_ind
= build_modify_expr
477 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
478 location
, *new_var
, TREE_TYPE (*new_var
));
479 new_no_expr
= build_modify_expr
480 (location
, array_ind_value
, TREE_TYPE (array_ind_value
),
482 location
, array_ind_value
, TREE_TYPE (array_ind_value
));
485 new_yes_ind
= build_modify_expr
486 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
487 location
, an_loop_info
[0].var
, TREE_TYPE (an_loop_info
[0].var
));
488 new_yes_expr
= build_modify_expr
489 (location
, array_ind_value
, TREE_TYPE (array_ind_value
),
491 location
, func_parm
, TREE_TYPE ((*array_operand
)[0]));
495 new_yes_ind
= build_modify_expr
496 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
497 location
, TREE_OPERAND (array_op0
, 1),
498 TREE_TYPE (TREE_OPERAND (array_op0
, 1)));
499 new_yes_expr
= build_modify_expr
500 (location
, array_ind_value
, TREE_TYPE (array_ind_value
),
502 location
, func_parm
, TREE_OPERAND (array_op0
, 1));
504 new_yes_list
= alloc_stmt_list ();
505 append_to_statement_list (new_yes_ind
, &new_yes_list
);
506 append_to_statement_list (new_yes_expr
, &new_yes_list
);
508 new_no_list
= alloc_stmt_list ();
509 append_to_statement_list (new_no_ind
, &new_no_list
);
510 append_to_statement_list (new_no_expr
, &new_no_list
);
512 new_expr
= build_conditional_expr
514 build2 (LE_EXPR
, TREE_TYPE (array_ind_value
), array_ind_value
,
517 new_yes_list
, TREE_TYPE (*new_var
), new_no_list
, TREE_TYPE (*new_var
));
519 case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND
:
520 new_var_init
= build_modify_expr
521 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
522 location
, build_zero_cst (new_var_type
), new_var_type
);
523 new_exp_init
= build_modify_expr
524 (location
, array_ind_value
, TREE_TYPE (array_ind_value
),
525 NOP_EXPR
, location
, func_parm
, TREE_TYPE (func_parm
));
526 new_no_ind
= build_modify_expr
527 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
528 location
, *new_var
, TREE_TYPE (*new_var
));
529 new_no_expr
= build_modify_expr
530 (location
, array_ind_value
, TREE_TYPE (array_ind_value
),
532 location
, array_ind_value
, TREE_TYPE (array_ind_value
));
535 new_yes_ind
= build_modify_expr
536 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
537 location
, an_loop_info
[0].var
, TREE_TYPE (an_loop_info
[0].var
));
538 new_yes_expr
= build_modify_expr
539 (location
, array_ind_value
, TREE_TYPE (array_ind_value
),
541 location
, func_parm
, TREE_TYPE (array_op0
));
545 new_yes_ind
= build_modify_expr
546 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
547 location
, TREE_OPERAND (array_op0
, 1),
548 TREE_TYPE (TREE_OPERAND (array_op0
, 1)));
549 new_yes_expr
= build_modify_expr
550 (location
, array_ind_value
, TREE_TYPE (array_ind_value
),
552 location
, func_parm
, TREE_OPERAND (array_op0
, 1));
554 new_yes_list
= alloc_stmt_list ();
555 append_to_statement_list (new_yes_ind
, &new_yes_list
);
556 append_to_statement_list (new_yes_expr
, &new_yes_list
);
558 new_no_list
= alloc_stmt_list ();
559 append_to_statement_list (new_no_ind
, &new_no_list
);
560 append_to_statement_list (new_no_expr
, &new_no_list
);
562 new_expr
= build_conditional_expr
564 build2 (GE_EXPR
, TREE_TYPE (array_ind_value
), array_ind_value
,
567 new_yes_list
, TREE_TYPE (*new_var
), new_no_list
, TREE_TYPE (*new_var
));
569 case BUILT_IN_CILKPLUS_SEC_REDUCE
:
570 new_var_init
= build_modify_expr
571 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
572 location
, identity_value
, new_var_type
);
573 new_call_expr
= build_call_expr (call_fn
, 2, *new_var
, func_parm
);
574 new_expr
= build_modify_expr
575 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
576 location
, new_call_expr
, TREE_TYPE (*new_var
));
578 case BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING
:
579 new_expr
= build_call_expr (call_fn
, 2, identity_value
, func_parm
);
586 for (ii
= 0; ii
< rank
; ii
++)
587 append_to_statement_list (an_loop_info
[ii
].ind_init
, &loop_init
);
589 if (an_type
== BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
590 || an_type
== BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND
)
591 append_to_statement_list (new_exp_init
, &loop_init
);
592 if (an_type
!= BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING
)
593 append_to_statement_list (new_var_init
, &loop_init
);
595 append_to_statement_list_force (loop_init
, &loop_with_init
);
597 for (ii
= 0; ii
< rank
; ii
++)
599 tree new_loop
= push_stmt_list ();
600 c_finish_loop (location
, an_loop_info
[ii
].cmp
, an_loop_info
[ii
].incr
,
601 body
, NULL_TREE
, NULL_TREE
, true);
602 body
= pop_stmt_list (new_loop
);
604 append_to_statement_list_force (body
, &loop_with_init
);
607 an_loop_info
.release ();
609 return loop_with_init
;
612 /* Returns a loop with ARRAY_REF inside it with an appropriate modify expr.
613 The LHS and/or RHS will be array notation expressions that have a MODIFYCODE
614 Their locations are specified by LHS_LOC, RHS_LOC. The location of the
615 modify expression is location. The original type of LHS and RHS are passed
616 in LHS_ORIGTYPE and RHS_ORIGTYPE. */
619 build_array_notation_expr (location_t location
, tree lhs
, tree lhs_origtype
,
620 enum tree_code modifycode
, location_t rhs_loc
,
621 tree rhs
, tree rhs_origtype
)
623 bool found_builtin_fn
= false;
624 tree array_expr_lhs
= NULL_TREE
, array_expr_rhs
= NULL_TREE
;
625 tree array_expr
= NULL_TREE
;
626 tree an_init
= NULL_TREE
;
627 vec
<tree
> cond_expr
= vNULL
;
628 tree body
, loop_with_init
= alloc_stmt_list();
629 tree scalar_mods
= NULL_TREE
;
630 vec
<tree
, va_gc
> *rhs_array_operand
= NULL
, *lhs_array_operand
= NULL
;
631 size_t lhs_rank
= 0, rhs_rank
= 0;
633 vec
<tree
, va_gc
> *lhs_list
= NULL
, *rhs_list
= NULL
;
634 tree new_modify_expr
, new_var
= NULL_TREE
, builtin_loop
= NULL_TREE
;
635 size_t rhs_list_size
= 0, lhs_list_size
= 0;
636 vec
<vec
<an_parts
> > lhs_an_info
= vNULL
, rhs_an_info
= vNULL
;
637 vec
<an_loop_parts
> lhs_an_loop_info
= vNULL
, rhs_an_loop_info
= vNULL
;
639 /* If either of this is true, an error message must have been send out
640 already. Not necessary to send out multiple error messages. */
641 if (lhs
== error_mark_node
|| rhs
== error_mark_node
)
642 return error_mark_node
;
644 if (!find_rank (location
, rhs
, rhs
, false, &rhs_rank
))
645 return error_mark_node
;
647 extract_array_notation_exprs (rhs
, false, &rhs_list
);
648 rhs_list_size
= vec_safe_length (rhs_list
);
649 an_init
= push_stmt_list ();
652 scalar_mods
= replace_invariant_exprs (&rhs
);
654 add_stmt (scalar_mods
);
656 for (ii
= 0; ii
< rhs_list_size
; ii
++)
658 tree rhs_node
= (*rhs_list
)[ii
];
659 if (TREE_CODE (rhs_node
) == CALL_EXPR
)
661 builtin_loop
= fix_builtin_array_notation_fn (rhs_node
, &new_var
);
662 if (builtin_loop
== error_mark_node
)
664 pop_stmt_list (an_init
);
665 return error_mark_node
;
667 else if (builtin_loop
)
669 add_stmt (builtin_loop
);
670 found_builtin_fn
= true;
673 vec
<tree
, va_gc
> *rhs_sub_list
= NULL
, *new_var_list
= NULL
;
674 vec_safe_push (rhs_sub_list
, rhs_node
);
675 vec_safe_push (new_var_list
, new_var
);
676 replace_array_notations (&rhs
, false, rhs_sub_list
,
685 if (!find_rank (location
, lhs
, lhs
, true, &lhs_rank
))
687 pop_stmt_list (an_init
);
688 return error_mark_node
;
691 if (!find_rank (location
, rhs
, rhs
, true, &rhs_rank
))
693 pop_stmt_list (an_init
);
694 return error_mark_node
;
697 if (lhs_rank
== 0 && rhs_rank
== 0)
699 if (found_builtin_fn
)
701 new_modify_expr
= build_modify_expr (location
, lhs
, lhs_origtype
,
702 modifycode
, rhs_loc
, rhs
,
704 add_stmt (new_modify_expr
);
705 pop_stmt_list (an_init
);
710 pop_stmt_list (an_init
);
716 extract_array_notation_exprs (rhs
, true, &rhs_list
);
717 extract_array_notation_exprs (lhs
, true, &lhs_list
);
718 rhs_list_size
= vec_safe_length (rhs_list
);
719 lhs_list_size
= vec_safe_length (lhs_list
);
721 if (lhs_rank
== 0 && rhs_rank
!= 0)
724 if (TREE_CODE (rhs_base
) == ARRAY_NOTATION_REF
)
726 for (ii
= 0; ii
< (size_t) rhs_rank
; ii
++)
727 rhs_base
= ARRAY_NOTATION_ARRAY (rhs
);
729 error_at (location
, "%qE cannot be scalar when %qE is not", lhs
,
731 return error_mark_node
;
735 error_at (location
, "%qE cannot be scalar when %qE is not", lhs
,
737 return error_mark_node
;
740 if (lhs_rank
!= 0 && rhs_rank
!= 0 && lhs_rank
!= rhs_rank
)
742 error_at (location
, "rank mismatch between %qE and %qE", lhs
, rhs
);
743 pop_stmt_list (an_init
);
744 return error_mark_node
;
747 /* Here we assign the array notation components to variable so that we can
748 satisfy the exec once rule. */
749 for (ii
= 0; ii
< lhs_list_size
; ii
++)
751 tree array_node
= (*lhs_list
)[ii
];
752 make_triplet_val_inv (location
, &ARRAY_NOTATION_START (array_node
));
753 make_triplet_val_inv (location
, &ARRAY_NOTATION_LENGTH (array_node
));
754 make_triplet_val_inv (location
, &ARRAY_NOTATION_STRIDE (array_node
));
756 for (ii
= 0; ii
< rhs_list_size
; ii
++)
757 if ((*rhs_list
)[ii
] && TREE_CODE ((*rhs_list
)[ii
]) == ARRAY_NOTATION_REF
)
759 tree array_node
= (*rhs_list
)[ii
];
760 make_triplet_val_inv (location
, &ARRAY_NOTATION_START (array_node
));
761 make_triplet_val_inv (location
, &ARRAY_NOTATION_LENGTH (array_node
));
762 make_triplet_val_inv (location
, &ARRAY_NOTATION_STRIDE (array_node
));
765 cond_expr
.safe_grow_cleared (MAX (lhs_rank
, rhs_rank
));
767 lhs_an_loop_info
.safe_grow_cleared (lhs_rank
);
769 rhs_an_loop_info
.safe_grow_cleared (rhs_rank
);
771 cilkplus_extract_an_triplets (lhs_list
, lhs_list_size
, lhs_rank
,
775 rhs_an_loop_info
.safe_grow_cleared (rhs_rank
);
776 cilkplus_extract_an_triplets (rhs_list
, rhs_list_size
, rhs_rank
,
779 if (length_mismatch_in_expr_p (EXPR_LOCATION (lhs
), lhs_an_info
)
781 && length_mismatch_in_expr_p (EXPR_LOCATION (rhs
), rhs_an_info
)))
783 pop_stmt_list (an_init
);
784 return error_mark_node
;
786 if (lhs_list_size
> 0 && rhs_list_size
> 0 && lhs_rank
> 0 && rhs_rank
> 0
787 && TREE_CODE (lhs_an_info
[0][0].length
) == INTEGER_CST
788 && rhs_an_info
[0][0].length
789 && TREE_CODE (rhs_an_info
[0][0].length
) == INTEGER_CST
)
791 HOST_WIDE_INT l_length
= int_cst_value (lhs_an_info
[0][0].length
);
792 HOST_WIDE_INT r_length
= int_cst_value (rhs_an_info
[0][0].length
);
793 /* Length can be negative or positive. As long as the magnitude is OK,
794 then the array notation is valid. */
795 if (absu_hwi (l_length
) != absu_hwi (r_length
))
797 error_at (location
, "length mismatch between LHS and RHS");
798 pop_stmt_list (an_init
);
799 return error_mark_node
;
802 for (ii
= 0; ii
< lhs_rank
; ii
++)
803 if (lhs_an_info
[0][ii
].is_vector
)
805 lhs_an_loop_info
[ii
].var
= create_tmp_var (integer_type_node
);
806 lhs_an_loop_info
[ii
].ind_init
= build_modify_expr
807 (location
, lhs_an_loop_info
[ii
].var
,
808 TREE_TYPE (lhs_an_loop_info
[ii
].var
), NOP_EXPR
,
809 location
, build_zero_cst (TREE_TYPE (lhs_an_loop_info
[ii
].var
)),
810 TREE_TYPE (lhs_an_loop_info
[ii
].var
));
812 for (ii
= 0; ii
< rhs_rank
; ii
++)
814 /* When we have a polynomial, we assume that the indices are of type
816 rhs_an_loop_info
[ii
].var
= create_tmp_var (integer_type_node
);
817 rhs_an_loop_info
[ii
].ind_init
= build_modify_expr
818 (location
, rhs_an_loop_info
[ii
].var
,
819 TREE_TYPE (rhs_an_loop_info
[ii
].var
), NOP_EXPR
,
820 location
, build_int_cst (TREE_TYPE (rhs_an_loop_info
[ii
].var
), 0),
821 TREE_TYPE (rhs_an_loop_info
[ii
].var
));
825 lhs_array_operand
= create_array_refs
826 (location
, lhs_an_info
, lhs_an_loop_info
, lhs_list_size
, lhs_rank
);
827 replace_array_notations (&lhs
, true, lhs_list
, lhs_array_operand
);
828 array_expr_lhs
= lhs
;
830 if (rhs_array_operand
)
831 vec_safe_truncate (rhs_array_operand
, 0);
834 rhs_array_operand
= create_array_refs
835 (location
, rhs_an_info
, rhs_an_loop_info
, rhs_list_size
, rhs_rank
);
836 replace_array_notations (&rhs
, true, rhs_list
, rhs_array_operand
);
837 vec_safe_truncate (rhs_array_operand
, 0);
838 rhs_array_operand
= fix_sec_implicit_args (location
, rhs_list
,
839 rhs_an_loop_info
, rhs_rank
,
841 if (!rhs_array_operand
)
842 return error_mark_node
;
843 replace_array_notations (&rhs
, true, rhs_list
, rhs_array_operand
);
845 else if (rhs_list_size
> 0)
847 rhs_array_operand
= fix_sec_implicit_args (location
, rhs_list
,
848 lhs_an_loop_info
, lhs_rank
,
850 if (!rhs_array_operand
)
851 return error_mark_node
;
852 replace_array_notations (&rhs
, true, rhs_list
, rhs_array_operand
);
854 array_expr_lhs
= lhs
;
855 array_expr_rhs
= rhs
;
856 array_expr
= build_modify_expr (location
, array_expr_lhs
, lhs_origtype
,
857 modifycode
, rhs_loc
, array_expr_rhs
,
859 create_cmp_incr (location
, &lhs_an_loop_info
, lhs_rank
, lhs_an_info
);
861 create_cmp_incr (location
, &rhs_an_loop_info
, rhs_rank
, rhs_an_info
);
863 for (ii
= 0; ii
< MAX (lhs_rank
, rhs_rank
); ii
++)
864 if (ii
< lhs_rank
&& ii
< rhs_rank
)
865 cond_expr
[ii
] = build2 (TRUTH_ANDIF_EXPR
, boolean_type_node
,
866 lhs_an_loop_info
[ii
].cmp
,
867 rhs_an_loop_info
[ii
].cmp
);
868 else if (ii
< lhs_rank
&& ii
>= rhs_rank
)
869 cond_expr
[ii
] = lhs_an_loop_info
[ii
].cmp
;
873 an_init
= pop_stmt_list (an_init
);
874 append_to_statement_list_force (an_init
, &loop_with_init
);
876 for (ii
= 0; ii
< MAX (lhs_rank
, rhs_rank
); ii
++)
878 tree incr_list
= alloc_stmt_list ();
879 tree new_loop
= push_stmt_list ();
881 add_stmt (lhs_an_loop_info
[ii
].ind_init
);
883 add_stmt (rhs_an_loop_info
[ii
].ind_init
);
885 append_to_statement_list_force (lhs_an_loop_info
[ii
].incr
, &incr_list
);
886 if (rhs_rank
&& rhs_an_loop_info
[ii
].incr
)
887 append_to_statement_list_force (rhs_an_loop_info
[ii
].incr
, &incr_list
);
888 c_finish_loop (location
, cond_expr
[ii
], incr_list
, body
, NULL_TREE
,
890 body
= pop_stmt_list (new_loop
);
892 append_to_statement_list_force (body
, &loop_with_init
);
894 lhs_an_info
.release ();
895 lhs_an_loop_info
.release ();
898 rhs_an_info
.release ();
899 rhs_an_loop_info
.release ();
901 cond_expr
.release ();
902 return loop_with_init
;
905 /* Helper function for fix_conditional_array_notations. Encloses the
906 conditional statement passed in STMT with a loop around it
907 and replaces the condition in STMT with a ARRAY_REF tree-node to the array.
908 The condition must have an ARRAY_NOTATION_REF tree. An expansion of array
909 notation in STMT is returned in a STATEMENT_LIST. */
912 fix_conditional_array_notations_1 (tree stmt
)
914 vec
<tree
, va_gc
> *array_list
= NULL
, *array_operand
= NULL
;
915 size_t list_size
= 0;
916 tree cond
= NULL_TREE
, builtin_loop
= NULL_TREE
, new_var
= NULL_TREE
;
917 size_t rank
= 0, ii
= 0;
919 location_t location
= EXPR_LOCATION (stmt
);
920 tree body
= NULL_TREE
, loop_with_init
= alloc_stmt_list ();
921 vec
<vec
<an_parts
> > an_info
= vNULL
;
922 vec
<an_loop_parts
> an_loop_info
= vNULL
;
924 if (TREE_CODE (stmt
) == COND_EXPR
)
925 cond
= COND_EXPR_COND (stmt
);
926 else if (TREE_CODE (stmt
) == SWITCH_EXPR
)
927 cond
= SWITCH_COND (stmt
);
928 else if (truth_value_p (TREE_CODE (stmt
)))
929 cond
= TREE_OPERAND (stmt
, 0);
931 /* Otherwise dont even touch the statement. */
934 if (!find_rank (location
, cond
, cond
, false, &rank
))
935 return error_mark_node
;
937 extract_array_notation_exprs (stmt
, false, &array_list
);
938 loop_init
= push_stmt_list ();
939 for (ii
= 0; ii
< vec_safe_length (array_list
); ii
++)
941 tree array_node
= (*array_list
)[ii
];
942 if (TREE_CODE (array_node
) == CALL_EXPR
)
944 builtin_loop
= fix_builtin_array_notation_fn (array_node
, &new_var
);
945 if (builtin_loop
== error_mark_node
)
947 add_stmt (error_mark_node
);
948 pop_stmt_list (loop_init
);
951 else if (builtin_loop
)
953 vec
<tree
, va_gc
>* sub_list
= NULL
, *new_var_list
= NULL
;
954 vec_safe_push (sub_list
, array_node
);
955 vec_safe_push (new_var_list
, new_var
);
956 add_stmt (builtin_loop
);
957 replace_array_notations (&stmt
, false, sub_list
, new_var_list
);
961 if (!find_rank (location
, stmt
, stmt
, true, &rank
))
963 pop_stmt_list (loop_init
);
964 return error_mark_node
;
969 pop_stmt_list (loop_init
);
972 extract_array_notation_exprs (stmt
, true, &array_list
);
974 if (vec_safe_length (array_list
) == 0)
977 list_size
= vec_safe_length (array_list
);
978 an_loop_info
.safe_grow_cleared (rank
);
980 for (ii
= 0; ii
< list_size
; ii
++)
981 if ((*array_list
)[ii
]
982 && TREE_CODE ((*array_list
)[ii
]) == ARRAY_NOTATION_REF
)
984 tree array_node
= (*array_list
)[ii
];
985 make_triplet_val_inv (location
, &ARRAY_NOTATION_START (array_node
));
986 make_triplet_val_inv (location
, &ARRAY_NOTATION_LENGTH (array_node
));
987 make_triplet_val_inv (location
, &ARRAY_NOTATION_STRIDE (array_node
));
989 cilkplus_extract_an_triplets (array_list
, list_size
, rank
, &an_info
);
990 for (ii
= 0; ii
< rank
; ii
++)
992 an_loop_info
[ii
].var
= create_tmp_var (integer_type_node
);
993 an_loop_info
[ii
].ind_init
=
994 build_modify_expr (location
, an_loop_info
[ii
].var
,
995 TREE_TYPE (an_loop_info
[ii
].var
), NOP_EXPR
,
997 build_int_cst (TREE_TYPE (an_loop_info
[ii
].var
), 0),
998 TREE_TYPE (an_loop_info
[ii
].var
));
1000 array_operand
= create_array_refs (location
, an_info
, an_loop_info
,
1002 replace_array_notations (&stmt
, true, array_list
, array_operand
);
1003 create_cmp_incr (location
, &an_loop_info
, rank
, an_info
);
1005 loop_init
= pop_stmt_list (loop_init
);
1007 append_to_statement_list_force (loop_init
, &loop_with_init
);
1009 for (ii
= 0; ii
< rank
; ii
++)
1011 tree new_loop
= push_stmt_list ();
1012 add_stmt (an_loop_info
[ii
].ind_init
);
1013 c_finish_loop (location
, an_loop_info
[ii
].cmp
, an_loop_info
[ii
].incr
,
1014 body
, NULL_TREE
, NULL_TREE
, true);
1015 body
= pop_stmt_list (new_loop
);
1017 append_to_statement_list_force (body
, &loop_with_init
);
1019 an_loop_info
.release ();
1022 return loop_with_init
;
1025 /* Top-level function to replace ARRAY_NOTATION_REF in a conditional statement
1026 in STMT. An expansion of array notation in STMT is returned as a
1030 fix_conditional_array_notations (tree stmt
)
1032 if (TREE_CODE (stmt
) == STATEMENT_LIST
)
1034 tree_stmt_iterator tsi
;
1035 for (tsi
= tsi_start (stmt
); !tsi_end_p (tsi
); tsi_next (&tsi
))
1037 tree single_stmt
= *tsi_stmt_ptr (tsi
);
1038 *tsi_stmt_ptr (tsi
) =
1039 fix_conditional_array_notations_1 (single_stmt
);
1044 return fix_conditional_array_notations_1 (stmt
);
1047 /* Create a struct c_expr that contains a loop with ARRAY_REF expr at location
1048 LOCATION with the tree_code CODE and the array notation expr is
1049 passed in ARG. Returns the fixed c_expr in ARG itself. */
1052 fix_array_notation_expr (location_t location
, enum tree_code code
,
1056 vec
<tree
, va_gc
> *array_list
= NULL
, *array_operand
= NULL
;
1057 size_t list_size
= 0, rank
= 0, ii
= 0;
1059 tree body
, loop_with_init
= alloc_stmt_list ();
1060 vec
<vec
<an_parts
> > an_info
= vNULL
;
1061 vec
<an_loop_parts
> an_loop_info
= vNULL
;
1063 if (!find_rank (location
, arg
.value
, arg
.value
, false, &rank
))
1065 /* If this function returns a NULL, we convert the tree value in the
1066 structure to error_mark_node and the parser should take care of the
1068 arg
.value
= error_mark_node
;
1075 extract_array_notation_exprs (arg
.value
, true, &array_list
);
1077 if (vec_safe_length (array_list
) == 0)
1080 list_size
= vec_safe_length (array_list
);
1082 an_loop_info
.safe_grow_cleared (rank
);
1083 cilkplus_extract_an_triplets (array_list
, list_size
, rank
, &an_info
);
1085 loop_init
= push_stmt_list ();
1086 for (ii
= 0; ii
< rank
; ii
++)
1088 an_loop_info
[ii
].var
= create_tmp_var (integer_type_node
);
1089 an_loop_info
[ii
].ind_init
=
1090 build_modify_expr (location
, an_loop_info
[ii
].var
,
1091 TREE_TYPE (an_loop_info
[ii
].var
), NOP_EXPR
,
1093 build_int_cst (TREE_TYPE (an_loop_info
[ii
].var
), 0),
1094 TREE_TYPE (an_loop_info
[ii
].var
));;
1097 array_operand
= create_array_refs (location
, an_info
, an_loop_info
,
1099 replace_array_notations (&arg
.value
, true, array_list
, array_operand
);
1100 create_cmp_incr (location
, &an_loop_info
, rank
, an_info
);
1102 arg
= default_function_array_read_conversion (location
, arg
);
1103 if (code
== POSTINCREMENT_EXPR
|| code
== POSTDECREMENT_EXPR
)
1104 arg
.value
= build_unary_op (location
, code
, arg
.value
, 0);
1105 else if (code
== PREINCREMENT_EXPR
|| code
== PREDECREMENT_EXPR
)
1106 arg
= parser_build_unary_op (location
, code
, arg
);
1108 loop_init
= pop_stmt_list (loop_init
);
1109 append_to_statement_list_force (loop_init
, &loop_with_init
);
1112 for (ii
= 0; ii
< rank
; ii
++)
1114 tree new_loop
= push_stmt_list ();
1115 add_stmt (an_loop_info
[ii
].ind_init
);
1116 c_finish_loop (location
, an_loop_info
[ii
].cmp
,
1117 an_loop_info
[ii
].incr
, body
, NULL_TREE
,
1119 body
= pop_stmt_list (new_loop
);
1121 append_to_statement_list_force (body
, &loop_with_init
);
1122 arg
.value
= loop_with_init
;
1124 an_loop_info
.release ();
1128 /* Replaces array notations in a void function call arguments in ARG and returns
1129 a STATEMENT_LIST. */
1132 fix_array_notation_call_expr (tree arg
)
1134 vec
<tree
, va_gc
> *array_list
= NULL
, *array_operand
= NULL
;
1135 tree new_var
= NULL_TREE
;
1136 size_t list_size
= 0, rank
= 0, ii
= 0;
1138 tree body
, loop_with_init
= alloc_stmt_list ();
1139 location_t location
= UNKNOWN_LOCATION
;
1140 vec
<vec
<an_parts
> > an_info
= vNULL
;
1141 vec
<an_loop_parts
> an_loop_info
= vNULL
;
1143 if (TREE_CODE (arg
) == CALL_EXPR
1144 && is_cilkplus_reduce_builtin (CALL_EXPR_FN (arg
)))
1146 loop_init
= fix_builtin_array_notation_fn (arg
, &new_var
);
1147 /* We are ignoring the new var because either the user does not want to
1148 capture it OR he is using sec_reduce_mutating function. */
1151 if (!find_rank (location
, arg
, arg
, false, &rank
))
1152 return error_mark_node
;
1157 extract_array_notation_exprs (arg
, true, &array_list
);
1158 if (vec_safe_length (array_list
) == 0)
1161 list_size
= vec_safe_length (array_list
);
1162 location
= EXPR_LOCATION (arg
);
1163 an_loop_info
.safe_grow_cleared (rank
);
1165 loop_init
= push_stmt_list ();
1166 for (ii
= 0; ii
< list_size
; ii
++)
1167 if ((*array_list
)[ii
]
1168 && TREE_CODE ((*array_list
)[ii
]) == ARRAY_NOTATION_REF
)
1170 tree array_node
= (*array_list
)[ii
];
1171 make_triplet_val_inv (location
, &ARRAY_NOTATION_START (array_node
));
1172 make_triplet_val_inv (location
, &ARRAY_NOTATION_LENGTH (array_node
));
1173 make_triplet_val_inv (location
, &ARRAY_NOTATION_STRIDE (array_node
));
1175 cilkplus_extract_an_triplets (array_list
, list_size
, rank
, &an_info
);
1176 if (length_mismatch_in_expr_p (location
, an_info
))
1178 pop_stmt_list (loop_init
);
1179 return error_mark_node
;
1181 for (ii
= 0; ii
< rank
; ii
++)
1183 an_loop_info
[ii
].var
= create_tmp_var (integer_type_node
);
1184 an_loop_info
[ii
].ind_init
=
1185 build_modify_expr (location
, an_loop_info
[ii
].var
,
1186 TREE_TYPE (an_loop_info
[ii
].var
), NOP_EXPR
, location
,
1187 build_int_cst (TREE_TYPE (an_loop_info
[ii
].var
), 0),
1188 TREE_TYPE (an_loop_info
[ii
].var
));
1191 array_operand
= create_array_refs (location
, an_info
, an_loop_info
,
1193 replace_array_notations (&arg
, true, array_list
, array_operand
);
1194 create_cmp_incr (location
, &an_loop_info
, rank
, an_info
);
1195 loop_init
= pop_stmt_list (loop_init
);
1196 append_to_statement_list_force (loop_init
, &loop_with_init
);
1198 for (ii
= 0; ii
< rank
; ii
++)
1200 tree new_loop
= push_stmt_list ();
1201 add_stmt (an_loop_info
[ii
].ind_init
);
1202 c_finish_loop (location
, an_loop_info
[ii
].cmp
, an_loop_info
[ii
].incr
,
1203 body
, NULL_TREE
, NULL_TREE
, true);
1204 body
= pop_stmt_list (new_loop
);
1206 append_to_statement_list_force (body
, &loop_with_init
);
1207 an_loop_info
.release ();
1209 return loop_with_init
;
1212 /* Expands the built-in functions in a return. EXPR is a RETURN_EXPR with
1213 a built-in reduction function. This function returns the expansion code for
1214 the built-in function. */
1217 fix_return_expr (tree expr
)
1219 tree new_mod_list
, new_var
, new_mod
, retval_expr
, retval_type
;
1220 location_t loc
= EXPR_LOCATION (expr
);
1222 new_mod_list
= alloc_stmt_list ();
1223 retval_expr
= TREE_OPERAND (expr
, 0);
1224 retval_type
= TREE_TYPE (TREE_OPERAND (retval_expr
, 1));
1225 new_var
= build_decl (loc
, VAR_DECL
, NULL_TREE
, TREE_TYPE (retval_expr
));
1226 new_mod
= build_array_notation_expr (loc
, new_var
, TREE_TYPE (new_var
),
1228 TREE_OPERAND (retval_expr
, 1),
1230 TREE_OPERAND (retval_expr
, 1) = new_var
;
1231 TREE_OPERAND (expr
, 0) = retval_expr
;
1232 append_to_statement_list_force (new_mod
, &new_mod_list
);
1233 append_to_statement_list_force (expr
, &new_mod_list
);
1234 return new_mod_list
;
1237 /* Callback for walk_tree. Expands all array notations in *TP. *WALK_SUBTREES
1238 is set to 1 unless *TP contains no array notation expressions. */
1241 expand_array_notations (tree
*tp
, int *walk_subtrees
, void *)
1243 if (!contains_array_notation_expr (*tp
))
1250 switch (TREE_CODE (*tp
))
1252 case TRUTH_ORIF_EXPR
:
1253 case TRUTH_ANDIF_EXPR
:
1255 case TRUTH_AND_EXPR
:
1256 case TRUTH_XOR_EXPR
:
1257 case TRUTH_NOT_EXPR
:
1259 *tp
= fix_conditional_array_notations (*tp
);
1263 location_t loc
= EXPR_HAS_LOCATION (*tp
) ? EXPR_LOCATION (*tp
) :
1265 tree lhs
= TREE_OPERAND (*tp
, 0);
1266 tree rhs
= TREE_OPERAND (*tp
, 1);
1267 location_t rhs_loc
= EXPR_HAS_LOCATION (rhs
) ? EXPR_LOCATION (rhs
) :
1269 *tp
= build_array_notation_expr (loc
, lhs
, TREE_TYPE (lhs
), NOP_EXPR
,
1270 rhs_loc
, rhs
, TREE_TYPE (rhs
));
1275 tree x
= DECL_EXPR_DECL (*tp
);
1276 if (DECL_INITIAL (x
))
1278 location_t loc
= DECL_SOURCE_LOCATION (x
);
1280 tree rhs
= DECL_INITIAL (x
);
1281 DECL_INITIAL (x
) = NULL
;
1282 tree new_modify_expr
= build_modify_expr (loc
, lhs
,
1287 expand_array_notations (&new_modify_expr
, walk_subtrees
, NULL
);
1288 *tp
= new_modify_expr
;
1293 *tp
= fix_array_notation_call_expr (*tp
);
1296 *tp
= fix_return_expr (*tp
);
1299 if (TREE_CODE (TREE_OPERAND (*tp
, 0)) == SAVE_EXPR
)
1301 /* In here we are calling expand_array_notations because
1302 we need to be able to catch the return value and check if
1303 it is an error_mark_node. */
1304 expand_array_notations (&TREE_OPERAND (*tp
, 1), walk_subtrees
, NULL
);
1306 /* SAVE_EXPR cannot have an error_mark_node inside it. This check
1307 will make sure that if there is an error in expanding of
1308 array notations (e.g. rank mismatch) then replace the entire
1309 SAVE_EXPR with an error_mark_node. */
1310 if (TREE_OPERAND (*tp
, 1) == error_mark_node
)
1311 *tp
= error_mark_node
;
1314 case ARRAY_NOTATION_REF
:
1315 /* If we are here, then we are dealing with cases like this:
1319 Replace those with just void zero node. */
1327 /* Walks through tree node T and expands all array notations in its subtrees.
1328 The return value is the same type as T but with all array notations
1329 replaced with appropriate ARRAY_REFS with a loop around it. */
1332 expand_array_notation_exprs (tree t
)
1334 walk_tree (&t
, expand_array_notations
, NULL
, NULL
);
1338 /* This handles expression of the form "a[i:j:k]" or "a[:]" or "a[i:j]," which
1339 denotes an array notation expression. If a is a variable or a member, then
1340 we generate a ARRAY_NOTATION_REF front-end tree and return it.
1341 This tree is broken down to ARRAY_REF toward the end of parsing.
1342 ARRAY_NOTATION_REF tree holds the START_INDEX, LENGTH, STRIDE and the TYPE
1343 of ARRAY_REF. Restrictions on START_INDEX, LENGTH and STRIDE is same as that
1344 of the index field passed into ARRAY_REF. The only additional restriction
1345 is that, unlike index in ARRAY_REF, stride, length and start_index cannot
1346 contain ARRAY_NOTATIONS. */
1349 build_array_notation_ref (location_t loc
, tree array
, tree start_index
,
1350 tree length
, tree stride
, tree type
)
1352 tree array_ntn_tree
= NULL_TREE
;
1353 size_t stride_rank
= 0, length_rank
= 0, start_rank
= 0;
1355 if (!INTEGRAL_TYPE_P (TREE_TYPE (start_index
)))
1358 "start-index of array notation triplet is not an integer");
1359 return error_mark_node
;
1361 if (!INTEGRAL_TYPE_P (TREE_TYPE (length
)))
1363 error_at (loc
, "length of array notation triplet is not an integer");
1364 return error_mark_node
;
1367 /* The stride is an optional field. */
1368 if (stride
&& !INTEGRAL_TYPE_P (TREE_TYPE (stride
)))
1370 error_at (loc
, "stride of array notation triplet is not an integer");
1371 return error_mark_node
;
1375 if (TREE_CONSTANT (start_index
) && TREE_CONSTANT (length
)
1376 && tree_int_cst_lt (length
, start_index
))
1377 stride
= build_int_cst (TREE_TYPE (start_index
), -1);
1379 stride
= build_int_cst (TREE_TYPE (start_index
), 1);
1382 if (!find_rank (loc
, start_index
, start_index
, false, &start_rank
))
1383 return error_mark_node
;
1384 if (!find_rank (loc
, length
, length
, false, &length_rank
))
1385 return error_mark_node
;
1386 if (!find_rank (loc
, stride
, stride
, false, &stride_rank
))
1387 return error_mark_node
;
1389 if (start_rank
!= 0)
1391 error_at (loc
, "rank of an array notation triplet's start-index is not "
1393 return error_mark_node
;
1395 if (length_rank
!= 0)
1397 error_at (loc
, "rank of an array notation triplet's length is not zero");
1398 return error_mark_node
;
1400 if (stride_rank
!= 0)
1402 error_at (loc
, "rank of array notation triplet's stride is not zero");
1403 return error_mark_node
;
1405 array_ntn_tree
= build4 (ARRAY_NOTATION_REF
, NULL_TREE
, NULL_TREE
, NULL_TREE
,
1406 NULL_TREE
, NULL_TREE
);
1407 ARRAY_NOTATION_ARRAY (array_ntn_tree
) = array
;
1408 ARRAY_NOTATION_START (array_ntn_tree
) = start_index
;
1409 ARRAY_NOTATION_LENGTH (array_ntn_tree
) = length
;
1410 ARRAY_NOTATION_STRIDE (array_ntn_tree
) = stride
;
1411 TREE_TYPE (array_ntn_tree
) = type
;
1413 return array_ntn_tree
;