2006-03-15 Paul Brook <paul@codesourcery.com>
[official-gcc.git] / gcc / fortran / trans-stmt.c
blobb3141ca84c740c010dde23b58188a12556dc854d
1 /* Statement translation -- generate GCC trees from gfc_code.
2 Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
3 Inc.
4 Contributed by Paul Brook <paul@nowt.org>
5 and Steven Bosscher <s.bosscher@student.tudelft.nl>
7 This file is part of GCC.
9 GCC is free software; you can redistribute it and/or modify it under
10 the terms of the GNU General Public License as published by the Free
11 Software Foundation; either version 2, or (at your option) any later
12 version.
14 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 for more details.
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING. If not, write to the Free
21 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
22 02110-1301, USA. */
25 #include "config.h"
26 #include "system.h"
27 #include "coretypes.h"
28 #include "tree.h"
29 #include "tree-gimple.h"
30 #include "ggc.h"
31 #include "toplev.h"
32 #include "real.h"
33 #include "gfortran.h"
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"
40 #include "dependency.h"
42 typedef struct iter_info
44 tree var;
45 tree start;
46 tree end;
47 tree step;
48 struct iter_info *next;
50 iter_info;
52 typedef struct forall_info
54 iter_info *this_loop;
55 tree mask;
56 tree pmask;
57 tree maskindex;
58 int nvar;
59 tree size;
60 struct forall_info *outer;
61 struct forall_info *next_nest;
63 forall_info;
65 static void gfc_trans_where_2 (gfc_code *, tree, bool,
66 forall_info *, stmtblock_t *);
68 /* Translate a F95 label number to a LABEL_EXPR. */
70 tree
71 gfc_trans_label_here (gfc_code * code)
73 return build1_v (LABEL_EXPR, gfc_get_label_decl (code->here));
77 /* Given a variable expression which has been ASSIGNed to, find the decl
78 containing the auxiliary variables. For variables in common blocks this
79 is a field_decl. */
81 void
82 gfc_conv_label_variable (gfc_se * se, gfc_expr * expr)
84 gcc_assert (expr->symtree->n.sym->attr.assign == 1);
85 gfc_conv_expr (se, expr);
86 /* Deals with variable in common block. Get the field declaration. */
87 if (TREE_CODE (se->expr) == COMPONENT_REF)
88 se->expr = TREE_OPERAND (se->expr, 1);
89 /* Deals with dummy argument. Get the parameter declaration. */
90 else if (TREE_CODE (se->expr) == INDIRECT_REF)
91 se->expr = TREE_OPERAND (se->expr, 0);
94 /* Translate a label assignment statement. */
96 tree
97 gfc_trans_label_assign (gfc_code * code)
99 tree label_tree;
100 gfc_se se;
101 tree len;
102 tree addr;
103 tree len_tree;
104 char *label_str;
105 int label_len;
107 /* Start a new block. */
108 gfc_init_se (&se, NULL);
109 gfc_start_block (&se.pre);
110 gfc_conv_label_variable (&se, code->expr);
112 len = GFC_DECL_STRING_LEN (se.expr);
113 addr = GFC_DECL_ASSIGN_ADDR (se.expr);
115 label_tree = gfc_get_label_decl (code->label);
117 if (code->label->defined == ST_LABEL_TARGET)
119 label_tree = gfc_build_addr_expr (pvoid_type_node, label_tree);
120 len_tree = integer_minus_one_node;
122 else
124 label_str = code->label->format->value.character.string;
125 label_len = code->label->format->value.character.length;
126 len_tree = build_int_cst (NULL_TREE, label_len);
127 label_tree = gfc_build_string_const (label_len + 1, label_str);
128 label_tree = gfc_build_addr_expr (pvoid_type_node, label_tree);
131 gfc_add_modify_expr (&se.pre, len, len_tree);
132 gfc_add_modify_expr (&se.pre, addr, label_tree);
134 return gfc_finish_block (&se.pre);
137 /* Translate a GOTO statement. */
139 tree
140 gfc_trans_goto (gfc_code * code)
142 tree assigned_goto;
143 tree target;
144 tree tmp;
145 tree assign_error;
146 tree range_error;
147 gfc_se se;
150 if (code->label != NULL)
151 return build1_v (GOTO_EXPR, gfc_get_label_decl (code->label));
153 /* ASSIGNED GOTO. */
154 gfc_init_se (&se, NULL);
155 gfc_start_block (&se.pre);
156 gfc_conv_label_variable (&se, code->expr);
157 assign_error =
158 gfc_build_cstring_const ("Assigned label is not a target label");
159 tmp = GFC_DECL_STRING_LEN (se.expr);
160 tmp = fold_build2 (NE_EXPR, boolean_type_node, tmp,
161 build_int_cst (TREE_TYPE (tmp), -1));
162 gfc_trans_runtime_check (tmp, assign_error, &se.pre);
164 assigned_goto = GFC_DECL_ASSIGN_ADDR (se.expr);
166 code = code->block;
167 if (code == NULL)
169 target = build1 (GOTO_EXPR, void_type_node, assigned_goto);
170 gfc_add_expr_to_block (&se.pre, target);
171 return gfc_finish_block (&se.pre);
174 /* Check the label list. */
175 range_error = gfc_build_cstring_const ("Assigned label is not in the list");
179 target = gfc_get_label_decl (code->label);
180 tmp = gfc_build_addr_expr (pvoid_type_node, target);
181 tmp = build2 (EQ_EXPR, boolean_type_node, tmp, assigned_goto);
182 tmp = build3_v (COND_EXPR, tmp,
183 build1 (GOTO_EXPR, void_type_node, target),
184 build_empty_stmt ());
185 gfc_add_expr_to_block (&se.pre, tmp);
186 code = code->block;
188 while (code != NULL);
189 gfc_trans_runtime_check (boolean_true_node, range_error, &se.pre);
190 return gfc_finish_block (&se.pre);
194 /* Translate an ENTRY statement. Just adds a label for this entry point. */
195 tree
196 gfc_trans_entry (gfc_code * code)
198 return build1_v (LABEL_EXPR, code->ext.entry->label);
202 /* Translate the CALL statement. Builds a call to an F95 subroutine. */
204 tree
205 gfc_trans_call (gfc_code * code)
207 gfc_se se;
208 gfc_ss * ss;
209 int has_alternate_specifier;
211 /* A CALL starts a new block because the actual arguments may have to
212 be evaluated first. */
213 gfc_init_se (&se, NULL);
214 gfc_start_block (&se.pre);
216 gcc_assert (code->resolved_sym);
218 ss = gfc_ss_terminator;
219 if (code->resolved_sym->attr.elemental)
220 ss = gfc_walk_elemental_function_args (ss, code->ext.actual, GFC_SS_REFERENCE);
222 /* Is not an elemental subroutine call with array valued arguments. */
223 if (ss == gfc_ss_terminator)
226 /* Translate the call. */
227 has_alternate_specifier
228 = gfc_conv_function_call (&se, code->resolved_sym, code->ext.actual);
230 /* A subroutine without side-effect, by definition, does nothing! */
231 TREE_SIDE_EFFECTS (se.expr) = 1;
233 /* Chain the pieces together and return the block. */
234 if (has_alternate_specifier)
236 gfc_code *select_code;
237 gfc_symbol *sym;
238 select_code = code->next;
239 gcc_assert(select_code->op == EXEC_SELECT);
240 sym = select_code->expr->symtree->n.sym;
241 se.expr = convert (gfc_typenode_for_spec (&sym->ts), se.expr);
242 gfc_add_modify_expr (&se.pre, sym->backend_decl, se.expr);
244 else
245 gfc_add_expr_to_block (&se.pre, se.expr);
247 gfc_add_block_to_block (&se.pre, &se.post);
250 else
252 /* An elemental subroutine call with array valued arguments has
253 to be scalarized. */
254 gfc_loopinfo loop;
255 stmtblock_t body;
256 stmtblock_t block;
257 gfc_se loopse;
259 /* gfc_walk_elemental_function_args renders the ss chain in the
260 reverse order to the actual argument order. */
261 ss = gfc_reverse_ss (ss);
263 /* Initialize the loop. */
264 gfc_init_se (&loopse, NULL);
265 gfc_init_loopinfo (&loop);
266 gfc_add_ss_to_loop (&loop, ss);
268 gfc_conv_ss_startstride (&loop);
269 gfc_conv_loop_setup (&loop);
270 gfc_mark_ss_chain_used (ss, 1);
272 /* Generate the loop body. */
273 gfc_start_scalarized_body (&loop, &body);
274 gfc_init_block (&block);
275 gfc_copy_loopinfo_to_se (&loopse, &loop);
276 loopse.ss = ss;
278 /* Add the subroutine call to the block. */
279 gfc_conv_function_call (&loopse, code->resolved_sym, code->ext.actual);
280 gfc_add_expr_to_block (&loopse.pre, loopse.expr);
282 gfc_add_block_to_block (&block, &loopse.pre);
283 gfc_add_block_to_block (&block, &loopse.post);
285 /* Finish up the loop block and the loop. */
286 gfc_add_expr_to_block (&body, gfc_finish_block (&block));
287 gfc_trans_scalarizing_loops (&loop, &body);
288 gfc_add_block_to_block (&se.pre, &loop.pre);
289 gfc_add_block_to_block (&se.pre, &loop.post);
290 gfc_cleanup_loop (&loop);
293 return gfc_finish_block (&se.pre);
297 /* Translate the RETURN statement. */
299 tree
300 gfc_trans_return (gfc_code * code ATTRIBUTE_UNUSED)
302 if (code->expr)
304 gfc_se se;
305 tree tmp;
306 tree result;
308 /* if code->expr is not NULL, this return statement must appear
309 in a subroutine and current_fake_result_decl has already
310 been generated. */
312 result = gfc_get_fake_result_decl (NULL, 0);
313 if (!result)
315 gfc_warning ("An alternate return at %L without a * dummy argument",
316 &code->expr->where);
317 return build1_v (GOTO_EXPR, gfc_get_return_label ());
320 /* Start a new block for this statement. */
321 gfc_init_se (&se, NULL);
322 gfc_start_block (&se.pre);
324 gfc_conv_expr (&se, code->expr);
326 tmp = build2 (MODIFY_EXPR, TREE_TYPE (result), result, se.expr);
327 gfc_add_expr_to_block (&se.pre, tmp);
329 tmp = build1_v (GOTO_EXPR, gfc_get_return_label ());
330 gfc_add_expr_to_block (&se.pre, tmp);
331 gfc_add_block_to_block (&se.pre, &se.post);
332 return gfc_finish_block (&se.pre);
334 else
335 return build1_v (GOTO_EXPR, gfc_get_return_label ());
339 /* Translate the PAUSE statement. We have to translate this statement
340 to a runtime library call. */
342 tree
343 gfc_trans_pause (gfc_code * code)
345 tree gfc_int4_type_node = gfc_get_int_type (4);
346 gfc_se se;
347 tree args;
348 tree tmp;
349 tree fndecl;
351 /* Start a new block for this statement. */
352 gfc_init_se (&se, NULL);
353 gfc_start_block (&se.pre);
356 if (code->expr == NULL)
358 tmp = build_int_cst (gfc_int4_type_node, code->ext.stop_code);
359 args = gfc_chainon_list (NULL_TREE, tmp);
360 fndecl = gfor_fndecl_pause_numeric;
362 else
364 gfc_conv_expr_reference (&se, code->expr);
365 args = gfc_chainon_list (NULL_TREE, se.expr);
366 args = gfc_chainon_list (args, se.string_length);
367 fndecl = gfor_fndecl_pause_string;
370 tmp = build_function_call_expr (fndecl, args);
371 gfc_add_expr_to_block (&se.pre, tmp);
373 gfc_add_block_to_block (&se.pre, &se.post);
375 return gfc_finish_block (&se.pre);
379 /* Translate the STOP statement. We have to translate this statement
380 to a runtime library call. */
382 tree
383 gfc_trans_stop (gfc_code * code)
385 tree gfc_int4_type_node = gfc_get_int_type (4);
386 gfc_se se;
387 tree args;
388 tree tmp;
389 tree fndecl;
391 /* Start a new block for this statement. */
392 gfc_init_se (&se, NULL);
393 gfc_start_block (&se.pre);
396 if (code->expr == NULL)
398 tmp = build_int_cst (gfc_int4_type_node, code->ext.stop_code);
399 args = gfc_chainon_list (NULL_TREE, tmp);
400 fndecl = gfor_fndecl_stop_numeric;
402 else
404 gfc_conv_expr_reference (&se, code->expr);
405 args = gfc_chainon_list (NULL_TREE, se.expr);
406 args = gfc_chainon_list (args, se.string_length);
407 fndecl = gfor_fndecl_stop_string;
410 tmp = build_function_call_expr (fndecl, args);
411 gfc_add_expr_to_block (&se.pre, tmp);
413 gfc_add_block_to_block (&se.pre, &se.post);
415 return gfc_finish_block (&se.pre);
419 /* Generate GENERIC for the IF construct. This function also deals with
420 the simple IF statement, because the front end translates the IF
421 statement into an IF construct.
423 We translate:
425 IF (cond) THEN
426 then_clause
427 ELSEIF (cond2)
428 elseif_clause
429 ELSE
430 else_clause
431 ENDIF
433 into:
435 pre_cond_s;
436 if (cond_s)
438 then_clause;
440 else
442 pre_cond_s
443 if (cond_s)
445 elseif_clause
447 else
449 else_clause;
453 where COND_S is the simplified version of the predicate. PRE_COND_S
454 are the pre side-effects produced by the translation of the
455 conditional.
456 We need to build the chain recursively otherwise we run into
457 problems with folding incomplete statements. */
459 static tree
460 gfc_trans_if_1 (gfc_code * code)
462 gfc_se if_se;
463 tree stmt, elsestmt;
465 /* Check for an unconditional ELSE clause. */
466 if (!code->expr)
467 return gfc_trans_code (code->next);
469 /* Initialize a statement builder for each block. Puts in NULL_TREEs. */
470 gfc_init_se (&if_se, NULL);
471 gfc_start_block (&if_se.pre);
473 /* Calculate the IF condition expression. */
474 gfc_conv_expr_val (&if_se, code->expr);
476 /* Translate the THEN clause. */
477 stmt = gfc_trans_code (code->next);
479 /* Translate the ELSE clause. */
480 if (code->block)
481 elsestmt = gfc_trans_if_1 (code->block);
482 else
483 elsestmt = build_empty_stmt ();
485 /* Build the condition expression and add it to the condition block. */
486 stmt = fold_build3 (COND_EXPR, void_type_node, if_se.expr, stmt, elsestmt);
488 gfc_add_expr_to_block (&if_se.pre, stmt);
490 /* Finish off this statement. */
491 return gfc_finish_block (&if_se.pre);
494 tree
495 gfc_trans_if (gfc_code * code)
497 /* Ignore the top EXEC_IF, it only announces an IF construct. The
498 actual code we must translate is in code->block. */
500 return gfc_trans_if_1 (code->block);
504 /* Translage an arithmetic IF expression.
506 IF (cond) label1, label2, label3 translates to
508 if (cond <= 0)
510 if (cond < 0)
511 goto label1;
512 else // cond == 0
513 goto label2;
515 else // cond > 0
516 goto label3;
518 An optimized version can be generated in case of equal labels.
519 E.g., if label1 is equal to label2, we can translate it to
521 if (cond <= 0)
522 goto label1;
523 else
524 goto label3;
527 tree
528 gfc_trans_arithmetic_if (gfc_code * code)
530 gfc_se se;
531 tree tmp;
532 tree branch1;
533 tree branch2;
534 tree zero;
536 /* Start a new block. */
537 gfc_init_se (&se, NULL);
538 gfc_start_block (&se.pre);
540 /* Pre-evaluate COND. */
541 gfc_conv_expr_val (&se, code->expr);
543 /* Build something to compare with. */
544 zero = gfc_build_const (TREE_TYPE (se.expr), integer_zero_node);
546 if (code->label->value != code->label2->value)
548 /* If (cond < 0) take branch1 else take branch2.
549 First build jumps to the COND .LT. 0 and the COND .EQ. 0 cases. */
550 branch1 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label));
551 branch2 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label2));
553 if (code->label->value != code->label3->value)
554 tmp = fold_build2 (LT_EXPR, boolean_type_node, se.expr, zero);
555 else
556 tmp = fold_build2 (NE_EXPR, boolean_type_node, se.expr, zero);
558 branch1 = fold_build3 (COND_EXPR, void_type_node, tmp, branch1, branch2);
560 else
561 branch1 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label));
563 if (code->label->value != code->label3->value
564 && code->label2->value != code->label3->value)
566 /* if (cond <= 0) take branch1 else take branch2. */
567 branch2 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label3));
568 tmp = fold_build2 (LE_EXPR, boolean_type_node, se.expr, zero);
569 branch1 = fold_build3 (COND_EXPR, void_type_node, tmp, branch1, branch2);
572 /* Append the COND_EXPR to the evaluation of COND, and return. */
573 gfc_add_expr_to_block (&se.pre, branch1);
574 return gfc_finish_block (&se.pre);
578 /* Translate the simple DO construct. This is where the loop variable has
579 integer type and step +-1. We can't use this in the general case
580 because integer overflow and floating point errors could give incorrect
581 results.
582 We translate a do loop from:
584 DO dovar = from, to, step
585 body
586 END DO
590 [Evaluate loop bounds and step]
591 dovar = from;
592 if ((step > 0) ? (dovar <= to) : (dovar => to))
594 for (;;)
596 body;
597 cycle_label:
598 cond = (dovar == to);
599 dovar += step;
600 if (cond) goto end_label;
603 end_label:
605 This helps the optimizers by avoiding the extra induction variable
606 used in the general case. */
608 static tree
609 gfc_trans_simple_do (gfc_code * code, stmtblock_t *pblock, tree dovar,
610 tree from, tree to, tree step)
612 stmtblock_t body;
613 tree type;
614 tree cond;
615 tree tmp;
616 tree cycle_label;
617 tree exit_label;
619 type = TREE_TYPE (dovar);
621 /* Initialize the DO variable: dovar = from. */
622 gfc_add_modify_expr (pblock, dovar, from);
624 /* Cycle and exit statements are implemented with gotos. */
625 cycle_label = gfc_build_label_decl (NULL_TREE);
626 exit_label = gfc_build_label_decl (NULL_TREE);
628 /* Put the labels where they can be found later. See gfc_trans_do(). */
629 code->block->backend_decl = tree_cons (cycle_label, exit_label, NULL);
631 /* Loop body. */
632 gfc_start_block (&body);
634 /* Main loop body. */
635 tmp = gfc_trans_code (code->block->next);
636 gfc_add_expr_to_block (&body, tmp);
638 /* Label for cycle statements (if needed). */
639 if (TREE_USED (cycle_label))
641 tmp = build1_v (LABEL_EXPR, cycle_label);
642 gfc_add_expr_to_block (&body, tmp);
645 /* Evaluate the loop condition. */
646 cond = fold_build2 (EQ_EXPR, boolean_type_node, dovar, to);
647 cond = gfc_evaluate_now (cond, &body);
649 /* Increment the loop variable. */
650 tmp = fold_build2 (PLUS_EXPR, type, dovar, step);
651 gfc_add_modify_expr (&body, dovar, tmp);
653 /* The loop exit. */
654 tmp = build1_v (GOTO_EXPR, exit_label);
655 TREE_USED (exit_label) = 1;
656 tmp = fold_build3 (COND_EXPR, void_type_node,
657 cond, tmp, build_empty_stmt ());
658 gfc_add_expr_to_block (&body, tmp);
660 /* Finish the loop body. */
661 tmp = gfc_finish_block (&body);
662 tmp = build1_v (LOOP_EXPR, tmp);
664 /* Only execute the loop if the number of iterations is positive. */
665 if (tree_int_cst_sgn (step) > 0)
666 cond = fold_build2 (LE_EXPR, boolean_type_node, dovar, to);
667 else
668 cond = fold_build2 (GE_EXPR, boolean_type_node, dovar, to);
669 tmp = fold_build3 (COND_EXPR, void_type_node,
670 cond, tmp, build_empty_stmt ());
671 gfc_add_expr_to_block (pblock, tmp);
673 /* Add the exit label. */
674 tmp = build1_v (LABEL_EXPR, exit_label);
675 gfc_add_expr_to_block (pblock, tmp);
677 return gfc_finish_block (pblock);
680 /* Translate the DO construct. This obviously is one of the most
681 important ones to get right with any compiler, but especially
682 so for Fortran.
684 We special case some loop forms as described in gfc_trans_simple_do.
685 For other cases we implement them with a separate loop count,
686 as described in the standard.
688 We translate a do loop from:
690 DO dovar = from, to, step
691 body
692 END DO
696 [evaluate loop bounds and step]
697 count = (to + step - from) / step;
698 dovar = from;
699 for (;;)
701 body;
702 cycle_label:
703 dovar += step
704 count--;
705 if (count <=0) goto exit_label;
707 exit_label:
709 TODO: Large loop counts
710 The code above assumes the loop count fits into a signed integer kind,
711 i.e. Does not work for loop counts > 2^31 for integer(kind=4) variables
712 We must support the full range. */
714 tree
715 gfc_trans_do (gfc_code * code)
717 gfc_se se;
718 tree dovar;
719 tree from;
720 tree to;
721 tree step;
722 tree count;
723 tree count_one;
724 tree type;
725 tree cond;
726 tree cycle_label;
727 tree exit_label;
728 tree tmp;
729 stmtblock_t block;
730 stmtblock_t body;
732 gfc_start_block (&block);
734 /* Evaluate all the expressions in the iterator. */
735 gfc_init_se (&se, NULL);
736 gfc_conv_expr_lhs (&se, code->ext.iterator->var);
737 gfc_add_block_to_block (&block, &se.pre);
738 dovar = se.expr;
739 type = TREE_TYPE (dovar);
741 gfc_init_se (&se, NULL);
742 gfc_conv_expr_val (&se, code->ext.iterator->start);
743 gfc_add_block_to_block (&block, &se.pre);
744 from = gfc_evaluate_now (se.expr, &block);
746 gfc_init_se (&se, NULL);
747 gfc_conv_expr_val (&se, code->ext.iterator->end);
748 gfc_add_block_to_block (&block, &se.pre);
749 to = gfc_evaluate_now (se.expr, &block);
751 gfc_init_se (&se, NULL);
752 gfc_conv_expr_val (&se, code->ext.iterator->step);
753 gfc_add_block_to_block (&block, &se.pre);
754 step = gfc_evaluate_now (se.expr, &block);
756 /* Special case simple loops. */
757 if (TREE_CODE (type) == INTEGER_TYPE
758 && (integer_onep (step)
759 || tree_int_cst_equal (step, integer_minus_one_node)))
760 return gfc_trans_simple_do (code, &block, dovar, from, to, step);
762 /* Initialize loop count. This code is executed before we enter the
763 loop body. We generate: count = (to + step - from) / step. */
765 tmp = fold_build2 (MINUS_EXPR, type, step, from);
766 tmp = fold_build2 (PLUS_EXPR, type, to, tmp);
767 if (TREE_CODE (type) == INTEGER_TYPE)
769 tmp = fold_build2 (TRUNC_DIV_EXPR, type, tmp, step);
770 count = gfc_create_var (type, "count");
772 else
774 /* TODO: We could use the same width as the real type.
775 This would probably cause more problems that it solves
776 when we implement "long double" types. */
777 tmp = fold_build2 (RDIV_EXPR, type, tmp, step);
778 tmp = fold_build1 (FIX_TRUNC_EXPR, gfc_array_index_type, tmp);
779 count = gfc_create_var (gfc_array_index_type, "count");
781 gfc_add_modify_expr (&block, count, tmp);
783 count_one = convert (TREE_TYPE (count), integer_one_node);
785 /* Initialize the DO variable: dovar = from. */
786 gfc_add_modify_expr (&block, dovar, from);
788 /* Loop body. */
789 gfc_start_block (&body);
791 /* Cycle and exit statements are implemented with gotos. */
792 cycle_label = gfc_build_label_decl (NULL_TREE);
793 exit_label = gfc_build_label_decl (NULL_TREE);
795 /* Start with the loop condition. Loop until count <= 0. */
796 cond = fold_build2 (LE_EXPR, boolean_type_node, count,
797 build_int_cst (TREE_TYPE (count), 0));
798 tmp = build1_v (GOTO_EXPR, exit_label);
799 TREE_USED (exit_label) = 1;
800 tmp = fold_build3 (COND_EXPR, void_type_node,
801 cond, tmp, build_empty_stmt ());
802 gfc_add_expr_to_block (&body, tmp);
804 /* Put these labels where they can be found later. We put the
805 labels in a TREE_LIST node (because TREE_CHAIN is already
806 used). cycle_label goes in TREE_PURPOSE (backend_decl), exit
807 label in TREE_VALUE (backend_decl). */
809 code->block->backend_decl = tree_cons (cycle_label, exit_label, NULL);
811 /* Main loop body. */
812 tmp = gfc_trans_code (code->block->next);
813 gfc_add_expr_to_block (&body, tmp);
815 /* Label for cycle statements (if needed). */
816 if (TREE_USED (cycle_label))
818 tmp = build1_v (LABEL_EXPR, cycle_label);
819 gfc_add_expr_to_block (&body, tmp);
822 /* Increment the loop variable. */
823 tmp = build2 (PLUS_EXPR, type, dovar, step);
824 gfc_add_modify_expr (&body, dovar, tmp);
826 /* Decrement the loop count. */
827 tmp = build2 (MINUS_EXPR, TREE_TYPE (count), count, count_one);
828 gfc_add_modify_expr (&body, count, tmp);
830 /* End of loop body. */
831 tmp = gfc_finish_block (&body);
833 /* The for loop itself. */
834 tmp = build1_v (LOOP_EXPR, tmp);
835 gfc_add_expr_to_block (&block, tmp);
837 /* Add the exit label. */
838 tmp = build1_v (LABEL_EXPR, exit_label);
839 gfc_add_expr_to_block (&block, tmp);
841 return gfc_finish_block (&block);
845 /* Translate the DO WHILE construct.
847 We translate
849 DO WHILE (cond)
850 body
851 END DO
855 for ( ; ; )
857 pre_cond;
858 if (! cond) goto exit_label;
859 body;
860 cycle_label:
862 exit_label:
864 Because the evaluation of the exit condition `cond' may have side
865 effects, we can't do much for empty loop bodies. The backend optimizers
866 should be smart enough to eliminate any dead loops. */
868 tree
869 gfc_trans_do_while (gfc_code * code)
871 gfc_se cond;
872 tree tmp;
873 tree cycle_label;
874 tree exit_label;
875 stmtblock_t block;
877 /* Everything we build here is part of the loop body. */
878 gfc_start_block (&block);
880 /* Cycle and exit statements are implemented with gotos. */
881 cycle_label = gfc_build_label_decl (NULL_TREE);
882 exit_label = gfc_build_label_decl (NULL_TREE);
884 /* Put the labels where they can be found later. See gfc_trans_do(). */
885 code->block->backend_decl = tree_cons (cycle_label, exit_label, NULL);
887 /* Create a GIMPLE version of the exit condition. */
888 gfc_init_se (&cond, NULL);
889 gfc_conv_expr_val (&cond, code->expr);
890 gfc_add_block_to_block (&block, &cond.pre);
891 cond.expr = fold_build1 (TRUTH_NOT_EXPR, boolean_type_node, cond.expr);
893 /* Build "IF (! cond) GOTO exit_label". */
894 tmp = build1_v (GOTO_EXPR, exit_label);
895 TREE_USED (exit_label) = 1;
896 tmp = fold_build3 (COND_EXPR, void_type_node,
897 cond.expr, tmp, build_empty_stmt ());
898 gfc_add_expr_to_block (&block, tmp);
900 /* The main body of the loop. */
901 tmp = gfc_trans_code (code->block->next);
902 gfc_add_expr_to_block (&block, tmp);
904 /* Label for cycle statements (if needed). */
905 if (TREE_USED (cycle_label))
907 tmp = build1_v (LABEL_EXPR, cycle_label);
908 gfc_add_expr_to_block (&block, tmp);
911 /* End of loop body. */
912 tmp = gfc_finish_block (&block);
914 gfc_init_block (&block);
915 /* Build the loop. */
916 tmp = build1_v (LOOP_EXPR, tmp);
917 gfc_add_expr_to_block (&block, tmp);
919 /* Add the exit label. */
920 tmp = build1_v (LABEL_EXPR, exit_label);
921 gfc_add_expr_to_block (&block, tmp);
923 return gfc_finish_block (&block);
927 /* Translate the SELECT CASE construct for INTEGER case expressions,
928 without killing all potential optimizations. The problem is that
929 Fortran allows unbounded cases, but the back-end does not, so we
930 need to intercept those before we enter the equivalent SWITCH_EXPR
931 we can build.
933 For example, we translate this,
935 SELECT CASE (expr)
936 CASE (:100,101,105:115)
937 block_1
938 CASE (190:199,200:)
939 block_2
940 CASE (300)
941 block_3
942 CASE DEFAULT
943 block_4
944 END SELECT
946 to the GENERIC equivalent,
948 switch (expr)
950 case (minimum value for typeof(expr) ... 100:
951 case 101:
952 case 105 ... 114:
953 block1:
954 goto end_label;
956 case 200 ... (maximum value for typeof(expr):
957 case 190 ... 199:
958 block2;
959 goto end_label;
961 case 300:
962 block_3;
963 goto end_label;
965 default:
966 block_4;
967 goto end_label;
970 end_label: */
972 static tree
973 gfc_trans_integer_select (gfc_code * code)
975 gfc_code *c;
976 gfc_case *cp;
977 tree end_label;
978 tree tmp;
979 gfc_se se;
980 stmtblock_t block;
981 stmtblock_t body;
983 gfc_start_block (&block);
985 /* Calculate the switch expression. */
986 gfc_init_se (&se, NULL);
987 gfc_conv_expr_val (&se, code->expr);
988 gfc_add_block_to_block (&block, &se.pre);
990 end_label = gfc_build_label_decl (NULL_TREE);
992 gfc_init_block (&body);
994 for (c = code->block; c; c = c->block)
996 for (cp = c->ext.case_list; cp; cp = cp->next)
998 tree low, high;
999 tree label;
1001 /* Assume it's the default case. */
1002 low = high = NULL_TREE;
1004 if (cp->low)
1006 low = gfc_conv_constant_to_tree (cp->low);
1008 /* If there's only a lower bound, set the high bound to the
1009 maximum value of the case expression. */
1010 if (!cp->high)
1011 high = TYPE_MAX_VALUE (TREE_TYPE (se.expr));
1014 if (cp->high)
1016 /* Three cases are possible here:
1018 1) There is no lower bound, e.g. CASE (:N).
1019 2) There is a lower bound .NE. high bound, that is
1020 a case range, e.g. CASE (N:M) where M>N (we make
1021 sure that M>N during type resolution).
1022 3) There is a lower bound, and it has the same value
1023 as the high bound, e.g. CASE (N:N). This is our
1024 internal representation of CASE(N).
1026 In the first and second case, we need to set a value for
1027 high. In the thirth case, we don't because the GCC middle
1028 end represents a single case value by just letting high be
1029 a NULL_TREE. We can't do that because we need to be able
1030 to represent unbounded cases. */
1032 if (!cp->low
1033 || (cp->low
1034 && mpz_cmp (cp->low->value.integer,
1035 cp->high->value.integer) != 0))
1036 high = gfc_conv_constant_to_tree (cp->high);
1038 /* Unbounded case. */
1039 if (!cp->low)
1040 low = TYPE_MIN_VALUE (TREE_TYPE (se.expr));
1043 /* Build a label. */
1044 label = gfc_build_label_decl (NULL_TREE);
1046 /* Add this case label.
1047 Add parameter 'label', make it match GCC backend. */
1048 tmp = build3 (CASE_LABEL_EXPR, void_type_node, low, high, label);
1049 gfc_add_expr_to_block (&body, tmp);
1052 /* Add the statements for this case. */
1053 tmp = gfc_trans_code (c->next);
1054 gfc_add_expr_to_block (&body, tmp);
1056 /* Break to the end of the construct. */
1057 tmp = build1_v (GOTO_EXPR, end_label);
1058 gfc_add_expr_to_block (&body, tmp);
1061 tmp = gfc_finish_block (&body);
1062 tmp = build3_v (SWITCH_EXPR, se.expr, tmp, NULL_TREE);
1063 gfc_add_expr_to_block (&block, tmp);
1065 tmp = build1_v (LABEL_EXPR, end_label);
1066 gfc_add_expr_to_block (&block, tmp);
1068 return gfc_finish_block (&block);
1072 /* Translate the SELECT CASE construct for LOGICAL case expressions.
1074 There are only two cases possible here, even though the standard
1075 does allow three cases in a LOGICAL SELECT CASE construct: .TRUE.,
1076 .FALSE., and DEFAULT.
1078 We never generate more than two blocks here. Instead, we always
1079 try to eliminate the DEFAULT case. This way, we can translate this
1080 kind of SELECT construct to a simple
1082 if {} else {};
1084 expression in GENERIC. */
1086 static tree
1087 gfc_trans_logical_select (gfc_code * code)
1089 gfc_code *c;
1090 gfc_code *t, *f, *d;
1091 gfc_case *cp;
1092 gfc_se se;
1093 stmtblock_t block;
1095 /* Assume we don't have any cases at all. */
1096 t = f = d = NULL;
1098 /* Now see which ones we actually do have. We can have at most two
1099 cases in a single case list: one for .TRUE. and one for .FALSE.
1100 The default case is always separate. If the cases for .TRUE. and
1101 .FALSE. are in the same case list, the block for that case list
1102 always executed, and we don't generate code a COND_EXPR. */
1103 for (c = code->block; c; c = c->block)
1105 for (cp = c->ext.case_list; cp; cp = cp->next)
1107 if (cp->low)
1109 if (cp->low->value.logical == 0) /* .FALSE. */
1110 f = c;
1111 else /* if (cp->value.logical != 0), thus .TRUE. */
1112 t = c;
1114 else
1115 d = c;
1119 /* Start a new block. */
1120 gfc_start_block (&block);
1122 /* Calculate the switch expression. We always need to do this
1123 because it may have side effects. */
1124 gfc_init_se (&se, NULL);
1125 gfc_conv_expr_val (&se, code->expr);
1126 gfc_add_block_to_block (&block, &se.pre);
1128 if (t == f && t != NULL)
1130 /* Cases for .TRUE. and .FALSE. are in the same block. Just
1131 translate the code for these cases, append it to the current
1132 block. */
1133 gfc_add_expr_to_block (&block, gfc_trans_code (t->next));
1135 else
1137 tree true_tree, false_tree, stmt;
1139 true_tree = build_empty_stmt ();
1140 false_tree = build_empty_stmt ();
1142 /* If we have a case for .TRUE. and for .FALSE., discard the default case.
1143 Otherwise, if .TRUE. or .FALSE. is missing and there is a default case,
1144 make the missing case the default case. */
1145 if (t != NULL && f != NULL)
1146 d = NULL;
1147 else if (d != NULL)
1149 if (t == NULL)
1150 t = d;
1151 else
1152 f = d;
1155 /* Translate the code for each of these blocks, and append it to
1156 the current block. */
1157 if (t != NULL)
1158 true_tree = gfc_trans_code (t->next);
1160 if (f != NULL)
1161 false_tree = gfc_trans_code (f->next);
1163 stmt = fold_build3 (COND_EXPR, void_type_node, se.expr,
1164 true_tree, false_tree);
1165 gfc_add_expr_to_block (&block, stmt);
1168 return gfc_finish_block (&block);
1172 /* Translate the SELECT CASE construct for CHARACTER case expressions.
1173 Instead of generating compares and jumps, it is far simpler to
1174 generate a data structure describing the cases in order and call a
1175 library subroutine that locates the right case.
1176 This is particularly true because this is the only case where we
1177 might have to dispose of a temporary.
1178 The library subroutine returns a pointer to jump to or NULL if no
1179 branches are to be taken. */
1181 static tree
1182 gfc_trans_character_select (gfc_code *code)
1184 tree init, node, end_label, tmp, type, args, *labels;
1185 stmtblock_t block, body;
1186 gfc_case *cp, *d;
1187 gfc_code *c;
1188 gfc_se se;
1189 int i, n;
1191 static tree select_struct;
1192 static tree ss_string1, ss_string1_len;
1193 static tree ss_string2, ss_string2_len;
1194 static tree ss_target;
1196 if (select_struct == NULL)
1198 tree gfc_int4_type_node = gfc_get_int_type (4);
1200 select_struct = make_node (RECORD_TYPE);
1201 TYPE_NAME (select_struct) = get_identifier ("_jump_struct");
1203 #undef ADD_FIELD
1204 #define ADD_FIELD(NAME, TYPE) \
1205 ss_##NAME = gfc_add_field_to_struct \
1206 (&(TYPE_FIELDS (select_struct)), select_struct, \
1207 get_identifier (stringize(NAME)), TYPE)
1209 ADD_FIELD (string1, pchar_type_node);
1210 ADD_FIELD (string1_len, gfc_int4_type_node);
1212 ADD_FIELD (string2, pchar_type_node);
1213 ADD_FIELD (string2_len, gfc_int4_type_node);
1215 ADD_FIELD (target, pvoid_type_node);
1216 #undef ADD_FIELD
1218 gfc_finish_type (select_struct);
1221 cp = code->block->ext.case_list;
1222 while (cp->left != NULL)
1223 cp = cp->left;
1225 n = 0;
1226 for (d = cp; d; d = d->right)
1227 d->n = n++;
1229 if (n != 0)
1230 labels = gfc_getmem (n * sizeof (tree));
1231 else
1232 labels = NULL;
1234 for(i = 0; i < n; i++)
1236 labels[i] = gfc_build_label_decl (NULL_TREE);
1237 TREE_USED (labels[i]) = 1;
1238 /* TODO: The gimplifier should do this for us, but it has
1239 inadequacies when dealing with static initializers. */
1240 FORCED_LABEL (labels[i]) = 1;
1243 end_label = gfc_build_label_decl (NULL_TREE);
1245 /* Generate the body */
1246 gfc_start_block (&block);
1247 gfc_init_block (&body);
1249 for (c = code->block; c; c = c->block)
1251 for (d = c->ext.case_list; d; d = d->next)
1253 tmp = build1_v (LABEL_EXPR, labels[d->n]);
1254 gfc_add_expr_to_block (&body, tmp);
1257 tmp = gfc_trans_code (c->next);
1258 gfc_add_expr_to_block (&body, tmp);
1260 tmp = build1_v (GOTO_EXPR, end_label);
1261 gfc_add_expr_to_block (&body, tmp);
1264 /* Generate the structure describing the branches */
1265 init = NULL_TREE;
1266 i = 0;
1268 for(d = cp; d; d = d->right, i++)
1270 node = NULL_TREE;
1272 gfc_init_se (&se, NULL);
1274 if (d->low == NULL)
1276 node = tree_cons (ss_string1, null_pointer_node, node);
1277 node = tree_cons (ss_string1_len, integer_zero_node, node);
1279 else
1281 gfc_conv_expr_reference (&se, d->low);
1283 node = tree_cons (ss_string1, se.expr, node);
1284 node = tree_cons (ss_string1_len, se.string_length, node);
1287 if (d->high == NULL)
1289 node = tree_cons (ss_string2, null_pointer_node, node);
1290 node = tree_cons (ss_string2_len, integer_zero_node, node);
1292 else
1294 gfc_init_se (&se, NULL);
1295 gfc_conv_expr_reference (&se, d->high);
1297 node = tree_cons (ss_string2, se.expr, node);
1298 node = tree_cons (ss_string2_len, se.string_length, node);
1301 tmp = gfc_build_addr_expr (pvoid_type_node, labels[i]);
1302 node = tree_cons (ss_target, tmp, node);
1304 tmp = build_constructor_from_list (select_struct, nreverse (node));
1305 init = tree_cons (NULL_TREE, tmp, init);
1308 type = build_array_type (select_struct, build_index_type
1309 (build_int_cst (NULL_TREE, n - 1)));
1311 init = build_constructor_from_list (type, nreverse(init));
1312 TREE_CONSTANT (init) = 1;
1313 TREE_INVARIANT (init) = 1;
1314 TREE_STATIC (init) = 1;
1315 /* Create a static variable to hold the jump table. */
1316 tmp = gfc_create_var (type, "jumptable");
1317 TREE_CONSTANT (tmp) = 1;
1318 TREE_INVARIANT (tmp) = 1;
1319 TREE_STATIC (tmp) = 1;
1320 DECL_INITIAL (tmp) = init;
1321 init = tmp;
1323 /* Build an argument list for the library call */
1324 init = gfc_build_addr_expr (pvoid_type_node, init);
1325 args = gfc_chainon_list (NULL_TREE, init);
1327 tmp = build_int_cst (NULL_TREE, n);
1328 args = gfc_chainon_list (args, tmp);
1330 tmp = gfc_build_addr_expr (pvoid_type_node, end_label);
1331 args = gfc_chainon_list (args, tmp);
1333 gfc_init_se (&se, NULL);
1334 gfc_conv_expr_reference (&se, code->expr);
1336 args = gfc_chainon_list (args, se.expr);
1337 args = gfc_chainon_list (args, se.string_length);
1339 gfc_add_block_to_block (&block, &se.pre);
1341 tmp = build_function_call_expr (gfor_fndecl_select_string, args);
1342 tmp = build1 (GOTO_EXPR, void_type_node, tmp);
1343 gfc_add_expr_to_block (&block, tmp);
1345 tmp = gfc_finish_block (&body);
1346 gfc_add_expr_to_block (&block, tmp);
1347 tmp = build1_v (LABEL_EXPR, end_label);
1348 gfc_add_expr_to_block (&block, tmp);
1350 if (n != 0)
1351 gfc_free (labels);
1353 return gfc_finish_block (&block);
1357 /* Translate the three variants of the SELECT CASE construct.
1359 SELECT CASEs with INTEGER case expressions can be translated to an
1360 equivalent GENERIC switch statement, and for LOGICAL case
1361 expressions we build one or two if-else compares.
1363 SELECT CASEs with CHARACTER case expressions are a whole different
1364 story, because they don't exist in GENERIC. So we sort them and
1365 do a binary search at runtime.
1367 Fortran has no BREAK statement, and it does not allow jumps from
1368 one case block to another. That makes things a lot easier for
1369 the optimizers. */
1371 tree
1372 gfc_trans_select (gfc_code * code)
1374 gcc_assert (code && code->expr);
1376 /* Empty SELECT constructs are legal. */
1377 if (code->block == NULL)
1378 return build_empty_stmt ();
1380 /* Select the correct translation function. */
1381 switch (code->expr->ts.type)
1383 case BT_LOGICAL: return gfc_trans_logical_select (code);
1384 case BT_INTEGER: return gfc_trans_integer_select (code);
1385 case BT_CHARACTER: return gfc_trans_character_select (code);
1386 default:
1387 gfc_internal_error ("gfc_trans_select(): Bad type for case expr.");
1388 /* Not reached */
1393 /* Generate the loops for a FORALL block. The normal loop format:
1394 count = (end - start + step) / step
1395 loopvar = start
1396 while (1)
1398 if (count <=0 )
1399 goto end_of_loop
1400 <body>
1401 loopvar += step
1402 count --
1404 end_of_loop: */
1406 static tree
1407 gfc_trans_forall_loop (forall_info *forall_tmp, int nvar, tree body, int mask_flag)
1409 int n;
1410 tree tmp;
1411 tree cond;
1412 stmtblock_t block;
1413 tree exit_label;
1414 tree count;
1415 tree var, start, end, step;
1416 iter_info *iter;
1418 iter = forall_tmp->this_loop;
1419 for (n = 0; n < nvar; n++)
1421 var = iter->var;
1422 start = iter->start;
1423 end = iter->end;
1424 step = iter->step;
1426 exit_label = gfc_build_label_decl (NULL_TREE);
1427 TREE_USED (exit_label) = 1;
1429 /* The loop counter. */
1430 count = gfc_create_var (TREE_TYPE (var), "count");
1432 /* The body of the loop. */
1433 gfc_init_block (&block);
1435 /* The exit condition. */
1436 cond = fold_build2 (LE_EXPR, boolean_type_node,
1437 count, build_int_cst (TREE_TYPE (count), 0));
1438 tmp = build1_v (GOTO_EXPR, exit_label);
1439 tmp = fold_build3 (COND_EXPR, void_type_node,
1440 cond, tmp, build_empty_stmt ());
1441 gfc_add_expr_to_block (&block, tmp);
1443 /* The main loop body. */
1444 gfc_add_expr_to_block (&block, body);
1446 /* Increment the loop variable. */
1447 tmp = build2 (PLUS_EXPR, TREE_TYPE (var), var, step);
1448 gfc_add_modify_expr (&block, var, tmp);
1450 /* Advance to the next mask element. Only do this for the
1451 innermost loop. */
1452 if (n == 0 && mask_flag && forall_tmp->mask)
1454 tree maskindex = forall_tmp->maskindex;
1455 tmp = build2 (PLUS_EXPR, gfc_array_index_type,
1456 maskindex, gfc_index_one_node);
1457 gfc_add_modify_expr (&block, maskindex, tmp);
1460 /* Decrement the loop counter. */
1461 tmp = build2 (MINUS_EXPR, TREE_TYPE (var), count, gfc_index_one_node);
1462 gfc_add_modify_expr (&block, count, tmp);
1464 body = gfc_finish_block (&block);
1466 /* Loop var initialization. */
1467 gfc_init_block (&block);
1468 gfc_add_modify_expr (&block, var, start);
1470 /* Initialize maskindex counter. Only do this before the
1471 outermost loop. */
1472 if (n == nvar - 1 && mask_flag && forall_tmp->mask)
1473 gfc_add_modify_expr (&block, forall_tmp->maskindex,
1474 gfc_index_zero_node);
1476 /* Initialize the loop counter. */
1477 tmp = fold_build2 (MINUS_EXPR, TREE_TYPE (var), step, start);
1478 tmp = fold_build2 (PLUS_EXPR, TREE_TYPE (var), end, tmp);
1479 tmp = fold_build2 (TRUNC_DIV_EXPR, TREE_TYPE (var), tmp, step);
1480 gfc_add_modify_expr (&block, count, tmp);
1482 /* The loop expression. */
1483 tmp = build1_v (LOOP_EXPR, body);
1484 gfc_add_expr_to_block (&block, tmp);
1486 /* The exit label. */
1487 tmp = build1_v (LABEL_EXPR, exit_label);
1488 gfc_add_expr_to_block (&block, tmp);
1490 body = gfc_finish_block (&block);
1491 iter = iter->next;
1493 return body;
1497 /* Generate the body and loops according to MASK_FLAG and NEST_FLAG.
1498 if MASK_FLAG is nonzero, the body is controlled by maskes in forall
1499 nest, otherwise, the body is not controlled by maskes.
1500 if NEST_FLAG is nonzero, generate loops for nested forall, otherwise,
1501 only generate loops for the current forall level. */
1503 static tree
1504 gfc_trans_nested_forall_loop (forall_info * nested_forall_info, tree body,
1505 int mask_flag, int nest_flag)
1507 tree tmp;
1508 int nvar;
1509 forall_info *forall_tmp;
1510 tree pmask, mask, maskindex;
1512 forall_tmp = nested_forall_info;
1513 /* Generate loops for nested forall. */
1514 if (nest_flag)
1516 while (forall_tmp->next_nest != NULL)
1517 forall_tmp = forall_tmp->next_nest;
1518 while (forall_tmp != NULL)
1520 /* Generate body with masks' control. */
1521 if (mask_flag)
1523 pmask = forall_tmp->pmask;
1524 mask = forall_tmp->mask;
1525 maskindex = forall_tmp->maskindex;
1527 if (mask)
1529 /* If a mask was specified make the assignment conditional. */
1530 if (pmask)
1531 tmp = build_fold_indirect_ref (mask);
1532 else
1533 tmp = mask;
1534 tmp = gfc_build_array_ref (tmp, maskindex);
1536 body = build3_v (COND_EXPR, tmp, body, build_empty_stmt ());
1539 nvar = forall_tmp->nvar;
1540 body = gfc_trans_forall_loop (forall_tmp, nvar, body, mask_flag);
1541 forall_tmp = forall_tmp->outer;
1544 else
1546 nvar = forall_tmp->nvar;
1547 body = gfc_trans_forall_loop (forall_tmp, nvar, body, mask_flag);
1550 return body;
1554 /* Allocate data for holding a temporary array. Returns either a local
1555 temporary array or a pointer variable. */
1557 static tree
1558 gfc_do_allocate (tree bytesize, tree size, tree * pdata, stmtblock_t * pblock,
1559 tree elem_type)
1561 tree tmpvar;
1562 tree type;
1563 tree tmp;
1564 tree args;
1566 if (INTEGER_CST_P (size))
1568 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type, size,
1569 gfc_index_one_node);
1571 else
1572 tmp = NULL_TREE;
1574 type = build_range_type (gfc_array_index_type, gfc_index_zero_node, tmp);
1575 type = build_array_type (elem_type, type);
1576 if (gfc_can_put_var_on_stack (bytesize))
1578 gcc_assert (INTEGER_CST_P (size));
1579 tmpvar = gfc_create_var (type, "temp");
1580 *pdata = NULL_TREE;
1582 else
1584 tmpvar = gfc_create_var (build_pointer_type (type), "temp");
1585 *pdata = convert (pvoid_type_node, tmpvar);
1587 args = gfc_chainon_list (NULL_TREE, bytesize);
1588 if (gfc_index_integer_kind == 4)
1589 tmp = gfor_fndecl_internal_malloc;
1590 else if (gfc_index_integer_kind == 8)
1591 tmp = gfor_fndecl_internal_malloc64;
1592 else
1593 gcc_unreachable ();
1594 tmp = build_function_call_expr (tmp, args);
1595 tmp = convert (TREE_TYPE (tmpvar), tmp);
1596 gfc_add_modify_expr (pblock, tmpvar, tmp);
1598 return tmpvar;
1602 /* Generate codes to copy the temporary to the actual lhs. */
1604 static tree
1605 generate_loop_for_temp_to_lhs (gfc_expr *expr, tree tmp1, tree count3,
1606 tree count1, tree wheremask, bool invert)
1608 gfc_ss *lss;
1609 gfc_se lse, rse;
1610 stmtblock_t block, body;
1611 gfc_loopinfo loop1;
1612 tree tmp;
1613 tree wheremaskexpr;
1615 /* Walk the lhs. */
1616 lss = gfc_walk_expr (expr);
1618 if (lss == gfc_ss_terminator)
1620 gfc_start_block (&block);
1622 gfc_init_se (&lse, NULL);
1624 /* Translate the expression. */
1625 gfc_conv_expr (&lse, expr);
1627 /* Form the expression for the temporary. */
1628 tmp = gfc_build_array_ref (tmp1, count1);
1630 /* Use the scalar assignment as is. */
1631 gfc_add_block_to_block (&block, &lse.pre);
1632 gfc_add_modify_expr (&block, lse.expr, tmp);
1633 gfc_add_block_to_block (&block, &lse.post);
1635 /* Increment the count1. */
1636 tmp = fold_build2 (PLUS_EXPR, TREE_TYPE (count1), count1,
1637 gfc_index_one_node);
1638 gfc_add_modify_expr (&block, count1, tmp);
1640 tmp = gfc_finish_block (&block);
1642 else
1644 gfc_start_block (&block);
1646 gfc_init_loopinfo (&loop1);
1647 gfc_init_se (&rse, NULL);
1648 gfc_init_se (&lse, NULL);
1650 /* Associate the lss with the loop. */
1651 gfc_add_ss_to_loop (&loop1, lss);
1653 /* Calculate the bounds of the scalarization. */
1654 gfc_conv_ss_startstride (&loop1);
1655 /* Setup the scalarizing loops. */
1656 gfc_conv_loop_setup (&loop1);
1658 gfc_mark_ss_chain_used (lss, 1);
1660 /* Start the scalarized loop body. */
1661 gfc_start_scalarized_body (&loop1, &body);
1663 /* Setup the gfc_se structures. */
1664 gfc_copy_loopinfo_to_se (&lse, &loop1);
1665 lse.ss = lss;
1667 /* Form the expression of the temporary. */
1668 if (lss != gfc_ss_terminator)
1669 rse.expr = gfc_build_array_ref (tmp1, count1);
1670 /* Translate expr. */
1671 gfc_conv_expr (&lse, expr);
1673 /* Use the scalar assignment. */
1674 tmp = gfc_trans_scalar_assign (&lse, &rse, expr->ts.type);
1676 /* Form the mask expression according to the mask tree list. */
1677 if (wheremask)
1679 wheremaskexpr = gfc_build_array_ref (wheremask, count3);
1680 if (invert)
1681 wheremaskexpr = fold_build1 (TRUTH_NOT_EXPR,
1682 TREE_TYPE (wheremaskexpr),
1683 wheremaskexpr);
1684 tmp = fold_build3 (COND_EXPR, void_type_node,
1685 wheremaskexpr, tmp, build_empty_stmt ());
1688 gfc_add_expr_to_block (&body, tmp);
1690 /* Increment count1. */
1691 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
1692 count1, gfc_index_one_node);
1693 gfc_add_modify_expr (&body, count1, tmp);
1695 /* Increment count3. */
1696 if (count3)
1698 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
1699 count3, gfc_index_one_node);
1700 gfc_add_modify_expr (&body, count3, tmp);
1703 /* Generate the copying loops. */
1704 gfc_trans_scalarizing_loops (&loop1, &body);
1705 gfc_add_block_to_block (&block, &loop1.pre);
1706 gfc_add_block_to_block (&block, &loop1.post);
1707 gfc_cleanup_loop (&loop1);
1709 tmp = gfc_finish_block (&block);
1711 return tmp;
1715 /* Generate codes to copy rhs to the temporary. TMP1 is the address of
1716 temporary, LSS and RSS are formed in function compute_inner_temp_size(),
1717 and should not be freed. WHEREMASK is the conditional execution mask
1718 whose sense may be inverted by INVERT. */
1720 static tree
1721 generate_loop_for_rhs_to_temp (gfc_expr *expr2, tree tmp1, tree count3,
1722 tree count1, gfc_ss *lss, gfc_ss *rss,
1723 tree wheremask, bool invert)
1725 stmtblock_t block, body1;
1726 gfc_loopinfo loop;
1727 gfc_se lse;
1728 gfc_se rse;
1729 tree tmp;
1730 tree wheremaskexpr;
1732 gfc_start_block (&block);
1734 gfc_init_se (&rse, NULL);
1735 gfc_init_se (&lse, NULL);
1737 if (lss == gfc_ss_terminator)
1739 gfc_init_block (&body1);
1740 gfc_conv_expr (&rse, expr2);
1741 lse.expr = gfc_build_array_ref (tmp1, count1);
1743 else
1745 /* Initialize the loop. */
1746 gfc_init_loopinfo (&loop);
1748 /* We may need LSS to determine the shape of the expression. */
1749 gfc_add_ss_to_loop (&loop, lss);
1750 gfc_add_ss_to_loop (&loop, rss);
1752 gfc_conv_ss_startstride (&loop);
1753 gfc_conv_loop_setup (&loop);
1755 gfc_mark_ss_chain_used (rss, 1);
1756 /* Start the loop body. */
1757 gfc_start_scalarized_body (&loop, &body1);
1759 /* Translate the expression. */
1760 gfc_copy_loopinfo_to_se (&rse, &loop);
1761 rse.ss = rss;
1762 gfc_conv_expr (&rse, expr2);
1764 /* Form the expression of the temporary. */
1765 lse.expr = gfc_build_array_ref (tmp1, count1);
1768 /* Use the scalar assignment. */
1769 tmp = gfc_trans_scalar_assign (&lse, &rse, expr2->ts.type);
1771 /* Form the mask expression according to the mask tree list. */
1772 if (wheremask)
1774 wheremaskexpr = gfc_build_array_ref (wheremask, count3);
1775 if (invert)
1776 wheremaskexpr = fold_build1 (TRUTH_NOT_EXPR,
1777 TREE_TYPE (wheremaskexpr),
1778 wheremaskexpr);
1779 tmp = fold_build3 (COND_EXPR, void_type_node,
1780 wheremaskexpr, tmp, build_empty_stmt ());
1783 gfc_add_expr_to_block (&body1, tmp);
1785 if (lss == gfc_ss_terminator)
1787 gfc_add_block_to_block (&block, &body1);
1789 /* Increment count1. */
1790 tmp = fold_build2 (PLUS_EXPR, TREE_TYPE (count1), count1,
1791 gfc_index_one_node);
1792 gfc_add_modify_expr (&block, count1, tmp);
1794 else
1796 /* Increment count1. */
1797 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
1798 count1, gfc_index_one_node);
1799 gfc_add_modify_expr (&body1, count1, tmp);
1801 /* Increment count3. */
1802 if (count3)
1804 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
1805 count3, gfc_index_one_node);
1806 gfc_add_modify_expr (&body1, count3, tmp);
1809 /* Generate the copying loops. */
1810 gfc_trans_scalarizing_loops (&loop, &body1);
1812 gfc_add_block_to_block (&block, &loop.pre);
1813 gfc_add_block_to_block (&block, &loop.post);
1815 gfc_cleanup_loop (&loop);
1816 /* TODO: Reuse lss and rss when copying temp->lhs. Need to be careful
1817 as tree nodes in SS may not be valid in different scope. */
1820 tmp = gfc_finish_block (&block);
1821 return tmp;
1825 /* Calculate the size of temporary needed in the assignment inside forall.
1826 LSS and RSS are filled in this function. */
1828 static tree
1829 compute_inner_temp_size (gfc_expr *expr1, gfc_expr *expr2,
1830 stmtblock_t * pblock,
1831 gfc_ss **lss, gfc_ss **rss)
1833 gfc_loopinfo loop;
1834 tree size;
1835 int i;
1836 tree tmp;
1838 *lss = gfc_walk_expr (expr1);
1839 *rss = NULL;
1841 size = gfc_index_one_node;
1842 if (*lss != gfc_ss_terminator)
1844 gfc_init_loopinfo (&loop);
1846 /* Walk the RHS of the expression. */
1847 *rss = gfc_walk_expr (expr2);
1848 if (*rss == gfc_ss_terminator)
1850 /* The rhs is scalar. Add a ss for the expression. */
1851 *rss = gfc_get_ss ();
1852 (*rss)->next = gfc_ss_terminator;
1853 (*rss)->type = GFC_SS_SCALAR;
1854 (*rss)->expr = expr2;
1857 /* Associate the SS with the loop. */
1858 gfc_add_ss_to_loop (&loop, *lss);
1859 /* We don't actually need to add the rhs at this point, but it might
1860 make guessing the loop bounds a bit easier. */
1861 gfc_add_ss_to_loop (&loop, *rss);
1863 /* We only want the shape of the expression, not rest of the junk
1864 generated by the scalarizer. */
1865 loop.array_parameter = 1;
1867 /* Calculate the bounds of the scalarization. */
1868 gfc_conv_ss_startstride (&loop);
1869 gfc_conv_loop_setup (&loop);
1871 /* Figure out how many elements we need. */
1872 for (i = 0; i < loop.dimen; i++)
1874 tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
1875 gfc_index_one_node, loop.from[i]);
1876 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
1877 tmp, loop.to[i]);
1878 size = fold_build2 (MULT_EXPR, gfc_array_index_type, size, tmp);
1880 gfc_add_block_to_block (pblock, &loop.pre);
1881 size = gfc_evaluate_now (size, pblock);
1882 gfc_add_block_to_block (pblock, &loop.post);
1884 /* TODO: write a function that cleans up a loopinfo without freeing
1885 the SS chains. Currently a NOP. */
1888 return size;
1892 /* Calculate the overall iterator number of the nested forall construct. */
1894 static tree
1895 compute_overall_iter_number (forall_info *nested_forall_info, tree inner_size,
1896 stmtblock_t *inner_size_body, stmtblock_t *block)
1898 tree tmp, number;
1899 stmtblock_t body;
1901 /* TODO: optimizing the computing process. */
1902 number = gfc_create_var (gfc_array_index_type, "num");
1903 gfc_add_modify_expr (block, number, gfc_index_zero_node);
1905 gfc_start_block (&body);
1906 if (inner_size_body)
1907 gfc_add_block_to_block (&body, inner_size_body);
1908 if (nested_forall_info)
1909 tmp = build2 (PLUS_EXPR, gfc_array_index_type, number,
1910 inner_size);
1911 else
1912 tmp = inner_size;
1913 gfc_add_modify_expr (&body, number, tmp);
1914 tmp = gfc_finish_block (&body);
1916 /* Generate loops. */
1917 if (nested_forall_info != NULL)
1918 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 0, 1);
1920 gfc_add_expr_to_block (block, tmp);
1922 return number;
1926 /* Allocate temporary for forall construct. SIZE is the size of temporary
1927 needed. PTEMP1 is returned for space free. */
1929 static tree
1930 allocate_temp_for_forall_nest_1 (tree type, tree size, stmtblock_t * block,
1931 tree * ptemp1)
1933 tree unit;
1934 tree temp1;
1935 tree tmp;
1936 tree bytesize;
1938 unit = TYPE_SIZE_UNIT (type);
1939 bytesize = fold_build2 (MULT_EXPR, gfc_array_index_type, size, unit);
1941 *ptemp1 = NULL;
1942 temp1 = gfc_do_allocate (bytesize, size, ptemp1, block, type);
1944 if (*ptemp1)
1945 tmp = build_fold_indirect_ref (temp1);
1946 else
1947 tmp = temp1;
1949 return tmp;
1953 /* Allocate temporary for forall construct according to the information in
1954 nested_forall_info. INNER_SIZE is the size of temporary needed in the
1955 assignment inside forall. PTEMP1 is returned for space free. */
1957 static tree
1958 allocate_temp_for_forall_nest (forall_info * nested_forall_info, tree type,
1959 tree inner_size, stmtblock_t * inner_size_body,
1960 stmtblock_t * block, tree * ptemp1)
1962 tree size;
1964 /* Calculate the total size of temporary needed in forall construct. */
1965 size = compute_overall_iter_number (nested_forall_info, inner_size,
1966 inner_size_body, block);
1968 return allocate_temp_for_forall_nest_1 (type, size, block, ptemp1);
1972 /* Handle assignments inside forall which need temporary.
1974 forall (i=start:end:stride; maskexpr)
1975 e<i> = f<i>
1976 end forall
1977 (where e,f<i> are arbitrary expressions possibly involving i
1978 and there is a dependency between e<i> and f<i>)
1979 Translates to:
1980 masktmp(:) = maskexpr(:)
1982 maskindex = 0;
1983 count1 = 0;
1984 num = 0;
1985 for (i = start; i <= end; i += stride)
1986 num += SIZE (f<i>)
1987 count1 = 0;
1988 ALLOCATE (tmp(num))
1989 for (i = start; i <= end; i += stride)
1991 if (masktmp[maskindex++])
1992 tmp[count1++] = f<i>
1994 maskindex = 0;
1995 count1 = 0;
1996 for (i = start; i <= end; i += stride)
1998 if (masktmp[maskindex++])
1999 e<i> = tmp[count1++]
2001 DEALLOCATE (tmp)
2003 static void
2004 gfc_trans_assign_need_temp (gfc_expr * expr1, gfc_expr * expr2,
2005 tree wheremask, bool invert,
2006 forall_info * nested_forall_info,
2007 stmtblock_t * block)
2009 tree type;
2010 tree inner_size;
2011 gfc_ss *lss, *rss;
2012 tree count, count1;
2013 tree tmp, tmp1;
2014 tree ptemp1;
2015 stmtblock_t inner_size_body;
2017 /* Create vars. count1 is the current iterator number of the nested
2018 forall. */
2019 count1 = gfc_create_var (gfc_array_index_type, "count1");
2021 /* Count is the wheremask index. */
2022 if (wheremask)
2024 count = gfc_create_var (gfc_array_index_type, "count");
2025 gfc_add_modify_expr (block, count, gfc_index_zero_node);
2027 else
2028 count = NULL;
2030 /* Initialize count1. */
2031 gfc_add_modify_expr (block, count1, gfc_index_zero_node);
2033 /* Calculate the size of temporary needed in the assignment. Return loop, lss
2034 and rss which are used in function generate_loop_for_rhs_to_temp(). */
2035 gfc_init_block (&inner_size_body);
2036 inner_size = compute_inner_temp_size (expr1, expr2, &inner_size_body,
2037 &lss, &rss);
2039 /* The type of LHS. Used in function allocate_temp_for_forall_nest */
2040 type = gfc_typenode_for_spec (&expr1->ts);
2042 /* Allocate temporary for nested forall construct according to the
2043 information in nested_forall_info and inner_size. */
2044 tmp1 = allocate_temp_for_forall_nest (nested_forall_info, type, inner_size,
2045 &inner_size_body, block, &ptemp1);
2047 /* Generate codes to copy rhs to the temporary . */
2048 tmp = generate_loop_for_rhs_to_temp (expr2, tmp1, count, count1, lss, rss,
2049 wheremask, invert);
2051 /* Generate body and loops according to the information in
2052 nested_forall_info. */
2053 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1, 1);
2054 gfc_add_expr_to_block (block, tmp);
2056 /* Reset count1. */
2057 gfc_add_modify_expr (block, count1, gfc_index_zero_node);
2059 /* Reset count. */
2060 if (wheremask)
2061 gfc_add_modify_expr (block, count, gfc_index_zero_node);
2063 /* Generate codes to copy the temporary to lhs. */
2064 tmp = generate_loop_for_temp_to_lhs (expr1, tmp1, count, count1,
2065 wheremask, invert);
2067 /* Generate body and loops according to the information in
2068 nested_forall_info. */
2069 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1, 1);
2070 gfc_add_expr_to_block (block, tmp);
2072 if (ptemp1)
2074 /* Free the temporary. */
2075 tmp = gfc_chainon_list (NULL_TREE, ptemp1);
2076 tmp = build_function_call_expr (gfor_fndecl_internal_free, tmp);
2077 gfc_add_expr_to_block (block, tmp);
2082 /* Translate pointer assignment inside FORALL which need temporary. */
2084 static void
2085 gfc_trans_pointer_assign_need_temp (gfc_expr * expr1, gfc_expr * expr2,
2086 forall_info * nested_forall_info,
2087 stmtblock_t * block)
2089 tree type;
2090 tree inner_size;
2091 gfc_ss *lss, *rss;
2092 gfc_se lse;
2093 gfc_se rse;
2094 gfc_ss_info *info;
2095 gfc_loopinfo loop;
2096 tree desc;
2097 tree parm;
2098 tree parmtype;
2099 stmtblock_t body;
2100 tree count;
2101 tree tmp, tmp1, ptemp1;
2103 count = gfc_create_var (gfc_array_index_type, "count");
2104 gfc_add_modify_expr (block, count, gfc_index_zero_node);
2106 inner_size = integer_one_node;
2107 lss = gfc_walk_expr (expr1);
2108 rss = gfc_walk_expr (expr2);
2109 if (lss == gfc_ss_terminator)
2111 type = gfc_typenode_for_spec (&expr1->ts);
2112 type = build_pointer_type (type);
2114 /* Allocate temporary for nested forall construct according to the
2115 information in nested_forall_info and inner_size. */
2116 tmp1 = allocate_temp_for_forall_nest (nested_forall_info, type,
2117 inner_size, NULL, block, &ptemp1);
2118 gfc_start_block (&body);
2119 gfc_init_se (&lse, NULL);
2120 lse.expr = gfc_build_array_ref (tmp1, count);
2121 gfc_init_se (&rse, NULL);
2122 rse.want_pointer = 1;
2123 gfc_conv_expr (&rse, expr2);
2124 gfc_add_block_to_block (&body, &rse.pre);
2125 gfc_add_modify_expr (&body, lse.expr,
2126 fold_convert (TREE_TYPE (lse.expr), rse.expr));
2127 gfc_add_block_to_block (&body, &rse.post);
2129 /* Increment count. */
2130 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
2131 count, gfc_index_one_node);
2132 gfc_add_modify_expr (&body, count, tmp);
2134 tmp = gfc_finish_block (&body);
2136 /* Generate body and loops according to the information in
2137 nested_forall_info. */
2138 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1, 1);
2139 gfc_add_expr_to_block (block, tmp);
2141 /* Reset count. */
2142 gfc_add_modify_expr (block, count, gfc_index_zero_node);
2144 gfc_start_block (&body);
2145 gfc_init_se (&lse, NULL);
2146 gfc_init_se (&rse, NULL);
2147 rse.expr = gfc_build_array_ref (tmp1, count);
2148 lse.want_pointer = 1;
2149 gfc_conv_expr (&lse, expr1);
2150 gfc_add_block_to_block (&body, &lse.pre);
2151 gfc_add_modify_expr (&body, lse.expr, rse.expr);
2152 gfc_add_block_to_block (&body, &lse.post);
2153 /* Increment count. */
2154 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
2155 count, gfc_index_one_node);
2156 gfc_add_modify_expr (&body, count, tmp);
2157 tmp = gfc_finish_block (&body);
2159 /* Generate body and loops according to the information in
2160 nested_forall_info. */
2161 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1, 1);
2162 gfc_add_expr_to_block (block, tmp);
2164 else
2166 gfc_init_loopinfo (&loop);
2168 /* Associate the SS with the loop. */
2169 gfc_add_ss_to_loop (&loop, rss);
2171 /* Setup the scalarizing loops and bounds. */
2172 gfc_conv_ss_startstride (&loop);
2174 gfc_conv_loop_setup (&loop);
2176 info = &rss->data.info;
2177 desc = info->descriptor;
2179 /* Make a new descriptor. */
2180 parmtype = gfc_get_element_type (TREE_TYPE (desc));
2181 parmtype = gfc_get_array_type_bounds (parmtype, loop.dimen,
2182 loop.from, loop.to, 1);
2184 /* Allocate temporary for nested forall construct. */
2185 tmp1 = allocate_temp_for_forall_nest (nested_forall_info, parmtype,
2186 inner_size, NULL, block, &ptemp1);
2187 gfc_start_block (&body);
2188 gfc_init_se (&lse, NULL);
2189 lse.expr = gfc_build_array_ref (tmp1, count);
2190 lse.direct_byref = 1;
2191 rss = gfc_walk_expr (expr2);
2192 gfc_conv_expr_descriptor (&lse, expr2, rss);
2194 gfc_add_block_to_block (&body, &lse.pre);
2195 gfc_add_block_to_block (&body, &lse.post);
2197 /* Increment count. */
2198 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
2199 count, gfc_index_one_node);
2200 gfc_add_modify_expr (&body, count, tmp);
2202 tmp = gfc_finish_block (&body);
2204 /* Generate body and loops according to the information in
2205 nested_forall_info. */
2206 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1, 1);
2207 gfc_add_expr_to_block (block, tmp);
2209 /* Reset count. */
2210 gfc_add_modify_expr (block, count, gfc_index_zero_node);
2212 parm = gfc_build_array_ref (tmp1, count);
2213 lss = gfc_walk_expr (expr1);
2214 gfc_init_se (&lse, NULL);
2215 gfc_conv_expr_descriptor (&lse, expr1, lss);
2216 gfc_add_modify_expr (&lse.pre, lse.expr, parm);
2217 gfc_start_block (&body);
2218 gfc_add_block_to_block (&body, &lse.pre);
2219 gfc_add_block_to_block (&body, &lse.post);
2221 /* Increment count. */
2222 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
2223 count, gfc_index_one_node);
2224 gfc_add_modify_expr (&body, count, tmp);
2226 tmp = gfc_finish_block (&body);
2228 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1, 1);
2229 gfc_add_expr_to_block (block, tmp);
2231 /* Free the temporary. */
2232 if (ptemp1)
2234 tmp = gfc_chainon_list (NULL_TREE, ptemp1);
2235 tmp = build_function_call_expr (gfor_fndecl_internal_free, tmp);
2236 gfc_add_expr_to_block (block, tmp);
2241 /* FORALL and WHERE statements are really nasty, especially when you nest
2242 them. All the rhs of a forall assignment must be evaluated before the
2243 actual assignments are performed. Presumably this also applies to all the
2244 assignments in an inner where statement. */
2246 /* Generate code for a FORALL statement. Any temporaries are allocated as a
2247 linear array, relying on the fact that we process in the same order in all
2248 loops.
2250 forall (i=start:end:stride; maskexpr)
2251 e<i> = f<i>
2252 g<i> = h<i>
2253 end forall
2254 (where e,f,g,h<i> are arbitrary expressions possibly involving i)
2255 Translates to:
2256 count = ((end + 1 - start) / stride)
2257 masktmp(:) = maskexpr(:)
2259 maskindex = 0;
2260 for (i = start; i <= end; i += stride)
2262 if (masktmp[maskindex++])
2263 e<i> = f<i>
2265 maskindex = 0;
2266 for (i = start; i <= end; i += stride)
2268 if (masktmp[maskindex++])
2269 g<i> = h<i>
2272 Note that this code only works when there are no dependencies.
2273 Forall loop with array assignments and data dependencies are a real pain,
2274 because the size of the temporary cannot always be determined before the
2275 loop is executed. This problem is compounded by the presence of nested
2276 FORALL constructs.
2279 static tree
2280 gfc_trans_forall_1 (gfc_code * code, forall_info * nested_forall_info)
2282 stmtblock_t block;
2283 stmtblock_t body;
2284 tree *var;
2285 tree *start;
2286 tree *end;
2287 tree *step;
2288 gfc_expr **varexpr;
2289 tree tmp;
2290 tree assign;
2291 tree size;
2292 tree bytesize;
2293 tree tmpvar;
2294 tree sizevar;
2295 tree lenvar;
2296 tree maskindex;
2297 tree mask;
2298 tree pmask;
2299 int n;
2300 int nvar;
2301 int need_temp;
2302 gfc_forall_iterator *fa;
2303 gfc_se se;
2304 gfc_code *c;
2305 gfc_saved_var *saved_vars;
2306 iter_info *this_forall, *iter_tmp;
2307 forall_info *info, *forall_tmp;
2309 gfc_start_block (&block);
2311 n = 0;
2312 /* Count the FORALL index number. */
2313 for (fa = code->ext.forall_iterator; fa; fa = fa->next)
2314 n++;
2315 nvar = n;
2317 /* Allocate the space for var, start, end, step, varexpr. */
2318 var = (tree *) gfc_getmem (nvar * sizeof (tree));
2319 start = (tree *) gfc_getmem (nvar * sizeof (tree));
2320 end = (tree *) gfc_getmem (nvar * sizeof (tree));
2321 step = (tree *) gfc_getmem (nvar * sizeof (tree));
2322 varexpr = (gfc_expr **) gfc_getmem (nvar * sizeof (gfc_expr *));
2323 saved_vars = (gfc_saved_var *) gfc_getmem (nvar * sizeof (gfc_saved_var));
2325 /* Allocate the space for info. */
2326 info = (forall_info *) gfc_getmem (sizeof (forall_info));
2327 n = 0;
2328 for (fa = code->ext.forall_iterator; fa; fa = fa->next)
2330 gfc_symbol *sym = fa->var->symtree->n.sym;
2332 /* allocate space for this_forall. */
2333 this_forall = (iter_info *) gfc_getmem (sizeof (iter_info));
2335 /* Create a temporary variable for the FORALL index. */
2336 tmp = gfc_typenode_for_spec (&sym->ts);
2337 var[n] = gfc_create_var (tmp, sym->name);
2338 gfc_shadow_sym (sym, var[n], &saved_vars[n]);
2340 /* Record it in this_forall. */
2341 this_forall->var = var[n];
2343 /* Replace the index symbol's backend_decl with the temporary decl. */
2344 sym->backend_decl = var[n];
2346 /* Work out the start, end and stride for the loop. */
2347 gfc_init_se (&se, NULL);
2348 gfc_conv_expr_val (&se, fa->start);
2349 /* Record it in this_forall. */
2350 this_forall->start = se.expr;
2351 gfc_add_block_to_block (&block, &se.pre);
2352 start[n] = se.expr;
2354 gfc_init_se (&se, NULL);
2355 gfc_conv_expr_val (&se, fa->end);
2356 /* Record it in this_forall. */
2357 this_forall->end = se.expr;
2358 gfc_make_safe_expr (&se);
2359 gfc_add_block_to_block (&block, &se.pre);
2360 end[n] = se.expr;
2362 gfc_init_se (&se, NULL);
2363 gfc_conv_expr_val (&se, fa->stride);
2364 /* Record it in this_forall. */
2365 this_forall->step = se.expr;
2366 gfc_make_safe_expr (&se);
2367 gfc_add_block_to_block (&block, &se.pre);
2368 step[n] = se.expr;
2370 /* Set the NEXT field of this_forall to NULL. */
2371 this_forall->next = NULL;
2372 /* Link this_forall to the info construct. */
2373 if (info->this_loop == NULL)
2374 info->this_loop = this_forall;
2375 else
2377 iter_tmp = info->this_loop;
2378 while (iter_tmp->next != NULL)
2379 iter_tmp = iter_tmp->next;
2380 iter_tmp->next = this_forall;
2383 n++;
2385 nvar = n;
2387 /* Work out the number of elements in the mask array. */
2388 tmpvar = NULL_TREE;
2389 lenvar = NULL_TREE;
2390 size = gfc_index_one_node;
2391 sizevar = NULL_TREE;
2393 for (n = 0; n < nvar; n++)
2395 if (lenvar && TREE_TYPE (lenvar) != TREE_TYPE (start[n]))
2396 lenvar = NULL_TREE;
2398 /* size = (end + step - start) / step. */
2399 tmp = fold_build2 (MINUS_EXPR, TREE_TYPE (start[n]),
2400 step[n], start[n]);
2401 tmp = fold_build2 (PLUS_EXPR, TREE_TYPE (end[n]), end[n], tmp);
2403 tmp = fold_build2 (FLOOR_DIV_EXPR, TREE_TYPE (tmp), tmp, step[n]);
2404 tmp = convert (gfc_array_index_type, tmp);
2406 size = fold_build2 (MULT_EXPR, gfc_array_index_type, size, tmp);
2409 /* Record the nvar and size of current forall level. */
2410 info->nvar = nvar;
2411 info->size = size;
2413 /* Link the current forall level to nested_forall_info. */
2414 forall_tmp = nested_forall_info;
2415 if (forall_tmp == NULL)
2416 nested_forall_info = info;
2417 else
2419 while (forall_tmp->next_nest != NULL)
2420 forall_tmp = forall_tmp->next_nest;
2421 info->outer = forall_tmp;
2422 forall_tmp->next_nest = info;
2425 /* Copy the mask into a temporary variable if required.
2426 For now we assume a mask temporary is needed. */
2427 if (code->expr)
2429 /* As the mask array can be very big, prefer compact
2430 boolean types. */
2431 tree smallest_boolean_type_node
2432 = gfc_get_logical_type (gfc_logical_kinds[0].kind);
2434 /* Allocate the mask temporary. */
2435 bytesize = fold_build2 (MULT_EXPR, gfc_array_index_type, size,
2436 TYPE_SIZE_UNIT (smallest_boolean_type_node));
2438 mask = gfc_do_allocate (bytesize, size, &pmask, &block,
2439 smallest_boolean_type_node);
2441 maskindex = gfc_create_var_np (gfc_array_index_type, "mi");
2442 /* Record them in the info structure. */
2443 info->pmask = pmask;
2444 info->mask = mask;
2445 info->maskindex = maskindex;
2447 gfc_add_modify_expr (&block, maskindex, gfc_index_zero_node);
2449 /* Start of mask assignment loop body. */
2450 gfc_start_block (&body);
2452 /* Evaluate the mask expression. */
2453 gfc_init_se (&se, NULL);
2454 gfc_conv_expr_val (&se, code->expr);
2455 gfc_add_block_to_block (&body, &se.pre);
2457 /* Store the mask. */
2458 se.expr = convert (smallest_boolean_type_node, se.expr);
2460 if (pmask)
2461 tmp = build_fold_indirect_ref (mask);
2462 else
2463 tmp = mask;
2464 tmp = gfc_build_array_ref (tmp, maskindex);
2465 gfc_add_modify_expr (&body, tmp, se.expr);
2467 /* Advance to the next mask element. */
2468 tmp = build2 (PLUS_EXPR, gfc_array_index_type,
2469 maskindex, gfc_index_one_node);
2470 gfc_add_modify_expr (&body, maskindex, tmp);
2472 /* Generate the loops. */
2473 tmp = gfc_finish_block (&body);
2474 tmp = gfc_trans_nested_forall_loop (info, tmp, 0, 0);
2475 gfc_add_expr_to_block (&block, tmp);
2477 else
2479 /* No mask was specified. */
2480 maskindex = NULL_TREE;
2481 mask = pmask = NULL_TREE;
2484 c = code->block->next;
2486 /* TODO: loop merging in FORALL statements. */
2487 /* Now that we've got a copy of the mask, generate the assignment loops. */
2488 while (c)
2490 switch (c->op)
2492 case EXEC_ASSIGN:
2493 /* A scalar or array assignment. */
2494 need_temp = gfc_check_dependency (c->expr, c->expr2, 0);
2495 /* Temporaries due to array assignment data dependencies introduce
2496 no end of problems. */
2497 if (need_temp)
2498 gfc_trans_assign_need_temp (c->expr, c->expr2, NULL, false,
2499 nested_forall_info, &block);
2500 else
2502 /* Use the normal assignment copying routines. */
2503 assign = gfc_trans_assignment (c->expr, c->expr2);
2505 /* Generate body and loops. */
2506 tmp = gfc_trans_nested_forall_loop (nested_forall_info, assign, 1, 1);
2507 gfc_add_expr_to_block (&block, tmp);
2510 break;
2512 case EXEC_WHERE:
2513 /* Translate WHERE or WHERE construct nested in FORALL. */
2514 gfc_trans_where_2 (c, NULL, false, nested_forall_info, &block);
2515 break;
2517 /* Pointer assignment inside FORALL. */
2518 case EXEC_POINTER_ASSIGN:
2519 need_temp = gfc_check_dependency (c->expr, c->expr2, 0);
2520 if (need_temp)
2521 gfc_trans_pointer_assign_need_temp (c->expr, c->expr2,
2522 nested_forall_info, &block);
2523 else
2525 /* Use the normal assignment copying routines. */
2526 assign = gfc_trans_pointer_assignment (c->expr, c->expr2);
2528 /* Generate body and loops. */
2529 tmp = gfc_trans_nested_forall_loop (nested_forall_info, assign,
2530 1, 1);
2531 gfc_add_expr_to_block (&block, tmp);
2533 break;
2535 case EXEC_FORALL:
2536 tmp = gfc_trans_forall_1 (c, nested_forall_info);
2537 gfc_add_expr_to_block (&block, tmp);
2538 break;
2540 /* Explicit subroutine calls are prevented by the frontend but interface
2541 assignments can legitimately produce them. */
2542 case EXEC_CALL:
2543 assign = gfc_trans_call (c);
2544 tmp = gfc_trans_nested_forall_loop (nested_forall_info, assign, 1, 1);
2545 gfc_add_expr_to_block (&block, tmp);
2546 break;
2548 default:
2549 gcc_unreachable ();
2552 c = c->next;
2555 /* Restore the original index variables. */
2556 for (fa = code->ext.forall_iterator, n = 0; fa; fa = fa->next, n++)
2557 gfc_restore_sym (fa->var->symtree->n.sym, &saved_vars[n]);
2559 /* Free the space for var, start, end, step, varexpr. */
2560 gfc_free (var);
2561 gfc_free (start);
2562 gfc_free (end);
2563 gfc_free (step);
2564 gfc_free (varexpr);
2565 gfc_free (saved_vars);
2567 if (pmask)
2569 /* Free the temporary for the mask. */
2570 tmp = gfc_chainon_list (NULL_TREE, pmask);
2571 tmp = build_function_call_expr (gfor_fndecl_internal_free, tmp);
2572 gfc_add_expr_to_block (&block, tmp);
2574 if (maskindex)
2575 pushdecl (maskindex);
2577 return gfc_finish_block (&block);
2581 /* Translate the FORALL statement or construct. */
2583 tree gfc_trans_forall (gfc_code * code)
2585 return gfc_trans_forall_1 (code, NULL);
2589 /* Evaluate the WHERE mask expression, copy its value to a temporary.
2590 If the WHERE construct is nested in FORALL, compute the overall temporary
2591 needed by the WHERE mask expression multiplied by the iterator number of
2592 the nested forall.
2593 ME is the WHERE mask expression.
2594 MASK is the current execution mask upon input, whose sense may or may
2595 not be inverted as specified by the INVERT argument.
2596 CMASK is the updated execution mask on output, or NULL if not required.
2597 PMASK is the pending execution mask on output, or NULL if not required.
2598 BLOCK is the block in which to place the condition evaluation loops. */
2600 static void
2601 gfc_evaluate_where_mask (gfc_expr * me, forall_info * nested_forall_info,
2602 tree mask, bool invert, tree cmask, tree pmask,
2603 tree mask_type, stmtblock_t * block)
2605 tree tmp, tmp1;
2606 gfc_ss *lss, *rss;
2607 gfc_loopinfo loop;
2608 stmtblock_t body, body1;
2609 tree count, cond, mtmp;
2610 gfc_se lse, rse;
2612 gfc_init_loopinfo (&loop);
2614 lss = gfc_walk_expr (me);
2615 rss = gfc_walk_expr (me);
2617 /* Variable to index the temporary. */
2618 count = gfc_create_var (gfc_array_index_type, "count");
2619 /* Initialize count. */
2620 gfc_add_modify_expr (block, count, gfc_index_zero_node);
2622 gfc_start_block (&body);
2624 gfc_init_se (&rse, NULL);
2625 gfc_init_se (&lse, NULL);
2627 if (lss == gfc_ss_terminator)
2629 gfc_init_block (&body1);
2631 else
2633 /* Initialize the loop. */
2634 gfc_init_loopinfo (&loop);
2636 /* We may need LSS to determine the shape of the expression. */
2637 gfc_add_ss_to_loop (&loop, lss);
2638 gfc_add_ss_to_loop (&loop, rss);
2640 gfc_conv_ss_startstride (&loop);
2641 gfc_conv_loop_setup (&loop);
2643 gfc_mark_ss_chain_used (rss, 1);
2644 /* Start the loop body. */
2645 gfc_start_scalarized_body (&loop, &body1);
2647 /* Translate the expression. */
2648 gfc_copy_loopinfo_to_se (&rse, &loop);
2649 rse.ss = rss;
2650 gfc_conv_expr (&rse, me);
2653 /* Variable to evalate mask condition. */
2654 cond = gfc_create_var (mask_type, "cond");
2655 if (mask && (cmask || pmask))
2656 mtmp = gfc_create_var (mask_type, "mask");
2657 else mtmp = NULL_TREE;
2659 gfc_add_block_to_block (&body1, &lse.pre);
2660 gfc_add_block_to_block (&body1, &rse.pre);
2662 gfc_add_modify_expr (&body1, cond, fold_convert (mask_type, rse.expr));
2664 if (mask && (cmask || pmask))
2666 tmp = gfc_build_array_ref (mask, count);
2667 if (invert)
2668 tmp = fold_build1 (TRUTH_NOT_EXPR, mask_type, tmp);
2669 gfc_add_modify_expr (&body1, mtmp, tmp);
2672 if (cmask)
2674 tmp1 = gfc_build_array_ref (cmask, count);
2675 tmp = cond;
2676 if (mask)
2677 tmp = build2 (TRUTH_AND_EXPR, mask_type, mtmp, tmp);
2678 gfc_add_modify_expr (&body1, tmp1, tmp);
2681 if (pmask)
2683 tmp1 = gfc_build_array_ref (pmask, count);
2684 tmp = build1 (TRUTH_NOT_EXPR, mask_type, cond);
2685 if (mask)
2686 tmp = build2 (TRUTH_AND_EXPR, mask_type, mtmp, tmp);
2687 gfc_add_modify_expr (&body1, tmp1, tmp);
2690 gfc_add_block_to_block (&body1, &lse.post);
2691 gfc_add_block_to_block (&body1, &rse.post);
2693 if (lss == gfc_ss_terminator)
2695 gfc_add_block_to_block (&body, &body1);
2697 else
2699 /* Increment count. */
2700 tmp1 = fold_build2 (PLUS_EXPR, gfc_array_index_type, count,
2701 gfc_index_one_node);
2702 gfc_add_modify_expr (&body1, count, tmp1);
2704 /* Generate the copying loops. */
2705 gfc_trans_scalarizing_loops (&loop, &body1);
2707 gfc_add_block_to_block (&body, &loop.pre);
2708 gfc_add_block_to_block (&body, &loop.post);
2710 gfc_cleanup_loop (&loop);
2711 /* TODO: Reuse lss and rss when copying temp->lhs. Need to be careful
2712 as tree nodes in SS may not be valid in different scope. */
2715 tmp1 = gfc_finish_block (&body);
2716 /* If the WHERE construct is inside FORALL, fill the full temporary. */
2717 if (nested_forall_info != NULL)
2718 tmp1 = gfc_trans_nested_forall_loop (nested_forall_info, tmp1, 1, 1);
2720 gfc_add_expr_to_block (block, tmp1);
2724 /* Translate an assignment statement in a WHERE statement or construct
2725 statement. The MASK expression is used to control which elements
2726 of EXPR1 shall be assigned. The sense of MASK is specified by
2727 INVERT. */
2729 static tree
2730 gfc_trans_where_assign (gfc_expr *expr1, gfc_expr *expr2,
2731 tree mask, bool invert,
2732 tree count1, tree count2)
2734 gfc_se lse;
2735 gfc_se rse;
2736 gfc_ss *lss;
2737 gfc_ss *lss_section;
2738 gfc_ss *rss;
2740 gfc_loopinfo loop;
2741 tree tmp;
2742 stmtblock_t block;
2743 stmtblock_t body;
2744 tree index, maskexpr;
2746 #if 0
2747 /* TODO: handle this special case.
2748 Special case a single function returning an array. */
2749 if (expr2->expr_type == EXPR_FUNCTION && expr2->rank > 0)
2751 tmp = gfc_trans_arrayfunc_assign (expr1, expr2);
2752 if (tmp)
2753 return tmp;
2755 #endif
2757 /* Assignment of the form lhs = rhs. */
2758 gfc_start_block (&block);
2760 gfc_init_se (&lse, NULL);
2761 gfc_init_se (&rse, NULL);
2763 /* Walk the lhs. */
2764 lss = gfc_walk_expr (expr1);
2765 rss = NULL;
2767 /* In each where-assign-stmt, the mask-expr and the variable being
2768 defined shall be arrays of the same shape. */
2769 gcc_assert (lss != gfc_ss_terminator);
2771 /* The assignment needs scalarization. */
2772 lss_section = lss;
2774 /* Find a non-scalar SS from the lhs. */
2775 while (lss_section != gfc_ss_terminator
2776 && lss_section->type != GFC_SS_SECTION)
2777 lss_section = lss_section->next;
2779 gcc_assert (lss_section != gfc_ss_terminator);
2781 /* Initialize the scalarizer. */
2782 gfc_init_loopinfo (&loop);
2784 /* Walk the rhs. */
2785 rss = gfc_walk_expr (expr2);
2786 if (rss == gfc_ss_terminator)
2788 /* The rhs is scalar. Add a ss for the expression. */
2789 rss = gfc_get_ss ();
2790 rss->next = gfc_ss_terminator;
2791 rss->type = GFC_SS_SCALAR;
2792 rss->expr = expr2;
2795 /* Associate the SS with the loop. */
2796 gfc_add_ss_to_loop (&loop, lss);
2797 gfc_add_ss_to_loop (&loop, rss);
2799 /* Calculate the bounds of the scalarization. */
2800 gfc_conv_ss_startstride (&loop);
2802 /* Resolve any data dependencies in the statement. */
2803 gfc_conv_resolve_dependencies (&loop, lss_section, rss);
2805 /* Setup the scalarizing loops. */
2806 gfc_conv_loop_setup (&loop);
2808 /* Setup the gfc_se structures. */
2809 gfc_copy_loopinfo_to_se (&lse, &loop);
2810 gfc_copy_loopinfo_to_se (&rse, &loop);
2812 rse.ss = rss;
2813 gfc_mark_ss_chain_used (rss, 1);
2814 if (loop.temp_ss == NULL)
2816 lse.ss = lss;
2817 gfc_mark_ss_chain_used (lss, 1);
2819 else
2821 lse.ss = loop.temp_ss;
2822 gfc_mark_ss_chain_used (lss, 3);
2823 gfc_mark_ss_chain_used (loop.temp_ss, 3);
2826 /* Start the scalarized loop body. */
2827 gfc_start_scalarized_body (&loop, &body);
2829 /* Translate the expression. */
2830 gfc_conv_expr (&rse, expr2);
2831 if (lss != gfc_ss_terminator && loop.temp_ss != NULL)
2833 gfc_conv_tmp_array_ref (&lse);
2834 gfc_advance_se_ss_chain (&lse);
2836 else
2837 gfc_conv_expr (&lse, expr1);
2839 /* Form the mask expression according to the mask. */
2840 index = count1;
2841 maskexpr = gfc_build_array_ref (mask, index);
2842 if (invert)
2843 maskexpr = fold_build1 (TRUTH_NOT_EXPR, TREE_TYPE (maskexpr), maskexpr);
2845 /* Use the scalar assignment as is. */
2846 tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts.type);
2847 tmp = build3_v (COND_EXPR, maskexpr, tmp, build_empty_stmt ());
2849 gfc_add_expr_to_block (&body, tmp);
2851 if (lss == gfc_ss_terminator)
2853 /* Increment count1. */
2854 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
2855 count1, gfc_index_one_node);
2856 gfc_add_modify_expr (&body, count1, tmp);
2858 /* Use the scalar assignment as is. */
2859 gfc_add_block_to_block (&block, &body);
2861 else
2863 gcc_assert (lse.ss == gfc_ss_terminator
2864 && rse.ss == gfc_ss_terminator);
2866 if (loop.temp_ss != NULL)
2868 /* Increment count1 before finish the main body of a scalarized
2869 expression. */
2870 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
2871 count1, gfc_index_one_node);
2872 gfc_add_modify_expr (&body, count1, tmp);
2873 gfc_trans_scalarized_loop_boundary (&loop, &body);
2875 /* We need to copy the temporary to the actual lhs. */
2876 gfc_init_se (&lse, NULL);
2877 gfc_init_se (&rse, NULL);
2878 gfc_copy_loopinfo_to_se (&lse, &loop);
2879 gfc_copy_loopinfo_to_se (&rse, &loop);
2881 rse.ss = loop.temp_ss;
2882 lse.ss = lss;
2884 gfc_conv_tmp_array_ref (&rse);
2885 gfc_advance_se_ss_chain (&rse);
2886 gfc_conv_expr (&lse, expr1);
2888 gcc_assert (lse.ss == gfc_ss_terminator
2889 && rse.ss == gfc_ss_terminator);
2891 /* Form the mask expression according to the mask tree list. */
2892 index = count2;
2893 maskexpr = gfc_build_array_ref (mask, index);
2894 if (invert)
2895 maskexpr = fold_build1 (TRUTH_NOT_EXPR, TREE_TYPE (maskexpr),
2896 maskexpr);
2898 /* Use the scalar assignment as is. */
2899 tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts.type);
2900 tmp = build3_v (COND_EXPR, maskexpr, tmp, build_empty_stmt ());
2901 gfc_add_expr_to_block (&body, tmp);
2903 /* Increment count2. */
2904 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
2905 count2, gfc_index_one_node);
2906 gfc_add_modify_expr (&body, count2, tmp);
2908 else
2910 /* Increment count1. */
2911 tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
2912 count1, gfc_index_one_node);
2913 gfc_add_modify_expr (&body, count1, tmp);
2916 /* Generate the copying loops. */
2917 gfc_trans_scalarizing_loops (&loop, &body);
2919 /* Wrap the whole thing up. */
2920 gfc_add_block_to_block (&block, &loop.pre);
2921 gfc_add_block_to_block (&block, &loop.post);
2922 gfc_cleanup_loop (&loop);
2925 return gfc_finish_block (&block);
2929 /* Translate the WHERE construct or statement.
2930 This function can be called iteratively to translate the nested WHERE
2931 construct or statement.
2932 MASK is the control mask. */
2934 static void
2935 gfc_trans_where_2 (gfc_code * code, tree mask, bool invert,
2936 forall_info * nested_forall_info, stmtblock_t * block)
2938 stmtblock_t inner_size_body;
2939 tree inner_size, size;
2940 gfc_ss *lss, *rss;
2941 tree mask_type;
2942 gfc_expr *expr1;
2943 gfc_expr *expr2;
2944 gfc_code *cblock;
2945 gfc_code *cnext;
2946 tree tmp;
2947 tree count1, count2;
2948 bool need_cmask;
2949 bool need_pmask;
2950 int need_temp;
2951 tree pcmask = NULL_TREE;
2952 tree ppmask = NULL_TREE;
2953 tree cmask = NULL_TREE;
2954 tree pmask = NULL_TREE;
2956 /* the WHERE statement or the WHERE construct statement. */
2957 cblock = code->block;
2959 /* As the mask array can be very big, prefer compact boolean types. */
2960 mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind);
2962 /* Determine which temporary masks are needed. */
2963 if (!cblock->block)
2965 /* One clause: No ELSEWHEREs. */
2966 need_cmask = (cblock->next != 0);
2967 need_pmask = false;
2969 else if (cblock->block->block)
2971 /* Three or more clauses: Conditional ELSEWHEREs. */
2972 need_cmask = true;
2973 need_pmask = true;
2975 else if (cblock->next)
2977 /* Two clauses, the first non-empty. */
2978 need_cmask = true;
2979 need_pmask = (mask != NULL_TREE
2980 && cblock->block->next != 0);
2982 else if (!cblock->block->next)
2984 /* Two clauses, both empty. */
2985 need_cmask = false;
2986 need_pmask = false;
2988 /* Two clauses, the first empty, the second non-empty. */
2989 else if (mask)
2991 need_cmask = (cblock->block->expr != 0);
2992 need_pmask = true;
2994 else
2996 need_cmask = true;
2997 need_pmask = false;
3000 if (need_cmask || need_pmask)
3002 /* Calculate the size of temporary needed by the mask-expr. */
3003 gfc_init_block (&inner_size_body);
3004 inner_size = compute_inner_temp_size (cblock->expr, cblock->expr,
3005 &inner_size_body, &lss, &rss);
3007 /* Calculate the total size of temporary needed. */
3008 size = compute_overall_iter_number (nested_forall_info, inner_size,
3009 &inner_size_body, block);
3011 /* Allocate temporary for WHERE mask if needed. */
3012 if (need_cmask)
3013 cmask = allocate_temp_for_forall_nest_1 (mask_type, size, block,
3014 &pcmask);
3016 /* Allocate temporary for !mask if needed. */
3017 if (need_pmask)
3018 pmask = allocate_temp_for_forall_nest_1 (mask_type, size, block,
3019 &ppmask);
3022 while (cblock)
3024 /* Each time around this loop, the where clause is conditional
3025 on the value of mask and invert, which are updated at the
3026 bottom of the loop. */
3028 /* Has mask-expr. */
3029 if (cblock->expr)
3031 /* Ensure that the WHERE mask will be evaluated exactly once.
3032 If there are no statements in this WHERE/ELSEWHERE clause,
3033 then we don't need to update the control mask (cmask).
3034 If this is the last clause of the WHERE construct, then
3035 we don't need to update the pending control mask (pmask). */
3036 if (mask)
3037 gfc_evaluate_where_mask (cblock->expr, nested_forall_info,
3038 mask, invert,
3039 cblock->next ? cmask : NULL_TREE,
3040 cblock->block ? pmask : NULL_TREE,
3041 mask_type, block);
3042 else
3043 gfc_evaluate_where_mask (cblock->expr, nested_forall_info,
3044 NULL_TREE, false,
3045 (cblock->next || cblock->block)
3046 ? cmask : NULL_TREE,
3047 NULL_TREE, mask_type, block);
3049 invert = false;
3051 /* It's a final elsewhere-stmt. No mask-expr is present. */
3052 else
3053 cmask = mask;
3055 /* The body of this where clause are controlled by cmask with
3056 sense specified by invert. */
3058 /* Get the assignment statement of a WHERE statement, or the first
3059 statement in where-body-construct of a WHERE construct. */
3060 cnext = cblock->next;
3061 while (cnext)
3063 switch (cnext->op)
3065 /* WHERE assignment statement. */
3066 case EXEC_ASSIGN:
3067 expr1 = cnext->expr;
3068 expr2 = cnext->expr2;
3069 if (nested_forall_info != NULL)
3071 need_temp = gfc_check_dependency (expr1, expr2, 0);
3072 if (need_temp)
3073 gfc_trans_assign_need_temp (expr1, expr2,
3074 cmask, invert,
3075 nested_forall_info, block);
3076 else
3078 /* Variables to control maskexpr. */
3079 count1 = gfc_create_var (gfc_array_index_type, "count1");
3080 count2 = gfc_create_var (gfc_array_index_type, "count2");
3081 gfc_add_modify_expr (block, count1, gfc_index_zero_node);
3082 gfc_add_modify_expr (block, count2, gfc_index_zero_node);
3084 tmp = gfc_trans_where_assign (expr1, expr2,
3085 cmask, invert,
3086 count1, count2);
3088 tmp = gfc_trans_nested_forall_loop (nested_forall_info,
3089 tmp, 1, 1);
3090 gfc_add_expr_to_block (block, tmp);
3093 else
3095 /* Variables to control maskexpr. */
3096 count1 = gfc_create_var (gfc_array_index_type, "count1");
3097 count2 = gfc_create_var (gfc_array_index_type, "count2");
3098 gfc_add_modify_expr (block, count1, gfc_index_zero_node);
3099 gfc_add_modify_expr (block, count2, gfc_index_zero_node);
3101 tmp = gfc_trans_where_assign (expr1, expr2,
3102 cmask, invert,
3103 count1, count2);
3104 gfc_add_expr_to_block (block, tmp);
3107 break;
3109 /* WHERE or WHERE construct is part of a where-body-construct. */
3110 case EXEC_WHERE:
3111 gfc_trans_where_2 (cnext, cmask, invert,
3112 nested_forall_info, block);
3113 break;
3115 default:
3116 gcc_unreachable ();
3119 /* The next statement within the same where-body-construct. */
3120 cnext = cnext->next;
3122 /* The next masked-elsewhere-stmt, elsewhere-stmt, or end-where-stmt. */
3123 cblock = cblock->block;
3124 if (mask == NULL_TREE)
3126 /* If we're the initial WHERE, we can simply invert the sense
3127 of the current mask to obtain the "mask" for the remaining
3128 ELSEWHEREs. */
3129 invert = true;
3130 mask = cmask;
3132 else
3134 /* Otherwise, for nested WHERE's we need to use the pending mask. */
3135 invert = false;
3136 mask = pmask;
3140 /* If we allocated a pending mask array, deallocate it now. */
3141 if (ppmask)
3143 tree args = gfc_chainon_list (NULL_TREE, ppmask);
3144 tmp = build_function_call_expr (gfor_fndecl_internal_free, args);
3145 gfc_add_expr_to_block (block, tmp);
3148 /* If we allocated a current mask array, deallocate it now. */
3149 if (pcmask)
3151 tree args = gfc_chainon_list (NULL_TREE, pcmask);
3152 tmp = build_function_call_expr (gfor_fndecl_internal_free, args);
3153 gfc_add_expr_to_block (block, tmp);
3157 /* Translate a simple WHERE construct or statement without dependencies.
3158 CBLOCK is the "then" clause of the WHERE statement, where CBLOCK->EXPR
3159 is the mask condition, and EBLOCK if non-NULL is the "else" clause.
3160 Currently both CBLOCK and EBLOCK are restricted to single assignments. */
3162 static tree
3163 gfc_trans_where_3 (gfc_code * cblock, gfc_code * eblock)
3165 stmtblock_t block, body;
3166 gfc_expr *cond, *tdst, *tsrc, *edst, *esrc;
3167 tree tmp, cexpr, tstmt, estmt;
3168 gfc_ss *css, *tdss, *tsss;
3169 gfc_se cse, tdse, tsse, edse, esse;
3170 gfc_loopinfo loop;
3171 gfc_ss *edss = 0;
3172 gfc_ss *esss = 0;
3174 cond = cblock->expr;
3175 tdst = cblock->next->expr;
3176 tsrc = cblock->next->expr2;
3177 edst = eblock ? eblock->next->expr : NULL;
3178 esrc = eblock ? eblock->next->expr2 : NULL;
3180 gfc_start_block (&block);
3181 gfc_init_loopinfo (&loop);
3183 /* Handle the condition. */
3184 gfc_init_se (&cse, NULL);
3185 css = gfc_walk_expr (cond);
3186 gfc_add_ss_to_loop (&loop, css);
3188 /* Handle the then-clause. */
3189 gfc_init_se (&tdse, NULL);
3190 gfc_init_se (&tsse, NULL);
3191 tdss = gfc_walk_expr (tdst);
3192 tsss = gfc_walk_expr (tsrc);
3193 if (tsss == gfc_ss_terminator)
3195 tsss = gfc_get_ss ();
3196 tsss->next = gfc_ss_terminator;
3197 tsss->type = GFC_SS_SCALAR;
3198 tsss->expr = tsrc;
3200 gfc_add_ss_to_loop (&loop, tdss);
3201 gfc_add_ss_to_loop (&loop, tsss);
3203 if (eblock)
3205 /* Handle the else clause. */
3206 gfc_init_se (&edse, NULL);
3207 gfc_init_se (&esse, NULL);
3208 edss = gfc_walk_expr (edst);
3209 esss = gfc_walk_expr (esrc);
3210 if (esss == gfc_ss_terminator)
3212 esss = gfc_get_ss ();
3213 esss->next = gfc_ss_terminator;
3214 esss->type = GFC_SS_SCALAR;
3215 esss->expr = esrc;
3217 gfc_add_ss_to_loop (&loop, edss);
3218 gfc_add_ss_to_loop (&loop, esss);
3221 gfc_conv_ss_startstride (&loop);
3222 gfc_conv_loop_setup (&loop);
3224 gfc_mark_ss_chain_used (css, 1);
3225 gfc_mark_ss_chain_used (tdss, 1);
3226 gfc_mark_ss_chain_used (tsss, 1);
3227 if (eblock)
3229 gfc_mark_ss_chain_used (edss, 1);
3230 gfc_mark_ss_chain_used (esss, 1);
3233 gfc_start_scalarized_body (&loop, &body);
3235 gfc_copy_loopinfo_to_se (&cse, &loop);
3236 gfc_copy_loopinfo_to_se (&tdse, &loop);
3237 gfc_copy_loopinfo_to_se (&tsse, &loop);
3238 cse.ss = css;
3239 tdse.ss = tdss;
3240 tsse.ss = tsss;
3241 if (eblock)
3243 gfc_copy_loopinfo_to_se (&edse, &loop);
3244 gfc_copy_loopinfo_to_se (&esse, &loop);
3245 edse.ss = edss;
3246 esse.ss = esss;
3249 gfc_conv_expr (&cse, cond);
3250 gfc_add_block_to_block (&body, &cse.pre);
3251 cexpr = cse.expr;
3253 gfc_conv_expr (&tsse, tsrc);
3254 if (tdss != gfc_ss_terminator && loop.temp_ss != NULL)
3256 gfc_conv_tmp_array_ref (&tdse);
3257 gfc_advance_se_ss_chain (&tdse);
3259 else
3260 gfc_conv_expr (&tdse, tdst);
3262 if (eblock)
3264 gfc_conv_expr (&esse, esrc);
3265 if (edss != gfc_ss_terminator && loop.temp_ss != NULL)
3267 gfc_conv_tmp_array_ref (&edse);
3268 gfc_advance_se_ss_chain (&edse);
3270 else
3271 gfc_conv_expr (&edse, edst);
3274 tstmt = gfc_trans_scalar_assign (&tdse, &tsse, tdst->ts.type);
3275 estmt = eblock ? gfc_trans_scalar_assign (&edse, &esse, edst->ts.type)
3276 : build_empty_stmt ();
3277 tmp = build3_v (COND_EXPR, cexpr, tstmt, estmt);
3278 gfc_add_expr_to_block (&body, tmp);
3279 gfc_add_block_to_block (&body, &cse.post);
3281 gfc_trans_scalarizing_loops (&loop, &body);
3282 gfc_add_block_to_block (&block, &loop.pre);
3283 gfc_add_block_to_block (&block, &loop.post);
3284 gfc_cleanup_loop (&loop);
3286 return gfc_finish_block (&block);
3289 /* As the WHERE or WHERE construct statement can be nested, we call
3290 gfc_trans_where_2 to do the translation, and pass the initial
3291 NULL values for both the control mask and the pending control mask. */
3293 tree
3294 gfc_trans_where (gfc_code * code)
3296 stmtblock_t block;
3297 gfc_code *cblock;
3298 gfc_code *eblock;
3300 cblock = code->block;
3301 if (cblock->next
3302 && cblock->next->op == EXEC_ASSIGN
3303 && !cblock->next->next)
3305 eblock = cblock->block;
3306 if (!eblock)
3308 /* A simple "WHERE (cond) x = y" statement or block is
3309 dependence free if cond is not dependent upon writing x,
3310 and the source y is unaffected by the destination x. */
3311 if (!gfc_check_dependency (cblock->next->expr,
3312 cblock->expr, 0)
3313 && !gfc_check_dependency (cblock->next->expr,
3314 cblock->next->expr2, 0))
3315 return gfc_trans_where_3 (cblock, NULL);
3317 else if (!eblock->expr
3318 && !eblock->block
3319 && eblock->next
3320 && eblock->next->op == EXEC_ASSIGN
3321 && !eblock->next->next)
3323 /* A simple "WHERE (cond) x1 = y1 ELSEWHERE x2 = y2 ENDWHERE"
3324 block is dependence free if cond is not dependent on writes
3325 to x1 and x2, y1 is not dependent on writes to x2, and y2
3326 is not dependent on writes to x1, and both y's are not
3327 dependent upon their own x's. */
3328 if (!gfc_check_dependency(cblock->next->expr,
3329 cblock->expr, 0)
3330 && !gfc_check_dependency(eblock->next->expr,
3331 cblock->expr, 0)
3332 && !gfc_check_dependency(cblock->next->expr,
3333 eblock->next->expr2, 0)
3334 && !gfc_check_dependency(eblock->next->expr,
3335 cblock->next->expr2, 0)
3336 && !gfc_check_dependency(cblock->next->expr,
3337 cblock->next->expr2, 0)
3338 && !gfc_check_dependency(eblock->next->expr,
3339 eblock->next->expr2, 0))
3340 return gfc_trans_where_3 (cblock, eblock);
3344 gfc_start_block (&block);
3346 gfc_trans_where_2 (code, NULL, false, NULL, &block);
3348 return gfc_finish_block (&block);
3352 /* CYCLE a DO loop. The label decl has already been created by
3353 gfc_trans_do(), it's in TREE_PURPOSE (backend_decl) of the gfc_code
3354 node at the head of the loop. We must mark the label as used. */
3356 tree
3357 gfc_trans_cycle (gfc_code * code)
3359 tree cycle_label;
3361 cycle_label = TREE_PURPOSE (code->ext.whichloop->backend_decl);
3362 TREE_USED (cycle_label) = 1;
3363 return build1_v (GOTO_EXPR, cycle_label);
3367 /* EXIT a DO loop. Similar to CYCLE, but now the label is in
3368 TREE_VALUE (backend_decl) of the gfc_code node at the head of the
3369 loop. */
3371 tree
3372 gfc_trans_exit (gfc_code * code)
3374 tree exit_label;
3376 exit_label = TREE_VALUE (code->ext.whichloop->backend_decl);
3377 TREE_USED (exit_label) = 1;
3378 return build1_v (GOTO_EXPR, exit_label);
3382 /* Translate the ALLOCATE statement. */
3384 tree
3385 gfc_trans_allocate (gfc_code * code)
3387 gfc_alloc *al;
3388 gfc_expr *expr;
3389 gfc_se se;
3390 tree tmp;
3391 tree parm;
3392 tree stat;
3393 tree pstat;
3394 tree error_label;
3395 stmtblock_t block;
3397 if (!code->ext.alloc_list)
3398 return NULL_TREE;
3400 gfc_start_block (&block);
3402 if (code->expr)
3404 tree gfc_int4_type_node = gfc_get_int_type (4);
3406 stat = gfc_create_var (gfc_int4_type_node, "stat");
3407 pstat = build_fold_addr_expr (stat);
3409 error_label = gfc_build_label_decl (NULL_TREE);
3410 TREE_USED (error_label) = 1;
3412 else
3414 pstat = integer_zero_node;
3415 stat = error_label = NULL_TREE;
3419 for (al = code->ext.alloc_list; al != NULL; al = al->next)
3421 expr = al->expr;
3423 gfc_init_se (&se, NULL);
3424 gfc_start_block (&se.pre);
3426 se.want_pointer = 1;
3427 se.descriptor_only = 1;
3428 gfc_conv_expr (&se, expr);
3430 if (!gfc_array_allocate (&se, expr, pstat))
3432 /* A scalar or derived type. */
3433 tree val;
3435 val = gfc_create_var (ppvoid_type_node, "ptr");
3436 tmp = gfc_build_addr_expr (ppvoid_type_node, se.expr);
3437 gfc_add_modify_expr (&se.pre, val, tmp);
3439 tmp = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (se.expr)));
3441 if (expr->ts.type == BT_CHARACTER && tmp == NULL_TREE)
3442 tmp = se.string_length;
3444 parm = gfc_chainon_list (NULL_TREE, val);
3445 parm = gfc_chainon_list (parm, tmp);
3446 parm = gfc_chainon_list (parm, pstat);
3447 tmp = build_function_call_expr (gfor_fndecl_allocate, parm);
3448 gfc_add_expr_to_block (&se.pre, tmp);
3450 if (code->expr)
3452 tmp = build1_v (GOTO_EXPR, error_label);
3453 parm = fold_build2 (NE_EXPR, boolean_type_node,
3454 stat, build_int_cst (TREE_TYPE (stat), 0));
3455 tmp = fold_build3 (COND_EXPR, void_type_node,
3456 parm, tmp, build_empty_stmt ());
3457 gfc_add_expr_to_block (&se.pre, tmp);
3461 tmp = gfc_finish_block (&se.pre);
3462 gfc_add_expr_to_block (&block, tmp);
3465 /* Assign the value to the status variable. */
3466 if (code->expr)
3468 tmp = build1_v (LABEL_EXPR, error_label);
3469 gfc_add_expr_to_block (&block, tmp);
3471 gfc_init_se (&se, NULL);
3472 gfc_conv_expr_lhs (&se, code->expr);
3473 tmp = convert (TREE_TYPE (se.expr), stat);
3474 gfc_add_modify_expr (&block, se.expr, tmp);
3477 return gfc_finish_block (&block);
3481 /* Translate a DEALLOCATE statement.
3482 There are two cases within the for loop:
3483 (1) deallocate(a1, a2, a3) is translated into the following sequence
3484 _gfortran_deallocate(a1, 0B)
3485 _gfortran_deallocate(a2, 0B)
3486 _gfortran_deallocate(a3, 0B)
3487 where the STAT= variable is passed a NULL pointer.
3488 (2) deallocate(a1, a2, a3, stat=i) is translated into the following
3489 astat = 0
3490 _gfortran_deallocate(a1, &stat)
3491 astat = astat + stat
3492 _gfortran_deallocate(a2, &stat)
3493 astat = astat + stat
3494 _gfortran_deallocate(a3, &stat)
3495 astat = astat + stat
3496 In case (1), we simply return at the end of the for loop. In case (2)
3497 we set STAT= astat. */
3498 tree
3499 gfc_trans_deallocate (gfc_code * code)
3501 gfc_se se;
3502 gfc_alloc *al;
3503 gfc_expr *expr;
3504 tree apstat, astat, parm, pstat, stat, tmp, type, var;
3505 stmtblock_t block;
3507 gfc_start_block (&block);
3509 /* Set up the optional STAT= */
3510 if (code->expr)
3512 tree gfc_int4_type_node = gfc_get_int_type (4);
3514 /* Variable used with the library call. */
3515 stat = gfc_create_var (gfc_int4_type_node, "stat");
3516 pstat = build_fold_addr_expr (stat);
3518 /* Running total of possible deallocation failures. */
3519 astat = gfc_create_var (gfc_int4_type_node, "astat");
3520 apstat = build_fold_addr_expr (astat);
3522 /* Initialize astat to 0. */
3523 gfc_add_modify_expr (&block, astat, build_int_cst (TREE_TYPE (astat), 0));
3525 else
3527 pstat = apstat = null_pointer_node;
3528 stat = astat = NULL_TREE;
3531 for (al = code->ext.alloc_list; al != NULL; al = al->next)
3533 expr = al->expr;
3534 gcc_assert (expr->expr_type == EXPR_VARIABLE);
3536 gfc_init_se (&se, NULL);
3537 gfc_start_block (&se.pre);
3539 se.want_pointer = 1;
3540 se.descriptor_only = 1;
3541 gfc_conv_expr (&se, expr);
3543 if (expr->rank)
3544 tmp = gfc_array_deallocate (se.expr, pstat);
3545 else
3547 type = build_pointer_type (TREE_TYPE (se.expr));
3548 var = gfc_create_var (type, "ptr");
3549 tmp = gfc_build_addr_expr (type, se.expr);
3550 gfc_add_modify_expr (&se.pre, var, tmp);
3552 parm = gfc_chainon_list (NULL_TREE, var);
3553 parm = gfc_chainon_list (parm, pstat);
3554 tmp = build_function_call_expr (gfor_fndecl_deallocate, parm);
3557 gfc_add_expr_to_block (&se.pre, tmp);
3559 /* Keep track of the number of failed deallocations by adding stat
3560 of the last deallocation to the running total. */
3561 if (code->expr)
3563 apstat = build2 (PLUS_EXPR, TREE_TYPE (stat), astat, stat);
3564 gfc_add_modify_expr (&se.pre, astat, apstat);
3567 tmp = gfc_finish_block (&se.pre);
3568 gfc_add_expr_to_block (&block, tmp);
3572 /* Assign the value to the status variable. */
3573 if (code->expr)
3575 gfc_init_se (&se, NULL);
3576 gfc_conv_expr_lhs (&se, code->expr);
3577 tmp = convert (TREE_TYPE (se.expr), astat);
3578 gfc_add_modify_expr (&block, se.expr, tmp);
3581 return gfc_finish_block (&block);