]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/fortran/trans-stmt.c
cgraph.c (dump_cgraph_node): Add replace output flag by process.
[thirdparty/gcc.git] / gcc / fortran / trans-stmt.c
CommitLineData
6de9cd9a 1/* Statement translation -- generate GCC trees from gfc_code.
8b791297 2 Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
bfcabc6c 3 Free Software Foundation, Inc.
6de9cd9a
DN
4 Contributed by Paul Brook <paul@nowt.org>
5 and Steven Bosscher <s.bosscher@student.tudelft.nl>
6
9fc4d79b 7This file is part of GCC.
6de9cd9a 8
9fc4d79b
TS
9GCC is free software; you can redistribute it and/or modify it under
10the terms of the GNU General Public License as published by the Free
d234d788 11Software Foundation; either version 3, or (at your option) any later
9fc4d79b 12version.
6de9cd9a 13
9fc4d79b
TS
14GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15WARRANTY; without even the implied warranty of MERCHANTABILITY or
16FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17for more details.
6de9cd9a
DN
18
19You should have received a copy of the GNU General Public License
d234d788
NC
20along with GCC; see the file COPYING3. If not see
21<http://www.gnu.org/licenses/>. */
6de9cd9a
DN
22
23
24#include "config.h"
25#include "system.h"
26#include "coretypes.h"
27#include "tree.h"
726a989a 28#include "gimple.h"
6de9cd9a
DN
29#include "ggc.h"
30#include "toplev.h"
31#include "real.h"
6de9cd9a 32#include "gfortran.h"
dd18a33b 33#include "flags.h"
6de9cd9a
DN
34#include "trans.h"
35#include "trans-stmt.h"
36#include "trans-types.h"
37#include "trans-array.h"
38#include "trans-const.h"
39#include "arith.h"
3ded6210 40#include "dependency.h"
6de9cd9a 41
6de9cd9a
DN
42typedef struct iter_info
43{
44 tree var;
45 tree start;
46 tree end;
47 tree step;
48 struct iter_info *next;
49}
50iter_info;
51
6de9cd9a
DN
52typedef struct forall_info
53{
54 iter_info *this_loop;
55 tree mask;
6de9cd9a
DN
56 tree maskindex;
57 int nvar;
58 tree size;
e8d366ec 59 struct forall_info *prev_nest;
6de9cd9a
DN
60}
61forall_info;
62
011daa76
RS
63static void gfc_trans_where_2 (gfc_code *, tree, bool,
64 forall_info *, stmtblock_t *);
6de9cd9a
DN
65
66/* Translate a F95 label number to a LABEL_EXPR. */
67
68tree
69gfc_trans_label_here (gfc_code * code)
70{
71 return build1_v (LABEL_EXPR, gfc_get_label_decl (code->here));
72}
73
ce2df7c6
FW
74
75/* Given a variable expression which has been ASSIGNed to, find the decl
76 containing the auxiliary variables. For variables in common blocks this
77 is a field_decl. */
78
79void
80gfc_conv_label_variable (gfc_se * se, gfc_expr * expr)
81{
82 gcc_assert (expr->symtree->n.sym->attr.assign == 1);
83 gfc_conv_expr (se, expr);
84 /* Deals with variable in common block. Get the field declaration. */
85 if (TREE_CODE (se->expr) == COMPONENT_REF)
86 se->expr = TREE_OPERAND (se->expr, 1);
910450c1
FW
87 /* Deals with dummy argument. Get the parameter declaration. */
88 else if (TREE_CODE (se->expr) == INDIRECT_REF)
89 se->expr = TREE_OPERAND (se->expr, 0);
ce2df7c6
FW
90}
91
6de9cd9a 92/* Translate a label assignment statement. */
ce2df7c6 93
6de9cd9a
DN
94tree
95gfc_trans_label_assign (gfc_code * code)
96{
97 tree label_tree;
98 gfc_se se;
99 tree len;
100 tree addr;
101 tree len_tree;
6de9cd9a
DN
102 int label_len;
103
104 /* Start a new block. */
105 gfc_init_se (&se, NULL);
106 gfc_start_block (&se.pre);
ce2df7c6
FW
107 gfc_conv_label_variable (&se, code->expr);
108
6de9cd9a
DN
109 len = GFC_DECL_STRING_LEN (se.expr);
110 addr = GFC_DECL_ASSIGN_ADDR (se.expr);
111
112 label_tree = gfc_get_label_decl (code->label);
113
114 if (code->label->defined == ST_LABEL_TARGET)
115 {
116 label_tree = gfc_build_addr_expr (pvoid_type_node, label_tree);
117 len_tree = integer_minus_one_node;
118 }
119 else
120 {
d393bbd7
FXC
121 gfc_expr *format = code->label->format;
122
123 label_len = format->value.character.length;
7d60be94 124 len_tree = build_int_cst (NULL_TREE, label_len);
d393bbd7
FXC
125 label_tree = gfc_build_wide_string_const (format->ts.kind, label_len + 1,
126 format->value.character.string);
b078dfbf 127 label_tree = gfc_build_addr_expr (pvoid_type_node, label_tree);
6de9cd9a
DN
128 }
129
726a989a
RB
130 gfc_add_modify (&se.pre, len, len_tree);
131 gfc_add_modify (&se.pre, addr, label_tree);
6de9cd9a
DN
132
133 return gfc_finish_block (&se.pre);
134}
135
136/* Translate a GOTO statement. */
137
138tree
139gfc_trans_goto (gfc_code * code)
140{
dd18a33b 141 locus loc = code->loc;
6de9cd9a
DN
142 tree assigned_goto;
143 tree target;
144 tree tmp;
6de9cd9a
DN
145 gfc_se se;
146
6de9cd9a
DN
147 if (code->label != NULL)
148 return build1_v (GOTO_EXPR, gfc_get_label_decl (code->label));
149
150 /* ASSIGNED GOTO. */
151 gfc_init_se (&se, NULL);
152 gfc_start_block (&se.pre);
ce2df7c6 153 gfc_conv_label_variable (&se, code->expr);
6de9cd9a 154 tmp = GFC_DECL_STRING_LEN (se.expr);
3f2ec06a
RG
155 tmp = fold_build2 (NE_EXPR, boolean_type_node, tmp,
156 build_int_cst (TREE_TYPE (tmp), -1));
0d52899f 157 gfc_trans_runtime_check (true, false, tmp, &se.pre, &loc,
c8fe94c7 158 "Assigned label is not a target label");
6de9cd9a
DN
159
160 assigned_goto = GFC_DECL_ASSIGN_ADDR (se.expr);
6de9cd9a
DN
161
162 code = code->block;
163 if (code == NULL)
164 {
44855d8c 165 target = fold_build1 (GOTO_EXPR, void_type_node, assigned_goto);
6de9cd9a
DN
166 gfc_add_expr_to_block (&se.pre, target);
167 return gfc_finish_block (&se.pre);
168 }
169
170 /* Check the label list. */
6de9cd9a
DN
171 do
172 {
75d2cf69
SB
173 target = gfc_get_label_decl (code->label);
174 tmp = gfc_build_addr_expr (pvoid_type_node, target);
44855d8c 175 tmp = fold_build2 (EQ_EXPR, boolean_type_node, tmp, assigned_goto);
75d2cf69 176 tmp = build3_v (COND_EXPR, tmp,
44855d8c 177 fold_build1 (GOTO_EXPR, void_type_node, target),
75d2cf69 178 build_empty_stmt ());
6de9cd9a
DN
179 gfc_add_expr_to_block (&se.pre, tmp);
180 code = code->block;
181 }
182 while (code != NULL);
0d52899f 183 gfc_trans_runtime_check (true, false, boolean_true_node, &se.pre, &loc,
c8fe94c7 184 "Assigned label is not in the list");
dd18a33b 185
6de9cd9a
DN
186 return gfc_finish_block (&se.pre);
187}
188
189
3d79abbd
PB
190/* Translate an ENTRY statement. Just adds a label for this entry point. */
191tree
192gfc_trans_entry (gfc_code * code)
193{
194 return build1_v (LABEL_EXPR, code->ext.entry->label);
195}
196
197
476220e7
PT
198/* Check for dependencies between INTENT(IN) and INTENT(OUT) arguments of
199 elemental subroutines. Make temporaries for output arguments if any such
200 dependencies are found. Output arguments are chosen because internal_unpack
201 can be used, as is, to copy the result back to the variable. */
202static void
203gfc_conv_elemental_dependencies (gfc_se * se, gfc_se * loopse,
2b0bd714
MM
204 gfc_symbol * sym, gfc_actual_arglist * arg,
205 gfc_dep_check check_variable)
476220e7
PT
206{
207 gfc_actual_arglist *arg0;
208 gfc_expr *e;
209 gfc_formal_arglist *formal;
210 gfc_loopinfo tmp_loop;
211 gfc_se parmse;
212 gfc_ss *ss;
213 gfc_ss_info *info;
214 gfc_symbol *fsym;
215 int n;
476220e7
PT
216 tree data;
217 tree offset;
218 tree size;
219 tree tmp;
220
221 if (loopse->ss == NULL)
222 return;
223
224 ss = loopse->ss;
225 arg0 = arg;
226 formal = sym->formal;
227
228 /* Loop over all the arguments testing for dependencies. */
229 for (; arg != NULL; arg = arg->next, formal = formal ? formal->next : NULL)
230 {
231 e = arg->expr;
232 if (e == NULL)
233 continue;
234
235 /* Obtain the info structure for the current argument. */
236 info = NULL;
237 for (ss = loopse->ss; ss && ss != gfc_ss_terminator; ss = ss->next)
238 {
239 if (ss->expr != e)
240 continue;
241 info = &ss->data.info;
242 break;
243 }
244
245 /* If there is a dependency, create a temporary and use it
66e4ab31 246 instead of the variable. */
476220e7
PT
247 fsym = formal ? formal->sym : NULL;
248 if (e->expr_type == EXPR_VARIABLE
249 && e->rank && fsym
06bcd751
PT
250 && fsym->attr.intent != INTENT_IN
251 && gfc_check_fncall_dependency (e, fsym->attr.intent,
2b0bd714 252 sym, arg0, check_variable))
476220e7 253 {
79e5286c 254 tree initial, temptype;
12f681a0
DK
255 stmtblock_t temp_post;
256
476220e7
PT
257 /* Make a local loopinfo for the temporary creation, so that
258 none of the other ss->info's have to be renormalized. */
259 gfc_init_loopinfo (&tmp_loop);
260 for (n = 0; n < info->dimen; n++)
261 {
262 tmp_loop.to[n] = loopse->loop->to[n];
263 tmp_loop.from[n] = loopse->loop->from[n];
264 tmp_loop.order[n] = loopse->loop->order[n];
265 }
266
12f681a0
DK
267 /* Obtain the argument descriptor for unpacking. */
268 gfc_init_se (&parmse, NULL);
269 parmse.want_pointer = 1;
270 gfc_conv_expr_descriptor (&parmse, e, gfc_walk_expr (e));
271 gfc_add_block_to_block (&se->pre, &parmse.pre);
272
273 /* If we've got INTENT(INOUT), initialize the array temporary with
274 a copy of the values. */
275 if (fsym->attr.intent == INTENT_INOUT)
276 initial = parmse.expr;
277 else
278 initial = NULL_TREE;
279
79e5286c
DK
280 /* Find the type of the temporary to create; we don't use the type
281 of e itself as this breaks for subcomponent-references in e (where
282 the type of e is that of the final reference, but parmse.expr's
283 type corresponds to the full derived-type). */
284 /* TODO: Fix this somehow so we don't need a temporary of the whole
285 array but instead only the components referenced. */
286 temptype = TREE_TYPE (parmse.expr); /* Pointer to descriptor. */
287 gcc_assert (TREE_CODE (temptype) == POINTER_TYPE);
288 temptype = TREE_TYPE (temptype);
289 temptype = gfc_get_element_type (temptype);
290
291 /* Generate the temporary. Cleaning up the temporary should be the
292 very last thing done, so we add the code to a new block and add it
293 to se->post as last instructions. */
476220e7
PT
294 size = gfc_create_var (gfc_array_index_type, NULL);
295 data = gfc_create_var (pvoid_type_node, NULL);
12f681a0 296 gfc_init_block (&temp_post);
12f681a0 297 tmp = gfc_trans_create_temp_array (&se->pre, &temp_post,
79e5286c 298 &tmp_loop, info, temptype,
12f681a0
DK
299 initial,
300 false, true, false,
301 &arg->expr->where);
726a989a 302 gfc_add_modify (&se->pre, size, tmp);
476220e7 303 tmp = fold_convert (pvoid_type_node, info->data);
726a989a 304 gfc_add_modify (&se->pre, data, tmp);
476220e7 305
476220e7
PT
306 /* Calculate the offset for the temporary. */
307 offset = gfc_index_zero_node;
308 for (n = 0; n < info->dimen; n++)
309 {
310 tmp = gfc_conv_descriptor_stride (info->descriptor,
311 gfc_rank_cst[n]);
312 tmp = fold_build2 (MULT_EXPR, gfc_array_index_type,
313 loopse->loop->from[n], tmp);
314 offset = fold_build2 (MINUS_EXPR, gfc_array_index_type,
315 offset, tmp);
316 }
317 info->offset = gfc_create_var (gfc_array_index_type, NULL);
726a989a 318 gfc_add_modify (&se->pre, info->offset, offset);
476220e7
PT
319
320 /* Copy the result back using unpack. */
5039610b 321 tmp = build_call_expr (gfor_fndecl_in_unpack, 2, parmse.expr, data);
476220e7
PT
322 gfc_add_expr_to_block (&se->post, tmp);
323
79e5286c 324 /* parmse.pre is already added above. */
476220e7 325 gfc_add_block_to_block (&se->post, &parmse.post);
12f681a0 326 gfc_add_block_to_block (&se->post, &temp_post);
476220e7
PT
327 }
328 }
329}
330
331
6de9cd9a
DN
332/* Translate the CALL statement. Builds a call to an F95 subroutine. */
333
334tree
476220e7 335gfc_trans_call (gfc_code * code, bool dependency_check)
6de9cd9a
DN
336{
337 gfc_se se;
48474141 338 gfc_ss * ss;
dda895f9 339 int has_alternate_specifier;
2b0bd714 340 gfc_dep_check check_variable;
6de9cd9a
DN
341
342 /* A CALL starts a new block because the actual arguments may have to
343 be evaluated first. */
344 gfc_init_se (&se, NULL);
345 gfc_start_block (&se.pre);
346
6e45f57b 347 gcc_assert (code->resolved_sym);
6de9cd9a 348
48474141
PT
349 ss = gfc_ss_terminator;
350 if (code->resolved_sym->attr.elemental)
351 ss = gfc_walk_elemental_function_args (ss, code->ext.actual, GFC_SS_REFERENCE);
6de9cd9a 352
48474141
PT
353 /* Is not an elemental subroutine call with array valued arguments. */
354 if (ss == gfc_ss_terminator)
6de9cd9a 355 {
48474141
PT
356
357 /* Translate the call. */
358 has_alternate_specifier
5a0aad31
FXC
359 = gfc_conv_function_call (&se, code->resolved_sym, code->ext.actual,
360 NULL_TREE);
48474141
PT
361
362 /* A subroutine without side-effect, by definition, does nothing! */
363 TREE_SIDE_EFFECTS (se.expr) = 1;
364
365 /* Chain the pieces together and return the block. */
366 if (has_alternate_specifier)
367 {
368 gfc_code *select_code;
369 gfc_symbol *sym;
370 select_code = code->next;
371 gcc_assert(select_code->op == EXEC_SELECT);
372 sym = select_code->expr->symtree->n.sym;
373 se.expr = convert (gfc_typenode_for_spec (&sym->ts), se.expr);
9ebe2d22
PT
374 if (sym->backend_decl == NULL)
375 sym->backend_decl = gfc_get_symbol_decl (sym);
726a989a 376 gfc_add_modify (&se.pre, sym->backend_decl, se.expr);
48474141
PT
377 }
378 else
379 gfc_add_expr_to_block (&se.pre, se.expr);
380
381 gfc_add_block_to_block (&se.pre, &se.post);
6de9cd9a 382 }
48474141 383
6de9cd9a 384 else
48474141
PT
385 {
386 /* An elemental subroutine call with array valued arguments has
387 to be scalarized. */
388 gfc_loopinfo loop;
389 stmtblock_t body;
390 stmtblock_t block;
391 gfc_se loopse;
70e72065 392 gfc_se depse;
48474141
PT
393
394 /* gfc_walk_elemental_function_args renders the ss chain in the
12f681a0 395 reverse order to the actual argument order. */
48474141
PT
396 ss = gfc_reverse_ss (ss);
397
398 /* Initialize the loop. */
399 gfc_init_se (&loopse, NULL);
400 gfc_init_loopinfo (&loop);
401 gfc_add_ss_to_loop (&loop, ss);
402
403 gfc_conv_ss_startstride (&loop);
2b0bd714
MM
404 /* TODO: gfc_conv_loop_setup generates a temporary for vector
405 subscripts. This could be prevented in the elemental case
406 as temporaries are handled separatedly
407 (below in gfc_conv_elemental_dependencies). */
bdfd2ff0 408 gfc_conv_loop_setup (&loop, &code->expr->where);
48474141
PT
409 gfc_mark_ss_chain_used (ss, 1);
410
476220e7
PT
411 /* Convert the arguments, checking for dependencies. */
412 gfc_copy_loopinfo_to_se (&loopse, &loop);
413 loopse.ss = ss;
414
06bcd751 415 /* For operator assignment, do dependency checking. */
476220e7 416 if (dependency_check)
2b0bd714
MM
417 check_variable = ELEM_CHECK_VARIABLE;
418 else
419 check_variable = ELEM_DONT_CHECK_VARIABLE;
70e72065
MM
420
421 gfc_init_se (&depse, NULL);
422 gfc_conv_elemental_dependencies (&depse, &loopse, code->resolved_sym,
2b0bd714 423 code->ext.actual, check_variable);
476220e7 424
70e72065
MM
425 gfc_add_block_to_block (&loop.pre, &depse.pre);
426 gfc_add_block_to_block (&loop.post, &depse.post);
427
48474141
PT
428 /* Generate the loop body. */
429 gfc_start_scalarized_body (&loop, &body);
430 gfc_init_block (&block);
48474141
PT
431
432 /* Add the subroutine call to the block. */
5a0aad31
FXC
433 gfc_conv_function_call (&loopse, code->resolved_sym, code->ext.actual,
434 NULL_TREE);
48474141
PT
435 gfc_add_expr_to_block (&loopse.pre, loopse.expr);
436
437 gfc_add_block_to_block (&block, &loopse.pre);
438 gfc_add_block_to_block (&block, &loopse.post);
439
440 /* Finish up the loop block and the loop. */
441 gfc_add_expr_to_block (&body, gfc_finish_block (&block));
442 gfc_trans_scalarizing_loops (&loop, &body);
443 gfc_add_block_to_block (&se.pre, &loop.pre);
444 gfc_add_block_to_block (&se.pre, &loop.post);
476220e7 445 gfc_add_block_to_block (&se.pre, &se.post);
48474141
PT
446 gfc_cleanup_loop (&loop);
447 }
6de9cd9a 448
6de9cd9a
DN
449 return gfc_finish_block (&se.pre);
450}
451
452
453/* Translate the RETURN statement. */
454
455tree
456gfc_trans_return (gfc_code * code ATTRIBUTE_UNUSED)
457{
458 if (code->expr)
459 {
460 gfc_se se;
461 tree tmp;
462 tree result;
463
da4c6ed8 464 /* If code->expr is not NULL, this return statement must appear
6de9cd9a
DN
465 in a subroutine and current_fake_result_decl has already
466 been generated. */
467
5f20c93a 468 result = gfc_get_fake_result_decl (NULL, 0);
6de9cd9a
DN
469 if (!result)
470 {
471 gfc_warning ("An alternate return at %L without a * dummy argument",
472 &code->expr->where);
473 return build1_v (GOTO_EXPR, gfc_get_return_label ());
474 }
475
476 /* Start a new block for this statement. */
477 gfc_init_se (&se, NULL);
478 gfc_start_block (&se.pre);
479
480 gfc_conv_expr (&se, code->expr);
481
44855d8c
TS
482 tmp = fold_build2 (MODIFY_EXPR, TREE_TYPE (result), result,
483 fold_convert (TREE_TYPE (result), se.expr));
6de9cd9a
DN
484 gfc_add_expr_to_block (&se.pre, tmp);
485
486 tmp = build1_v (GOTO_EXPR, gfc_get_return_label ());
487 gfc_add_expr_to_block (&se.pre, tmp);
488 gfc_add_block_to_block (&se.pre, &se.post);
489 return gfc_finish_block (&se.pre);
490 }
491 else
492 return build1_v (GOTO_EXPR, gfc_get_return_label ());
493}
494
495
496/* Translate the PAUSE statement. We have to translate this statement
497 to a runtime library call. */
498
499tree
500gfc_trans_pause (gfc_code * code)
501{
e2cad04b 502 tree gfc_int4_type_node = gfc_get_int_type (4);
6de9cd9a 503 gfc_se se;
6de9cd9a 504 tree tmp;
6de9cd9a
DN
505
506 /* Start a new block for this statement. */
507 gfc_init_se (&se, NULL);
508 gfc_start_block (&se.pre);
509
510
511 if (code->expr == NULL)
512 {
7d60be94 513 tmp = build_int_cst (gfc_int4_type_node, code->ext.stop_code);
5039610b 514 tmp = build_call_expr (gfor_fndecl_pause_numeric, 1, tmp);
6de9cd9a
DN
515 }
516 else
517 {
518 gfc_conv_expr_reference (&se, code->expr);
5039610b
SL
519 tmp = build_call_expr (gfor_fndecl_pause_string, 2,
520 se.expr, se.string_length);
6de9cd9a
DN
521 }
522
6de9cd9a
DN
523 gfc_add_expr_to_block (&se.pre, tmp);
524
525 gfc_add_block_to_block (&se.pre, &se.post);
526
527 return gfc_finish_block (&se.pre);
528}
529
530
531/* Translate the STOP statement. We have to translate this statement
532 to a runtime library call. */
533
534tree
535gfc_trans_stop (gfc_code * code)
536{
e2cad04b 537 tree gfc_int4_type_node = gfc_get_int_type (4);
6de9cd9a 538 gfc_se se;
6de9cd9a 539 tree tmp;
6de9cd9a
DN
540
541 /* Start a new block for this statement. */
542 gfc_init_se (&se, NULL);
543 gfc_start_block (&se.pre);
544
545
546 if (code->expr == NULL)
547 {
7d60be94 548 tmp = build_int_cst (gfc_int4_type_node, code->ext.stop_code);
5039610b 549 tmp = build_call_expr (gfor_fndecl_stop_numeric, 1, tmp);
6de9cd9a
DN
550 }
551 else
552 {
553 gfc_conv_expr_reference (&se, code->expr);
5039610b
SL
554 tmp = build_call_expr (gfor_fndecl_stop_string, 2,
555 se.expr, se.string_length);
6de9cd9a
DN
556 }
557
6de9cd9a
DN
558 gfc_add_expr_to_block (&se.pre, tmp);
559
560 gfc_add_block_to_block (&se.pre, &se.post);
561
562 return gfc_finish_block (&se.pre);
563}
564
565
566/* Generate GENERIC for the IF construct. This function also deals with
567 the simple IF statement, because the front end translates the IF
568 statement into an IF construct.
569
570 We translate:
571
572 IF (cond) THEN
573 then_clause
574 ELSEIF (cond2)
575 elseif_clause
576 ELSE
577 else_clause
578 ENDIF
579
580 into:
581
582 pre_cond_s;
583 if (cond_s)
584 {
585 then_clause;
586 }
587 else
588 {
589 pre_cond_s
590 if (cond_s)
591 {
592 elseif_clause
593 }
594 else
595 {
596 else_clause;
597 }
598 }
599
600 where COND_S is the simplified version of the predicate. PRE_COND_S
601 are the pre side-effects produced by the translation of the
602 conditional.
603 We need to build the chain recursively otherwise we run into
604 problems with folding incomplete statements. */
605
606static tree
607gfc_trans_if_1 (gfc_code * code)
608{
609 gfc_se if_se;
610 tree stmt, elsestmt;
611
612 /* Check for an unconditional ELSE clause. */
613 if (!code->expr)
614 return gfc_trans_code (code->next);
615
616 /* Initialize a statement builder for each block. Puts in NULL_TREEs. */
617 gfc_init_se (&if_se, NULL);
618 gfc_start_block (&if_se.pre);
619
620 /* Calculate the IF condition expression. */
621 gfc_conv_expr_val (&if_se, code->expr);
622
623 /* Translate the THEN clause. */
624 stmt = gfc_trans_code (code->next);
625
626 /* Translate the ELSE clause. */
627 if (code->block)
628 elsestmt = gfc_trans_if_1 (code->block);
629 else
630 elsestmt = build_empty_stmt ();
631
632 /* Build the condition expression and add it to the condition block. */
61ead135 633 stmt = fold_build3 (COND_EXPR, void_type_node, if_se.expr, stmt, elsestmt);
6de9cd9a
DN
634
635 gfc_add_expr_to_block (&if_se.pre, stmt);
636
637 /* Finish off this statement. */
638 return gfc_finish_block (&if_se.pre);
639}
640
641tree
642gfc_trans_if (gfc_code * code)
643{
644 /* Ignore the top EXEC_IF, it only announces an IF construct. The
645 actual code we must translate is in code->block. */
646
647 return gfc_trans_if_1 (code->block);
648}
649
650
fa951694 651/* Translate an arithmetic IF expression.
6de9cd9a
DN
652
653 IF (cond) label1, label2, label3 translates to
654
655 if (cond <= 0)
656 {
657 if (cond < 0)
658 goto label1;
659 else // cond == 0
660 goto label2;
661 }
662 else // cond > 0
663 goto label3;
442c1644
CY
664
665 An optimized version can be generated in case of equal labels.
666 E.g., if label1 is equal to label2, we can translate it to
667
668 if (cond <= 0)
669 goto label1;
670 else
671 goto label3;
6de9cd9a
DN
672*/
673
674tree
675gfc_trans_arithmetic_if (gfc_code * code)
676{
677 gfc_se se;
678 tree tmp;
679 tree branch1;
680 tree branch2;
681 tree zero;
682
683 /* Start a new block. */
684 gfc_init_se (&se, NULL);
685 gfc_start_block (&se.pre);
686
687 /* Pre-evaluate COND. */
688 gfc_conv_expr_val (&se, code->expr);
5ec1334b 689 se.expr = gfc_evaluate_now (se.expr, &se.pre);
6de9cd9a
DN
690
691 /* Build something to compare with. */
692 zero = gfc_build_const (TREE_TYPE (se.expr), integer_zero_node);
693
442c1644
CY
694 if (code->label->value != code->label2->value)
695 {
696 /* If (cond < 0) take branch1 else take branch2.
697 First build jumps to the COND .LT. 0 and the COND .EQ. 0 cases. */
698 branch1 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label));
699 branch2 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label2));
700
701 if (code->label->value != code->label3->value)
61ead135 702 tmp = fold_build2 (LT_EXPR, boolean_type_node, se.expr, zero);
442c1644 703 else
61ead135 704 tmp = fold_build2 (NE_EXPR, boolean_type_node, se.expr, zero);
6de9cd9a 705
61ead135 706 branch1 = fold_build3 (COND_EXPR, void_type_node, tmp, branch1, branch2);
442c1644
CY
707 }
708 else
709 branch1 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label));
6de9cd9a 710
442c1644
CY
711 if (code->label->value != code->label3->value
712 && code->label2->value != code->label3->value)
713 {
714 /* if (cond <= 0) take branch1 else take branch2. */
715 branch2 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label3));
61ead135
RG
716 tmp = fold_build2 (LE_EXPR, boolean_type_node, se.expr, zero);
717 branch1 = fold_build3 (COND_EXPR, void_type_node, tmp, branch1, branch2);
442c1644 718 }
6de9cd9a
DN
719
720 /* Append the COND_EXPR to the evaluation of COND, and return. */
721 gfc_add_expr_to_block (&se.pre, branch1);
722 return gfc_finish_block (&se.pre);
723}
724
725
54c2d931 726/* Translate the simple DO construct. This is where the loop variable has
fbdad37d
PB
727 integer type and step +-1. We can't use this in the general case
728 because integer overflow and floating point errors could give incorrect
729 results.
730 We translate a do loop from:
731
732 DO dovar = from, to, step
733 body
734 END DO
735
736 to:
737
738 [Evaluate loop bounds and step]
739 dovar = from;
740 if ((step > 0) ? (dovar <= to) : (dovar => to))
741 {
742 for (;;)
743 {
744 body;
745 cycle_label:
746 cond = (dovar == to);
747 dovar += step;
748 if (cond) goto end_label;
749 }
750 }
751 end_label:
752
753 This helps the optimizers by avoiding the extra induction variable
754 used in the general case. */
755
756static tree
757gfc_trans_simple_do (gfc_code * code, stmtblock_t *pblock, tree dovar,
758 tree from, tree to, tree step)
759{
760 stmtblock_t body;
761 tree type;
762 tree cond;
763 tree tmp;
764 tree cycle_label;
765 tree exit_label;
766
767 type = TREE_TYPE (dovar);
768
769 /* Initialize the DO variable: dovar = from. */
726a989a 770 gfc_add_modify (pblock, dovar, from);
fbdad37d
PB
771
772 /* Cycle and exit statements are implemented with gotos. */
773 cycle_label = gfc_build_label_decl (NULL_TREE);
774 exit_label = gfc_build_label_decl (NULL_TREE);
775
776 /* Put the labels where they can be found later. See gfc_trans_do(). */
777 code->block->backend_decl = tree_cons (cycle_label, exit_label, NULL);
778
779 /* Loop body. */
780 gfc_start_block (&body);
781
782 /* Main loop body. */
783 tmp = gfc_trans_code (code->block->next);
784 gfc_add_expr_to_block (&body, tmp);
785
786 /* Label for cycle statements (if needed). */
787 if (TREE_USED (cycle_label))
788 {
789 tmp = build1_v (LABEL_EXPR, cycle_label);
790 gfc_add_expr_to_block (&body, tmp);
791 }
792
793 /* Evaluate the loop condition. */
61ead135 794 cond = fold_build2 (EQ_EXPR, boolean_type_node, dovar, to);
fbdad37d
PB
795 cond = gfc_evaluate_now (cond, &body);
796
797 /* Increment the loop variable. */
61ead135 798 tmp = fold_build2 (PLUS_EXPR, type, dovar, step);
726a989a 799 gfc_add_modify (&body, dovar, tmp);
fbdad37d
PB
800
801 /* The loop exit. */
802 tmp = build1_v (GOTO_EXPR, exit_label);
803 TREE_USED (exit_label) = 1;
61ead135
RG
804 tmp = fold_build3 (COND_EXPR, void_type_node,
805 cond, tmp, build_empty_stmt ());
fbdad37d
PB
806 gfc_add_expr_to_block (&body, tmp);
807
808 /* Finish the loop body. */
809 tmp = gfc_finish_block (&body);
810 tmp = build1_v (LOOP_EXPR, tmp);
811
812 /* Only execute the loop if the number of iterations is positive. */
813 if (tree_int_cst_sgn (step) > 0)
10c7a96f 814 cond = fold_build2 (LE_EXPR, boolean_type_node, dovar, to);
fbdad37d 815 else
10c7a96f 816 cond = fold_build2 (GE_EXPR, boolean_type_node, dovar, to);
61ead135
RG
817 tmp = fold_build3 (COND_EXPR, void_type_node,
818 cond, tmp, build_empty_stmt ());
fbdad37d
PB
819 gfc_add_expr_to_block (pblock, tmp);
820
821 /* Add the exit label. */
822 tmp = build1_v (LABEL_EXPR, exit_label);
823 gfc_add_expr_to_block (pblock, tmp);
824
825 return gfc_finish_block (pblock);
826}
827
6de9cd9a
DN
828/* Translate the DO construct. This obviously is one of the most
829 important ones to get right with any compiler, but especially
830 so for Fortran.
831
fbdad37d
PB
832 We special case some loop forms as described in gfc_trans_simple_do.
833 For other cases we implement them with a separate loop count,
834 as described in the standard.
6de9cd9a
DN
835
836 We translate a do loop from:
837
838 DO dovar = from, to, step
839 body
840 END DO
841
842 to:
843
fbdad37d 844 [evaluate loop bounds and step]
5d148c08
FXC
845 empty = (step > 0 ? to < from : to > from);
846 countm1 = (to - from) / step;
fbdad37d 847 dovar = from;
5d148c08 848 if (empty) goto exit_label;
fbdad37d 849 for (;;)
6de9cd9a
DN
850 {
851 body;
852cycle_label:
fbdad37d 853 dovar += step
5d148c08 854 if (countm1 ==0) goto exit_label;
76dac339 855 countm1--;
6de9cd9a
DN
856 }
857exit_label:
858
5d148c08
FXC
859 countm1 is an unsigned integer. It is equal to the loop count minus one,
860 because the loop count itself can overflow. */
6de9cd9a
DN
861
862tree
863gfc_trans_do (gfc_code * code)
864{
865 gfc_se se;
866 tree dovar;
867 tree from;
868 tree to;
869 tree step;
5d148c08 870 tree countm1;
6de9cd9a 871 tree type;
5d148c08 872 tree utype;
6de9cd9a
DN
873 tree cond;
874 tree cycle_label;
875 tree exit_label;
876 tree tmp;
5d148c08 877 tree pos_step;
6de9cd9a
DN
878 stmtblock_t block;
879 stmtblock_t body;
880
881 gfc_start_block (&block);
882
fbdad37d 883 /* Evaluate all the expressions in the iterator. */
6de9cd9a
DN
884 gfc_init_se (&se, NULL);
885 gfc_conv_expr_lhs (&se, code->ext.iterator->var);
886 gfc_add_block_to_block (&block, &se.pre);
887 dovar = se.expr;
888 type = TREE_TYPE (dovar);
889
890 gfc_init_se (&se, NULL);
8d5cfa27 891 gfc_conv_expr_val (&se, code->ext.iterator->start);
6de9cd9a 892 gfc_add_block_to_block (&block, &se.pre);
fbdad37d 893 from = gfc_evaluate_now (se.expr, &block);
6de9cd9a
DN
894
895 gfc_init_se (&se, NULL);
8d5cfa27 896 gfc_conv_expr_val (&se, code->ext.iterator->end);
6de9cd9a 897 gfc_add_block_to_block (&block, &se.pre);
fbdad37d 898 to = gfc_evaluate_now (se.expr, &block);
6de9cd9a
DN
899
900 gfc_init_se (&se, NULL);
8d5cfa27 901 gfc_conv_expr_val (&se, code->ext.iterator->step);
6de9cd9a 902 gfc_add_block_to_block (&block, &se.pre);
fbdad37d
PB
903 step = gfc_evaluate_now (se.expr, &block);
904
905 /* Special case simple loops. */
906 if (TREE_CODE (type) == INTEGER_TYPE
907 && (integer_onep (step)
908 || tree_int_cst_equal (step, integer_minus_one_node)))
909 return gfc_trans_simple_do (code, &block, dovar, from, to, step);
c0b29099 910
5d148c08
FXC
911 pos_step = fold_build2 (GT_EXPR, boolean_type_node, step,
912 fold_convert (type, integer_zero_node));
6de9cd9a 913
8d5cfa27 914 if (TREE_CODE (type) == INTEGER_TYPE)
c0b29099
JJ
915 utype = unsigned_type_for (type);
916 else
917 utype = unsigned_type_for (gfc_array_index_type);
918 countm1 = gfc_create_var (utype, "countm1");
5d148c08 919
c0b29099
JJ
920 /* Cycle and exit statements are implemented with gotos. */
921 cycle_label = gfc_build_label_decl (NULL_TREE);
922 exit_label = gfc_build_label_decl (NULL_TREE);
923 TREE_USED (exit_label) = 1;
924
925 /* Initialize the DO variable: dovar = from. */
926 gfc_add_modify (&block, dovar, from);
927
928 /* Initialize loop count and jump to exit label if the loop is empty.
929 This code is executed before we enter the loop body. We generate:
930 if (step > 0)
931 {
932 if (to < from) goto exit_label;
933 countm1 = (to - from) / step;
934 }
935 else
936 {
937 if (to > from) goto exit_label;
938 countm1 = (from - to) / -step;
939 } */
940 if (TREE_CODE (type) == INTEGER_TYPE)
941 {
942 tree pos, neg;
5d148c08 943
c0b29099
JJ
944 tmp = fold_build2 (LT_EXPR, boolean_type_node, to, from);
945 pos = fold_build3 (COND_EXPR, void_type_node, tmp,
946 build1_v (GOTO_EXPR, exit_label),
947 build_empty_stmt ());
948 tmp = fold_build2 (MINUS_EXPR, type, to, from);
949 tmp = fold_convert (utype, tmp);
950 tmp = fold_build2 (TRUNC_DIV_EXPR, utype, tmp,
951 fold_convert (utype, step));
952 tmp = build2 (MODIFY_EXPR, void_type_node, countm1, tmp);
953 pos = build2 (COMPOUND_EXPR, void_type_node, pos, tmp);
954
955 tmp = fold_build2 (GT_EXPR, boolean_type_node, to, from);
956 neg = fold_build3 (COND_EXPR, void_type_node, tmp,
957 build1_v (GOTO_EXPR, exit_label),
958 build_empty_stmt ());
959 tmp = fold_build2 (MINUS_EXPR, type, from, to);
960 tmp = fold_convert (utype, tmp);
961 tmp = fold_build2 (TRUNC_DIV_EXPR, utype, tmp,
962 fold_convert (utype, fold_build1 (NEGATE_EXPR,
963 type, step)));
964 tmp = build2 (MODIFY_EXPR, void_type_node, countm1, tmp);
965 neg = build2 (COMPOUND_EXPR, void_type_node, neg, tmp);
966
967 tmp = fold_build3 (COND_EXPR, void_type_node, pos_step, pos, neg);
968 gfc_add_expr_to_block (&block, tmp);
8d5cfa27
SK
969 }
970 else
971 {
972 /* TODO: We could use the same width as the real type.
973 This would probably cause more problems that it solves
974 when we implement "long double" types. */
c0b29099 975
5d148c08 976 tmp = fold_build2 (MINUS_EXPR, type, to, from);
10c7a96f 977 tmp = fold_build2 (RDIV_EXPR, type, tmp, step);
5d148c08 978 tmp = fold_build1 (FIX_TRUNC_EXPR, utype, tmp);
c0b29099
JJ
979 gfc_add_modify (&block, countm1, tmp);
980
981 /* We need a special check for empty loops:
982 empty = (step > 0 ? to < from : to > from); */
983 tmp = fold_build3 (COND_EXPR, boolean_type_node, pos_step,
984 fold_build2 (LT_EXPR, boolean_type_node, to, from),
985 fold_build2 (GT_EXPR, boolean_type_node, to, from));
986 /* If the loop is empty, go directly to the exit label. */
987 tmp = fold_build3 (COND_EXPR, void_type_node, tmp,
988 build1_v (GOTO_EXPR, exit_label),
989 build_empty_stmt ());
990 gfc_add_expr_to_block (&block, tmp);
8d5cfa27 991 }
5d148c08 992
6de9cd9a
DN
993 /* Loop body. */
994 gfc_start_block (&body);
995
6de9cd9a
DN
996 /* Put these labels where they can be found later. We put the
997 labels in a TREE_LIST node (because TREE_CHAIN is already
998 used). cycle_label goes in TREE_PURPOSE (backend_decl), exit
999 label in TREE_VALUE (backend_decl). */
1000
1001 code->block->backend_decl = tree_cons (cycle_label, exit_label, NULL);
1002
1003 /* Main loop body. */
1004 tmp = gfc_trans_code (code->block->next);
1005 gfc_add_expr_to_block (&body, tmp);
1006
1007 /* Label for cycle statements (if needed). */
1008 if (TREE_USED (cycle_label))
1009 {
1010 tmp = build1_v (LABEL_EXPR, cycle_label);
1011 gfc_add_expr_to_block (&body, tmp);
1012 }
1013
244974bd 1014 /* Increment the loop variable. */
44855d8c 1015 tmp = fold_build2 (PLUS_EXPR, type, dovar, step);
726a989a 1016 gfc_add_modify (&body, dovar, tmp);
244974bd 1017
5d148c08
FXC
1018 /* End with the loop condition. Loop until countm1 == 0. */
1019 cond = fold_build2 (EQ_EXPR, boolean_type_node, countm1,
1020 build_int_cst (utype, 0));
1021 tmp = build1_v (GOTO_EXPR, exit_label);
1022 tmp = fold_build3 (COND_EXPR, void_type_node,
1023 cond, tmp, build_empty_stmt ());
1024 gfc_add_expr_to_block (&body, tmp);
1025
6de9cd9a 1026 /* Decrement the loop count. */
44855d8c 1027 tmp = fold_build2 (MINUS_EXPR, utype, countm1, build_int_cst (utype, 1));
726a989a 1028 gfc_add_modify (&body, countm1, tmp);
6de9cd9a
DN
1029
1030 /* End of loop body. */
1031 tmp = gfc_finish_block (&body);
1032
1033 /* The for loop itself. */
923ab88c 1034 tmp = build1_v (LOOP_EXPR, tmp);
6de9cd9a
DN
1035 gfc_add_expr_to_block (&block, tmp);
1036
1037 /* Add the exit label. */
1038 tmp = build1_v (LABEL_EXPR, exit_label);
1039 gfc_add_expr_to_block (&block, tmp);
1040
1041 return gfc_finish_block (&block);
1042}
1043
1044
1045/* Translate the DO WHILE construct.
1046
1047 We translate
1048
1049 DO WHILE (cond)
1050 body
1051 END DO
1052
1053 to:
1054
1055 for ( ; ; )
1056 {
1057 pre_cond;
1058 if (! cond) goto exit_label;
1059 body;
1060cycle_label:
1061 }
1062exit_label:
1063
1064 Because the evaluation of the exit condition `cond' may have side
1065 effects, we can't do much for empty loop bodies. The backend optimizers
1066 should be smart enough to eliminate any dead loops. */
1067
1068tree
1069gfc_trans_do_while (gfc_code * code)
1070{
1071 gfc_se cond;
1072 tree tmp;
1073 tree cycle_label;
1074 tree exit_label;
1075 stmtblock_t block;
1076
1077 /* Everything we build here is part of the loop body. */
1078 gfc_start_block (&block);
1079
1080 /* Cycle and exit statements are implemented with gotos. */
1081 cycle_label = gfc_build_label_decl (NULL_TREE);
1082 exit_label = gfc_build_label_decl (NULL_TREE);
1083
1084 /* Put the labels where they can be found later. See gfc_trans_do(). */
1085 code->block->backend_decl = tree_cons (cycle_label, exit_label, NULL);
1086
1087 /* Create a GIMPLE version of the exit condition. */
1088 gfc_init_se (&cond, NULL);
1089 gfc_conv_expr_val (&cond, code->expr);
1090 gfc_add_block_to_block (&block, &cond.pre);
10c7a96f 1091 cond.expr = fold_build1 (TRUTH_NOT_EXPR, boolean_type_node, cond.expr);
6de9cd9a
DN
1092
1093 /* Build "IF (! cond) GOTO exit_label". */
1094 tmp = build1_v (GOTO_EXPR, exit_label);
1095 TREE_USED (exit_label) = 1;
61ead135
RG
1096 tmp = fold_build3 (COND_EXPR, void_type_node,
1097 cond.expr, tmp, build_empty_stmt ());
6de9cd9a
DN
1098 gfc_add_expr_to_block (&block, tmp);
1099
1100 /* The main body of the loop. */
1101 tmp = gfc_trans_code (code->block->next);
1102 gfc_add_expr_to_block (&block, tmp);
1103
1104 /* Label for cycle statements (if needed). */
1105 if (TREE_USED (cycle_label))
1106 {
1107 tmp = build1_v (LABEL_EXPR, cycle_label);
1108 gfc_add_expr_to_block (&block, tmp);
1109 }
1110
1111 /* End of loop body. */
1112 tmp = gfc_finish_block (&block);
1113
1114 gfc_init_block (&block);
1115 /* Build the loop. */
923ab88c 1116 tmp = build1_v (LOOP_EXPR, tmp);
6de9cd9a
DN
1117 gfc_add_expr_to_block (&block, tmp);
1118
1119 /* Add the exit label. */
1120 tmp = build1_v (LABEL_EXPR, exit_label);
1121 gfc_add_expr_to_block (&block, tmp);
1122
1123 return gfc_finish_block (&block);
1124}
1125
1126
1127/* Translate the SELECT CASE construct for INTEGER case expressions,
1128 without killing all potential optimizations. The problem is that
1129 Fortran allows unbounded cases, but the back-end does not, so we
1130 need to intercept those before we enter the equivalent SWITCH_EXPR
1131 we can build.
1132
1133 For example, we translate this,
1134
1135 SELECT CASE (expr)
1136 CASE (:100,101,105:115)
1137 block_1
1138 CASE (190:199,200:)
1139 block_2
1140 CASE (300)
1141 block_3
1142 CASE DEFAULT
1143 block_4
1144 END SELECT
1145
1146 to the GENERIC equivalent,
1147
1148 switch (expr)
1149 {
1150 case (minimum value for typeof(expr) ... 100:
1151 case 101:
1152 case 105 ... 114:
1153 block1:
1154 goto end_label;
1155
1156 case 200 ... (maximum value for typeof(expr):
1157 case 190 ... 199:
1158 block2;
1159 goto end_label;
1160
1161 case 300:
1162 block_3;
1163 goto end_label;
1164
1165 default:
1166 block_4;
1167 goto end_label;
1168 }
1169
1170 end_label: */
1171
1172static tree
1173gfc_trans_integer_select (gfc_code * code)
1174{
1175 gfc_code *c;
1176 gfc_case *cp;
1177 tree end_label;
1178 tree tmp;
1179 gfc_se se;
1180 stmtblock_t block;
1181 stmtblock_t body;
1182
1183 gfc_start_block (&block);
1184
1185 /* Calculate the switch expression. */
1186 gfc_init_se (&se, NULL);
1187 gfc_conv_expr_val (&se, code->expr);
1188 gfc_add_block_to_block (&block, &se.pre);
1189
1190 end_label = gfc_build_label_decl (NULL_TREE);
1191
1192 gfc_init_block (&body);
1193
1194 for (c = code->block; c; c = c->block)
1195 {
1196 for (cp = c->ext.case_list; cp; cp = cp->next)
1197 {
1198 tree low, high;
1199 tree label;
1200
1201 /* Assume it's the default case. */
1202 low = high = NULL_TREE;
1203
1204 if (cp->low)
1205 {
20585ad6
BM
1206 low = gfc_conv_mpz_to_tree (cp->low->value.integer,
1207 cp->low->ts.kind);
6de9cd9a
DN
1208
1209 /* If there's only a lower bound, set the high bound to the
1210 maximum value of the case expression. */
1211 if (!cp->high)
1212 high = TYPE_MAX_VALUE (TREE_TYPE (se.expr));
1213 }
1214
1215 if (cp->high)
1216 {
1217 /* Three cases are possible here:
1218
1219 1) There is no lower bound, e.g. CASE (:N).
1220 2) There is a lower bound .NE. high bound, that is
1221 a case range, e.g. CASE (N:M) where M>N (we make
1222 sure that M>N during type resolution).
1223 3) There is a lower bound, and it has the same value
1224 as the high bound, e.g. CASE (N:N). This is our
1225 internal representation of CASE(N).
1226
1227 In the first and second case, we need to set a value for
e2ae1407 1228 high. In the third case, we don't because the GCC middle
6de9cd9a
DN
1229 end represents a single case value by just letting high be
1230 a NULL_TREE. We can't do that because we need to be able
1231 to represent unbounded cases. */
1232
1233 if (!cp->low
1234 || (cp->low
1235 && mpz_cmp (cp->low->value.integer,
1236 cp->high->value.integer) != 0))
20585ad6
BM
1237 high = gfc_conv_mpz_to_tree (cp->high->value.integer,
1238 cp->high->ts.kind);
6de9cd9a
DN
1239
1240 /* Unbounded case. */
1241 if (!cp->low)
1242 low = TYPE_MIN_VALUE (TREE_TYPE (se.expr));
1243 }
1244
1245 /* Build a label. */
c006df4e 1246 label = gfc_build_label_decl (NULL_TREE);
6de9cd9a
DN
1247
1248 /* Add this case label.
1249 Add parameter 'label', make it match GCC backend. */
44855d8c
TS
1250 tmp = fold_build3 (CASE_LABEL_EXPR, void_type_node,
1251 low, high, label);
6de9cd9a
DN
1252 gfc_add_expr_to_block (&body, tmp);
1253 }
1254
1255 /* Add the statements for this case. */
1256 tmp = gfc_trans_code (c->next);
1257 gfc_add_expr_to_block (&body, tmp);
1258
1259 /* Break to the end of the construct. */
1260 tmp = build1_v (GOTO_EXPR, end_label);
1261 gfc_add_expr_to_block (&body, tmp);
1262 }
1263
1264 tmp = gfc_finish_block (&body);
923ab88c 1265 tmp = build3_v (SWITCH_EXPR, se.expr, tmp, NULL_TREE);
6de9cd9a
DN
1266 gfc_add_expr_to_block (&block, tmp);
1267
1268 tmp = build1_v (LABEL_EXPR, end_label);
1269 gfc_add_expr_to_block (&block, tmp);
1270
1271 return gfc_finish_block (&block);
1272}
1273
1274
1275/* Translate the SELECT CASE construct for LOGICAL case expressions.
1276
1277 There are only two cases possible here, even though the standard
1278 does allow three cases in a LOGICAL SELECT CASE construct: .TRUE.,
1279 .FALSE., and DEFAULT.
1280
1281 We never generate more than two blocks here. Instead, we always
1282 try to eliminate the DEFAULT case. This way, we can translate this
1283 kind of SELECT construct to a simple
1284
1285 if {} else {};
1286
1287 expression in GENERIC. */
1288
1289static tree
1290gfc_trans_logical_select (gfc_code * code)
1291{
1292 gfc_code *c;
1293 gfc_code *t, *f, *d;
1294 gfc_case *cp;
1295 gfc_se se;
1296 stmtblock_t block;
1297
1298 /* Assume we don't have any cases at all. */
1299 t = f = d = NULL;
1300
1301 /* Now see which ones we actually do have. We can have at most two
1302 cases in a single case list: one for .TRUE. and one for .FALSE.
1303 The default case is always separate. If the cases for .TRUE. and
1304 .FALSE. are in the same case list, the block for that case list
1305 always executed, and we don't generate code a COND_EXPR. */
1306 for (c = code->block; c; c = c->block)
1307 {
1308 for (cp = c->ext.case_list; cp; cp = cp->next)
1309 {
1310 if (cp->low)
1311 {
1312 if (cp->low->value.logical == 0) /* .FALSE. */
1313 f = c;
1314 else /* if (cp->value.logical != 0), thus .TRUE. */
1315 t = c;
1316 }
1317 else
1318 d = c;
1319 }
1320 }
1321
1322 /* Start a new block. */
1323 gfc_start_block (&block);
1324
1325 /* Calculate the switch expression. We always need to do this
1326 because it may have side effects. */
1327 gfc_init_se (&se, NULL);
1328 gfc_conv_expr_val (&se, code->expr);
1329 gfc_add_block_to_block (&block, &se.pre);
1330
1331 if (t == f && t != NULL)
1332 {
1333 /* Cases for .TRUE. and .FALSE. are in the same block. Just
1334 translate the code for these cases, append it to the current
1335 block. */
1336 gfc_add_expr_to_block (&block, gfc_trans_code (t->next));
1337 }
1338 else
1339 {
61ead135 1340 tree true_tree, false_tree, stmt;
6de9cd9a
DN
1341
1342 true_tree = build_empty_stmt ();
1343 false_tree = build_empty_stmt ();
1344
1345 /* If we have a case for .TRUE. and for .FALSE., discard the default case.
1346 Otherwise, if .TRUE. or .FALSE. is missing and there is a default case,
1347 make the missing case the default case. */
1348 if (t != NULL && f != NULL)
1349 d = NULL;
1350 else if (d != NULL)
1351 {
1352 if (t == NULL)
1353 t = d;
1354 else
1355 f = d;
1356 }
1357
1358 /* Translate the code for each of these blocks, and append it to
1359 the current block. */
1360 if (t != NULL)
1361 true_tree = gfc_trans_code (t->next);
1362
1363 if (f != NULL)
1364 false_tree = gfc_trans_code (f->next);
1365
61ead135
RG
1366 stmt = fold_build3 (COND_EXPR, void_type_node, se.expr,
1367 true_tree, false_tree);
1368 gfc_add_expr_to_block (&block, stmt);
6de9cd9a
DN
1369 }
1370
1371 return gfc_finish_block (&block);
1372}
1373
1374
1375/* Translate the SELECT CASE construct for CHARACTER case expressions.
1376 Instead of generating compares and jumps, it is far simpler to
1377 generate a data structure describing the cases in order and call a
1378 library subroutine that locates the right case.
1379 This is particularly true because this is the only case where we
1380 might have to dispose of a temporary.
1381 The library subroutine returns a pointer to jump to or NULL if no
1382 branches are to be taken. */
1383
1384static tree
1385gfc_trans_character_select (gfc_code *code)
1386{
d393bbd7 1387 tree init, node, end_label, tmp, type, case_num, label, fndecl;
6de9cd9a
DN
1388 stmtblock_t block, body;
1389 gfc_case *cp, *d;
1390 gfc_code *c;
1391 gfc_se se;
d393bbd7
FXC
1392 int n, k;
1393
1394 /* The jump table types are stored in static variables to avoid
1395 constructing them from scratch every single time. */
1396 static tree select_struct[2];
1397 static tree ss_string1[2], ss_string1_len[2];
1398 static tree ss_string2[2], ss_string2_len[2];
1399 static tree ss_target[2];
1400
1401 tree pchartype = gfc_get_pchar_type (code->expr->ts.kind);
6de9cd9a 1402
d393bbd7
FXC
1403 if (code->expr->ts.kind == 1)
1404 k = 0;
1405 else if (code->expr->ts.kind == 4)
1406 k = 1;
1407 else
1408 gcc_unreachable ();
6de9cd9a 1409
d393bbd7 1410 if (select_struct[k] == NULL)
6de9cd9a 1411 {
d393bbd7 1412 select_struct[k] = make_node (RECORD_TYPE);
e2cad04b 1413
d393bbd7
FXC
1414 if (code->expr->ts.kind == 1)
1415 TYPE_NAME (select_struct[k]) = get_identifier ("_jump_struct_char1");
1416 else if (code->expr->ts.kind == 4)
1417 TYPE_NAME (select_struct[k]) = get_identifier ("_jump_struct_char4");
1418 else
1419 gcc_unreachable ();
6de9cd9a
DN
1420
1421#undef ADD_FIELD
d393bbd7
FXC
1422#define ADD_FIELD(NAME, TYPE) \
1423 ss_##NAME[k] = gfc_add_field_to_struct \
1424 (&(TYPE_FIELDS (select_struct[k])), select_struct[k], \
6de9cd9a
DN
1425 get_identifier (stringize(NAME)), TYPE)
1426
d393bbd7
FXC
1427 ADD_FIELD (string1, pchartype);
1428 ADD_FIELD (string1_len, gfc_charlen_type_node);
6de9cd9a 1429
d393bbd7
FXC
1430 ADD_FIELD (string2, pchartype);
1431 ADD_FIELD (string2_len, gfc_charlen_type_node);
6de9cd9a 1432
dd52ecb0 1433 ADD_FIELD (target, integer_type_node);
6de9cd9a
DN
1434#undef ADD_FIELD
1435
d393bbd7 1436 gfc_finish_type (select_struct[k]);
6de9cd9a
DN
1437 }
1438
1439 cp = code->block->ext.case_list;
1440 while (cp->left != NULL)
1441 cp = cp->left;
1442
1443 n = 0;
1444 for (d = cp; d; d = d->right)
1445 d->n = n++;
1446
6de9cd9a
DN
1447 end_label = gfc_build_label_decl (NULL_TREE);
1448
1449 /* Generate the body */
1450 gfc_start_block (&block);
1451 gfc_init_block (&body);
1452
1453 for (c = code->block; c; c = c->block)
1454 {
1455 for (d = c->ext.case_list; d; d = d->next)
1456 {
2b8327ce 1457 label = gfc_build_label_decl (NULL_TREE);
44855d8c
TS
1458 tmp = fold_build3 (CASE_LABEL_EXPR, void_type_node,
1459 build_int_cst (NULL_TREE, d->n),
1460 build_int_cst (NULL_TREE, d->n), label);
6de9cd9a
DN
1461 gfc_add_expr_to_block (&body, tmp);
1462 }
1463
1464 tmp = gfc_trans_code (c->next);
1465 gfc_add_expr_to_block (&body, tmp);
1466
923ab88c 1467 tmp = build1_v (GOTO_EXPR, end_label);
6de9cd9a
DN
1468 gfc_add_expr_to_block (&body, tmp);
1469 }
1470
1471 /* Generate the structure describing the branches */
1472 init = NULL_TREE;
6de9cd9a 1473
2b8327ce 1474 for(d = cp; d; d = d->right)
6de9cd9a
DN
1475 {
1476 node = NULL_TREE;
1477
1478 gfc_init_se (&se, NULL);
1479
1480 if (d->low == NULL)
1481 {
d393bbd7
FXC
1482 node = tree_cons (ss_string1[k], null_pointer_node, node);
1483 node = tree_cons (ss_string1_len[k], integer_zero_node, node);
6de9cd9a
DN
1484 }
1485 else
1486 {
1487 gfc_conv_expr_reference (&se, d->low);
1488
d393bbd7
FXC
1489 node = tree_cons (ss_string1[k], se.expr, node);
1490 node = tree_cons (ss_string1_len[k], se.string_length, node);
6de9cd9a
DN
1491 }
1492
1493 if (d->high == NULL)
1494 {
d393bbd7
FXC
1495 node = tree_cons (ss_string2[k], null_pointer_node, node);
1496 node = tree_cons (ss_string2_len[k], integer_zero_node, node);
6de9cd9a
DN
1497 }
1498 else
1499 {
1500 gfc_init_se (&se, NULL);
1501 gfc_conv_expr_reference (&se, d->high);
1502
d393bbd7
FXC
1503 node = tree_cons (ss_string2[k], se.expr, node);
1504 node = tree_cons (ss_string2_len[k], se.string_length, node);
6de9cd9a
DN
1505 }
1506
d393bbd7 1507 node = tree_cons (ss_target[k], build_int_cst (integer_type_node, d->n),
2b8327ce 1508 node);
6de9cd9a 1509
d393bbd7 1510 tmp = build_constructor_from_list (select_struct[k], nreverse (node));
6de9cd9a
DN
1511 init = tree_cons (NULL_TREE, tmp, init);
1512 }
1513
d393bbd7
FXC
1514 type = build_array_type (select_struct[k],
1515 build_index_type (build_int_cst (NULL_TREE, n-1)));
6de9cd9a 1516
4038c495 1517 init = build_constructor_from_list (type, nreverse(init));
6de9cd9a 1518 TREE_CONSTANT (init) = 1;
6de9cd9a
DN
1519 TREE_STATIC (init) = 1;
1520 /* Create a static variable to hold the jump table. */
1521 tmp = gfc_create_var (type, "jumptable");
1522 TREE_CONSTANT (tmp) = 1;
6de9cd9a 1523 TREE_STATIC (tmp) = 1;
0f0707d1 1524 TREE_READONLY (tmp) = 1;
6de9cd9a
DN
1525 DECL_INITIAL (tmp) = init;
1526 init = tmp;
1527
5039610b 1528 /* Build the library call */
6de9cd9a 1529 init = gfc_build_addr_expr (pvoid_type_node, init);
6de9cd9a
DN
1530
1531 gfc_init_se (&se, NULL);
1532 gfc_conv_expr_reference (&se, code->expr);
1533
6de9cd9a
DN
1534 gfc_add_block_to_block (&block, &se.pre);
1535
d393bbd7
FXC
1536 if (code->expr->ts.kind == 1)
1537 fndecl = gfor_fndecl_select_string;
1538 else if (code->expr->ts.kind == 4)
1539 fndecl = gfor_fndecl_select_string_char4;
1540 else
1541 gcc_unreachable ();
1542
1543 tmp = build_call_expr (fndecl, 4, init, build_int_cst (NULL_TREE, n),
1544 se.expr, se.string_length);
dd52ecb0 1545 case_num = gfc_create_var (integer_type_node, "case_num");
726a989a 1546 gfc_add_modify (&block, case_num, tmp);
dc6c7714
PT
1547
1548 gfc_add_block_to_block (&block, &se.post);
1549
6de9cd9a 1550 tmp = gfc_finish_block (&body);
2b8327ce 1551 tmp = build3_v (SWITCH_EXPR, case_num, tmp, NULL_TREE);
6de9cd9a 1552 gfc_add_expr_to_block (&block, tmp);
2b8327ce 1553
923ab88c 1554 tmp = build1_v (LABEL_EXPR, end_label);
6de9cd9a
DN
1555 gfc_add_expr_to_block (&block, tmp);
1556
6de9cd9a
DN
1557 return gfc_finish_block (&block);
1558}
1559
1560
1561/* Translate the three variants of the SELECT CASE construct.
1562
1563 SELECT CASEs with INTEGER case expressions can be translated to an
1564 equivalent GENERIC switch statement, and for LOGICAL case
1565 expressions we build one or two if-else compares.
1566
1567 SELECT CASEs with CHARACTER case expressions are a whole different
1568 story, because they don't exist in GENERIC. So we sort them and
1569 do a binary search at runtime.
1570
1571 Fortran has no BREAK statement, and it does not allow jumps from
1572 one case block to another. That makes things a lot easier for
1573 the optimizers. */
1574
1575tree
1576gfc_trans_select (gfc_code * code)
1577{
6e45f57b 1578 gcc_assert (code && code->expr);
6de9cd9a
DN
1579
1580 /* Empty SELECT constructs are legal. */
1581 if (code->block == NULL)
1582 return build_empty_stmt ();
1583
1584 /* Select the correct translation function. */
1585 switch (code->expr->ts.type)
1586 {
1587 case BT_LOGICAL: return gfc_trans_logical_select (code);
1588 case BT_INTEGER: return gfc_trans_integer_select (code);
1589 case BT_CHARACTER: return gfc_trans_character_select (code);
1590 default:
1591 gfc_internal_error ("gfc_trans_select(): Bad type for case expr.");
1592 /* Not reached */
1593 }
1594}
1595
1596
640670c7
PT
1597/* Traversal function to substitute a replacement symtree if the symbol
1598 in the expression is the same as that passed. f == 2 signals that
1599 that variable itself is not to be checked - only the references.
1600 This group of functions is used when the variable expression in a
1601 FORALL assignment has internal references. For example:
1602 FORALL (i = 1:4) p(p(i)) = i
1603 The only recourse here is to store a copy of 'p' for the index
1604 expression. */
1605
1606static gfc_symtree *new_symtree;
1607static gfc_symtree *old_symtree;
1608
1609static bool
1610forall_replace (gfc_expr *expr, gfc_symbol *sym, int *f)
1611{
908a2235
PT
1612 if (expr->expr_type != EXPR_VARIABLE)
1613 return false;
640670c7
PT
1614
1615 if (*f == 2)
1616 *f = 1;
1617 else if (expr->symtree->n.sym == sym)
1618 expr->symtree = new_symtree;
1619
1620 return false;
1621}
1622
1623static void
1624forall_replace_symtree (gfc_expr *e, gfc_symbol *sym, int f)
1625{
1626 gfc_traverse_expr (e, sym, forall_replace, f);
1627}
1628
1629static bool
1630forall_restore (gfc_expr *expr,
1631 gfc_symbol *sym ATTRIBUTE_UNUSED,
1632 int *f ATTRIBUTE_UNUSED)
1633{
908a2235
PT
1634 if (expr->expr_type != EXPR_VARIABLE)
1635 return false;
640670c7
PT
1636
1637 if (expr->symtree == new_symtree)
1638 expr->symtree = old_symtree;
1639
1640 return false;
1641}
1642
1643static void
1644forall_restore_symtree (gfc_expr *e)
1645{
1646 gfc_traverse_expr (e, NULL, forall_restore, 0);
1647}
1648
1649static void
1650forall_make_variable_temp (gfc_code *c, stmtblock_t *pre, stmtblock_t *post)
1651{
1652 gfc_se tse;
1653 gfc_se rse;
1654 gfc_expr *e;
1655 gfc_symbol *new_sym;
1656 gfc_symbol *old_sym;
1657 gfc_symtree *root;
1658 tree tmp;
1659
1660 /* Build a copy of the lvalue. */
1661 old_symtree = c->expr->symtree;
1662 old_sym = old_symtree->n.sym;
1663 e = gfc_lval_expr_from_sym (old_sym);
1664 if (old_sym->attr.dimension)
1665 {
1666 gfc_init_se (&tse, NULL);
1667 gfc_conv_subref_array_arg (&tse, e, 0, INTENT_IN);
1668 gfc_add_block_to_block (pre, &tse.pre);
1669 gfc_add_block_to_block (post, &tse.post);
1670 tse.expr = build_fold_indirect_ref (tse.expr);
1671
1672 if (e->ts.type != BT_CHARACTER)
1673 {
1674 /* Use the variable offset for the temporary. */
1675 tmp = gfc_conv_descriptor_offset (tse.expr);
726a989a 1676 gfc_add_modify (pre, tmp,
640670c7
PT
1677 gfc_conv_array_offset (old_sym->backend_decl));
1678 }
1679 }
1680 else
1681 {
1682 gfc_init_se (&tse, NULL);
1683 gfc_init_se (&rse, NULL);
1684 gfc_conv_expr (&rse, e);
1685 if (e->ts.type == BT_CHARACTER)
1686 {
1687 tse.string_length = rse.string_length;
1688 tmp = gfc_get_character_type_len (gfc_default_character_kind,
1689 tse.string_length);
1690 tse.expr = gfc_conv_string_tmp (&tse, build_pointer_type (tmp),
1691 rse.string_length);
1692 gfc_add_block_to_block (pre, &tse.pre);
1693 gfc_add_block_to_block (post, &tse.post);
1694 }
1695 else
1696 {
1697 tmp = gfc_typenode_for_spec (&e->ts);
1698 tse.expr = gfc_create_var (tmp, "temp");
1699 }
1700
1701 tmp = gfc_trans_scalar_assign (&tse, &rse, e->ts, true,
1702 e->expr_type == EXPR_VARIABLE);
1703 gfc_add_expr_to_block (pre, tmp);
1704 }
1705 gfc_free_expr (e);
1706
1707 /* Create a new symbol to represent the lvalue. */
1708 new_sym = gfc_new_symbol (old_sym->name, NULL);
1709 new_sym->ts = old_sym->ts;
1710 new_sym->attr.referenced = 1;
1711 new_sym->attr.dimension = old_sym->attr.dimension;
1712 new_sym->attr.flavor = old_sym->attr.flavor;
1713
1714 /* Use the temporary as the backend_decl. */
1715 new_sym->backend_decl = tse.expr;
1716
1717 /* Create a fake symtree for it. */
1718 root = NULL;
1719 new_symtree = gfc_new_symtree (&root, old_sym->name);
1720 new_symtree->n.sym = new_sym;
1721 gcc_assert (new_symtree == root);
1722
1723 /* Go through the expression reference replacing the old_symtree
1724 with the new. */
1725 forall_replace_symtree (c->expr, old_sym, 2);
1726
1727 /* Now we have made this temporary, we might as well use it for
1728 the right hand side. */
1729 forall_replace_symtree (c->expr2, old_sym, 1);
1730}
1731
1732
1733/* Handles dependencies in forall assignments. */
1734static int
1735check_forall_dependencies (gfc_code *c, stmtblock_t *pre, stmtblock_t *post)
1736{
1737 gfc_ref *lref;
1738 gfc_ref *rref;
1739 int need_temp;
1740 gfc_symbol *lsym;
1741
1742 lsym = c->expr->symtree->n.sym;
1743 need_temp = gfc_check_dependency (c->expr, c->expr2, 0);
1744
1745 /* Now check for dependencies within the 'variable'
1746 expression itself. These are treated by making a complete
1747 copy of variable and changing all the references to it
1748 point to the copy instead. Note that the shallow copy of
1749 the variable will not suffice for derived types with
1750 pointer components. We therefore leave these to their
1751 own devices. */
1752 if (lsym->ts.type == BT_DERIVED
1753 && lsym->ts.derived->attr.pointer_comp)
1754 return need_temp;
1755
1756 new_symtree = NULL;
1757 if (find_forall_index (c->expr, lsym, 2) == SUCCESS)
1758 {
1759 forall_make_variable_temp (c, pre, post);
1760 need_temp = 0;
1761 }
1762
1763 /* Substrings with dependencies are treated in the same
1764 way. */
1765 if (c->expr->ts.type == BT_CHARACTER
1766 && c->expr->ref
1767 && c->expr2->expr_type == EXPR_VARIABLE
1768 && lsym == c->expr2->symtree->n.sym)
1769 {
1770 for (lref = c->expr->ref; lref; lref = lref->next)
1771 if (lref->type == REF_SUBSTRING)
1772 break;
1773 for (rref = c->expr2->ref; rref; rref = rref->next)
1774 if (rref->type == REF_SUBSTRING)
1775 break;
1776
1777 if (rref && lref
1778 && gfc_dep_compare_expr (rref->u.ss.start, lref->u.ss.start) < 0)
1779 {
1780 forall_make_variable_temp (c, pre, post);
1781 need_temp = 0;
1782 }
1783 }
1784 return need_temp;
1785}
1786
1787
1788static void
1789cleanup_forall_symtrees (gfc_code *c)
1790{
1791 forall_restore_symtree (c->expr);
1792 forall_restore_symtree (c->expr2);
1793 gfc_free (new_symtree->n.sym);
1794 gfc_free (new_symtree);
1795}
1796
1797
bfcabc6c
RS
1798/* Generate the loops for a FORALL block, specified by FORALL_TMP. BODY
1799 is the contents of the FORALL block/stmt to be iterated. MASK_FLAG
1800 indicates whether we should generate code to test the FORALLs mask
1801 array. OUTER is the loop header to be used for initializing mask
1802 indices.
1803
1804 The generated loop format is:
6de9cd9a
DN
1805 count = (end - start + step) / step
1806 loopvar = start
1807 while (1)
1808 {
1809 if (count <=0 )
1810 goto end_of_loop
1811 <body>
1812 loopvar += step
1813 count --
1814 }
1815 end_of_loop: */
1816
1817static tree
bfcabc6c
RS
1818gfc_trans_forall_loop (forall_info *forall_tmp, tree body,
1819 int mask_flag, stmtblock_t *outer)
6de9cd9a 1820{
bfcabc6c 1821 int n, nvar;
6de9cd9a
DN
1822 tree tmp;
1823 tree cond;
1824 stmtblock_t block;
1825 tree exit_label;
1826 tree count;
fcf3be37 1827 tree var, start, end, step;
6de9cd9a
DN
1828 iter_info *iter;
1829
bfcabc6c
RS
1830 /* Initialize the mask index outside the FORALL nest. */
1831 if (mask_flag && forall_tmp->mask)
726a989a 1832 gfc_add_modify (outer, forall_tmp->maskindex, gfc_index_zero_node);
bfcabc6c 1833
6de9cd9a 1834 iter = forall_tmp->this_loop;
bfcabc6c 1835 nvar = forall_tmp->nvar;
6de9cd9a
DN
1836 for (n = 0; n < nvar; n++)
1837 {
1838 var = iter->var;
1839 start = iter->start;
1840 end = iter->end;
1841 step = iter->step;
1842
1843 exit_label = gfc_build_label_decl (NULL_TREE);
1844 TREE_USED (exit_label) = 1;
1845
1846 /* The loop counter. */
1847 count = gfc_create_var (TREE_TYPE (var), "count");
1848
1849 /* The body of the loop. */
1850 gfc_init_block (&block);
1851
1852 /* The exit condition. */
61ead135
RG
1853 cond = fold_build2 (LE_EXPR, boolean_type_node,
1854 count, build_int_cst (TREE_TYPE (count), 0));
6de9cd9a 1855 tmp = build1_v (GOTO_EXPR, exit_label);
61ead135
RG
1856 tmp = fold_build3 (COND_EXPR, void_type_node,
1857 cond, tmp, build_empty_stmt ());
6de9cd9a
DN
1858 gfc_add_expr_to_block (&block, tmp);
1859
1860 /* The main loop body. */
1861 gfc_add_expr_to_block (&block, body);
1862
1863 /* Increment the loop variable. */
44855d8c 1864 tmp = fold_build2 (PLUS_EXPR, TREE_TYPE (var), var, step);
726a989a 1865 gfc_add_modify (&block, var, tmp);
6de9cd9a 1866
a8e12e4d
TS
1867 /* Advance to the next mask element. Only do this for the
1868 innermost loop. */
fcf3be37
JJ
1869 if (n == 0 && mask_flag && forall_tmp->mask)
1870 {
1871 tree maskindex = forall_tmp->maskindex;
44855d8c
TS
1872 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
1873 maskindex, gfc_index_one_node);
726a989a 1874 gfc_add_modify (&block, maskindex, tmp);
fcf3be37
JJ
1875 }
1876
6de9cd9a 1877 /* Decrement the loop counter. */
44855d8c
TS
1878 tmp = fold_build2 (MINUS_EXPR, TREE_TYPE (var), count,
1879 build_int_cst (TREE_TYPE (var), 1));
726a989a 1880 gfc_add_modify (&block, count, tmp);
6de9cd9a
DN
1881
1882 body = gfc_finish_block (&block);
1883
1884 /* Loop var initialization. */
1885 gfc_init_block (&block);
726a989a 1886 gfc_add_modify (&block, var, start);
6de9cd9a 1887
fcf3be37 1888
6de9cd9a 1889 /* Initialize the loop counter. */
10c7a96f
SB
1890 tmp = fold_build2 (MINUS_EXPR, TREE_TYPE (var), step, start);
1891 tmp = fold_build2 (PLUS_EXPR, TREE_TYPE (var), end, tmp);
1892 tmp = fold_build2 (TRUNC_DIV_EXPR, TREE_TYPE (var), tmp, step);
726a989a 1893 gfc_add_modify (&block, count, tmp);
6de9cd9a
DN
1894
1895 /* The loop expression. */
923ab88c 1896 tmp = build1_v (LOOP_EXPR, body);
6de9cd9a
DN
1897 gfc_add_expr_to_block (&block, tmp);
1898
1899 /* The exit label. */
1900 tmp = build1_v (LABEL_EXPR, exit_label);
1901 gfc_add_expr_to_block (&block, tmp);
1902
1903 body = gfc_finish_block (&block);
1904 iter = iter->next;
1905 }
1906 return body;
1907}
1908
1909
bfcabc6c
RS
1910/* Generate the body and loops according to MASK_FLAG. If MASK_FLAG
1911 is nonzero, the body is controlled by all masks in the forall nest.
1912 Otherwise, the innermost loop is not controlled by it's mask. This
1913 is used for initializing that mask. */
6de9cd9a
DN
1914
1915static tree
1916gfc_trans_nested_forall_loop (forall_info * nested_forall_info, tree body,
bfcabc6c 1917 int mask_flag)
6de9cd9a
DN
1918{
1919 tree tmp;
bfcabc6c 1920 stmtblock_t header;
6de9cd9a 1921 forall_info *forall_tmp;
bfcabc6c
RS
1922 tree mask, maskindex;
1923
1924 gfc_start_block (&header);
6de9cd9a
DN
1925
1926 forall_tmp = nested_forall_info;
bfcabc6c 1927 while (forall_tmp != NULL)
6de9cd9a 1928 {
bfcabc6c
RS
1929 /* Generate body with masks' control. */
1930 if (mask_flag)
6de9cd9a 1931 {
bfcabc6c
RS
1932 mask = forall_tmp->mask;
1933 maskindex = forall_tmp->maskindex;
6de9cd9a 1934
bfcabc6c
RS
1935 /* If a mask was specified make the assignment conditional. */
1936 if (mask)
1937 {
1d6b7f39 1938 tmp = gfc_build_array_ref (mask, maskindex, NULL);
bfcabc6c 1939 body = build3_v (COND_EXPR, tmp, body, build_empty_stmt ());
6de9cd9a 1940 }
6de9cd9a 1941 }
bfcabc6c 1942 body = gfc_trans_forall_loop (forall_tmp, body, mask_flag, &header);
e8d366ec 1943 forall_tmp = forall_tmp->prev_nest;
bfcabc6c 1944 mask_flag = 1;
6de9cd9a
DN
1945 }
1946
bfcabc6c
RS
1947 gfc_add_expr_to_block (&header, body);
1948 return gfc_finish_block (&header);
6de9cd9a
DN
1949}
1950
1951
1952/* Allocate data for holding a temporary array. Returns either a local
1953 temporary array or a pointer variable. */
1954
1955static tree
1956gfc_do_allocate (tree bytesize, tree size, tree * pdata, stmtblock_t * pblock,
1957 tree elem_type)
1958{
1959 tree tmpvar;
1960 tree type;
1961 tree tmp;
6de9cd9a
DN
1962
1963 if (INTEGER_CST_P (size))
1964 {
10c7a96f
SB
1965 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type, size,
1966 gfc_index_one_node);
6de9cd9a
DN
1967 }
1968 else
1969 tmp = NULL_TREE;
1970
7ab92584 1971 type = build_range_type (gfc_array_index_type, gfc_index_zero_node, tmp);
6de9cd9a
DN
1972 type = build_array_type (elem_type, type);
1973 if (gfc_can_put_var_on_stack (bytesize))
1974 {
6e45f57b 1975 gcc_assert (INTEGER_CST_P (size));
6de9cd9a
DN
1976 tmpvar = gfc_create_var (type, "temp");
1977 *pdata = NULL_TREE;
1978 }
1979 else
1980 {
1981 tmpvar = gfc_create_var (build_pointer_type (type), "temp");
1982 *pdata = convert (pvoid_type_node, tmpvar);
1983
1529b8d9 1984 tmp = gfc_call_malloc (pblock, TREE_TYPE (tmpvar), bytesize);
726a989a 1985 gfc_add_modify (pblock, tmpvar, tmp);
6de9cd9a
DN
1986 }
1987 return tmpvar;
1988}
1989
1990
1991/* Generate codes to copy the temporary to the actual lhs. */
1992
1993static tree
8de1f441 1994generate_loop_for_temp_to_lhs (gfc_expr *expr, tree tmp1, tree count3,
011daa76 1995 tree count1, tree wheremask, bool invert)
6de9cd9a
DN
1996{
1997 gfc_ss *lss;
1998 gfc_se lse, rse;
1999 stmtblock_t block, body;
2000 gfc_loopinfo loop1;
011daa76 2001 tree tmp;
6de9cd9a
DN
2002 tree wheremaskexpr;
2003
2004 /* Walk the lhs. */
2005 lss = gfc_walk_expr (expr);
2006
2007 if (lss == gfc_ss_terminator)
2008 {
2009 gfc_start_block (&block);
2010
2011 gfc_init_se (&lse, NULL);
2012
2013 /* Translate the expression. */
2014 gfc_conv_expr (&lse, expr);
2015
2016 /* Form the expression for the temporary. */
1d6b7f39 2017 tmp = gfc_build_array_ref (tmp1, count1, NULL);
6de9cd9a
DN
2018
2019 /* Use the scalar assignment as is. */
2020 gfc_add_block_to_block (&block, &lse.pre);
726a989a 2021 gfc_add_modify (&block, lse.expr, tmp);
6de9cd9a
DN
2022 gfc_add_block_to_block (&block, &lse.post);
2023
2024 /* Increment the count1. */
8de1f441
JJ
2025 tmp = fold_build2 (PLUS_EXPR, TREE_TYPE (count1), count1,
2026 gfc_index_one_node);
726a989a 2027 gfc_add_modify (&block, count1, tmp);
8de1f441 2028
6de9cd9a
DN
2029 tmp = gfc_finish_block (&block);
2030 }
2031 else
2032 {
2033 gfc_start_block (&block);
2034
2035 gfc_init_loopinfo (&loop1);
2036 gfc_init_se (&rse, NULL);
2037 gfc_init_se (&lse, NULL);
2038
2039 /* Associate the lss with the loop. */
2040 gfc_add_ss_to_loop (&loop1, lss);
2041
2042 /* Calculate the bounds of the scalarization. */
2043 gfc_conv_ss_startstride (&loop1);
2044 /* Setup the scalarizing loops. */
bdfd2ff0 2045 gfc_conv_loop_setup (&loop1, &expr->where);
6de9cd9a
DN
2046
2047 gfc_mark_ss_chain_used (lss, 1);
6de9cd9a
DN
2048
2049 /* Start the scalarized loop body. */
2050 gfc_start_scalarized_body (&loop1, &body);
2051
2052 /* Setup the gfc_se structures. */
2053 gfc_copy_loopinfo_to_se (&lse, &loop1);
2054 lse.ss = lss;
2055
2056 /* Form the expression of the temporary. */
2057 if (lss != gfc_ss_terminator)
1d6b7f39 2058 rse.expr = gfc_build_array_ref (tmp1, count1, NULL);
6de9cd9a
DN
2059 /* Translate expr. */
2060 gfc_conv_expr (&lse, expr);
2061
2062 /* Use the scalar assignment. */
5046aff5
PT
2063 rse.string_length = lse.string_length;
2064 tmp = gfc_trans_scalar_assign (&lse, &rse, expr->ts, false, false);
6de9cd9a 2065
011daa76
RS
2066 /* Form the mask expression according to the mask tree list. */
2067 if (wheremask)
2068 {
1d6b7f39 2069 wheremaskexpr = gfc_build_array_ref (wheremask, count3, NULL);
011daa76
RS
2070 if (invert)
2071 wheremaskexpr = fold_build1 (TRUTH_NOT_EXPR,
2072 TREE_TYPE (wheremaskexpr),
2073 wheremaskexpr);
2074 tmp = fold_build3 (COND_EXPR, void_type_node,
2075 wheremaskexpr, tmp, build_empty_stmt ());
6de9cd9a
DN
2076 }
2077
2078 gfc_add_expr_to_block (&body, tmp);
2079
8de1f441 2080 /* Increment count1. */
10c7a96f 2081 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
8de1f441 2082 count1, gfc_index_one_node);
726a989a 2083 gfc_add_modify (&body, count1, tmp);
6de9cd9a
DN
2084
2085 /* Increment count3. */
2086 if (count3)
8de1f441
JJ
2087 {
2088 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
10c7a96f 2089 count3, gfc_index_one_node);
726a989a 2090 gfc_add_modify (&body, count3, tmp);
8de1f441 2091 }
6de9cd9a
DN
2092
2093 /* Generate the copying loops. */
2094 gfc_trans_scalarizing_loops (&loop1, &body);
2095 gfc_add_block_to_block (&block, &loop1.pre);
2096 gfc_add_block_to_block (&block, &loop1.post);
2097 gfc_cleanup_loop (&loop1);
2098
6de9cd9a
DN
2099 tmp = gfc_finish_block (&block);
2100 }
2101 return tmp;
2102}
2103
2104
011daa76
RS
2105/* Generate codes to copy rhs to the temporary. TMP1 is the address of
2106 temporary, LSS and RSS are formed in function compute_inner_temp_size(),
2107 and should not be freed. WHEREMASK is the conditional execution mask
2108 whose sense may be inverted by INVERT. */
6de9cd9a
DN
2109
2110static tree
8de1f441
JJ
2111generate_loop_for_rhs_to_temp (gfc_expr *expr2, tree tmp1, tree count3,
2112 tree count1, gfc_ss *lss, gfc_ss *rss,
011daa76 2113 tree wheremask, bool invert)
6de9cd9a
DN
2114{
2115 stmtblock_t block, body1;
2116 gfc_loopinfo loop;
2117 gfc_se lse;
2118 gfc_se rse;
011daa76 2119 tree tmp;
6de9cd9a
DN
2120 tree wheremaskexpr;
2121
2122 gfc_start_block (&block);
2123
2124 gfc_init_se (&rse, NULL);
2125 gfc_init_se (&lse, NULL);
2126
2127 if (lss == gfc_ss_terminator)
2128 {
2129 gfc_init_block (&body1);
2130 gfc_conv_expr (&rse, expr2);
1d6b7f39 2131 lse.expr = gfc_build_array_ref (tmp1, count1, NULL);
6de9cd9a
DN
2132 }
2133 else
2134 {
1f2959f0 2135 /* Initialize the loop. */
6de9cd9a
DN
2136 gfc_init_loopinfo (&loop);
2137
2138 /* We may need LSS to determine the shape of the expression. */
2139 gfc_add_ss_to_loop (&loop, lss);
2140 gfc_add_ss_to_loop (&loop, rss);
2141
2142 gfc_conv_ss_startstride (&loop);
bdfd2ff0 2143 gfc_conv_loop_setup (&loop, &expr2->where);
6de9cd9a
DN
2144
2145 gfc_mark_ss_chain_used (rss, 1);
2146 /* Start the loop body. */
2147 gfc_start_scalarized_body (&loop, &body1);
2148
2149 /* Translate the expression. */
2150 gfc_copy_loopinfo_to_se (&rse, &loop);
2151 rse.ss = rss;
2152 gfc_conv_expr (&rse, expr2);
2153
2154 /* Form the expression of the temporary. */
1d6b7f39 2155 lse.expr = gfc_build_array_ref (tmp1, count1, NULL);
6de9cd9a
DN
2156 }
2157
2158 /* Use the scalar assignment. */
5046aff5
PT
2159 lse.string_length = rse.string_length;
2160 tmp = gfc_trans_scalar_assign (&lse, &rse, expr2->ts, true,
2161 expr2->expr_type == EXPR_VARIABLE);
6de9cd9a
DN
2162
2163 /* Form the mask expression according to the mask tree list. */
2164 if (wheremask)
2165 {
1d6b7f39 2166 wheremaskexpr = gfc_build_array_ref (wheremask, count3, NULL);
011daa76
RS
2167 if (invert)
2168 wheremaskexpr = fold_build1 (TRUTH_NOT_EXPR,
2169 TREE_TYPE (wheremaskexpr),
2170 wheremaskexpr);
61ead135
RG
2171 tmp = fold_build3 (COND_EXPR, void_type_node,
2172 wheremaskexpr, tmp, build_empty_stmt ());
6de9cd9a
DN
2173 }
2174
2175 gfc_add_expr_to_block (&body1, tmp);
2176
2177 if (lss == gfc_ss_terminator)
2178 {
2179 gfc_add_block_to_block (&block, &body1);
8de1f441
JJ
2180
2181 /* Increment count1. */
2182 tmp = fold_build2 (PLUS_EXPR, TREE_TYPE (count1), count1,
2183 gfc_index_one_node);
726a989a 2184 gfc_add_modify (&block, count1, tmp);
6de9cd9a
DN
2185 }
2186 else
2187 {
8de1f441 2188 /* Increment count1. */
10c7a96f 2189 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
8de1f441 2190 count1, gfc_index_one_node);
726a989a 2191 gfc_add_modify (&body1, count1, tmp);
6de9cd9a
DN
2192
2193 /* Increment count3. */
2194 if (count3)
8de1f441
JJ
2195 {
2196 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
10c7a96f 2197 count3, gfc_index_one_node);
726a989a 2198 gfc_add_modify (&body1, count3, tmp);
8de1f441 2199 }
6de9cd9a
DN
2200
2201 /* Generate the copying loops. */
2202 gfc_trans_scalarizing_loops (&loop, &body1);
2203
2204 gfc_add_block_to_block (&block, &loop.pre);
2205 gfc_add_block_to_block (&block, &loop.post);
2206
2207 gfc_cleanup_loop (&loop);
2208 /* TODO: Reuse lss and rss when copying temp->lhs. Need to be careful
8de1f441 2209 as tree nodes in SS may not be valid in different scope. */
6de9cd9a 2210 }
6de9cd9a
DN
2211
2212 tmp = gfc_finish_block (&block);
2213 return tmp;
2214}
2215
2216
2217/* Calculate the size of temporary needed in the assignment inside forall.
2218 LSS and RSS are filled in this function. */
2219
2220static tree
2221compute_inner_temp_size (gfc_expr *expr1, gfc_expr *expr2,
2222 stmtblock_t * pblock,
2223 gfc_ss **lss, gfc_ss **rss)
2224{
2225 gfc_loopinfo loop;
2226 tree size;
2227 int i;
ca86ddcc 2228 int save_flag;
6de9cd9a
DN
2229 tree tmp;
2230
2231 *lss = gfc_walk_expr (expr1);
2232 *rss = NULL;
2233
7ab92584 2234 size = gfc_index_one_node;
6de9cd9a
DN
2235 if (*lss != gfc_ss_terminator)
2236 {
2237 gfc_init_loopinfo (&loop);
2238
2239 /* Walk the RHS of the expression. */
2240 *rss = gfc_walk_expr (expr2);
2241 if (*rss == gfc_ss_terminator)
2242 {
2243 /* The rhs is scalar. Add a ss for the expression. */
2244 *rss = gfc_get_ss ();
2245 (*rss)->next = gfc_ss_terminator;
2246 (*rss)->type = GFC_SS_SCALAR;
2247 (*rss)->expr = expr2;
2248 }
2249
2250 /* Associate the SS with the loop. */
2251 gfc_add_ss_to_loop (&loop, *lss);
2252 /* We don't actually need to add the rhs at this point, but it might
2253 make guessing the loop bounds a bit easier. */
2254 gfc_add_ss_to_loop (&loop, *rss);
2255
2256 /* We only want the shape of the expression, not rest of the junk
2257 generated by the scalarizer. */
2258 loop.array_parameter = 1;
2259
2260 /* Calculate the bounds of the scalarization. */
ca86ddcc
FXC
2261 save_flag = flag_bounds_check;
2262 flag_bounds_check = 0;
6de9cd9a 2263 gfc_conv_ss_startstride (&loop);
ca86ddcc 2264 flag_bounds_check = save_flag;
bdfd2ff0 2265 gfc_conv_loop_setup (&loop, &expr2->where);
6de9cd9a
DN
2266
2267 /* Figure out how many elements we need. */
2268 for (i = 0; i < loop.dimen; i++)
2269 {
10c7a96f
SB
2270 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
2271 gfc_index_one_node, loop.from[i]);
2272 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
2273 tmp, loop.to[i]);
2274 size = fold_build2 (MULT_EXPR, gfc_array_index_type, size, tmp);
6de9cd9a
DN
2275 }
2276 gfc_add_block_to_block (pblock, &loop.pre);
2277 size = gfc_evaluate_now (size, pblock);
2278 gfc_add_block_to_block (pblock, &loop.post);
2279
2280 /* TODO: write a function that cleans up a loopinfo without freeing
2281 the SS chains. Currently a NOP. */
2282 }
2283
2284 return size;
2285}
2286
2287
2ad62c9b
RS
2288/* Calculate the overall iterator number of the nested forall construct.
2289 This routine actually calculates the number of times the body of the
2290 nested forall specified by NESTED_FORALL_INFO is executed and multiplies
2291 that by the expression INNER_SIZE. The BLOCK argument specifies the
2292 block in which to calculate the result, and the optional INNER_SIZE_BODY
2293 argument contains any statements that need to executed (inside the loop)
2294 to initialize or calculate INNER_SIZE. */
6de9cd9a
DN
2295
2296static tree
2297compute_overall_iter_number (forall_info *nested_forall_info, tree inner_size,
8de1f441 2298 stmtblock_t *inner_size_body, stmtblock_t *block)
6de9cd9a 2299{
2ad62c9b 2300 forall_info *forall_tmp = nested_forall_info;
6de9cd9a
DN
2301 tree tmp, number;
2302 stmtblock_t body;
2303
2ad62c9b
RS
2304 /* We can eliminate the innermost unconditional loops with constant
2305 array bounds. */
3bf783b7
RS
2306 if (INTEGER_CST_P (inner_size))
2307 {
2ad62c9b
RS
2308 while (forall_tmp
2309 && !forall_tmp->mask
2310 && INTEGER_CST_P (forall_tmp->size))
3bf783b7 2311 {
2ad62c9b
RS
2312 inner_size = fold_build2 (MULT_EXPR, gfc_array_index_type,
2313 inner_size, forall_tmp->size);
2314 forall_tmp = forall_tmp->prev_nest;
3bf783b7 2315 }
2ad62c9b
RS
2316
2317 /* If there are no loops left, we have our constant result. */
2318 if (!forall_tmp)
2319 return inner_size;
3bf783b7 2320 }
2ad62c9b
RS
2321
2322 /* Otherwise, create a temporary variable to compute the result. */
6de9cd9a 2323 number = gfc_create_var (gfc_array_index_type, "num");
726a989a 2324 gfc_add_modify (block, number, gfc_index_zero_node);
6de9cd9a
DN
2325
2326 gfc_start_block (&body);
8de1f441
JJ
2327 if (inner_size_body)
2328 gfc_add_block_to_block (&body, inner_size_body);
2ad62c9b 2329 if (forall_tmp)
44855d8c
TS
2330 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
2331 number, inner_size);
6de9cd9a
DN
2332 else
2333 tmp = inner_size;
726a989a 2334 gfc_add_modify (&body, number, tmp);
6de9cd9a
DN
2335 tmp = gfc_finish_block (&body);
2336
2337 /* Generate loops. */
2ad62c9b
RS
2338 if (forall_tmp != NULL)
2339 tmp = gfc_trans_nested_forall_loop (forall_tmp, tmp, 1);
6de9cd9a
DN
2340
2341 gfc_add_expr_to_block (block, tmp);
2342
2343 return number;
2344}
2345
2346
8de1f441
JJ
2347/* Allocate temporary for forall construct. SIZE is the size of temporary
2348 needed. PTEMP1 is returned for space free. */
6de9cd9a
DN
2349
2350static tree
8de1f441
JJ
2351allocate_temp_for_forall_nest_1 (tree type, tree size, stmtblock_t * block,
2352 tree * ptemp1)
6de9cd9a 2353{
bfcabc6c 2354 tree bytesize;
6de9cd9a 2355 tree unit;
6de9cd9a 2356 tree tmp;
6de9cd9a 2357
7c57b2f1 2358 unit = fold_convert (gfc_array_index_type, TYPE_SIZE_UNIT (type));
bfcabc6c
RS
2359 if (!integer_onep (unit))
2360 bytesize = fold_build2 (MULT_EXPR, gfc_array_index_type, size, unit);
2361 else
2362 bytesize = size;
6de9cd9a
DN
2363
2364 *ptemp1 = NULL;
bfcabc6c 2365 tmp = gfc_do_allocate (bytesize, size, ptemp1, block, type);
6de9cd9a
DN
2366
2367 if (*ptemp1)
bfcabc6c 2368 tmp = build_fold_indirect_ref (tmp);
6de9cd9a
DN
2369 return tmp;
2370}
2371
2372
8de1f441
JJ
2373/* Allocate temporary for forall construct according to the information in
2374 nested_forall_info. INNER_SIZE is the size of temporary needed in the
2375 assignment inside forall. PTEMP1 is returned for space free. */
2376
2377static tree
2378allocate_temp_for_forall_nest (forall_info * nested_forall_info, tree type,
2379 tree inner_size, stmtblock_t * inner_size_body,
2380 stmtblock_t * block, tree * ptemp1)
2381{
2382 tree size;
2383
2384 /* Calculate the total size of temporary needed in forall construct. */
2385 size = compute_overall_iter_number (nested_forall_info, inner_size,
2386 inner_size_body, block);
2387
2388 return allocate_temp_for_forall_nest_1 (type, size, block, ptemp1);
2389}
2390
2391
2392/* Handle assignments inside forall which need temporary.
2393
2394 forall (i=start:end:stride; maskexpr)
2395 e<i> = f<i>
2396 end forall
2397 (where e,f<i> are arbitrary expressions possibly involving i
2398 and there is a dependency between e<i> and f<i>)
2399 Translates to:
2400 masktmp(:) = maskexpr(:)
2401
2402 maskindex = 0;
2403 count1 = 0;
2404 num = 0;
2405 for (i = start; i <= end; i += stride)
2406 num += SIZE (f<i>)
2407 count1 = 0;
2408 ALLOCATE (tmp(num))
2409 for (i = start; i <= end; i += stride)
2410 {
2411 if (masktmp[maskindex++])
2412 tmp[count1++] = f<i>
2413 }
2414 maskindex = 0;
2415 count1 = 0;
2416 for (i = start; i <= end; i += stride)
2417 {
2418 if (masktmp[maskindex++])
2419 e<i> = tmp[count1++]
2420 }
2421 DEALLOCATE (tmp)
2422 */
6de9cd9a 2423static void
011daa76
RS
2424gfc_trans_assign_need_temp (gfc_expr * expr1, gfc_expr * expr2,
2425 tree wheremask, bool invert,
6de9cd9a
DN
2426 forall_info * nested_forall_info,
2427 stmtblock_t * block)
2428{
2429 tree type;
2430 tree inner_size;
2431 gfc_ss *lss, *rss;
8de1f441 2432 tree count, count1;
6de9cd9a
DN
2433 tree tmp, tmp1;
2434 tree ptemp1;
8de1f441 2435 stmtblock_t inner_size_body;
6de9cd9a 2436
8de1f441
JJ
2437 /* Create vars. count1 is the current iterator number of the nested
2438 forall. */
6de9cd9a 2439 count1 = gfc_create_var (gfc_array_index_type, "count1");
6de9cd9a
DN
2440
2441 /* Count is the wheremask index. */
2442 if (wheremask)
2443 {
2444 count = gfc_create_var (gfc_array_index_type, "count");
726a989a 2445 gfc_add_modify (block, count, gfc_index_zero_node);
6de9cd9a
DN
2446 }
2447 else
2448 count = NULL;
2449
2450 /* Initialize count1. */
726a989a 2451 gfc_add_modify (block, count1, gfc_index_zero_node);
6de9cd9a
DN
2452
2453 /* Calculate the size of temporary needed in the assignment. Return loop, lss
2454 and rss which are used in function generate_loop_for_rhs_to_temp(). */
8de1f441
JJ
2455 gfc_init_block (&inner_size_body);
2456 inner_size = compute_inner_temp_size (expr1, expr2, &inner_size_body,
2457 &lss, &rss);
6de9cd9a
DN
2458
2459 /* The type of LHS. Used in function allocate_temp_for_forall_nest */
640670c7
PT
2460 if (expr1->ts.type == BT_CHARACTER && expr1->ts.cl->length)
2461 {
2462 if (!expr1->ts.cl->backend_decl)
2463 {
2464 gfc_se tse;
2465 gfc_init_se (&tse, NULL);
2466 gfc_conv_expr (&tse, expr1->ts.cl->length);
2467 expr1->ts.cl->backend_decl = tse.expr;
2468 }
2469 type = gfc_get_character_type_len (gfc_default_character_kind,
2470 expr1->ts.cl->backend_decl);
2471 }
2472 else
2473 type = gfc_typenode_for_spec (&expr1->ts);
6de9cd9a
DN
2474
2475 /* Allocate temporary for nested forall construct according to the
f7b529fa 2476 information in nested_forall_info and inner_size. */
8de1f441
JJ
2477 tmp1 = allocate_temp_for_forall_nest (nested_forall_info, type, inner_size,
2478 &inner_size_body, block, &ptemp1);
6de9cd9a 2479
6de9cd9a 2480 /* Generate codes to copy rhs to the temporary . */
8de1f441 2481 tmp = generate_loop_for_rhs_to_temp (expr2, tmp1, count, count1, lss, rss,
011daa76 2482 wheremask, invert);
6de9cd9a 2483
1f2959f0 2484 /* Generate body and loops according to the information in
6de9cd9a 2485 nested_forall_info. */
bfcabc6c 2486 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
6de9cd9a
DN
2487 gfc_add_expr_to_block (block, tmp);
2488
2489 /* Reset count1. */
726a989a 2490 gfc_add_modify (block, count1, gfc_index_zero_node);
6de9cd9a 2491
6de9cd9a
DN
2492 /* Reset count. */
2493 if (wheremask)
726a989a 2494 gfc_add_modify (block, count, gfc_index_zero_node);
6de9cd9a
DN
2495
2496 /* Generate codes to copy the temporary to lhs. */
011daa76
RS
2497 tmp = generate_loop_for_temp_to_lhs (expr1, tmp1, count, count1,
2498 wheremask, invert);
6de9cd9a 2499
1f2959f0 2500 /* Generate body and loops according to the information in
6de9cd9a 2501 nested_forall_info. */
bfcabc6c 2502 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
6de9cd9a
DN
2503 gfc_add_expr_to_block (block, tmp);
2504
2505 if (ptemp1)
2506 {
2507 /* Free the temporary. */
1529b8d9 2508 tmp = gfc_call_free (ptemp1);
6de9cd9a
DN
2509 gfc_add_expr_to_block (block, tmp);
2510 }
2511}
2512
2513
2514/* Translate pointer assignment inside FORALL which need temporary. */
2515
2516static void
2517gfc_trans_pointer_assign_need_temp (gfc_expr * expr1, gfc_expr * expr2,
2518 forall_info * nested_forall_info,
2519 stmtblock_t * block)
2520{
2521 tree type;
2522 tree inner_size;
2523 gfc_ss *lss, *rss;
2524 gfc_se lse;
2525 gfc_se rse;
2526 gfc_ss_info *info;
2527 gfc_loopinfo loop;
2528 tree desc;
2529 tree parm;
2530 tree parmtype;
2531 stmtblock_t body;
2532 tree count;
2533 tree tmp, tmp1, ptemp1;
6de9cd9a
DN
2534
2535 count = gfc_create_var (gfc_array_index_type, "count");
726a989a 2536 gfc_add_modify (block, count, gfc_index_zero_node);
6de9cd9a
DN
2537
2538 inner_size = integer_one_node;
2539 lss = gfc_walk_expr (expr1);
2540 rss = gfc_walk_expr (expr2);
2541 if (lss == gfc_ss_terminator)
2542 {
2543 type = gfc_typenode_for_spec (&expr1->ts);
2544 type = build_pointer_type (type);
2545
2546 /* Allocate temporary for nested forall construct according to the
2547 information in nested_forall_info and inner_size. */
8de1f441
JJ
2548 tmp1 = allocate_temp_for_forall_nest (nested_forall_info, type,
2549 inner_size, NULL, block, &ptemp1);
6de9cd9a
DN
2550 gfc_start_block (&body);
2551 gfc_init_se (&lse, NULL);
1d6b7f39 2552 lse.expr = gfc_build_array_ref (tmp1, count, NULL);
6de9cd9a
DN
2553 gfc_init_se (&rse, NULL);
2554 rse.want_pointer = 1;
2555 gfc_conv_expr (&rse, expr2);
2556 gfc_add_block_to_block (&body, &rse.pre);
726a989a 2557 gfc_add_modify (&body, lse.expr,
cc2804f1 2558 fold_convert (TREE_TYPE (lse.expr), rse.expr));
6de9cd9a
DN
2559 gfc_add_block_to_block (&body, &rse.post);
2560
2561 /* Increment count. */
10c7a96f
SB
2562 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
2563 count, gfc_index_one_node);
726a989a 2564 gfc_add_modify (&body, count, tmp);
6de9cd9a
DN
2565
2566 tmp = gfc_finish_block (&body);
2567
1f2959f0 2568 /* Generate body and loops according to the information in
6de9cd9a 2569 nested_forall_info. */
bfcabc6c 2570 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
6de9cd9a
DN
2571 gfc_add_expr_to_block (block, tmp);
2572
2573 /* Reset count. */
726a989a 2574 gfc_add_modify (block, count, gfc_index_zero_node);
6de9cd9a 2575
6de9cd9a
DN
2576 gfc_start_block (&body);
2577 gfc_init_se (&lse, NULL);
2578 gfc_init_se (&rse, NULL);
1d6b7f39 2579 rse.expr = gfc_build_array_ref (tmp1, count, NULL);
6de9cd9a
DN
2580 lse.want_pointer = 1;
2581 gfc_conv_expr (&lse, expr1);
2582 gfc_add_block_to_block (&body, &lse.pre);
726a989a 2583 gfc_add_modify (&body, lse.expr, rse.expr);
6de9cd9a
DN
2584 gfc_add_block_to_block (&body, &lse.post);
2585 /* Increment count. */
10c7a96f
SB
2586 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
2587 count, gfc_index_one_node);
726a989a 2588 gfc_add_modify (&body, count, tmp);
6de9cd9a
DN
2589 tmp = gfc_finish_block (&body);
2590
1f2959f0 2591 /* Generate body and loops according to the information in
6de9cd9a 2592 nested_forall_info. */
bfcabc6c 2593 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
6de9cd9a
DN
2594 gfc_add_expr_to_block (block, tmp);
2595 }
2596 else
2597 {
2598 gfc_init_loopinfo (&loop);
2599
2600 /* Associate the SS with the loop. */
2601 gfc_add_ss_to_loop (&loop, rss);
2602
2603 /* Setup the scalarizing loops and bounds. */
2604 gfc_conv_ss_startstride (&loop);
2605
bdfd2ff0 2606 gfc_conv_loop_setup (&loop, &expr2->where);
6de9cd9a
DN
2607
2608 info = &rss->data.info;
2609 desc = info->descriptor;
2610
2611 /* Make a new descriptor. */
2612 parmtype = gfc_get_element_type (TREE_TYPE (desc));
2613 parmtype = gfc_get_array_type_bounds (parmtype, loop.dimen,
fad0afd7
JJ
2614 loop.from, loop.to, 1,
2615 GFC_ARRAY_UNKNOWN);
6de9cd9a
DN
2616
2617 /* Allocate temporary for nested forall construct. */
2618 tmp1 = allocate_temp_for_forall_nest (nested_forall_info, parmtype,
8de1f441 2619 inner_size, NULL, block, &ptemp1);
6de9cd9a
DN
2620 gfc_start_block (&body);
2621 gfc_init_se (&lse, NULL);
1d6b7f39 2622 lse.expr = gfc_build_array_ref (tmp1, count, NULL);
6de9cd9a
DN
2623 lse.direct_byref = 1;
2624 rss = gfc_walk_expr (expr2);
2625 gfc_conv_expr_descriptor (&lse, expr2, rss);
2626
2627 gfc_add_block_to_block (&body, &lse.pre);
2628 gfc_add_block_to_block (&body, &lse.post);
2629
2630 /* Increment count. */
10c7a96f
SB
2631 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
2632 count, gfc_index_one_node);
726a989a 2633 gfc_add_modify (&body, count, tmp);
6de9cd9a
DN
2634
2635 tmp = gfc_finish_block (&body);
2636
1f2959f0 2637 /* Generate body and loops according to the information in
6de9cd9a 2638 nested_forall_info. */
bfcabc6c 2639 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
6de9cd9a
DN
2640 gfc_add_expr_to_block (block, tmp);
2641
2642 /* Reset count. */
726a989a 2643 gfc_add_modify (block, count, gfc_index_zero_node);
6de9cd9a 2644
1d6b7f39 2645 parm = gfc_build_array_ref (tmp1, count, NULL);
6de9cd9a
DN
2646 lss = gfc_walk_expr (expr1);
2647 gfc_init_se (&lse, NULL);
2648 gfc_conv_expr_descriptor (&lse, expr1, lss);
726a989a 2649 gfc_add_modify (&lse.pre, lse.expr, parm);
6de9cd9a
DN
2650 gfc_start_block (&body);
2651 gfc_add_block_to_block (&body, &lse.pre);
2652 gfc_add_block_to_block (&body, &lse.post);
2653
2654 /* Increment count. */
10c7a96f
SB
2655 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
2656 count, gfc_index_one_node);
726a989a 2657 gfc_add_modify (&body, count, tmp);
6de9cd9a
DN
2658
2659 tmp = gfc_finish_block (&body);
2660
bfcabc6c 2661 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
6de9cd9a
DN
2662 gfc_add_expr_to_block (block, tmp);
2663 }
2664 /* Free the temporary. */
2665 if (ptemp1)
2666 {
1529b8d9 2667 tmp = gfc_call_free (ptemp1);
6de9cd9a
DN
2668 gfc_add_expr_to_block (block, tmp);
2669 }
2670}
2671
2672
2673/* FORALL and WHERE statements are really nasty, especially when you nest
2674 them. All the rhs of a forall assignment must be evaluated before the
2675 actual assignments are performed. Presumably this also applies to all the
2676 assignments in an inner where statement. */
2677
2678/* Generate code for a FORALL statement. Any temporaries are allocated as a
2679 linear array, relying on the fact that we process in the same order in all
2680 loops.
2681
2682 forall (i=start:end:stride; maskexpr)
2683 e<i> = f<i>
2684 g<i> = h<i>
2685 end forall
e7dc5b4f 2686 (where e,f,g,h<i> are arbitrary expressions possibly involving i)
6de9cd9a 2687 Translates to:
8de1f441 2688 count = ((end + 1 - start) / stride)
6de9cd9a
DN
2689 masktmp(:) = maskexpr(:)
2690
2691 maskindex = 0;
2692 for (i = start; i <= end; i += stride)
2693 {
2694 if (masktmp[maskindex++])
2695 e<i> = f<i>
2696 }
2697 maskindex = 0;
2698 for (i = start; i <= end; i += stride)
2699 {
2700 if (masktmp[maskindex++])
cafa34aa 2701 g<i> = h<i>
6de9cd9a
DN
2702 }
2703
2704 Note that this code only works when there are no dependencies.
2705 Forall loop with array assignments and data dependencies are a real pain,
2706 because the size of the temporary cannot always be determined before the
1f2959f0 2707 loop is executed. This problem is compounded by the presence of nested
6de9cd9a
DN
2708 FORALL constructs.
2709 */
2710
2711static tree
2712gfc_trans_forall_1 (gfc_code * code, forall_info * nested_forall_info)
2713{
640670c7
PT
2714 stmtblock_t pre;
2715 stmtblock_t post;
6de9cd9a
DN
2716 stmtblock_t block;
2717 stmtblock_t body;
2718 tree *var;
2719 tree *start;
2720 tree *end;
2721 tree *step;
2722 gfc_expr **varexpr;
2723 tree tmp;
2724 tree assign;
2725 tree size;
6de9cd9a
DN
2726 tree maskindex;
2727 tree mask;
2728 tree pmask;
2729 int n;
2730 int nvar;
2731 int need_temp;
2732 gfc_forall_iterator *fa;
2733 gfc_se se;
2734 gfc_code *c;
7b5b57b7 2735 gfc_saved_var *saved_vars;
bfcabc6c
RS
2736 iter_info *this_forall;
2737 forall_info *info;
e35a0e64
RS
2738 bool need_mask;
2739
2740 /* Do nothing if the mask is false. */
2741 if (code->expr
2742 && code->expr->expr_type == EXPR_CONSTANT
2743 && !code->expr->value.logical)
2744 return build_empty_stmt ();
6de9cd9a
DN
2745
2746 n = 0;
2747 /* Count the FORALL index number. */
2748 for (fa = code->ext.forall_iterator; fa; fa = fa->next)
2749 n++;
2750 nvar = n;
2751
2752 /* Allocate the space for var, start, end, step, varexpr. */
2753 var = (tree *) gfc_getmem (nvar * sizeof (tree));
2754 start = (tree *) gfc_getmem (nvar * sizeof (tree));
2755 end = (tree *) gfc_getmem (nvar * sizeof (tree));
2756 step = (tree *) gfc_getmem (nvar * sizeof (tree));
2757 varexpr = (gfc_expr **) gfc_getmem (nvar * sizeof (gfc_expr *));
7b5b57b7 2758 saved_vars = (gfc_saved_var *) gfc_getmem (nvar * sizeof (gfc_saved_var));
6de9cd9a
DN
2759
2760 /* Allocate the space for info. */
2761 info = (forall_info *) gfc_getmem (sizeof (forall_info));
bfcabc6c 2762
640670c7
PT
2763 gfc_start_block (&pre);
2764 gfc_init_block (&post);
2765 gfc_init_block (&block);
bfcabc6c 2766
6de9cd9a
DN
2767 n = 0;
2768 for (fa = code->ext.forall_iterator; fa; fa = fa->next)
2769 {
2770 gfc_symbol *sym = fa->var->symtree->n.sym;
2771
bfcabc6c 2772 /* Allocate space for this_forall. */
6de9cd9a
DN
2773 this_forall = (iter_info *) gfc_getmem (sizeof (iter_info));
2774
6de9cd9a
DN
2775 /* Create a temporary variable for the FORALL index. */
2776 tmp = gfc_typenode_for_spec (&sym->ts);
2777 var[n] = gfc_create_var (tmp, sym->name);
7b5b57b7
PB
2778 gfc_shadow_sym (sym, var[n], &saved_vars[n]);
2779
6de9cd9a
DN
2780 /* Record it in this_forall. */
2781 this_forall->var = var[n];
2782
2783 /* Replace the index symbol's backend_decl with the temporary decl. */
2784 sym->backend_decl = var[n];
2785
2786 /* Work out the start, end and stride for the loop. */
2787 gfc_init_se (&se, NULL);
2788 gfc_conv_expr_val (&se, fa->start);
2789 /* Record it in this_forall. */
2790 this_forall->start = se.expr;
2791 gfc_add_block_to_block (&block, &se.pre);
2792 start[n] = se.expr;
2793
2794 gfc_init_se (&se, NULL);
2795 gfc_conv_expr_val (&se, fa->end);
2796 /* Record it in this_forall. */
2797 this_forall->end = se.expr;
2798 gfc_make_safe_expr (&se);
2799 gfc_add_block_to_block (&block, &se.pre);
2800 end[n] = se.expr;
2801
2802 gfc_init_se (&se, NULL);
2803 gfc_conv_expr_val (&se, fa->stride);
2804 /* Record it in this_forall. */
2805 this_forall->step = se.expr;
2806 gfc_make_safe_expr (&se);
2807 gfc_add_block_to_block (&block, &se.pre);
2808 step[n] = se.expr;
2809
2810 /* Set the NEXT field of this_forall to NULL. */
2811 this_forall->next = NULL;
2812 /* Link this_forall to the info construct. */
bfcabc6c 2813 if (info->this_loop)
6de9cd9a 2814 {
bfcabc6c 2815 iter_info *iter_tmp = info->this_loop;
6de9cd9a
DN
2816 while (iter_tmp->next != NULL)
2817 iter_tmp = iter_tmp->next;
2818 iter_tmp->next = this_forall;
2819 }
bfcabc6c
RS
2820 else
2821 info->this_loop = this_forall;
6de9cd9a
DN
2822
2823 n++;
2824 }
2825 nvar = n;
2826
bfcabc6c 2827 /* Calculate the size needed for the current forall level. */
7ab92584 2828 size = gfc_index_one_node;
6de9cd9a
DN
2829 for (n = 0; n < nvar; n++)
2830 {
6de9cd9a 2831 /* size = (end + step - start) / step. */
10c7a96f
SB
2832 tmp = fold_build2 (MINUS_EXPR, TREE_TYPE (start[n]),
2833 step[n], start[n]);
2834 tmp = fold_build2 (PLUS_EXPR, TREE_TYPE (end[n]), end[n], tmp);
6de9cd9a 2835
10c7a96f 2836 tmp = fold_build2 (FLOOR_DIV_EXPR, TREE_TYPE (tmp), tmp, step[n]);
6de9cd9a
DN
2837 tmp = convert (gfc_array_index_type, tmp);
2838
10c7a96f 2839 size = fold_build2 (MULT_EXPR, gfc_array_index_type, size, tmp);
6de9cd9a
DN
2840 }
2841
2842 /* Record the nvar and size of current forall level. */
2843 info->nvar = nvar;
2844 info->size = size;
2845
bfcabc6c 2846 if (code->expr)
e35a0e64
RS
2847 {
2848 /* If the mask is .true., consider the FORALL unconditional. */
2849 if (code->expr->expr_type == EXPR_CONSTANT
2850 && code->expr->value.logical)
2851 need_mask = false;
2852 else
2853 need_mask = true;
2854 }
2855 else
2856 need_mask = false;
2857
2858 /* First we need to allocate the mask. */
2859 if (need_mask)
bfcabc6c
RS
2860 {
2861 /* As the mask array can be very big, prefer compact boolean types. */
2862 tree mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind);
2863 mask = allocate_temp_for_forall_nest (nested_forall_info, mask_type,
2864 size, NULL, &block, &pmask);
2865 maskindex = gfc_create_var_np (gfc_array_index_type, "mi");
2866
2867 /* Record them in the info structure. */
2868 info->maskindex = maskindex;
2869 info->mask = mask;
2870 }
6de9cd9a
DN
2871 else
2872 {
bfcabc6c
RS
2873 /* No mask was specified. */
2874 maskindex = NULL_TREE;
2875 mask = pmask = NULL_TREE;
2876 }
2877
2878 /* Link the current forall level to nested_forall_info. */
e8d366ec
RS
2879 info->prev_nest = nested_forall_info;
2880 nested_forall_info = info;
6de9cd9a
DN
2881
2882 /* Copy the mask into a temporary variable if required.
f7b529fa 2883 For now we assume a mask temporary is needed. */
e35a0e64 2884 if (need_mask)
6de9cd9a 2885 {
bfcabc6c
RS
2886 /* As the mask array can be very big, prefer compact boolean types. */
2887 tree mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind);
6de9cd9a 2888
726a989a 2889 gfc_add_modify (&block, maskindex, gfc_index_zero_node);
6de9cd9a
DN
2890
2891 /* Start of mask assignment loop body. */
2892 gfc_start_block (&body);
2893
2894 /* Evaluate the mask expression. */
2895 gfc_init_se (&se, NULL);
2896 gfc_conv_expr_val (&se, code->expr);
2897 gfc_add_block_to_block (&body, &se.pre);
2898
2899 /* Store the mask. */
bfcabc6c 2900 se.expr = convert (mask_type, se.expr);
6de9cd9a 2901
1d6b7f39 2902 tmp = gfc_build_array_ref (mask, maskindex, NULL);
726a989a 2903 gfc_add_modify (&body, tmp, se.expr);
6de9cd9a
DN
2904
2905 /* Advance to the next mask element. */
44855d8c
TS
2906 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
2907 maskindex, gfc_index_one_node);
726a989a 2908 gfc_add_modify (&body, maskindex, tmp);
6de9cd9a
DN
2909
2910 /* Generate the loops. */
2911 tmp = gfc_finish_block (&body);
bfcabc6c 2912 tmp = gfc_trans_nested_forall_loop (info, tmp, 0);
6de9cd9a
DN
2913 gfc_add_expr_to_block (&block, tmp);
2914 }
6de9cd9a
DN
2915
2916 c = code->block->next;
2917
2918 /* TODO: loop merging in FORALL statements. */
2919 /* Now that we've got a copy of the mask, generate the assignment loops. */
2920 while (c)
2921 {
2922 switch (c->op)
2923 {
2924 case EXEC_ASSIGN:
640670c7
PT
2925 /* A scalar or array assignment. DO the simple check for
2926 lhs to rhs dependencies. These make a temporary for the
2927 rhs and form a second forall block to copy to variable. */
2928 need_temp = check_forall_dependencies(c, &pre, &post);
2929
69de3b83 2930 /* Temporaries due to array assignment data dependencies introduce
6de9cd9a
DN
2931 no end of problems. */
2932 if (need_temp)
011daa76 2933 gfc_trans_assign_need_temp (c->expr, c->expr2, NULL, false,
6de9cd9a
DN
2934 nested_forall_info, &block);
2935 else
2936 {
2937 /* Use the normal assignment copying routines. */
6b591ec0 2938 assign = gfc_trans_assignment (c->expr, c->expr2, false);
6de9cd9a 2939
6de9cd9a 2940 /* Generate body and loops. */
bfcabc6c
RS
2941 tmp = gfc_trans_nested_forall_loop (nested_forall_info,
2942 assign, 1);
6de9cd9a
DN
2943 gfc_add_expr_to_block (&block, tmp);
2944 }
2945
640670c7
PT
2946 /* Cleanup any temporary symtrees that have been made to deal
2947 with dependencies. */
2948 if (new_symtree)
2949 cleanup_forall_symtrees (c);
2950
6de9cd9a
DN
2951 break;
2952
2953 case EXEC_WHERE:
6de9cd9a 2954 /* Translate WHERE or WHERE construct nested in FORALL. */
011daa76 2955 gfc_trans_where_2 (c, NULL, false, nested_forall_info, &block);
3891cee2 2956 break;
6de9cd9a
DN
2957
2958 /* Pointer assignment inside FORALL. */
2959 case EXEC_POINTER_ASSIGN:
3ded6210 2960 need_temp = gfc_check_dependency (c->expr, c->expr2, 0);
6de9cd9a
DN
2961 if (need_temp)
2962 gfc_trans_pointer_assign_need_temp (c->expr, c->expr2,
2963 nested_forall_info, &block);
2964 else
2965 {
2966 /* Use the normal assignment copying routines. */
2967 assign = gfc_trans_pointer_assignment (c->expr, c->expr2);
2968
6de9cd9a 2969 /* Generate body and loops. */
bfcabc6c
RS
2970 tmp = gfc_trans_nested_forall_loop (nested_forall_info,
2971 assign, 1);
6de9cd9a
DN
2972 gfc_add_expr_to_block (&block, tmp);
2973 }
2974 break;
2975
2976 case EXEC_FORALL:
2977 tmp = gfc_trans_forall_1 (c, nested_forall_info);
2978 gfc_add_expr_to_block (&block, tmp);
2979 break;
2980
48474141
PT
2981 /* Explicit subroutine calls are prevented by the frontend but interface
2982 assignments can legitimately produce them. */
476220e7
PT
2983 case EXEC_ASSIGN_CALL:
2984 assign = gfc_trans_call (c, true);
bfcabc6c 2985 tmp = gfc_trans_nested_forall_loop (nested_forall_info, assign, 1);
48474141
PT
2986 gfc_add_expr_to_block (&block, tmp);
2987 break;
2988
6de9cd9a 2989 default:
6e45f57b 2990 gcc_unreachable ();
6de9cd9a
DN
2991 }
2992
2993 c = c->next;
2994 }
2995
7b5b57b7
PB
2996 /* Restore the original index variables. */
2997 for (fa = code->ext.forall_iterator, n = 0; fa; fa = fa->next, n++)
2998 gfc_restore_sym (fa->var->symtree->n.sym, &saved_vars[n]);
6de9cd9a
DN
2999
3000 /* Free the space for var, start, end, step, varexpr. */
3001 gfc_free (var);
3002 gfc_free (start);
3003 gfc_free (end);
3004 gfc_free (step);
3005 gfc_free (varexpr);
7b5b57b7 3006 gfc_free (saved_vars);
6de9cd9a 3007
e8d366ec
RS
3008 /* Free the space for this forall_info. */
3009 gfc_free (info);
3010
6de9cd9a
DN
3011 if (pmask)
3012 {
3013 /* Free the temporary for the mask. */
1529b8d9 3014 tmp = gfc_call_free (pmask);
6de9cd9a
DN
3015 gfc_add_expr_to_block (&block, tmp);
3016 }
3017 if (maskindex)
3018 pushdecl (maskindex);
3019
640670c7
PT
3020 gfc_add_block_to_block (&pre, &block);
3021 gfc_add_block_to_block (&pre, &post);
3022
3023 return gfc_finish_block (&pre);
6de9cd9a
DN
3024}
3025
3026
3027/* Translate the FORALL statement or construct. */
3028
3029tree gfc_trans_forall (gfc_code * code)
3030{
3031 return gfc_trans_forall_1 (code, NULL);
3032}
3033
3034
3035/* Evaluate the WHERE mask expression, copy its value to a temporary.
3036 If the WHERE construct is nested in FORALL, compute the overall temporary
3037 needed by the WHERE mask expression multiplied by the iterator number of
3038 the nested forall.
3039 ME is the WHERE mask expression.
011daa76
RS
3040 MASK is the current execution mask upon input, whose sense may or may
3041 not be inverted as specified by the INVERT argument.
3891cee2
RS
3042 CMASK is the updated execution mask on output, or NULL if not required.
3043 PMASK is the pending execution mask on output, or NULL if not required.
3044 BLOCK is the block in which to place the condition evaluation loops. */
6de9cd9a 3045
3891cee2 3046static void
6de9cd9a 3047gfc_evaluate_where_mask (gfc_expr * me, forall_info * nested_forall_info,
011daa76 3048 tree mask, bool invert, tree cmask, tree pmask,
3891cee2 3049 tree mask_type, stmtblock_t * block)
6de9cd9a
DN
3050{
3051 tree tmp, tmp1;
3052 gfc_ss *lss, *rss;
3053 gfc_loopinfo loop;
3891cee2
RS
3054 stmtblock_t body, body1;
3055 tree count, cond, mtmp;
6de9cd9a 3056 gfc_se lse, rse;
6de9cd9a
DN
3057
3058 gfc_init_loopinfo (&loop);
3059
3891cee2
RS
3060 lss = gfc_walk_expr (me);
3061 rss = gfc_walk_expr (me);
6de9cd9a
DN
3062
3063 /* Variable to index the temporary. */
3064 count = gfc_create_var (gfc_array_index_type, "count");
1f2959f0 3065 /* Initialize count. */
726a989a 3066 gfc_add_modify (block, count, gfc_index_zero_node);
6de9cd9a
DN
3067
3068 gfc_start_block (&body);
3069
3070 gfc_init_se (&rse, NULL);
3071 gfc_init_se (&lse, NULL);
3072
3073 if (lss == gfc_ss_terminator)
3074 {
3075 gfc_init_block (&body1);
3076 }
3077 else
3078 {
1f2959f0 3079 /* Initialize the loop. */
6de9cd9a
DN
3080 gfc_init_loopinfo (&loop);
3081
3082 /* We may need LSS to determine the shape of the expression. */
3083 gfc_add_ss_to_loop (&loop, lss);
3084 gfc_add_ss_to_loop (&loop, rss);
3085
3086 gfc_conv_ss_startstride (&loop);
bdfd2ff0 3087 gfc_conv_loop_setup (&loop, &me->where);
6de9cd9a
DN
3088
3089 gfc_mark_ss_chain_used (rss, 1);
3090 /* Start the loop body. */
3091 gfc_start_scalarized_body (&loop, &body1);
3092
3093 /* Translate the expression. */
3094 gfc_copy_loopinfo_to_se (&rse, &loop);
3095 rse.ss = rss;
3096 gfc_conv_expr (&rse, me);
3097 }
6de9cd9a 3098
b82feea5 3099 /* Variable to evaluate mask condition. */
3891cee2
RS
3100 cond = gfc_create_var (mask_type, "cond");
3101 if (mask && (cmask || pmask))
3102 mtmp = gfc_create_var (mask_type, "mask");
3103 else mtmp = NULL_TREE;
3104
3105 gfc_add_block_to_block (&body1, &lse.pre);
3106 gfc_add_block_to_block (&body1, &rse.pre);
6de9cd9a 3107
726a989a 3108 gfc_add_modify (&body1, cond, fold_convert (mask_type, rse.expr));
3891cee2
RS
3109
3110 if (mask && (cmask || pmask))
42e73749 3111 {
1d6b7f39 3112 tmp = gfc_build_array_ref (mask, count, NULL);
011daa76
RS
3113 if (invert)
3114 tmp = fold_build1 (TRUTH_NOT_EXPR, mask_type, tmp);
726a989a 3115 gfc_add_modify (&body1, mtmp, tmp);
42e73749 3116 }
6de9cd9a 3117
3891cee2
RS
3118 if (cmask)
3119 {
1d6b7f39 3120 tmp1 = gfc_build_array_ref (cmask, count, NULL);
3891cee2
RS
3121 tmp = cond;
3122 if (mask)
44855d8c 3123 tmp = fold_build2 (TRUTH_AND_EXPR, mask_type, mtmp, tmp);
726a989a 3124 gfc_add_modify (&body1, tmp1, tmp);
3891cee2
RS
3125 }
3126
3127 if (pmask)
3128 {
1d6b7f39 3129 tmp1 = gfc_build_array_ref (pmask, count, NULL);
44855d8c 3130 tmp = fold_build1 (TRUTH_NOT_EXPR, mask_type, cond);
3891cee2 3131 if (mask)
44855d8c 3132 tmp = fold_build2 (TRUTH_AND_EXPR, mask_type, mtmp, tmp);
726a989a 3133 gfc_add_modify (&body1, tmp1, tmp);
3891cee2
RS
3134 }
3135
3136 gfc_add_block_to_block (&body1, &lse.post);
3137 gfc_add_block_to_block (&body1, &rse.post);
3138
3139 if (lss == gfc_ss_terminator)
6de9cd9a
DN
3140 {
3141 gfc_add_block_to_block (&body, &body1);
3142 }
3143 else
3144 {
3145 /* Increment count. */
10c7a96f
SB
3146 tmp1 = fold_build2 (PLUS_EXPR, gfc_array_index_type, count,
3147 gfc_index_one_node);
726a989a 3148 gfc_add_modify (&body1, count, tmp1);
6de9cd9a
DN
3149
3150 /* Generate the copying loops. */
3151 gfc_trans_scalarizing_loops (&loop, &body1);
3152
3153 gfc_add_block_to_block (&body, &loop.pre);
3154 gfc_add_block_to_block (&body, &loop.post);
3155
3156 gfc_cleanup_loop (&loop);
3157 /* TODO: Reuse lss and rss when copying temp->lhs. Need to be careful
3158 as tree nodes in SS may not be valid in different scope. */
3159 }
3160
3161 tmp1 = gfc_finish_block (&body);
3162 /* If the WHERE construct is inside FORALL, fill the full temporary. */
3163 if (nested_forall_info != NULL)
bfcabc6c 3164 tmp1 = gfc_trans_nested_forall_loop (nested_forall_info, tmp1, 1);
6de9cd9a
DN
3165
3166 gfc_add_expr_to_block (block, tmp1);
6de9cd9a
DN
3167}
3168
3169
3170/* Translate an assignment statement in a WHERE statement or construct
3171 statement. The MASK expression is used to control which elements
011daa76
RS
3172 of EXPR1 shall be assigned. The sense of MASK is specified by
3173 INVERT. */
6de9cd9a
DN
3174
3175static tree
011daa76
RS
3176gfc_trans_where_assign (gfc_expr *expr1, gfc_expr *expr2,
3177 tree mask, bool invert,
a00b8d1a
PT
3178 tree count1, tree count2,
3179 gfc_symbol *sym)
6de9cd9a
DN
3180{
3181 gfc_se lse;
3182 gfc_se rse;
3183 gfc_ss *lss;
3184 gfc_ss *lss_section;
3185 gfc_ss *rss;
3186
3187 gfc_loopinfo loop;
3188 tree tmp;
3189 stmtblock_t block;
3190 stmtblock_t body;
3c90c9ae 3191 tree index, maskexpr;
6de9cd9a
DN
3192
3193#if 0
3194 /* TODO: handle this special case.
3195 Special case a single function returning an array. */
3196 if (expr2->expr_type == EXPR_FUNCTION && expr2->rank > 0)
3197 {
3198 tmp = gfc_trans_arrayfunc_assign (expr1, expr2);
3199 if (tmp)
3200 return tmp;
3201 }
3202#endif
3203
3204 /* Assignment of the form lhs = rhs. */
3205 gfc_start_block (&block);
3206
3207 gfc_init_se (&lse, NULL);
3208 gfc_init_se (&rse, NULL);
3209
3210 /* Walk the lhs. */
3211 lss = gfc_walk_expr (expr1);
3212 rss = NULL;
3213
3214 /* In each where-assign-stmt, the mask-expr and the variable being
3215 defined shall be arrays of the same shape. */
6e45f57b 3216 gcc_assert (lss != gfc_ss_terminator);
6de9cd9a
DN
3217
3218 /* The assignment needs scalarization. */
3219 lss_section = lss;
3220
3221 /* Find a non-scalar SS from the lhs. */
3222 while (lss_section != gfc_ss_terminator
3223 && lss_section->type != GFC_SS_SECTION)
3224 lss_section = lss_section->next;
3225
6e45f57b 3226 gcc_assert (lss_section != gfc_ss_terminator);
6de9cd9a
DN
3227
3228 /* Initialize the scalarizer. */
3229 gfc_init_loopinfo (&loop);
3230
3231 /* Walk the rhs. */
3232 rss = gfc_walk_expr (expr2);
3233 if (rss == gfc_ss_terminator)
3234 {
3235 /* The rhs is scalar. Add a ss for the expression. */
3236 rss = gfc_get_ss ();
ae772c2d 3237 rss->where = 1;
6de9cd9a
DN
3238 rss->next = gfc_ss_terminator;
3239 rss->type = GFC_SS_SCALAR;
3240 rss->expr = expr2;
3241 }
3242
3243 /* Associate the SS with the loop. */
3244 gfc_add_ss_to_loop (&loop, lss);
3245 gfc_add_ss_to_loop (&loop, rss);
3246
3247 /* Calculate the bounds of the scalarization. */
3248 gfc_conv_ss_startstride (&loop);
3249
3250 /* Resolve any data dependencies in the statement. */
3251 gfc_conv_resolve_dependencies (&loop, lss_section, rss);
3252
3253 /* Setup the scalarizing loops. */
bdfd2ff0 3254 gfc_conv_loop_setup (&loop, &expr2->where);
6de9cd9a
DN
3255
3256 /* Setup the gfc_se structures. */
3257 gfc_copy_loopinfo_to_se (&lse, &loop);
3258 gfc_copy_loopinfo_to_se (&rse, &loop);
3259
3260 rse.ss = rss;
3261 gfc_mark_ss_chain_used (rss, 1);
3262 if (loop.temp_ss == NULL)
3263 {
3264 lse.ss = lss;
3265 gfc_mark_ss_chain_used (lss, 1);
3266 }
3267 else
3268 {
3269 lse.ss = loop.temp_ss;
3270 gfc_mark_ss_chain_used (lss, 3);
3271 gfc_mark_ss_chain_used (loop.temp_ss, 3);
3272 }
3273
3274 /* Start the scalarized loop body. */
3275 gfc_start_scalarized_body (&loop, &body);
3276
3277 /* Translate the expression. */
3278 gfc_conv_expr (&rse, expr2);
3279 if (lss != gfc_ss_terminator && loop.temp_ss != NULL)
3280 {
3281 gfc_conv_tmp_array_ref (&lse);
3282 gfc_advance_se_ss_chain (&lse);
3283 }
3284 else
3285 gfc_conv_expr (&lse, expr1);
3286
3c90c9ae 3287 /* Form the mask expression according to the mask. */
6de9cd9a 3288 index = count1;
1d6b7f39 3289 maskexpr = gfc_build_array_ref (mask, index, NULL);
011daa76
RS
3290 if (invert)
3291 maskexpr = fold_build1 (TRUTH_NOT_EXPR, TREE_TYPE (maskexpr), maskexpr);
6de9cd9a 3292
6de9cd9a 3293 /* Use the scalar assignment as is. */
a00b8d1a
PT
3294 if (sym == NULL)
3295 tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts,
3296 loop.temp_ss != NULL, false);
3297 else
3298 tmp = gfc_conv_operator_assign (&lse, &rse, sym);
3299
923ab88c 3300 tmp = build3_v (COND_EXPR, maskexpr, tmp, build_empty_stmt ());
6de9cd9a
DN
3301
3302 gfc_add_expr_to_block (&body, tmp);
3303
3304 if (lss == gfc_ss_terminator)
3305 {
3306 /* Increment count1. */
10c7a96f
SB
3307 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
3308 count1, gfc_index_one_node);
726a989a 3309 gfc_add_modify (&body, count1, tmp);
6de9cd9a
DN
3310
3311 /* Use the scalar assignment as is. */
3312 gfc_add_block_to_block (&block, &body);
3313 }
3314 else
3315 {
6e45f57b
PB
3316 gcc_assert (lse.ss == gfc_ss_terminator
3317 && rse.ss == gfc_ss_terminator);
6de9cd9a
DN
3318
3319 if (loop.temp_ss != NULL)
3320 {
3321 /* Increment count1 before finish the main body of a scalarized
3322 expression. */
10c7a96f
SB
3323 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
3324 count1, gfc_index_one_node);
726a989a 3325 gfc_add_modify (&body, count1, tmp);
6de9cd9a
DN
3326 gfc_trans_scalarized_loop_boundary (&loop, &body);
3327
3328 /* We need to copy the temporary to the actual lhs. */
3329 gfc_init_se (&lse, NULL);
3330 gfc_init_se (&rse, NULL);
3331 gfc_copy_loopinfo_to_se (&lse, &loop);
3332 gfc_copy_loopinfo_to_se (&rse, &loop);
3333
3334 rse.ss = loop.temp_ss;
3335 lse.ss = lss;
3336
3337 gfc_conv_tmp_array_ref (&rse);
3338 gfc_advance_se_ss_chain (&rse);
3339 gfc_conv_expr (&lse, expr1);
3340
6e45f57b
PB
3341 gcc_assert (lse.ss == gfc_ss_terminator
3342 && rse.ss == gfc_ss_terminator);
6de9cd9a
DN
3343
3344 /* Form the mask expression according to the mask tree list. */
3345 index = count2;
1d6b7f39 3346 maskexpr = gfc_build_array_ref (mask, index, NULL);
011daa76
RS
3347 if (invert)
3348 maskexpr = fold_build1 (TRUTH_NOT_EXPR, TREE_TYPE (maskexpr),
3349 maskexpr);
6de9cd9a 3350
6de9cd9a 3351 /* Use the scalar assignment as is. */
5046aff5 3352 tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts, false, false);
923ab88c 3353 tmp = build3_v (COND_EXPR, maskexpr, tmp, build_empty_stmt ());
6de9cd9a 3354 gfc_add_expr_to_block (&body, tmp);
7ab92584 3355
6de9cd9a 3356 /* Increment count2. */
10c7a96f
SB
3357 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
3358 count2, gfc_index_one_node);
726a989a 3359 gfc_add_modify (&body, count2, tmp);
6de9cd9a
DN
3360 }
3361 else
3362 {
3363 /* Increment count1. */
10c7a96f
SB
3364 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
3365 count1, gfc_index_one_node);
726a989a 3366 gfc_add_modify (&body, count1, tmp);
6de9cd9a
DN
3367 }
3368
3369 /* Generate the copying loops. */
3370 gfc_trans_scalarizing_loops (&loop, &body);
3371
3372 /* Wrap the whole thing up. */
3373 gfc_add_block_to_block (&block, &loop.pre);
3374 gfc_add_block_to_block (&block, &loop.post);
3375 gfc_cleanup_loop (&loop);
3376 }
3377
3378 return gfc_finish_block (&block);
3379}
3380
3381
3382/* Translate the WHERE construct or statement.
aa9c57ec 3383 This function can be called iteratively to translate the nested WHERE
6de9cd9a 3384 construct or statement.
3891cee2 3385 MASK is the control mask. */
6de9cd9a
DN
3386
3387static void
011daa76 3388gfc_trans_where_2 (gfc_code * code, tree mask, bool invert,
3891cee2 3389 forall_info * nested_forall_info, stmtblock_t * block)
6de9cd9a 3390{
3891cee2
RS
3391 stmtblock_t inner_size_body;
3392 tree inner_size, size;
3393 gfc_ss *lss, *rss;
3394 tree mask_type;
6de9cd9a
DN
3395 gfc_expr *expr1;
3396 gfc_expr *expr2;
3397 gfc_code *cblock;
3398 gfc_code *cnext;
3891cee2 3399 tree tmp;
ae772c2d 3400 tree cond;
6de9cd9a 3401 tree count1, count2;
011daa76
RS
3402 bool need_cmask;
3403 bool need_pmask;
6de9cd9a 3404 int need_temp;
3891cee2
RS
3405 tree pcmask = NULL_TREE;
3406 tree ppmask = NULL_TREE;
3407 tree cmask = NULL_TREE;
3408 tree pmask = NULL_TREE;
a00b8d1a 3409 gfc_actual_arglist *arg;
6de9cd9a
DN
3410
3411 /* the WHERE statement or the WHERE construct statement. */
3412 cblock = code->block;
3891cee2 3413
3891cee2
RS
3414 /* As the mask array can be very big, prefer compact boolean types. */
3415 mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind);
3416
011daa76
RS
3417 /* Determine which temporary masks are needed. */
3418 if (!cblock->block)
90f58ec8 3419 {
011daa76
RS
3420 /* One clause: No ELSEWHEREs. */
3421 need_cmask = (cblock->next != 0);
3422 need_pmask = false;
90f58ec8 3423 }
011daa76 3424 else if (cblock->block->block)
90f58ec8 3425 {
011daa76
RS
3426 /* Three or more clauses: Conditional ELSEWHEREs. */
3427 need_cmask = true;
3428 need_pmask = true;
90f58ec8 3429 }
011daa76
RS
3430 else if (cblock->next)
3431 {
3432 /* Two clauses, the first non-empty. */
3433 need_cmask = true;
3434 need_pmask = (mask != NULL_TREE
3435 && cblock->block->next != 0);
3436 }
3437 else if (!cblock->block->next)
3891cee2 3438 {
011daa76
RS
3439 /* Two clauses, both empty. */
3440 need_cmask = false;
3441 need_pmask = false;
3442 }
3443 /* Two clauses, the first empty, the second non-empty. */
3444 else if (mask)
3445 {
3446 need_cmask = (cblock->block->expr != 0);
3447 need_pmask = true;
3891cee2
RS
3448 }
3449 else
3450 {
011daa76
RS
3451 need_cmask = true;
3452 need_pmask = false;
3453 }
3454
3455 if (need_cmask || need_pmask)
3456 {
3457 /* Calculate the size of temporary needed by the mask-expr. */
3458 gfc_init_block (&inner_size_body);
3459 inner_size = compute_inner_temp_size (cblock->expr, cblock->expr,
3460 &inner_size_body, &lss, &rss);
3461
3462 /* Calculate the total size of temporary needed. */
3463 size = compute_overall_iter_number (nested_forall_info, inner_size,
3464 &inner_size_body, block);
3465
ae772c2d
PT
3466 /* Check whether the size is negative. */
3467 cond = fold_build2 (LE_EXPR, boolean_type_node, size,
3468 gfc_index_zero_node);
3469 size = fold_build3 (COND_EXPR, gfc_array_index_type, cond,
3470 gfc_index_zero_node, size);
3471 size = gfc_evaluate_now (size, block);
3472
011daa76
RS
3473 /* Allocate temporary for WHERE mask if needed. */
3474 if (need_cmask)
3475 cmask = allocate_temp_for_forall_nest_1 (mask_type, size, block,
3476 &pcmask);
3477
3478 /* Allocate temporary for !mask if needed. */
3479 if (need_pmask)
3480 pmask = allocate_temp_for_forall_nest_1 (mask_type, size, block,
3481 &ppmask);
3891cee2
RS
3482 }
3483
6de9cd9a
DN
3484 while (cblock)
3485 {
011daa76
RS
3486 /* Each time around this loop, the where clause is conditional
3487 on the value of mask and invert, which are updated at the
3488 bottom of the loop. */
3489
6de9cd9a
DN
3490 /* Has mask-expr. */
3491 if (cblock->expr)
3492 {
90f58ec8
RS
3493 /* Ensure that the WHERE mask will be evaluated exactly once.
3494 If there are no statements in this WHERE/ELSEWHERE clause,
3495 then we don't need to update the control mask (cmask).
3496 If this is the last clause of the WHERE construct, then
3891cee2 3497 we don't need to update the pending control mask (pmask). */
011daa76
RS
3498 if (mask)
3499 gfc_evaluate_where_mask (cblock->expr, nested_forall_info,
3500 mask, invert,
3501 cblock->next ? cmask : NULL_TREE,
3502 cblock->block ? pmask : NULL_TREE,
3503 mask_type, block);
3504 else
3505 gfc_evaluate_where_mask (cblock->expr, nested_forall_info,
3506 NULL_TREE, false,
3507 (cblock->next || cblock->block)
3508 ? cmask : NULL_TREE,
3509 NULL_TREE, mask_type, block);
6de9cd9a 3510
011daa76 3511 invert = false;
6de9cd9a 3512 }
90f58ec8 3513 /* It's a final elsewhere-stmt. No mask-expr is present. */
6de9cd9a 3514 else
3891cee2 3515 cmask = mask;
6de9cd9a 3516
011daa76
RS
3517 /* The body of this where clause are controlled by cmask with
3518 sense specified by invert. */
3519
6de9cd9a
DN
3520 /* Get the assignment statement of a WHERE statement, or the first
3521 statement in where-body-construct of a WHERE construct. */
3522 cnext = cblock->next;
3523 while (cnext)
3524 {
3525 switch (cnext->op)
3526 {
3527 /* WHERE assignment statement. */
a00b8d1a
PT
3528 case EXEC_ASSIGN_CALL:
3529
3530 arg = cnext->ext.actual;
3531 expr1 = expr2 = NULL;
3532 for (; arg; arg = arg->next)
3533 {
3534 if (!arg->expr)
3535 continue;
3536 if (expr1 == NULL)
3537 expr1 = arg->expr;
3538 else
3539 expr2 = arg->expr;
3540 }
3541 goto evaluate;
3542
6de9cd9a
DN
3543 case EXEC_ASSIGN:
3544 expr1 = cnext->expr;
3545 expr2 = cnext->expr2;
a00b8d1a 3546 evaluate:
6de9cd9a
DN
3547 if (nested_forall_info != NULL)
3548 {
3ded6210 3549 need_temp = gfc_check_dependency (expr1, expr2, 0);
a00b8d1a 3550 if (need_temp && cnext->op != EXEC_ASSIGN_CALL)
011daa76
RS
3551 gfc_trans_assign_need_temp (expr1, expr2,
3552 cmask, invert,
6de9cd9a
DN
3553 nested_forall_info, block);
3554 else
3555 {
3556 /* Variables to control maskexpr. */
3557 count1 = gfc_create_var (gfc_array_index_type, "count1");
3558 count2 = gfc_create_var (gfc_array_index_type, "count2");
726a989a
RB
3559 gfc_add_modify (block, count1, gfc_index_zero_node);
3560 gfc_add_modify (block, count2, gfc_index_zero_node);
6de9cd9a 3561
011daa76
RS
3562 tmp = gfc_trans_where_assign (expr1, expr2,
3563 cmask, invert,
a00b8d1a
PT
3564 count1, count2,
3565 cnext->resolved_sym);
8de1f441 3566
6de9cd9a 3567 tmp = gfc_trans_nested_forall_loop (nested_forall_info,
bfcabc6c 3568 tmp, 1);
6de9cd9a
DN
3569 gfc_add_expr_to_block (block, tmp);
3570 }
3571 }
3572 else
3573 {
3574 /* Variables to control maskexpr. */
3575 count1 = gfc_create_var (gfc_array_index_type, "count1");
3576 count2 = gfc_create_var (gfc_array_index_type, "count2");
726a989a
RB
3577 gfc_add_modify (block, count1, gfc_index_zero_node);
3578 gfc_add_modify (block, count2, gfc_index_zero_node);
6de9cd9a 3579
011daa76
RS
3580 tmp = gfc_trans_where_assign (expr1, expr2,
3581 cmask, invert,
a00b8d1a
PT
3582 count1, count2,
3583 cnext->resolved_sym);
6de9cd9a
DN
3584 gfc_add_expr_to_block (block, tmp);
3585
3586 }
3587 break;
3588
3589 /* WHERE or WHERE construct is part of a where-body-construct. */
3590 case EXEC_WHERE:
011daa76
RS
3591 gfc_trans_where_2 (cnext, cmask, invert,
3592 nested_forall_info, block);
3891cee2 3593 break;
6de9cd9a
DN
3594
3595 default:
6e45f57b 3596 gcc_unreachable ();
6de9cd9a
DN
3597 }
3598
3599 /* The next statement within the same where-body-construct. */
3600 cnext = cnext->next;
3601 }
3602 /* The next masked-elsewhere-stmt, elsewhere-stmt, or end-where-stmt. */
3603 cblock = cblock->block;
011daa76
RS
3604 if (mask == NULL_TREE)
3605 {
3606 /* If we're the initial WHERE, we can simply invert the sense
3607 of the current mask to obtain the "mask" for the remaining
3608 ELSEWHEREs. */
3609 invert = true;
3610 mask = cmask;
3611 }
3612 else
3613 {
3614 /* Otherwise, for nested WHERE's we need to use the pending mask. */
3615 invert = false;
3616 mask = pmask;
3617 }
6de9cd9a 3618 }
3891cee2
RS
3619
3620 /* If we allocated a pending mask array, deallocate it now. */
3621 if (ppmask)
3622 {
1529b8d9 3623 tmp = gfc_call_free (ppmask);
3891cee2
RS
3624 gfc_add_expr_to_block (block, tmp);
3625 }
3626
3627 /* If we allocated a current mask array, deallocate it now. */
3628 if (pcmask)
3629 {
1529b8d9 3630 tmp = gfc_call_free (pcmask);
3891cee2
RS
3631 gfc_add_expr_to_block (block, tmp);
3632 }
6de9cd9a
DN
3633}
3634
3ded6210
RS
3635/* Translate a simple WHERE construct or statement without dependencies.
3636 CBLOCK is the "then" clause of the WHERE statement, where CBLOCK->EXPR
3637 is the mask condition, and EBLOCK if non-NULL is the "else" clause.
3638 Currently both CBLOCK and EBLOCK are restricted to single assignments. */
3639
3640static tree
3641gfc_trans_where_3 (gfc_code * cblock, gfc_code * eblock)
3642{
3643 stmtblock_t block, body;
3644 gfc_expr *cond, *tdst, *tsrc, *edst, *esrc;
3645 tree tmp, cexpr, tstmt, estmt;
3646 gfc_ss *css, *tdss, *tsss;
3647 gfc_se cse, tdse, tsse, edse, esse;
3648 gfc_loopinfo loop;
3649 gfc_ss *edss = 0;
3650 gfc_ss *esss = 0;
3651
3652 cond = cblock->expr;
3653 tdst = cblock->next->expr;
3654 tsrc = cblock->next->expr2;
3655 edst = eblock ? eblock->next->expr : NULL;
3656 esrc = eblock ? eblock->next->expr2 : NULL;
3657
3658 gfc_start_block (&block);
3659 gfc_init_loopinfo (&loop);
3660
3661 /* Handle the condition. */
3662 gfc_init_se (&cse, NULL);
3663 css = gfc_walk_expr (cond);
3664 gfc_add_ss_to_loop (&loop, css);
3665
3666 /* Handle the then-clause. */
3667 gfc_init_se (&tdse, NULL);
3668 gfc_init_se (&tsse, NULL);
3669 tdss = gfc_walk_expr (tdst);
3670 tsss = gfc_walk_expr (tsrc);
3671 if (tsss == gfc_ss_terminator)
3672 {
3673 tsss = gfc_get_ss ();
ae772c2d 3674 tsss->where = 1;
3ded6210
RS
3675 tsss->next = gfc_ss_terminator;
3676 tsss->type = GFC_SS_SCALAR;
3677 tsss->expr = tsrc;
3678 }
3679 gfc_add_ss_to_loop (&loop, tdss);
3680 gfc_add_ss_to_loop (&loop, tsss);
3681
3682 if (eblock)
3683 {
3684 /* Handle the else clause. */
3685 gfc_init_se (&edse, NULL);
3686 gfc_init_se (&esse, NULL);
3687 edss = gfc_walk_expr (edst);
3688 esss = gfc_walk_expr (esrc);
3689 if (esss == gfc_ss_terminator)
3690 {
3691 esss = gfc_get_ss ();
ae772c2d 3692 esss->where = 1;
3ded6210
RS
3693 esss->next = gfc_ss_terminator;
3694 esss->type = GFC_SS_SCALAR;
3695 esss->expr = esrc;
3696 }
3697 gfc_add_ss_to_loop (&loop, edss);
3698 gfc_add_ss_to_loop (&loop, esss);
3699 }
3700
3701 gfc_conv_ss_startstride (&loop);
bdfd2ff0 3702 gfc_conv_loop_setup (&loop, &tdst->where);
3ded6210
RS
3703
3704 gfc_mark_ss_chain_used (css, 1);
3705 gfc_mark_ss_chain_used (tdss, 1);
3706 gfc_mark_ss_chain_used (tsss, 1);
3707 if (eblock)
3708 {
3709 gfc_mark_ss_chain_used (edss, 1);
3710 gfc_mark_ss_chain_used (esss, 1);
3711 }
3712
3713 gfc_start_scalarized_body (&loop, &body);
3714
3715 gfc_copy_loopinfo_to_se (&cse, &loop);
3716 gfc_copy_loopinfo_to_se (&tdse, &loop);
3717 gfc_copy_loopinfo_to_se (&tsse, &loop);
3718 cse.ss = css;
3719 tdse.ss = tdss;
3720 tsse.ss = tsss;
3721 if (eblock)
3722 {
3723 gfc_copy_loopinfo_to_se (&edse, &loop);
3724 gfc_copy_loopinfo_to_se (&esse, &loop);
3725 edse.ss = edss;
3726 esse.ss = esss;
3727 }
3728
3729 gfc_conv_expr (&cse, cond);
3730 gfc_add_block_to_block (&body, &cse.pre);
3731 cexpr = cse.expr;
3732
3733 gfc_conv_expr (&tsse, tsrc);
3734 if (tdss != gfc_ss_terminator && loop.temp_ss != NULL)
3735 {
3736 gfc_conv_tmp_array_ref (&tdse);
3737 gfc_advance_se_ss_chain (&tdse);
3738 }
3739 else
3740 gfc_conv_expr (&tdse, tdst);
3741
3742 if (eblock)
3743 {
3744 gfc_conv_expr (&esse, esrc);
3745 if (edss != gfc_ss_terminator && loop.temp_ss != NULL)
3746 {
3747 gfc_conv_tmp_array_ref (&edse);
3748 gfc_advance_se_ss_chain (&edse);
3749 }
3750 else
3751 gfc_conv_expr (&edse, edst);
3752 }
3753
5046aff5
PT
3754 tstmt = gfc_trans_scalar_assign (&tdse, &tsse, tdst->ts, false, false);
3755 estmt = eblock ? gfc_trans_scalar_assign (&edse, &esse, edst->ts, false, false)
3ded6210
RS
3756 : build_empty_stmt ();
3757 tmp = build3_v (COND_EXPR, cexpr, tstmt, estmt);
3758 gfc_add_expr_to_block (&body, tmp);
3759 gfc_add_block_to_block (&body, &cse.post);
3760
3761 gfc_trans_scalarizing_loops (&loop, &body);
3762 gfc_add_block_to_block (&block, &loop.pre);
3763 gfc_add_block_to_block (&block, &loop.post);
3764 gfc_cleanup_loop (&loop);
3765
3766 return gfc_finish_block (&block);
3767}
6de9cd9a
DN
3768
3769/* As the WHERE or WHERE construct statement can be nested, we call
3770 gfc_trans_where_2 to do the translation, and pass the initial
f7b529fa 3771 NULL values for both the control mask and the pending control mask. */
6de9cd9a
DN
3772
3773tree
3774gfc_trans_where (gfc_code * code)
3775{
3776 stmtblock_t block;
3ded6210
RS
3777 gfc_code *cblock;
3778 gfc_code *eblock;
6de9cd9a 3779
3ded6210
RS
3780 cblock = code->block;
3781 if (cblock->next
3782 && cblock->next->op == EXEC_ASSIGN
3783 && !cblock->next->next)
3784 {
3785 eblock = cblock->block;
3786 if (!eblock)
3787 {
3788 /* A simple "WHERE (cond) x = y" statement or block is
3789 dependence free if cond is not dependent upon writing x,
3790 and the source y is unaffected by the destination x. */
3791 if (!gfc_check_dependency (cblock->next->expr,
3792 cblock->expr, 0)
3793 && !gfc_check_dependency (cblock->next->expr,
3794 cblock->next->expr2, 0))
3795 return gfc_trans_where_3 (cblock, NULL);
3796 }
3797 else if (!eblock->expr
3798 && !eblock->block
3799 && eblock->next
3800 && eblock->next->op == EXEC_ASSIGN
3801 && !eblock->next->next)
3802 {
3803 /* A simple "WHERE (cond) x1 = y1 ELSEWHERE x2 = y2 ENDWHERE"
3804 block is dependence free if cond is not dependent on writes
3805 to x1 and x2, y1 is not dependent on writes to x2, and y2
3806 is not dependent on writes to x1, and both y's are not
ae772c2d
PT
3807 dependent upon their own x's. In addition to this, the
3808 final two dependency checks below exclude all but the same
3809 array reference if the where and elswhere destinations
3810 are the same. In short, this is VERY conservative and this
3811 is needed because the two loops, required by the standard
3812 are coalesced in gfc_trans_where_3. */
3ded6210
RS
3813 if (!gfc_check_dependency(cblock->next->expr,
3814 cblock->expr, 0)
3815 && !gfc_check_dependency(eblock->next->expr,
3816 cblock->expr, 0)
3817 && !gfc_check_dependency(cblock->next->expr,
ae772c2d
PT
3818 eblock->next->expr2, 1)
3819 && !gfc_check_dependency(eblock->next->expr,
3820 cblock->next->expr2, 1)
3821 && !gfc_check_dependency(cblock->next->expr,
3822 cblock->next->expr2, 1)
3ded6210 3823 && !gfc_check_dependency(eblock->next->expr,
ae772c2d 3824 eblock->next->expr2, 1)
3ded6210 3825 && !gfc_check_dependency(cblock->next->expr,
ae772c2d 3826 eblock->next->expr, 0)
3ded6210 3827 && !gfc_check_dependency(eblock->next->expr,
ae772c2d 3828 cblock->next->expr, 0))
3ded6210
RS
3829 return gfc_trans_where_3 (cblock, eblock);
3830 }
3831 }
3832
6de9cd9a 3833 gfc_start_block (&block);
6de9cd9a 3834
011daa76 3835 gfc_trans_where_2 (code, NULL, false, NULL, &block);
6de9cd9a 3836
6de9cd9a
DN
3837 return gfc_finish_block (&block);
3838}
3839
3840
3841/* CYCLE a DO loop. The label decl has already been created by
3842 gfc_trans_do(), it's in TREE_PURPOSE (backend_decl) of the gfc_code
3843 node at the head of the loop. We must mark the label as used. */
3844
3845tree
3846gfc_trans_cycle (gfc_code * code)
3847{
3848 tree cycle_label;
3849
3850 cycle_label = TREE_PURPOSE (code->ext.whichloop->backend_decl);
3851 TREE_USED (cycle_label) = 1;
3852 return build1_v (GOTO_EXPR, cycle_label);
3853}
3854
3855
e7dc5b4f 3856/* EXIT a DO loop. Similar to CYCLE, but now the label is in
6de9cd9a
DN
3857 TREE_VALUE (backend_decl) of the gfc_code node at the head of the
3858 loop. */
3859
3860tree
3861gfc_trans_exit (gfc_code * code)
3862{
3863 tree exit_label;
3864
3865 exit_label = TREE_VALUE (code->ext.whichloop->backend_decl);
3866 TREE_USED (exit_label) = 1;
3867 return build1_v (GOTO_EXPR, exit_label);
3868}
3869
3870
3871/* Translate the ALLOCATE statement. */
3872
3873tree
3874gfc_trans_allocate (gfc_code * code)
3875{
3876 gfc_alloc *al;
3877 gfc_expr *expr;
3878 gfc_se se;
3879 tree tmp;
3880 tree parm;
6de9cd9a
DN
3881 tree stat;
3882 tree pstat;
3883 tree error_label;
3884 stmtblock_t block;
3885
3886 if (!code->ext.alloc_list)
3887 return NULL_TREE;
3888
3889 gfc_start_block (&block);
3890
3891 if (code->expr)
3892 {
e2cad04b
RH
3893 tree gfc_int4_type_node = gfc_get_int_type (4);
3894
6de9cd9a 3895 stat = gfc_create_var (gfc_int4_type_node, "stat");
628c189e 3896 pstat = gfc_build_addr_expr (NULL_TREE, stat);
6de9cd9a
DN
3897
3898 error_label = gfc_build_label_decl (NULL_TREE);
3899 TREE_USED (error_label) = 1;
3900 }
3901 else
4376b7cf 3902 pstat = stat = error_label = NULL_TREE;
6de9cd9a
DN
3903
3904 for (al = code->ext.alloc_list; al != NULL; al = al->next)
3905 {
3906 expr = al->expr;
3907
3908 gfc_init_se (&se, NULL);
3909 gfc_start_block (&se.pre);
3910
3911 se.want_pointer = 1;
3912 se.descriptor_only = 1;
3913 gfc_conv_expr (&se, expr);
3914
5b725b8d 3915 if (!gfc_array_allocate (&se, expr, pstat))
6de9cd9a
DN
3916 {
3917 /* A scalar or derived type. */
6de9cd9a 3918 tmp = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (se.expr)));
c4bbc105
PT
3919
3920 if (expr->ts.type == BT_CHARACTER && tmp == NULL_TREE)
3921 tmp = se.string_length;
3922
4376b7cf 3923 tmp = gfc_allocate_with_status (&se.pre, tmp, pstat);
44855d8c
TS
3924 tmp = fold_build2 (MODIFY_EXPR, void_type_node, se.expr,
3925 fold_convert (TREE_TYPE (se.expr), tmp));
6de9cd9a
DN
3926 gfc_add_expr_to_block (&se.pre, tmp);
3927
3928 if (code->expr)
3929 {
3930 tmp = build1_v (GOTO_EXPR, error_label);
61ead135
RG
3931 parm = fold_build2 (NE_EXPR, boolean_type_node,
3932 stat, build_int_cst (TREE_TYPE (stat), 0));
3933 tmp = fold_build3 (COND_EXPR, void_type_node,
3934 parm, tmp, build_empty_stmt ());
6de9cd9a
DN
3935 gfc_add_expr_to_block (&se.pre, tmp);
3936 }
5046aff5
PT
3937
3938 if (expr->ts.type == BT_DERIVED && expr->ts.derived->attr.alloc_comp)
3939 {
3940 tmp = build_fold_indirect_ref (se.expr);
3941 tmp = gfc_nullify_alloc_comp (expr->ts.derived, tmp, 0);
3942 gfc_add_expr_to_block (&se.pre, tmp);
3943 }
3944
6de9cd9a
DN
3945 }
3946
3947 tmp = gfc_finish_block (&se.pre);
3948 gfc_add_expr_to_block (&block, tmp);
3949 }
3950
3951 /* Assign the value to the status variable. */
3952 if (code->expr)
3953 {
3954 tmp = build1_v (LABEL_EXPR, error_label);
3955 gfc_add_expr_to_block (&block, tmp);
3956
3957 gfc_init_se (&se, NULL);
3958 gfc_conv_expr_lhs (&se, code->expr);
3959 tmp = convert (TREE_TYPE (se.expr), stat);
726a989a 3960 gfc_add_modify (&block, se.expr, tmp);
6de9cd9a
DN
3961 }
3962
3963 return gfc_finish_block (&block);
3964}
3965
3966
364667a1
SK
3967/* Translate a DEALLOCATE statement.
3968 There are two cases within the for loop:
3969 (1) deallocate(a1, a2, a3) is translated into the following sequence
3970 _gfortran_deallocate(a1, 0B)
3971 _gfortran_deallocate(a2, 0B)
3972 _gfortran_deallocate(a3, 0B)
3973 where the STAT= variable is passed a NULL pointer.
3974 (2) deallocate(a1, a2, a3, stat=i) is translated into the following
3975 astat = 0
3976 _gfortran_deallocate(a1, &stat)
3977 astat = astat + stat
3978 _gfortran_deallocate(a2, &stat)
3979 astat = astat + stat
3980 _gfortran_deallocate(a3, &stat)
3981 astat = astat + stat
3982 In case (1), we simply return at the end of the for loop. In case (2)
3983 we set STAT= astat. */
6de9cd9a
DN
3984tree
3985gfc_trans_deallocate (gfc_code * code)
3986{
3987 gfc_se se;
3988 gfc_alloc *al;
3989 gfc_expr *expr;
5039610b 3990 tree apstat, astat, pstat, stat, tmp;
6de9cd9a
DN
3991 stmtblock_t block;
3992
3993 gfc_start_block (&block);
3994
364667a1
SK
3995 /* Set up the optional STAT= */
3996 if (code->expr)
3997 {
3998 tree gfc_int4_type_node = gfc_get_int_type (4);
3999
4000 /* Variable used with the library call. */
4001 stat = gfc_create_var (gfc_int4_type_node, "stat");
628c189e 4002 pstat = gfc_build_addr_expr (NULL_TREE, stat);
364667a1
SK
4003
4004 /* Running total of possible deallocation failures. */
4005 astat = gfc_create_var (gfc_int4_type_node, "astat");
628c189e 4006 apstat = gfc_build_addr_expr (NULL_TREE, astat);
364667a1
SK
4007
4008 /* Initialize astat to 0. */
726a989a 4009 gfc_add_modify (&block, astat, build_int_cst (TREE_TYPE (astat), 0));
364667a1
SK
4010 }
4011 else
4376b7cf 4012 pstat = apstat = stat = astat = NULL_TREE;
364667a1 4013
6de9cd9a
DN
4014 for (al = code->ext.alloc_list; al != NULL; al = al->next)
4015 {
4016 expr = al->expr;
6e45f57b 4017 gcc_assert (expr->expr_type == EXPR_VARIABLE);
6de9cd9a
DN
4018
4019 gfc_init_se (&se, NULL);
4020 gfc_start_block (&se.pre);
4021
4022 se.want_pointer = 1;
4023 se.descriptor_only = 1;
4024 gfc_conv_expr (&se, expr);
4025
5046aff5
PT
4026 if (expr->ts.type == BT_DERIVED
4027 && expr->ts.derived->attr.alloc_comp)
4028 {
4029 gfc_ref *ref;
4030 gfc_ref *last = NULL;
4031 for (ref = expr->ref; ref; ref = ref->next)
4032 if (ref->type == REF_COMPONENT)
4033 last = ref;
4034
4035 /* Do not deallocate the components of a derived type
4036 ultimate pointer component. */
d4b7d0f0 4037 if (!(last && last->u.c.component->attr.pointer)
5046aff5
PT
4038 && !(!last && expr->symtree->n.sym->attr.pointer))
4039 {
4040 tmp = gfc_deallocate_alloc_comp (expr->ts.derived, se.expr,
f25a62a5 4041 expr->rank);
5046aff5
PT
4042 gfc_add_expr_to_block (&se.pre, tmp);
4043 }
4044 }
4045
4c46bf2e 4046 if (expr->rank)
f25a62a5 4047 tmp = gfc_array_deallocate (se.expr, pstat, expr);
6de9cd9a
DN
4048 else
4049 {
f25a62a5 4050 tmp = gfc_deallocate_with_status (se.expr, pstat, false, expr);
54200abb
RG
4051 gfc_add_expr_to_block (&se.pre, tmp);
4052
44855d8c
TS
4053 tmp = fold_build2 (MODIFY_EXPR, void_type_node,
4054 se.expr, build_int_cst (TREE_TYPE (se.expr), 0));
6de9cd9a 4055 }
364667a1
SK
4056
4057 gfc_add_expr_to_block (&se.pre, tmp);
4058
4059 /* Keep track of the number of failed deallocations by adding stat
4060 of the last deallocation to the running total. */
4061 if (code->expr)
4062 {
44855d8c 4063 apstat = fold_build2 (PLUS_EXPR, TREE_TYPE (stat), astat, stat);
726a989a 4064 gfc_add_modify (&se.pre, astat, apstat);
364667a1
SK
4065 }
4066
6de9cd9a
DN
4067 tmp = gfc_finish_block (&se.pre);
4068 gfc_add_expr_to_block (&block, tmp);
364667a1
SK
4069
4070 }
4071
4072 /* Assign the value to the status variable. */
4073 if (code->expr)
4074 {
4075 gfc_init_se (&se, NULL);
4076 gfc_conv_expr_lhs (&se, code->expr);
4077 tmp = convert (TREE_TYPE (se.expr), astat);
726a989a 4078 gfc_add_modify (&block, se.expr, tmp);
6de9cd9a
DN
4079 }
4080
4081 return gfc_finish_block (&block);
4082}
4083