annotate gcc/c/c-array-notation.c @ 118:fd00160c1b76

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