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