Merge from trunk:
[official-gcc.git] / main / gcc / c-family / array-notation-common.c
blob84f6f452799487a0534ad9aa523ab00e798dd749
1 /* This file is part of the Intel(R) Cilk(TM) Plus support
2 This file contains the builtin functions for Array
3 notations.
4 Copyright (C) 2013-2014 Free Software Foundation, Inc.
5 Contributed by Balaji V. Iyer <balaji.v.iyer@intel.com>,
6 Intel Corporation
8 This file is part of GCC.
10 GCC is free software; you can redistribute it and/or modify it
11 under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3, or (at your option)
13 any later version.
15 GCC is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with GCC; see the file COPYING3. If not see
22 <http://www.gnu.org/licenses/>. */
24 #include "config.h"
25 #include "system.h"
26 #include "coretypes.h"
27 #include "tree.h"
28 #include "langhooks.h"
29 #include "tree-iterator.h"
30 #include "c-family/c-common.h"
31 #include "diagnostic-core.h"
33 /* Returns true if the function call in FNDECL is __sec_implicit_index. */
35 bool
36 is_sec_implicit_index_fn (tree fndecl)
38 if (TREE_CODE (fndecl) == ADDR_EXPR)
39 fndecl = TREE_OPERAND (fndecl, 0);
41 return
42 (TREE_CODE (fndecl) == FUNCTION_DECL
43 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
44 && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CILKPLUS_SEC_IMPLICIT_INDEX);
47 /* Returns the first and only argument for FN, which should be a
48 sec_implicit_index function. FN's location in the source file is as
49 indicated by LOCATION. The argument to FN must be a constant integer
50 expression, otherwise returns -1. */
52 HOST_WIDE_INT
53 extract_sec_implicit_index_arg (location_t location, tree fn)
55 tree fn_arg;
56 HOST_WIDE_INT return_int = 0;
58 if (TREE_CODE (fn) == CALL_EXPR)
60 fn_arg = CALL_EXPR_ARG (fn, 0);
61 if (TREE_CODE (fn_arg) == INTEGER_CST)
62 return_int = int_cst_value (fn_arg);
63 else
65 /* If the location is unknown, and if fn has a location, then use that
66 information so that the user has a better idea where the error
67 could be. */
68 if (location == UNKNOWN_LOCATION && EXPR_HAS_LOCATION (fn))
69 location = EXPR_LOCATION (fn);
70 error_at (location, "__sec_implicit_index parameter must be an "
71 "integer constant expression");
72 return -1;
75 return return_int;
78 /* Returns true if there is a length mismatch among exprssions that are at the
79 same dimension and one the same side of the equal sign. The Array notation
80 lengths (LIST->LENGTH) is passed in as a 2D vector of trees. */
82 bool
83 length_mismatch_in_expr_p (location_t loc, vec<vec<an_parts> >list)
85 size_t ii, jj;
86 tree length = NULL_TREE;
88 size_t x = list.length ();
89 size_t y = list[0].length ();
91 for (jj = 0; jj < y; jj++)
93 length = NULL_TREE;
94 for (ii = 0; ii < x; ii++)
96 if (!length)
97 length = list[ii][jj].length;
98 else if (TREE_CODE (length) == INTEGER_CST)
100 /* If length is a INTEGER, and list[ii][jj] is an integer then
101 check if they are equal. If they are not equal then return
102 true. */
103 if (TREE_CODE (list[ii][jj].length) == INTEGER_CST
104 && !tree_int_cst_equal (list[ii][jj].length, length))
106 error_at (loc, "length mismatch in expression");
107 return true;
110 else
111 /* We set the length node as the current node just in case it turns
112 out to be an integer. */
113 length = list[ii][jj].length;
116 return false;
119 /* Given an FNDECL of type FUNCTION_DECL or ADDR_EXPR, return the corresponding
120 BUILT_IN_CILKPLUS_SEC_REDUCE_* being called. If none, return
121 BUILT_IN_NONE. */
123 enum built_in_function
124 is_cilkplus_reduce_builtin (tree fndecl)
126 if (!fndecl)
127 return BUILT_IN_NONE;
128 if (TREE_CODE (fndecl) == ADDR_EXPR)
129 fndecl = TREE_OPERAND (fndecl, 0);
131 if (TREE_CODE (fndecl) == FUNCTION_DECL
132 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
133 switch (DECL_FUNCTION_CODE (fndecl))
135 case BUILT_IN_CILKPLUS_SEC_REDUCE_ADD:
136 case BUILT_IN_CILKPLUS_SEC_REDUCE_MUL:
137 case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_ZERO:
138 case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO:
139 case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX:
140 case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN:
141 case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND:
142 case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND:
143 case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_NONZERO:
144 case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_NONZERO:
145 case BUILT_IN_CILKPLUS_SEC_REDUCE:
146 case BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING:
147 return DECL_FUNCTION_CODE (fndecl);
148 default:
149 break;
152 return BUILT_IN_NONE;
155 /* This function will recurse into EXPR finding any
156 ARRAY_NOTATION_EXPRs and calculate the overall rank of EXPR,
157 storing it in *RANK. LOC is the location of the original expression.
159 ORIG_EXPR is the original expression used to display if any rank
160 mismatch errors are found.
162 Upon entry, *RANK must be either 0, or the rank of a parent
163 expression that must have the same rank as the one being
164 calculated. It is illegal to have multiple array notation with different
165 rank in the same expression (see examples below for clarification).
167 If there were any rank mismatches while calculating the rank, an
168 error will be issued, and FALSE will be returned. Otherwise, TRUE
169 is returned.
171 If IGNORE_BUILTIN_FN is TRUE, ignore array notation specific
172 built-in functions (__sec_reduce_*, etc).
174 Here are some examples of array notations and their rank:
176 Expression RANK
178 X (a variable) 0
179 *Y (a pointer) 0
180 A[5] 0
181 B[5][10] 0
182 A[:] 1
183 B[0:10] 1
184 C[0:10:2] 1
185 D[5][0:10:2] 1 (since D[5] is considered "scalar")
186 D[5][:][10] 1
187 E[:] + 5 1
188 F[:][:][:] + 5 + X 3
189 F[:][:][:] + E[:] + 5 + X RANKMISMATCH-ERROR since rank (E[:]) = 1 and
190 rank (F[:][:][:]) = 3. They must be equal
191 or have a rank of zero.
192 F[:][5][10] + E[:] * 5 + *Y 1
194 int func (int);
195 func (A[:]) 1
196 func (B[:][:][:][:]) 4
198 int func2 (int, int)
199 func2 (A[:], B[:][:][:][:]) RANKMISMATCH-ERROR -- Since Rank (A[:]) = 1
200 and Rank (B[:][:][:][:]) = 4
202 A[:] + func (B[:][:][:][:]) RANKMISMATCH-ERROR
203 func2 (A[:], B[:]) + func (A) 1
207 bool
208 find_rank (location_t loc, tree orig_expr, tree expr, bool ignore_builtin_fn,
209 size_t *rank)
211 tree ii_tree;
212 size_t ii = 0, current_rank = 0;
214 if (TREE_CODE (expr) == ARRAY_NOTATION_REF)
216 ii_tree = expr;
217 while (ii_tree)
219 if (TREE_CODE (ii_tree) == ARRAY_NOTATION_REF)
221 current_rank++;
222 ii_tree = ARRAY_NOTATION_ARRAY (ii_tree);
224 else if (TREE_CODE (ii_tree) == ARRAY_REF)
225 ii_tree = TREE_OPERAND (ii_tree, 0);
226 else if (TREE_CODE (ii_tree) == PARM_DECL
227 || TREE_CODE (ii_tree) == VAR_DECL)
228 break;
230 if (*rank == 0)
231 /* In this case, all the expressions this function has encountered thus
232 far have been scalars or expressions with zero rank. Please see
233 header comment for examples of such expression. */
234 *rank = current_rank;
235 else if (*rank != current_rank)
237 /* In this case, find rank is being recursed through a set of
238 expression of the form A <OPERATION> B, where A and B both have
239 array notations in them and the rank of A is not equal to rank of
241 A simple example of such case is the following: X[:] + Y[:][:] */
242 *rank = current_rank;
243 return false;
246 else if (TREE_CODE (expr) == STATEMENT_LIST)
248 tree_stmt_iterator ii_tsi;
249 for (ii_tsi = tsi_start (expr); !tsi_end_p (ii_tsi);
250 tsi_next (&ii_tsi))
251 if (!find_rank (loc, orig_expr, *tsi_stmt_ptr (ii_tsi),
252 ignore_builtin_fn, rank))
253 return false;
255 else
257 if (TREE_CODE (expr) == CALL_EXPR)
259 tree func_name = CALL_EXPR_FN (expr);
260 tree prev_arg = NULL_TREE, arg;
261 call_expr_arg_iterator iter;
262 size_t prev_rank = 0;
263 if (TREE_CODE (func_name) == ADDR_EXPR)
264 if (!ignore_builtin_fn)
265 if (is_cilkplus_reduce_builtin (func_name))
266 /* If it is a built-in function, then we know it returns a
267 scalar. */
268 return true;
269 if (!find_rank (loc, orig_expr, func_name, ignore_builtin_fn, rank))
270 return false;
271 FOR_EACH_CALL_EXPR_ARG (arg, iter, expr)
273 if (!find_rank (loc, orig_expr, arg, ignore_builtin_fn, rank))
275 if (prev_arg && EXPR_HAS_LOCATION (prev_arg)
276 && prev_rank != *rank)
277 error_at (EXPR_LOCATION (prev_arg),
278 "rank mismatch between %qE and %qE", prev_arg,
279 arg);
280 else if (prev_arg && prev_rank != *rank)
281 /* Here the original expression is printed as a "heads-up"
282 to the programmer. This is because since there is no
283 location information for the offending argument, the
284 error could be in some internally generated code that is
285 not visible for the programmer. Thus, the correct fix
286 may lie in the original expression. */
287 error_at (loc, "rank mismatch in expression %qE",
288 orig_expr);
289 return false;
291 prev_arg = arg;
292 prev_rank = *rank;
295 else
297 tree prev_arg = NULL_TREE;
298 for (ii = 0; ii < TREE_CODE_LENGTH (TREE_CODE (expr)); ii++)
300 if (TREE_OPERAND (expr, ii)
301 && !find_rank (loc, orig_expr, TREE_OPERAND (expr, ii),
302 ignore_builtin_fn, rank))
304 if (prev_arg && EXPR_HAS_LOCATION (prev_arg))
305 error_at (EXPR_LOCATION (prev_arg),
306 "rank mismatch between %qE and %qE", prev_arg,
307 TREE_OPERAND (expr, ii));
308 return false;
310 prev_arg = TREE_OPERAND (expr, ii);
314 return true;
317 /* Extracts all array notations in NODE and stores them in ARRAY_LIST. If
318 IGNORE_BUILTIN_FN is set, then array notations inside array notation
319 specific built-in functions are ignored. The NODE can be constants,
320 VAR_DECL, PARM_DECLS, STATEMENT_LISTS or full expressions. */
322 void
323 extract_array_notation_exprs (tree node, bool ignore_builtin_fn,
324 vec<tree, va_gc> **array_list)
326 size_t ii = 0;
327 if (TREE_CODE (node) == ARRAY_NOTATION_REF)
329 vec_safe_push (*array_list, node);
330 return;
332 if (TREE_CODE (node) == DECL_EXPR)
334 tree x = DECL_EXPR_DECL (node);
335 if (DECL_INITIAL (x))
336 extract_array_notation_exprs (DECL_INITIAL (x),
337 ignore_builtin_fn,
338 array_list);
340 else if (TREE_CODE (node) == STATEMENT_LIST)
342 tree_stmt_iterator ii_tsi;
343 for (ii_tsi = tsi_start (node); !tsi_end_p (ii_tsi); tsi_next (&ii_tsi))
344 extract_array_notation_exprs (*tsi_stmt_ptr (ii_tsi),
345 ignore_builtin_fn, array_list);
347 else if (TREE_CODE (node) == CALL_EXPR)
349 tree arg;
350 call_expr_arg_iterator iter;
351 if (is_cilkplus_reduce_builtin (CALL_EXPR_FN (node)))
353 if (ignore_builtin_fn)
354 return;
355 else
357 vec_safe_push (*array_list, node);
358 return;
361 if (is_sec_implicit_index_fn (CALL_EXPR_FN (node)))
363 vec_safe_push (*array_list, node);
364 return;
366 /* This will extract array notations in function pointers. */
367 extract_array_notation_exprs (CALL_EXPR_FN (node), ignore_builtin_fn,
368 array_list);
369 FOR_EACH_CALL_EXPR_ARG (arg, iter, node)
370 extract_array_notation_exprs (arg, ignore_builtin_fn, array_list);
372 else
373 for (ii = 0; ii < TREE_CODE_LENGTH (TREE_CODE (node)); ii++)
374 if (TREE_OPERAND (node, ii))
375 extract_array_notation_exprs (TREE_OPERAND (node, ii),
376 ignore_builtin_fn, array_list);
377 return;
380 /* LIST contains all the array notations found in *ORIG and ARRAY_OPERAND
381 contains the expanded ARRAY_REF. E.g., if LIST[<some_index>] contains
382 an array_notation expression, then ARRAY_OPERAND[<some_index>] contains its
383 expansion. If *ORIG matches LIST[<some_index>] then *ORIG is set to
384 ARRAY_OPERAND[<some_index>]. This function recursively steps through
385 all the sub-trees of *ORIG, if it is larger than a single
386 ARRAY_NOTATION_REF. */
388 void
389 replace_array_notations (tree *orig, bool ignore_builtin_fn,
390 vec<tree, va_gc> *list,
391 vec<tree, va_gc> *array_operand)
393 size_t ii = 0;
394 extern tree build_c_cast (location_t, tree, tree);
395 tree node = NULL_TREE, node_replacement = NULL_TREE;
397 if (vec_safe_length (list) == 0)
398 return;
400 if (TREE_CODE (*orig) == ARRAY_NOTATION_REF)
402 for (ii = 0; vec_safe_iterate (list, ii, &node); ii++)
403 if (*orig == node)
405 node_replacement = (*array_operand)[ii];
406 *orig = node_replacement;
409 else if (TREE_CODE (*orig) == STATEMENT_LIST)
411 tree_stmt_iterator ii_tsi;
412 for (ii_tsi = tsi_start (*orig); !tsi_end_p (ii_tsi); tsi_next (&ii_tsi))
413 replace_array_notations (tsi_stmt_ptr (ii_tsi), ignore_builtin_fn, list,
414 array_operand);
416 else if (TREE_CODE (*orig) == CALL_EXPR)
418 tree arg;
419 call_expr_arg_iterator iter;
420 if (is_cilkplus_reduce_builtin (CALL_EXPR_FN (*orig)))
422 if (!ignore_builtin_fn)
424 for (ii = 0; vec_safe_iterate (list, ii, &node); ii++)
425 if (*orig == node)
427 node_replacement = (*array_operand)[ii];
428 *orig = node_replacement;
431 return;
433 if (is_sec_implicit_index_fn (CALL_EXPR_FN (*orig)))
435 for (ii = 0; vec_safe_iterate (list, ii, &node); ii++)
436 if (*orig == node)
438 node_replacement = (*array_operand)[ii];
439 *orig = build_c_cast (EXPR_LOCATION (*orig),
440 TREE_TYPE (*orig), node_replacement);
442 return;
444 /* Fixes array notations in array notations in function pointers. */
445 replace_array_notations (&CALL_EXPR_FN (*orig), ignore_builtin_fn, list,
446 array_operand);
447 ii = 0;
448 FOR_EACH_CALL_EXPR_ARG (arg, iter, *orig)
450 replace_array_notations (&arg, ignore_builtin_fn, list,
451 array_operand);
452 CALL_EXPR_ARG (*orig, ii) = arg;
453 ii++;
456 else
458 for (ii = 0; ii < (size_t) TREE_CODE_LENGTH (TREE_CODE (*orig)); ii++)
459 if (TREE_OPERAND (*orig, ii))
460 replace_array_notations (&TREE_OPERAND (*orig, ii), ignore_builtin_fn,
461 list, array_operand);
463 return;
466 /* Callback for walk_tree. Find all the scalar expressions in *TP and push
467 them in DATA struct, typecasted to (void *). If *WALK_SUBTREES is set to 0
468 then do not go into the *TP's subtrees. Since this function steps through
469 all the subtrees, *TP and TP can be NULL_TREE and NULL, respectively. The
470 function returns NULL_TREE unconditionally. */
472 tree
473 find_inv_trees (tree *tp, int *walk_subtrees, void *data)
475 struct inv_list *i_list = (struct inv_list *) data;
476 unsigned int ii = 0;
478 if (!tp || !*tp)
479 return NULL_TREE;
480 if (TREE_CONSTANT (*tp))
481 return NULL_TREE; /* No need to save constant to a variable. */
482 if (TREE_CODE (*tp) != COMPOUND_EXPR && !contains_array_notation_expr (*tp))
484 vec_safe_push (i_list->list_values, *tp);
485 *walk_subtrees = 0;
487 else if (TREE_CODE (*tp) == ARRAY_NOTATION_REF
488 || TREE_CODE (*tp) == ARRAY_REF
489 || TREE_CODE (*tp) == CALL_EXPR)
490 /* No need to step through the internals of array notation. */
491 *walk_subtrees = 0;
492 else
494 *walk_subtrees = 1;
496 /* This function is used by C and C++ front-ends. In C++, additional
497 tree codes such as TARGET_EXPR must be eliminated. These codes are
498 passed into additional_tcodes and are walked through and checked. */
499 for (ii = 0; ii < vec_safe_length (i_list->additional_tcodes); ii++)
500 if (TREE_CODE (*tp) == (*(i_list->additional_tcodes))[ii])
501 *walk_subtrees = 0;
503 return NULL_TREE;
506 /* Callback for walk_tree. Replace all the scalar expressions in *TP with the
507 appropriate replacement stored in the struct *DATA (typecasted to void*).
508 The subtrees are not touched if *WALK_SUBTREES is set to zero. */
510 tree
511 replace_inv_trees (tree *tp, int *walk_subtrees, void *data)
513 size_t ii = 0;
514 tree t, r;
515 struct inv_list *i_list = (struct inv_list *) data;
517 if (vec_safe_length (i_list->list_values))
519 for (ii = 0; vec_safe_iterate (i_list->list_values, ii, &t); ii++)
520 if (simple_cst_equal (*tp, t) == 1)
522 vec_safe_iterate (i_list->replacement, ii, &r);
523 gcc_assert (r != NULL_TREE);
524 *tp = r;
525 *walk_subtrees = 0;
528 else
529 *walk_subtrees = 0;
530 return NULL_TREE;
533 /* Returns true if EXPR or any of its subtrees contain ARRAY_NOTATION_EXPR
534 node. */
536 bool
537 contains_array_notation_expr (tree expr)
539 vec<tree, va_gc> *array_list = NULL;
541 if (!expr)
542 return false;
543 if (TREE_CODE (expr) == FUNCTION_DECL)
544 if (is_cilkplus_reduce_builtin (expr))
545 return true;
547 extract_array_notation_exprs (expr, false, &array_list);
548 if (vec_safe_length (array_list) == 0)
549 return false;
550 else
551 return true;
554 /* This function will check if OP is a CALL_EXPR that is a built-in array
555 notation function. If so, then we will return its type to be the type of
556 the array notation inside. */
558 tree
559 find_correct_array_notation_type (tree op)
561 tree fn_arg, return_type = NULL_TREE;
563 if (op)
565 return_type = TREE_TYPE (op); /* This is the default case. */
566 if (TREE_CODE (op) == CALL_EXPR)
567 if (is_cilkplus_reduce_builtin (CALL_EXPR_FN (op)))
569 fn_arg = CALL_EXPR_ARG (op, 0);
570 if (fn_arg)
571 return_type = TREE_TYPE (fn_arg);
574 return return_type;
577 /* Extracts all the array notation triplet information from LIST and stores
578 them in the following fields of the 2-D array NODE(size x rank):
579 START, LENGTH and STRIDE, holding the starting index, length, and stride,
580 respectively. In addition, it also sets two bool fields, IS_VECTOR and
581 COUNT_DOWN, in NODE indicating whether a certain value at a certain field
582 is a vector and if the array is accessed from high to low. */
584 void
585 cilkplus_extract_an_triplets (vec<tree, va_gc> *list, size_t size, size_t rank,
586 vec<vec<struct cilkplus_an_parts> > *node)
588 vec<vec<tree> > array_exprs = vNULL;
590 node->safe_grow_cleared (size);
591 array_exprs.safe_grow_cleared (size);
593 if (rank > 0)
594 for (size_t ii = 0; ii < size; ii++)
596 (*node)[ii].safe_grow_cleared (rank);
597 array_exprs[ii].safe_grow_cleared (rank);
599 for (size_t ii = 0; ii < size; ii++)
601 size_t jj = 0;
602 tree ii_tree = (*list)[ii];
603 while (ii_tree)
605 if (TREE_CODE (ii_tree) == ARRAY_NOTATION_REF)
607 array_exprs[ii][jj] = ii_tree;
608 jj++;
609 ii_tree = ARRAY_NOTATION_ARRAY (ii_tree);
611 else if (TREE_CODE (ii_tree) == ARRAY_REF)
612 ii_tree = TREE_OPERAND (ii_tree, 0);
613 else
614 break;
617 for (size_t ii = 0; ii < size; ii++)
618 if (TREE_CODE ((*list)[ii]) == ARRAY_NOTATION_REF)
619 for (size_t jj = 0; jj < rank; jj++)
621 tree ii_tree = array_exprs[ii][jj];
622 (*node)[ii][jj].is_vector = true;
623 (*node)[ii][jj].value = ARRAY_NOTATION_ARRAY (ii_tree);
624 (*node)[ii][jj].start = ARRAY_NOTATION_START (ii_tree);
625 (*node)[ii][jj].length =
626 fold_build1 (CONVERT_EXPR, integer_type_node,
627 ARRAY_NOTATION_LENGTH (ii_tree));
628 (*node)[ii][jj].stride =
629 fold_build1 (CONVERT_EXPR, integer_type_node,
630 ARRAY_NOTATION_STRIDE (ii_tree));
634 /* Replaces all the __sec_implicit_arg functions in LIST with the induction
635 variable stored in VAR at the appropriate location pointed by the
636 __sec_implicit_arg's first parameter. Emits an error if the parameter is
637 not between 0 and RANK. */
639 vec <tree, va_gc> *
640 fix_sec_implicit_args (location_t loc, vec <tree, va_gc> *list,
641 vec<an_loop_parts> an_loop_info, size_t rank,
642 tree orig_stmt)
644 vec <tree, va_gc> *array_operand = NULL;
645 for (size_t ii = 0; ii < vec_safe_length (list); ii++)
646 if (TREE_CODE ((*list)[ii]) == CALL_EXPR
647 && is_sec_implicit_index_fn (CALL_EXPR_FN ((*list)[ii])))
649 int idx = extract_sec_implicit_index_arg (loc, (*list)[ii]);
650 if (idx < 0)
651 /* In this case, the returning function would have emitted an
652 error thus it is not necessary to do so again. */
653 return NULL;
654 else if (idx < (int) rank)
655 vec_safe_push (array_operand, an_loop_info[idx].var);
656 else
658 error_at (loc, "__sec_implicit_index argument %d must be "
659 "less than the rank of %qE", idx, orig_stmt);
660 return NULL;
663 else
664 /* Save the existing value into the array operand. */
665 vec_safe_push (array_operand, (*list)[ii]);
666 return array_operand;