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