Import pre-release gcc-5.0 to new vendor branch
[dragonfly.git] / contrib / gcc-5.0 / 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 "double-int.h"
77 #include "machmode.h"
78 #include "flags.h"
79 #include "inchash.h"
80 #include "tree.h"
81 #include "c-tree.h"
82 #include "gimple-expr.h"
83 #include "tree-iterator.h"
84 #include "opts.h"
85 #include "c-family/c-common.h"
86
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
90 static inline void
91 make_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
111 static void
112 create_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
136 static vec<tree, va_gc> *
137 create_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   
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
168 tree
169 replace_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;
178   data.additional_tcodes = NULL;
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
206 static tree
207 fix_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;
214   size_t list_size = 0, rank = 0, ii = 0;
215   tree loop_init, array_op0;
216   tree identity_value = NULL_TREE, call_fn = NULL_TREE, new_call_expr, body;
217   location_t location = UNKNOWN_LOCATION;
218   tree loop_with_init = alloc_stmt_list ();
219   vec<vec<an_parts> > an_info = vNULL;
220   vec<an_loop_parts> an_loop_info = vNULL;
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
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
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);
237       if (TREE_CODE (call_fn) == ADDR_EXPR)
238         call_fn = TREE_OPERAND (call_fn, 0);
239       identity_value = CALL_EXPR_ARG (an_builtin_fn, 0);
240       func_parm = CALL_EXPR_ARG (an_builtin_fn, 1);
241     }
242   else
243     func_parm = CALL_EXPR_ARG (an_builtin_fn, 0);
244   
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);
248   if (func_parm == error_mark_node)
249     return error_mark_node;
250   
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)
257     {
258       error_at (location, "Invalid builtin arguments");
259       return error_mark_node;
260     }
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     }
300
301   an_loop_info.safe_grow_cleared (rank);
302   cilkplus_extract_an_triplets (array_list, list_size, rank, &an_info);
303   loop_init = alloc_stmt_list ();
304
305   for (ii = 0; ii < rank; ii++)
306     {
307       an_loop_info[ii].var = create_tmp_var (integer_type_node);
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,
311                            location,
312                            build_int_cst (TREE_TYPE (an_loop_info[ii].var), 0),
313                            TREE_TYPE (an_loop_info[ii].var));   
314     }
315   array_operand = create_array_refs (location, an_info, an_loop_info,
316                                      list_size, rank);
317   replace_array_notations (&func_parm, true, array_list, array_operand);
318
319   create_cmp_incr (location, &an_loop_info, rank, an_info);
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));
332   array_op0 = (*array_operand)[0];
333   if (TREE_CODE (array_op0) == INDIRECT_REF)
334     array_op0 = TREE_OPERAND (array_op0, 0);
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,
489              location, an_loop_info[0].var, TREE_TYPE (an_loop_info[0].var));
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,
539              location, an_loop_info[0].var, TREE_TYPE (an_loop_info[0].var));
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++)
589     append_to_statement_list (an_loop_info[ii].ind_init, &loop_init);
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 ();
602       c_finish_loop (location, an_loop_info[ii].cmp, an_loop_info[ii].incr,
603                      body, NULL_TREE, NULL_TREE, true);
604       body = pop_stmt_list (new_loop);
605     }
606   append_to_statement_list_force (body, &loop_with_init);
607
608   an_info.release ();
609   an_loop_info.release ();
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
620 tree
621 build_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 {
625   bool found_builtin_fn = false;
626   tree array_expr_lhs = NULL_TREE, array_expr_rhs = NULL_TREE;
627   tree array_expr = NULL_TREE;
628   tree an_init = NULL_TREE;
629   vec<tree> cond_expr = vNULL;
630   tree body, loop_with_init = alloc_stmt_list();
631   tree scalar_mods = NULL_TREE;
632   vec<tree, va_gc> *rhs_array_operand = NULL, *lhs_array_operand = NULL;
633   size_t lhs_rank = 0, rhs_rank = 0;
634   size_t ii = 0;
635   vec<tree, va_gc> *lhs_list = NULL, *rhs_list = NULL;
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   
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   
723   if (lhs_rank == 0 && rhs_rank != 0)
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     {
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++)
752     { 
753       tree array_node = (*lhs_list)[ii];
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));
757     }
758   for (ii = 0; ii < rhs_list_size; ii++)
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       }
766   
767   cond_expr.safe_grow_cleared (MAX (lhs_rank, rhs_rank));
768
769   lhs_an_loop_info.safe_grow_cleared (lhs_rank);
770   if (rhs_rank)
771     rhs_an_loop_info.safe_grow_cleared (rhs_rank);
772
773   cilkplus_extract_an_triplets (lhs_list, lhs_list_size, lhs_rank,
774                                 &lhs_an_info);
775   if (rhs_rank)
776     {
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);
780     }
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)))
784     {
785       pop_stmt_list (an_init);
786       return error_mark_node;
787     }
788   if (lhs_list_size > 0 && rhs_list_size > 0 && lhs_rank > 0 && rhs_rank > 0
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)
792     {
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);
795       /* Length can be negative or positive.  As long as the magnitude is OK,
796          then the array notation is valid.  */
797       if (absu_hwi (l_length) != absu_hwi (r_length))
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++)
805     if (lhs_an_info[0][ii].is_vector)
806       {
807         lhs_an_loop_info[ii].var = create_tmp_var (integer_type_node);
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       }
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.  */
818       rhs_an_loop_info[ii].var = create_tmp_var (integer_type_node);
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));
824     }
825   if (lhs_rank)
826     {
827       lhs_array_operand = create_array_refs
828         (location, lhs_an_info, lhs_an_loop_info, lhs_list_size, lhs_rank);
829       replace_array_notations (&lhs, true, lhs_list, lhs_array_operand);
830       array_expr_lhs = lhs;
831     }
832   if (rhs_array_operand)
833     vec_safe_truncate (rhs_array_operand, 0);
834   if (rhs_rank)
835     {
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;
845       replace_array_notations (&rhs, true, rhs_list, rhs_array_operand);
846     }
847   else if (rhs_list_size > 0)
848     {
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;
854       replace_array_notations (&rhs, true, rhs_list, rhs_array_operand);
855     }
856   array_expr_lhs = lhs;
857   array_expr_rhs = rhs;
858   array_expr = build_modify_expr (location, array_expr_lhs, lhs_origtype, 
859                                   modifycode, rhs_loc, array_expr_rhs, 
860                                   rhs_origtype);
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 ();
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)
883         add_stmt (lhs_an_loop_info[ii].ind_init);
884       if (rhs_rank)
885         add_stmt (rhs_an_loop_info[ii].ind_init);
886       if (lhs_rank)
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);
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);
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 ();
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
913 static tree
914 fix_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;
919   size_t rank = 0, ii = 0;
920   tree loop_init;
921   location_t location = EXPR_LOCATION (stmt);
922   tree body = NULL_TREE, loop_with_init = alloc_stmt_list ();
923   vec<vec<an_parts> > an_info = vNULL;
924   vec<an_loop_parts> an_loop_info = vNULL;
925  
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);
930   else if (truth_value_p (TREE_CODE (stmt)))
931     cond = TREE_OPERAND (stmt, 0);
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   
939   extract_array_notation_exprs (stmt, false, &array_list);
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);
959               replace_array_notations (&stmt, false, sub_list, new_var_list); 
960             }
961         }
962     }
963   if (!find_rank (location, stmt, stmt, true, &rank))
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     }  
974   extract_array_notation_exprs (stmt, true, &array_list);
975
976   if (vec_safe_length (array_list) == 0)
977     return stmt;
978
979   list_size = vec_safe_length (array_list);
980   an_loop_info.safe_grow_cleared (rank);
981   
982   for (ii = 0; ii < list_size; ii++)
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);
992   for (ii = 0; ii < rank; ii++)
993     {
994       an_loop_info[ii].var = create_tmp_var (integer_type_node);
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,
998                            location,
999                            build_int_cst (TREE_TYPE (an_loop_info[ii].var), 0),
1000                            TREE_TYPE (an_loop_info[ii].var));
1001     }
1002   array_operand = create_array_refs (location, an_info, an_loop_info,
1003                                      list_size, rank);
1004   replace_array_notations (&stmt, true, array_list, array_operand);
1005   create_cmp_incr (location, &an_loop_info, rank, an_info);
1006   
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 ();
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);
1017       body = pop_stmt_list (new_loop);
1018     }
1019   append_to_statement_list_force (body, &loop_with_init);
1020
1021   an_loop_info.release ();
1022   an_info.release ();
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
1031 tree
1032 fix_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
1053 struct c_expr 
1054 fix_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;
1059   size_t list_size = 0, rank = 0, ii = 0;
1060   tree loop_init;
1061   tree body, loop_with_init = alloc_stmt_list ();
1062   vec<vec<an_parts> > an_info = vNULL;
1063   vec<an_loop_parts> an_loop_info = vNULL;
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);
1083
1084   an_loop_info.safe_grow_cleared (rank);
1085   cilkplus_extract_an_triplets (array_list, list_size, rank, &an_info);
1086   
1087   loop_init = push_stmt_list ();
1088   for (ii = 0; ii < rank; ii++)
1089     {
1090       an_loop_info[ii].var = create_tmp_var (integer_type_node);
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,
1094                            location,
1095                            build_int_cst (TREE_TYPE (an_loop_info[ii].var), 0),
1096                            TREE_TYPE (an_loop_info[ii].var));;
1097         
1098     }
1099   array_operand = create_array_refs (location, an_info, an_loop_info,
1100                                      list_size, rank);
1101   replace_array_notations (&arg.value, true, array_list, array_operand);
1102   create_cmp_incr (location, &an_loop_info, rank, an_info);
1103
1104   arg = default_function_array_read_conversion (location, arg);
1105   if (code == POSTINCREMENT_EXPR || code == POSTDECREMENT_EXPR)
1106     arg.value = build_unary_op (location, code, arg.value, 0);
1107   else if (code == PREINCREMENT_EXPR || code == PREDECREMENT_EXPR)
1108     arg = parser_build_unary_op (location, code, arg);
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 ();
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,
1120                      NULL_TREE, true);
1121       body = pop_stmt_list (new_loop);
1122     }
1123   append_to_statement_list_force (body, &loop_with_init);
1124   arg.value = loop_with_init;
1125   an_info.release ();
1126   an_loop_info.release ();
1127   return arg;
1128 }
1129
1130 /* Replaces array notations in a void function call arguments in ARG and returns
1131    a STATEMENT_LIST.  */
1132
1133 static tree
1134 fix_array_notation_call_expr (tree arg)
1135 {
1136   vec<tree, va_gc> *array_list = NULL, *array_operand = NULL;
1137   tree new_var = NULL_TREE;
1138   size_t list_size = 0, rank = 0, ii = 0;
1139   tree loop_init;
1140   tree body, loop_with_init = alloc_stmt_list ();
1141   location_t location = UNKNOWN_LOCATION;
1142   vec<vec<an_parts> > an_info = vNULL;
1143   vec<an_loop_parts> an_loop_info = vNULL;
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;
1152     }  
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);
1165   an_loop_info.safe_grow_cleared (rank);
1166   
1167   loop_init = push_stmt_list ();
1168   for (ii = 0; ii < list_size; ii++)
1169     if ((*array_list)[ii]
1170         && TREE_CODE ((*array_list)[ii]) == ARRAY_NOTATION_REF)
1171         {
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));
1176         }
1177   cilkplus_extract_an_triplets (array_list, list_size, rank, &an_info);
1178   if (length_mismatch_in_expr_p (location, an_info))
1179     {
1180       pop_stmt_list (loop_init);
1181       return error_mark_node;
1182     }
1183   for (ii = 0; ii < rank; ii++)
1184     {
1185       an_loop_info[ii].var = create_tmp_var (integer_type_node);
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));
1191         
1192     }
1193   array_operand = create_array_refs (location, an_info, an_loop_info,
1194                                      list_size, rank);
1195   replace_array_notations (&arg, true, array_list, array_operand);
1196   create_cmp_incr (location, &an_loop_info, rank, an_info);
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 ();
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);
1206       body = pop_stmt_list (new_loop);
1207     }
1208   append_to_statement_list_force (body, &loop_with_init);
1209   an_loop_info.release ();
1210   an_info.release ();
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
1218 static tree
1219 fix_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
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.  */
1241
1242 static tree
1243 expand_array_notations (tree *tp, int *walk_subtrees, void *)
1244 {
1245   if (!contains_array_notation_expr (*tp))
1246     {
1247       *walk_subtrees = 0;
1248       return NULL_TREE;
1249     }
1250   *walk_subtrees = 1;
1251
1252   switch (TREE_CODE (*tp))
1253     {
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:
1260     case COND_EXPR:
1261       *tp = fix_conditional_array_notations (*tp);
1262       break;
1263     case MODIFY_EXPR:
1264       {
1265         location_t loc = EXPR_HAS_LOCATION (*tp) ? EXPR_LOCATION (*tp) :
1266           UNKNOWN_LOCATION;
1267         tree lhs = TREE_OPERAND (*tp, 0);
1268         tree rhs = TREE_OPERAND (*tp, 1);
1269         location_t rhs_loc = EXPR_HAS_LOCATION (rhs) ? EXPR_LOCATION (rhs) :
1270           UNKNOWN_LOCATION;
1271         *tp = build_array_notation_expr (loc, lhs, TREE_TYPE (lhs), NOP_EXPR,
1272                                          rhs_loc, rhs, TREE_TYPE (rhs));
1273       }
1274       break;
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;
1294     case CALL_EXPR:
1295       *tp = fix_array_notation_call_expr (*tp);
1296       break;
1297     case RETURN_EXPR:
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;
1316     case ARRAY_NOTATION_REF:
1317       /* If we are here, then we are dealing with cases like this:
1318          A[:];
1319          A[x:y:z];
1320          A[x:y];
1321          Replace those with just void zero node.  */
1322       *tp = void_node;
1323     default:
1324       break;
1325     }
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
1333 tree
1334 expand_array_notation_exprs (tree t)
1335 {
1336   walk_tree (&t, expand_array_notations, NULL, NULL);
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
1350 tree
1351 build_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 }