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-2014 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 "gimple-expr.h"
74 #include "tree-iterator.h"
76 #include "c-family/c-common.h"
78 /* If *VALUE is not of type INTEGER_CST, PARM_DECL or VAR_DECL, then map it
79 to a variable and then set *VALUE to the new variable. */
82 make_triplet_val_inv (location_t loc
, tree
*value
)
85 if (TREE_CODE (*value
) != INTEGER_CST
86 && TREE_CODE (*value
) != PARM_DECL
87 && TREE_CODE (*value
) != VAR_DECL
)
89 var
= build_decl (loc
, VAR_DECL
, NULL_TREE
, integer_type_node
);
90 new_exp
= build_modify_expr (loc
, var
, TREE_TYPE (var
), NOP_EXPR
, loc
,
91 *value
, TREE_TYPE (*value
));
97 /* Populates the INCR and CMP vectors with the increment (of type POSTINCREMENT
98 or POSTDECREMENT) and comparison (of TYPE GT_EXPR or LT_EXPR) expressions,
99 using data from LENGTH, COUNT_DOWN, and VAR. INCR and CMP vectors are of
103 create_cmp_incr (location_t loc
, vec
<an_loop_parts
> *node
, size_t rank
,
104 vec
<vec
<an_parts
> > an_info
)
106 for (size_t ii
= 0; ii
< rank
; ii
++)
108 tree var
= (*node
)[ii
].var
;
109 tree length
= an_info
[0][ii
].length
;
110 (*node
)[ii
].incr
= build_unary_op (loc
, POSTINCREMENT_EXPR
, var
, 0);
111 (*node
)[ii
].cmp
= build2 (LT_EXPR
, boolean_type_node
, var
, length
);
115 /* Returns a vector of size RANK that contains an array ref that is derived from
116 array notation triplet parameters stored in VALUE, START, STRIDE. IS_VECTOR
117 is used to check if the data stored at its corresponding location is an
118 array notation. VAR is the induction variable passed in by the caller.
120 For example: For an array notation A[5:10:2], the vector start will be
121 of size 1 holding '5', stride of same size as start but holding the value of
122 as 2, is_vector as true and count_down as false. Let's assume VAR is 'x'
123 This function returns a vector of size 1 with the following data:
127 static vec
<tree
, va_gc
> *
128 create_array_refs (location_t loc
, vec
<vec
<an_parts
> > an_info
,
129 vec
<an_loop_parts
> an_loop_info
, size_t size
, size_t rank
)
131 tree ind_mult
, ind_incr
;
132 vec
<tree
, va_gc
> *array_operand
= NULL
;
133 for (size_t ii
= 0; ii
< size
; ii
++)
134 if (an_info
[ii
][0].is_vector
)
136 tree array_opr
= an_info
[ii
][rank
- 1].value
;
137 for (int s_jj
= rank
- 1; s_jj
>= 0; s_jj
--)
139 tree var
= an_loop_info
[s_jj
].var
;
140 tree stride
= an_info
[ii
][s_jj
].stride
;
141 tree start
= an_info
[ii
][s_jj
].start
;
142 ind_mult
= build2 (MULT_EXPR
, TREE_TYPE (var
), var
, stride
);
143 ind_incr
= build2 (PLUS_EXPR
, TREE_TYPE (var
), start
, ind_mult
);
144 array_opr
= build_array_ref (loc
, array_opr
, ind_incr
);
146 vec_safe_push (array_operand
, array_opr
);
149 /* This is just a dummy node to make sure both the list sizes for both
150 array list and array operand list are the same. */
151 vec_safe_push (array_operand
, integer_one_node
);
152 return array_operand
;
155 /* Replaces all the scalar expressions in *NODE. Returns a STATEMENT_LIST that
156 holds the NODE along with variables that holds the results of the invariant
160 replace_invariant_exprs (tree
*node
)
163 tree node_list
= NULL_TREE
;
164 tree t
= NULL_TREE
, new_var
= NULL_TREE
, new_node
;
165 struct inv_list data
;
167 data
.list_values
= NULL
;
168 data
.replacement
= NULL
;
169 data
.additional_tcodes
= NULL
;
170 walk_tree (node
, find_inv_trees
, (void *)&data
, NULL
);
172 if (vec_safe_length (data
.list_values
))
174 node_list
= push_stmt_list ();
175 for (ix
= 0; vec_safe_iterate (data
.list_values
, ix
, &t
); ix
++)
177 new_var
= build_decl (EXPR_LOCATION (t
), VAR_DECL
, NULL_TREE
,
179 gcc_assert (new_var
!= NULL_TREE
&& new_var
!= error_mark_node
);
180 new_node
= build2 (MODIFY_EXPR
, TREE_TYPE (t
), new_var
, t
);
182 vec_safe_push (data
.replacement
, new_var
);
184 walk_tree (node
, replace_inv_trees
, (void *)&data
, NULL
);
185 node_list
= pop_stmt_list (node_list
);
190 /* Given a CALL_EXPR to an array notation built-in function in
191 AN_BUILTIN_FN, replace the call with the appropriate loop and
192 computation. Return the computation in *NEW_VAR.
194 The return value in *NEW_VAR will always be a scalar. If the
195 built-in is __sec_reduce_mutating, *NEW_VAR is set to NULL_TREE. */
198 fix_builtin_array_notation_fn (tree an_builtin_fn
, tree
*new_var
)
200 tree new_var_type
= NULL_TREE
, func_parm
, new_expr
, new_yes_expr
, new_no_expr
;
201 tree array_ind_value
= NULL_TREE
, new_no_ind
, new_yes_ind
, new_no_list
;
202 tree new_yes_list
, new_cond_expr
, new_var_init
= NULL_TREE
;
203 tree new_exp_init
= NULL_TREE
;
204 vec
<tree
, va_gc
> *array_list
= NULL
, *array_operand
= NULL
;
205 size_t list_size
= 0, rank
= 0, ii
= 0;
206 tree loop_init
, array_op0
;
207 tree identity_value
= NULL_TREE
, call_fn
= NULL_TREE
, new_call_expr
, body
;
208 location_t location
= UNKNOWN_LOCATION
;
209 tree loop_with_init
= alloc_stmt_list ();
210 vec
<vec
<an_parts
> > an_info
= vNULL
;
211 vec
<an_loop_parts
> an_loop_info
= vNULL
;
212 enum built_in_function an_type
=
213 is_cilkplus_reduce_builtin (CALL_EXPR_FN (an_builtin_fn
));
214 if (an_type
== BUILT_IN_NONE
)
217 if (an_type
== BUILT_IN_CILKPLUS_SEC_REDUCE
218 || an_type
== BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING
)
220 call_fn
= CALL_EXPR_ARG (an_builtin_fn
, 2);
221 if (TREE_CODE (call_fn
) == ADDR_EXPR
)
222 call_fn
= TREE_OPERAND (call_fn
, 0);
223 identity_value
= CALL_EXPR_ARG (an_builtin_fn
, 0);
224 func_parm
= CALL_EXPR_ARG (an_builtin_fn
, 1);
227 func_parm
= CALL_EXPR_ARG (an_builtin_fn
, 0);
229 /* Fully fold any EXCESSIVE_PRECISION EXPR that can occur in the function
231 func_parm
= c_fully_fold (func_parm
, false, NULL
);
232 if (func_parm
== error_mark_node
)
233 return error_mark_node
;
235 location
= EXPR_LOCATION (an_builtin_fn
);
237 if (!find_rank (location
, an_builtin_fn
, an_builtin_fn
, true, &rank
))
238 return error_mark_node
;
241 return an_builtin_fn
;
243 && (an_type
== BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
244 || an_type
== BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND
))
246 error_at (location
, "__sec_reduce_min_ind or __sec_reduce_max_ind cannot"
247 " have arrays with dimension greater than 1");
248 return error_mark_node
;
251 extract_array_notation_exprs (func_parm
, true, &array_list
);
252 list_size
= vec_safe_length (array_list
);
255 case BUILT_IN_CILKPLUS_SEC_REDUCE_ADD
:
256 case BUILT_IN_CILKPLUS_SEC_REDUCE_MUL
:
257 case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX
:
258 case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN
:
259 new_var_type
= TREE_TYPE ((*array_list
)[0]);
261 case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_ZERO
:
262 case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_NONZERO
:
263 case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO
:
264 case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_NONZERO
:
265 new_var_type
= integer_type_node
;
267 case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
:
268 case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND
:
269 new_var_type
= integer_type_node
;
271 case BUILT_IN_CILKPLUS_SEC_REDUCE
:
272 if (call_fn
&& identity_value
)
273 new_var_type
= TREE_TYPE ((*array_list
)[0]);
275 case BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING
:
276 new_var_type
= NULL_TREE
;
282 an_loop_info
.safe_grow_cleared (rank
);
283 cilkplus_extract_an_triplets (array_list
, list_size
, rank
, &an_info
);
284 loop_init
= alloc_stmt_list ();
286 for (ii
= 0; ii
< rank
; ii
++)
288 an_loop_info
[ii
].var
= create_tmp_var (integer_type_node
, NULL
);
289 an_loop_info
[ii
].ind_init
=
290 build_modify_expr (location
, an_loop_info
[ii
].var
,
291 TREE_TYPE (an_loop_info
[ii
].var
), NOP_EXPR
,
293 build_int_cst (TREE_TYPE (an_loop_info
[ii
].var
), 0),
294 TREE_TYPE (an_loop_info
[ii
].var
));
296 array_operand
= create_array_refs (location
, an_info
, an_loop_info
,
298 replace_array_notations (&func_parm
, true, array_list
, array_operand
);
300 create_cmp_incr (location
, &an_loop_info
, rank
, an_info
);
301 if (an_type
!= BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING
)
303 *new_var
= build_decl (location
, VAR_DECL
, NULL_TREE
, new_var_type
);
304 gcc_assert (*new_var
&& *new_var
!= error_mark_node
);
307 *new_var
= NULL_TREE
;
309 if (an_type
== BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
310 || an_type
== BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND
)
311 array_ind_value
= build_decl (location
, VAR_DECL
, NULL_TREE
,
312 TREE_TYPE (func_parm
));
313 array_op0
= (*array_operand
)[0];
314 if (TREE_CODE (array_op0
) == INDIRECT_REF
)
315 array_op0
= TREE_OPERAND (array_op0
, 0);
318 case BUILT_IN_CILKPLUS_SEC_REDUCE_ADD
:
319 new_var_init
= build_modify_expr
320 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
321 location
, build_zero_cst (new_var_type
), new_var_type
);
322 new_expr
= build_modify_expr
323 (location
, *new_var
, TREE_TYPE (*new_var
), PLUS_EXPR
,
324 location
, func_parm
, TREE_TYPE (func_parm
));
326 case BUILT_IN_CILKPLUS_SEC_REDUCE_MUL
:
327 new_var_init
= build_modify_expr
328 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
329 location
, build_one_cst (new_var_type
), new_var_type
);
330 new_expr
= build_modify_expr
331 (location
, *new_var
, TREE_TYPE (*new_var
), MULT_EXPR
,
332 location
, func_parm
, TREE_TYPE (func_parm
));
334 case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_ZERO
:
335 new_var_init
= build_modify_expr
336 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
337 location
, build_one_cst (new_var_type
), new_var_type
);
338 /* Initially you assume everything is zero, now if we find a case where
339 it is NOT true, then we set the result to false. Otherwise
340 we just keep the previous value. */
341 new_yes_expr
= build_modify_expr
342 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
343 location
, build_zero_cst (TREE_TYPE (*new_var
)),
344 TREE_TYPE (*new_var
));
345 new_no_expr
= build_modify_expr
346 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
347 location
, *new_var
, TREE_TYPE (*new_var
));
348 new_cond_expr
= build2 (NE_EXPR
, TREE_TYPE (func_parm
), func_parm
,
349 build_zero_cst (TREE_TYPE (func_parm
)));
350 new_expr
= build_conditional_expr
351 (location
, new_cond_expr
, false, new_yes_expr
,
352 TREE_TYPE (new_yes_expr
), new_no_expr
, TREE_TYPE (new_no_expr
));
354 case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_NONZERO
:
355 new_var_init
= build_modify_expr
356 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
357 location
, build_one_cst (new_var_type
), new_var_type
);
358 /* Initially you assume everything is non-zero, now if we find a case
359 where it is NOT true, then we set the result to false. Otherwise
360 we just keep the previous value. */
361 new_yes_expr
= build_modify_expr
362 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
363 location
, build_zero_cst (TREE_TYPE (*new_var
)),
364 TREE_TYPE (*new_var
));
365 new_no_expr
= build_modify_expr
366 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
367 location
, *new_var
, TREE_TYPE (*new_var
));
368 new_cond_expr
= build2 (EQ_EXPR
, TREE_TYPE (func_parm
), func_parm
,
369 build_zero_cst (TREE_TYPE (func_parm
)));
370 new_expr
= build_conditional_expr
371 (location
, new_cond_expr
, false, new_yes_expr
,
372 TREE_TYPE (new_yes_expr
), new_no_expr
, TREE_TYPE (new_no_expr
));
374 case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO
:
375 new_var_init
= build_modify_expr
376 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
377 location
, build_zero_cst (new_var_type
), new_var_type
);
378 /* Initially we assume there are NO zeros in the list. When we find
379 a non-zero, we keep the previous value. If we find a zero, we
380 set the value to true. */
381 new_yes_expr
= build_modify_expr
382 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
383 location
, build_one_cst (new_var_type
), new_var_type
);
384 new_no_expr
= build_modify_expr
385 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
386 location
, *new_var
, TREE_TYPE (*new_var
));
387 new_cond_expr
= build2 (EQ_EXPR
, TREE_TYPE (func_parm
), func_parm
,
388 build_zero_cst (TREE_TYPE (func_parm
)));
389 new_expr
= build_conditional_expr
390 (location
, new_cond_expr
, false, new_yes_expr
,
391 TREE_TYPE (new_yes_expr
), new_no_expr
, TREE_TYPE (new_no_expr
));
393 case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_NONZERO
:
394 new_var_init
= build_modify_expr
395 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
396 location
, build_zero_cst (new_var_type
), new_var_type
);
397 /* Initially we assume there are NO non-zeros in the list. When we find
398 a zero, we keep the previous value. If we find a non-zero, we set
399 the value to true. */
400 new_yes_expr
= build_modify_expr
401 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
402 location
, build_one_cst (new_var_type
), new_var_type
);
403 new_no_expr
= build_modify_expr
404 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
405 location
, *new_var
, TREE_TYPE (*new_var
));
406 new_cond_expr
= build2 (NE_EXPR
, TREE_TYPE (func_parm
), func_parm
,
407 build_zero_cst (TREE_TYPE (func_parm
)));
408 new_expr
= build_conditional_expr
409 (location
, new_cond_expr
, false, new_yes_expr
,
410 TREE_TYPE (new_yes_expr
), new_no_expr
, TREE_TYPE (new_no_expr
));
412 case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX
:
413 if (TYPE_MIN_VALUE (new_var_type
))
414 new_var_init
= build_modify_expr
415 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
416 location
, TYPE_MIN_VALUE (new_var_type
), new_var_type
);
418 new_var_init
= build_modify_expr
419 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
420 location
, func_parm
, new_var_type
);
421 new_no_expr
= build_modify_expr
422 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
423 location
, *new_var
, TREE_TYPE (*new_var
));
424 new_yes_expr
= build_modify_expr
425 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
426 location
, func_parm
, TREE_TYPE (*new_var
));
427 new_expr
= build_conditional_expr
429 build2 (LT_EXPR
, TREE_TYPE (*new_var
), *new_var
, func_parm
), false,
430 new_yes_expr
, TREE_TYPE (*new_var
), new_no_expr
, TREE_TYPE (*new_var
));
432 case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN
:
433 if (TYPE_MAX_VALUE (new_var_type
))
434 new_var_init
= build_modify_expr
435 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
436 location
, TYPE_MAX_VALUE (new_var_type
), new_var_type
);
438 new_var_init
= build_modify_expr
439 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
440 location
, func_parm
, new_var_type
);
441 new_no_expr
= build_modify_expr
442 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
443 location
, *new_var
, TREE_TYPE (*new_var
));
444 new_yes_expr
= build_modify_expr
445 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
446 location
, func_parm
, TREE_TYPE (*new_var
));
447 new_expr
= build_conditional_expr
449 build2 (GT_EXPR
, TREE_TYPE (*new_var
), *new_var
, func_parm
), false,
450 new_yes_expr
, TREE_TYPE (*new_var
), new_no_expr
, TREE_TYPE (*new_var
));
452 case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
:
453 new_var_init
= build_modify_expr
454 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
455 location
, build_zero_cst (new_var_type
), new_var_type
);
456 new_exp_init
= build_modify_expr
457 (location
, array_ind_value
, TREE_TYPE (array_ind_value
),
458 NOP_EXPR
, location
, func_parm
, TREE_TYPE (func_parm
));
459 new_no_ind
= build_modify_expr
460 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
461 location
, *new_var
, TREE_TYPE (*new_var
));
462 new_no_expr
= build_modify_expr
463 (location
, array_ind_value
, TREE_TYPE (array_ind_value
),
465 location
, array_ind_value
, TREE_TYPE (array_ind_value
));
468 new_yes_ind
= build_modify_expr
469 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
470 location
, an_loop_info
[0].var
, TREE_TYPE (an_loop_info
[0].var
));
471 new_yes_expr
= build_modify_expr
472 (location
, array_ind_value
, TREE_TYPE (array_ind_value
),
474 location
, func_parm
, TREE_TYPE ((*array_operand
)[0]));
478 new_yes_ind
= build_modify_expr
479 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
480 location
, TREE_OPERAND (array_op0
, 1),
481 TREE_TYPE (TREE_OPERAND (array_op0
, 1)));
482 new_yes_expr
= build_modify_expr
483 (location
, array_ind_value
, TREE_TYPE (array_ind_value
),
485 location
, func_parm
, TREE_OPERAND (array_op0
, 1));
487 new_yes_list
= alloc_stmt_list ();
488 append_to_statement_list (new_yes_ind
, &new_yes_list
);
489 append_to_statement_list (new_yes_expr
, &new_yes_list
);
491 new_no_list
= alloc_stmt_list ();
492 append_to_statement_list (new_no_ind
, &new_no_list
);
493 append_to_statement_list (new_no_expr
, &new_no_list
);
495 new_expr
= build_conditional_expr
497 build2 (LE_EXPR
, TREE_TYPE (array_ind_value
), array_ind_value
,
500 new_yes_list
, TREE_TYPE (*new_var
), new_no_list
, TREE_TYPE (*new_var
));
502 case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND
:
503 new_var_init
= build_modify_expr
504 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
505 location
, build_zero_cst (new_var_type
), new_var_type
);
506 new_exp_init
= build_modify_expr
507 (location
, array_ind_value
, TREE_TYPE (array_ind_value
),
508 NOP_EXPR
, location
, func_parm
, TREE_TYPE (func_parm
));
509 new_no_ind
= build_modify_expr
510 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
511 location
, *new_var
, TREE_TYPE (*new_var
));
512 new_no_expr
= build_modify_expr
513 (location
, array_ind_value
, TREE_TYPE (array_ind_value
),
515 location
, array_ind_value
, TREE_TYPE (array_ind_value
));
518 new_yes_ind
= build_modify_expr
519 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
520 location
, an_loop_info
[0].var
, TREE_TYPE (an_loop_info
[0].var
));
521 new_yes_expr
= build_modify_expr
522 (location
, array_ind_value
, TREE_TYPE (array_ind_value
),
524 location
, func_parm
, TREE_TYPE (array_op0
));
528 new_yes_ind
= build_modify_expr
529 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
530 location
, TREE_OPERAND (array_op0
, 1),
531 TREE_TYPE (TREE_OPERAND (array_op0
, 1)));
532 new_yes_expr
= build_modify_expr
533 (location
, array_ind_value
, TREE_TYPE (array_ind_value
),
535 location
, func_parm
, TREE_OPERAND (array_op0
, 1));
537 new_yes_list
= alloc_stmt_list ();
538 append_to_statement_list (new_yes_ind
, &new_yes_list
);
539 append_to_statement_list (new_yes_expr
, &new_yes_list
);
541 new_no_list
= alloc_stmt_list ();
542 append_to_statement_list (new_no_ind
, &new_no_list
);
543 append_to_statement_list (new_no_expr
, &new_no_list
);
545 new_expr
= build_conditional_expr
547 build2 (GE_EXPR
, TREE_TYPE (array_ind_value
), array_ind_value
,
550 new_yes_list
, TREE_TYPE (*new_var
), new_no_list
, TREE_TYPE (*new_var
));
552 case BUILT_IN_CILKPLUS_SEC_REDUCE
:
553 new_var_init
= build_modify_expr
554 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
555 location
, identity_value
, new_var_type
);
556 new_call_expr
= build_call_expr (call_fn
, 2, *new_var
, func_parm
);
557 new_expr
= build_modify_expr
558 (location
, *new_var
, TREE_TYPE (*new_var
), NOP_EXPR
,
559 location
, new_call_expr
, TREE_TYPE (*new_var
));
561 case BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING
:
562 new_expr
= build_call_expr (call_fn
, 2, identity_value
, func_parm
);
569 for (ii
= 0; ii
< rank
; ii
++)
570 append_to_statement_list (an_loop_info
[ii
].ind_init
, &loop_init
);
572 if (an_type
== BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
573 || an_type
== BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND
)
574 append_to_statement_list (new_exp_init
, &loop_init
);
575 if (an_type
!= BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING
)
576 append_to_statement_list (new_var_init
, &loop_init
);
578 append_to_statement_list_force (loop_init
, &loop_with_init
);
580 for (ii
= 0; ii
< rank
; ii
++)
582 tree new_loop
= push_stmt_list ();
583 c_finish_loop (location
, an_loop_info
[ii
].cmp
, an_loop_info
[ii
].incr
,
584 body
, NULL_TREE
, NULL_TREE
, true);
585 body
= pop_stmt_list (new_loop
);
587 append_to_statement_list_force (body
, &loop_with_init
);
590 an_loop_info
.release ();
592 return loop_with_init
;
595 /* Returns a loop with ARRAY_REF inside it with an appropriate modify expr.
596 The LHS and/or RHS will be array notation expressions that have a MODIFYCODE
597 Their locations are specified by LHS_LOC, RHS_LOC. The location of the
598 modify expression is location. The original type of LHS and RHS are passed
599 in LHS_ORIGTYPE and RHS_ORIGTYPE. */
602 build_array_notation_expr (location_t location
, tree lhs
, tree lhs_origtype
,
603 enum tree_code modifycode
, location_t rhs_loc
,
604 tree rhs
, tree rhs_origtype
)
606 bool found_builtin_fn
= false;
607 tree array_expr_lhs
= NULL_TREE
, array_expr_rhs
= NULL_TREE
;
608 tree array_expr
= NULL_TREE
;
609 tree an_init
= NULL_TREE
;
610 vec
<tree
> cond_expr
= vNULL
;
611 tree body
, loop_with_init
= alloc_stmt_list();
612 tree scalar_mods
= NULL_TREE
;
613 vec
<tree
, va_gc
> *rhs_array_operand
= NULL
, *lhs_array_operand
= NULL
;
614 size_t lhs_rank
= 0, rhs_rank
= 0;
616 vec
<tree
, va_gc
> *lhs_list
= NULL
, *rhs_list
= NULL
;
617 tree new_modify_expr
, new_var
= NULL_TREE
, builtin_loop
= NULL_TREE
;
618 size_t rhs_list_size
= 0, lhs_list_size
= 0;
619 vec
<vec
<an_parts
> > lhs_an_info
= vNULL
, rhs_an_info
= vNULL
;
620 vec
<an_loop_parts
> lhs_an_loop_info
= vNULL
, rhs_an_loop_info
= vNULL
;
622 /* If either of this is true, an error message must have been send out
623 already. Not necessary to send out multiple error messages. */
624 if (lhs
== error_mark_node
|| rhs
== error_mark_node
)
625 return error_mark_node
;
627 if (!find_rank (location
, rhs
, rhs
, false, &rhs_rank
))
628 return error_mark_node
;
630 extract_array_notation_exprs (rhs
, false, &rhs_list
);
631 rhs_list_size
= vec_safe_length (rhs_list
);
632 an_init
= push_stmt_list ();
635 scalar_mods
= replace_invariant_exprs (&rhs
);
637 add_stmt (scalar_mods
);
639 for (ii
= 0; ii
< rhs_list_size
; ii
++)
641 tree rhs_node
= (*rhs_list
)[ii
];
642 if (TREE_CODE (rhs_node
) == CALL_EXPR
)
644 builtin_loop
= fix_builtin_array_notation_fn (rhs_node
, &new_var
);
645 if (builtin_loop
== error_mark_node
)
647 pop_stmt_list (an_init
);
648 return error_mark_node
;
650 else if (builtin_loop
)
652 add_stmt (builtin_loop
);
653 found_builtin_fn
= true;
656 vec
<tree
, va_gc
> *rhs_sub_list
= NULL
, *new_var_list
= NULL
;
657 vec_safe_push (rhs_sub_list
, rhs_node
);
658 vec_safe_push (new_var_list
, new_var
);
659 replace_array_notations (&rhs
, false, rhs_sub_list
,
668 if (!find_rank (location
, lhs
, lhs
, true, &lhs_rank
))
670 pop_stmt_list (an_init
);
671 return error_mark_node
;
674 if (!find_rank (location
, rhs
, rhs
, true, &rhs_rank
))
676 pop_stmt_list (an_init
);
677 return error_mark_node
;
680 if (lhs_rank
== 0 && rhs_rank
== 0)
682 if (found_builtin_fn
)
684 new_modify_expr
= build_modify_expr (location
, lhs
, lhs_origtype
,
685 modifycode
, rhs_loc
, rhs
,
687 add_stmt (new_modify_expr
);
688 pop_stmt_list (an_init
);
693 pop_stmt_list (an_init
);
699 extract_array_notation_exprs (rhs
, true, &rhs_list
);
700 extract_array_notation_exprs (lhs
, true, &lhs_list
);
701 rhs_list_size
= vec_safe_length (rhs_list
);
702 lhs_list_size
= vec_safe_length (lhs_list
);
704 if (lhs_rank
== 0 && rhs_rank
!= 0)
707 if (TREE_CODE (rhs_base
) == ARRAY_NOTATION_REF
)
709 for (ii
= 0; ii
< (size_t) rhs_rank
; ii
++)
710 rhs_base
= ARRAY_NOTATION_ARRAY (rhs
);
712 error_at (location
, "%qE cannot be scalar when %qE is not", lhs
,
714 return error_mark_node
;
718 error_at (location
, "%qE cannot be scalar when %qE is not", lhs
,
720 return error_mark_node
;
723 if (lhs_rank
!= 0 && rhs_rank
!= 0 && lhs_rank
!= rhs_rank
)
725 error_at (location
, "rank mismatch between %qE and %qE", lhs
, rhs
);
726 pop_stmt_list (an_init
);
727 return error_mark_node
;
730 /* Here we assign the array notation components to variable so that we can
731 satisfy the exec once rule. */
732 for (ii
= 0; ii
< lhs_list_size
; ii
++)
734 tree array_node
= (*lhs_list
)[ii
];
735 make_triplet_val_inv (location
, &ARRAY_NOTATION_START (array_node
));
736 make_triplet_val_inv (location
, &ARRAY_NOTATION_LENGTH (array_node
));
737 make_triplet_val_inv (location
, &ARRAY_NOTATION_STRIDE (array_node
));
739 for (ii
= 0; ii
< rhs_list_size
; ii
++)
740 if ((*rhs_list
)[ii
] && TREE_CODE ((*rhs_list
)[ii
]) == ARRAY_NOTATION_REF
)
742 tree array_node
= (*rhs_list
)[ii
];
743 make_triplet_val_inv (location
, &ARRAY_NOTATION_START (array_node
));
744 make_triplet_val_inv (location
, &ARRAY_NOTATION_LENGTH (array_node
));
745 make_triplet_val_inv (location
, &ARRAY_NOTATION_STRIDE (array_node
));
748 cond_expr
.safe_grow_cleared (MAX (lhs_rank
, rhs_rank
));
750 lhs_an_loop_info
.safe_grow_cleared (lhs_rank
);
752 rhs_an_loop_info
.safe_grow_cleared (rhs_rank
);
754 cilkplus_extract_an_triplets (lhs_list
, lhs_list_size
, lhs_rank
,
758 rhs_an_loop_info
.safe_grow_cleared (rhs_rank
);
759 cilkplus_extract_an_triplets (rhs_list
, rhs_list_size
, rhs_rank
,
762 if (length_mismatch_in_expr_p (EXPR_LOCATION (lhs
), lhs_an_info
)
764 && length_mismatch_in_expr_p (EXPR_LOCATION (rhs
), rhs_an_info
)))
766 pop_stmt_list (an_init
);
767 return error_mark_node
;
769 if (lhs_list_size
> 0 && rhs_list_size
> 0 && lhs_rank
> 0 && rhs_rank
> 0
770 && TREE_CODE (lhs_an_info
[0][0].length
) == INTEGER_CST
771 && rhs_an_info
[0][0].length
772 && TREE_CODE (rhs_an_info
[0][0].length
) == INTEGER_CST
)
774 HOST_WIDE_INT l_length
= int_cst_value (lhs_an_info
[0][0].length
);
775 HOST_WIDE_INT r_length
= int_cst_value (rhs_an_info
[0][0].length
);
776 /* Length can be negative or positive. As long as the magnitude is OK,
777 then the array notation is valid. */
778 if (absu_hwi (l_length
) != absu_hwi (r_length
))
780 error_at (location
, "length mismatch between LHS and RHS");
781 pop_stmt_list (an_init
);
782 return error_mark_node
;
785 for (ii
= 0; ii
< lhs_rank
; ii
++)
786 if (lhs_an_info
[0][ii
].is_vector
)
788 lhs_an_loop_info
[ii
].var
= create_tmp_var (integer_type_node
,
790 lhs_an_loop_info
[ii
].ind_init
= build_modify_expr
791 (location
, lhs_an_loop_info
[ii
].var
,
792 TREE_TYPE (lhs_an_loop_info
[ii
].var
), NOP_EXPR
,
793 location
, build_zero_cst (TREE_TYPE (lhs_an_loop_info
[ii
].var
)),
794 TREE_TYPE (lhs_an_loop_info
[ii
].var
));
796 for (ii
= 0; ii
< rhs_rank
; ii
++)
798 /* When we have a polynomial, we assume that the indices are of type
800 rhs_an_loop_info
[ii
].var
= create_tmp_var (integer_type_node
,
802 rhs_an_loop_info
[ii
].ind_init
= build_modify_expr
803 (location
, rhs_an_loop_info
[ii
].var
,
804 TREE_TYPE (rhs_an_loop_info
[ii
].var
), NOP_EXPR
,
805 location
, build_int_cst (TREE_TYPE (rhs_an_loop_info
[ii
].var
), 0),
806 TREE_TYPE (rhs_an_loop_info
[ii
].var
));
810 lhs_array_operand
= create_array_refs
811 (location
, lhs_an_info
, lhs_an_loop_info
, lhs_list_size
, lhs_rank
);
812 replace_array_notations (&lhs
, true, lhs_list
, lhs_array_operand
);
813 array_expr_lhs
= lhs
;
815 if (rhs_array_operand
)
816 vec_safe_truncate (rhs_array_operand
, 0);
819 rhs_array_operand
= create_array_refs
820 (location
, rhs_an_info
, rhs_an_loop_info
, rhs_list_size
, rhs_rank
);
821 replace_array_notations (&rhs
, true, rhs_list
, rhs_array_operand
);
822 vec_safe_truncate (rhs_array_operand
, 0);
823 rhs_array_operand
= fix_sec_implicit_args (location
, rhs_list
,
824 rhs_an_loop_info
, rhs_rank
,
826 if (!rhs_array_operand
)
827 return error_mark_node
;
828 replace_array_notations (&rhs
, true, rhs_list
, rhs_array_operand
);
830 else if (rhs_list_size
> 0)
832 rhs_array_operand
= fix_sec_implicit_args (location
, rhs_list
,
833 lhs_an_loop_info
, lhs_rank
,
835 if (!rhs_array_operand
)
836 return error_mark_node
;
837 replace_array_notations (&rhs
, true, rhs_list
, rhs_array_operand
);
839 array_expr_lhs
= lhs
;
840 array_expr_rhs
= rhs
;
841 array_expr
= build_modify_expr (location
, array_expr_lhs
, lhs_origtype
,
842 modifycode
, rhs_loc
, array_expr_rhs
,
844 create_cmp_incr (location
, &lhs_an_loop_info
, lhs_rank
, lhs_an_info
);
846 create_cmp_incr (location
, &rhs_an_loop_info
, rhs_rank
, rhs_an_info
);
848 for (ii
= 0; ii
< MAX (lhs_rank
, rhs_rank
); ii
++)
849 if (ii
< lhs_rank
&& ii
< rhs_rank
)
850 cond_expr
[ii
] = build2 (TRUTH_ANDIF_EXPR
, boolean_type_node
,
851 lhs_an_loop_info
[ii
].cmp
,
852 rhs_an_loop_info
[ii
].cmp
);
853 else if (ii
< lhs_rank
&& ii
>= rhs_rank
)
854 cond_expr
[ii
] = lhs_an_loop_info
[ii
].cmp
;
858 an_init
= pop_stmt_list (an_init
);
859 append_to_statement_list_force (an_init
, &loop_with_init
);
861 for (ii
= 0; ii
< MAX (lhs_rank
, rhs_rank
); ii
++)
863 tree incr_list
= alloc_stmt_list ();
864 tree new_loop
= push_stmt_list ();
866 add_stmt (lhs_an_loop_info
[ii
].ind_init
);
868 add_stmt (rhs_an_loop_info
[ii
].ind_init
);
870 append_to_statement_list_force (lhs_an_loop_info
[ii
].incr
, &incr_list
);
871 if (rhs_rank
&& rhs_an_loop_info
[ii
].incr
)
872 append_to_statement_list_force (rhs_an_loop_info
[ii
].incr
, &incr_list
);
873 c_finish_loop (location
, cond_expr
[ii
], incr_list
, body
, NULL_TREE
,
875 body
= pop_stmt_list (new_loop
);
877 append_to_statement_list_force (body
, &loop_with_init
);
879 lhs_an_info
.release ();
880 lhs_an_loop_info
.release ();
883 rhs_an_info
.release ();
884 rhs_an_loop_info
.release ();
886 cond_expr
.release ();
887 return loop_with_init
;
890 /* Helper function for fix_conditional_array_notations. Encloses the
891 conditional statement passed in STMT with a loop around it
892 and replaces the condition in STMT with a ARRAY_REF tree-node to the array.
893 The condition must have an ARRAY_NOTATION_REF tree. An expansion of array
894 notation in STMT is returned in a STATEMENT_LIST. */
897 fix_conditional_array_notations_1 (tree stmt
)
899 vec
<tree
, va_gc
> *array_list
= NULL
, *array_operand
= NULL
;
900 size_t list_size
= 0;
901 tree cond
= NULL_TREE
, builtin_loop
= NULL_TREE
, new_var
= NULL_TREE
;
902 size_t rank
= 0, ii
= 0;
904 location_t location
= EXPR_LOCATION (stmt
);
905 tree body
= NULL_TREE
, loop_with_init
= alloc_stmt_list ();
906 vec
<vec
<an_parts
> > an_info
= vNULL
;
907 vec
<an_loop_parts
> an_loop_info
= vNULL
;
909 if (TREE_CODE (stmt
) == COND_EXPR
)
910 cond
= COND_EXPR_COND (stmt
);
911 else if (TREE_CODE (stmt
) == SWITCH_EXPR
)
912 cond
= SWITCH_COND (stmt
);
913 else if (truth_value_p (TREE_CODE (stmt
)))
914 cond
= TREE_OPERAND (stmt
, 0);
916 /* Otherwise dont even touch the statement. */
919 if (!find_rank (location
, cond
, cond
, false, &rank
))
920 return error_mark_node
;
922 extract_array_notation_exprs (stmt
, false, &array_list
);
923 loop_init
= push_stmt_list ();
924 for (ii
= 0; ii
< vec_safe_length (array_list
); ii
++)
926 tree array_node
= (*array_list
)[ii
];
927 if (TREE_CODE (array_node
) == CALL_EXPR
)
929 builtin_loop
= fix_builtin_array_notation_fn (array_node
, &new_var
);
930 if (builtin_loop
== error_mark_node
)
932 add_stmt (error_mark_node
);
933 pop_stmt_list (loop_init
);
936 else if (builtin_loop
)
938 vec
<tree
, va_gc
>* sub_list
= NULL
, *new_var_list
= NULL
;
939 vec_safe_push (sub_list
, array_node
);
940 vec_safe_push (new_var_list
, new_var
);
941 add_stmt (builtin_loop
);
942 replace_array_notations (&stmt
, false, sub_list
, new_var_list
);
946 if (!find_rank (location
, stmt
, stmt
, true, &rank
))
948 pop_stmt_list (loop_init
);
949 return error_mark_node
;
954 pop_stmt_list (loop_init
);
957 extract_array_notation_exprs (stmt
, true, &array_list
);
959 if (vec_safe_length (array_list
) == 0)
962 list_size
= vec_safe_length (array_list
);
963 an_loop_info
.safe_grow_cleared (rank
);
965 for (ii
= 0; ii
< list_size
; ii
++)
966 if ((*array_list
)[ii
]
967 && TREE_CODE ((*array_list
)[ii
]) == ARRAY_NOTATION_REF
)
969 tree array_node
= (*array_list
)[ii
];
970 make_triplet_val_inv (location
, &ARRAY_NOTATION_START (array_node
));
971 make_triplet_val_inv (location
, &ARRAY_NOTATION_LENGTH (array_node
));
972 make_triplet_val_inv (location
, &ARRAY_NOTATION_STRIDE (array_node
));
974 cilkplus_extract_an_triplets (array_list
, list_size
, rank
, &an_info
);
975 for (ii
= 0; ii
< rank
; ii
++)
977 an_loop_info
[ii
].var
= create_tmp_var (integer_type_node
, NULL
);
978 an_loop_info
[ii
].ind_init
=
979 build_modify_expr (location
, an_loop_info
[ii
].var
,
980 TREE_TYPE (an_loop_info
[ii
].var
), NOP_EXPR
,
982 build_int_cst (TREE_TYPE (an_loop_info
[ii
].var
), 0),
983 TREE_TYPE (an_loop_info
[ii
].var
));
985 array_operand
= create_array_refs (location
, an_info
, an_loop_info
,
987 replace_array_notations (&stmt
, true, array_list
, array_operand
);
988 create_cmp_incr (location
, &an_loop_info
, rank
, an_info
);
990 loop_init
= pop_stmt_list (loop_init
);
992 append_to_statement_list_force (loop_init
, &loop_with_init
);
994 for (ii
= 0; ii
< rank
; ii
++)
996 tree new_loop
= push_stmt_list ();
997 add_stmt (an_loop_info
[ii
].ind_init
);
998 c_finish_loop (location
, an_loop_info
[ii
].cmp
, an_loop_info
[ii
].incr
,
999 body
, NULL_TREE
, NULL_TREE
, true);
1000 body
= pop_stmt_list (new_loop
);
1002 append_to_statement_list_force (body
, &loop_with_init
);
1004 an_loop_info
.release ();
1007 return loop_with_init
;
1010 /* Top-level function to replace ARRAY_NOTATION_REF in a conditional statement
1011 in STMT. An expansion of array notation in STMT is returned as a
1015 fix_conditional_array_notations (tree stmt
)
1017 if (TREE_CODE (stmt
) == STATEMENT_LIST
)
1019 tree_stmt_iterator tsi
;
1020 for (tsi
= tsi_start (stmt
); !tsi_end_p (tsi
); tsi_next (&tsi
))
1022 tree single_stmt
= *tsi_stmt_ptr (tsi
);
1023 *tsi_stmt_ptr (tsi
) =
1024 fix_conditional_array_notations_1 (single_stmt
);
1029 return fix_conditional_array_notations_1 (stmt
);
1032 /* Create a struct c_expr that contains a loop with ARRAY_REF expr at location
1033 LOCATION with the tree_code CODE and the array notation expr is
1034 passed in ARG. Returns the fixed c_expr in ARG itself. */
1037 fix_array_notation_expr (location_t location
, enum tree_code code
,
1041 vec
<tree
, va_gc
> *array_list
= NULL
, *array_operand
= NULL
;
1042 size_t list_size
= 0, rank
= 0, ii
= 0;
1044 tree body
, loop_with_init
= alloc_stmt_list ();
1045 vec
<vec
<an_parts
> > an_info
= vNULL
;
1046 vec
<an_loop_parts
> an_loop_info
= vNULL
;
1048 if (!find_rank (location
, arg
.value
, arg
.value
, false, &rank
))
1050 /* If this function returns a NULL, we convert the tree value in the
1051 structure to error_mark_node and the parser should take care of the
1053 arg
.value
= error_mark_node
;
1060 extract_array_notation_exprs (arg
.value
, true, &array_list
);
1062 if (vec_safe_length (array_list
) == 0)
1065 list_size
= vec_safe_length (array_list
);
1067 an_loop_info
.safe_grow_cleared (rank
);
1068 cilkplus_extract_an_triplets (array_list
, list_size
, rank
, &an_info
);
1070 loop_init
= push_stmt_list ();
1071 for (ii
= 0; ii
< rank
; ii
++)
1073 an_loop_info
[ii
].var
= create_tmp_var (integer_type_node
, NULL
);
1074 an_loop_info
[ii
].ind_init
=
1075 build_modify_expr (location
, an_loop_info
[ii
].var
,
1076 TREE_TYPE (an_loop_info
[ii
].var
), NOP_EXPR
,
1078 build_int_cst (TREE_TYPE (an_loop_info
[ii
].var
), 0),
1079 TREE_TYPE (an_loop_info
[ii
].var
));;
1082 array_operand
= create_array_refs (location
, an_info
, an_loop_info
,
1084 replace_array_notations (&arg
.value
, true, array_list
, array_operand
);
1085 create_cmp_incr (location
, &an_loop_info
, rank
, an_info
);
1087 arg
= default_function_array_read_conversion (location
, arg
);
1088 if (code
== POSTINCREMENT_EXPR
|| code
== POSTDECREMENT_EXPR
)
1089 arg
.value
= build_unary_op (location
, code
, arg
.value
, 0);
1090 else if (code
== PREINCREMENT_EXPR
|| code
== PREDECREMENT_EXPR
)
1091 arg
= parser_build_unary_op (location
, code
, arg
);
1093 loop_init
= pop_stmt_list (loop_init
);
1094 append_to_statement_list_force (loop_init
, &loop_with_init
);
1097 for (ii
= 0; ii
< rank
; ii
++)
1099 tree new_loop
= push_stmt_list ();
1100 add_stmt (an_loop_info
[ii
].ind_init
);
1101 c_finish_loop (location
, an_loop_info
[ii
].cmp
,
1102 an_loop_info
[ii
].incr
, body
, NULL_TREE
,
1104 body
= pop_stmt_list (new_loop
);
1106 append_to_statement_list_force (body
, &loop_with_init
);
1107 arg
.value
= loop_with_init
;
1109 an_loop_info
.release ();
1113 /* Replaces array notations in a void function call arguments in ARG and returns
1114 a STATEMENT_LIST. */
1117 fix_array_notation_call_expr (tree arg
)
1119 vec
<tree
, va_gc
> *array_list
= NULL
, *array_operand
= NULL
;
1120 tree new_var
= NULL_TREE
;
1121 size_t list_size
= 0, rank
= 0, ii
= 0;
1123 tree body
, loop_with_init
= alloc_stmt_list ();
1124 location_t location
= UNKNOWN_LOCATION
;
1125 vec
<vec
<an_parts
> > an_info
= vNULL
;
1126 vec
<an_loop_parts
> an_loop_info
= vNULL
;
1128 if (TREE_CODE (arg
) == CALL_EXPR
1129 && is_cilkplus_reduce_builtin (CALL_EXPR_FN (arg
)))
1131 loop_init
= fix_builtin_array_notation_fn (arg
, &new_var
);
1132 /* We are ignoring the new var because either the user does not want to
1133 capture it OR he is using sec_reduce_mutating function. */
1136 if (!find_rank (location
, arg
, arg
, false, &rank
))
1137 return error_mark_node
;
1142 extract_array_notation_exprs (arg
, true, &array_list
);
1143 if (vec_safe_length (array_list
) == 0)
1146 list_size
= vec_safe_length (array_list
);
1147 location
= EXPR_LOCATION (arg
);
1148 an_loop_info
.safe_grow_cleared (rank
);
1150 loop_init
= push_stmt_list ();
1151 for (ii
= 0; ii
< list_size
; ii
++)
1152 if ((*array_list
)[ii
]
1153 && TREE_CODE ((*array_list
)[ii
]) == ARRAY_NOTATION_REF
)
1155 tree array_node
= (*array_list
)[ii
];
1156 make_triplet_val_inv (location
, &ARRAY_NOTATION_START (array_node
));
1157 make_triplet_val_inv (location
, &ARRAY_NOTATION_LENGTH (array_node
));
1158 make_triplet_val_inv (location
, &ARRAY_NOTATION_STRIDE (array_node
));
1160 cilkplus_extract_an_triplets (array_list
, list_size
, rank
, &an_info
);
1161 if (length_mismatch_in_expr_p (location
, an_info
))
1163 pop_stmt_list (loop_init
);
1164 return error_mark_node
;
1166 for (ii
= 0; ii
< rank
; ii
++)
1168 an_loop_info
[ii
].var
= create_tmp_var (integer_type_node
, NULL
);
1169 an_loop_info
[ii
].ind_init
=
1170 build_modify_expr (location
, an_loop_info
[ii
].var
,
1171 TREE_TYPE (an_loop_info
[ii
].var
), NOP_EXPR
, location
,
1172 build_int_cst (TREE_TYPE (an_loop_info
[ii
].var
), 0),
1173 TREE_TYPE (an_loop_info
[ii
].var
));
1176 array_operand
= create_array_refs (location
, an_info
, an_loop_info
,
1178 replace_array_notations (&arg
, true, array_list
, array_operand
);
1179 create_cmp_incr (location
, &an_loop_info
, rank
, an_info
);
1180 loop_init
= pop_stmt_list (loop_init
);
1181 append_to_statement_list_force (loop_init
, &loop_with_init
);
1183 for (ii
= 0; ii
< rank
; ii
++)
1185 tree new_loop
= push_stmt_list ();
1186 add_stmt (an_loop_info
[ii
].ind_init
);
1187 c_finish_loop (location
, an_loop_info
[ii
].cmp
, an_loop_info
[ii
].incr
,
1188 body
, NULL_TREE
, NULL_TREE
, true);
1189 body
= pop_stmt_list (new_loop
);
1191 append_to_statement_list_force (body
, &loop_with_init
);
1192 an_loop_info
.release ();
1194 return loop_with_init
;
1197 /* Expands the built-in functions in a return. EXPR is a RETURN_EXPR with
1198 a built-in reduction function. This function returns the expansion code for
1199 the built-in function. */
1202 fix_return_expr (tree expr
)
1204 tree new_mod_list
, new_var
, new_mod
, retval_expr
, retval_type
;
1205 location_t loc
= EXPR_LOCATION (expr
);
1207 new_mod_list
= alloc_stmt_list ();
1208 retval_expr
= TREE_OPERAND (expr
, 0);
1209 retval_type
= TREE_TYPE (TREE_OPERAND (retval_expr
, 1));
1210 new_var
= build_decl (loc
, VAR_DECL
, NULL_TREE
, TREE_TYPE (retval_expr
));
1211 new_mod
= build_array_notation_expr (loc
, new_var
, TREE_TYPE (new_var
),
1213 TREE_OPERAND (retval_expr
, 1),
1215 TREE_OPERAND (retval_expr
, 1) = new_var
;
1216 TREE_OPERAND (expr
, 0) = retval_expr
;
1217 append_to_statement_list_force (new_mod
, &new_mod_list
);
1218 append_to_statement_list_force (expr
, &new_mod_list
);
1219 return new_mod_list
;
1222 /* Callback for walk_tree. Expands all array notations in *TP. *WALK_SUBTREES
1223 is set to 1 unless *TP contains no array notation expressions. */
1226 expand_array_notations (tree
*tp
, int *walk_subtrees
, void *)
1228 if (!contains_array_notation_expr (*tp
))
1235 switch (TREE_CODE (*tp
))
1237 case TRUTH_ORIF_EXPR
:
1238 case TRUTH_ANDIF_EXPR
:
1240 case TRUTH_AND_EXPR
:
1241 case TRUTH_XOR_EXPR
:
1242 case TRUTH_NOT_EXPR
:
1244 *tp
= fix_conditional_array_notations (*tp
);
1248 location_t loc
= EXPR_HAS_LOCATION (*tp
) ? EXPR_LOCATION (*tp
) :
1250 tree lhs
= TREE_OPERAND (*tp
, 0);
1251 tree rhs
= TREE_OPERAND (*tp
, 1);
1252 location_t rhs_loc
= EXPR_HAS_LOCATION (rhs
) ? EXPR_LOCATION (rhs
) :
1254 *tp
= build_array_notation_expr (loc
, lhs
, TREE_TYPE (lhs
), NOP_EXPR
,
1255 rhs_loc
, rhs
, TREE_TYPE (rhs
));
1259 *tp
= fix_array_notation_call_expr (*tp
);
1262 *tp
= fix_return_expr (*tp
);
1265 if (TREE_CODE (TREE_OPERAND (*tp
, 0)) == SAVE_EXPR
)
1267 /* In here we are calling expand_array_notations because
1268 we need to be able to catch the return value and check if
1269 it is an error_mark_node. */
1270 expand_array_notations (&TREE_OPERAND (*tp
, 1), walk_subtrees
, NULL
);
1272 /* SAVE_EXPR cannot have an error_mark_node inside it. This check
1273 will make sure that if there is an error in expanding of
1274 array notations (e.g. rank mismatch) then replace the entire
1275 SAVE_EXPR with an error_mark_node. */
1276 if (TREE_OPERAND (*tp
, 1) == error_mark_node
)
1277 *tp
= error_mark_node
;
1280 case ARRAY_NOTATION_REF
:
1281 /* If we are here, then we are dealing with cases like this:
1285 Replace those with just void zero node. */
1293 /* Walks through tree node T and expands all array notations in its subtrees.
1294 The return value is the same type as T but with all array notations
1295 replaced with appropriate ARRAY_REFS with a loop around it. */
1298 expand_array_notation_exprs (tree t
)
1300 walk_tree (&t
, expand_array_notations
, NULL
, NULL
);
1304 /* This handles expression of the form "a[i:j:k]" or "a[:]" or "a[i:j]," which
1305 denotes an array notation expression. If a is a variable or a member, then
1306 we generate a ARRAY_NOTATION_REF front-end tree and return it.
1307 This tree is broken down to ARRAY_REF toward the end of parsing.
1308 ARRAY_NOTATION_REF tree holds the START_INDEX, LENGTH, STRIDE and the TYPE
1309 of ARRAY_REF. Restrictions on START_INDEX, LENGTH and STRIDE is same as that
1310 of the index field passed into ARRAY_REF. The only additional restriction
1311 is that, unlike index in ARRAY_REF, stride, length and start_index cannot
1312 contain ARRAY_NOTATIONS. */
1315 build_array_notation_ref (location_t loc
, tree array
, tree start_index
,
1316 tree length
, tree stride
, tree type
)
1318 tree array_ntn_tree
= NULL_TREE
;
1319 size_t stride_rank
= 0, length_rank
= 0, start_rank
= 0;
1321 if (!INTEGRAL_TYPE_P (TREE_TYPE (start_index
)))
1324 "start-index of array notation triplet is not an integer");
1325 return error_mark_node
;
1327 if (!INTEGRAL_TYPE_P (TREE_TYPE (length
)))
1329 error_at (loc
, "length of array notation triplet is not an integer");
1330 return error_mark_node
;
1333 /* The stride is an optional field. */
1334 if (stride
&& !INTEGRAL_TYPE_P (TREE_TYPE (stride
)))
1336 error_at (loc
, "stride of array notation triplet is not an integer");
1337 return error_mark_node
;
1341 if (TREE_CONSTANT (start_index
) && TREE_CONSTANT (length
)
1342 && tree_int_cst_lt (length
, start_index
))
1343 stride
= build_int_cst (TREE_TYPE (start_index
), -1);
1345 stride
= build_int_cst (TREE_TYPE (start_index
), 1);
1348 if (!find_rank (loc
, start_index
, start_index
, false, &start_rank
))
1349 return error_mark_node
;
1350 if (!find_rank (loc
, length
, length
, false, &length_rank
))
1351 return error_mark_node
;
1352 if (!find_rank (loc
, stride
, stride
, false, &stride_rank
))
1353 return error_mark_node
;
1355 if (start_rank
!= 0)
1357 error_at (loc
, "rank of an array notation triplet's start-index is not "
1359 return error_mark_node
;
1361 if (length_rank
!= 0)
1363 error_at (loc
, "rank of an array notation triplet's length is not zero");
1364 return error_mark_node
;
1366 if (stride_rank
!= 0)
1368 error_at (loc
, "rank of array notation triplet's stride is not zero");
1369 return error_mark_node
;
1371 array_ntn_tree
= build4 (ARRAY_NOTATION_REF
, NULL_TREE
, NULL_TREE
, NULL_TREE
,
1372 NULL_TREE
, NULL_TREE
);
1373 ARRAY_NOTATION_ARRAY (array_ntn_tree
) = array
;
1374 ARRAY_NOTATION_START (array_ntn_tree
) = start_index
;
1375 ARRAY_NOTATION_LENGTH (array_ntn_tree
) = length
;
1376 ARRAY_NOTATION_STRIDE (array_ntn_tree
) = stride
;
1377 TREE_TYPE (array_ntn_tree
) = type
;
1379 return array_ntn_tree
;