tree-core.h: Include symtab.h.
[gcc.git] / gcc / c / c-array-notation.c
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>,
6 Intel Corporation.
7
8 This file is part of GCC.
9
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)
13 any later version.
14
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.
19
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/>. */
23
24 /* The Array Notation Transformation Technique:
25
26 An array notation expression has 4 major components:
27 1. The array name
28 2. Start Index
29 3. Number of elements we need to acess (we call it length)
30 4. Stride
31
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.
35
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
38 technique:
39
40 Let's say we have an array notation in a statement like this:
41
42 A[St1:Ln:Str1] = B[St2:Ln:Str2] + <NON ARRAY_NOTATION_STMT>
43
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.
48
49 The above expression is broken into the following
50 (with the help of c_finish_loop function from c-typeck.c):
51
52 Tmp_Var = 0;
53 goto compare_label:
54 body_label:
55
56 A[St1+Tmp_Var*Str1] = B[St1+Tmp_Var*Str2] + <NON ARRAY_NOTATION_STMT>;
57 Tmp_Var++;
58
59 compare_label:
60 if (Tmp_Var < Ln)
61 goto body_label;
62 else
63 goto exit_label;
64 exit_label:
65
66 */
67
68 #include "config.h"
69 #include "system.h"
70 #include "coretypes.h"
71 #include "tree.h"
72 #include "alias.h"
73 #include "flags.h"
74 #include "c-tree.h"
75 #include "gimple-expr.h"
76 #include "tree-iterator.h"
77 #include "opts.h"
78 #include "c-family/c-common.h"
79
80 /* If *VALUE is not of type INTEGER_CST, PARM_DECL or VAR_DECL, then map it
81 to a variable and then set *VALUE to the new variable. */
82
83 static inline void
84 make_triplet_val_inv (location_t loc, tree *value)
85 {
86 tree var, new_exp;
87 if (TREE_CODE (*value) != INTEGER_CST
88 && TREE_CODE (*value) != PARM_DECL
89 && !VAR_P (*value))
90 {
91 var = build_decl (loc, VAR_DECL, NULL_TREE, integer_type_node);
92 new_exp = build_modify_expr (loc, var, TREE_TYPE (var), NOP_EXPR, loc,
93 *value, TREE_TYPE (*value));
94 add_stmt (new_exp);
95 *value = var;
96 }
97 }
98
99 /* Populates the INCR and CMP vectors with the increment (of type POSTINCREMENT
100 or POSTDECREMENT) and comparison (of TYPE GT_EXPR or LT_EXPR) expressions,
101 using data from LENGTH, COUNT_DOWN, and VAR. INCR and CMP vectors are of
102 size RANK. */
103
104 static void
105 create_cmp_incr (location_t loc, vec<an_loop_parts> *node, size_t rank,
106 vec<vec<an_parts> > an_info)
107 {
108 for (size_t ii = 0; ii < rank; ii++)
109 {
110 tree var = (*node)[ii].var;
111 tree length = an_info[0][ii].length;
112 (*node)[ii].incr = build_unary_op (loc, POSTINCREMENT_EXPR, var, 0);
113 (*node)[ii].cmp = build2 (LT_EXPR, boolean_type_node, var, length);
114 }
115 }
116
117 /* Returns a vector of size RANK that contains an array ref that is derived from
118 array notation triplet parameters stored in VALUE, START, STRIDE. IS_VECTOR
119 is used to check if the data stored at its corresponding location is an
120 array notation. VAR is the induction variable passed in by the caller.
121
122 For example: For an array notation A[5:10:2], the vector start will be
123 of size 1 holding '5', stride of same size as start but holding the value of
124 as 2, is_vector as true and count_down as false. Let's assume VAR is 'x'
125 This function returns a vector of size 1 with the following data:
126 A[5 + (x * 2)] .
127 */
128
129 static vec<tree, va_gc> *
130 create_array_refs (location_t loc, vec<vec<an_parts> > an_info,
131 vec<an_loop_parts> an_loop_info, size_t size, size_t rank)
132 {
133 tree ind_mult, ind_incr;
134 vec<tree, va_gc> *array_operand = NULL;
135 for (size_t ii = 0; ii < size; ii++)
136 if (an_info[ii][0].is_vector)
137 {
138 tree array_opr = an_info[ii][rank - 1].value;
139 for (int s_jj = rank - 1; s_jj >= 0; s_jj--)
140 {
141 tree var = an_loop_info[s_jj].var;
142 tree stride = an_info[ii][s_jj].stride;
143 tree start = an_info[ii][s_jj].start;
144 ind_mult = build2 (MULT_EXPR, TREE_TYPE (var), var, stride);
145 ind_incr = build2 (PLUS_EXPR, TREE_TYPE (var), start, ind_mult);
146 array_opr = build_array_ref (loc, array_opr, ind_incr);
147 }
148 vec_safe_push (array_operand, array_opr);
149 }
150 else
151 /* This is just a dummy node to make sure both the list sizes for both
152 array list and array operand list are the same. */
153 vec_safe_push (array_operand, integer_one_node);
154 return array_operand;
155 }
156
157 /* Replaces all the scalar expressions in *NODE. Returns a STATEMENT_LIST that
158 holds the NODE along with variables that holds the results of the invariant
159 expressions. */
160
161 tree
162 replace_invariant_exprs (tree *node)
163 {
164 size_t ix = 0;
165 tree node_list = NULL_TREE;
166 tree t = NULL_TREE, new_var = NULL_TREE, new_node;
167 struct inv_list data;
168
169 data.list_values = NULL;
170 data.replacement = NULL;
171 data.additional_tcodes = NULL;
172 walk_tree (node, find_inv_trees, (void *)&data, NULL);
173
174 if (vec_safe_length (data.list_values))
175 {
176 node_list = push_stmt_list ();
177 for (ix = 0; vec_safe_iterate (data.list_values, ix, &t); ix++)
178 {
179 new_var = build_decl (EXPR_LOCATION (t), VAR_DECL, NULL_TREE,
180 TREE_TYPE (t));
181 gcc_assert (new_var != NULL_TREE && new_var != error_mark_node);
182 new_node = build2 (MODIFY_EXPR, TREE_TYPE (t), new_var, t);
183 add_stmt (new_node);
184 vec_safe_push (data.replacement, new_var);
185 }
186 walk_tree (node, replace_inv_trees, (void *)&data, NULL);
187 node_list = pop_stmt_list (node_list);
188 }
189 return node_list;
190 }
191
192 /* Given a CALL_EXPR to an array notation built-in function in
193 AN_BUILTIN_FN, replace the call with the appropriate loop and
194 computation. Return the computation in *NEW_VAR.
195
196 The return value in *NEW_VAR will always be a scalar. If the
197 built-in is __sec_reduce_mutating, *NEW_VAR is set to NULL_TREE. */
198
199 static tree
200 fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var)
201 {
202 tree new_var_type = NULL_TREE, func_parm, new_expr, new_yes_expr, new_no_expr;
203 tree array_ind_value = NULL_TREE, new_no_ind, new_yes_ind, new_no_list;
204 tree new_yes_list, new_cond_expr, new_var_init = NULL_TREE;
205 tree new_exp_init = NULL_TREE;
206 vec<tree, va_gc> *array_list = NULL, *array_operand = NULL;
207 size_t list_size = 0, rank = 0, ii = 0;
208 tree loop_init, array_op0;
209 tree identity_value = NULL_TREE, call_fn = NULL_TREE, new_call_expr, body;
210 location_t location = UNKNOWN_LOCATION;
211 tree loop_with_init = alloc_stmt_list ();
212 vec<vec<an_parts> > an_info = vNULL;
213 vec<an_loop_parts> an_loop_info = vNULL;
214 enum built_in_function an_type =
215 is_cilkplus_reduce_builtin (CALL_EXPR_FN (an_builtin_fn));
216 if (an_type == BUILT_IN_NONE)
217 return NULL_TREE;
218
219 /* Builtin call should contain at least one argument. */
220 if (call_expr_nargs (an_builtin_fn) == 0)
221 {
222 error_at (EXPR_LOCATION (an_builtin_fn), "Invalid builtin arguments");
223 return error_mark_node;
224 }
225
226 if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE
227 || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING)
228 {
229 call_fn = CALL_EXPR_ARG (an_builtin_fn, 2);
230 if (TREE_CODE (call_fn) == ADDR_EXPR)
231 call_fn = TREE_OPERAND (call_fn, 0);
232 identity_value = CALL_EXPR_ARG (an_builtin_fn, 0);
233 func_parm = CALL_EXPR_ARG (an_builtin_fn, 1);
234 }
235 else
236 func_parm = CALL_EXPR_ARG (an_builtin_fn, 0);
237
238 /* Fully fold any EXCESSIVE_PRECISION EXPR that can occur in the function
239 parameter. */
240 func_parm = c_fully_fold (func_parm, false, NULL);
241 if (func_parm == error_mark_node)
242 return error_mark_node;
243
244 location = EXPR_LOCATION (an_builtin_fn);
245
246 if (!find_rank (location, an_builtin_fn, an_builtin_fn, true, &rank))
247 return error_mark_node;
248
249 if (rank == 0)
250 {
251 error_at (location, "Invalid builtin arguments");
252 return error_mark_node;
253 }
254 else if (rank > 1
255 && (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
256 || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND))
257 {
258 error_at (location, "__sec_reduce_min_ind or __sec_reduce_max_ind cannot"
259 " have arrays with dimension greater than 1");
260 return error_mark_node;
261 }
262
263 extract_array_notation_exprs (func_parm, true, &array_list);
264 list_size = vec_safe_length (array_list);
265 switch (an_type)
266 {
267 case BUILT_IN_CILKPLUS_SEC_REDUCE_ADD:
268 case BUILT_IN_CILKPLUS_SEC_REDUCE_MUL:
269 case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX:
270 case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN:
271 new_var_type = TREE_TYPE ((*array_list)[0]);
272 break;
273 case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_ZERO:
274 case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_NONZERO:
275 case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO:
276 case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_NONZERO:
277 new_var_type = integer_type_node;
278 break;
279 case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND:
280 case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND:
281 new_var_type = integer_type_node;
282 break;
283 case BUILT_IN_CILKPLUS_SEC_REDUCE:
284 if (call_fn && identity_value)
285 new_var_type = TREE_TYPE ((*array_list)[0]);
286 break;
287 case BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING:
288 new_var_type = NULL_TREE;
289 break;
290 default:
291 gcc_unreachable ();
292 }
293
294 an_loop_info.safe_grow_cleared (rank);
295 cilkplus_extract_an_triplets (array_list, list_size, rank, &an_info);
296 loop_init = alloc_stmt_list ();
297
298 for (ii = 0; ii < rank; ii++)
299 {
300 an_loop_info[ii].var = create_tmp_var (integer_type_node);
301 an_loop_info[ii].ind_init =
302 build_modify_expr (location, an_loop_info[ii].var,
303 TREE_TYPE (an_loop_info[ii].var), NOP_EXPR,
304 location,
305 build_int_cst (TREE_TYPE (an_loop_info[ii].var), 0),
306 TREE_TYPE (an_loop_info[ii].var));
307 }
308 array_operand = create_array_refs (location, an_info, an_loop_info,
309 list_size, rank);
310 replace_array_notations (&func_parm, true, array_list, array_operand);
311
312 create_cmp_incr (location, &an_loop_info, rank, an_info);
313 if (an_type != BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING)
314 {
315 *new_var = build_decl (location, VAR_DECL, NULL_TREE, new_var_type);
316 gcc_assert (*new_var && *new_var != error_mark_node);
317 }
318 else
319 *new_var = NULL_TREE;
320
321 if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
322 || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND)
323 array_ind_value = build_decl (location, VAR_DECL, NULL_TREE,
324 TREE_TYPE (func_parm));
325 array_op0 = (*array_operand)[0];
326 if (INDIRECT_REF_P (array_op0))
327 array_op0 = TREE_OPERAND (array_op0, 0);
328 switch (an_type)
329 {
330 case BUILT_IN_CILKPLUS_SEC_REDUCE_ADD:
331 new_var_init = build_modify_expr
332 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
333 location, build_zero_cst (new_var_type), new_var_type);
334 new_expr = build_modify_expr
335 (location, *new_var, TREE_TYPE (*new_var), PLUS_EXPR,
336 location, func_parm, TREE_TYPE (func_parm));
337 break;
338 case BUILT_IN_CILKPLUS_SEC_REDUCE_MUL:
339 new_var_init = build_modify_expr
340 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
341 location, build_one_cst (new_var_type), new_var_type);
342 new_expr = build_modify_expr
343 (location, *new_var, TREE_TYPE (*new_var), MULT_EXPR,
344 location, func_parm, TREE_TYPE (func_parm));
345 break;
346 case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_ZERO:
347 new_var_init = build_modify_expr
348 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
349 location, build_one_cst (new_var_type), new_var_type);
350 /* Initially you assume everything is zero, now if we find a case where
351 it is NOT true, then we set the result to false. Otherwise
352 we just keep the previous value. */
353 new_yes_expr = build_modify_expr
354 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
355 location, build_zero_cst (TREE_TYPE (*new_var)),
356 TREE_TYPE (*new_var));
357 new_no_expr = build_modify_expr
358 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
359 location, *new_var, TREE_TYPE (*new_var));
360 new_cond_expr = build2 (NE_EXPR, TREE_TYPE (func_parm), func_parm,
361 build_zero_cst (TREE_TYPE (func_parm)));
362 new_expr = build_conditional_expr
363 (location, new_cond_expr, false, new_yes_expr,
364 TREE_TYPE (new_yes_expr), new_no_expr, TREE_TYPE (new_no_expr));
365 break;
366 case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_NONZERO:
367 new_var_init = build_modify_expr
368 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
369 location, build_one_cst (new_var_type), new_var_type);
370 /* Initially you assume everything is non-zero, now if we find a case
371 where it is NOT true, then we set the result to false. Otherwise
372 we just keep the previous value. */
373 new_yes_expr = build_modify_expr
374 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
375 location, build_zero_cst (TREE_TYPE (*new_var)),
376 TREE_TYPE (*new_var));
377 new_no_expr = build_modify_expr
378 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
379 location, *new_var, TREE_TYPE (*new_var));
380 new_cond_expr = build2 (EQ_EXPR, TREE_TYPE (func_parm), func_parm,
381 build_zero_cst (TREE_TYPE (func_parm)));
382 new_expr = build_conditional_expr
383 (location, new_cond_expr, false, new_yes_expr,
384 TREE_TYPE (new_yes_expr), new_no_expr, TREE_TYPE (new_no_expr));
385 break;
386 case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO:
387 new_var_init = build_modify_expr
388 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
389 location, build_zero_cst (new_var_type), new_var_type);
390 /* Initially we assume there are NO zeros in the list. When we find
391 a non-zero, we keep the previous value. If we find a zero, we
392 set the value to true. */
393 new_yes_expr = build_modify_expr
394 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
395 location, build_one_cst (new_var_type), new_var_type);
396 new_no_expr = build_modify_expr
397 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
398 location, *new_var, TREE_TYPE (*new_var));
399 new_cond_expr = build2 (EQ_EXPR, TREE_TYPE (func_parm), func_parm,
400 build_zero_cst (TREE_TYPE (func_parm)));
401 new_expr = build_conditional_expr
402 (location, new_cond_expr, false, new_yes_expr,
403 TREE_TYPE (new_yes_expr), new_no_expr, TREE_TYPE (new_no_expr));
404 break;
405 case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_NONZERO:
406 new_var_init = build_modify_expr
407 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
408 location, build_zero_cst (new_var_type), new_var_type);
409 /* Initially we assume there are NO non-zeros in the list. When we find
410 a zero, we keep the previous value. If we find a non-zero, we set
411 the value to true. */
412 new_yes_expr = build_modify_expr
413 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
414 location, build_one_cst (new_var_type), new_var_type);
415 new_no_expr = build_modify_expr
416 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
417 location, *new_var, TREE_TYPE (*new_var));
418 new_cond_expr = build2 (NE_EXPR, TREE_TYPE (func_parm), func_parm,
419 build_zero_cst (TREE_TYPE (func_parm)));
420 new_expr = build_conditional_expr
421 (location, new_cond_expr, false, new_yes_expr,
422 TREE_TYPE (new_yes_expr), new_no_expr, TREE_TYPE (new_no_expr));
423 break;
424 case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX:
425 if (TYPE_MIN_VALUE (new_var_type))
426 new_var_init = build_modify_expr
427 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
428 location, TYPE_MIN_VALUE (new_var_type), new_var_type);
429 else
430 new_var_init = build_modify_expr
431 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
432 location, func_parm, new_var_type);
433 new_no_expr = build_modify_expr
434 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
435 location, *new_var, TREE_TYPE (*new_var));
436 new_yes_expr = build_modify_expr
437 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
438 location, func_parm, TREE_TYPE (*new_var));
439 new_expr = build_conditional_expr
440 (location,
441 build2 (LT_EXPR, TREE_TYPE (*new_var), *new_var, func_parm), false,
442 new_yes_expr, TREE_TYPE (*new_var), new_no_expr, TREE_TYPE (*new_var));
443 break;
444 case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN:
445 if (TYPE_MAX_VALUE (new_var_type))
446 new_var_init = build_modify_expr
447 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
448 location, TYPE_MAX_VALUE (new_var_type), new_var_type);
449 else
450 new_var_init = build_modify_expr
451 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
452 location, func_parm, new_var_type);
453 new_no_expr = build_modify_expr
454 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
455 location, *new_var, TREE_TYPE (*new_var));
456 new_yes_expr = build_modify_expr
457 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
458 location, func_parm, TREE_TYPE (*new_var));
459 new_expr = build_conditional_expr
460 (location,
461 build2 (GT_EXPR, TREE_TYPE (*new_var), *new_var, func_parm), false,
462 new_yes_expr, TREE_TYPE (*new_var), new_no_expr, TREE_TYPE (*new_var));
463 break;
464 case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND:
465 new_var_init = build_modify_expr
466 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
467 location, build_zero_cst (new_var_type), new_var_type);
468 new_exp_init = build_modify_expr
469 (location, array_ind_value, TREE_TYPE (array_ind_value),
470 NOP_EXPR, location, func_parm, TREE_TYPE (func_parm));
471 new_no_ind = build_modify_expr
472 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
473 location, *new_var, TREE_TYPE (*new_var));
474 new_no_expr = build_modify_expr
475 (location, array_ind_value, TREE_TYPE (array_ind_value),
476 NOP_EXPR,
477 location, array_ind_value, TREE_TYPE (array_ind_value));
478 if (list_size > 1)
479 {
480 new_yes_ind = build_modify_expr
481 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
482 location, an_loop_info[0].var, TREE_TYPE (an_loop_info[0].var));
483 new_yes_expr = build_modify_expr
484 (location, array_ind_value, TREE_TYPE (array_ind_value),
485 NOP_EXPR,
486 location, func_parm, TREE_TYPE ((*array_operand)[0]));
487 }
488 else
489 {
490 new_yes_ind = build_modify_expr
491 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
492 location, TREE_OPERAND (array_op0, 1),
493 TREE_TYPE (TREE_OPERAND (array_op0, 1)));
494 new_yes_expr = build_modify_expr
495 (location, array_ind_value, TREE_TYPE (array_ind_value),
496 NOP_EXPR,
497 location, func_parm, TREE_OPERAND (array_op0, 1));
498 }
499 new_yes_list = alloc_stmt_list ();
500 append_to_statement_list (new_yes_ind, &new_yes_list);
501 append_to_statement_list (new_yes_expr, &new_yes_list);
502
503 new_no_list = alloc_stmt_list ();
504 append_to_statement_list (new_no_ind, &new_no_list);
505 append_to_statement_list (new_no_expr, &new_no_list);
506
507 new_expr = build_conditional_expr
508 (location,
509 build2 (LE_EXPR, TREE_TYPE (array_ind_value), array_ind_value,
510 func_parm),
511 false,
512 new_yes_list, TREE_TYPE (*new_var), new_no_list, TREE_TYPE (*new_var));
513 break;
514 case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND:
515 new_var_init = build_modify_expr
516 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
517 location, build_zero_cst (new_var_type), new_var_type);
518 new_exp_init = build_modify_expr
519 (location, array_ind_value, TREE_TYPE (array_ind_value),
520 NOP_EXPR, location, func_parm, TREE_TYPE (func_parm));
521 new_no_ind = build_modify_expr
522 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
523 location, *new_var, TREE_TYPE (*new_var));
524 new_no_expr = build_modify_expr
525 (location, array_ind_value, TREE_TYPE (array_ind_value),
526 NOP_EXPR,
527 location, array_ind_value, TREE_TYPE (array_ind_value));
528 if (list_size > 1)
529 {
530 new_yes_ind = build_modify_expr
531 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
532 location, an_loop_info[0].var, TREE_TYPE (an_loop_info[0].var));
533 new_yes_expr = build_modify_expr
534 (location, array_ind_value, TREE_TYPE (array_ind_value),
535 NOP_EXPR,
536 location, func_parm, TREE_TYPE (array_op0));
537 }
538 else
539 {
540 new_yes_ind = build_modify_expr
541 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
542 location, TREE_OPERAND (array_op0, 1),
543 TREE_TYPE (TREE_OPERAND (array_op0, 1)));
544 new_yes_expr = build_modify_expr
545 (location, array_ind_value, TREE_TYPE (array_ind_value),
546 NOP_EXPR,
547 location, func_parm, TREE_OPERAND (array_op0, 1));
548 }
549 new_yes_list = alloc_stmt_list ();
550 append_to_statement_list (new_yes_ind, &new_yes_list);
551 append_to_statement_list (new_yes_expr, &new_yes_list);
552
553 new_no_list = alloc_stmt_list ();
554 append_to_statement_list (new_no_ind, &new_no_list);
555 append_to_statement_list (new_no_expr, &new_no_list);
556
557 new_expr = build_conditional_expr
558 (location,
559 build2 (GE_EXPR, TREE_TYPE (array_ind_value), array_ind_value,
560 func_parm),
561 false,
562 new_yes_list, TREE_TYPE (*new_var), new_no_list, TREE_TYPE (*new_var));
563 break;
564 case BUILT_IN_CILKPLUS_SEC_REDUCE:
565 new_var_init = build_modify_expr
566 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
567 location, identity_value, new_var_type);
568 new_call_expr = build_call_expr (call_fn, 2, *new_var, func_parm);
569 new_expr = build_modify_expr
570 (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
571 location, new_call_expr, TREE_TYPE (*new_var));
572 break;
573 case BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING:
574 new_expr = build_call_expr (call_fn, 2, identity_value, func_parm);
575 break;
576 default:
577 gcc_unreachable ();
578 break;
579 }
580
581 for (ii = 0; ii < rank; ii++)
582 append_to_statement_list (an_loop_info[ii].ind_init, &loop_init);
583
584 if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
585 || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND)
586 append_to_statement_list (new_exp_init, &loop_init);
587 if (an_type != BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING)
588 append_to_statement_list (new_var_init, &loop_init);
589
590 append_to_statement_list_force (loop_init, &loop_with_init);
591 body = new_expr;
592 for (ii = 0; ii < rank; ii++)
593 {
594 tree new_loop = push_stmt_list ();
595 c_finish_loop (location, an_loop_info[ii].cmp, an_loop_info[ii].incr,
596 body, NULL_TREE, NULL_TREE, true);
597 body = pop_stmt_list (new_loop);
598 }
599 append_to_statement_list_force (body, &loop_with_init);
600
601 an_info.release ();
602 an_loop_info.release ();
603
604 return loop_with_init;
605 }
606
607 /* Returns a loop with ARRAY_REF inside it with an appropriate modify expr.
608 The LHS and/or RHS will be array notation expressions that have a MODIFYCODE
609 Their locations are specified by LHS_LOC, RHS_LOC. The location of the
610 modify expression is location. The original type of LHS and RHS are passed
611 in LHS_ORIGTYPE and RHS_ORIGTYPE. */
612
613 tree
614 build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype,
615 enum tree_code modifycode, location_t rhs_loc,
616 tree rhs, tree rhs_origtype)
617 {
618 bool found_builtin_fn = false;
619 tree array_expr_lhs = NULL_TREE, array_expr_rhs = NULL_TREE;
620 tree array_expr = NULL_TREE;
621 tree an_init = NULL_TREE;
622 vec<tree> cond_expr = vNULL;
623 tree body, loop_with_init = alloc_stmt_list();
624 tree scalar_mods = NULL_TREE;
625 vec<tree, va_gc> *rhs_array_operand = NULL, *lhs_array_operand = NULL;
626 size_t lhs_rank = 0, rhs_rank = 0;
627 size_t ii = 0;
628 vec<tree, va_gc> *lhs_list = NULL, *rhs_list = NULL;
629 tree new_modify_expr, new_var = NULL_TREE, builtin_loop = NULL_TREE;
630 size_t rhs_list_size = 0, lhs_list_size = 0;
631 vec<vec<an_parts> > lhs_an_info = vNULL, rhs_an_info = vNULL;
632 vec<an_loop_parts> lhs_an_loop_info = vNULL, rhs_an_loop_info = vNULL;
633
634 /* If either of this is true, an error message must have been send out
635 already. Not necessary to send out multiple error messages. */
636 if (lhs == error_mark_node || rhs == error_mark_node)
637 return error_mark_node;
638
639 if (!find_rank (location, rhs, rhs, false, &rhs_rank))
640 return error_mark_node;
641
642 extract_array_notation_exprs (rhs, false, &rhs_list);
643 rhs_list_size = vec_safe_length (rhs_list);
644 an_init = push_stmt_list ();
645 if (rhs_rank)
646 {
647 scalar_mods = replace_invariant_exprs (&rhs);
648 if (scalar_mods)
649 add_stmt (scalar_mods);
650 }
651 for (ii = 0; ii < rhs_list_size; ii++)
652 {
653 tree rhs_node = (*rhs_list)[ii];
654 if (TREE_CODE (rhs_node) == CALL_EXPR)
655 {
656 builtin_loop = fix_builtin_array_notation_fn (rhs_node, &new_var);
657 if (builtin_loop == error_mark_node)
658 {
659 pop_stmt_list (an_init);
660 return error_mark_node;
661 }
662 else if (builtin_loop)
663 {
664 add_stmt (builtin_loop);
665 found_builtin_fn = true;
666 if (new_var)
667 {
668 vec<tree, va_gc> *rhs_sub_list = NULL, *new_var_list = NULL;
669 vec_safe_push (rhs_sub_list, rhs_node);
670 vec_safe_push (new_var_list, new_var);
671 replace_array_notations (&rhs, false, rhs_sub_list,
672 new_var_list);
673 }
674 }
675 }
676 }
677
678 lhs_rank = 0;
679 rhs_rank = 0;
680 if (!find_rank (location, lhs, lhs, true, &lhs_rank))
681 {
682 pop_stmt_list (an_init);
683 return error_mark_node;
684 }
685
686 if (!find_rank (location, rhs, rhs, true, &rhs_rank))
687 {
688 pop_stmt_list (an_init);
689 return error_mark_node;
690 }
691
692 if (lhs_rank == 0 && rhs_rank == 0)
693 {
694 if (found_builtin_fn)
695 {
696 new_modify_expr = build_modify_expr (location, lhs, lhs_origtype,
697 modifycode, rhs_loc, rhs,
698 rhs_origtype);
699 add_stmt (new_modify_expr);
700 pop_stmt_list (an_init);
701 return an_init;
702 }
703 else
704 {
705 pop_stmt_list (an_init);
706 return NULL_TREE;
707 }
708 }
709 rhs_list_size = 0;
710 rhs_list = NULL;
711 extract_array_notation_exprs (rhs, true, &rhs_list);
712 extract_array_notation_exprs (lhs, true, &lhs_list);
713 rhs_list_size = vec_safe_length (rhs_list);
714 lhs_list_size = vec_safe_length (lhs_list);
715
716 if (lhs_rank == 0 && rhs_rank != 0)
717 {
718 tree rhs_base = rhs;
719 if (TREE_CODE (rhs_base) == ARRAY_NOTATION_REF)
720 {
721 for (ii = 0; ii < (size_t) rhs_rank; ii++)
722 rhs_base = ARRAY_NOTATION_ARRAY (rhs);
723
724 error_at (location, "%qE cannot be scalar when %qE is not", lhs,
725 rhs_base);
726 return error_mark_node;
727 }
728 else
729 {
730 error_at (location, "%qE cannot be scalar when %qE is not", lhs,
731 rhs_base);
732 return error_mark_node;
733 }
734 }
735 if (lhs_rank != 0 && rhs_rank != 0 && lhs_rank != rhs_rank)
736 {
737 error_at (location, "rank mismatch between %qE and %qE", lhs, rhs);
738 pop_stmt_list (an_init);
739 return error_mark_node;
740 }
741
742 /* Here we assign the array notation components to variable so that we can
743 satisfy the exec once rule. */
744 for (ii = 0; ii < lhs_list_size; ii++)
745 {
746 tree array_node = (*lhs_list)[ii];
747 make_triplet_val_inv (location, &ARRAY_NOTATION_START (array_node));
748 make_triplet_val_inv (location, &ARRAY_NOTATION_LENGTH (array_node));
749 make_triplet_val_inv (location, &ARRAY_NOTATION_STRIDE (array_node));
750 }
751 for (ii = 0; ii < rhs_list_size; ii++)
752 if ((*rhs_list)[ii] && TREE_CODE ((*rhs_list)[ii]) == ARRAY_NOTATION_REF)
753 {
754 tree array_node = (*rhs_list)[ii];
755 make_triplet_val_inv (location, &ARRAY_NOTATION_START (array_node));
756 make_triplet_val_inv (location, &ARRAY_NOTATION_LENGTH (array_node));
757 make_triplet_val_inv (location, &ARRAY_NOTATION_STRIDE (array_node));
758 }
759
760 cond_expr.safe_grow_cleared (MAX (lhs_rank, rhs_rank));
761
762 lhs_an_loop_info.safe_grow_cleared (lhs_rank);
763 if (rhs_rank)
764 rhs_an_loop_info.safe_grow_cleared (rhs_rank);
765
766 cilkplus_extract_an_triplets (lhs_list, lhs_list_size, lhs_rank,
767 &lhs_an_info);
768 if (rhs_rank)
769 {
770 rhs_an_loop_info.safe_grow_cleared (rhs_rank);
771 cilkplus_extract_an_triplets (rhs_list, rhs_list_size, rhs_rank,
772 &rhs_an_info);
773 }
774 if (length_mismatch_in_expr_p (EXPR_LOCATION (lhs), lhs_an_info)
775 || (rhs_rank
776 && length_mismatch_in_expr_p (EXPR_LOCATION (rhs), rhs_an_info)))
777 {
778 pop_stmt_list (an_init);
779 return error_mark_node;
780 }
781 if (lhs_list_size > 0 && rhs_list_size > 0 && lhs_rank > 0 && rhs_rank > 0
782 && TREE_CODE (lhs_an_info[0][0].length) == INTEGER_CST
783 && rhs_an_info[0][0].length
784 && TREE_CODE (rhs_an_info[0][0].length) == INTEGER_CST)
785 {
786 HOST_WIDE_INT l_length = int_cst_value (lhs_an_info[0][0].length);
787 HOST_WIDE_INT r_length = int_cst_value (rhs_an_info[0][0].length);
788 /* Length can be negative or positive. As long as the magnitude is OK,
789 then the array notation is valid. */
790 if (absu_hwi (l_length) != absu_hwi (r_length))
791 {
792 error_at (location, "length mismatch between LHS and RHS");
793 pop_stmt_list (an_init);
794 return error_mark_node;
795 }
796 }
797 for (ii = 0; ii < lhs_rank; ii++)
798 if (lhs_an_info[0][ii].is_vector)
799 {
800 lhs_an_loop_info[ii].var = create_tmp_var (integer_type_node);
801 lhs_an_loop_info[ii].ind_init = build_modify_expr
802 (location, lhs_an_loop_info[ii].var,
803 TREE_TYPE (lhs_an_loop_info[ii].var), NOP_EXPR,
804 location, build_zero_cst (TREE_TYPE (lhs_an_loop_info[ii].var)),
805 TREE_TYPE (lhs_an_loop_info[ii].var));
806 }
807 for (ii = 0; ii < rhs_rank; ii++)
808 {
809 /* When we have a polynomial, we assume that the indices are of type
810 integer. */
811 rhs_an_loop_info[ii].var = create_tmp_var (integer_type_node);
812 rhs_an_loop_info[ii].ind_init = build_modify_expr
813 (location, rhs_an_loop_info[ii].var,
814 TREE_TYPE (rhs_an_loop_info[ii].var), NOP_EXPR,
815 location, build_int_cst (TREE_TYPE (rhs_an_loop_info[ii].var), 0),
816 TREE_TYPE (rhs_an_loop_info[ii].var));
817 }
818 if (lhs_rank)
819 {
820 lhs_array_operand = create_array_refs
821 (location, lhs_an_info, lhs_an_loop_info, lhs_list_size, lhs_rank);
822 replace_array_notations (&lhs, true, lhs_list, lhs_array_operand);
823 array_expr_lhs = lhs;
824 }
825 if (rhs_array_operand)
826 vec_safe_truncate (rhs_array_operand, 0);
827 if (rhs_rank)
828 {
829 rhs_array_operand = create_array_refs
830 (location, rhs_an_info, rhs_an_loop_info, rhs_list_size, rhs_rank);
831 replace_array_notations (&rhs, true, rhs_list, rhs_array_operand);
832 vec_safe_truncate (rhs_array_operand, 0);
833 rhs_array_operand = fix_sec_implicit_args (location, rhs_list,
834 rhs_an_loop_info, rhs_rank,
835 rhs);
836 if (!rhs_array_operand)
837 return error_mark_node;
838 replace_array_notations (&rhs, true, rhs_list, rhs_array_operand);
839 }
840 else if (rhs_list_size > 0)
841 {
842 rhs_array_operand = fix_sec_implicit_args (location, rhs_list,
843 lhs_an_loop_info, lhs_rank,
844 lhs);
845 if (!rhs_array_operand)
846 return error_mark_node;
847 replace_array_notations (&rhs, true, rhs_list, rhs_array_operand);
848 }
849 array_expr_lhs = lhs;
850 array_expr_rhs = rhs;
851 array_expr = build_modify_expr (location, array_expr_lhs, lhs_origtype,
852 modifycode, rhs_loc, array_expr_rhs,
853 rhs_origtype);
854 create_cmp_incr (location, &lhs_an_loop_info, lhs_rank, lhs_an_info);
855 if (rhs_rank)
856 create_cmp_incr (location, &rhs_an_loop_info, rhs_rank, rhs_an_info);
857
858 for (ii = 0; ii < MAX (lhs_rank, rhs_rank); ii++)
859 if (ii < lhs_rank && ii < rhs_rank)
860 cond_expr[ii] = build2 (TRUTH_ANDIF_EXPR, boolean_type_node,
861 lhs_an_loop_info[ii].cmp,
862 rhs_an_loop_info[ii].cmp);
863 else if (ii < lhs_rank && ii >= rhs_rank)
864 cond_expr[ii] = lhs_an_loop_info[ii].cmp;
865 else
866 gcc_unreachable ();
867
868 an_init = pop_stmt_list (an_init);
869 append_to_statement_list_force (an_init, &loop_with_init);
870 body = array_expr;
871 for (ii = 0; ii < MAX (lhs_rank, rhs_rank); ii++)
872 {
873 tree incr_list = alloc_stmt_list ();
874 tree new_loop = push_stmt_list ();
875 if (lhs_rank)
876 add_stmt (lhs_an_loop_info[ii].ind_init);
877 if (rhs_rank)
878 add_stmt (rhs_an_loop_info[ii].ind_init);
879 if (lhs_rank)
880 append_to_statement_list_force (lhs_an_loop_info[ii].incr, &incr_list);
881 if (rhs_rank && rhs_an_loop_info[ii].incr)
882 append_to_statement_list_force (rhs_an_loop_info[ii].incr, &incr_list);
883 c_finish_loop (location, cond_expr[ii], incr_list, body, NULL_TREE,
884 NULL_TREE, true);
885 body = pop_stmt_list (new_loop);
886 }
887 append_to_statement_list_force (body, &loop_with_init);
888
889 lhs_an_info.release ();
890 lhs_an_loop_info.release ();
891 if (rhs_rank)
892 {
893 rhs_an_info.release ();
894 rhs_an_loop_info.release ();
895 }
896 cond_expr.release ();
897 return loop_with_init;
898 }
899
900 /* Helper function for fix_conditional_array_notations. Encloses the
901 conditional statement passed in STMT with a loop around it
902 and replaces the condition in STMT with a ARRAY_REF tree-node to the array.
903 The condition must have an ARRAY_NOTATION_REF tree. An expansion of array
904 notation in STMT is returned in a STATEMENT_LIST. */
905
906 static tree
907 fix_conditional_array_notations_1 (tree stmt)
908 {
909 vec<tree, va_gc> *array_list = NULL, *array_operand = NULL;
910 size_t list_size = 0;
911 tree cond = NULL_TREE, builtin_loop = NULL_TREE, new_var = NULL_TREE;
912 size_t rank = 0, ii = 0;
913 tree loop_init;
914 location_t location = EXPR_LOCATION (stmt);
915 tree body = NULL_TREE, loop_with_init = alloc_stmt_list ();
916 vec<vec<an_parts> > an_info = vNULL;
917 vec<an_loop_parts> an_loop_info = vNULL;
918
919 if (TREE_CODE (stmt) == COND_EXPR)
920 cond = COND_EXPR_COND (stmt);
921 else if (TREE_CODE (stmt) == SWITCH_EXPR)
922 cond = SWITCH_COND (stmt);
923 else if (truth_value_p (TREE_CODE (stmt)))
924 cond = TREE_OPERAND (stmt, 0);
925 else
926 /* Otherwise dont even touch the statement. */
927 return stmt;
928
929 if (!find_rank (location, cond, cond, false, &rank))
930 return error_mark_node;
931
932 extract_array_notation_exprs (stmt, false, &array_list);
933 loop_init = push_stmt_list ();
934 for (ii = 0; ii < vec_safe_length (array_list); ii++)
935 {
936 tree array_node = (*array_list)[ii];
937 if (TREE_CODE (array_node) == CALL_EXPR)
938 {
939 builtin_loop = fix_builtin_array_notation_fn (array_node, &new_var);
940 if (builtin_loop == error_mark_node)
941 {
942 add_stmt (error_mark_node);
943 pop_stmt_list (loop_init);
944 return loop_init;
945 }
946 else if (builtin_loop)
947 {
948 vec <tree, va_gc>* sub_list = NULL, *new_var_list = NULL;
949 vec_safe_push (sub_list, array_node);
950 vec_safe_push (new_var_list, new_var);
951 add_stmt (builtin_loop);
952 replace_array_notations (&stmt, false, sub_list, new_var_list);
953 }
954 }
955 }
956 if (!find_rank (location, stmt, stmt, true, &rank))
957 {
958 pop_stmt_list (loop_init);
959 return error_mark_node;
960 }
961 if (rank == 0)
962 {
963 add_stmt (stmt);
964 pop_stmt_list (loop_init);
965 return loop_init;
966 }
967 extract_array_notation_exprs (stmt, true, &array_list);
968
969 if (vec_safe_length (array_list) == 0)
970 return stmt;
971
972 list_size = vec_safe_length (array_list);
973 an_loop_info.safe_grow_cleared (rank);
974
975 for (ii = 0; ii < list_size; ii++)
976 if ((*array_list)[ii]
977 && TREE_CODE ((*array_list)[ii]) == ARRAY_NOTATION_REF)
978 {
979 tree array_node = (*array_list)[ii];
980 make_triplet_val_inv (location, &ARRAY_NOTATION_START (array_node));
981 make_triplet_val_inv (location, &ARRAY_NOTATION_LENGTH (array_node));
982 make_triplet_val_inv (location, &ARRAY_NOTATION_STRIDE (array_node));
983 }
984 cilkplus_extract_an_triplets (array_list, list_size, rank, &an_info);
985 for (ii = 0; ii < rank; ii++)
986 {
987 an_loop_info[ii].var = create_tmp_var (integer_type_node);
988 an_loop_info[ii].ind_init =
989 build_modify_expr (location, an_loop_info[ii].var,
990 TREE_TYPE (an_loop_info[ii].var), NOP_EXPR,
991 location,
992 build_int_cst (TREE_TYPE (an_loop_info[ii].var), 0),
993 TREE_TYPE (an_loop_info[ii].var));
994 }
995 array_operand = create_array_refs (location, an_info, an_loop_info,
996 list_size, rank);
997 replace_array_notations (&stmt, true, array_list, array_operand);
998 create_cmp_incr (location, &an_loop_info, rank, an_info);
999
1000 loop_init = pop_stmt_list (loop_init);
1001 body = stmt;
1002 append_to_statement_list_force (loop_init, &loop_with_init);
1003
1004 for (ii = 0; ii < rank; ii++)
1005 {
1006 tree new_loop = push_stmt_list ();
1007 add_stmt (an_loop_info[ii].ind_init);
1008 c_finish_loop (location, an_loop_info[ii].cmp, an_loop_info[ii].incr,
1009 body, NULL_TREE, NULL_TREE, true);
1010 body = pop_stmt_list (new_loop);
1011 }
1012 append_to_statement_list_force (body, &loop_with_init);
1013
1014 an_loop_info.release ();
1015 an_info.release ();
1016
1017 return loop_with_init;
1018 }
1019
1020 /* Top-level function to replace ARRAY_NOTATION_REF in a conditional statement
1021 in STMT. An expansion of array notation in STMT is returned as a
1022 STATEMENT_LIST. */
1023
1024 tree
1025 fix_conditional_array_notations (tree stmt)
1026 {
1027 if (TREE_CODE (stmt) == STATEMENT_LIST)
1028 {
1029 tree_stmt_iterator tsi;
1030 for (tsi = tsi_start (stmt); !tsi_end_p (tsi); tsi_next (&tsi))
1031 {
1032 tree single_stmt = *tsi_stmt_ptr (tsi);
1033 *tsi_stmt_ptr (tsi) =
1034 fix_conditional_array_notations_1 (single_stmt);
1035 }
1036 return stmt;
1037 }
1038 else
1039 return fix_conditional_array_notations_1 (stmt);
1040 }
1041
1042 /* Create a struct c_expr that contains a loop with ARRAY_REF expr at location
1043 LOCATION with the tree_code CODE and the array notation expr is
1044 passed in ARG. Returns the fixed c_expr in ARG itself. */
1045
1046 struct c_expr
1047 fix_array_notation_expr (location_t location, enum tree_code code,
1048 struct c_expr arg)
1049 {
1050
1051 vec<tree, va_gc> *array_list = NULL, *array_operand = NULL;
1052 size_t list_size = 0, rank = 0, ii = 0;
1053 tree loop_init;
1054 tree body, loop_with_init = alloc_stmt_list ();
1055 vec<vec<an_parts> > an_info = vNULL;
1056 vec<an_loop_parts> an_loop_info = vNULL;
1057
1058 if (!find_rank (location, arg.value, arg.value, false, &rank))
1059 {
1060 /* If this function returns a NULL, we convert the tree value in the
1061 structure to error_mark_node and the parser should take care of the
1062 rest. */
1063 arg.value = error_mark_node;
1064 return arg;
1065 }
1066
1067 if (rank == 0)
1068 return arg;
1069
1070 extract_array_notation_exprs (arg.value, true, &array_list);
1071
1072 if (vec_safe_length (array_list) == 0)
1073 return arg;
1074
1075 list_size = vec_safe_length (array_list);
1076
1077 an_loop_info.safe_grow_cleared (rank);
1078 cilkplus_extract_an_triplets (array_list, list_size, rank, &an_info);
1079
1080 loop_init = push_stmt_list ();
1081 for (ii = 0; ii < rank; ii++)
1082 {
1083 an_loop_info[ii].var = create_tmp_var (integer_type_node);
1084 an_loop_info[ii].ind_init =
1085 build_modify_expr (location, an_loop_info[ii].var,
1086 TREE_TYPE (an_loop_info[ii].var), NOP_EXPR,
1087 location,
1088 build_int_cst (TREE_TYPE (an_loop_info[ii].var), 0),
1089 TREE_TYPE (an_loop_info[ii].var));;
1090
1091 }
1092 array_operand = create_array_refs (location, an_info, an_loop_info,
1093 list_size, rank);
1094 replace_array_notations (&arg.value, true, array_list, array_operand);
1095 create_cmp_incr (location, &an_loop_info, rank, an_info);
1096
1097 arg = default_function_array_read_conversion (location, arg);
1098 if (code == POSTINCREMENT_EXPR || code == POSTDECREMENT_EXPR)
1099 arg.value = build_unary_op (location, code, arg.value, 0);
1100 else if (code == PREINCREMENT_EXPR || code == PREDECREMENT_EXPR)
1101 arg = parser_build_unary_op (location, code, arg);
1102
1103 loop_init = pop_stmt_list (loop_init);
1104 append_to_statement_list_force (loop_init, &loop_with_init);
1105 body = arg.value;
1106
1107 for (ii = 0; ii < rank; ii++)
1108 {
1109 tree new_loop = push_stmt_list ();
1110 add_stmt (an_loop_info[ii].ind_init);
1111 c_finish_loop (location, an_loop_info[ii].cmp,
1112 an_loop_info[ii].incr, body, NULL_TREE,
1113 NULL_TREE, true);
1114 body = pop_stmt_list (new_loop);
1115 }
1116 append_to_statement_list_force (body, &loop_with_init);
1117 arg.value = loop_with_init;
1118 an_info.release ();
1119 an_loop_info.release ();
1120 return arg;
1121 }
1122
1123 /* Replaces array notations in a void function call arguments in ARG and returns
1124 a STATEMENT_LIST. */
1125
1126 static tree
1127 fix_array_notation_call_expr (tree arg)
1128 {
1129 vec<tree, va_gc> *array_list = NULL, *array_operand = NULL;
1130 tree new_var = NULL_TREE;
1131 size_t list_size = 0, rank = 0, ii = 0;
1132 tree loop_init;
1133 tree body, loop_with_init = alloc_stmt_list ();
1134 location_t location = UNKNOWN_LOCATION;
1135 vec<vec<an_parts> > an_info = vNULL;
1136 vec<an_loop_parts> an_loop_info = vNULL;
1137
1138 if (TREE_CODE (arg) == CALL_EXPR
1139 && is_cilkplus_reduce_builtin (CALL_EXPR_FN (arg)))
1140 {
1141 loop_init = fix_builtin_array_notation_fn (arg, &new_var);
1142 /* We are ignoring the new var because either the user does not want to
1143 capture it OR he is using sec_reduce_mutating function. */
1144 return loop_init;
1145 }
1146 if (!find_rank (location, arg, arg, false, &rank))
1147 return error_mark_node;
1148
1149 if (rank == 0)
1150 return arg;
1151
1152 extract_array_notation_exprs (arg, true, &array_list);
1153 if (vec_safe_length (array_list) == 0)
1154 return arg;
1155
1156 list_size = vec_safe_length (array_list);
1157 location = EXPR_LOCATION (arg);
1158 an_loop_info.safe_grow_cleared (rank);
1159
1160 loop_init = push_stmt_list ();
1161 for (ii = 0; ii < list_size; ii++)
1162 if ((*array_list)[ii]
1163 && TREE_CODE ((*array_list)[ii]) == ARRAY_NOTATION_REF)
1164 {
1165 tree array_node = (*array_list)[ii];
1166 make_triplet_val_inv (location, &ARRAY_NOTATION_START (array_node));
1167 make_triplet_val_inv (location, &ARRAY_NOTATION_LENGTH (array_node));
1168 make_triplet_val_inv (location, &ARRAY_NOTATION_STRIDE (array_node));
1169 }
1170 cilkplus_extract_an_triplets (array_list, list_size, rank, &an_info);
1171 if (length_mismatch_in_expr_p (location, an_info))
1172 {
1173 pop_stmt_list (loop_init);
1174 return error_mark_node;
1175 }
1176 for (ii = 0; ii < rank; ii++)
1177 {
1178 an_loop_info[ii].var = create_tmp_var (integer_type_node);
1179 an_loop_info[ii].ind_init =
1180 build_modify_expr (location, an_loop_info[ii].var,
1181 TREE_TYPE (an_loop_info[ii].var), NOP_EXPR, location,
1182 build_int_cst (TREE_TYPE (an_loop_info[ii].var), 0),
1183 TREE_TYPE (an_loop_info[ii].var));
1184
1185 }
1186 array_operand = create_array_refs (location, an_info, an_loop_info,
1187 list_size, rank);
1188 replace_array_notations (&arg, true, array_list, array_operand);
1189 create_cmp_incr (location, &an_loop_info, rank, an_info);
1190 loop_init = pop_stmt_list (loop_init);
1191 append_to_statement_list_force (loop_init, &loop_with_init);
1192 body = arg;
1193 for (ii = 0; ii < rank; ii++)
1194 {
1195 tree new_loop = push_stmt_list ();
1196 add_stmt (an_loop_info[ii].ind_init);
1197 c_finish_loop (location, an_loop_info[ii].cmp, an_loop_info[ii].incr,
1198 body, NULL_TREE, NULL_TREE, true);
1199 body = pop_stmt_list (new_loop);
1200 }
1201 append_to_statement_list_force (body, &loop_with_init);
1202 an_loop_info.release ();
1203 an_info.release ();
1204 return loop_with_init;
1205 }
1206
1207 /* Expands the built-in functions in a return. EXPR is a RETURN_EXPR with
1208 a built-in reduction function. This function returns the expansion code for
1209 the built-in function. */
1210
1211 static tree
1212 fix_return_expr (tree expr)
1213 {
1214 tree new_mod_list, new_var, new_mod, retval_expr, retval_type;
1215 location_t loc = EXPR_LOCATION (expr);
1216
1217 new_mod_list = alloc_stmt_list ();
1218 retval_expr = TREE_OPERAND (expr, 0);
1219 retval_type = TREE_TYPE (TREE_OPERAND (retval_expr, 1));
1220 new_var = build_decl (loc, VAR_DECL, NULL_TREE, TREE_TYPE (retval_expr));
1221 new_mod = build_array_notation_expr (loc, new_var, TREE_TYPE (new_var),
1222 NOP_EXPR, loc,
1223 TREE_OPERAND (retval_expr, 1),
1224 retval_type);
1225 TREE_OPERAND (retval_expr, 1) = new_var;
1226 TREE_OPERAND (expr, 0) = retval_expr;
1227 append_to_statement_list_force (new_mod, &new_mod_list);
1228 append_to_statement_list_force (expr, &new_mod_list);
1229 return new_mod_list;
1230 }
1231
1232 /* Callback for walk_tree. Expands all array notations in *TP. *WALK_SUBTREES
1233 is set to 1 unless *TP contains no array notation expressions. */
1234
1235 static tree
1236 expand_array_notations (tree *tp, int *walk_subtrees, void *)
1237 {
1238 if (!contains_array_notation_expr (*tp))
1239 {
1240 *walk_subtrees = 0;
1241 return NULL_TREE;
1242 }
1243 *walk_subtrees = 1;
1244
1245 switch (TREE_CODE (*tp))
1246 {
1247 case TRUTH_ORIF_EXPR:
1248 case TRUTH_ANDIF_EXPR:
1249 case TRUTH_OR_EXPR:
1250 case TRUTH_AND_EXPR:
1251 case TRUTH_XOR_EXPR:
1252 case TRUTH_NOT_EXPR:
1253 case COND_EXPR:
1254 *tp = fix_conditional_array_notations (*tp);
1255 break;
1256 case MODIFY_EXPR:
1257 {
1258 location_t loc = EXPR_HAS_LOCATION (*tp) ? EXPR_LOCATION (*tp) :
1259 UNKNOWN_LOCATION;
1260 tree lhs = TREE_OPERAND (*tp, 0);
1261 tree rhs = TREE_OPERAND (*tp, 1);
1262 location_t rhs_loc = EXPR_HAS_LOCATION (rhs) ? EXPR_LOCATION (rhs) :
1263 UNKNOWN_LOCATION;
1264 *tp = build_array_notation_expr (loc, lhs, TREE_TYPE (lhs), NOP_EXPR,
1265 rhs_loc, rhs, TREE_TYPE (rhs));
1266 }
1267 break;
1268 case DECL_EXPR:
1269 {
1270 tree x = DECL_EXPR_DECL (*tp);
1271 if (DECL_INITIAL (x))
1272 {
1273 location_t loc = DECL_SOURCE_LOCATION (x);
1274 tree lhs = x;
1275 tree rhs = DECL_INITIAL (x);
1276 DECL_INITIAL (x) = NULL;
1277 tree new_modify_expr = build_modify_expr (loc, lhs,
1278 TREE_TYPE (lhs),
1279 NOP_EXPR,
1280 loc, rhs,
1281 TREE_TYPE(rhs));
1282 expand_array_notations (&new_modify_expr, walk_subtrees, NULL);
1283 *tp = new_modify_expr;
1284 }
1285 }
1286 break;
1287 case CALL_EXPR:
1288 *tp = fix_array_notation_call_expr (*tp);
1289 break;
1290 case RETURN_EXPR:
1291 *tp = fix_return_expr (*tp);
1292 break;
1293 case COMPOUND_EXPR:
1294 if (TREE_CODE (TREE_OPERAND (*tp, 0)) == SAVE_EXPR)
1295 {
1296 /* In here we are calling expand_array_notations because
1297 we need to be able to catch the return value and check if
1298 it is an error_mark_node. */
1299 expand_array_notations (&TREE_OPERAND (*tp, 1), walk_subtrees, NULL);
1300
1301 /* SAVE_EXPR cannot have an error_mark_node inside it. This check
1302 will make sure that if there is an error in expanding of
1303 array notations (e.g. rank mismatch) then replace the entire
1304 SAVE_EXPR with an error_mark_node. */
1305 if (TREE_OPERAND (*tp, 1) == error_mark_node)
1306 *tp = error_mark_node;
1307 }
1308 break;
1309 case ARRAY_NOTATION_REF:
1310 /* If we are here, then we are dealing with cases like this:
1311 A[:];
1312 A[x:y:z];
1313 A[x:y];
1314 Replace those with just void zero node. */
1315 *tp = void_node;
1316 default:
1317 break;
1318 }
1319 return NULL_TREE;
1320 }
1321
1322 /* Walks through tree node T and expands all array notations in its subtrees.
1323 The return value is the same type as T but with all array notations
1324 replaced with appropriate ARRAY_REFS with a loop around it. */
1325
1326 tree
1327 expand_array_notation_exprs (tree t)
1328 {
1329 walk_tree (&t, expand_array_notations, NULL, NULL);
1330 return t;
1331 }
1332
1333 /* This handles expression of the form "a[i:j:k]" or "a[:]" or "a[i:j]," which
1334 denotes an array notation expression. If a is a variable or a member, then
1335 we generate a ARRAY_NOTATION_REF front-end tree and return it.
1336 This tree is broken down to ARRAY_REF toward the end of parsing.
1337 ARRAY_NOTATION_REF tree holds the START_INDEX, LENGTH, STRIDE and the TYPE
1338 of ARRAY_REF. Restrictions on START_INDEX, LENGTH and STRIDE is same as that
1339 of the index field passed into ARRAY_REF. The only additional restriction
1340 is that, unlike index in ARRAY_REF, stride, length and start_index cannot
1341 contain ARRAY_NOTATIONS. */
1342
1343 tree
1344 build_array_notation_ref (location_t loc, tree array, tree start_index,
1345 tree length, tree stride, tree type)
1346 {
1347 tree array_ntn_tree = NULL_TREE;
1348 size_t stride_rank = 0, length_rank = 0, start_rank = 0;
1349
1350 if (!INTEGRAL_TYPE_P (TREE_TYPE (start_index)))
1351 {
1352 error_at (loc,
1353 "start-index of array notation triplet is not an integer");
1354 return error_mark_node;
1355 }
1356 if (!INTEGRAL_TYPE_P (TREE_TYPE (length)))
1357 {
1358 error_at (loc, "length of array notation triplet is not an integer");
1359 return error_mark_node;
1360 }
1361
1362 /* The stride is an optional field. */
1363 if (stride && !INTEGRAL_TYPE_P (TREE_TYPE (stride)))
1364 {
1365 error_at (loc, "stride of array notation triplet is not an integer");
1366 return error_mark_node;
1367 }
1368 if (!stride)
1369 {
1370 if (TREE_CONSTANT (start_index) && TREE_CONSTANT (length)
1371 && tree_int_cst_lt (length, start_index))
1372 stride = build_int_cst (TREE_TYPE (start_index), -1);
1373 else
1374 stride = build_int_cst (TREE_TYPE (start_index), 1);
1375 }
1376
1377 if (!find_rank (loc, start_index, start_index, false, &start_rank))
1378 return error_mark_node;
1379 if (!find_rank (loc, length, length, false, &length_rank))
1380 return error_mark_node;
1381 if (!find_rank (loc, stride, stride, false, &stride_rank))
1382 return error_mark_node;
1383
1384 if (start_rank != 0)
1385 {
1386 error_at (loc, "rank of an array notation triplet's start-index is not "
1387 "zero");
1388 return error_mark_node;
1389 }
1390 if (length_rank != 0)
1391 {
1392 error_at (loc, "rank of an array notation triplet's length is not zero");
1393 return error_mark_node;
1394 }
1395 if (stride_rank != 0)
1396 {
1397 error_at (loc, "rank of array notation triplet's stride is not zero");
1398 return error_mark_node;
1399 }
1400 array_ntn_tree = build4 (ARRAY_NOTATION_REF, NULL_TREE, NULL_TREE, NULL_TREE,
1401 NULL_TREE, NULL_TREE);
1402 ARRAY_NOTATION_ARRAY (array_ntn_tree) = array;
1403 ARRAY_NOTATION_START (array_ntn_tree) = start_index;
1404 ARRAY_NOTATION_LENGTH (array_ntn_tree) = length;
1405 ARRAY_NOTATION_STRIDE (array_ntn_tree) = stride;
1406 TREE_TYPE (array_ntn_tree) = type;
1407
1408 return array_ntn_tree;
1409 }