2018-06-04 Richard Biener <rguenther@suse.de>
[official-gcc.git] / gcc / fortran / frontend-passes.c
blob40e88b1a7d4263415360049fb4d5705f865ef47c
1 /* Pass manager for Fortran front end.
2 Copyright (C) 2010-2018 Free Software Foundation, Inc.
3 Contributed by Thomas König.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
10 version.
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "options.h"
25 #include "gfortran.h"
26 #include "dependency.h"
27 #include "constructor.h"
28 #include "intrinsic.h"
30 /* Forward declarations. */
32 static void strip_function_call (gfc_expr *);
33 static void optimize_namespace (gfc_namespace *);
34 static void optimize_assignment (gfc_code *);
35 static bool optimize_op (gfc_expr *);
36 static bool optimize_comparison (gfc_expr *, gfc_intrinsic_op);
37 static bool optimize_trim (gfc_expr *);
38 static bool optimize_lexical_comparison (gfc_expr *);
39 static void optimize_minmaxloc (gfc_expr **);
40 static bool is_empty_string (gfc_expr *e);
41 static void doloop_warn (gfc_namespace *);
42 static int do_intent (gfc_expr **);
43 static int do_subscript (gfc_expr **);
44 static void optimize_reduction (gfc_namespace *);
45 static int callback_reduction (gfc_expr **, int *, void *);
46 static void realloc_strings (gfc_namespace *);
47 static gfc_expr *create_var (gfc_expr *, const char *vname=NULL);
48 static int matmul_to_var_expr (gfc_expr **, int *, void *);
49 static int matmul_to_var_code (gfc_code **, int *, void *);
50 static int inline_matmul_assign (gfc_code **, int *, void *);
51 static gfc_code * create_do_loop (gfc_expr *, gfc_expr *, gfc_expr *,
52 locus *, gfc_namespace *,
53 char *vname=NULL);
54 static gfc_expr* check_conjg_transpose_variable (gfc_expr *, bool *,
55 bool *);
56 static bool has_dimen_vector_ref (gfc_expr *);
57 static int matmul_temp_args (gfc_code **, int *,void *data);
58 static int index_interchange (gfc_code **, int*, void *);
60 #ifdef CHECKING_P
61 static void check_locus (gfc_namespace *);
62 #endif
64 /* How deep we are inside an argument list. */
66 static int count_arglist;
68 /* Vector of gfc_expr ** we operate on. */
70 static vec<gfc_expr **> expr_array;
72 /* Pointer to the gfc_code we currently work on - to be able to insert
73 a block before the statement. */
75 static gfc_code **current_code;
77 /* Pointer to the block to be inserted, and the statement we are
78 changing within the block. */
80 static gfc_code *inserted_block, **changed_statement;
82 /* The namespace we are currently dealing with. */
84 static gfc_namespace *current_ns;
86 /* If we are within any forall loop. */
88 static int forall_level;
90 /* Keep track of whether we are within an OMP workshare. */
92 static bool in_omp_workshare;
94 /* Keep track of whether we are within a WHERE statement. */
96 static bool in_where;
98 /* Keep track of iterators for array constructors. */
100 static int iterator_level;
102 /* Keep track of DO loop levels. */
104 typedef struct {
105 gfc_code *c;
106 int branch_level;
107 bool seen_goto;
108 } do_t;
110 static vec<do_t> doloop_list;
111 static int doloop_level;
113 /* Keep track of if and select case levels. */
115 static int if_level;
116 static int select_level;
118 /* Vector of gfc_expr * to keep track of DO loops. */
120 struct my_struct *evec;
122 /* Keep track of association lists. */
124 static bool in_assoc_list;
126 /* Counter for temporary variables. */
128 static int var_num = 1;
130 /* What sort of matrix we are dealing with when inlining MATMUL. */
132 enum matrix_case { none=0, A2B2, A2B1, A1B2, A2B2T, A2TB2 };
134 /* Keep track of the number of expressions we have inserted so far
135 using create_var. */
137 int n_vars;
139 /* Entry point - run all passes for a namespace. */
141 void
142 gfc_run_passes (gfc_namespace *ns)
145 /* Warn about dubious DO loops where the index might
146 change. */
148 doloop_level = 0;
149 if_level = 0;
150 select_level = 0;
151 doloop_warn (ns);
152 doloop_list.release ();
153 int w, e;
155 #ifdef CHECKING_P
156 check_locus (ns);
157 #endif
159 gfc_get_errors (&w, &e);
160 if (e > 0)
161 return;
163 if (flag_frontend_optimize || flag_frontend_loop_interchange)
164 optimize_namespace (ns);
166 if (flag_frontend_optimize)
168 optimize_reduction (ns);
169 if (flag_dump_fortran_optimized)
170 gfc_dump_parse_tree (ns, stdout);
172 expr_array.release ();
175 if (flag_realloc_lhs)
176 realloc_strings (ns);
179 #ifdef CHECKING_P
181 /* Callback function: Warn if there is no location information in a
182 statement. */
184 static int
185 check_locus_code (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
186 void *data ATTRIBUTE_UNUSED)
188 current_code = c;
189 if (c && *c && (((*c)->loc.nextc == NULL) || ((*c)->loc.lb == NULL)))
190 gfc_warning_internal (0, "No location in statement");
192 return 0;
196 /* Callback function: Warn if there is no location information in an
197 expression. */
199 static int
200 check_locus_expr (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
201 void *data ATTRIBUTE_UNUSED)
204 if (e && *e && (((*e)->where.nextc == NULL || (*e)->where.lb == NULL)))
205 gfc_warning_internal (0, "No location in expression near %L",
206 &((*current_code)->loc));
207 return 0;
210 /* Run check for missing location information. */
212 static void
213 check_locus (gfc_namespace *ns)
215 gfc_code_walker (&ns->code, check_locus_code, check_locus_expr, NULL);
217 for (ns = ns->contained; ns; ns = ns->sibling)
219 if (ns->code == NULL || ns->code->op != EXEC_BLOCK)
220 check_locus (ns);
224 #endif
226 /* Callback for each gfc_code node invoked from check_realloc_strings.
227 For an allocatable LHS string which also appears as a variable on
228 the RHS, replace
230 a = a(x:y)
232 with
234 tmp = a(x:y)
235 a = tmp
238 static int
239 realloc_string_callback (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
240 void *data ATTRIBUTE_UNUSED)
242 gfc_expr *expr1, *expr2;
243 gfc_code *co = *c;
244 gfc_expr *n;
245 gfc_ref *ref;
246 bool found_substr;
248 if (co->op != EXEC_ASSIGN)
249 return 0;
251 expr1 = co->expr1;
252 if (expr1->ts.type != BT_CHARACTER
253 || !gfc_expr_attr(expr1).allocatable
254 || !expr1->ts.deferred)
255 return 0;
257 expr2 = gfc_discard_nops (co->expr2);
259 if (expr2->expr_type == EXPR_VARIABLE)
261 found_substr = false;
262 for (ref = expr2->ref; ref; ref = ref->next)
264 if (ref->type == REF_SUBSTRING)
266 found_substr = true;
267 break;
270 if (!found_substr)
271 return 0;
273 else if (expr2->expr_type != EXPR_ARRAY
274 && (expr2->expr_type != EXPR_OP
275 || expr2->value.op.op != INTRINSIC_CONCAT))
276 return 0;
278 if (!gfc_check_dependency (expr1, expr2, true))
279 return 0;
281 /* gfc_check_dependency doesn't always pick up identical expressions.
282 However, eliminating the above sends the compiler into an infinite
283 loop on valid expressions. Without this check, the gimplifier emits
284 an ICE for a = a, where a is deferred character length. */
285 if (!gfc_dep_compare_expr (expr1, expr2))
286 return 0;
288 current_code = c;
289 inserted_block = NULL;
290 changed_statement = NULL;
291 n = create_var (expr2, "realloc_string");
292 co->expr2 = n;
293 return 0;
296 /* Callback for each gfc_code node invoked through gfc_code_walker
297 from optimize_namespace. */
299 static int
300 optimize_code (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
301 void *data ATTRIBUTE_UNUSED)
304 gfc_exec_op op;
306 op = (*c)->op;
308 if (op == EXEC_CALL || op == EXEC_COMPCALL || op == EXEC_ASSIGN_CALL
309 || op == EXEC_CALL_PPC)
310 count_arglist = 1;
311 else
312 count_arglist = 0;
314 current_code = c;
315 inserted_block = NULL;
316 changed_statement = NULL;
318 if (op == EXEC_ASSIGN)
319 optimize_assignment (*c);
320 return 0;
323 /* Callback for each gfc_expr node invoked through gfc_code_walker
324 from optimize_namespace. */
326 static int
327 optimize_expr (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
328 void *data ATTRIBUTE_UNUSED)
330 bool function_expr;
332 if ((*e)->expr_type == EXPR_FUNCTION)
334 count_arglist ++;
335 function_expr = true;
337 else
338 function_expr = false;
340 if (optimize_trim (*e))
341 gfc_simplify_expr (*e, 0);
343 if (optimize_lexical_comparison (*e))
344 gfc_simplify_expr (*e, 0);
346 if ((*e)->expr_type == EXPR_OP && optimize_op (*e))
347 gfc_simplify_expr (*e, 0);
349 if ((*e)->expr_type == EXPR_FUNCTION && (*e)->value.function.isym)
350 switch ((*e)->value.function.isym->id)
352 case GFC_ISYM_MINLOC:
353 case GFC_ISYM_MAXLOC:
354 optimize_minmaxloc (e);
355 break;
356 default:
357 break;
360 if (function_expr)
361 count_arglist --;
363 return 0;
366 /* Auxiliary function to handle the arguments to reduction intrnisics. If the
367 function is a scalar, just copy it; otherwise returns the new element, the
368 old one can be freed. */
370 static gfc_expr *
371 copy_walk_reduction_arg (gfc_constructor *c, gfc_expr *fn)
373 gfc_expr *fcn, *e = c->expr;
375 fcn = gfc_copy_expr (e);
376 if (c->iterator)
378 gfc_constructor_base newbase;
379 gfc_expr *new_expr;
380 gfc_constructor *new_c;
382 newbase = NULL;
383 new_expr = gfc_get_expr ();
384 new_expr->expr_type = EXPR_ARRAY;
385 new_expr->ts = e->ts;
386 new_expr->where = e->where;
387 new_expr->rank = 1;
388 new_c = gfc_constructor_append_expr (&newbase, fcn, &(e->where));
389 new_c->iterator = c->iterator;
390 new_expr->value.constructor = newbase;
391 c->iterator = NULL;
393 fcn = new_expr;
396 if (fcn->rank != 0)
398 gfc_isym_id id = fn->value.function.isym->id;
400 if (id == GFC_ISYM_SUM || id == GFC_ISYM_PRODUCT)
401 fcn = gfc_build_intrinsic_call (current_ns, id,
402 fn->value.function.isym->name,
403 fn->where, 3, fcn, NULL, NULL);
404 else if (id == GFC_ISYM_ANY || id == GFC_ISYM_ALL)
405 fcn = gfc_build_intrinsic_call (current_ns, id,
406 fn->value.function.isym->name,
407 fn->where, 2, fcn, NULL);
408 else
409 gfc_internal_error ("Illegal id in copy_walk_reduction_arg");
411 fcn->symtree->n.sym->attr.access = ACCESS_PRIVATE;
414 return fcn;
417 /* Callback function for optimzation of reductions to scalars. Transform ANY
418 ([f1,f2,f3, ...]) to f1 .or. f2 .or. f3 .or. ..., with ANY, SUM and PRODUCT
419 correspondingly. Handly only the simple cases without MASK and DIM. */
421 static int
422 callback_reduction (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
423 void *data ATTRIBUTE_UNUSED)
425 gfc_expr *fn, *arg;
426 gfc_intrinsic_op op;
427 gfc_isym_id id;
428 gfc_actual_arglist *a;
429 gfc_actual_arglist *dim;
430 gfc_constructor *c;
431 gfc_expr *res, *new_expr;
432 gfc_actual_arglist *mask;
434 fn = *e;
436 if (fn->rank != 0 || fn->expr_type != EXPR_FUNCTION
437 || fn->value.function.isym == NULL)
438 return 0;
440 id = fn->value.function.isym->id;
442 if (id != GFC_ISYM_SUM && id != GFC_ISYM_PRODUCT
443 && id != GFC_ISYM_ANY && id != GFC_ISYM_ALL)
444 return 0;
446 a = fn->value.function.actual;
448 /* Don't handle MASK or DIM. */
450 dim = a->next;
452 if (dim->expr != NULL)
453 return 0;
455 if (id == GFC_ISYM_SUM || id == GFC_ISYM_PRODUCT)
457 mask = dim->next;
458 if ( mask->expr != NULL)
459 return 0;
462 arg = a->expr;
464 if (arg->expr_type != EXPR_ARRAY)
465 return 0;
467 switch (id)
469 case GFC_ISYM_SUM:
470 op = INTRINSIC_PLUS;
471 break;
473 case GFC_ISYM_PRODUCT:
474 op = INTRINSIC_TIMES;
475 break;
477 case GFC_ISYM_ANY:
478 op = INTRINSIC_OR;
479 break;
481 case GFC_ISYM_ALL:
482 op = INTRINSIC_AND;
483 break;
485 default:
486 return 0;
489 c = gfc_constructor_first (arg->value.constructor);
491 /* Don't do any simplififcation if we have
492 - no element in the constructor or
493 - only have a single element in the array which contains an
494 iterator. */
496 if (c == NULL)
497 return 0;
499 res = copy_walk_reduction_arg (c, fn);
501 c = gfc_constructor_next (c);
502 while (c)
504 new_expr = gfc_get_expr ();
505 new_expr->ts = fn->ts;
506 new_expr->expr_type = EXPR_OP;
507 new_expr->rank = fn->rank;
508 new_expr->where = fn->where;
509 new_expr->value.op.op = op;
510 new_expr->value.op.op1 = res;
511 new_expr->value.op.op2 = copy_walk_reduction_arg (c, fn);
512 res = new_expr;
513 c = gfc_constructor_next (c);
516 gfc_simplify_expr (res, 0);
517 *e = res;
518 gfc_free_expr (fn);
520 return 0;
523 /* Callback function for common function elimination, called from cfe_expr_0.
524 Put all eligible function expressions into expr_array. */
526 static int
527 cfe_register_funcs (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
528 void *data ATTRIBUTE_UNUSED)
531 if ((*e)->expr_type != EXPR_FUNCTION)
532 return 0;
534 /* We don't do character functions with unknown charlens. */
535 if ((*e)->ts.type == BT_CHARACTER
536 && ((*e)->ts.u.cl == NULL || (*e)->ts.u.cl->length == NULL
537 || (*e)->ts.u.cl->length->expr_type != EXPR_CONSTANT))
538 return 0;
540 /* We don't do function elimination within FORALL statements, it can
541 lead to wrong-code in certain circumstances. */
543 if (forall_level > 0)
544 return 0;
546 /* Function elimination inside an iterator could lead to functions which
547 depend on iterator variables being moved outside. FIXME: We should check
548 if the functions do indeed depend on the iterator variable. */
550 if (iterator_level > 0)
551 return 0;
553 /* If we don't know the shape at compile time, we create an allocatable
554 temporary variable to hold the intermediate result, but only if
555 allocation on assignment is active. */
557 if ((*e)->rank > 0 && (*e)->shape == NULL && !flag_realloc_lhs)
558 return 0;
560 /* Skip the test for pure functions if -faggressive-function-elimination
561 is specified. */
562 if ((*e)->value.function.esym)
564 /* Don't create an array temporary for elemental functions. */
565 if ((*e)->value.function.esym->attr.elemental && (*e)->rank > 0)
566 return 0;
568 /* Only eliminate potentially impure functions if the
569 user specifically requested it. */
570 if (!flag_aggressive_function_elimination
571 && !(*e)->value.function.esym->attr.pure
572 && !(*e)->value.function.esym->attr.implicit_pure)
573 return 0;
576 if ((*e)->value.function.isym)
578 /* Conversions are handled on the fly by the middle end,
579 transpose during trans-* stages and TRANSFER by the middle end. */
580 if ((*e)->value.function.isym->id == GFC_ISYM_CONVERSION
581 || (*e)->value.function.isym->id == GFC_ISYM_TRANSFER
582 || gfc_inline_intrinsic_function_p (*e))
583 return 0;
585 /* Don't create an array temporary for elemental functions,
586 as this would be wasteful of memory.
587 FIXME: Create a scalar temporary during scalarization. */
588 if ((*e)->value.function.isym->elemental && (*e)->rank > 0)
589 return 0;
591 if (!(*e)->value.function.isym->pure)
592 return 0;
595 expr_array.safe_push (e);
596 return 0;
599 /* Auxiliary function to check if an expression is a temporary created by
600 create var. */
602 static bool
603 is_fe_temp (gfc_expr *e)
605 if (e->expr_type != EXPR_VARIABLE)
606 return false;
608 return e->symtree->n.sym->attr.fe_temp;
611 /* Determine the length of a string, if it can be evaluated as a constant
612 expression. Return a newly allocated gfc_expr or NULL on failure.
613 If the user specified a substring which is potentially longer than
614 the string itself, the string will be padded with spaces, which
615 is harmless. */
617 static gfc_expr *
618 constant_string_length (gfc_expr *e)
621 gfc_expr *length;
622 gfc_ref *ref;
623 gfc_expr *res;
624 mpz_t value;
626 if (e->ts.u.cl)
628 length = e->ts.u.cl->length;
629 if (length && length->expr_type == EXPR_CONSTANT)
630 return gfc_copy_expr(length);
633 /* Return length of substring, if constant. */
634 for (ref = e->ref; ref; ref = ref->next)
636 if (ref->type == REF_SUBSTRING
637 && gfc_dep_difference (ref->u.ss.end, ref->u.ss.start, &value))
639 res = gfc_get_constant_expr (BT_INTEGER, gfc_charlen_int_kind,
640 &e->where);
642 mpz_add_ui (res->value.integer, value, 1);
643 mpz_clear (value);
644 return res;
648 /* Return length of char symbol, if constant. */
650 if (e->symtree && e->symtree->n.sym->ts.u.cl
651 && e->symtree->n.sym->ts.u.cl->length
652 && e->symtree->n.sym->ts.u.cl->length->expr_type == EXPR_CONSTANT)
653 return gfc_copy_expr (e->symtree->n.sym->ts.u.cl->length);
655 return NULL;
659 /* Insert a block at the current position unless it has already
660 been inserted; in this case use the one already there. */
662 static gfc_namespace*
663 insert_block ()
665 gfc_namespace *ns;
667 /* If the block hasn't already been created, do so. */
668 if (inserted_block == NULL)
670 inserted_block = XCNEW (gfc_code);
671 inserted_block->op = EXEC_BLOCK;
672 inserted_block->loc = (*current_code)->loc;
673 ns = gfc_build_block_ns (current_ns);
674 inserted_block->ext.block.ns = ns;
675 inserted_block->ext.block.assoc = NULL;
677 ns->code = *current_code;
679 /* If the statement has a label, make sure it is transferred to
680 the newly created block. */
682 if ((*current_code)->here)
684 inserted_block->here = (*current_code)->here;
685 (*current_code)->here = NULL;
688 inserted_block->next = (*current_code)->next;
689 changed_statement = &(inserted_block->ext.block.ns->code);
690 (*current_code)->next = NULL;
691 /* Insert the BLOCK at the right position. */
692 *current_code = inserted_block;
693 ns->parent = current_ns;
695 else
696 ns = inserted_block->ext.block.ns;
698 return ns;
701 /* Returns a new expression (a variable) to be used in place of the old one,
702 with an optional assignment statement before the current statement to set
703 the value of the variable. Creates a new BLOCK for the statement if that
704 hasn't already been done and puts the statement, plus the newly created
705 variables, in that block. Special cases: If the expression is constant or
706 a temporary which has already been created, just copy it. */
708 static gfc_expr*
709 create_var (gfc_expr * e, const char *vname)
711 char name[GFC_MAX_SYMBOL_LEN +1];
712 gfc_symtree *symtree;
713 gfc_symbol *symbol;
714 gfc_expr *result;
715 gfc_code *n;
716 gfc_namespace *ns;
717 int i;
718 bool deferred;
720 if (e->expr_type == EXPR_CONSTANT || is_fe_temp (e))
721 return gfc_copy_expr (e);
723 /* Creation of an array of unknown size requires realloc on assignment.
724 If that is not possible, just return NULL. */
725 if (flag_realloc_lhs == 0 && e->rank > 0 && e->shape == NULL)
726 return NULL;
728 ns = insert_block ();
730 if (vname)
731 snprintf (name, GFC_MAX_SYMBOL_LEN, "__var_%d_%s", var_num++, vname);
732 else
733 snprintf (name, GFC_MAX_SYMBOL_LEN, "__var_%d", var_num++);
735 if (gfc_get_sym_tree (name, ns, &symtree, false) != 0)
736 gcc_unreachable ();
738 symbol = symtree->n.sym;
739 symbol->ts = e->ts;
741 if (e->rank > 0)
743 symbol->as = gfc_get_array_spec ();
744 symbol->as->rank = e->rank;
746 if (e->shape == NULL)
748 /* We don't know the shape at compile time, so we use an
749 allocatable. */
750 symbol->as->type = AS_DEFERRED;
751 symbol->attr.allocatable = 1;
753 else
755 symbol->as->type = AS_EXPLICIT;
756 /* Copy the shape. */
757 for (i=0; i<e->rank; i++)
759 gfc_expr *p, *q;
761 p = gfc_get_constant_expr (BT_INTEGER, gfc_default_integer_kind,
762 &(e->where));
763 mpz_set_si (p->value.integer, 1);
764 symbol->as->lower[i] = p;
766 q = gfc_get_constant_expr (BT_INTEGER, gfc_index_integer_kind,
767 &(e->where));
768 mpz_set (q->value.integer, e->shape[i]);
769 symbol->as->upper[i] = q;
774 deferred = 0;
775 if (e->ts.type == BT_CHARACTER)
777 gfc_expr *length;
779 symbol->ts.u.cl = gfc_new_charlen (ns, NULL);
780 length = constant_string_length (e);
781 if (length)
782 symbol->ts.u.cl->length = length;
783 else
785 symbol->attr.allocatable = 1;
786 symbol->ts.u.cl->length = NULL;
787 symbol->ts.deferred = 1;
788 deferred = 1;
792 symbol->attr.flavor = FL_VARIABLE;
793 symbol->attr.referenced = 1;
794 symbol->attr.dimension = e->rank > 0;
795 symbol->attr.fe_temp = 1;
796 gfc_commit_symbol (symbol);
798 result = gfc_get_expr ();
799 result->expr_type = EXPR_VARIABLE;
800 result->ts = symbol->ts;
801 result->ts.deferred = deferred;
802 result->rank = e->rank;
803 result->shape = gfc_copy_shape (e->shape, e->rank);
804 result->symtree = symtree;
805 result->where = e->where;
806 if (e->rank > 0)
808 result->ref = gfc_get_ref ();
809 result->ref->type = REF_ARRAY;
810 result->ref->u.ar.type = AR_FULL;
811 result->ref->u.ar.where = e->where;
812 result->ref->u.ar.dimen = e->rank;
813 result->ref->u.ar.as = symbol->ts.type == BT_CLASS
814 ? CLASS_DATA (symbol)->as : symbol->as;
815 if (warn_array_temporaries)
816 gfc_warning (OPT_Warray_temporaries,
817 "Creating array temporary at %L", &(e->where));
820 /* Generate the new assignment. */
821 n = XCNEW (gfc_code);
822 n->op = EXEC_ASSIGN;
823 n->loc = (*current_code)->loc;
824 n->next = *changed_statement;
825 n->expr1 = gfc_copy_expr (result);
826 n->expr2 = e;
827 *changed_statement = n;
828 n_vars ++;
830 return result;
833 /* Warn about function elimination. */
835 static void
836 do_warn_function_elimination (gfc_expr *e)
838 if (e->expr_type != EXPR_FUNCTION)
839 return;
840 if (e->value.function.esym)
841 gfc_warning (OPT_Wfunction_elimination,
842 "Removing call to function %qs at %L",
843 e->value.function.esym->name, &(e->where));
844 else if (e->value.function.isym)
845 gfc_warning (OPT_Wfunction_elimination,
846 "Removing call to function %qs at %L",
847 e->value.function.isym->name, &(e->where));
849 /* Callback function for the code walker for doing common function
850 elimination. This builds up the list of functions in the expression
851 and goes through them to detect duplicates, which it then replaces
852 by variables. */
854 static int
855 cfe_expr_0 (gfc_expr **e, int *walk_subtrees,
856 void *data ATTRIBUTE_UNUSED)
858 int i,j;
859 gfc_expr *newvar;
860 gfc_expr **ei, **ej;
862 /* Don't do this optimization within OMP workshare or ASSOC lists. */
864 if (in_omp_workshare || in_assoc_list)
866 *walk_subtrees = 0;
867 return 0;
870 expr_array.release ();
872 gfc_expr_walker (e, cfe_register_funcs, NULL);
874 /* Walk through all the functions. */
876 FOR_EACH_VEC_ELT_FROM (expr_array, i, ei, 1)
878 /* Skip if the function has been replaced by a variable already. */
879 if ((*ei)->expr_type == EXPR_VARIABLE)
880 continue;
882 newvar = NULL;
883 for (j=0; j<i; j++)
885 ej = expr_array[j];
886 if (gfc_dep_compare_functions (*ei, *ej, true) == 0)
888 if (newvar == NULL)
889 newvar = create_var (*ei, "fcn");
891 if (warn_function_elimination)
892 do_warn_function_elimination (*ej);
894 free (*ej);
895 *ej = gfc_copy_expr (newvar);
898 if (newvar)
899 *ei = newvar;
902 /* We did all the necessary walking in this function. */
903 *walk_subtrees = 0;
904 return 0;
907 /* Callback function for common function elimination, called from
908 gfc_code_walker. This keeps track of the current code, in order
909 to insert statements as needed. */
911 static int
912 cfe_code (gfc_code **c, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
914 current_code = c;
915 inserted_block = NULL;
916 changed_statement = NULL;
918 /* Do not do anything inside a WHERE statement; scalar assignments, BLOCKs
919 and allocation on assigment are prohibited inside WHERE, and finally
920 masking an expression would lead to wrong-code when replacing
922 WHERE (a>0)
923 b = sum(foo(a) + foo(a))
924 END WHERE
926 with
928 WHERE (a > 0)
929 tmp = foo(a)
930 b = sum(tmp + tmp)
931 END WHERE
934 if ((*c)->op == EXEC_WHERE)
936 *walk_subtrees = 0;
937 return 0;
941 return 0;
944 /* Dummy function for expression call back, for use when we
945 really don't want to do any walking. */
947 static int
948 dummy_expr_callback (gfc_expr **e ATTRIBUTE_UNUSED, int *walk_subtrees,
949 void *data ATTRIBUTE_UNUSED)
951 *walk_subtrees = 0;
952 return 0;
955 /* Dummy function for code callback, for use when we really
956 don't want to do anything. */
958 gfc_dummy_code_callback (gfc_code **e ATTRIBUTE_UNUSED,
959 int *walk_subtrees ATTRIBUTE_UNUSED,
960 void *data ATTRIBUTE_UNUSED)
962 return 0;
965 /* Code callback function for converting
966 do while(a)
967 end do
968 into the equivalent
970 if (.not. a) exit
971 end do
972 This is because common function elimination would otherwise place the
973 temporary variables outside the loop. */
975 static int
976 convert_do_while (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
977 void *data ATTRIBUTE_UNUSED)
979 gfc_code *co = *c;
980 gfc_code *c_if1, *c_if2, *c_exit;
981 gfc_code *loopblock;
982 gfc_expr *e_not, *e_cond;
984 if (co->op != EXEC_DO_WHILE)
985 return 0;
987 if (co->expr1 == NULL || co->expr1->expr_type == EXPR_CONSTANT)
988 return 0;
990 e_cond = co->expr1;
992 /* Generate the condition of the if statement, which is .not. the original
993 statement. */
994 e_not = gfc_get_expr ();
995 e_not->ts = e_cond->ts;
996 e_not->where = e_cond->where;
997 e_not->expr_type = EXPR_OP;
998 e_not->value.op.op = INTRINSIC_NOT;
999 e_not->value.op.op1 = e_cond;
1001 /* Generate the EXIT statement. */
1002 c_exit = XCNEW (gfc_code);
1003 c_exit->op = EXEC_EXIT;
1004 c_exit->ext.which_construct = co;
1005 c_exit->loc = co->loc;
1007 /* Generate the IF statement. */
1008 c_if2 = XCNEW (gfc_code);
1009 c_if2->op = EXEC_IF;
1010 c_if2->expr1 = e_not;
1011 c_if2->next = c_exit;
1012 c_if2->loc = co->loc;
1014 /* ... plus the one to chain it to. */
1015 c_if1 = XCNEW (gfc_code);
1016 c_if1->op = EXEC_IF;
1017 c_if1->block = c_if2;
1018 c_if1->loc = co->loc;
1020 /* Make the DO WHILE loop into a DO block by replacing the condition
1021 with a true constant. */
1022 co->expr1 = gfc_get_logical_expr (gfc_default_integer_kind, &co->loc, true);
1024 /* Hang the generated if statement into the loop body. */
1026 loopblock = co->block->next;
1027 co->block->next = c_if1;
1028 c_if1->next = loopblock;
1030 return 0;
1033 /* Code callback function for converting
1034 if (a) then
1036 else if (b) then
1037 end if
1039 into
1040 if (a) then
1041 else
1042 if (b) then
1043 end if
1044 end if
1046 because otherwise common function elimination would place the BLOCKs
1047 into the wrong place. */
1049 static int
1050 convert_elseif (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
1051 void *data ATTRIBUTE_UNUSED)
1053 gfc_code *co = *c;
1054 gfc_code *c_if1, *c_if2, *else_stmt;
1056 if (co->op != EXEC_IF)
1057 return 0;
1059 /* This loop starts out with the first ELSE statement. */
1060 else_stmt = co->block->block;
1062 while (else_stmt != NULL)
1064 gfc_code *next_else;
1066 /* If there is no condition, we're done. */
1067 if (else_stmt->expr1 == NULL)
1068 break;
1070 next_else = else_stmt->block;
1072 /* Generate the new IF statement. */
1073 c_if2 = XCNEW (gfc_code);
1074 c_if2->op = EXEC_IF;
1075 c_if2->expr1 = else_stmt->expr1;
1076 c_if2->next = else_stmt->next;
1077 c_if2->loc = else_stmt->loc;
1078 c_if2->block = next_else;
1080 /* ... plus the one to chain it to. */
1081 c_if1 = XCNEW (gfc_code);
1082 c_if1->op = EXEC_IF;
1083 c_if1->block = c_if2;
1084 c_if1->loc = else_stmt->loc;
1086 /* Insert the new IF after the ELSE. */
1087 else_stmt->expr1 = NULL;
1088 else_stmt->next = c_if1;
1089 else_stmt->block = NULL;
1091 else_stmt = next_else;
1093 /* Don't walk subtrees. */
1094 return 0;
1097 struct do_stack
1099 struct do_stack *prev;
1100 gfc_iterator *iter;
1101 gfc_code *code;
1102 } *stack_top;
1104 /* Recursively traverse the block of a WRITE or READ statement, and maybe
1105 optimize by replacing do loops with their analog array slices. For
1106 example:
1108 write (*,*) (a(i), i=1,4)
1110 is replaced with
1112 write (*,*) a(1:4:1) . */
1114 static bool
1115 traverse_io_block (gfc_code *code, bool *has_reached, gfc_code *prev)
1117 gfc_code *curr;
1118 gfc_expr *new_e, *expr, *start;
1119 gfc_ref *ref;
1120 struct do_stack ds_push;
1121 int i, future_rank = 0;
1122 gfc_iterator *iters[GFC_MAX_DIMENSIONS];
1123 gfc_expr *e;
1125 /* Find the first transfer/do statement. */
1126 for (curr = code; curr; curr = curr->next)
1128 if (curr->op == EXEC_DO || curr->op == EXEC_TRANSFER)
1129 break;
1132 /* Ensure it is the only transfer/do statement because cases like
1134 write (*,*) (a(i), b(i), i=1,4)
1136 cannot be optimized. */
1138 if (!curr || curr->next)
1139 return false;
1141 if (curr->op == EXEC_DO)
1143 if (curr->ext.iterator->var->ref)
1144 return false;
1145 ds_push.prev = stack_top;
1146 ds_push.iter = curr->ext.iterator;
1147 ds_push.code = curr;
1148 stack_top = &ds_push;
1149 if (traverse_io_block (curr->block->next, has_reached, prev))
1151 if (curr != stack_top->code && !*has_reached)
1153 curr->block->next = NULL;
1154 gfc_free_statements (curr);
1156 else
1157 *has_reached = true;
1158 return true;
1160 return false;
1163 gcc_assert (curr->op == EXEC_TRANSFER);
1165 e = curr->expr1;
1166 ref = e->ref;
1167 if (!ref || ref->type != REF_ARRAY || ref->u.ar.codimen != 0 || ref->next)
1168 return false;
1170 /* Find the iterators belonging to each variable and check conditions. */
1171 for (i = 0; i < ref->u.ar.dimen; i++)
1173 if (!ref->u.ar.start[i] || ref->u.ar.start[i]->ref
1174 || ref->u.ar.dimen_type[i] != DIMEN_ELEMENT)
1175 return false;
1177 start = ref->u.ar.start[i];
1178 gfc_simplify_expr (start, 0);
1179 switch (start->expr_type)
1181 case EXPR_VARIABLE:
1183 /* write (*,*) (a(i), i=a%b,1) not handled yet. */
1184 if (start->ref)
1185 return false;
1187 /* Check for (a(k), i=1,4) or ((a(j, i), i=1,4), j=1,4). */
1188 if (!stack_top || !stack_top->iter
1189 || stack_top->iter->var->symtree != start->symtree)
1191 /* Check for (a(i,i), i=1,3). */
1192 int j;
1194 for (j=0; j<i; j++)
1195 if (iters[j] && iters[j]->var->symtree == start->symtree)
1196 return false;
1198 iters[i] = NULL;
1200 else
1202 iters[i] = stack_top->iter;
1203 stack_top = stack_top->prev;
1204 future_rank++;
1206 break;
1207 case EXPR_CONSTANT:
1208 iters[i] = NULL;
1209 break;
1210 case EXPR_OP:
1211 switch (start->value.op.op)
1213 case INTRINSIC_PLUS:
1214 case INTRINSIC_TIMES:
1215 if (start->value.op.op1->expr_type != EXPR_VARIABLE)
1216 std::swap (start->value.op.op1, start->value.op.op2);
1217 gcc_fallthrough ();
1218 case INTRINSIC_MINUS:
1219 if ((start->value.op.op1->expr_type!= EXPR_VARIABLE
1220 && start->value.op.op2->expr_type != EXPR_CONSTANT)
1221 || start->value.op.op1->ref)
1222 return false;
1223 if (!stack_top || !stack_top->iter
1224 || stack_top->iter->var->symtree
1225 != start->value.op.op1->symtree)
1226 return false;
1227 iters[i] = stack_top->iter;
1228 stack_top = stack_top->prev;
1229 break;
1230 default:
1231 return false;
1233 future_rank++;
1234 break;
1235 default:
1236 return false;
1240 /* Check for cases like ((a(i, j), i=1, j), j=1, 2). */
1241 for (int i = 1; i < ref->u.ar.dimen; i++)
1243 if (iters[i])
1245 gfc_expr *var = iters[i]->var;
1246 for (int j = i - 1; j < i; j++)
1248 if (iters[j]
1249 && (gfc_check_dependency (var, iters[j]->start, true)
1250 || gfc_check_dependency (var, iters[j]->end, true)
1251 || gfc_check_dependency (var, iters[j]->step, true)))
1252 return false;
1257 /* Create new expr. */
1258 new_e = gfc_copy_expr (curr->expr1);
1259 new_e->expr_type = EXPR_VARIABLE;
1260 new_e->rank = future_rank;
1261 if (curr->expr1->shape)
1262 new_e->shape = gfc_get_shape (new_e->rank);
1264 /* Assign new starts, ends and strides if necessary. */
1265 for (i = 0; i < ref->u.ar.dimen; i++)
1267 if (!iters[i])
1268 continue;
1269 start = ref->u.ar.start[i];
1270 switch (start->expr_type)
1272 case EXPR_CONSTANT:
1273 gfc_internal_error ("bad expression");
1274 break;
1275 case EXPR_VARIABLE:
1276 new_e->ref->u.ar.dimen_type[i] = DIMEN_RANGE;
1277 new_e->ref->u.ar.type = AR_SECTION;
1278 gfc_free_expr (new_e->ref->u.ar.start[i]);
1279 new_e->ref->u.ar.start[i] = gfc_copy_expr (iters[i]->start);
1280 new_e->ref->u.ar.end[i] = gfc_copy_expr (iters[i]->end);
1281 new_e->ref->u.ar.stride[i] = gfc_copy_expr (iters[i]->step);
1282 break;
1283 case EXPR_OP:
1284 new_e->ref->u.ar.dimen_type[i] = DIMEN_RANGE;
1285 new_e->ref->u.ar.type = AR_SECTION;
1286 gfc_free_expr (new_e->ref->u.ar.start[i]);
1287 expr = gfc_copy_expr (start);
1288 expr->value.op.op1 = gfc_copy_expr (iters[i]->start);
1289 new_e->ref->u.ar.start[i] = expr;
1290 gfc_simplify_expr (new_e->ref->u.ar.start[i], 0);
1291 expr = gfc_copy_expr (start);
1292 expr->value.op.op1 = gfc_copy_expr (iters[i]->end);
1293 new_e->ref->u.ar.end[i] = expr;
1294 gfc_simplify_expr (new_e->ref->u.ar.end[i], 0);
1295 switch (start->value.op.op)
1297 case INTRINSIC_MINUS:
1298 case INTRINSIC_PLUS:
1299 new_e->ref->u.ar.stride[i] = gfc_copy_expr (iters[i]->step);
1300 break;
1301 case INTRINSIC_TIMES:
1302 expr = gfc_copy_expr (start);
1303 expr->value.op.op1 = gfc_copy_expr (iters[i]->step);
1304 new_e->ref->u.ar.stride[i] = expr;
1305 gfc_simplify_expr (new_e->ref->u.ar.stride[i], 0);
1306 break;
1307 default:
1308 gfc_internal_error ("bad op");
1310 break;
1311 default:
1312 gfc_internal_error ("bad expression");
1315 curr->expr1 = new_e;
1317 /* Insert modified statement. Check whether the statement needs to be
1318 inserted at the lowest level. */
1319 if (!stack_top->iter)
1321 if (prev)
1323 curr->next = prev->next->next;
1324 prev->next = curr;
1326 else
1328 curr->next = stack_top->code->block->next->next->next;
1329 stack_top->code->block->next = curr;
1332 else
1333 stack_top->code->block->next = curr;
1334 return true;
1337 /* Function for the gfc_code_walker. If code is a READ or WRITE statement, it
1338 tries to optimize its block. */
1340 static int
1341 simplify_io_impl_do (gfc_code **code, int *walk_subtrees,
1342 void *data ATTRIBUTE_UNUSED)
1344 gfc_code **curr, *prev = NULL;
1345 struct do_stack write, first;
1346 bool b = false;
1347 *walk_subtrees = 1;
1348 if (!(*code)->block
1349 || ((*code)->block->op != EXEC_WRITE
1350 && (*code)->block->op != EXEC_READ))
1351 return 0;
1353 *walk_subtrees = 0;
1354 write.prev = NULL;
1355 write.iter = NULL;
1356 write.code = *code;
1358 for (curr = &(*code)->block; *curr; curr = &(*curr)->next)
1360 if ((*curr)->op == EXEC_DO)
1362 first.prev = &write;
1363 first.iter = (*curr)->ext.iterator;
1364 first.code = *curr;
1365 stack_top = &first;
1366 traverse_io_block ((*curr)->block->next, &b, prev);
1367 stack_top = NULL;
1369 prev = *curr;
1371 return 0;
1374 /* Optimize a namespace, including all contained namespaces.
1375 flag_frontend_optimize and flag_fronend_loop_interchange are
1376 handled separately. */
1378 static void
1379 optimize_namespace (gfc_namespace *ns)
1381 gfc_namespace *saved_ns = gfc_current_ns;
1382 current_ns = ns;
1383 gfc_current_ns = ns;
1384 forall_level = 0;
1385 iterator_level = 0;
1386 in_assoc_list = false;
1387 in_omp_workshare = false;
1389 if (flag_frontend_optimize)
1391 gfc_code_walker (&ns->code, simplify_io_impl_do, dummy_expr_callback, NULL);
1392 gfc_code_walker (&ns->code, convert_do_while, dummy_expr_callback, NULL);
1393 gfc_code_walker (&ns->code, convert_elseif, dummy_expr_callback, NULL);
1394 gfc_code_walker (&ns->code, cfe_code, cfe_expr_0, NULL);
1395 gfc_code_walker (&ns->code, optimize_code, optimize_expr, NULL);
1396 if (flag_inline_matmul_limit != 0)
1398 bool found;
1401 found = false;
1402 gfc_code_walker (&ns->code, matmul_to_var_code, matmul_to_var_expr,
1403 (void *) &found);
1405 while (found);
1407 gfc_code_walker (&ns->code, matmul_temp_args, dummy_expr_callback,
1408 NULL);
1409 gfc_code_walker (&ns->code, inline_matmul_assign, dummy_expr_callback,
1410 NULL);
1414 if (flag_frontend_loop_interchange)
1415 gfc_code_walker (&ns->code, index_interchange, dummy_expr_callback,
1416 NULL);
1418 /* BLOCKs are handled in the expression walker below. */
1419 for (ns = ns->contained; ns; ns = ns->sibling)
1421 if (ns->code == NULL || ns->code->op != EXEC_BLOCK)
1422 optimize_namespace (ns);
1424 gfc_current_ns = saved_ns;
1427 /* Handle dependencies for allocatable strings which potentially redefine
1428 themselves in an assignment. */
1430 static void
1431 realloc_strings (gfc_namespace *ns)
1433 current_ns = ns;
1434 gfc_code_walker (&ns->code, realloc_string_callback, dummy_expr_callback, NULL);
1436 for (ns = ns->contained; ns; ns = ns->sibling)
1438 if (ns->code == NULL || ns->code->op != EXEC_BLOCK)
1439 realloc_strings (ns);
1444 static void
1445 optimize_reduction (gfc_namespace *ns)
1447 current_ns = ns;
1448 gfc_code_walker (&ns->code, gfc_dummy_code_callback,
1449 callback_reduction, NULL);
1451 /* BLOCKs are handled in the expression walker below. */
1452 for (ns = ns->contained; ns; ns = ns->sibling)
1454 if (ns->code == NULL || ns->code->op != EXEC_BLOCK)
1455 optimize_reduction (ns);
1459 /* Replace code like
1460 a = matmul(b,c) + d
1461 with
1462 a = matmul(b,c) ; a = a + d
1463 where the array function is not elemental and not allocatable
1464 and does not depend on the left-hand side.
1467 static bool
1468 optimize_binop_array_assignment (gfc_code *c, gfc_expr **rhs, bool seen_op)
1470 gfc_expr *e;
1472 if (!*rhs)
1473 return false;
1475 e = *rhs;
1476 if (e->expr_type == EXPR_OP)
1478 switch (e->value.op.op)
1480 /* Unary operators and exponentiation: Only look at a single
1481 operand. */
1482 case INTRINSIC_NOT:
1483 case INTRINSIC_UPLUS:
1484 case INTRINSIC_UMINUS:
1485 case INTRINSIC_PARENTHESES:
1486 case INTRINSIC_POWER:
1487 if (optimize_binop_array_assignment (c, &e->value.op.op1, seen_op))
1488 return true;
1489 break;
1491 case INTRINSIC_CONCAT:
1492 /* Do not do string concatenations. */
1493 break;
1495 default:
1496 /* Binary operators. */
1497 if (optimize_binop_array_assignment (c, &e->value.op.op1, true))
1498 return true;
1500 if (optimize_binop_array_assignment (c, &e->value.op.op2, true))
1501 return true;
1503 break;
1506 else if (seen_op && e->expr_type == EXPR_FUNCTION && e->rank > 0
1507 && ! (e->value.function.esym
1508 && (e->value.function.esym->attr.elemental
1509 || e->value.function.esym->attr.allocatable
1510 || e->value.function.esym->ts.type != c->expr1->ts.type
1511 || e->value.function.esym->ts.kind != c->expr1->ts.kind))
1512 && ! (e->value.function.isym
1513 && (e->value.function.isym->elemental
1514 || e->ts.type != c->expr1->ts.type
1515 || e->ts.kind != c->expr1->ts.kind))
1516 && ! gfc_inline_intrinsic_function_p (e))
1519 gfc_code *n;
1520 gfc_expr *new_expr;
1522 /* Insert a new assignment statement after the current one. */
1523 n = XCNEW (gfc_code);
1524 n->op = EXEC_ASSIGN;
1525 n->loc = c->loc;
1526 n->next = c->next;
1527 c->next = n;
1529 n->expr1 = gfc_copy_expr (c->expr1);
1530 n->expr2 = c->expr2;
1531 new_expr = gfc_copy_expr (c->expr1);
1532 c->expr2 = e;
1533 *rhs = new_expr;
1535 return true;
1539 /* Nothing to optimize. */
1540 return false;
1543 /* Remove unneeded TRIMs at the end of expressions. */
1545 static bool
1546 remove_trim (gfc_expr *rhs)
1548 bool ret;
1550 ret = false;
1551 if (!rhs)
1552 return ret;
1554 /* Check for a // b // trim(c). Looping is probably not
1555 necessary because the parser usually generates
1556 (// (// a b ) trim(c) ) , but better safe than sorry. */
1558 while (rhs->expr_type == EXPR_OP
1559 && rhs->value.op.op == INTRINSIC_CONCAT)
1560 rhs = rhs->value.op.op2;
1562 while (rhs->expr_type == EXPR_FUNCTION && rhs->value.function.isym
1563 && rhs->value.function.isym->id == GFC_ISYM_TRIM)
1565 strip_function_call (rhs);
1566 /* Recursive call to catch silly stuff like trim ( a // trim(b)). */
1567 remove_trim (rhs);
1568 ret = true;
1571 return ret;
1574 /* Optimizations for an assignment. */
1576 static void
1577 optimize_assignment (gfc_code * c)
1579 gfc_expr *lhs, *rhs;
1581 lhs = c->expr1;
1582 rhs = c->expr2;
1584 if (lhs->ts.type == BT_CHARACTER && !lhs->ts.deferred)
1586 /* Optimize a = trim(b) to a = b. */
1587 remove_trim (rhs);
1589 /* Replace a = ' ' by a = '' to optimize away a memcpy. */
1590 if (is_empty_string (rhs))
1591 rhs->value.character.length = 0;
1594 if (lhs->rank > 0 && gfc_check_dependency (lhs, rhs, true) == 0)
1595 optimize_binop_array_assignment (c, &rhs, false);
1599 /* Remove an unneeded function call, modifying the expression.
1600 This replaces the function call with the value of its
1601 first argument. The rest of the argument list is freed. */
1603 static void
1604 strip_function_call (gfc_expr *e)
1606 gfc_expr *e1;
1607 gfc_actual_arglist *a;
1609 a = e->value.function.actual;
1611 /* We should have at least one argument. */
1612 gcc_assert (a->expr != NULL);
1614 e1 = a->expr;
1616 /* Free the remaining arglist, if any. */
1617 if (a->next)
1618 gfc_free_actual_arglist (a->next);
1620 /* Graft the argument expression onto the original function. */
1621 *e = *e1;
1622 free (e1);
1626 /* Optimization of lexical comparison functions. */
1628 static bool
1629 optimize_lexical_comparison (gfc_expr *e)
1631 if (e->expr_type != EXPR_FUNCTION || e->value.function.isym == NULL)
1632 return false;
1634 switch (e->value.function.isym->id)
1636 case GFC_ISYM_LLE:
1637 return optimize_comparison (e, INTRINSIC_LE);
1639 case GFC_ISYM_LGE:
1640 return optimize_comparison (e, INTRINSIC_GE);
1642 case GFC_ISYM_LGT:
1643 return optimize_comparison (e, INTRINSIC_GT);
1645 case GFC_ISYM_LLT:
1646 return optimize_comparison (e, INTRINSIC_LT);
1648 default:
1649 break;
1651 return false;
1654 /* Combine stuff like [a]>b into [a>b], for easier optimization later. Do not
1655 do CHARACTER because of possible pessimization involving character
1656 lengths. */
1658 static bool
1659 combine_array_constructor (gfc_expr *e)
1662 gfc_expr *op1, *op2;
1663 gfc_expr *scalar;
1664 gfc_expr *new_expr;
1665 gfc_constructor *c, *new_c;
1666 gfc_constructor_base oldbase, newbase;
1667 bool scalar_first;
1668 int n_elem;
1669 bool all_const;
1671 /* Array constructors have rank one. */
1672 if (e->rank != 1)
1673 return false;
1675 /* Don't try to combine association lists, this makes no sense
1676 and leads to an ICE. */
1677 if (in_assoc_list)
1678 return false;
1680 /* With FORALL, the BLOCKS created by create_var will cause an ICE. */
1681 if (forall_level > 0)
1682 return false;
1684 /* Inside an iterator, things can get hairy; we are likely to create
1685 an invalid temporary variable. */
1686 if (iterator_level > 0)
1687 return false;
1689 op1 = e->value.op.op1;
1690 op2 = e->value.op.op2;
1692 if (!op1 || !op2)
1693 return false;
1695 if (op1->expr_type == EXPR_ARRAY && op2->rank == 0)
1696 scalar_first = false;
1697 else if (op2->expr_type == EXPR_ARRAY && op1->rank == 0)
1699 scalar_first = true;
1700 op1 = e->value.op.op2;
1701 op2 = e->value.op.op1;
1703 else
1704 return false;
1706 if (op2->ts.type == BT_CHARACTER)
1707 return false;
1709 /* This might be an expanded constructor with very many constant values. If
1710 we perform the operation here, we might end up with a long compile time
1711 and actually longer execution time, so a length bound is in order here.
1712 If the constructor constains something which is not a constant, it did
1713 not come from an expansion, so leave it alone. */
1715 #define CONSTR_LEN_MAX 4
1717 oldbase = op1->value.constructor;
1719 n_elem = 0;
1720 all_const = true;
1721 for (c = gfc_constructor_first (oldbase); c; c = gfc_constructor_next(c))
1723 if (c->expr->expr_type != EXPR_CONSTANT)
1725 all_const = false;
1726 break;
1728 n_elem += 1;
1731 if (all_const && n_elem > CONSTR_LEN_MAX)
1732 return false;
1734 #undef CONSTR_LEN_MAX
1736 newbase = NULL;
1737 e->expr_type = EXPR_ARRAY;
1739 scalar = create_var (gfc_copy_expr (op2), "constr");
1741 for (c = gfc_constructor_first (oldbase); c;
1742 c = gfc_constructor_next (c))
1744 new_expr = gfc_get_expr ();
1745 new_expr->ts = e->ts;
1746 new_expr->expr_type = EXPR_OP;
1747 new_expr->rank = c->expr->rank;
1748 new_expr->where = c->expr->where;
1749 new_expr->value.op.op = e->value.op.op;
1751 if (scalar_first)
1753 new_expr->value.op.op1 = gfc_copy_expr (scalar);
1754 new_expr->value.op.op2 = gfc_copy_expr (c->expr);
1756 else
1758 new_expr->value.op.op1 = gfc_copy_expr (c->expr);
1759 new_expr->value.op.op2 = gfc_copy_expr (scalar);
1762 new_c = gfc_constructor_append_expr (&newbase, new_expr, &(e->where));
1763 new_c->iterator = c->iterator;
1764 c->iterator = NULL;
1767 gfc_free_expr (op1);
1768 gfc_free_expr (op2);
1769 gfc_free_expr (scalar);
1771 e->value.constructor = newbase;
1772 return true;
1775 /* Change (-1)**k into 1-ishift(iand(k,1),1) and
1776 2**k into ishift(1,k) */
1778 static bool
1779 optimize_power (gfc_expr *e)
1781 gfc_expr *op1, *op2;
1782 gfc_expr *iand, *ishft;
1784 if (e->ts.type != BT_INTEGER)
1785 return false;
1787 op1 = e->value.op.op1;
1789 if (op1 == NULL || op1->expr_type != EXPR_CONSTANT)
1790 return false;
1792 if (mpz_cmp_si (op1->value.integer, -1L) == 0)
1794 gfc_free_expr (op1);
1796 op2 = e->value.op.op2;
1798 if (op2 == NULL)
1799 return false;
1801 iand = gfc_build_intrinsic_call (current_ns, GFC_ISYM_IAND,
1802 "_internal_iand", e->where, 2, op2,
1803 gfc_get_int_expr (e->ts.kind,
1804 &e->where, 1));
1806 ishft = gfc_build_intrinsic_call (current_ns, GFC_ISYM_ISHFT,
1807 "_internal_ishft", e->where, 2, iand,
1808 gfc_get_int_expr (e->ts.kind,
1809 &e->where, 1));
1811 e->value.op.op = INTRINSIC_MINUS;
1812 e->value.op.op1 = gfc_get_int_expr (e->ts.kind, &e->where, 1);
1813 e->value.op.op2 = ishft;
1814 return true;
1816 else if (mpz_cmp_si (op1->value.integer, 2L) == 0)
1818 gfc_free_expr (op1);
1820 op2 = e->value.op.op2;
1821 if (op2 == NULL)
1822 return false;
1824 ishft = gfc_build_intrinsic_call (current_ns, GFC_ISYM_ISHFT,
1825 "_internal_ishft", e->where, 2,
1826 gfc_get_int_expr (e->ts.kind,
1827 &e->where, 1),
1828 op2);
1829 *e = *ishft;
1830 return true;
1833 else if (mpz_cmp_si (op1->value.integer, 1L) == 0)
1835 op2 = e->value.op.op2;
1836 if (op2 == NULL)
1837 return false;
1839 gfc_free_expr (op1);
1840 gfc_free_expr (op2);
1842 e->expr_type = EXPR_CONSTANT;
1843 e->value.op.op1 = NULL;
1844 e->value.op.op2 = NULL;
1845 mpz_init_set_si (e->value.integer, 1);
1846 /* Typespec and location are still OK. */
1847 return true;
1850 return false;
1853 /* Recursive optimization of operators. */
1855 static bool
1856 optimize_op (gfc_expr *e)
1858 bool changed;
1860 gfc_intrinsic_op op = e->value.op.op;
1862 changed = false;
1864 /* Only use new-style comparisons. */
1865 switch(op)
1867 case INTRINSIC_EQ_OS:
1868 op = INTRINSIC_EQ;
1869 break;
1871 case INTRINSIC_GE_OS:
1872 op = INTRINSIC_GE;
1873 break;
1875 case INTRINSIC_LE_OS:
1876 op = INTRINSIC_LE;
1877 break;
1879 case INTRINSIC_NE_OS:
1880 op = INTRINSIC_NE;
1881 break;
1883 case INTRINSIC_GT_OS:
1884 op = INTRINSIC_GT;
1885 break;
1887 case INTRINSIC_LT_OS:
1888 op = INTRINSIC_LT;
1889 break;
1891 default:
1892 break;
1895 switch (op)
1897 case INTRINSIC_EQ:
1898 case INTRINSIC_GE:
1899 case INTRINSIC_LE:
1900 case INTRINSIC_NE:
1901 case INTRINSIC_GT:
1902 case INTRINSIC_LT:
1903 changed = optimize_comparison (e, op);
1905 gcc_fallthrough ();
1906 /* Look at array constructors. */
1907 case INTRINSIC_PLUS:
1908 case INTRINSIC_MINUS:
1909 case INTRINSIC_TIMES:
1910 case INTRINSIC_DIVIDE:
1911 return combine_array_constructor (e) || changed;
1913 case INTRINSIC_POWER:
1914 return optimize_power (e);
1916 default:
1917 break;
1920 return false;
1924 /* Return true if a constant string contains only blanks. */
1926 static bool
1927 is_empty_string (gfc_expr *e)
1929 int i;
1931 if (e->ts.type != BT_CHARACTER || e->expr_type != EXPR_CONSTANT)
1932 return false;
1934 for (i=0; i < e->value.character.length; i++)
1936 if (e->value.character.string[i] != ' ')
1937 return false;
1940 return true;
1944 /* Insert a call to the intrinsic len_trim. Use a different name for
1945 the symbol tree so we don't run into trouble when the user has
1946 renamed len_trim for some reason. */
1948 static gfc_expr*
1949 get_len_trim_call (gfc_expr *str, int kind)
1951 gfc_expr *fcn;
1952 gfc_actual_arglist *actual_arglist, *next;
1954 fcn = gfc_get_expr ();
1955 fcn->expr_type = EXPR_FUNCTION;
1956 fcn->value.function.isym = gfc_intrinsic_function_by_id (GFC_ISYM_LEN_TRIM);
1957 actual_arglist = gfc_get_actual_arglist ();
1958 actual_arglist->expr = str;
1959 next = gfc_get_actual_arglist ();
1960 next->expr = gfc_get_int_expr (gfc_default_integer_kind, NULL, kind);
1961 actual_arglist->next = next;
1963 fcn->value.function.actual = actual_arglist;
1964 fcn->where = str->where;
1965 fcn->ts.type = BT_INTEGER;
1966 fcn->ts.kind = gfc_charlen_int_kind;
1968 gfc_get_sym_tree ("__internal_len_trim", current_ns, &fcn->symtree, false);
1969 fcn->symtree->n.sym->ts = fcn->ts;
1970 fcn->symtree->n.sym->attr.flavor = FL_PROCEDURE;
1971 fcn->symtree->n.sym->attr.function = 1;
1972 fcn->symtree->n.sym->attr.elemental = 1;
1973 fcn->symtree->n.sym->attr.referenced = 1;
1974 fcn->symtree->n.sym->attr.access = ACCESS_PRIVATE;
1975 gfc_commit_symbol (fcn->symtree->n.sym);
1977 return fcn;
1980 /* Optimize expressions for equality. */
1982 static bool
1983 optimize_comparison (gfc_expr *e, gfc_intrinsic_op op)
1985 gfc_expr *op1, *op2;
1986 bool change;
1987 int eq;
1988 bool result;
1989 gfc_actual_arglist *firstarg, *secondarg;
1991 if (e->expr_type == EXPR_OP)
1993 firstarg = NULL;
1994 secondarg = NULL;
1995 op1 = e->value.op.op1;
1996 op2 = e->value.op.op2;
1998 else if (e->expr_type == EXPR_FUNCTION)
2000 /* One of the lexical comparison functions. */
2001 firstarg = e->value.function.actual;
2002 secondarg = firstarg->next;
2003 op1 = firstarg->expr;
2004 op2 = secondarg->expr;
2006 else
2007 gcc_unreachable ();
2009 /* Strip off unneeded TRIM calls from string comparisons. */
2011 change = remove_trim (op1);
2013 if (remove_trim (op2))
2014 change = true;
2016 /* An expression of type EXPR_CONSTANT is only valid for scalars. */
2017 /* TODO: A scalar constant may be acceptable in some cases (the scalarizer
2018 handles them well). However, there are also cases that need a non-scalar
2019 argument. For example the any intrinsic. See PR 45380. */
2020 if (e->rank > 0)
2021 return change;
2023 /* Replace a == '' with len_trim(a) == 0 and a /= '' with
2024 len_trim(a) != 0 */
2025 if (op1->ts.type == BT_CHARACTER && op2->ts.type == BT_CHARACTER
2026 && (op == INTRINSIC_EQ || op == INTRINSIC_NE))
2028 bool empty_op1, empty_op2;
2029 empty_op1 = is_empty_string (op1);
2030 empty_op2 = is_empty_string (op2);
2032 if (empty_op1 || empty_op2)
2034 gfc_expr *fcn;
2035 gfc_expr *zero;
2036 gfc_expr *str;
2038 /* This can only happen when an error for comparing
2039 characters of different kinds has already been issued. */
2040 if (empty_op1 && empty_op2)
2041 return false;
2043 zero = gfc_get_int_expr (gfc_charlen_int_kind, &e->where, 0);
2044 str = empty_op1 ? op2 : op1;
2046 fcn = get_len_trim_call (str, gfc_charlen_int_kind);
2049 if (empty_op1)
2050 gfc_free_expr (op1);
2051 else
2052 gfc_free_expr (op2);
2054 op1 = fcn;
2055 op2 = zero;
2056 e->value.op.op1 = fcn;
2057 e->value.op.op2 = zero;
2062 /* Don't compare REAL or COMPLEX expressions when honoring NaNs. */
2064 if (flag_finite_math_only
2065 || (op1->ts.type != BT_REAL && op2->ts.type != BT_REAL
2066 && op1->ts.type != BT_COMPLEX && op2->ts.type != BT_COMPLEX))
2068 eq = gfc_dep_compare_expr (op1, op2);
2069 if (eq <= -2)
2071 /* Replace A // B < A // C with B < C, and A // B < C // B
2072 with A < C. */
2073 if (op1->ts.type == BT_CHARACTER && op2->ts.type == BT_CHARACTER
2074 && op1->expr_type == EXPR_OP
2075 && op1->value.op.op == INTRINSIC_CONCAT
2076 && op2->expr_type == EXPR_OP
2077 && op2->value.op.op == INTRINSIC_CONCAT)
2079 gfc_expr *op1_left = op1->value.op.op1;
2080 gfc_expr *op2_left = op2->value.op.op1;
2081 gfc_expr *op1_right = op1->value.op.op2;
2082 gfc_expr *op2_right = op2->value.op.op2;
2084 if (gfc_dep_compare_expr (op1_left, op2_left) == 0)
2086 /* Watch out for 'A ' // x vs. 'A' // x. */
2088 if (op1_left->expr_type == EXPR_CONSTANT
2089 && op2_left->expr_type == EXPR_CONSTANT
2090 && op1_left->value.character.length
2091 != op2_left->value.character.length)
2092 return change;
2093 else
2095 free (op1_left);
2096 free (op2_left);
2097 if (firstarg)
2099 firstarg->expr = op1_right;
2100 secondarg->expr = op2_right;
2102 else
2104 e->value.op.op1 = op1_right;
2105 e->value.op.op2 = op2_right;
2107 optimize_comparison (e, op);
2108 return true;
2111 if (gfc_dep_compare_expr (op1_right, op2_right) == 0)
2113 free (op1_right);
2114 free (op2_right);
2115 if (firstarg)
2117 firstarg->expr = op1_left;
2118 secondarg->expr = op2_left;
2120 else
2122 e->value.op.op1 = op1_left;
2123 e->value.op.op2 = op2_left;
2126 optimize_comparison (e, op);
2127 return true;
2131 else
2133 /* eq can only be -1, 0 or 1 at this point. */
2134 switch (op)
2136 case INTRINSIC_EQ:
2137 result = eq == 0;
2138 break;
2140 case INTRINSIC_GE:
2141 result = eq >= 0;
2142 break;
2144 case INTRINSIC_LE:
2145 result = eq <= 0;
2146 break;
2148 case INTRINSIC_NE:
2149 result = eq != 0;
2150 break;
2152 case INTRINSIC_GT:
2153 result = eq > 0;
2154 break;
2156 case INTRINSIC_LT:
2157 result = eq < 0;
2158 break;
2160 default:
2161 gfc_internal_error ("illegal OP in optimize_comparison");
2162 break;
2165 /* Replace the expression by a constant expression. The typespec
2166 and where remains the way it is. */
2167 free (op1);
2168 free (op2);
2169 e->expr_type = EXPR_CONSTANT;
2170 e->value.logical = result;
2171 return true;
2175 return change;
2178 /* Optimize a trim function by replacing it with an equivalent substring
2179 involving a call to len_trim. This only works for expressions where
2180 variables are trimmed. Return true if anything was modified. */
2182 static bool
2183 optimize_trim (gfc_expr *e)
2185 gfc_expr *a;
2186 gfc_ref *ref;
2187 gfc_expr *fcn;
2188 gfc_ref **rr = NULL;
2190 /* Don't do this optimization within an argument list, because
2191 otherwise aliasing issues may occur. */
2193 if (count_arglist != 1)
2194 return false;
2196 if (e->ts.type != BT_CHARACTER || e->expr_type != EXPR_FUNCTION
2197 || e->value.function.isym == NULL
2198 || e->value.function.isym->id != GFC_ISYM_TRIM)
2199 return false;
2201 a = e->value.function.actual->expr;
2203 if (a->expr_type != EXPR_VARIABLE)
2204 return false;
2206 /* This would pessimize the idiom a = trim(a) for reallocatable strings. */
2208 if (a->symtree->n.sym->attr.allocatable)
2209 return false;
2211 /* Follow all references to find the correct place to put the newly
2212 created reference. FIXME: Also handle substring references and
2213 array references. Array references cause strange regressions at
2214 the moment. */
2216 if (a->ref)
2218 for (rr = &(a->ref); *rr; rr = &((*rr)->next))
2220 if ((*rr)->type == REF_SUBSTRING || (*rr)->type == REF_ARRAY)
2221 return false;
2225 strip_function_call (e);
2227 if (e->ref == NULL)
2228 rr = &(e->ref);
2230 /* Create the reference. */
2232 ref = gfc_get_ref ();
2233 ref->type = REF_SUBSTRING;
2235 /* Set the start of the reference. */
2237 ref->u.ss.start = gfc_get_int_expr (gfc_charlen_int_kind, NULL, 1);
2239 /* Build the function call to len_trim(x, gfc_default_integer_kind). */
2241 fcn = get_len_trim_call (gfc_copy_expr (e), gfc_charlen_int_kind);
2243 /* Set the end of the reference to the call to len_trim. */
2245 ref->u.ss.end = fcn;
2246 gcc_assert (rr != NULL && *rr == NULL);
2247 *rr = ref;
2248 return true;
2251 /* Optimize minloc(b), where b is rank 1 array, into
2252 (/ minloc(b, dim=1) /), and similarly for maxloc,
2253 as the latter forms are expanded inline. */
2255 static void
2256 optimize_minmaxloc (gfc_expr **e)
2258 gfc_expr *fn = *e;
2259 gfc_actual_arglist *a;
2260 char *name, *p;
2262 if (fn->rank != 1
2263 || fn->value.function.actual == NULL
2264 || fn->value.function.actual->expr == NULL
2265 || fn->value.function.actual->expr->rank != 1)
2266 return;
2268 *e = gfc_get_array_expr (fn->ts.type, fn->ts.kind, &fn->where);
2269 (*e)->shape = fn->shape;
2270 fn->rank = 0;
2271 fn->shape = NULL;
2272 gfc_constructor_append_expr (&(*e)->value.constructor, fn, &fn->where);
2274 name = XALLOCAVEC (char, strlen (fn->value.function.name) + 1);
2275 strcpy (name, fn->value.function.name);
2276 p = strstr (name, "loc0");
2277 p[3] = '1';
2278 fn->value.function.name = gfc_get_string ("%s", name);
2279 if (fn->value.function.actual->next)
2281 a = fn->value.function.actual->next;
2282 gcc_assert (a->expr == NULL);
2284 else
2286 a = gfc_get_actual_arglist ();
2287 fn->value.function.actual->next = a;
2289 a->expr = gfc_get_constant_expr (BT_INTEGER, gfc_default_integer_kind,
2290 &fn->where);
2291 mpz_set_ui (a->expr->value.integer, 1);
2294 /* Callback function for code checking that we do not pass a DO variable to an
2295 INTENT(OUT) or INTENT(INOUT) dummy variable. */
2297 static int
2298 doloop_code (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
2299 void *data ATTRIBUTE_UNUSED)
2301 gfc_code *co;
2302 int i;
2303 gfc_formal_arglist *f;
2304 gfc_actual_arglist *a;
2305 gfc_code *cl;
2306 do_t loop, *lp;
2307 bool seen_goto;
2309 co = *c;
2311 /* If the doloop_list grew, we have to truncate it here. */
2313 if ((unsigned) doloop_level < doloop_list.length())
2314 doloop_list.truncate (doloop_level);
2316 seen_goto = false;
2317 switch (co->op)
2319 case EXEC_DO:
2321 if (co->ext.iterator && co->ext.iterator->var)
2322 loop.c = co;
2323 else
2324 loop.c = NULL;
2326 loop.branch_level = if_level + select_level;
2327 loop.seen_goto = false;
2328 doloop_list.safe_push (loop);
2329 break;
2331 /* If anything could transfer control away from a suspicious
2332 subscript, make sure to set seen_goto in the current DO loop
2333 (if any). */
2334 case EXEC_GOTO:
2335 case EXEC_EXIT:
2336 case EXEC_STOP:
2337 case EXEC_ERROR_STOP:
2338 case EXEC_CYCLE:
2339 seen_goto = true;
2340 break;
2342 case EXEC_OPEN:
2343 if (co->ext.open->err)
2344 seen_goto = true;
2345 break;
2347 case EXEC_CLOSE:
2348 if (co->ext.close->err)
2349 seen_goto = true;
2350 break;
2352 case EXEC_BACKSPACE:
2353 case EXEC_ENDFILE:
2354 case EXEC_REWIND:
2355 case EXEC_FLUSH:
2357 if (co->ext.filepos->err)
2358 seen_goto = true;
2359 break;
2361 case EXEC_INQUIRE:
2362 if (co->ext.filepos->err)
2363 seen_goto = true;
2364 break;
2366 case EXEC_READ:
2367 case EXEC_WRITE:
2368 if (co->ext.dt->err || co->ext.dt->end || co->ext.dt->eor)
2369 seen_goto = true;
2370 break;
2372 case EXEC_WAIT:
2373 if (co->ext.wait->err || co->ext.wait->end || co->ext.wait->eor)
2374 loop.seen_goto = true;
2375 break;
2377 case EXEC_CALL:
2379 if (co->resolved_sym == NULL)
2380 break;
2382 f = gfc_sym_get_dummy_args (co->resolved_sym);
2384 /* Withot a formal arglist, there is only unknown INTENT,
2385 which we don't check for. */
2386 if (f == NULL)
2387 break;
2389 a = co->ext.actual;
2391 while (a && f)
2393 FOR_EACH_VEC_ELT (doloop_list, i, lp)
2395 gfc_symbol *do_sym;
2396 cl = lp->c;
2398 if (cl == NULL)
2399 break;
2401 do_sym = cl->ext.iterator->var->symtree->n.sym;
2403 if (a->expr && a->expr->symtree
2404 && a->expr->symtree->n.sym == do_sym)
2406 if (f->sym->attr.intent == INTENT_OUT)
2407 gfc_error_now ("Variable %qs at %L set to undefined "
2408 "value inside loop beginning at %L as "
2409 "INTENT(OUT) argument to subroutine %qs",
2410 do_sym->name, &a->expr->where,
2411 &(doloop_list[i].c->loc),
2412 co->symtree->n.sym->name);
2413 else if (f->sym->attr.intent == INTENT_INOUT)
2414 gfc_error_now ("Variable %qs at %L not definable inside "
2415 "loop beginning at %L as INTENT(INOUT) "
2416 "argument to subroutine %qs",
2417 do_sym->name, &a->expr->where,
2418 &(doloop_list[i].c->loc),
2419 co->symtree->n.sym->name);
2422 a = a->next;
2423 f = f->next;
2425 break;
2427 default:
2428 break;
2430 if (seen_goto && doloop_level > 0)
2431 doloop_list[doloop_level-1].seen_goto = true;
2433 return 0;
2436 /* Callback function to warn about different things within DO loops. */
2438 static int
2439 do_function (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
2440 void *data ATTRIBUTE_UNUSED)
2442 do_t *last;
2444 if (doloop_list.length () == 0)
2445 return 0;
2447 if ((*e)->expr_type == EXPR_FUNCTION)
2448 do_intent (e);
2450 last = &doloop_list.last();
2451 if (last->seen_goto && !warn_do_subscript)
2452 return 0;
2454 if ((*e)->expr_type == EXPR_VARIABLE)
2455 do_subscript (e);
2457 return 0;
2460 typedef struct
2462 gfc_symbol *sym;
2463 mpz_t val;
2464 } insert_index_t;
2466 /* Callback function - if the expression is the variable in data->sym,
2467 replace it with a constant from data->val. */
2469 static int
2470 callback_insert_index (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
2471 void *data)
2473 insert_index_t *d;
2474 gfc_expr *ex, *n;
2476 ex = (*e);
2477 if (ex->expr_type != EXPR_VARIABLE)
2478 return 0;
2480 d = (insert_index_t *) data;
2481 if (ex->symtree->n.sym != d->sym)
2482 return 0;
2484 n = gfc_get_constant_expr (BT_INTEGER, ex->ts.kind, &ex->where);
2485 mpz_set (n->value.integer, d->val);
2487 gfc_free_expr (ex);
2488 *e = n;
2489 return 0;
2492 /* In the expression e, replace occurrences of the variable sym with
2493 val. If this results in a constant expression, return true and
2494 return the value in ret. Return false if the expression already
2495 is a constant. Caller has to clear ret in that case. */
2497 static bool
2498 insert_index (gfc_expr *e, gfc_symbol *sym, mpz_t val, mpz_t ret)
2500 gfc_expr *n;
2501 insert_index_t data;
2502 bool rc;
2504 if (e->expr_type == EXPR_CONSTANT)
2505 return false;
2507 n = gfc_copy_expr (e);
2508 data.sym = sym;
2509 mpz_init_set (data.val, val);
2510 gfc_expr_walker (&n, callback_insert_index, (void *) &data);
2511 gfc_simplify_expr (n, 0);
2513 if (n->expr_type == EXPR_CONSTANT)
2515 rc = true;
2516 mpz_init_set (ret, n->value.integer);
2518 else
2519 rc = false;
2521 mpz_clear (data.val);
2522 gfc_free_expr (n);
2523 return rc;
2527 /* Check array subscripts for possible out-of-bounds accesses in DO
2528 loops with constant bounds. */
2530 static int
2531 do_subscript (gfc_expr **e)
2533 gfc_expr *v;
2534 gfc_array_ref *ar;
2535 gfc_ref *ref;
2536 int i,j;
2537 gfc_code *dl;
2538 do_t *lp;
2540 v = *e;
2541 /* Constants are already checked. */
2542 if (v->expr_type == EXPR_CONSTANT)
2543 return 0;
2545 /* Wrong warnings will be generated in an associate list. */
2546 if (in_assoc_list)
2547 return 0;
2549 for (ref = v->ref; ref; ref = ref->next)
2551 if (ref->type == REF_ARRAY && ref->u.ar.type == AR_ELEMENT)
2553 ar = & ref->u.ar;
2554 FOR_EACH_VEC_ELT (doloop_list, j, lp)
2556 gfc_symbol *do_sym;
2557 mpz_t do_start, do_step, do_end;
2558 bool have_do_start, have_do_end;
2559 bool error_not_proven;
2560 int warn;
2562 dl = lp->c;
2563 if (dl == NULL)
2564 break;
2566 /* If we are within a branch, or a goto or equivalent
2567 was seen in the DO loop before, then we cannot prove that
2568 this expression is actually evaluated. Don't do anything
2569 unless we want to see it all. */
2570 error_not_proven = lp->seen_goto
2571 || lp->branch_level < if_level + select_level;
2573 if (error_not_proven && !warn_do_subscript)
2574 break;
2576 if (error_not_proven)
2577 warn = OPT_Wdo_subscript;
2578 else
2579 warn = 0;
2581 do_sym = dl->ext.iterator->var->symtree->n.sym;
2582 if (do_sym->ts.type != BT_INTEGER)
2583 continue;
2585 /* If we do not know about the stepsize, the loop may be zero trip.
2586 Do not warn in this case. */
2588 if (dl->ext.iterator->step->expr_type == EXPR_CONSTANT)
2589 mpz_init_set (do_step, dl->ext.iterator->step->value.integer);
2590 else
2591 continue;
2593 if (dl->ext.iterator->start->expr_type == EXPR_CONSTANT)
2595 have_do_start = true;
2596 mpz_init_set (do_start, dl->ext.iterator->start->value.integer);
2598 else
2599 have_do_start = false;
2602 if (dl->ext.iterator->end->expr_type == EXPR_CONSTANT)
2604 have_do_end = true;
2605 mpz_init_set (do_end, dl->ext.iterator->end->value.integer);
2607 else
2608 have_do_end = false;
2610 if (!have_do_start && !have_do_end)
2611 return 0;
2613 /* May have to correct the end value if the step does not equal
2614 one. */
2615 if (have_do_start && have_do_end && mpz_cmp_ui (do_step, 1) != 0)
2617 mpz_t diff, rem;
2619 mpz_init (diff);
2620 mpz_init (rem);
2621 mpz_sub (diff, do_end, do_start);
2622 mpz_tdiv_r (rem, diff, do_step);
2623 mpz_sub (do_end, do_end, rem);
2624 mpz_clear (diff);
2625 mpz_clear (rem);
2628 for (i = 0; i< ar->dimen; i++)
2630 mpz_t val;
2631 if (ar->dimen_type[i] == DIMEN_ELEMENT && have_do_start
2632 && insert_index (ar->start[i], do_sym, do_start, val))
2634 if (ar->as->lower[i]
2635 && ar->as->lower[i]->expr_type == EXPR_CONSTANT
2636 && mpz_cmp (val, ar->as->lower[i]->value.integer) < 0)
2637 gfc_warning (warn, "Array reference at %L out of bounds "
2638 "(%ld < %ld) in loop beginning at %L",
2639 &ar->start[i]->where, mpz_get_si (val),
2640 mpz_get_si (ar->as->lower[i]->value.integer),
2641 &doloop_list[j].c->loc);
2643 if (ar->as->upper[i]
2644 && ar->as->upper[i]->expr_type == EXPR_CONSTANT
2645 && mpz_cmp (val, ar->as->upper[i]->value.integer) > 0)
2646 gfc_warning (warn, "Array reference at %L out of bounds "
2647 "(%ld > %ld) in loop beginning at %L",
2648 &ar->start[i]->where, mpz_get_si (val),
2649 mpz_get_si (ar->as->upper[i]->value.integer),
2650 &doloop_list[j].c->loc);
2652 mpz_clear (val);
2655 if (ar->dimen_type[i] == DIMEN_ELEMENT && have_do_end
2656 && insert_index (ar->start[i], do_sym, do_end, val))
2658 if (ar->as->lower[i]
2659 && ar->as->lower[i]->expr_type == EXPR_CONSTANT
2660 && mpz_cmp (val, ar->as->lower[i]->value.integer) < 0)
2661 gfc_warning (warn, "Array reference at %L out of bounds "
2662 "(%ld < %ld) in loop beginning at %L",
2663 &ar->start[i]->where, mpz_get_si (val),
2664 mpz_get_si (ar->as->lower[i]->value.integer),
2665 &doloop_list[j].c->loc);
2667 if (ar->as->upper[i]
2668 && ar->as->upper[i]->expr_type == EXPR_CONSTANT
2669 && mpz_cmp (val, ar->as->upper[i]->value.integer) > 0)
2670 gfc_warning (warn, "Array reference at %L out of bounds "
2671 "(%ld > %ld) in loop beginning at %L",
2672 &ar->start[i]->where, mpz_get_si (val),
2673 mpz_get_si (ar->as->upper[i]->value.integer),
2674 &doloop_list[j].c->loc);
2676 mpz_clear (val);
2682 return 0;
2684 /* Function for functions checking that we do not pass a DO variable
2685 to an INTENT(OUT) or INTENT(INOUT) dummy variable. */
2687 static int
2688 do_intent (gfc_expr **e)
2690 gfc_formal_arglist *f;
2691 gfc_actual_arglist *a;
2692 gfc_expr *expr;
2693 gfc_code *dl;
2694 do_t *lp;
2695 int i;
2697 expr = *e;
2698 if (expr->expr_type != EXPR_FUNCTION)
2699 return 0;
2701 /* Intrinsic functions don't modify their arguments. */
2703 if (expr->value.function.isym)
2704 return 0;
2706 f = gfc_sym_get_dummy_args (expr->symtree->n.sym);
2708 /* Without a formal arglist, there is only unknown INTENT,
2709 which we don't check for. */
2710 if (f == NULL)
2711 return 0;
2713 a = expr->value.function.actual;
2715 while (a && f)
2717 FOR_EACH_VEC_ELT (doloop_list, i, lp)
2719 gfc_symbol *do_sym;
2720 dl = lp->c;
2721 if (dl == NULL)
2722 break;
2724 do_sym = dl->ext.iterator->var->symtree->n.sym;
2726 if (a->expr && a->expr->symtree
2727 && a->expr->symtree->n.sym == do_sym)
2729 if (f->sym->attr.intent == INTENT_OUT)
2730 gfc_error_now ("Variable %qs at %L set to undefined value "
2731 "inside loop beginning at %L as INTENT(OUT) "
2732 "argument to function %qs", do_sym->name,
2733 &a->expr->where, &doloop_list[i].c->loc,
2734 expr->symtree->n.sym->name);
2735 else if (f->sym->attr.intent == INTENT_INOUT)
2736 gfc_error_now ("Variable %qs at %L not definable inside loop"
2737 " beginning at %L as INTENT(INOUT) argument to"
2738 " function %qs", do_sym->name,
2739 &a->expr->where, &doloop_list[i].c->loc,
2740 expr->symtree->n.sym->name);
2743 a = a->next;
2744 f = f->next;
2747 return 0;
2750 static void
2751 doloop_warn (gfc_namespace *ns)
2753 gfc_code_walker (&ns->code, doloop_code, do_function, NULL);
2756 /* This selction deals with inlining calls to MATMUL. */
2758 /* Replace calls to matmul outside of straight assignments with a temporary
2759 variable so that later inlining will work. */
2761 static int
2762 matmul_to_var_expr (gfc_expr **ep, int *walk_subtrees ATTRIBUTE_UNUSED,
2763 void *data)
2765 gfc_expr *e, *n;
2766 bool *found = (bool *) data;
2768 e = *ep;
2770 if (e->expr_type != EXPR_FUNCTION
2771 || e->value.function.isym == NULL
2772 || e->value.function.isym->id != GFC_ISYM_MATMUL)
2773 return 0;
2775 if (forall_level > 0 || iterator_level > 0 || in_omp_workshare
2776 || in_where || in_assoc_list)
2777 return 0;
2779 /* Check if this is already in the form c = matmul(a,b). */
2781 if ((*current_code)->expr2 == e)
2782 return 0;
2784 n = create_var (e, "matmul");
2786 /* If create_var is unable to create a variable (for example if
2787 -fno-realloc-lhs is in force with a variable that does not have bounds
2788 known at compile-time), just return. */
2790 if (n == NULL)
2791 return 0;
2793 *ep = n;
2794 *found = true;
2795 return 0;
2798 /* Set current_code and associated variables so that matmul_to_var_expr can
2799 work. */
2801 static int
2802 matmul_to_var_code (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
2803 void *data ATTRIBUTE_UNUSED)
2805 if (current_code != c)
2807 current_code = c;
2808 inserted_block = NULL;
2809 changed_statement = NULL;
2812 return 0;
2816 /* Take a statement of the shape c = matmul(a,b) and create temporaries
2817 for a and b if there is a dependency between the arguments and the
2818 result variable or if a or b are the result of calculations that cannot
2819 be handled by the inliner. */
2821 static int
2822 matmul_temp_args (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
2823 void *data ATTRIBUTE_UNUSED)
2825 gfc_expr *expr1, *expr2;
2826 gfc_code *co;
2827 gfc_actual_arglist *a, *b;
2828 bool a_tmp, b_tmp;
2829 gfc_expr *matrix_a, *matrix_b;
2830 bool conjg_a, conjg_b, transpose_a, transpose_b;
2832 co = *c;
2834 if (co->op != EXEC_ASSIGN)
2835 return 0;
2837 if (forall_level > 0 || iterator_level > 0 || in_omp_workshare
2838 || in_where)
2839 return 0;
2841 /* This has some duplication with inline_matmul_assign. This
2842 is because the creation of temporary variables could still fail,
2843 and inline_matmul_assign still needs to be able to handle these
2844 cases. */
2845 expr1 = co->expr1;
2846 expr2 = co->expr2;
2848 if (expr2->expr_type != EXPR_FUNCTION
2849 || expr2->value.function.isym == NULL
2850 || expr2->value.function.isym->id != GFC_ISYM_MATMUL)
2851 return 0;
2853 a_tmp = false;
2854 a = expr2->value.function.actual;
2855 matrix_a = check_conjg_transpose_variable (a->expr, &conjg_a, &transpose_a);
2856 if (matrix_a != NULL)
2858 if (matrix_a->expr_type == EXPR_VARIABLE
2859 && (gfc_check_dependency (matrix_a, expr1, true)
2860 || has_dimen_vector_ref (matrix_a)))
2861 a_tmp = true;
2863 else
2864 a_tmp = true;
2866 b_tmp = false;
2867 b = a->next;
2868 matrix_b = check_conjg_transpose_variable (b->expr, &conjg_b, &transpose_b);
2869 if (matrix_b != NULL)
2871 if (matrix_b->expr_type == EXPR_VARIABLE
2872 && (gfc_check_dependency (matrix_b, expr1, true)
2873 || has_dimen_vector_ref (matrix_b)))
2874 b_tmp = true;
2876 else
2877 b_tmp = true;
2879 if (!a_tmp && !b_tmp)
2880 return 0;
2882 current_code = c;
2883 inserted_block = NULL;
2884 changed_statement = NULL;
2885 if (a_tmp)
2887 gfc_expr *at;
2888 at = create_var (a->expr,"mma");
2889 if (at)
2890 a->expr = at;
2892 if (b_tmp)
2894 gfc_expr *bt;
2895 bt = create_var (b->expr,"mmb");
2896 if (bt)
2897 b->expr = bt;
2899 return 0;
2902 /* Auxiliary function to build and simplify an array inquiry function.
2903 dim is zero-based. */
2905 static gfc_expr *
2906 get_array_inq_function (gfc_isym_id id, gfc_expr *e, int dim)
2908 gfc_expr *fcn;
2909 gfc_expr *dim_arg, *kind;
2910 const char *name;
2911 gfc_expr *ec;
2913 switch (id)
2915 case GFC_ISYM_LBOUND:
2916 name = "_gfortran_lbound";
2917 break;
2919 case GFC_ISYM_UBOUND:
2920 name = "_gfortran_ubound";
2921 break;
2923 case GFC_ISYM_SIZE:
2924 name = "_gfortran_size";
2925 break;
2927 default:
2928 gcc_unreachable ();
2931 dim_arg = gfc_get_int_expr (gfc_default_integer_kind, &e->where, dim);
2932 kind = gfc_get_int_expr (gfc_default_integer_kind, &e->where,
2933 gfc_index_integer_kind);
2935 ec = gfc_copy_expr (e);
2936 fcn = gfc_build_intrinsic_call (current_ns, id, name, e->where, 3,
2937 ec, dim_arg, kind);
2938 gfc_simplify_expr (fcn, 0);
2939 return fcn;
2942 /* Builds a logical expression. */
2944 static gfc_expr*
2945 build_logical_expr (gfc_intrinsic_op op, gfc_expr *e1, gfc_expr *e2)
2947 gfc_typespec ts;
2948 gfc_expr *res;
2950 ts.type = BT_LOGICAL;
2951 ts.kind = gfc_default_logical_kind;
2952 res = gfc_get_expr ();
2953 res->where = e1->where;
2954 res->expr_type = EXPR_OP;
2955 res->value.op.op = op;
2956 res->value.op.op1 = e1;
2957 res->value.op.op2 = e2;
2958 res->ts = ts;
2960 return res;
2964 /* Return an operation of one two gfc_expr (one if e2 is NULL). This assumes
2965 compatible typespecs. */
2967 static gfc_expr *
2968 get_operand (gfc_intrinsic_op op, gfc_expr *e1, gfc_expr *e2)
2970 gfc_expr *res;
2972 res = gfc_get_expr ();
2973 res->ts = e1->ts;
2974 res->where = e1->where;
2975 res->expr_type = EXPR_OP;
2976 res->value.op.op = op;
2977 res->value.op.op1 = e1;
2978 res->value.op.op2 = e2;
2979 gfc_simplify_expr (res, 0);
2980 return res;
2983 /* Generate the IF statement for a runtime check if we want to do inlining or
2984 not - putting in the code for both branches and putting it into the syntax
2985 tree is the caller's responsibility. For fixed array sizes, this should be
2986 removed by DCE. Only called for rank-two matrices A and B. */
2988 static gfc_code *
2989 inline_limit_check (gfc_expr *a, gfc_expr *b, enum matrix_case m_case)
2991 gfc_expr *inline_limit;
2992 gfc_code *if_1, *if_2, *else_2;
2993 gfc_expr *b2, *a2, *a1, *m1, *m2;
2994 gfc_typespec ts;
2995 gfc_expr *cond;
2997 gcc_assert (m_case == A2B2 || m_case == A2B2T || m_case == A2TB2);
2999 /* Calculation is done in real to avoid integer overflow. */
3001 inline_limit = gfc_get_constant_expr (BT_REAL, gfc_default_real_kind,
3002 &a->where);
3003 mpfr_set_si (inline_limit->value.real, flag_inline_matmul_limit,
3004 GFC_RND_MODE);
3005 mpfr_pow_ui (inline_limit->value.real, inline_limit->value.real, 3,
3006 GFC_RND_MODE);
3008 a1 = get_array_inq_function (GFC_ISYM_SIZE, a, 1);
3009 a2 = get_array_inq_function (GFC_ISYM_SIZE, a, 2);
3010 b2 = get_array_inq_function (GFC_ISYM_SIZE, b, 2);
3012 gfc_clear_ts (&ts);
3013 ts.type = BT_REAL;
3014 ts.kind = gfc_default_real_kind;
3015 gfc_convert_type_warn (a1, &ts, 2, 0);
3016 gfc_convert_type_warn (a2, &ts, 2, 0);
3017 gfc_convert_type_warn (b2, &ts, 2, 0);
3019 m1 = get_operand (INTRINSIC_TIMES, a1, a2);
3020 m2 = get_operand (INTRINSIC_TIMES, m1, b2);
3022 cond = build_logical_expr (INTRINSIC_LE, m2, inline_limit);
3023 gfc_simplify_expr (cond, 0);
3025 else_2 = XCNEW (gfc_code);
3026 else_2->op = EXEC_IF;
3027 else_2->loc = a->where;
3029 if_2 = XCNEW (gfc_code);
3030 if_2->op = EXEC_IF;
3031 if_2->expr1 = cond;
3032 if_2->loc = a->where;
3033 if_2->block = else_2;
3035 if_1 = XCNEW (gfc_code);
3036 if_1->op = EXEC_IF;
3037 if_1->block = if_2;
3038 if_1->loc = a->where;
3040 return if_1;
3044 /* Insert code to issue a runtime error if the expressions are not equal. */
3046 static gfc_code *
3047 runtime_error_ne (gfc_expr *e1, gfc_expr *e2, const char *msg)
3049 gfc_expr *cond;
3050 gfc_code *if_1, *if_2;
3051 gfc_code *c;
3052 gfc_actual_arglist *a1, *a2, *a3;
3054 gcc_assert (e1->where.lb);
3055 /* Build the call to runtime_error. */
3056 c = XCNEW (gfc_code);
3057 c->op = EXEC_CALL;
3058 c->loc = e1->where;
3060 /* Get a null-terminated message string. */
3062 a1 = gfc_get_actual_arglist ();
3063 a1->expr = gfc_get_character_expr (gfc_default_character_kind, &e1->where,
3064 msg, strlen(msg)+1);
3065 c->ext.actual = a1;
3067 /* Pass the value of the first expression. */
3068 a2 = gfc_get_actual_arglist ();
3069 a2->expr = gfc_copy_expr (e1);
3070 a1->next = a2;
3072 /* Pass the value of the second expression. */
3073 a3 = gfc_get_actual_arglist ();
3074 a3->expr = gfc_copy_expr (e2);
3075 a2->next = a3;
3077 gfc_check_fe_runtime_error (c->ext.actual);
3078 gfc_resolve_fe_runtime_error (c);
3080 if_2 = XCNEW (gfc_code);
3081 if_2->op = EXEC_IF;
3082 if_2->loc = e1->where;
3083 if_2->next = c;
3085 if_1 = XCNEW (gfc_code);
3086 if_1->op = EXEC_IF;
3087 if_1->block = if_2;
3088 if_1->loc = e1->where;
3090 cond = build_logical_expr (INTRINSIC_NE, e1, e2);
3091 gfc_simplify_expr (cond, 0);
3092 if_2->expr1 = cond;
3094 return if_1;
3097 /* Handle matrix reallocation. Caller is responsible to insert into
3098 the code tree.
3100 For the two-dimensional case, build
3102 if (allocated(c)) then
3103 if (size(c,1) /= size(a,1) .or. size(c,2) /= size(b,2)) then
3104 deallocate(c)
3105 allocate (c(size(a,1), size(b,2)))
3106 end if
3107 else
3108 allocate (c(size(a,1),size(b,2)))
3109 end if
3111 and for the other cases correspondingly.
3114 static gfc_code *
3115 matmul_lhs_realloc (gfc_expr *c, gfc_expr *a, gfc_expr *b,
3116 enum matrix_case m_case)
3119 gfc_expr *allocated, *alloc_expr;
3120 gfc_code *if_alloc_1, *if_alloc_2, *if_size_1, *if_size_2;
3121 gfc_code *else_alloc;
3122 gfc_code *deallocate, *allocate1, *allocate_else;
3123 gfc_array_ref *ar;
3124 gfc_expr *cond, *ne1, *ne2;
3126 if (warn_realloc_lhs)
3127 gfc_warning (OPT_Wrealloc_lhs,
3128 "Code for reallocating the allocatable array at %L will "
3129 "be added", &c->where);
3131 alloc_expr = gfc_copy_expr (c);
3133 ar = gfc_find_array_ref (alloc_expr);
3134 gcc_assert (ar && ar->type == AR_FULL);
3136 /* c comes in as a full ref. Change it into a copy and make it into an
3137 element ref so it has the right form for for ALLOCATE. In the same
3138 switch statement, also generate the size comparison for the secod IF
3139 statement. */
3141 ar->type = AR_ELEMENT;
3143 switch (m_case)
3145 case A2B2:
3146 ar->start[0] = get_array_inq_function (GFC_ISYM_SIZE, a, 1);
3147 ar->start[1] = get_array_inq_function (GFC_ISYM_SIZE, b, 2);
3148 ne1 = build_logical_expr (INTRINSIC_NE,
3149 get_array_inq_function (GFC_ISYM_SIZE, c, 1),
3150 get_array_inq_function (GFC_ISYM_SIZE, a, 1));
3151 ne2 = build_logical_expr (INTRINSIC_NE,
3152 get_array_inq_function (GFC_ISYM_SIZE, c, 2),
3153 get_array_inq_function (GFC_ISYM_SIZE, b, 2));
3154 cond = build_logical_expr (INTRINSIC_OR, ne1, ne2);
3155 break;
3157 case A2B2T:
3158 ar->start[0] = get_array_inq_function (GFC_ISYM_SIZE, a, 1);
3159 ar->start[1] = get_array_inq_function (GFC_ISYM_SIZE, b, 1);
3161 ne1 = build_logical_expr (INTRINSIC_NE,
3162 get_array_inq_function (GFC_ISYM_SIZE, c, 1),
3163 get_array_inq_function (GFC_ISYM_SIZE, a, 1));
3164 ne2 = build_logical_expr (INTRINSIC_NE,
3165 get_array_inq_function (GFC_ISYM_SIZE, c, 2),
3166 get_array_inq_function (GFC_ISYM_SIZE, b, 1));
3167 cond = build_logical_expr (INTRINSIC_OR, ne1, ne2);
3168 break;
3170 case A2TB2:
3172 ar->start[0] = get_array_inq_function (GFC_ISYM_SIZE, a, 2);
3173 ar->start[1] = get_array_inq_function (GFC_ISYM_SIZE, b, 2);
3175 ne1 = build_logical_expr (INTRINSIC_NE,
3176 get_array_inq_function (GFC_ISYM_SIZE, c, 1),
3177 get_array_inq_function (GFC_ISYM_SIZE, a, 2));
3178 ne2 = build_logical_expr (INTRINSIC_NE,
3179 get_array_inq_function (GFC_ISYM_SIZE, c, 2),
3180 get_array_inq_function (GFC_ISYM_SIZE, b, 2));
3181 cond = build_logical_expr (INTRINSIC_OR, ne1, ne2);
3182 break;
3184 case A2B1:
3185 ar->start[0] = get_array_inq_function (GFC_ISYM_SIZE, a, 1);
3186 cond = build_logical_expr (INTRINSIC_NE,
3187 get_array_inq_function (GFC_ISYM_SIZE, c, 1),
3188 get_array_inq_function (GFC_ISYM_SIZE, a, 2));
3189 break;
3191 case A1B2:
3192 ar->start[0] = get_array_inq_function (GFC_ISYM_SIZE, b, 2);
3193 cond = build_logical_expr (INTRINSIC_NE,
3194 get_array_inq_function (GFC_ISYM_SIZE, c, 1),
3195 get_array_inq_function (GFC_ISYM_SIZE, b, 2));
3196 break;
3198 default:
3199 gcc_unreachable();
3203 gfc_simplify_expr (cond, 0);
3205 /* We need two identical allocate statements in two
3206 branches of the IF statement. */
3208 allocate1 = XCNEW (gfc_code);
3209 allocate1->op = EXEC_ALLOCATE;
3210 allocate1->ext.alloc.list = gfc_get_alloc ();
3211 allocate1->loc = c->where;
3212 allocate1->ext.alloc.list->expr = gfc_copy_expr (alloc_expr);
3214 allocate_else = XCNEW (gfc_code);
3215 allocate_else->op = EXEC_ALLOCATE;
3216 allocate_else->ext.alloc.list = gfc_get_alloc ();
3217 allocate_else->loc = c->where;
3218 allocate_else->ext.alloc.list->expr = alloc_expr;
3220 allocated = gfc_build_intrinsic_call (current_ns, GFC_ISYM_ALLOCATED,
3221 "_gfortran_allocated", c->where,
3222 1, gfc_copy_expr (c));
3224 deallocate = XCNEW (gfc_code);
3225 deallocate->op = EXEC_DEALLOCATE;
3226 deallocate->ext.alloc.list = gfc_get_alloc ();
3227 deallocate->ext.alloc.list->expr = gfc_copy_expr (c);
3228 deallocate->next = allocate1;
3229 deallocate->loc = c->where;
3231 if_size_2 = XCNEW (gfc_code);
3232 if_size_2->op = EXEC_IF;
3233 if_size_2->expr1 = cond;
3234 if_size_2->loc = c->where;
3235 if_size_2->next = deallocate;
3237 if_size_1 = XCNEW (gfc_code);
3238 if_size_1->op = EXEC_IF;
3239 if_size_1->block = if_size_2;
3240 if_size_1->loc = c->where;
3242 else_alloc = XCNEW (gfc_code);
3243 else_alloc->op = EXEC_IF;
3244 else_alloc->loc = c->where;
3245 else_alloc->next = allocate_else;
3247 if_alloc_2 = XCNEW (gfc_code);
3248 if_alloc_2->op = EXEC_IF;
3249 if_alloc_2->expr1 = allocated;
3250 if_alloc_2->loc = c->where;
3251 if_alloc_2->next = if_size_1;
3252 if_alloc_2->block = else_alloc;
3254 if_alloc_1 = XCNEW (gfc_code);
3255 if_alloc_1->op = EXEC_IF;
3256 if_alloc_1->block = if_alloc_2;
3257 if_alloc_1->loc = c->where;
3259 return if_alloc_1;
3262 /* Callback function for has_function_or_op. */
3264 static int
3265 is_function_or_op (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
3266 void *data ATTRIBUTE_UNUSED)
3268 if ((*e) == 0)
3269 return 0;
3270 else
3271 return (*e)->expr_type == EXPR_FUNCTION
3272 || (*e)->expr_type == EXPR_OP;
3275 /* Returns true if the expression contains a function. */
3277 static bool
3278 has_function_or_op (gfc_expr **e)
3280 if (e == NULL)
3281 return false;
3282 else
3283 return gfc_expr_walker (e, is_function_or_op, NULL);
3286 /* Freeze (assign to a temporary variable) a single expression. */
3288 static void
3289 freeze_expr (gfc_expr **ep)
3291 gfc_expr *ne;
3292 if (has_function_or_op (ep))
3294 ne = create_var (*ep, "freeze");
3295 *ep = ne;
3299 /* Go through an expression's references and assign them to temporary
3300 variables if they contain functions. This is usually done prior to
3301 front-end scalarization to avoid multiple invocations of functions. */
3303 static void
3304 freeze_references (gfc_expr *e)
3306 gfc_ref *r;
3307 gfc_array_ref *ar;
3308 int i;
3310 for (r=e->ref; r; r=r->next)
3312 if (r->type == REF_SUBSTRING)
3314 if (r->u.ss.start != NULL)
3315 freeze_expr (&r->u.ss.start);
3317 if (r->u.ss.end != NULL)
3318 freeze_expr (&r->u.ss.end);
3320 else if (r->type == REF_ARRAY)
3322 ar = &r->u.ar;
3323 switch (ar->type)
3325 case AR_FULL:
3326 break;
3328 case AR_SECTION:
3329 for (i=0; i<ar->dimen; i++)
3331 if (ar->dimen_type[i] == DIMEN_RANGE)
3333 freeze_expr (&ar->start[i]);
3334 freeze_expr (&ar->end[i]);
3335 freeze_expr (&ar->stride[i]);
3337 else if (ar->dimen_type[i] == DIMEN_ELEMENT)
3339 freeze_expr (&ar->start[i]);
3342 break;
3344 case AR_ELEMENT:
3345 for (i=0; i<ar->dimen; i++)
3346 freeze_expr (&ar->start[i]);
3347 break;
3349 default:
3350 break;
3356 /* Convert to gfc_index_integer_kind if needed, just do a copy otherwise. */
3358 static gfc_expr *
3359 convert_to_index_kind (gfc_expr *e)
3361 gfc_expr *res;
3363 gcc_assert (e != NULL);
3365 res = gfc_copy_expr (e);
3367 gcc_assert (e->ts.type == BT_INTEGER);
3369 if (res->ts.kind != gfc_index_integer_kind)
3371 gfc_typespec ts;
3372 gfc_clear_ts (&ts);
3373 ts.type = BT_INTEGER;
3374 ts.kind = gfc_index_integer_kind;
3376 gfc_convert_type_warn (e, &ts, 2, 0);
3379 return res;
3382 /* Function to create a DO loop including creation of the
3383 iteration variable. gfc_expr are copied.*/
3385 static gfc_code *
3386 create_do_loop (gfc_expr *start, gfc_expr *end, gfc_expr *step, locus *where,
3387 gfc_namespace *ns, char *vname)
3390 char name[GFC_MAX_SYMBOL_LEN +1];
3391 gfc_symtree *symtree;
3392 gfc_symbol *symbol;
3393 gfc_expr *i;
3394 gfc_code *n, *n2;
3396 /* Create an expression for the iteration variable. */
3397 if (vname)
3398 sprintf (name, "__var_%d_do_%s", var_num++, vname);
3399 else
3400 sprintf (name, "__var_%d_do", var_num++);
3403 if (gfc_get_sym_tree (name, ns, &symtree, false) != 0)
3404 gcc_unreachable ();
3406 /* Create the loop variable. */
3408 symbol = symtree->n.sym;
3409 symbol->ts.type = BT_INTEGER;
3410 symbol->ts.kind = gfc_index_integer_kind;
3411 symbol->attr.flavor = FL_VARIABLE;
3412 symbol->attr.referenced = 1;
3413 symbol->attr.dimension = 0;
3414 symbol->attr.fe_temp = 1;
3415 gfc_commit_symbol (symbol);
3417 i = gfc_get_expr ();
3418 i->expr_type = EXPR_VARIABLE;
3419 i->ts = symbol->ts;
3420 i->rank = 0;
3421 i->where = *where;
3422 i->symtree = symtree;
3424 /* ... and the nested DO statements. */
3425 n = XCNEW (gfc_code);
3426 n->op = EXEC_DO;
3427 n->loc = *where;
3428 n->ext.iterator = gfc_get_iterator ();
3429 n->ext.iterator->var = i;
3430 n->ext.iterator->start = convert_to_index_kind (start);
3431 n->ext.iterator->end = convert_to_index_kind (end);
3432 if (step)
3433 n->ext.iterator->step = convert_to_index_kind (step);
3434 else
3435 n->ext.iterator->step = gfc_get_int_expr (gfc_index_integer_kind,
3436 where, 1);
3438 n2 = XCNEW (gfc_code);
3439 n2->op = EXEC_DO;
3440 n2->loc = *where;
3441 n2->next = NULL;
3442 n->block = n2;
3443 return n;
3446 /* Get the upper bound of the DO loops for matmul along a dimension. This
3447 is one-based. */
3449 static gfc_expr*
3450 get_size_m1 (gfc_expr *e, int dimen)
3452 mpz_t size;
3453 gfc_expr *res;
3455 if (gfc_array_dimen_size (e, dimen - 1, &size))
3457 res = gfc_get_constant_expr (BT_INTEGER,
3458 gfc_index_integer_kind, &e->where);
3459 mpz_sub_ui (res->value.integer, size, 1);
3460 mpz_clear (size);
3462 else
3464 res = get_operand (INTRINSIC_MINUS,
3465 get_array_inq_function (GFC_ISYM_SIZE, e, dimen),
3466 gfc_get_int_expr (gfc_index_integer_kind,
3467 &e->where, 1));
3468 gfc_simplify_expr (res, 0);
3471 return res;
3474 /* Function to return a scalarized expression. It is assumed that indices are
3475 zero based to make generation of DO loops easier. A zero as index will
3476 access the first element along a dimension. Single element references will
3477 be skipped. A NULL as an expression will be replaced by a full reference.
3478 This assumes that the index loops have gfc_index_integer_kind, and that all
3479 references have been frozen. */
3481 static gfc_expr*
3482 scalarized_expr (gfc_expr *e_in, gfc_expr **index, int count_index)
3484 gfc_array_ref *ar;
3485 int i;
3486 int rank;
3487 gfc_expr *e;
3488 int i_index;
3489 bool was_fullref;
3491 e = gfc_copy_expr(e_in);
3493 rank = e->rank;
3495 ar = gfc_find_array_ref (e);
3497 /* We scalarize count_index variables, reducing the rank by count_index. */
3499 e->rank = rank - count_index;
3501 was_fullref = ar->type == AR_FULL;
3503 if (e->rank == 0)
3504 ar->type = AR_ELEMENT;
3505 else
3506 ar->type = AR_SECTION;
3508 /* Loop over the indices. For each index, create the expression
3509 index * stride + lbound(e, dim). */
3511 i_index = 0;
3512 for (i=0; i < ar->dimen; i++)
3514 if (was_fullref || ar->dimen_type[i] == DIMEN_RANGE)
3516 if (index[i_index] != NULL)
3518 gfc_expr *lbound, *nindex;
3519 gfc_expr *loopvar;
3521 loopvar = gfc_copy_expr (index[i_index]);
3523 if (ar->stride[i])
3525 gfc_expr *tmp;
3527 tmp = gfc_copy_expr(ar->stride[i]);
3528 if (tmp->ts.kind != gfc_index_integer_kind)
3530 gfc_typespec ts;
3531 gfc_clear_ts (&ts);
3532 ts.type = BT_INTEGER;
3533 ts.kind = gfc_index_integer_kind;
3534 gfc_convert_type (tmp, &ts, 2);
3536 nindex = get_operand (INTRINSIC_TIMES, loopvar, tmp);
3538 else
3539 nindex = loopvar;
3541 /* Calculate the lower bound of the expression. */
3542 if (ar->start[i])
3544 lbound = gfc_copy_expr (ar->start[i]);
3545 if (lbound->ts.kind != gfc_index_integer_kind)
3547 gfc_typespec ts;
3548 gfc_clear_ts (&ts);
3549 ts.type = BT_INTEGER;
3550 ts.kind = gfc_index_integer_kind;
3551 gfc_convert_type (lbound, &ts, 2);
3555 else
3557 gfc_expr *lbound_e;
3558 gfc_ref *ref;
3560 lbound_e = gfc_copy_expr (e_in);
3562 for (ref = lbound_e->ref; ref; ref = ref->next)
3563 if (ref->type == REF_ARRAY
3564 && (ref->u.ar.type == AR_FULL
3565 || ref->u.ar.type == AR_SECTION))
3566 break;
3568 if (ref->next)
3570 gfc_free_ref_list (ref->next);
3571 ref->next = NULL;
3574 if (!was_fullref)
3576 /* Look at full individual sections, like a(:). The first index
3577 is the lbound of a full ref. */
3578 int j;
3579 gfc_array_ref *ar;
3580 int to;
3582 ar = &ref->u.ar;
3584 /* For assumed size, we need to keep around the final
3585 reference in order not to get an error on resolution
3586 below, and we cannot use AR_FULL. */
3588 if (ar->as->type == AS_ASSUMED_SIZE)
3590 ar->type = AR_SECTION;
3591 to = ar->dimen - 1;
3593 else
3595 to = ar->dimen;
3596 ar->type = AR_FULL;
3599 for (j = 0; j < to; j++)
3601 gfc_free_expr (ar->start[j]);
3602 ar->start[j] = NULL;
3603 gfc_free_expr (ar->end[j]);
3604 ar->end[j] = NULL;
3605 gfc_free_expr (ar->stride[j]);
3606 ar->stride[j] = NULL;
3609 /* We have to get rid of the shape, if there is one. Do
3610 so by freeing it and calling gfc_resolve to rebuild
3611 it, if necessary. */
3613 if (lbound_e->shape)
3614 gfc_free_shape (&(lbound_e->shape), lbound_e->rank);
3616 lbound_e->rank = ar->dimen;
3617 gfc_resolve_expr (lbound_e);
3619 lbound = get_array_inq_function (GFC_ISYM_LBOUND, lbound_e,
3620 i + 1);
3621 gfc_free_expr (lbound_e);
3624 ar->dimen_type[i] = DIMEN_ELEMENT;
3626 gfc_free_expr (ar->start[i]);
3627 ar->start[i] = get_operand (INTRINSIC_PLUS, nindex, lbound);
3629 gfc_free_expr (ar->end[i]);
3630 ar->end[i] = NULL;
3631 gfc_free_expr (ar->stride[i]);
3632 ar->stride[i] = NULL;
3633 gfc_simplify_expr (ar->start[i], 0);
3635 else if (was_fullref)
3637 gfc_internal_error ("Scalarization using DIMEN_RANGE unimplemented");
3639 i_index ++;
3643 return e;
3646 /* Helper function to check for a dimen vector as subscript. */
3648 static bool
3649 has_dimen_vector_ref (gfc_expr *e)
3651 gfc_array_ref *ar;
3652 int i;
3654 ar = gfc_find_array_ref (e);
3655 gcc_assert (ar);
3656 if (ar->type == AR_FULL)
3657 return false;
3659 for (i=0; i<ar->dimen; i++)
3660 if (ar->dimen_type[i] == DIMEN_VECTOR)
3661 return true;
3663 return false;
3666 /* If handed an expression of the form
3668 TRANSPOSE(CONJG(A))
3670 check if A can be handled by matmul and return if there is an uneven number
3671 of CONJG calls. Return a pointer to the array when everything is OK, NULL
3672 otherwise. The caller has to check for the correct rank. */
3674 static gfc_expr*
3675 check_conjg_transpose_variable (gfc_expr *e, bool *conjg, bool *transpose)
3677 *conjg = false;
3678 *transpose = false;
3682 if (e->expr_type == EXPR_VARIABLE)
3684 gcc_assert (e->rank == 1 || e->rank == 2);
3685 return e;
3687 else if (e->expr_type == EXPR_FUNCTION)
3689 if (e->value.function.isym == NULL)
3690 return NULL;
3692 if (e->value.function.isym->id == GFC_ISYM_CONJG)
3693 *conjg = !*conjg;
3694 else if (e->value.function.isym->id == GFC_ISYM_TRANSPOSE)
3695 *transpose = !*transpose;
3696 else return NULL;
3698 else
3699 return NULL;
3701 e = e->value.function.actual->expr;
3703 while(1);
3705 return NULL;
3708 /* Inline assignments of the form c = matmul(a,b).
3709 Handle only the cases currently where b and c are rank-two arrays.
3711 This basically translates the code to
3713 BLOCK
3714 integer i,j,k
3715 c = 0
3716 do j=0, size(b,2)-1
3717 do k=0, size(a, 2)-1
3718 do i=0, size(a, 1)-1
3719 c(i * stride(c,1) + lbound(c,1), j * stride(c,2) + lbound(c,2)) =
3720 c(i * stride(c,1) + lbound(c,1), j * stride(c,2) + lbound(c,2)) +
3721 a(i * stride(a,1) + lbound(a,1), k * stride(a,2) + lbound(a,2)) *
3722 b(k * stride(b,1) + lbound(b,1), j * stride(b,2) + lbound(b,2))
3723 end do
3724 end do
3725 end do
3726 END BLOCK
3730 static int
3731 inline_matmul_assign (gfc_code **c, int *walk_subtrees,
3732 void *data ATTRIBUTE_UNUSED)
3734 gfc_code *co = *c;
3735 gfc_expr *expr1, *expr2;
3736 gfc_expr *matrix_a, *matrix_b;
3737 gfc_actual_arglist *a, *b;
3738 gfc_code *do_1, *do_2, *do_3, *assign_zero, *assign_matmul;
3739 gfc_expr *zero_e;
3740 gfc_expr *u1, *u2, *u3;
3741 gfc_expr *list[2];
3742 gfc_expr *ascalar, *bscalar, *cscalar;
3743 gfc_expr *mult;
3744 gfc_expr *var_1, *var_2, *var_3;
3745 gfc_expr *zero;
3746 gfc_namespace *ns;
3747 gfc_intrinsic_op op_times, op_plus;
3748 enum matrix_case m_case;
3749 int i;
3750 gfc_code *if_limit = NULL;
3751 gfc_code **next_code_point;
3752 bool conjg_a, conjg_b, transpose_a, transpose_b;
3754 if (co->op != EXEC_ASSIGN)
3755 return 0;
3757 if (in_where || in_assoc_list)
3758 return 0;
3760 /* The BLOCKS generated for the temporary variables and FORALL don't
3761 mix. */
3762 if (forall_level > 0)
3763 return 0;
3765 /* For now don't do anything in OpenMP workshare, it confuses
3766 its translation, which expects only the allowed statements in there.
3767 We should figure out how to parallelize this eventually. */
3768 if (in_omp_workshare)
3769 return 0;
3771 expr1 = co->expr1;
3772 expr2 = co->expr2;
3773 if (expr2->expr_type != EXPR_FUNCTION
3774 || expr2->value.function.isym == NULL
3775 || expr2->value.function.isym->id != GFC_ISYM_MATMUL)
3776 return 0;
3778 current_code = c;
3779 inserted_block = NULL;
3780 changed_statement = NULL;
3782 a = expr2->value.function.actual;
3783 matrix_a = check_conjg_transpose_variable (a->expr, &conjg_a, &transpose_a);
3784 if (matrix_a == NULL)
3785 return 0;
3787 b = a->next;
3788 matrix_b = check_conjg_transpose_variable (b->expr, &conjg_b, &transpose_b);
3789 if (matrix_b == NULL)
3790 return 0;
3792 if (has_dimen_vector_ref (expr1) || has_dimen_vector_ref (matrix_a)
3793 || has_dimen_vector_ref (matrix_b))
3794 return 0;
3796 /* We do not handle data dependencies yet. */
3797 if (gfc_check_dependency (expr1, matrix_a, true)
3798 || gfc_check_dependency (expr1, matrix_b, true))
3799 return 0;
3801 m_case = none;
3802 if (matrix_a->rank == 2)
3804 if (transpose_a)
3806 if (matrix_b->rank == 2 && !transpose_b)
3807 m_case = A2TB2;
3809 else
3811 if (matrix_b->rank == 1)
3812 m_case = A2B1;
3813 else /* matrix_b->rank == 2 */
3815 if (transpose_b)
3816 m_case = A2B2T;
3817 else
3818 m_case = A2B2;
3822 else /* matrix_a->rank == 1 */
3824 if (matrix_b->rank == 2)
3826 if (!transpose_b)
3827 m_case = A1B2;
3831 if (m_case == none)
3832 return 0;
3834 ns = insert_block ();
3836 /* Assign the type of the zero expression for initializing the resulting
3837 array, and the expression (+ and * for real, integer and complex;
3838 .and. and .or for logical. */
3840 switch(expr1->ts.type)
3842 case BT_INTEGER:
3843 zero_e = gfc_get_int_expr (expr1->ts.kind, &expr1->where, 0);
3844 op_times = INTRINSIC_TIMES;
3845 op_plus = INTRINSIC_PLUS;
3846 break;
3848 case BT_LOGICAL:
3849 op_times = INTRINSIC_AND;
3850 op_plus = INTRINSIC_OR;
3851 zero_e = gfc_get_logical_expr (expr1->ts.kind, &expr1->where,
3853 break;
3854 case BT_REAL:
3855 zero_e = gfc_get_constant_expr (BT_REAL, expr1->ts.kind,
3856 &expr1->where);
3857 mpfr_set_si (zero_e->value.real, 0, GFC_RND_MODE);
3858 op_times = INTRINSIC_TIMES;
3859 op_plus = INTRINSIC_PLUS;
3860 break;
3862 case BT_COMPLEX:
3863 zero_e = gfc_get_constant_expr (BT_COMPLEX, expr1->ts.kind,
3864 &expr1->where);
3865 mpc_set_si_si (zero_e->value.complex, 0, 0, GFC_RND_MODE);
3866 op_times = INTRINSIC_TIMES;
3867 op_plus = INTRINSIC_PLUS;
3869 break;
3871 default:
3872 gcc_unreachable();
3875 current_code = &ns->code;
3877 /* Freeze the references, keeping track of how many temporary variables were
3878 created. */
3879 n_vars = 0;
3880 freeze_references (matrix_a);
3881 freeze_references (matrix_b);
3882 freeze_references (expr1);
3884 if (n_vars == 0)
3885 next_code_point = current_code;
3886 else
3888 next_code_point = &ns->code;
3889 for (i=0; i<n_vars; i++)
3890 next_code_point = &(*next_code_point)->next;
3893 /* Take care of the inline flag. If the limit check evaluates to a
3894 constant, dead code elimination will eliminate the unneeded branch. */
3896 if (m_case == A2B2 && flag_inline_matmul_limit > 0)
3898 if_limit = inline_limit_check (matrix_a, matrix_b, m_case);
3900 /* Insert the original statement into the else branch. */
3901 if_limit->block->block->next = co;
3902 co->next = NULL;
3904 /* ... and the new ones go into the original one. */
3905 *next_code_point = if_limit;
3906 next_code_point = &if_limit->block->next;
3909 assign_zero = XCNEW (gfc_code);
3910 assign_zero->op = EXEC_ASSIGN;
3911 assign_zero->loc = co->loc;
3912 assign_zero->expr1 = gfc_copy_expr (expr1);
3913 assign_zero->expr2 = zero_e;
3915 /* Handle the reallocation, if needed. */
3916 if (flag_realloc_lhs && gfc_is_reallocatable_lhs (expr1))
3918 gfc_code *lhs_alloc;
3920 /* Only need to check a single dimension for the A2B2 case for
3921 bounds checking, the rest will be allocated. Also check this
3922 for A2B1. */
3924 if ((gfc_option.rtcheck & GFC_RTCHECK_BOUNDS) && (m_case == A2B2 || m_case == A2B1))
3926 gfc_code *test;
3927 gfc_expr *a2, *b1;
3929 a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2);
3930 b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1);
3931 test = runtime_error_ne (b1, a2, "Dimension of array B incorrect "
3932 "in MATMUL intrinsic: Is %ld, should be %ld");
3933 *next_code_point = test;
3934 next_code_point = &test->next;
3938 lhs_alloc = matmul_lhs_realloc (expr1, matrix_a, matrix_b, m_case);
3940 *next_code_point = lhs_alloc;
3941 next_code_point = &lhs_alloc->next;
3944 else if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
3946 gfc_code *test;
3947 gfc_expr *a2, *b1, *c1, *c2, *a1, *b2;
3949 if (m_case == A2B2 || m_case == A2B1)
3951 a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2);
3952 b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1);
3953 test = runtime_error_ne (b1, a2, "Dimension of array B incorrect "
3954 "in MATMUL intrinsic: Is %ld, should be %ld");
3955 *next_code_point = test;
3956 next_code_point = &test->next;
3958 c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1);
3959 a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1);
3961 if (m_case == A2B2)
3962 test = runtime_error_ne (c1, a1, "Incorrect extent in return array in "
3963 "MATMUL intrinsic for dimension 1: "
3964 "is %ld, should be %ld");
3965 else if (m_case == A2B1)
3966 test = runtime_error_ne (c1, a1, "Incorrect extent in return array in "
3967 "MATMUL intrinsic: "
3968 "is %ld, should be %ld");
3971 *next_code_point = test;
3972 next_code_point = &test->next;
3974 else if (m_case == A1B2)
3976 a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1);
3977 b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1);
3978 test = runtime_error_ne (b1, a1, "Dimension of array B incorrect "
3979 "in MATMUL intrinsic: Is %ld, should be %ld");
3980 *next_code_point = test;
3981 next_code_point = &test->next;
3983 c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1);
3984 b2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 2);
3986 test = runtime_error_ne (c1, b2, "Incorrect extent in return array in "
3987 "MATMUL intrinsic: "
3988 "is %ld, should be %ld");
3990 *next_code_point = test;
3991 next_code_point = &test->next;
3994 if (m_case == A2B2)
3996 c2 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 2);
3997 b2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 2);
3998 test = runtime_error_ne (c2, b2, "Incorrect extent in return array in "
3999 "MATMUL intrinsic for dimension 2: is %ld, should be %ld");
4001 *next_code_point = test;
4002 next_code_point = &test->next;
4005 if (m_case == A2B2T)
4007 c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1);
4008 a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1);
4009 test = runtime_error_ne (c1, a1, "Incorrect extent in return array in "
4010 "MATMUL intrinsic for dimension 1: "
4011 "is %ld, should be %ld");
4013 *next_code_point = test;
4014 next_code_point = &test->next;
4016 c2 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 2);
4017 b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1);
4018 test = runtime_error_ne (c2, b1, "Incorrect extent in return array in "
4019 "MATMUL intrinsic for dimension 2: "
4020 "is %ld, should be %ld");
4021 *next_code_point = test;
4022 next_code_point = &test->next;
4024 a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2);
4025 b2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 2);
4027 test = runtime_error_ne (b2, a2, "Incorrect extent in argument B in "
4028 "MATMUL intrnisic for dimension 2: "
4029 "is %ld, should be %ld");
4030 *next_code_point = test;
4031 next_code_point = &test->next;
4035 if (m_case == A2TB2)
4037 c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1);
4038 a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2);
4040 test = runtime_error_ne (c1, a2, "Incorrect extent in return array in "
4041 "MATMUL intrinsic for dimension 1: "
4042 "is %ld, should be %ld");
4044 *next_code_point = test;
4045 next_code_point = &test->next;
4047 c2 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 2);
4048 b2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 2);
4049 test = runtime_error_ne (c2, b2, "Incorrect extent in return array in "
4050 "MATMUL intrinsic for dimension 2: "
4051 "is %ld, should be %ld");
4052 *next_code_point = test;
4053 next_code_point = &test->next;
4055 a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1);
4056 b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1);
4058 test = runtime_error_ne (b1, a1, "Incorrect extent in argument B in "
4059 "MATMUL intrnisic for dimension 2: "
4060 "is %ld, should be %ld");
4061 *next_code_point = test;
4062 next_code_point = &test->next;
4067 *next_code_point = assign_zero;
4069 zero = gfc_get_int_expr (gfc_index_integer_kind, &co->loc, 0);
4071 assign_matmul = XCNEW (gfc_code);
4072 assign_matmul->op = EXEC_ASSIGN;
4073 assign_matmul->loc = co->loc;
4075 /* Get the bounds for the loops, create them and create the scalarized
4076 expressions. */
4078 switch (m_case)
4080 case A2B2:
4081 inline_limit_check (matrix_a, matrix_b, m_case);
4083 u1 = get_size_m1 (matrix_b, 2);
4084 u2 = get_size_m1 (matrix_a, 2);
4085 u3 = get_size_m1 (matrix_a, 1);
4087 do_1 = create_do_loop (gfc_copy_expr (zero), u1, NULL, &co->loc, ns);
4088 do_2 = create_do_loop (gfc_copy_expr (zero), u2, NULL, &co->loc, ns);
4089 do_3 = create_do_loop (gfc_copy_expr (zero), u3, NULL, &co->loc, ns);
4091 do_1->block->next = do_2;
4092 do_2->block->next = do_3;
4093 do_3->block->next = assign_matmul;
4095 var_1 = do_1->ext.iterator->var;
4096 var_2 = do_2->ext.iterator->var;
4097 var_3 = do_3->ext.iterator->var;
4099 list[0] = var_3;
4100 list[1] = var_1;
4101 cscalar = scalarized_expr (co->expr1, list, 2);
4103 list[0] = var_3;
4104 list[1] = var_2;
4105 ascalar = scalarized_expr (matrix_a, list, 2);
4107 list[0] = var_2;
4108 list[1] = var_1;
4109 bscalar = scalarized_expr (matrix_b, list, 2);
4111 break;
4113 case A2B2T:
4114 inline_limit_check (matrix_a, matrix_b, m_case);
4116 u1 = get_size_m1 (matrix_b, 1);
4117 u2 = get_size_m1 (matrix_a, 2);
4118 u3 = get_size_m1 (matrix_a, 1);
4120 do_1 = create_do_loop (gfc_copy_expr (zero), u1, NULL, &co->loc, ns);
4121 do_2 = create_do_loop (gfc_copy_expr (zero), u2, NULL, &co->loc, ns);
4122 do_3 = create_do_loop (gfc_copy_expr (zero), u3, NULL, &co->loc, ns);
4124 do_1->block->next = do_2;
4125 do_2->block->next = do_3;
4126 do_3->block->next = assign_matmul;
4128 var_1 = do_1->ext.iterator->var;
4129 var_2 = do_2->ext.iterator->var;
4130 var_3 = do_3->ext.iterator->var;
4132 list[0] = var_3;
4133 list[1] = var_1;
4134 cscalar = scalarized_expr (co->expr1, list, 2);
4136 list[0] = var_3;
4137 list[1] = var_2;
4138 ascalar = scalarized_expr (matrix_a, list, 2);
4140 list[0] = var_1;
4141 list[1] = var_2;
4142 bscalar = scalarized_expr (matrix_b, list, 2);
4144 break;
4146 case A2TB2:
4147 inline_limit_check (matrix_a, matrix_b, m_case);
4149 u1 = get_size_m1 (matrix_a, 2);
4150 u2 = get_size_m1 (matrix_b, 2);
4151 u3 = get_size_m1 (matrix_a, 1);
4153 do_1 = create_do_loop (gfc_copy_expr (zero), u1, NULL, &co->loc, ns);
4154 do_2 = create_do_loop (gfc_copy_expr (zero), u2, NULL, &co->loc, ns);
4155 do_3 = create_do_loop (gfc_copy_expr (zero), u3, NULL, &co->loc, ns);
4157 do_1->block->next = do_2;
4158 do_2->block->next = do_3;
4159 do_3->block->next = assign_matmul;
4161 var_1 = do_1->ext.iterator->var;
4162 var_2 = do_2->ext.iterator->var;
4163 var_3 = do_3->ext.iterator->var;
4165 list[0] = var_1;
4166 list[1] = var_2;
4167 cscalar = scalarized_expr (co->expr1, list, 2);
4169 list[0] = var_3;
4170 list[1] = var_1;
4171 ascalar = scalarized_expr (matrix_a, list, 2);
4173 list[0] = var_3;
4174 list[1] = var_2;
4175 bscalar = scalarized_expr (matrix_b, list, 2);
4177 break;
4179 case A2B1:
4180 u1 = get_size_m1 (matrix_b, 1);
4181 u2 = get_size_m1 (matrix_a, 1);
4183 do_1 = create_do_loop (gfc_copy_expr (zero), u1, NULL, &co->loc, ns);
4184 do_2 = create_do_loop (gfc_copy_expr (zero), u2, NULL, &co->loc, ns);
4186 do_1->block->next = do_2;
4187 do_2->block->next = assign_matmul;
4189 var_1 = do_1->ext.iterator->var;
4190 var_2 = do_2->ext.iterator->var;
4192 list[0] = var_2;
4193 cscalar = scalarized_expr (co->expr1, list, 1);
4195 list[0] = var_2;
4196 list[1] = var_1;
4197 ascalar = scalarized_expr (matrix_a, list, 2);
4199 list[0] = var_1;
4200 bscalar = scalarized_expr (matrix_b, list, 1);
4202 break;
4204 case A1B2:
4205 u1 = get_size_m1 (matrix_b, 2);
4206 u2 = get_size_m1 (matrix_a, 1);
4208 do_1 = create_do_loop (gfc_copy_expr (zero), u1, NULL, &co->loc, ns);
4209 do_2 = create_do_loop (gfc_copy_expr (zero), u2, NULL, &co->loc, ns);
4211 do_1->block->next = do_2;
4212 do_2->block->next = assign_matmul;
4214 var_1 = do_1->ext.iterator->var;
4215 var_2 = do_2->ext.iterator->var;
4217 list[0] = var_1;
4218 cscalar = scalarized_expr (co->expr1, list, 1);
4220 list[0] = var_2;
4221 ascalar = scalarized_expr (matrix_a, list, 1);
4223 list[0] = var_2;
4224 list[1] = var_1;
4225 bscalar = scalarized_expr (matrix_b, list, 2);
4227 break;
4229 default:
4230 gcc_unreachable();
4233 /* Build the conjg call around the variables. Set the typespec manually
4234 because gfc_build_intrinsic_call sometimes gets this wrong. */
4235 if (conjg_a)
4237 gfc_typespec ts;
4238 ts = matrix_a->ts;
4239 ascalar = gfc_build_intrinsic_call (ns, GFC_ISYM_CONJG, "conjg",
4240 matrix_a->where, 1, ascalar);
4241 ascalar->ts = ts;
4244 if (conjg_b)
4246 gfc_typespec ts;
4247 ts = matrix_b->ts;
4248 bscalar = gfc_build_intrinsic_call (ns, GFC_ISYM_CONJG, "conjg",
4249 matrix_b->where, 1, bscalar);
4250 bscalar->ts = ts;
4252 /* First loop comes after the zero assignment. */
4253 assign_zero->next = do_1;
4255 /* Build the assignment expression in the loop. */
4256 assign_matmul->expr1 = gfc_copy_expr (cscalar);
4258 mult = get_operand (op_times, ascalar, bscalar);
4259 assign_matmul->expr2 = get_operand (op_plus, cscalar, mult);
4261 /* If we don't want to keep the original statement around in
4262 the else branch, we can free it. */
4264 if (if_limit == NULL)
4265 gfc_free_statements(co);
4266 else
4267 co->next = NULL;
4269 gfc_free_expr (zero);
4270 *walk_subtrees = 0;
4271 return 0;
4275 /* Code for index interchange for loops which are grouped together in DO
4276 CONCURRENT or FORALL statements. This is currently only applied if the
4277 iterations are grouped together in a single statement.
4279 For this transformation, it is assumed that memory access in strides is
4280 expensive, and that loops which access later indices (which access memory
4281 in bigger strides) should be moved to the first loops.
4283 For this, a loop over all the statements is executed, counting the times
4284 that the loop iteration values are accessed in each index. The loop
4285 indices are then sorted to minimize access to later indices from inner
4286 loops. */
4288 /* Type for holding index information. */
4290 typedef struct {
4291 gfc_symbol *sym;
4292 gfc_forall_iterator *fa;
4293 int num;
4294 int n[GFC_MAX_DIMENSIONS];
4295 } ind_type;
4297 /* Callback function to determine if an expression is the
4298 corresponding variable. */
4300 static int
4301 has_var (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED, void *data)
4303 gfc_expr *expr = *e;
4304 gfc_symbol *sym;
4306 if (expr->expr_type != EXPR_VARIABLE)
4307 return 0;
4309 sym = (gfc_symbol *) data;
4310 return sym == expr->symtree->n.sym;
4313 /* Callback function to calculate the cost of a certain index. */
4315 static int
4316 index_cost (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
4317 void *data)
4319 ind_type *ind;
4320 gfc_expr *expr;
4321 gfc_array_ref *ar;
4322 gfc_ref *ref;
4323 int i,j;
4325 expr = *e;
4326 if (expr->expr_type != EXPR_VARIABLE)
4327 return 0;
4329 ar = NULL;
4330 for (ref = expr->ref; ref; ref = ref->next)
4332 if (ref->type == REF_ARRAY)
4334 ar = &ref->u.ar;
4335 break;
4338 if (ar == NULL || ar->type != AR_ELEMENT)
4339 return 0;
4341 ind = (ind_type *) data;
4342 for (i = 0; i < ar->dimen; i++)
4344 for (j=0; ind[j].sym != NULL; j++)
4346 if (gfc_expr_walker (&ar->start[i], has_var, (void *) (ind[j].sym)))
4347 ind[j].n[i]++;
4350 return 0;
4353 /* Callback function for qsort, to sort the loop indices. */
4355 static int
4356 loop_comp (const void *e1, const void *e2)
4358 const ind_type *i1 = (const ind_type *) e1;
4359 const ind_type *i2 = (const ind_type *) e2;
4360 int i;
4362 for (i=GFC_MAX_DIMENSIONS-1; i >= 0; i--)
4364 if (i1->n[i] != i2->n[i])
4365 return i1->n[i] - i2->n[i];
4367 /* All other things being equal, let's not change the ordering. */
4368 return i2->num - i1->num;
4371 /* Main function to do the index interchange. */
4373 static int
4374 index_interchange (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
4375 void *data ATTRIBUTE_UNUSED)
4377 gfc_code *co;
4378 co = *c;
4379 int n_iter;
4380 gfc_forall_iterator *fa;
4381 ind_type *ind;
4382 int i, j;
4384 if (co->op != EXEC_FORALL && co->op != EXEC_DO_CONCURRENT)
4385 return 0;
4387 n_iter = 0;
4388 for (fa = co->ext.forall_iterator; fa; fa = fa->next)
4389 n_iter ++;
4391 /* Nothing to reorder. */
4392 if (n_iter < 2)
4393 return 0;
4395 ind = XALLOCAVEC (ind_type, n_iter + 1);
4397 i = 0;
4398 for (fa = co->ext.forall_iterator; fa; fa = fa->next)
4400 ind[i].sym = fa->var->symtree->n.sym;
4401 ind[i].fa = fa;
4402 for (j=0; j<GFC_MAX_DIMENSIONS; j++)
4403 ind[i].n[j] = 0;
4404 ind[i].num = i;
4405 i++;
4407 ind[n_iter].sym = NULL;
4408 ind[n_iter].fa = NULL;
4410 gfc_code_walker (c, gfc_dummy_code_callback, index_cost, (void *) ind);
4411 qsort ((void *) ind, n_iter, sizeof (ind_type), loop_comp);
4413 /* Do the actual index interchange. */
4414 co->ext.forall_iterator = fa = ind[0].fa;
4415 for (i=1; i<n_iter; i++)
4417 fa->next = ind[i].fa;
4418 fa = fa->next;
4420 fa->next = NULL;
4422 if (flag_warn_frontend_loop_interchange)
4424 for (i=1; i<n_iter; i++)
4426 if (ind[i-1].num > ind[i].num)
4428 gfc_warning (OPT_Wfrontend_loop_interchange,
4429 "Interchanging loops at %L", &co->loc);
4430 break;
4435 return 0;
4438 #define WALK_SUBEXPR(NODE) \
4439 do \
4441 result = gfc_expr_walker (&(NODE), exprfn, data); \
4442 if (result) \
4443 return result; \
4445 while (0)
4446 #define WALK_SUBEXPR_TAIL(NODE) e = &(NODE); continue
4448 /* Walk expression *E, calling EXPRFN on each expression in it. */
4451 gfc_expr_walker (gfc_expr **e, walk_expr_fn_t exprfn, void *data)
4453 while (*e)
4455 int walk_subtrees = 1;
4456 gfc_actual_arglist *a;
4457 gfc_ref *r;
4458 gfc_constructor *c;
4460 int result = exprfn (e, &walk_subtrees, data);
4461 if (result)
4462 return result;
4463 if (walk_subtrees)
4464 switch ((*e)->expr_type)
4466 case EXPR_OP:
4467 WALK_SUBEXPR ((*e)->value.op.op1);
4468 WALK_SUBEXPR_TAIL ((*e)->value.op.op2);
4469 break;
4470 case EXPR_FUNCTION:
4471 for (a = (*e)->value.function.actual; a; a = a->next)
4472 WALK_SUBEXPR (a->expr);
4473 break;
4474 case EXPR_COMPCALL:
4475 case EXPR_PPC:
4476 WALK_SUBEXPR ((*e)->value.compcall.base_object);
4477 for (a = (*e)->value.compcall.actual; a; a = a->next)
4478 WALK_SUBEXPR (a->expr);
4479 break;
4481 case EXPR_STRUCTURE:
4482 case EXPR_ARRAY:
4483 for (c = gfc_constructor_first ((*e)->value.constructor); c;
4484 c = gfc_constructor_next (c))
4486 if (c->iterator == NULL)
4487 WALK_SUBEXPR (c->expr);
4488 else
4490 iterator_level ++;
4491 WALK_SUBEXPR (c->expr);
4492 iterator_level --;
4493 WALK_SUBEXPR (c->iterator->var);
4494 WALK_SUBEXPR (c->iterator->start);
4495 WALK_SUBEXPR (c->iterator->end);
4496 WALK_SUBEXPR (c->iterator->step);
4500 if ((*e)->expr_type != EXPR_ARRAY)
4501 break;
4503 /* Fall through to the variable case in order to walk the
4504 reference. */
4505 gcc_fallthrough ();
4507 case EXPR_SUBSTRING:
4508 case EXPR_VARIABLE:
4509 for (r = (*e)->ref; r; r = r->next)
4511 gfc_array_ref *ar;
4512 int i;
4514 switch (r->type)
4516 case REF_ARRAY:
4517 ar = &r->u.ar;
4518 if (ar->type == AR_SECTION || ar->type == AR_ELEMENT)
4520 for (i=0; i< ar->dimen; i++)
4522 WALK_SUBEXPR (ar->start[i]);
4523 WALK_SUBEXPR (ar->end[i]);
4524 WALK_SUBEXPR (ar->stride[i]);
4528 break;
4530 case REF_SUBSTRING:
4531 WALK_SUBEXPR (r->u.ss.start);
4532 WALK_SUBEXPR (r->u.ss.end);
4533 break;
4535 case REF_COMPONENT:
4536 break;
4540 default:
4541 break;
4543 return 0;
4545 return 0;
4548 #define WALK_SUBCODE(NODE) \
4549 do \
4551 result = gfc_code_walker (&(NODE), codefn, exprfn, data); \
4552 if (result) \
4553 return result; \
4555 while (0)
4557 /* Walk code *C, calling CODEFN on each gfc_code node in it and calling EXPRFN
4558 on each expression in it. If any of the hooks returns non-zero, that
4559 value is immediately returned. If the hook sets *WALK_SUBTREES to 0,
4560 no subcodes or subexpressions are traversed. */
4563 gfc_code_walker (gfc_code **c, walk_code_fn_t codefn, walk_expr_fn_t exprfn,
4564 void *data)
4566 for (; *c; c = &(*c)->next)
4568 int walk_subtrees = 1;
4569 int result = codefn (c, &walk_subtrees, data);
4570 if (result)
4571 return result;
4573 if (walk_subtrees)
4575 gfc_code *b;
4576 gfc_actual_arglist *a;
4577 gfc_code *co;
4578 gfc_association_list *alist;
4579 bool saved_in_omp_workshare;
4580 bool saved_in_where;
4582 /* There might be statement insertions before the current code,
4583 which must not affect the expression walker. */
4585 co = *c;
4586 saved_in_omp_workshare = in_omp_workshare;
4587 saved_in_where = in_where;
4589 switch (co->op)
4592 case EXEC_BLOCK:
4593 WALK_SUBCODE (co->ext.block.ns->code);
4594 if (co->ext.block.assoc)
4596 bool saved_in_assoc_list = in_assoc_list;
4598 in_assoc_list = true;
4599 for (alist = co->ext.block.assoc; alist; alist = alist->next)
4600 WALK_SUBEXPR (alist->target);
4602 in_assoc_list = saved_in_assoc_list;
4605 break;
4607 case EXEC_DO:
4608 doloop_level ++;
4609 WALK_SUBEXPR (co->ext.iterator->var);
4610 WALK_SUBEXPR (co->ext.iterator->start);
4611 WALK_SUBEXPR (co->ext.iterator->end);
4612 WALK_SUBEXPR (co->ext.iterator->step);
4613 break;
4615 case EXEC_IF:
4616 if_level ++;
4617 break;
4619 case EXEC_WHERE:
4620 in_where = true;
4621 break;
4623 case EXEC_CALL:
4624 case EXEC_ASSIGN_CALL:
4625 for (a = co->ext.actual; a; a = a->next)
4626 WALK_SUBEXPR (a->expr);
4627 break;
4629 case EXEC_CALL_PPC:
4630 WALK_SUBEXPR (co->expr1);
4631 for (a = co->ext.actual; a; a = a->next)
4632 WALK_SUBEXPR (a->expr);
4633 break;
4635 case EXEC_SELECT:
4636 WALK_SUBEXPR (co->expr1);
4637 select_level ++;
4638 for (b = co->block; b; b = b->block)
4640 gfc_case *cp;
4641 for (cp = b->ext.block.case_list; cp; cp = cp->next)
4643 WALK_SUBEXPR (cp->low);
4644 WALK_SUBEXPR (cp->high);
4646 WALK_SUBCODE (b->next);
4648 continue;
4650 case EXEC_ALLOCATE:
4651 case EXEC_DEALLOCATE:
4653 gfc_alloc *a;
4654 for (a = co->ext.alloc.list; a; a = a->next)
4655 WALK_SUBEXPR (a->expr);
4656 break;
4659 case EXEC_FORALL:
4660 case EXEC_DO_CONCURRENT:
4662 gfc_forall_iterator *fa;
4663 for (fa = co->ext.forall_iterator; fa; fa = fa->next)
4665 WALK_SUBEXPR (fa->var);
4666 WALK_SUBEXPR (fa->start);
4667 WALK_SUBEXPR (fa->end);
4668 WALK_SUBEXPR (fa->stride);
4670 if (co->op == EXEC_FORALL)
4671 forall_level ++;
4672 break;
4675 case EXEC_OPEN:
4676 WALK_SUBEXPR (co->ext.open->unit);
4677 WALK_SUBEXPR (co->ext.open->file);
4678 WALK_SUBEXPR (co->ext.open->status);
4679 WALK_SUBEXPR (co->ext.open->access);
4680 WALK_SUBEXPR (co->ext.open->form);
4681 WALK_SUBEXPR (co->ext.open->recl);
4682 WALK_SUBEXPR (co->ext.open->blank);
4683 WALK_SUBEXPR (co->ext.open->position);
4684 WALK_SUBEXPR (co->ext.open->action);
4685 WALK_SUBEXPR (co->ext.open->delim);
4686 WALK_SUBEXPR (co->ext.open->pad);
4687 WALK_SUBEXPR (co->ext.open->iostat);
4688 WALK_SUBEXPR (co->ext.open->iomsg);
4689 WALK_SUBEXPR (co->ext.open->convert);
4690 WALK_SUBEXPR (co->ext.open->decimal);
4691 WALK_SUBEXPR (co->ext.open->encoding);
4692 WALK_SUBEXPR (co->ext.open->round);
4693 WALK_SUBEXPR (co->ext.open->sign);
4694 WALK_SUBEXPR (co->ext.open->asynchronous);
4695 WALK_SUBEXPR (co->ext.open->id);
4696 WALK_SUBEXPR (co->ext.open->newunit);
4697 WALK_SUBEXPR (co->ext.open->share);
4698 WALK_SUBEXPR (co->ext.open->cc);
4699 break;
4701 case EXEC_CLOSE:
4702 WALK_SUBEXPR (co->ext.close->unit);
4703 WALK_SUBEXPR (co->ext.close->status);
4704 WALK_SUBEXPR (co->ext.close->iostat);
4705 WALK_SUBEXPR (co->ext.close->iomsg);
4706 break;
4708 case EXEC_BACKSPACE:
4709 case EXEC_ENDFILE:
4710 case EXEC_REWIND:
4711 case EXEC_FLUSH:
4712 WALK_SUBEXPR (co->ext.filepos->unit);
4713 WALK_SUBEXPR (co->ext.filepos->iostat);
4714 WALK_SUBEXPR (co->ext.filepos->iomsg);
4715 break;
4717 case EXEC_INQUIRE:
4718 WALK_SUBEXPR (co->ext.inquire->unit);
4719 WALK_SUBEXPR (co->ext.inquire->file);
4720 WALK_SUBEXPR (co->ext.inquire->iomsg);
4721 WALK_SUBEXPR (co->ext.inquire->iostat);
4722 WALK_SUBEXPR (co->ext.inquire->exist);
4723 WALK_SUBEXPR (co->ext.inquire->opened);
4724 WALK_SUBEXPR (co->ext.inquire->number);
4725 WALK_SUBEXPR (co->ext.inquire->named);
4726 WALK_SUBEXPR (co->ext.inquire->name);
4727 WALK_SUBEXPR (co->ext.inquire->access);
4728 WALK_SUBEXPR (co->ext.inquire->sequential);
4729 WALK_SUBEXPR (co->ext.inquire->direct);
4730 WALK_SUBEXPR (co->ext.inquire->form);
4731 WALK_SUBEXPR (co->ext.inquire->formatted);
4732 WALK_SUBEXPR (co->ext.inquire->unformatted);
4733 WALK_SUBEXPR (co->ext.inquire->recl);
4734 WALK_SUBEXPR (co->ext.inquire->nextrec);
4735 WALK_SUBEXPR (co->ext.inquire->blank);
4736 WALK_SUBEXPR (co->ext.inquire->position);
4737 WALK_SUBEXPR (co->ext.inquire->action);
4738 WALK_SUBEXPR (co->ext.inquire->read);
4739 WALK_SUBEXPR (co->ext.inquire->write);
4740 WALK_SUBEXPR (co->ext.inquire->readwrite);
4741 WALK_SUBEXPR (co->ext.inquire->delim);
4742 WALK_SUBEXPR (co->ext.inquire->encoding);
4743 WALK_SUBEXPR (co->ext.inquire->pad);
4744 WALK_SUBEXPR (co->ext.inquire->iolength);
4745 WALK_SUBEXPR (co->ext.inquire->convert);
4746 WALK_SUBEXPR (co->ext.inquire->strm_pos);
4747 WALK_SUBEXPR (co->ext.inquire->asynchronous);
4748 WALK_SUBEXPR (co->ext.inquire->decimal);
4749 WALK_SUBEXPR (co->ext.inquire->pending);
4750 WALK_SUBEXPR (co->ext.inquire->id);
4751 WALK_SUBEXPR (co->ext.inquire->sign);
4752 WALK_SUBEXPR (co->ext.inquire->size);
4753 WALK_SUBEXPR (co->ext.inquire->round);
4754 break;
4756 case EXEC_WAIT:
4757 WALK_SUBEXPR (co->ext.wait->unit);
4758 WALK_SUBEXPR (co->ext.wait->iostat);
4759 WALK_SUBEXPR (co->ext.wait->iomsg);
4760 WALK_SUBEXPR (co->ext.wait->id);
4761 break;
4763 case EXEC_READ:
4764 case EXEC_WRITE:
4765 WALK_SUBEXPR (co->ext.dt->io_unit);
4766 WALK_SUBEXPR (co->ext.dt->format_expr);
4767 WALK_SUBEXPR (co->ext.dt->rec);
4768 WALK_SUBEXPR (co->ext.dt->advance);
4769 WALK_SUBEXPR (co->ext.dt->iostat);
4770 WALK_SUBEXPR (co->ext.dt->size);
4771 WALK_SUBEXPR (co->ext.dt->iomsg);
4772 WALK_SUBEXPR (co->ext.dt->id);
4773 WALK_SUBEXPR (co->ext.dt->pos);
4774 WALK_SUBEXPR (co->ext.dt->asynchronous);
4775 WALK_SUBEXPR (co->ext.dt->blank);
4776 WALK_SUBEXPR (co->ext.dt->decimal);
4777 WALK_SUBEXPR (co->ext.dt->delim);
4778 WALK_SUBEXPR (co->ext.dt->pad);
4779 WALK_SUBEXPR (co->ext.dt->round);
4780 WALK_SUBEXPR (co->ext.dt->sign);
4781 WALK_SUBEXPR (co->ext.dt->extra_comma);
4782 break;
4784 case EXEC_OMP_PARALLEL:
4785 case EXEC_OMP_PARALLEL_DO:
4786 case EXEC_OMP_PARALLEL_DO_SIMD:
4787 case EXEC_OMP_PARALLEL_SECTIONS:
4789 in_omp_workshare = false;
4791 /* This goto serves as a shortcut to avoid code
4792 duplication or a larger if or switch statement. */
4793 goto check_omp_clauses;
4795 case EXEC_OMP_WORKSHARE:
4796 case EXEC_OMP_PARALLEL_WORKSHARE:
4798 in_omp_workshare = true;
4800 /* Fall through */
4802 case EXEC_OMP_CRITICAL:
4803 case EXEC_OMP_DISTRIBUTE:
4804 case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
4805 case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
4806 case EXEC_OMP_DISTRIBUTE_SIMD:
4807 case EXEC_OMP_DO:
4808 case EXEC_OMP_DO_SIMD:
4809 case EXEC_OMP_ORDERED:
4810 case EXEC_OMP_SECTIONS:
4811 case EXEC_OMP_SINGLE:
4812 case EXEC_OMP_END_SINGLE:
4813 case EXEC_OMP_SIMD:
4814 case EXEC_OMP_TASKLOOP:
4815 case EXEC_OMP_TASKLOOP_SIMD:
4816 case EXEC_OMP_TARGET:
4817 case EXEC_OMP_TARGET_DATA:
4818 case EXEC_OMP_TARGET_ENTER_DATA:
4819 case EXEC_OMP_TARGET_EXIT_DATA:
4820 case EXEC_OMP_TARGET_PARALLEL:
4821 case EXEC_OMP_TARGET_PARALLEL_DO:
4822 case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
4823 case EXEC_OMP_TARGET_SIMD:
4824 case EXEC_OMP_TARGET_TEAMS:
4825 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
4826 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
4827 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
4828 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
4829 case EXEC_OMP_TARGET_UPDATE:
4830 case EXEC_OMP_TASK:
4831 case EXEC_OMP_TEAMS:
4832 case EXEC_OMP_TEAMS_DISTRIBUTE:
4833 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
4834 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
4835 case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
4837 /* Come to this label only from the
4838 EXEC_OMP_PARALLEL_* cases above. */
4840 check_omp_clauses:
4842 if (co->ext.omp_clauses)
4844 gfc_omp_namelist *n;
4845 static int list_types[]
4846 = { OMP_LIST_ALIGNED, OMP_LIST_LINEAR, OMP_LIST_DEPEND,
4847 OMP_LIST_MAP, OMP_LIST_TO, OMP_LIST_FROM };
4848 size_t idx;
4849 WALK_SUBEXPR (co->ext.omp_clauses->if_expr);
4850 WALK_SUBEXPR (co->ext.omp_clauses->final_expr);
4851 WALK_SUBEXPR (co->ext.omp_clauses->num_threads);
4852 WALK_SUBEXPR (co->ext.omp_clauses->chunk_size);
4853 WALK_SUBEXPR (co->ext.omp_clauses->safelen_expr);
4854 WALK_SUBEXPR (co->ext.omp_clauses->simdlen_expr);
4855 WALK_SUBEXPR (co->ext.omp_clauses->num_teams);
4856 WALK_SUBEXPR (co->ext.omp_clauses->device);
4857 WALK_SUBEXPR (co->ext.omp_clauses->thread_limit);
4858 WALK_SUBEXPR (co->ext.omp_clauses->dist_chunk_size);
4859 WALK_SUBEXPR (co->ext.omp_clauses->grainsize);
4860 WALK_SUBEXPR (co->ext.omp_clauses->hint);
4861 WALK_SUBEXPR (co->ext.omp_clauses->num_tasks);
4862 WALK_SUBEXPR (co->ext.omp_clauses->priority);
4863 for (idx = 0; idx < OMP_IF_LAST; idx++)
4864 WALK_SUBEXPR (co->ext.omp_clauses->if_exprs[idx]);
4865 for (idx = 0;
4866 idx < sizeof (list_types) / sizeof (list_types[0]);
4867 idx++)
4868 for (n = co->ext.omp_clauses->lists[list_types[idx]];
4869 n; n = n->next)
4870 WALK_SUBEXPR (n->expr);
4872 break;
4873 default:
4874 break;
4877 WALK_SUBEXPR (co->expr1);
4878 WALK_SUBEXPR (co->expr2);
4879 WALK_SUBEXPR (co->expr3);
4880 WALK_SUBEXPR (co->expr4);
4881 for (b = co->block; b; b = b->block)
4883 WALK_SUBEXPR (b->expr1);
4884 WALK_SUBEXPR (b->expr2);
4885 WALK_SUBCODE (b->next);
4888 if (co->op == EXEC_FORALL)
4889 forall_level --;
4891 if (co->op == EXEC_DO)
4892 doloop_level --;
4894 if (co->op == EXEC_IF)
4895 if_level --;
4897 if (co->op == EXEC_SELECT)
4898 select_level --;
4900 in_omp_workshare = saved_in_omp_workshare;
4901 in_where = saved_in_where;
4904 return 0;