1 /* This file is part of the Intel(R) Cilk(TM) Plus support
2 This file contains the builtin functions for Array
4 Copyright (C) 2013-2015 Free Software Foundation, Inc.
5 Contributed by Balaji V. Iyer <balaji.v.iyer@intel.com>,
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)
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/>. */
26 #include "coretypes.h"
30 #include "double-int.h"
38 #include "langhooks.h"
39 #include "tree-iterator.h"
40 #include "c-family/c-common.h"
41 #include "diagnostic-core.h"
43 /* Returns true if the function call in FNDECL is __sec_implicit_index. */
46 is_sec_implicit_index_fn (tree fndecl)
51 if (TREE_CODE (fndecl) == ADDR_EXPR)
52 fndecl = TREE_OPERAND (fndecl, 0);
55 (TREE_CODE (fndecl) == FUNCTION_DECL
56 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
57 && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CILKPLUS_SEC_IMPLICIT_INDEX);
60 /* Returns the first and only argument for FN, which should be a
61 sec_implicit_index function. FN's location in the source file is as
62 indicated by LOCATION. The argument to FN must be a constant integer
63 expression, otherwise returns -1. */
66 extract_sec_implicit_index_arg (location_t location, tree fn)
69 HOST_WIDE_INT return_int = 0;
71 if (TREE_CODE (fn) == CALL_EXPR)
73 fn_arg = CALL_EXPR_ARG (fn, 0);
74 if (TREE_CODE (fn_arg) == INTEGER_CST)
75 return_int = int_cst_value (fn_arg);
78 /* If the location is unknown, and if fn has a location, then use that
79 information so that the user has a better idea where the error
81 if (location == UNKNOWN_LOCATION && EXPR_HAS_LOCATION (fn))
82 location = EXPR_LOCATION (fn);
83 error_at (location, "__sec_implicit_index parameter must be an "
84 "integer constant expression");
91 /* Returns true if there is a length mismatch among exprssions that are at the
92 same dimension and one the same side of the equal sign. The Array notation
93 lengths (LIST->LENGTH) is passed in as a 2D vector of trees. */
96 length_mismatch_in_expr_p (location_t loc, vec<vec<an_parts> >list)
99 tree length = NULL_TREE;
101 size_t x = list.length ();
102 size_t y = list[0].length ();
104 for (jj = 0; jj < y; jj++)
107 for (ii = 0; ii < x; ii++)
110 length = list[ii][jj].length;
111 else if (TREE_CODE (length) == INTEGER_CST)
113 /* If length is a INTEGER, and list[ii][jj] is an integer then
114 check if they are equal. If they are not equal then return
116 if (TREE_CODE (list[ii][jj].length) == INTEGER_CST
117 && !tree_int_cst_equal (list[ii][jj].length, length))
119 error_at (loc, "length mismatch in expression");
124 /* We set the length node as the current node just in case it turns
125 out to be an integer. */
126 length = list[ii][jj].length;
132 /* Given an FNDECL of type FUNCTION_DECL or ADDR_EXPR, return the corresponding
133 BUILT_IN_CILKPLUS_SEC_REDUCE_* being called. If none, return
136 enum built_in_function
137 is_cilkplus_reduce_builtin (tree fndecl)
140 return BUILT_IN_NONE;
141 if (TREE_CODE (fndecl) == ADDR_EXPR)
142 fndecl = TREE_OPERAND (fndecl, 0);
144 if (TREE_CODE (fndecl) == FUNCTION_DECL
145 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
146 switch (DECL_FUNCTION_CODE (fndecl))
148 case BUILT_IN_CILKPLUS_SEC_REDUCE_ADD:
149 case BUILT_IN_CILKPLUS_SEC_REDUCE_MUL:
150 case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_ZERO:
151 case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO:
152 case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX:
153 case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN:
154 case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND:
155 case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND:
156 case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_NONZERO:
157 case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_NONZERO:
158 case BUILT_IN_CILKPLUS_SEC_REDUCE:
159 case BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING:
160 return DECL_FUNCTION_CODE (fndecl);
165 return BUILT_IN_NONE;
168 /* This function will recurse into EXPR finding any
169 ARRAY_NOTATION_EXPRs and calculate the overall rank of EXPR,
170 storing it in *RANK. LOC is the location of the original expression.
172 ORIG_EXPR is the original expression used to display if any rank
173 mismatch errors are found.
175 Upon entry, *RANK must be either 0, or the rank of a parent
176 expression that must have the same rank as the one being
177 calculated. It is illegal to have multiple array notation with different
178 rank in the same expression (see examples below for clarification).
180 If there were any rank mismatches while calculating the rank, an
181 error will be issued, and FALSE will be returned. Otherwise, TRUE
184 If IGNORE_BUILTIN_FN is TRUE, ignore array notation specific
185 built-in functions (__sec_reduce_*, etc).
187 Here are some examples of array notations and their rank:
198 D[5][0:10:2] 1 (since D[5] is considered "scalar")
202 F[:][:][:] + E[:] + 5 + X RANKMISMATCH-ERROR since rank (E[:]) = 1 and
203 rank (F[:][:][:]) = 3. They must be equal
204 or have a rank of zero.
205 F[:][5][10] + E[:] * 5 + *Y 1
209 func (B[:][:][:][:]) 4
212 func2 (A[:], B[:][:][:][:]) RANKMISMATCH-ERROR -- Since Rank (A[:]) = 1
213 and Rank (B[:][:][:][:]) = 4
215 A[:] + func (B[:][:][:][:]) RANKMISMATCH-ERROR
216 func2 (A[:], B[:]) + func (A) 1
221 find_rank (location_t loc, tree orig_expr, tree expr, bool ignore_builtin_fn,
225 size_t ii = 0, current_rank = 0;
227 if (TREE_CODE (expr) == ARRAY_NOTATION_REF)
232 if (TREE_CODE (ii_tree) == ARRAY_NOTATION_REF)
235 ii_tree = ARRAY_NOTATION_ARRAY (ii_tree);
237 else if (handled_component_p (ii_tree)
238 || TREE_CODE (ii_tree) == INDIRECT_REF)
239 ii_tree = TREE_OPERAND (ii_tree, 0);
240 else if (TREE_CODE (ii_tree) == PARM_DECL
241 || TREE_CODE (ii_tree) == VAR_DECL)
247 /* In this case, all the expressions this function has encountered thus
248 far have been scalars or expressions with zero rank. Please see
249 header comment for examples of such expression. */
250 *rank = current_rank;
251 else if (*rank != current_rank)
253 /* In this case, find rank is being recursed through a set of
254 expression of the form A <OPERATION> B, where A and B both have
255 array notations in them and the rank of A is not equal to rank of
257 A simple example of such case is the following: X[:] + Y[:][:] */
258 *rank = current_rank;
262 else if (TREE_CODE (expr) == STATEMENT_LIST)
264 tree_stmt_iterator ii_tsi;
265 for (ii_tsi = tsi_start (expr); !tsi_end_p (ii_tsi);
267 if (!find_rank (loc, orig_expr, *tsi_stmt_ptr (ii_tsi),
268 ignore_builtin_fn, rank))
273 if (TREE_CODE (expr) == CALL_EXPR)
275 tree func_name = CALL_EXPR_FN (expr);
276 tree prev_arg = NULL_TREE, arg;
277 call_expr_arg_iterator iter;
278 size_t prev_rank = 0;
279 if (TREE_CODE (func_name) == ADDR_EXPR)
280 if (!ignore_builtin_fn)
281 if (is_cilkplus_reduce_builtin (func_name))
282 /* If it is a built-in function, then we know it returns a
285 if (!find_rank (loc, orig_expr, func_name, ignore_builtin_fn, rank))
287 FOR_EACH_CALL_EXPR_ARG (arg, iter, expr)
289 if (!find_rank (loc, orig_expr, arg, ignore_builtin_fn, rank))
291 if (prev_arg && EXPR_HAS_LOCATION (prev_arg)
292 && prev_rank != *rank)
293 error_at (EXPR_LOCATION (prev_arg),
294 "rank mismatch between %qE and %qE", prev_arg,
296 else if (prev_arg && prev_rank != *rank)
297 /* Here the original expression is printed as a "heads-up"
298 to the programmer. This is because since there is no
299 location information for the offending argument, the
300 error could be in some internally generated code that is
301 not visible for the programmer. Thus, the correct fix
302 may lie in the original expression. */
303 error_at (loc, "rank mismatch in expression %qE",
313 tree prev_arg = NULL_TREE;
314 for (ii = 0; ii < TREE_CODE_LENGTH (TREE_CODE (expr)); ii++)
316 if (TREE_OPERAND (expr, ii)
317 && !find_rank (loc, orig_expr, TREE_OPERAND (expr, ii),
318 ignore_builtin_fn, rank))
320 if (prev_arg && EXPR_HAS_LOCATION (prev_arg))
321 error_at (EXPR_LOCATION (prev_arg),
322 "rank mismatch between %qE and %qE", prev_arg,
323 TREE_OPERAND (expr, ii));
326 prev_arg = TREE_OPERAND (expr, ii);
333 /* Extracts all array notations in NODE and stores them in ARRAY_LIST. If
334 IGNORE_BUILTIN_FN is set, then array notations inside array notation
335 specific built-in functions are ignored. The NODE can be constants,
336 VAR_DECL, PARM_DECLS, STATEMENT_LISTS or full expressions. */
339 extract_array_notation_exprs (tree node, bool ignore_builtin_fn,
340 vec<tree, va_gc> **array_list)
346 if (TREE_CODE (node) == ARRAY_NOTATION_REF)
348 vec_safe_push (*array_list, node);
351 if (TREE_CODE (node) == DECL_EXPR)
353 tree x = DECL_EXPR_DECL (node);
354 if (DECL_INITIAL (x))
355 extract_array_notation_exprs (DECL_INITIAL (x),
359 else if (TREE_CODE (node) == STATEMENT_LIST)
361 tree_stmt_iterator ii_tsi;
362 for (ii_tsi = tsi_start (node); !tsi_end_p (ii_tsi); tsi_next (&ii_tsi))
363 extract_array_notation_exprs (*tsi_stmt_ptr (ii_tsi),
364 ignore_builtin_fn, array_list);
366 else if (TREE_CODE (node) == CALL_EXPR)
369 call_expr_arg_iterator iter;
370 if (is_cilkplus_reduce_builtin (CALL_EXPR_FN (node)))
372 if (ignore_builtin_fn)
376 vec_safe_push (*array_list, node);
380 if (is_sec_implicit_index_fn (CALL_EXPR_FN (node)))
382 vec_safe_push (*array_list, node);
385 /* This will extract array notations in function pointers. */
386 extract_array_notation_exprs (CALL_EXPR_FN (node), ignore_builtin_fn,
388 FOR_EACH_CALL_EXPR_ARG (arg, iter, node)
389 extract_array_notation_exprs (arg, ignore_builtin_fn, array_list);
392 for (ii = 0; ii < TREE_CODE_LENGTH (TREE_CODE (node)); ii++)
393 if (TREE_OPERAND (node, ii))
394 extract_array_notation_exprs (TREE_OPERAND (node, ii),
395 ignore_builtin_fn, array_list);
399 /* LIST contains all the array notations found in *ORIG and ARRAY_OPERAND
400 contains the expanded ARRAY_REF. E.g., if LIST[<some_index>] contains
401 an array_notation expression, then ARRAY_OPERAND[<some_index>] contains its
402 expansion. If *ORIG matches LIST[<some_index>] then *ORIG is set to
403 ARRAY_OPERAND[<some_index>]. This function recursively steps through
404 all the sub-trees of *ORIG, if it is larger than a single
405 ARRAY_NOTATION_REF. */
408 replace_array_notations (tree *orig, bool ignore_builtin_fn,
409 vec<tree, va_gc> *list,
410 vec<tree, va_gc> *array_operand)
413 extern tree build_c_cast (location_t, tree, tree);
414 tree node = NULL_TREE, node_replacement = NULL_TREE;
416 if (vec_safe_length (list) == 0)
419 if (TREE_CODE (*orig) == ARRAY_NOTATION_REF)
421 for (ii = 0; vec_safe_iterate (list, ii, &node); ii++)
424 node_replacement = (*array_operand)[ii];
425 *orig = node_replacement;
428 else if (TREE_CODE (*orig) == STATEMENT_LIST)
430 tree_stmt_iterator ii_tsi;
431 for (ii_tsi = tsi_start (*orig); !tsi_end_p (ii_tsi); tsi_next (&ii_tsi))
432 replace_array_notations (tsi_stmt_ptr (ii_tsi), ignore_builtin_fn, list,
435 else if (TREE_CODE (*orig) == CALL_EXPR)
438 call_expr_arg_iterator iter;
439 if (is_cilkplus_reduce_builtin (CALL_EXPR_FN (*orig)))
441 if (!ignore_builtin_fn)
443 for (ii = 0; vec_safe_iterate (list, ii, &node); ii++)
446 node_replacement = (*array_operand)[ii];
447 *orig = node_replacement;
452 if (is_sec_implicit_index_fn (CALL_EXPR_FN (*orig)))
454 for (ii = 0; vec_safe_iterate (list, ii, &node); ii++)
457 node_replacement = (*array_operand)[ii];
458 *orig = build_c_cast (EXPR_LOCATION (*orig),
459 TREE_TYPE (*orig), node_replacement);
463 /* Fixes array notations in array notations in function pointers. */
464 replace_array_notations (&CALL_EXPR_FN (*orig), ignore_builtin_fn, list,
467 FOR_EACH_CALL_EXPR_ARG (arg, iter, *orig)
469 replace_array_notations (&arg, ignore_builtin_fn, list,
471 CALL_EXPR_ARG (*orig, ii) = arg;
477 for (ii = 0; ii < (size_t) TREE_CODE_LENGTH (TREE_CODE (*orig)); ii++)
478 if (TREE_OPERAND (*orig, ii))
479 replace_array_notations (&TREE_OPERAND (*orig, ii), ignore_builtin_fn,
480 list, array_operand);
485 /* Callback for walk_tree. Find all the scalar expressions in *TP and push
486 them in DATA struct, typecasted to (void *). If *WALK_SUBTREES is set to 0
487 then do not go into the *TP's subtrees. Since this function steps through
488 all the subtrees, *TP and TP can be NULL_TREE and NULL, respectively. The
489 function returns NULL_TREE unconditionally. */
492 find_inv_trees (tree *tp, int *walk_subtrees, void *data)
494 struct inv_list *i_list = (struct inv_list *) data;
499 if (TREE_CONSTANT (*tp))
500 return NULL_TREE; /* No need to save constant to a variable. */
501 if (TREE_CODE (*tp) != COMPOUND_EXPR && !contains_array_notation_expr (*tp))
503 vec_safe_push (i_list->list_values, *tp);
506 else if (TREE_CODE (*tp) == ARRAY_NOTATION_REF
507 || TREE_CODE (*tp) == ARRAY_REF
508 || TREE_CODE (*tp) == CALL_EXPR)
509 /* No need to step through the internals of array notation. */
515 /* This function is used by C and C++ front-ends. In C++, additional
516 tree codes such as TARGET_EXPR must be eliminated. These codes are
517 passed into additional_tcodes and are walked through and checked. */
518 for (ii = 0; ii < vec_safe_length (i_list->additional_tcodes); ii++)
519 if (TREE_CODE (*tp) == (*(i_list->additional_tcodes))[ii])
525 /* Callback for walk_tree. Replace all the scalar expressions in *TP with the
526 appropriate replacement stored in the struct *DATA (typecasted to void*).
527 The subtrees are not touched if *WALK_SUBTREES is set to zero. */
530 replace_inv_trees (tree *tp, int *walk_subtrees, void *data)
534 struct inv_list *i_list = (struct inv_list *) data;
536 if (vec_safe_length (i_list->list_values))
538 for (ii = 0; vec_safe_iterate (i_list->list_values, ii, &t); ii++)
539 if (simple_cst_equal (*tp, t) == 1)
541 vec_safe_iterate (i_list->replacement, ii, &r);
542 gcc_assert (r != NULL_TREE);
552 /* Returns true if EXPR or any of its subtrees contain ARRAY_NOTATION_EXPR
556 contains_array_notation_expr (tree expr)
558 vec<tree, va_gc> *array_list = NULL;
562 if (TREE_CODE (expr) == FUNCTION_DECL)
563 if (is_cilkplus_reduce_builtin (expr))
566 extract_array_notation_exprs (expr, false, &array_list);
567 if (vec_safe_length (array_list) == 0)
573 /* This function will check if OP is a CALL_EXPR that is a built-in array
574 notation function. If so, then we will return its type to be the type of
575 the array notation inside. */
578 find_correct_array_notation_type (tree op)
580 tree fn_arg, return_type = NULL_TREE;
584 return_type = TREE_TYPE (op); /* This is the default case. */
585 if (TREE_CODE (op) == CALL_EXPR)
586 if (is_cilkplus_reduce_builtin (CALL_EXPR_FN (op)))
588 fn_arg = CALL_EXPR_ARG (op, 0);
590 return_type = TREE_TYPE (fn_arg);
596 /* Extracts all the array notation triplet information from LIST and stores
597 them in the following fields of the 2-D array NODE(size x rank):
598 START, LENGTH and STRIDE, holding the starting index, length, and stride,
599 respectively. In addition, it also sets two bool fields, IS_VECTOR and
600 COUNT_DOWN, in NODE indicating whether a certain value at a certain field
601 is a vector and if the array is accessed from high to low. */
604 cilkplus_extract_an_triplets (vec<tree, va_gc> *list, size_t size, size_t rank,
605 vec<vec<struct cilkplus_an_parts> > *node)
607 vec<vec<tree> > array_exprs = vNULL;
609 node->safe_grow_cleared (size);
610 array_exprs.safe_grow_cleared (size);
613 for (size_t ii = 0; ii < size; ii++)
615 (*node)[ii].safe_grow_cleared (rank);
616 array_exprs[ii].safe_grow_cleared (rank);
618 for (size_t ii = 0; ii < size; ii++)
621 tree ii_tree = (*list)[ii];
624 if (TREE_CODE (ii_tree) == ARRAY_NOTATION_REF)
626 array_exprs[ii][jj] = ii_tree;
628 ii_tree = ARRAY_NOTATION_ARRAY (ii_tree);
630 else if (TREE_CODE (ii_tree) == ARRAY_REF)
631 ii_tree = TREE_OPERAND (ii_tree, 0);
636 for (size_t ii = 0; ii < size; ii++)
637 if (TREE_CODE ((*list)[ii]) == ARRAY_NOTATION_REF)
638 for (size_t jj = 0; jj < rank; jj++)
640 tree ii_tree = array_exprs[ii][jj];
641 (*node)[ii][jj].is_vector = true;
642 (*node)[ii][jj].value = ARRAY_NOTATION_ARRAY (ii_tree);
643 (*node)[ii][jj].start = ARRAY_NOTATION_START (ii_tree);
644 (*node)[ii][jj].length =
645 fold_build1 (CONVERT_EXPR, integer_type_node,
646 ARRAY_NOTATION_LENGTH (ii_tree));
647 (*node)[ii][jj].stride =
648 fold_build1 (CONVERT_EXPR, integer_type_node,
649 ARRAY_NOTATION_STRIDE (ii_tree));
653 /* Replaces all the __sec_implicit_arg functions in LIST with the induction
654 variable stored in VAR at the appropriate location pointed by the
655 __sec_implicit_arg's first parameter. Emits an error if the parameter is
656 not between 0 and RANK. */
659 fix_sec_implicit_args (location_t loc, vec <tree, va_gc> *list,
660 vec<an_loop_parts> an_loop_info, size_t rank,
663 vec <tree, va_gc> *array_operand = NULL;
664 for (size_t ii = 0; ii < vec_safe_length (list); ii++)
665 if (TREE_CODE ((*list)[ii]) == CALL_EXPR
666 && is_sec_implicit_index_fn (CALL_EXPR_FN ((*list)[ii])))
668 int idx = extract_sec_implicit_index_arg (loc, (*list)[ii]);
670 /* In this case, the returning function would have emitted an
671 error thus it is not necessary to do so again. */
673 else if (idx < (int) rank)
674 vec_safe_push (array_operand, an_loop_info[idx].var);
677 error_at (loc, "__sec_implicit_index argument %d must be "
678 "less than the rank of %qE", idx, orig_stmt);
683 /* Save the existing value into the array operand. */
684 vec_safe_push (array_operand, (*list)[ii]);
685 return array_operand;