xref: /netbsd-src/external/gpl3/gcc/dist/gcc/fortran/frontend-passes.cc (revision 0a3071956a3a9fdebdbf7f338cf2d439b45fc728)
1 /* Pass manager for Fortran front end.
2    Copyright (C) 2010-2022 Free Software Foundation, Inc.
3    Contributed by Thomas König.
4 
5 This file is part of GCC.
6 
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.
11 
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.
16 
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/>.  */
20 
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"
29 
30 /* Forward declarations.  */
31 
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 int call_external_blas (gfc_code **, int *, void *);
57 static int matmul_temp_args (gfc_code **, int *,void *data);
58 static int index_interchange (gfc_code **, int*, void *);
59 static bool is_fe_temp (gfc_expr *e);
60 
61 #ifdef CHECKING_P
62 static void check_locus (gfc_namespace *);
63 #endif
64 
65 /* How deep we are inside an argument list.  */
66 
67 static int count_arglist;
68 
69 /* Vector of gfc_expr ** we operate on.  */
70 
71 static vec<gfc_expr **> expr_array;
72 
73 /* Pointer to the gfc_code we currently work on - to be able to insert
74    a block before the statement.  */
75 
76 static gfc_code **current_code;
77 
78 /* Pointer to the block to be inserted, and the statement we are
79    changing within the block.  */
80 
81 static gfc_code *inserted_block, **changed_statement;
82 
83 /* The namespace we are currently dealing with.  */
84 
85 static gfc_namespace *current_ns;
86 
87 /* If we are within any forall loop.  */
88 
89 static int forall_level;
90 
91 /* Keep track of whether we are within an OMP workshare.  */
92 
93 static bool in_omp_workshare;
94 
95 /* Keep track of whether we are within an OMP atomic.  */
96 
97 static bool in_omp_atomic;
98 
99 /* Keep track of whether we are within a WHERE statement.  */
100 
101 static bool in_where;
102 
103 /* Keep track of iterators for array constructors.  */
104 
105 static int iterator_level;
106 
107 /* Keep track of DO loop levels.  */
108 
109 typedef struct {
110   gfc_code *c;
111   int branch_level;
112   bool seen_goto;
113 } do_t;
114 
115 static vec<do_t> doloop_list;
116 static int doloop_level;
117 
118 /* Keep track of if and select case levels.  */
119 
120 static int if_level;
121 static int select_level;
122 
123 /* Vector of gfc_expr * to keep track of DO loops.  */
124 
125 struct my_struct *evec;
126 
127 /* Keep track of association lists.  */
128 
129 static bool in_assoc_list;
130 
131 /* Counter for temporary variables.  */
132 
133 static int var_num = 1;
134 
135 /* What sort of matrix we are dealing with when inlining MATMUL.  */
136 
137 enum matrix_case { none=0, A2B2, A2B1, A1B2, A2B2T, A2TB2, A2TB2T };
138 
139 /* Keep track of the number of expressions we have inserted so far
140    using create_var.  */
141 
142 int n_vars;
143 
144 /* Entry point - run all passes for a namespace.  */
145 
146 void
gfc_run_passes(gfc_namespace * ns)147 gfc_run_passes (gfc_namespace *ns)
148 {
149 
150   /* Warn about dubious DO loops where the index might
151      change.  */
152 
153   doloop_level = 0;
154   if_level = 0;
155   select_level = 0;
156   doloop_warn (ns);
157   doloop_list.release ();
158   int w, e;
159 
160 #ifdef CHECKING_P
161   check_locus (ns);
162 #endif
163 
164   gfc_get_errors (&w, &e);
165   if (e > 0)
166     return;
167 
168   if (flag_frontend_optimize || flag_frontend_loop_interchange)
169     optimize_namespace (ns);
170 
171   if (flag_frontend_optimize)
172     {
173       optimize_reduction (ns);
174       if (flag_dump_fortran_optimized)
175 	gfc_dump_parse_tree (ns, stdout);
176 
177       expr_array.release ();
178     }
179 
180   if (flag_realloc_lhs)
181     realloc_strings (ns);
182 }
183 
184 #ifdef CHECKING_P
185 
186 /* Callback function: Warn if there is no location information in a
187    statement.  */
188 
189 static int
check_locus_code(gfc_code ** c,int * walk_subtrees ATTRIBUTE_UNUSED,void * data ATTRIBUTE_UNUSED)190 check_locus_code (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
191 		  void *data ATTRIBUTE_UNUSED)
192 {
193   current_code = c;
194   if (c && *c && (((*c)->loc.nextc == NULL) || ((*c)->loc.lb == NULL)))
195     gfc_warning_internal (0, "Inconsistent internal state: "
196 			  "No location in statement");
197 
198   return 0;
199 }
200 
201 
202 /* Callback function: Warn if there is no location information in an
203    expression.  */
204 
205 static int
check_locus_expr(gfc_expr ** e,int * walk_subtrees ATTRIBUTE_UNUSED,void * data ATTRIBUTE_UNUSED)206 check_locus_expr (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
207 		  void *data ATTRIBUTE_UNUSED)
208 {
209 
210   if (e && *e && (((*e)->where.nextc == NULL || (*e)->where.lb == NULL)))
211     gfc_warning_internal (0, "Inconsistent internal state: "
212 			  "No location in expression near %L",
213 			  &((*current_code)->loc));
214   return 0;
215 }
216 
217 /* Run check for missing location information.  */
218 
219 static void
check_locus(gfc_namespace * ns)220 check_locus (gfc_namespace *ns)
221 {
222   gfc_code_walker (&ns->code, check_locus_code, check_locus_expr, NULL);
223 
224   for (ns = ns->contained; ns; ns = ns->sibling)
225     {
226       if (ns->code == NULL || ns->code->op != EXEC_BLOCK)
227 	check_locus (ns);
228     }
229 }
230 
231 #endif
232 
233 /* Callback for each gfc_code node invoked from check_realloc_strings.
234    For an allocatable LHS string which also appears as a variable on
235    the RHS, replace
236 
237    a = a(x:y)
238 
239    with
240 
241    tmp = a(x:y)
242    a = tmp
243  */
244 
245 static int
realloc_string_callback(gfc_code ** c,int * walk_subtrees ATTRIBUTE_UNUSED,void * data ATTRIBUTE_UNUSED)246 realloc_string_callback (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
247 			 void *data ATTRIBUTE_UNUSED)
248 {
249   gfc_expr *expr1, *expr2;
250   gfc_code *co = *c;
251   gfc_expr *n;
252   gfc_ref *ref;
253   bool found_substr;
254 
255   if (co->op != EXEC_ASSIGN)
256     return 0;
257 
258   expr1 = co->expr1;
259   if (expr1->ts.type != BT_CHARACTER
260       || !gfc_expr_attr(expr1).allocatable
261       || !expr1->ts.deferred)
262     return 0;
263 
264   if (is_fe_temp (expr1))
265     return 0;
266 
267   expr2 = gfc_discard_nops (co->expr2);
268 
269   if (expr2->expr_type == EXPR_VARIABLE)
270     {
271       found_substr = false;
272       for (ref = expr2->ref; ref; ref = ref->next)
273 	{
274 	  if (ref->type == REF_SUBSTRING)
275 	    {
276 	      found_substr = true;
277 	      break;
278 	    }
279 	}
280       if (!found_substr)
281 	return 0;
282     }
283   else if (expr2->expr_type != EXPR_ARRAY
284 	   && (expr2->expr_type != EXPR_OP
285 	       || expr2->value.op.op != INTRINSIC_CONCAT))
286     return 0;
287 
288   if (!gfc_check_dependency (expr1, expr2, true))
289     return 0;
290 
291   /* gfc_check_dependency doesn't always pick up identical expressions.
292      However, eliminating the above sends the compiler into an infinite
293      loop on valid expressions.  Without this check, the gimplifier emits
294      an ICE for a = a, where a is deferred character length.  */
295   if (!gfc_dep_compare_expr (expr1, expr2))
296     return 0;
297 
298   current_code = c;
299   inserted_block = NULL;
300   changed_statement = NULL;
301   n = create_var (expr2, "realloc_string");
302   co->expr2 = n;
303   return 0;
304 }
305 
306 /* Callback for each gfc_code node invoked through gfc_code_walker
307    from optimize_namespace.  */
308 
309 static int
optimize_code(gfc_code ** c,int * walk_subtrees ATTRIBUTE_UNUSED,void * data ATTRIBUTE_UNUSED)310 optimize_code (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
311 	       void *data ATTRIBUTE_UNUSED)
312 {
313 
314   gfc_exec_op op;
315 
316   op = (*c)->op;
317 
318   if (op == EXEC_CALL || op == EXEC_COMPCALL || op == EXEC_ASSIGN_CALL
319       || op == EXEC_CALL_PPC)
320     count_arglist = 1;
321   else
322     count_arglist = 0;
323 
324   current_code = c;
325   inserted_block = NULL;
326   changed_statement = NULL;
327 
328   if (op == EXEC_ASSIGN)
329     optimize_assignment (*c);
330   return 0;
331 }
332 
333 /* Callback for each gfc_expr node invoked through gfc_code_walker
334    from optimize_namespace.  */
335 
336 static int
optimize_expr(gfc_expr ** e,int * walk_subtrees ATTRIBUTE_UNUSED,void * data ATTRIBUTE_UNUSED)337 optimize_expr (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
338 	       void *data ATTRIBUTE_UNUSED)
339 {
340   bool function_expr;
341 
342   if ((*e)->expr_type == EXPR_FUNCTION)
343     {
344       count_arglist ++;
345       function_expr = true;
346     }
347   else
348     function_expr = false;
349 
350   if (optimize_trim (*e))
351     gfc_simplify_expr (*e, 0);
352 
353   if (optimize_lexical_comparison (*e))
354     gfc_simplify_expr (*e, 0);
355 
356   if ((*e)->expr_type == EXPR_OP && optimize_op (*e))
357     gfc_simplify_expr (*e, 0);
358 
359   if ((*e)->expr_type == EXPR_FUNCTION && (*e)->value.function.isym)
360     switch ((*e)->value.function.isym->id)
361       {
362       case GFC_ISYM_MINLOC:
363       case GFC_ISYM_MAXLOC:
364 	optimize_minmaxloc (e);
365 	break;
366       default:
367 	break;
368       }
369 
370   if (function_expr)
371     count_arglist --;
372 
373   return 0;
374 }
375 
376 /* Auxiliary function to handle the arguments to reduction intrinsics.  If the
377    function is a scalar, just copy it; otherwise returns the new element, the
378    old one can be freed.  */
379 
380 static gfc_expr *
copy_walk_reduction_arg(gfc_constructor * c,gfc_expr * fn)381 copy_walk_reduction_arg (gfc_constructor *c, gfc_expr *fn)
382 {
383   gfc_expr *fcn, *e = c->expr;
384 
385   fcn = gfc_copy_expr (e);
386   if (c->iterator)
387     {
388       gfc_constructor_base newbase;
389       gfc_expr *new_expr;
390       gfc_constructor *new_c;
391 
392       newbase = NULL;
393       new_expr = gfc_get_expr ();
394       new_expr->expr_type = EXPR_ARRAY;
395       new_expr->ts = e->ts;
396       new_expr->where = e->where;
397       new_expr->rank = 1;
398       new_c = gfc_constructor_append_expr (&newbase, fcn, &(e->where));
399       new_c->iterator = c->iterator;
400       new_expr->value.constructor = newbase;
401       c->iterator = NULL;
402 
403       fcn = new_expr;
404     }
405 
406   if (fcn->rank != 0)
407     {
408       gfc_isym_id id = fn->value.function.isym->id;
409 
410       if (id == GFC_ISYM_SUM || id == GFC_ISYM_PRODUCT)
411 	fcn = gfc_build_intrinsic_call (current_ns, id,
412 					fn->value.function.isym->name,
413 					fn->where, 3, fcn, NULL, NULL);
414       else if (id == GFC_ISYM_ANY || id == GFC_ISYM_ALL)
415 	fcn = gfc_build_intrinsic_call (current_ns, id,
416 					fn->value.function.isym->name,
417 					fn->where, 2, fcn, NULL);
418       else
419 	gfc_internal_error ("Illegal id in copy_walk_reduction_arg");
420 
421       fcn->symtree->n.sym->attr.access = ACCESS_PRIVATE;
422     }
423 
424   return fcn;
425 }
426 
427 /* Callback function for optimzation of reductions to scalars.  Transform ANY
428    ([f1,f2,f3, ...]) to f1 .or. f2 .or. f3 .or. ..., with ANY, SUM and PRODUCT
429    correspondingly.  Handly only the simple cases without MASK and DIM.  */
430 
431 static int
callback_reduction(gfc_expr ** e,int * walk_subtrees ATTRIBUTE_UNUSED,void * data ATTRIBUTE_UNUSED)432 callback_reduction (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
433 		    void *data ATTRIBUTE_UNUSED)
434 {
435   gfc_expr *fn, *arg;
436   gfc_intrinsic_op op;
437   gfc_isym_id id;
438   gfc_actual_arglist *a;
439   gfc_actual_arglist *dim;
440   gfc_constructor *c;
441   gfc_expr *res, *new_expr;
442   gfc_actual_arglist *mask;
443 
444   fn = *e;
445 
446   if (fn->rank != 0 || fn->expr_type != EXPR_FUNCTION
447       || fn->value.function.isym == NULL)
448     return 0;
449 
450   id = fn->value.function.isym->id;
451 
452   if (id != GFC_ISYM_SUM && id != GFC_ISYM_PRODUCT
453       && id != GFC_ISYM_ANY && id != GFC_ISYM_ALL)
454     return 0;
455 
456   a = fn->value.function.actual;
457 
458   /* Don't handle MASK or DIM.  */
459 
460   dim = a->next;
461 
462   if (dim->expr != NULL)
463     return 0;
464 
465   if (id == GFC_ISYM_SUM || id == GFC_ISYM_PRODUCT)
466     {
467       mask = dim->next;
468       if ( mask->expr != NULL)
469 	return 0;
470     }
471 
472   arg = a->expr;
473 
474   if (arg->expr_type != EXPR_ARRAY)
475     return 0;
476 
477   switch (id)
478     {
479     case GFC_ISYM_SUM:
480       op = INTRINSIC_PLUS;
481       break;
482 
483     case GFC_ISYM_PRODUCT:
484       op = INTRINSIC_TIMES;
485       break;
486 
487     case GFC_ISYM_ANY:
488       op = INTRINSIC_OR;
489       break;
490 
491     case GFC_ISYM_ALL:
492       op = INTRINSIC_AND;
493       break;
494 
495     default:
496       return 0;
497     }
498 
499   c = gfc_constructor_first (arg->value.constructor);
500 
501   /* Don't do any simplififcation if we have
502      - no element in the constructor or
503      - only have a single element in the array which contains an
504      iterator.  */
505 
506   if (c == NULL)
507     return 0;
508 
509   res = copy_walk_reduction_arg (c, fn);
510 
511   c = gfc_constructor_next (c);
512   while (c)
513     {
514       new_expr = gfc_get_expr ();
515       new_expr->ts = fn->ts;
516       new_expr->expr_type = EXPR_OP;
517       new_expr->rank = fn->rank;
518       new_expr->where = fn->where;
519       new_expr->value.op.op = op;
520       new_expr->value.op.op1 = res;
521       new_expr->value.op.op2 = copy_walk_reduction_arg (c, fn);
522       res = new_expr;
523       c = gfc_constructor_next (c);
524     }
525 
526   gfc_simplify_expr (res, 0);
527   *e = res;
528   gfc_free_expr (fn);
529 
530   return 0;
531 }
532 
533 /* Callback function for common function elimination, called from cfe_expr_0.
534    Put all eligible function expressions into expr_array.  */
535 
536 static int
cfe_register_funcs(gfc_expr ** e,int * walk_subtrees ATTRIBUTE_UNUSED,void * data ATTRIBUTE_UNUSED)537 cfe_register_funcs (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
538 	  void *data ATTRIBUTE_UNUSED)
539 {
540 
541   if ((*e)->expr_type != EXPR_FUNCTION)
542     return 0;
543 
544   /* We don't do character functions with unknown charlens.  */
545   if ((*e)->ts.type == BT_CHARACTER
546       && ((*e)->ts.u.cl == NULL || (*e)->ts.u.cl->length == NULL
547 	  || (*e)->ts.u.cl->length->expr_type != EXPR_CONSTANT))
548     return 0;
549 
550   /* We don't do function elimination within FORALL statements, it can
551      lead to wrong-code in certain circumstances.  */
552 
553   if (forall_level > 0)
554     return 0;
555 
556   /* Function elimination inside an iterator could lead to functions which
557      depend on iterator variables being moved outside.  FIXME: We should check
558      if the functions do indeed depend on the iterator variable.  */
559 
560   if (iterator_level > 0)
561     return 0;
562 
563   /* If we don't know the shape at compile time, we create an allocatable
564      temporary variable to hold the intermediate result, but only if
565      allocation on assignment is active.  */
566 
567   if ((*e)->rank > 0 && (*e)->shape == NULL && !flag_realloc_lhs)
568     return 0;
569 
570   /* Skip the test for pure functions if -faggressive-function-elimination
571      is specified.  */
572   if ((*e)->value.function.esym)
573     {
574       /* Don't create an array temporary for elemental functions.  */
575       if ((*e)->value.function.esym->attr.elemental && (*e)->rank > 0)
576 	return 0;
577 
578       /* Only eliminate potentially impure functions if the
579 	 user specifically requested it.  */
580       if (!flag_aggressive_function_elimination
581 	  && !(*e)->value.function.esym->attr.pure
582 	  && !(*e)->value.function.esym->attr.implicit_pure)
583 	return 0;
584     }
585 
586   if ((*e)->value.function.isym)
587     {
588       /* Conversions are handled on the fly by the middle end,
589 	 transpose during trans-* stages and TRANSFER by the middle end.  */
590       if ((*e)->value.function.isym->id == GFC_ISYM_CONVERSION
591 	  || (*e)->value.function.isym->id == GFC_ISYM_TRANSFER
592 	  || gfc_inline_intrinsic_function_p (*e))
593 	return 0;
594 
595       /* Don't create an array temporary for elemental functions,
596 	 as this would be wasteful of memory.
597 	 FIXME: Create a scalar temporary during scalarization.  */
598       if ((*e)->value.function.isym->elemental && (*e)->rank > 0)
599 	return 0;
600 
601       if (!(*e)->value.function.isym->pure)
602 	return 0;
603     }
604 
605   expr_array.safe_push (e);
606   return 0;
607 }
608 
609 /* Auxiliary function to check if an expression is a temporary created by
610    create var.  */
611 
612 static bool
is_fe_temp(gfc_expr * e)613 is_fe_temp (gfc_expr *e)
614 {
615   if (e->expr_type != EXPR_VARIABLE)
616     return false;
617 
618   return e->symtree->n.sym->attr.fe_temp;
619 }
620 
621 /* Determine the length of a string, if it can be evaluated as a constant
622    expression.  Return a newly allocated gfc_expr or NULL on failure.
623    If the user specified a substring which is potentially longer than
624    the string itself, the string will be padded with spaces, which
625    is harmless.  */
626 
627 static gfc_expr *
constant_string_length(gfc_expr * e)628 constant_string_length (gfc_expr *e)
629 {
630 
631   gfc_expr *length;
632   gfc_ref *ref;
633   gfc_expr *res;
634   mpz_t value;
635 
636   if (e->ts.u.cl)
637     {
638       length = e->ts.u.cl->length;
639       if (length && length->expr_type == EXPR_CONSTANT)
640 	return gfc_copy_expr(length);
641     }
642 
643   /* See if there is a substring. If it has a constant length, return
644      that and NULL otherwise.  */
645   for (ref = e->ref; ref; ref = ref->next)
646     {
647       if (ref->type == REF_SUBSTRING)
648 	{
649 	  if (gfc_dep_difference (ref->u.ss.end, ref->u.ss.start, &value))
650 	    {
651 	      res = gfc_get_constant_expr (BT_INTEGER, gfc_charlen_int_kind,
652 					   &e->where);
653 
654 	      mpz_add_ui (res->value.integer, value, 1);
655 	      mpz_clear (value);
656 	      return res;
657 	    }
658 	  else
659 	    return NULL;
660 	}
661     }
662 
663   /* Return length of char symbol, if constant.  */
664   if (e->symtree && e->symtree->n.sym->ts.u.cl
665       && e->symtree->n.sym->ts.u.cl->length
666       && e->symtree->n.sym->ts.u.cl->length->expr_type == EXPR_CONSTANT)
667     return gfc_copy_expr (e->symtree->n.sym->ts.u.cl->length);
668 
669   return NULL;
670 
671 }
672 
673 /* Insert a block at the current position unless it has already
674    been inserted; in this case use the one already there.  */
675 
676 static gfc_namespace*
insert_block()677 insert_block ()
678 {
679   gfc_namespace *ns;
680 
681   /* If the block hasn't already been created, do so.  */
682   if (inserted_block == NULL)
683     {
684       inserted_block = XCNEW (gfc_code);
685       inserted_block->op = EXEC_BLOCK;
686       inserted_block->loc = (*current_code)->loc;
687       ns = gfc_build_block_ns (current_ns);
688       inserted_block->ext.block.ns = ns;
689       inserted_block->ext.block.assoc = NULL;
690 
691       ns->code = *current_code;
692 
693       /* If the statement has a label,  make sure it is transferred to
694 	 the newly created block.  */
695 
696       if ((*current_code)->here)
697 	{
698 	  inserted_block->here = (*current_code)->here;
699 	  (*current_code)->here = NULL;
700 	}
701 
702       inserted_block->next = (*current_code)->next;
703       changed_statement = &(inserted_block->ext.block.ns->code);
704       (*current_code)->next = NULL;
705       /* Insert the BLOCK at the right position.  */
706       *current_code = inserted_block;
707       ns->parent = current_ns;
708     }
709   else
710     ns = inserted_block->ext.block.ns;
711 
712   return ns;
713 }
714 
715 
716 /* Insert a call to the intrinsic len. Use a different name for
717    the symbol tree so we don't run into trouble when the user has
718    renamed len for some reason.  */
719 
720 static gfc_expr*
get_len_call(gfc_expr * str)721 get_len_call (gfc_expr *str)
722 {
723   gfc_expr *fcn;
724   gfc_actual_arglist *actual_arglist;
725 
726   fcn = gfc_get_expr ();
727   fcn->expr_type = EXPR_FUNCTION;
728   fcn->value.function.isym = gfc_intrinsic_function_by_id (GFC_ISYM_LEN);
729   actual_arglist = gfc_get_actual_arglist ();
730   actual_arglist->expr = str;
731 
732   fcn->value.function.actual = actual_arglist;
733   fcn->where = str->where;
734   fcn->ts.type = BT_INTEGER;
735   fcn->ts.kind = gfc_charlen_int_kind;
736 
737   gfc_get_sym_tree ("__internal_len", current_ns, &fcn->symtree, false);
738   fcn->symtree->n.sym->ts = fcn->ts;
739   fcn->symtree->n.sym->attr.flavor = FL_PROCEDURE;
740   fcn->symtree->n.sym->attr.function = 1;
741   fcn->symtree->n.sym->attr.elemental = 1;
742   fcn->symtree->n.sym->attr.referenced = 1;
743   fcn->symtree->n.sym->attr.access = ACCESS_PRIVATE;
744   gfc_commit_symbol (fcn->symtree->n.sym);
745 
746   return fcn;
747 }
748 
749 
750 /* Returns a new expression (a variable) to be used in place of the old one,
751    with an optional assignment statement before the current statement to set
752    the value of the variable. Creates a new BLOCK for the statement if that
753    hasn't already been done and puts the statement, plus the newly created
754    variables, in that block.  Special cases: If the expression is constant or
755    a temporary which has already been created, just copy it.  */
756 
757 static gfc_expr*
create_var(gfc_expr * e,const char * vname)758 create_var (gfc_expr * e, const char *vname)
759 {
760   char name[GFC_MAX_SYMBOL_LEN +1];
761   gfc_symtree *symtree;
762   gfc_symbol *symbol;
763   gfc_expr *result;
764   gfc_code *n;
765   gfc_namespace *ns;
766   int i;
767   bool deferred;
768 
769   if (e->expr_type == EXPR_CONSTANT || is_fe_temp (e))
770     return gfc_copy_expr (e);
771 
772   /* Creation of an array of unknown size requires realloc on assignment.
773      If that is not possible, just return NULL.  */
774   if (flag_realloc_lhs == 0 && e->rank > 0 && e->shape == NULL)
775     return NULL;
776 
777   ns = insert_block ();
778 
779   if (vname)
780     snprintf (name, GFC_MAX_SYMBOL_LEN, "__var_%d_%s", var_num++, vname);
781   else
782     snprintf (name, GFC_MAX_SYMBOL_LEN, "__var_%d", var_num++);
783 
784   if (gfc_get_sym_tree (name, ns, &symtree, false) != 0)
785     gcc_unreachable ();
786 
787   symbol = symtree->n.sym;
788   symbol->ts = e->ts;
789 
790   if (e->rank > 0)
791     {
792       symbol->as = gfc_get_array_spec ();
793       symbol->as->rank = e->rank;
794 
795       if (e->shape == NULL)
796 	{
797 	  /* We don't know the shape at compile time, so we use an
798 	     allocatable.  */
799 	  symbol->as->type = AS_DEFERRED;
800 	  symbol->attr.allocatable = 1;
801 	}
802       else
803 	{
804 	  symbol->as->type = AS_EXPLICIT;
805 	  /* Copy the shape.  */
806 	  for (i=0; i<e->rank; i++)
807 	    {
808 	      gfc_expr *p, *q;
809 
810 	      p = gfc_get_constant_expr (BT_INTEGER, gfc_default_integer_kind,
811 					 &(e->where));
812 	      mpz_set_si (p->value.integer, 1);
813 	      symbol->as->lower[i] = p;
814 
815 	      q = gfc_get_constant_expr (BT_INTEGER, gfc_index_integer_kind,
816 					 &(e->where));
817 	      mpz_set (q->value.integer, e->shape[i]);
818 	      symbol->as->upper[i] = q;
819 	    }
820 	}
821     }
822 
823   deferred = 0;
824   if (e->ts.type == BT_CHARACTER)
825     {
826       gfc_expr *length;
827 
828       symbol->ts.u.cl = gfc_new_charlen (ns, NULL);
829       length = constant_string_length (e);
830       if (length)
831 	symbol->ts.u.cl->length = length;
832       else if (e->expr_type == EXPR_VARIABLE
833 	       && e->symtree->n.sym->ts.type == BT_CHARACTER
834 	       && e->ts.u.cl->length)
835 	symbol->ts.u.cl->length = get_len_call (gfc_copy_expr (e));
836       else
837 	{
838 	  symbol->attr.allocatable = 1;
839 	  symbol->ts.u.cl->length = NULL;
840 	  symbol->ts.deferred = 1;
841 	  deferred = 1;
842 	}
843     }
844 
845   symbol->attr.flavor = FL_VARIABLE;
846   symbol->attr.referenced = 1;
847   symbol->attr.dimension = e->rank > 0;
848   symbol->attr.fe_temp = 1;
849   gfc_commit_symbol (symbol);
850 
851   result = gfc_get_expr ();
852   result->expr_type = EXPR_VARIABLE;
853   result->ts = symbol->ts;
854   result->ts.deferred = deferred;
855   result->rank = e->rank;
856   result->shape = gfc_copy_shape (e->shape, e->rank);
857   result->symtree = symtree;
858   result->where = e->where;
859   if (e->rank > 0)
860     {
861       result->ref = gfc_get_ref ();
862       result->ref->type = REF_ARRAY;
863       result->ref->u.ar.type = AR_FULL;
864       result->ref->u.ar.where = e->where;
865       result->ref->u.ar.dimen = e->rank;
866       result->ref->u.ar.as = symbol->ts.type == BT_CLASS
867 			     ? CLASS_DATA (symbol)->as : symbol->as;
868       if (warn_array_temporaries)
869 	gfc_warning (OPT_Warray_temporaries,
870 		     "Creating array temporary at %L", &(e->where));
871     }
872 
873   /* Generate the new assignment.  */
874   n = XCNEW (gfc_code);
875   n->op = EXEC_ASSIGN;
876   n->loc = (*current_code)->loc;
877   n->next = *changed_statement;
878   n->expr1 = gfc_copy_expr (result);
879   n->expr2 = e;
880   *changed_statement = n;
881   n_vars ++;
882 
883   return result;
884 }
885 
886 /* Warn about function elimination.  */
887 
888 static void
do_warn_function_elimination(gfc_expr * e)889 do_warn_function_elimination (gfc_expr *e)
890 {
891   const char *name;
892   if (e->expr_type == EXPR_FUNCTION
893       && !gfc_pure_function (e, &name) && !gfc_implicit_pure_function (e))
894    {
895       if (name)
896 	  gfc_warning (OPT_Wfunction_elimination,
897 		      "Removing call to impure function %qs at %L", name,
898 		      &(e->where));
899       else
900 	  gfc_warning (OPT_Wfunction_elimination,
901 		      "Removing call to impure function at %L",
902 		      &(e->where));
903    }
904 }
905 
906 
907 /* Callback function for the code walker for doing common function
908    elimination.  This builds up the list of functions in the expression
909    and goes through them to detect duplicates, which it then replaces
910    by variables.  */
911 
912 static int
cfe_expr_0(gfc_expr ** e,int * walk_subtrees,void * data ATTRIBUTE_UNUSED)913 cfe_expr_0 (gfc_expr **e, int *walk_subtrees,
914 	  void *data ATTRIBUTE_UNUSED)
915 {
916   int i,j;
917   gfc_expr *newvar;
918   gfc_expr **ei, **ej;
919 
920   /* Don't do this optimization within OMP workshare/atomic or ASSOC lists.  */
921 
922   if (in_omp_workshare || in_omp_atomic || in_assoc_list)
923     {
924       *walk_subtrees = 0;
925       return 0;
926     }
927 
928   expr_array.release ();
929 
930   gfc_expr_walker (e, cfe_register_funcs, NULL);
931 
932   /* Walk through all the functions.  */
933 
934   FOR_EACH_VEC_ELT_FROM (expr_array, i, ei, 1)
935     {
936       /* Skip if the function has been replaced by a variable already.  */
937       if ((*ei)->expr_type == EXPR_VARIABLE)
938 	continue;
939 
940       newvar = NULL;
941       for (j=0; j<i; j++)
942 	{
943 	  ej = expr_array[j];
944 	  if (gfc_dep_compare_functions (*ei, *ej, true) == 0)
945 	    {
946 	      if (newvar == NULL)
947 		newvar = create_var (*ei, "fcn");
948 
949 	      if (warn_function_elimination)
950 		do_warn_function_elimination (*ej);
951 
952 	      free (*ej);
953 	      *ej = gfc_copy_expr (newvar);
954 	    }
955 	}
956       if (newvar)
957 	*ei = newvar;
958     }
959 
960   /* We did all the necessary walking in this function.  */
961   *walk_subtrees = 0;
962   return 0;
963 }
964 
965 /* Callback function for common function elimination, called from
966    gfc_code_walker.  This keeps track of the current code, in order
967    to insert statements as needed.  */
968 
969 static int
cfe_code(gfc_code ** c,int * walk_subtrees,void * data ATTRIBUTE_UNUSED)970 cfe_code (gfc_code **c, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
971 {
972   current_code = c;
973   inserted_block = NULL;
974   changed_statement = NULL;
975 
976   /* Do not do anything inside a WHERE statement; scalar assignments, BLOCKs
977      and allocation on assignment are prohibited inside WHERE, and finally
978      masking an expression would lead to wrong-code when replacing
979 
980      WHERE (a>0)
981        b = sum(foo(a) + foo(a))
982      END WHERE
983 
984      with
985 
986      WHERE (a > 0)
987        tmp = foo(a)
988        b = sum(tmp + tmp)
989      END WHERE
990 */
991 
992   if ((*c)->op == EXEC_WHERE)
993     {
994       *walk_subtrees = 0;
995       return 0;
996     }
997 
998 
999   return 0;
1000 }
1001 
1002 /* Dummy function for expression call back, for use when we
1003    really don't want to do any walking.  */
1004 
1005 static int
dummy_expr_callback(gfc_expr ** e ATTRIBUTE_UNUSED,int * walk_subtrees,void * data ATTRIBUTE_UNUSED)1006 dummy_expr_callback (gfc_expr **e ATTRIBUTE_UNUSED, int *walk_subtrees,
1007 		     void *data ATTRIBUTE_UNUSED)
1008 {
1009   *walk_subtrees = 0;
1010   return 0;
1011 }
1012 
1013 /* Dummy function for code callback, for use when we really
1014    don't want to do anything.  */
1015 int
gfc_dummy_code_callback(gfc_code ** e ATTRIBUTE_UNUSED,int * walk_subtrees ATTRIBUTE_UNUSED,void * data ATTRIBUTE_UNUSED)1016 gfc_dummy_code_callback (gfc_code **e ATTRIBUTE_UNUSED,
1017 			 int *walk_subtrees ATTRIBUTE_UNUSED,
1018 			 void *data ATTRIBUTE_UNUSED)
1019 {
1020   return 0;
1021 }
1022 
1023 /* Code callback function for converting
1024    do while(a)
1025    end do
1026    into the equivalent
1027    do
1028      if (.not. a) exit
1029    end do
1030    This is because common function elimination would otherwise place the
1031    temporary variables outside the loop.  */
1032 
1033 static int
convert_do_while(gfc_code ** c,int * walk_subtrees ATTRIBUTE_UNUSED,void * data ATTRIBUTE_UNUSED)1034 convert_do_while (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
1035 		  void *data ATTRIBUTE_UNUSED)
1036 {
1037   gfc_code *co = *c;
1038   gfc_code *c_if1, *c_if2, *c_exit;
1039   gfc_code *loopblock;
1040   gfc_expr *e_not, *e_cond;
1041 
1042   if (co->op != EXEC_DO_WHILE)
1043     return 0;
1044 
1045   if (co->expr1 == NULL || co->expr1->expr_type == EXPR_CONSTANT)
1046     return 0;
1047 
1048   e_cond = co->expr1;
1049 
1050   /* Generate the condition of the if statement, which is .not. the original
1051      statement.  */
1052   e_not = gfc_get_expr ();
1053   e_not->ts = e_cond->ts;
1054   e_not->where = e_cond->where;
1055   e_not->expr_type = EXPR_OP;
1056   e_not->value.op.op = INTRINSIC_NOT;
1057   e_not->value.op.op1 = e_cond;
1058 
1059   /* Generate the EXIT statement.  */
1060   c_exit = XCNEW (gfc_code);
1061   c_exit->op = EXEC_EXIT;
1062   c_exit->ext.which_construct = co;
1063   c_exit->loc = co->loc;
1064 
1065   /* Generate the IF statement.  */
1066   c_if2 = XCNEW (gfc_code);
1067   c_if2->op = EXEC_IF;
1068   c_if2->expr1 = e_not;
1069   c_if2->next = c_exit;
1070   c_if2->loc = co->loc;
1071 
1072   /* ... plus the one to chain it to.  */
1073   c_if1 = XCNEW (gfc_code);
1074   c_if1->op = EXEC_IF;
1075   c_if1->block = c_if2;
1076   c_if1->loc = co->loc;
1077 
1078   /* Make the DO WHILE loop into a DO block by replacing the condition
1079      with a true constant.  */
1080   co->expr1 = gfc_get_logical_expr (gfc_default_integer_kind, &co->loc, true);
1081 
1082   /* Hang the generated if statement into the loop body.  */
1083 
1084   loopblock = co->block->next;
1085   co->block->next = c_if1;
1086   c_if1->next = loopblock;
1087 
1088   return 0;
1089 }
1090 
1091 /* Code callback function for converting
1092    if (a) then
1093    ...
1094    else if (b) then
1095    end if
1096 
1097    into
1098    if (a) then
1099    else
1100      if (b) then
1101      end if
1102    end if
1103 
1104    because otherwise common function elimination would place the BLOCKs
1105    into the wrong place.  */
1106 
1107 static int
convert_elseif(gfc_code ** c,int * walk_subtrees ATTRIBUTE_UNUSED,void * data ATTRIBUTE_UNUSED)1108 convert_elseif (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
1109 		void *data ATTRIBUTE_UNUSED)
1110 {
1111   gfc_code *co = *c;
1112   gfc_code *c_if1, *c_if2, *else_stmt;
1113 
1114   if (co->op != EXEC_IF)
1115     return 0;
1116 
1117   /* This loop starts out with the first ELSE statement.  */
1118   else_stmt = co->block->block;
1119 
1120   while (else_stmt != NULL)
1121     {
1122       gfc_code *next_else;
1123 
1124       /* If there is no condition, we're done.  */
1125       if (else_stmt->expr1 == NULL)
1126 	break;
1127 
1128       next_else = else_stmt->block;
1129 
1130       /* Generate the new IF statement.  */
1131       c_if2 = XCNEW (gfc_code);
1132       c_if2->op = EXEC_IF;
1133       c_if2->expr1 = else_stmt->expr1;
1134       c_if2->next = else_stmt->next;
1135       c_if2->loc = else_stmt->loc;
1136       c_if2->block = next_else;
1137 
1138       /* ... plus the one to chain it to.  */
1139       c_if1 = XCNEW (gfc_code);
1140       c_if1->op = EXEC_IF;
1141       c_if1->block = c_if2;
1142       c_if1->loc = else_stmt->loc;
1143 
1144       /* Insert the new IF after the ELSE.  */
1145       else_stmt->expr1 = NULL;
1146       else_stmt->next = c_if1;
1147       else_stmt->block = NULL;
1148 
1149       else_stmt = next_else;
1150     }
1151   /*  Don't walk subtrees.  */
1152   return 0;
1153 }
1154 
1155 /* Callback function to var_in_expr - return true if expr1 and
1156    expr2 are identical variables. */
1157 static int
var_in_expr_callback(gfc_expr ** e,int * walk_subtrees ATTRIBUTE_UNUSED,void * data)1158 var_in_expr_callback (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
1159 		      void *data)
1160 {
1161   gfc_expr *expr1 = (gfc_expr *) data;
1162   gfc_expr *expr2 = *e;
1163 
1164   if (expr2->expr_type != EXPR_VARIABLE)
1165     return 0;
1166 
1167   return expr1->symtree->n.sym == expr2->symtree->n.sym;
1168 }
1169 
1170 /* Return true if expr1 is found in expr2. */
1171 
1172 static bool
var_in_expr(gfc_expr * expr1,gfc_expr * expr2)1173 var_in_expr (gfc_expr *expr1, gfc_expr *expr2)
1174 {
1175   gcc_assert (expr1->expr_type == EXPR_VARIABLE);
1176 
1177   return gfc_expr_walker (&expr2, var_in_expr_callback, (void *) expr1);
1178 }
1179 
1180 struct do_stack
1181 {
1182   struct do_stack *prev;
1183   gfc_iterator *iter;
1184   gfc_code *code;
1185 } *stack_top;
1186 
1187 /* Recursively traverse the block of a WRITE or READ statement, and maybe
1188    optimize by replacing do loops with their analog array slices.  For
1189    example:
1190 
1191      write (*,*) (a(i), i=1,4)
1192 
1193    is replaced with
1194 
1195      write (*,*) a(1:4:1) .  */
1196 
1197 static bool
traverse_io_block(gfc_code * code,bool * has_reached,gfc_code * prev)1198 traverse_io_block (gfc_code *code, bool *has_reached, gfc_code *prev)
1199 {
1200   gfc_code *curr;
1201   gfc_expr *new_e, *expr, *start;
1202   gfc_ref *ref;
1203   struct do_stack ds_push;
1204   int i, future_rank = 0;
1205   gfc_iterator *iters[GFC_MAX_DIMENSIONS];
1206   gfc_expr *e;
1207 
1208   /* Find the first transfer/do statement.  */
1209   for (curr = code; curr; curr = curr->next)
1210     {
1211       if (curr->op == EXEC_DO || curr->op == EXEC_TRANSFER)
1212 	break;
1213     }
1214 
1215   /* Ensure it is the only transfer/do statement because cases like
1216 
1217      write (*,*) (a(i), b(i), i=1,4)
1218 
1219      cannot be optimized.  */
1220 
1221   if (!curr || curr->next)
1222     return false;
1223 
1224   if (curr->op == EXEC_DO)
1225     {
1226       if (curr->ext.iterator->var->ref)
1227 	return false;
1228       ds_push.prev = stack_top;
1229       ds_push.iter = curr->ext.iterator;
1230       ds_push.code = curr;
1231       stack_top = &ds_push;
1232       if (traverse_io_block (curr->block->next, has_reached, prev))
1233 	{
1234 	  if (curr != stack_top->code && !*has_reached)
1235 	    {
1236 	      curr->block->next = NULL;
1237 	      gfc_free_statements (curr);
1238 	    }
1239 	  else
1240 	    *has_reached = true;
1241 	  return true;
1242 	}
1243       return false;
1244     }
1245 
1246   gcc_assert (curr->op == EXEC_TRANSFER);
1247 
1248   e = curr->expr1;
1249   ref = e->ref;
1250   if (!ref || ref->type != REF_ARRAY || ref->u.ar.codimen != 0 || ref->next)
1251     return false;
1252 
1253   /* Find the iterators belonging to each variable and check conditions.  */
1254   for (i = 0; i < ref->u.ar.dimen; i++)
1255     {
1256       if (!ref->u.ar.start[i] || ref->u.ar.start[i]->ref
1257 	  || ref->u.ar.dimen_type[i] != DIMEN_ELEMENT)
1258 	return false;
1259 
1260       start = ref->u.ar.start[i];
1261       gfc_simplify_expr (start, 0);
1262       switch (start->expr_type)
1263 	{
1264 	case EXPR_VARIABLE:
1265 
1266 	  /* write (*,*) (a(i), i=a%b,1) not handled yet.  */
1267 	  if (start->ref)
1268 	    return false;
1269 
1270 	  /*  Check for (a(k), i=1,4) or ((a(j, i), i=1,4), j=1,4).  */
1271 	  if (!stack_top || !stack_top->iter
1272 	      || stack_top->iter->var->symtree != start->symtree)
1273 	    {
1274 	      /* Check for (a(i,i), i=1,3).  */
1275 	      int j;
1276 
1277 	      for (j=0; j<i; j++)
1278 		if (iters[j] && iters[j]->var->symtree == start->symtree)
1279 		  return false;
1280 
1281 	      iters[i] = NULL;
1282 	    }
1283 	  else
1284 	    {
1285 	      iters[i] = stack_top->iter;
1286 	      stack_top = stack_top->prev;
1287 	      future_rank++;
1288 	    }
1289 	  break;
1290 	case EXPR_CONSTANT:
1291 	  iters[i] = NULL;
1292 	  break;
1293 	case EXPR_OP:
1294 	  switch (start->value.op.op)
1295 	    {
1296 	    case INTRINSIC_PLUS:
1297 	    case INTRINSIC_TIMES:
1298 	      if (start->value.op.op1->expr_type != EXPR_VARIABLE)
1299 		std::swap (start->value.op.op1, start->value.op.op2);
1300 	      gcc_fallthrough ();
1301 	    case INTRINSIC_MINUS:
1302 	      if (start->value.op.op1->expr_type!= EXPR_VARIABLE
1303 		  || start->value.op.op2->expr_type != EXPR_CONSTANT
1304 		  || start->value.op.op1->ref)
1305 		return false;
1306 	      if (!stack_top || !stack_top->iter
1307 		  || stack_top->iter->var->symtree
1308 		  != start->value.op.op1->symtree)
1309 		return false;
1310 	      iters[i] = stack_top->iter;
1311 	      stack_top = stack_top->prev;
1312 	      break;
1313 	    default:
1314 	      return false;
1315 	    }
1316 	  future_rank++;
1317 	  break;
1318 	default:
1319 	  return false;
1320 	}
1321     }
1322 
1323   /* Check for cases like ((a(i, j), i=1, j), j=1, 2). */
1324   for (int i = 1; i < ref->u.ar.dimen; i++)
1325     {
1326       if (iters[i])
1327 	{
1328 	  gfc_expr *var = iters[i]->var;
1329 	  for (int j = 0; j < i; j++)
1330 	    {
1331 	      if (iters[j]
1332 		  && (var_in_expr (var, iters[j]->start)
1333 		      || var_in_expr (var, iters[j]->end)
1334 		      || var_in_expr (var, iters[j]->step)))
1335 		  return false;
1336 	    }
1337 	}
1338     }
1339 
1340   /* Create new expr.  */
1341   new_e = gfc_copy_expr (curr->expr1);
1342   new_e->expr_type = EXPR_VARIABLE;
1343   new_e->rank = future_rank;
1344   if (curr->expr1->shape)
1345     new_e->shape = gfc_get_shape (new_e->rank);
1346 
1347   /* Assign new starts, ends and strides if necessary.  */
1348   for (i = 0; i < ref->u.ar.dimen; i++)
1349     {
1350       if (!iters[i])
1351 	continue;
1352       start = ref->u.ar.start[i];
1353       switch (start->expr_type)
1354 	{
1355 	case EXPR_CONSTANT:
1356 	  gfc_internal_error ("bad expression");
1357 	  break;
1358 	case EXPR_VARIABLE:
1359 	  new_e->ref->u.ar.dimen_type[i] = DIMEN_RANGE;
1360 	  new_e->ref->u.ar.type = AR_SECTION;
1361 	  gfc_free_expr (new_e->ref->u.ar.start[i]);
1362 	  new_e->ref->u.ar.start[i] = gfc_copy_expr (iters[i]->start);
1363 	  new_e->ref->u.ar.end[i] = gfc_copy_expr (iters[i]->end);
1364 	  new_e->ref->u.ar.stride[i] = gfc_copy_expr (iters[i]->step);
1365 	  break;
1366 	case EXPR_OP:
1367 	  new_e->ref->u.ar.dimen_type[i] = DIMEN_RANGE;
1368 	  new_e->ref->u.ar.type = AR_SECTION;
1369 	  gfc_free_expr (new_e->ref->u.ar.start[i]);
1370 	  expr = gfc_copy_expr (start);
1371 	  expr->value.op.op1 = gfc_copy_expr (iters[i]->start);
1372 	  new_e->ref->u.ar.start[i] = expr;
1373 	  gfc_simplify_expr (new_e->ref->u.ar.start[i], 0);
1374 	  expr = gfc_copy_expr (start);
1375 	  expr->value.op.op1 = gfc_copy_expr (iters[i]->end);
1376 	  new_e->ref->u.ar.end[i] = expr;
1377 	  gfc_simplify_expr (new_e->ref->u.ar.end[i], 0);
1378 	  switch (start->value.op.op)
1379 	    {
1380 	    case INTRINSIC_MINUS:
1381 	    case INTRINSIC_PLUS:
1382 	      new_e->ref->u.ar.stride[i] = gfc_copy_expr (iters[i]->step);
1383 	      break;
1384 	    case INTRINSIC_TIMES:
1385 	      expr = gfc_copy_expr (start);
1386 	      expr->value.op.op1 = gfc_copy_expr (iters[i]->step);
1387 	      new_e->ref->u.ar.stride[i] = expr;
1388 	      gfc_simplify_expr (new_e->ref->u.ar.stride[i], 0);
1389 	      break;
1390 	    default:
1391 	      gfc_internal_error ("bad op");
1392 	    }
1393 	  break;
1394 	default:
1395 	  gfc_internal_error ("bad expression");
1396 	}
1397     }
1398   curr->expr1 = new_e;
1399 
1400   /* Insert modified statement. Check whether the statement needs to be
1401      inserted at the lowest level.  */
1402   if (!stack_top->iter)
1403     {
1404       if (prev)
1405 	{
1406 	  curr->next = prev->next->next;
1407 	  prev->next = curr;
1408 	}
1409       else
1410 	{
1411 	  curr->next = stack_top->code->block->next->next->next;
1412 	  stack_top->code->block->next = curr;
1413 	}
1414     }
1415   else
1416     stack_top->code->block->next = curr;
1417   return true;
1418 }
1419 
1420 /* Function for the gfc_code_walker.  If code is a READ or WRITE statement, it
1421    tries to optimize its block.  */
1422 
1423 static int
simplify_io_impl_do(gfc_code ** code,int * walk_subtrees,void * data ATTRIBUTE_UNUSED)1424 simplify_io_impl_do (gfc_code **code, int *walk_subtrees,
1425 		     void *data ATTRIBUTE_UNUSED)
1426 {
1427   gfc_code **curr, *prev = NULL;
1428   struct do_stack write, first;
1429   bool b = false;
1430   *walk_subtrees = 1;
1431   if (!(*code)->block
1432       || ((*code)->block->op != EXEC_WRITE
1433 	  && (*code)->block->op != EXEC_READ))
1434     return 0;
1435 
1436   *walk_subtrees = 0;
1437   write.prev = NULL;
1438   write.iter = NULL;
1439   write.code = *code;
1440 
1441   for (curr = &(*code)->block; *curr; curr = &(*curr)->next)
1442     {
1443       if ((*curr)->op == EXEC_DO)
1444 	{
1445 	  first.prev = &write;
1446 	  first.iter = (*curr)->ext.iterator;
1447 	  first.code = *curr;
1448 	  stack_top = &first;
1449 	  traverse_io_block ((*curr)->block->next, &b, prev);
1450 	  stack_top = NULL;
1451 	}
1452       prev = *curr;
1453     }
1454   return 0;
1455 }
1456 
1457 /* Optimize a namespace, including all contained namespaces.
1458   flag_frontend_optimize and flag_fronend_loop_interchange are
1459   handled separately.  */
1460 
1461 static void
optimize_namespace(gfc_namespace * ns)1462 optimize_namespace (gfc_namespace *ns)
1463 {
1464   gfc_namespace *saved_ns = gfc_current_ns;
1465   current_ns = ns;
1466   gfc_current_ns = ns;
1467   forall_level = 0;
1468   iterator_level = 0;
1469   in_assoc_list = false;
1470   in_omp_workshare = false;
1471   in_omp_atomic = false;
1472 
1473   if (flag_frontend_optimize)
1474     {
1475       gfc_code_walker (&ns->code, simplify_io_impl_do, dummy_expr_callback, NULL);
1476       gfc_code_walker (&ns->code, convert_do_while, dummy_expr_callback, NULL);
1477       gfc_code_walker (&ns->code, convert_elseif, dummy_expr_callback, NULL);
1478       gfc_code_walker (&ns->code, cfe_code, cfe_expr_0, NULL);
1479       gfc_code_walker (&ns->code, optimize_code, optimize_expr, NULL);
1480       if (flag_inline_matmul_limit != 0 || flag_external_blas)
1481 	{
1482 	  bool found;
1483 	  do
1484 	    {
1485 	      found = false;
1486 	      gfc_code_walker (&ns->code, matmul_to_var_code, matmul_to_var_expr,
1487 			       (void *) &found);
1488 	    }
1489 	  while (found);
1490 
1491 	  gfc_code_walker (&ns->code, matmul_temp_args, dummy_expr_callback,
1492 			   NULL);
1493 	}
1494 
1495       if (flag_external_blas)
1496 	gfc_code_walker (&ns->code, call_external_blas, dummy_expr_callback,
1497 			 NULL);
1498 
1499       if (flag_inline_matmul_limit != 0)
1500 	gfc_code_walker (&ns->code, inline_matmul_assign, dummy_expr_callback,
1501 			 NULL);
1502     }
1503 
1504   if (flag_frontend_loop_interchange)
1505     gfc_code_walker (&ns->code, index_interchange, dummy_expr_callback,
1506 		     NULL);
1507 
1508   /* BLOCKs are handled in the expression walker below.  */
1509   for (ns = ns->contained; ns; ns = ns->sibling)
1510     {
1511       if (ns->code == NULL || ns->code->op != EXEC_BLOCK)
1512 	optimize_namespace (ns);
1513     }
1514   gfc_current_ns = saved_ns;
1515 }
1516 
1517 /* Handle dependencies for allocatable strings which potentially redefine
1518    themselves in an assignment.  */
1519 
1520 static void
realloc_strings(gfc_namespace * ns)1521 realloc_strings (gfc_namespace *ns)
1522 {
1523   current_ns = ns;
1524   gfc_code_walker (&ns->code, realloc_string_callback, dummy_expr_callback, NULL);
1525 
1526   for (ns = ns->contained; ns; ns = ns->sibling)
1527     {
1528       if (ns->code == NULL || ns->code->op != EXEC_BLOCK)
1529 	realloc_strings (ns);
1530     }
1531 
1532 }
1533 
1534 static void
optimize_reduction(gfc_namespace * ns)1535 optimize_reduction (gfc_namespace *ns)
1536 {
1537   current_ns = ns;
1538   gfc_code_walker (&ns->code, gfc_dummy_code_callback,
1539 		   callback_reduction, NULL);
1540 
1541 /* BLOCKs are handled in the expression walker below.  */
1542   for (ns = ns->contained; ns; ns = ns->sibling)
1543     {
1544       if (ns->code == NULL || ns->code->op != EXEC_BLOCK)
1545 	optimize_reduction (ns);
1546     }
1547 }
1548 
1549 /* Replace code like
1550    a = matmul(b,c) + d
1551    with
1552    a = matmul(b,c) ;   a = a + d
1553    where the array function is not elemental and not allocatable
1554    and does not depend on the left-hand side.
1555 */
1556 
1557 static bool
optimize_binop_array_assignment(gfc_code * c,gfc_expr ** rhs,bool seen_op)1558 optimize_binop_array_assignment (gfc_code *c, gfc_expr **rhs, bool seen_op)
1559 {
1560   gfc_expr *e;
1561 
1562   if (!*rhs)
1563     return false;
1564 
1565   e = *rhs;
1566   if (e->expr_type == EXPR_OP)
1567     {
1568       switch (e->value.op.op)
1569 	{
1570 	  /* Unary operators and exponentiation: Only look at a single
1571 	     operand.  */
1572 	case INTRINSIC_NOT:
1573 	case INTRINSIC_UPLUS:
1574 	case INTRINSIC_UMINUS:
1575 	case INTRINSIC_PARENTHESES:
1576 	case INTRINSIC_POWER:
1577 	  if (optimize_binop_array_assignment (c, &e->value.op.op1, seen_op))
1578 	    return true;
1579 	  break;
1580 
1581 	case INTRINSIC_CONCAT:
1582 	  /* Do not do string concatenations.  */
1583 	  break;
1584 
1585 	default:
1586 	  /* Binary operators.  */
1587 	  if (optimize_binop_array_assignment (c, &e->value.op.op1, true))
1588 	    return true;
1589 
1590 	  if (optimize_binop_array_assignment (c, &e->value.op.op2, true))
1591 	    return true;
1592 
1593 	  break;
1594 	}
1595     }
1596   else if (seen_op && e->expr_type == EXPR_FUNCTION && e->rank > 0
1597 	   && ! (e->value.function.esym
1598 		 && (e->value.function.esym->attr.elemental
1599 		     || e->value.function.esym->attr.allocatable
1600 		     || e->value.function.esym->ts.type != c->expr1->ts.type
1601 		     || e->value.function.esym->ts.kind != c->expr1->ts.kind))
1602 	   && ! (e->value.function.isym
1603 		 && (e->value.function.isym->elemental
1604 		     || e->ts.type != c->expr1->ts.type
1605 		     || e->ts.kind != c->expr1->ts.kind))
1606 	   && ! gfc_inline_intrinsic_function_p (e))
1607     {
1608 
1609       gfc_code *n;
1610       gfc_expr *new_expr;
1611 
1612       /* Insert a new assignment statement after the current one.  */
1613       n = XCNEW (gfc_code);
1614       n->op = EXEC_ASSIGN;
1615       n->loc = c->loc;
1616       n->next = c->next;
1617       c->next = n;
1618 
1619       n->expr1 = gfc_copy_expr (c->expr1);
1620       n->expr2 = c->expr2;
1621       new_expr = gfc_copy_expr (c->expr1);
1622       c->expr2 = e;
1623       *rhs = new_expr;
1624 
1625       return true;
1626 
1627     }
1628 
1629   /* Nothing to optimize.  */
1630   return false;
1631 }
1632 
1633 /* Remove unneeded TRIMs at the end of expressions.  */
1634 
1635 static bool
remove_trim(gfc_expr * rhs)1636 remove_trim (gfc_expr *rhs)
1637 {
1638   bool ret;
1639 
1640   ret = false;
1641   if (!rhs)
1642     return ret;
1643 
1644   /* Check for a // b // trim(c).  Looping is probably not
1645      necessary because the parser usually generates
1646      (// (// a b ) trim(c) ) , but better safe than sorry.  */
1647 
1648   while (rhs->expr_type == EXPR_OP
1649 	 && rhs->value.op.op == INTRINSIC_CONCAT)
1650     rhs = rhs->value.op.op2;
1651 
1652   while (rhs->expr_type == EXPR_FUNCTION && rhs->value.function.isym
1653 	 && rhs->value.function.isym->id == GFC_ISYM_TRIM)
1654     {
1655       strip_function_call (rhs);
1656       /* Recursive call to catch silly stuff like trim ( a // trim(b)).  */
1657       remove_trim (rhs);
1658       ret = true;
1659     }
1660 
1661   return ret;
1662 }
1663 
1664 /* Optimizations for an assignment.  */
1665 
1666 static void
optimize_assignment(gfc_code * c)1667 optimize_assignment (gfc_code * c)
1668 {
1669   gfc_expr *lhs, *rhs;
1670 
1671   lhs = c->expr1;
1672   rhs = c->expr2;
1673 
1674   if (lhs->ts.type == BT_CHARACTER && !lhs->ts.deferred)
1675     {
1676       /* Optimize  a = trim(b)  to  a = b.  */
1677       remove_trim (rhs);
1678 
1679       /* Replace a = '   ' by a = '' to optimize away a memcpy.  */
1680       if (is_empty_string (rhs))
1681 	rhs->value.character.length = 0;
1682     }
1683 
1684   if (lhs->rank > 0 && gfc_check_dependency (lhs, rhs, true) == 0)
1685     optimize_binop_array_assignment (c, &rhs, false);
1686 }
1687 
1688 
1689 /* Remove an unneeded function call, modifying the expression.
1690    This replaces the function call with the value of its
1691    first argument.  The rest of the argument list is freed.  */
1692 
1693 static void
strip_function_call(gfc_expr * e)1694 strip_function_call (gfc_expr *e)
1695 {
1696   gfc_expr *e1;
1697   gfc_actual_arglist *a;
1698 
1699   a = e->value.function.actual;
1700 
1701   /* We should have at least one argument.  */
1702   gcc_assert (a->expr != NULL);
1703 
1704   e1 = a->expr;
1705 
1706   /* Free the remaining arglist, if any.  */
1707   if (a->next)
1708     gfc_free_actual_arglist (a->next);
1709 
1710   /* Graft the argument expression onto the original function.  */
1711   *e = *e1;
1712   free (e1);
1713 
1714 }
1715 
1716 /* Optimization of lexical comparison functions.  */
1717 
1718 static bool
optimize_lexical_comparison(gfc_expr * e)1719 optimize_lexical_comparison (gfc_expr *e)
1720 {
1721   if (e->expr_type != EXPR_FUNCTION || e->value.function.isym == NULL)
1722     return false;
1723 
1724   switch (e->value.function.isym->id)
1725     {
1726     case GFC_ISYM_LLE:
1727       return optimize_comparison (e, INTRINSIC_LE);
1728 
1729     case GFC_ISYM_LGE:
1730       return optimize_comparison (e, INTRINSIC_GE);
1731 
1732     case GFC_ISYM_LGT:
1733       return optimize_comparison (e, INTRINSIC_GT);
1734 
1735     case GFC_ISYM_LLT:
1736       return optimize_comparison (e, INTRINSIC_LT);
1737 
1738     default:
1739       break;
1740     }
1741   return false;
1742 }
1743 
1744 /* Combine stuff like [a]>b into [a>b], for easier optimization later.  Do not
1745    do CHARACTER because of possible pessimization involving character
1746    lengths.  */
1747 
1748 static bool
combine_array_constructor(gfc_expr * e)1749 combine_array_constructor (gfc_expr *e)
1750 {
1751 
1752   gfc_expr *op1, *op2;
1753   gfc_expr *scalar;
1754   gfc_expr *new_expr;
1755   gfc_constructor *c, *new_c;
1756   gfc_constructor_base oldbase, newbase;
1757   bool scalar_first;
1758   int n_elem;
1759   bool all_const;
1760 
1761   /* Array constructors have rank one.  */
1762   if (e->rank != 1)
1763     return false;
1764 
1765   /* Don't try to combine association lists, this makes no sense
1766      and leads to an ICE.  */
1767   if (in_assoc_list)
1768     return false;
1769 
1770   /* With FORALL, the BLOCKS created by create_var will cause an ICE.  */
1771   if (forall_level > 0)
1772     return false;
1773 
1774   /* Inside an iterator, things can get hairy; we are likely to create
1775      an invalid temporary variable.  */
1776   if (iterator_level > 0)
1777     return false;
1778 
1779   /* WHERE also doesn't work.  */
1780   if (in_where > 0)
1781     return false;
1782 
1783   op1 = e->value.op.op1;
1784   op2 = e->value.op.op2;
1785 
1786   if (!op1 || !op2)
1787     return false;
1788 
1789   if (op1->expr_type == EXPR_ARRAY && op2->rank == 0)
1790     scalar_first = false;
1791   else if (op2->expr_type == EXPR_ARRAY && op1->rank == 0)
1792     {
1793       scalar_first = true;
1794       op1 = e->value.op.op2;
1795       op2 = e->value.op.op1;
1796     }
1797   else
1798     return false;
1799 
1800   if (op2->ts.type == BT_CHARACTER)
1801     return false;
1802 
1803   /* This might be an expanded constructor with very many constant values. If
1804      we perform the operation here, we might end up with a long compile time
1805      and actually longer execution time, so a length bound is in order here.
1806      If the constructor constains something which is not a constant, it did
1807      not come from an expansion, so leave it alone.  */
1808 
1809 #define CONSTR_LEN_MAX 4
1810 
1811   oldbase = op1->value.constructor;
1812 
1813   n_elem = 0;
1814   all_const = true;
1815   for (c = gfc_constructor_first (oldbase); c; c = gfc_constructor_next(c))
1816     {
1817       if (c->expr->expr_type != EXPR_CONSTANT)
1818 	{
1819 	  all_const = false;
1820 	  break;
1821 	}
1822       n_elem += 1;
1823     }
1824 
1825   if (all_const && n_elem > CONSTR_LEN_MAX)
1826     return false;
1827 
1828 #undef CONSTR_LEN_MAX
1829 
1830   newbase = NULL;
1831   e->expr_type = EXPR_ARRAY;
1832 
1833   scalar = create_var (gfc_copy_expr (op2), "constr");
1834 
1835   for (c = gfc_constructor_first (oldbase); c;
1836        c = gfc_constructor_next (c))
1837     {
1838       new_expr = gfc_get_expr ();
1839       new_expr->ts = e->ts;
1840       new_expr->expr_type = EXPR_OP;
1841       new_expr->rank = c->expr->rank;
1842       new_expr->where = c->expr->where;
1843       new_expr->value.op.op = e->value.op.op;
1844 
1845       if (scalar_first)
1846 	{
1847 	  new_expr->value.op.op1 = gfc_copy_expr (scalar);
1848 	  new_expr->value.op.op2 = gfc_copy_expr (c->expr);
1849 	}
1850       else
1851 	{
1852 	  new_expr->value.op.op1 = gfc_copy_expr (c->expr);
1853 	  new_expr->value.op.op2 = gfc_copy_expr (scalar);
1854 	}
1855 
1856       new_c = gfc_constructor_append_expr (&newbase, new_expr, &(e->where));
1857       new_c->iterator = c->iterator;
1858       c->iterator = NULL;
1859     }
1860 
1861   gfc_free_expr (op1);
1862   gfc_free_expr (op2);
1863   gfc_free_expr (scalar);
1864 
1865   e->value.constructor = newbase;
1866   return true;
1867 }
1868 
1869 /* Recursive optimization of operators.  */
1870 
1871 static bool
optimize_op(gfc_expr * e)1872 optimize_op (gfc_expr *e)
1873 {
1874   bool changed;
1875 
1876   gfc_intrinsic_op op = e->value.op.op;
1877 
1878   changed = false;
1879 
1880   /* Only use new-style comparisons.  */
1881   switch(op)
1882     {
1883     case INTRINSIC_EQ_OS:
1884       op = INTRINSIC_EQ;
1885       break;
1886 
1887     case INTRINSIC_GE_OS:
1888       op = INTRINSIC_GE;
1889       break;
1890 
1891     case INTRINSIC_LE_OS:
1892       op = INTRINSIC_LE;
1893       break;
1894 
1895     case INTRINSIC_NE_OS:
1896       op = INTRINSIC_NE;
1897       break;
1898 
1899     case INTRINSIC_GT_OS:
1900       op = INTRINSIC_GT;
1901       break;
1902 
1903     case INTRINSIC_LT_OS:
1904       op = INTRINSIC_LT;
1905       break;
1906 
1907     default:
1908       break;
1909     }
1910 
1911   switch (op)
1912     {
1913     case INTRINSIC_EQ:
1914     case INTRINSIC_GE:
1915     case INTRINSIC_LE:
1916     case INTRINSIC_NE:
1917     case INTRINSIC_GT:
1918     case INTRINSIC_LT:
1919       changed = optimize_comparison (e, op);
1920 
1921       gcc_fallthrough ();
1922       /* Look at array constructors.  */
1923     case INTRINSIC_PLUS:
1924     case INTRINSIC_MINUS:
1925     case INTRINSIC_TIMES:
1926     case INTRINSIC_DIVIDE:
1927       return combine_array_constructor (e) || changed;
1928 
1929     default:
1930       break;
1931     }
1932 
1933   return false;
1934 }
1935 
1936 
1937 /* Return true if a constant string contains only blanks.  */
1938 
1939 static bool
is_empty_string(gfc_expr * e)1940 is_empty_string (gfc_expr *e)
1941 {
1942   int i;
1943 
1944   if (e->ts.type != BT_CHARACTER || e->expr_type != EXPR_CONSTANT)
1945     return false;
1946 
1947   for (i=0; i < e->value.character.length; i++)
1948     {
1949       if (e->value.character.string[i] != ' ')
1950 	return false;
1951     }
1952 
1953   return true;
1954 }
1955 
1956 
1957 /* Insert a call to the intrinsic len_trim. Use a different name for
1958    the symbol tree so we don't run into trouble when the user has
1959    renamed len_trim for some reason.  */
1960 
1961 static gfc_expr*
get_len_trim_call(gfc_expr * str,int kind)1962 get_len_trim_call (gfc_expr *str, int kind)
1963 {
1964   gfc_expr *fcn;
1965   gfc_actual_arglist *actual_arglist, *next;
1966 
1967   fcn = gfc_get_expr ();
1968   fcn->expr_type = EXPR_FUNCTION;
1969   fcn->value.function.isym = gfc_intrinsic_function_by_id (GFC_ISYM_LEN_TRIM);
1970   actual_arglist = gfc_get_actual_arglist ();
1971   actual_arglist->expr = str;
1972   next = gfc_get_actual_arglist ();
1973   next->expr = gfc_get_int_expr (gfc_default_integer_kind, NULL, kind);
1974   actual_arglist->next = next;
1975 
1976   fcn->value.function.actual = actual_arglist;
1977   fcn->where = str->where;
1978   fcn->ts.type = BT_INTEGER;
1979   fcn->ts.kind = gfc_charlen_int_kind;
1980 
1981   gfc_get_sym_tree ("__internal_len_trim", current_ns, &fcn->symtree, false);
1982   fcn->symtree->n.sym->ts = fcn->ts;
1983   fcn->symtree->n.sym->attr.flavor = FL_PROCEDURE;
1984   fcn->symtree->n.sym->attr.function = 1;
1985   fcn->symtree->n.sym->attr.elemental = 1;
1986   fcn->symtree->n.sym->attr.referenced = 1;
1987   fcn->symtree->n.sym->attr.access = ACCESS_PRIVATE;
1988   gfc_commit_symbol (fcn->symtree->n.sym);
1989 
1990   return fcn;
1991 }
1992 
1993 
1994 /* Optimize expressions for equality.  */
1995 
1996 static bool
optimize_comparison(gfc_expr * e,gfc_intrinsic_op op)1997 optimize_comparison (gfc_expr *e, gfc_intrinsic_op op)
1998 {
1999   gfc_expr *op1, *op2;
2000   bool change;
2001   int eq;
2002   bool result;
2003   gfc_actual_arglist *firstarg, *secondarg;
2004 
2005   if (e->expr_type == EXPR_OP)
2006     {
2007       firstarg = NULL;
2008       secondarg = NULL;
2009       op1 = e->value.op.op1;
2010       op2 = e->value.op.op2;
2011     }
2012   else if (e->expr_type == EXPR_FUNCTION)
2013     {
2014       /* One of the lexical comparison functions.  */
2015       firstarg = e->value.function.actual;
2016       secondarg = firstarg->next;
2017       op1 = firstarg->expr;
2018       op2 = secondarg->expr;
2019     }
2020   else
2021     gcc_unreachable ();
2022 
2023   /* Strip off unneeded TRIM calls from string comparisons.  */
2024 
2025   change = remove_trim (op1);
2026 
2027   if (remove_trim (op2))
2028     change = true;
2029 
2030   /* An expression of type EXPR_CONSTANT is only valid for scalars.  */
2031   /* TODO: A scalar constant may be acceptable in some cases (the scalarizer
2032      handles them well). However, there are also cases that need a non-scalar
2033      argument. For example the any intrinsic. See PR 45380.  */
2034   if (e->rank > 0)
2035     return change;
2036 
2037   /* Replace a == '' with len_trim(a) == 0 and a /= '' with
2038      len_trim(a) != 0 */
2039   if (op1->ts.type == BT_CHARACTER && op2->ts.type == BT_CHARACTER
2040       && (op == INTRINSIC_EQ || op == INTRINSIC_NE))
2041     {
2042       bool empty_op1, empty_op2;
2043       empty_op1 = is_empty_string (op1);
2044       empty_op2 = is_empty_string (op2);
2045 
2046       if (empty_op1 || empty_op2)
2047 	{
2048 	  gfc_expr *fcn;
2049 	  gfc_expr *zero;
2050 	  gfc_expr *str;
2051 
2052 	  /* This can only happen when an error for comparing
2053 	     characters of different kinds has already been issued.  */
2054 	  if (empty_op1 && empty_op2)
2055 	    return false;
2056 
2057 	  zero = gfc_get_int_expr (gfc_charlen_int_kind, &e->where, 0);
2058 	  str = empty_op1 ? op2 : op1;
2059 
2060 	  fcn = get_len_trim_call (str, gfc_charlen_int_kind);
2061 
2062 
2063 	  if (empty_op1)
2064 	    gfc_free_expr (op1);
2065 	  else
2066 	    gfc_free_expr (op2);
2067 
2068 	  op1 = fcn;
2069 	  op2 = zero;
2070 	  e->value.op.op1 = fcn;
2071 	  e->value.op.op2 = zero;
2072 	}
2073     }
2074 
2075 
2076   /* Don't compare REAL or COMPLEX expressions when honoring NaNs.  */
2077 
2078   if (flag_finite_math_only
2079       || (op1->ts.type != BT_REAL && op2->ts.type != BT_REAL
2080 	  && op1->ts.type != BT_COMPLEX && op2->ts.type != BT_COMPLEX))
2081     {
2082       eq = gfc_dep_compare_expr (op1, op2);
2083       if (eq <= -2)
2084 	{
2085 	  /* Replace A // B < A // C with B < C, and A // B < C // B
2086 	     with A < C.  */
2087 	  if (op1->ts.type == BT_CHARACTER && op2->ts.type == BT_CHARACTER
2088 	      && op1->expr_type == EXPR_OP
2089 	      && op1->value.op.op == INTRINSIC_CONCAT
2090 	      && op2->expr_type == EXPR_OP
2091 	      && op2->value.op.op == INTRINSIC_CONCAT)
2092 	    {
2093 	      gfc_expr *op1_left = op1->value.op.op1;
2094 	      gfc_expr *op2_left = op2->value.op.op1;
2095 	      gfc_expr *op1_right = op1->value.op.op2;
2096 	      gfc_expr *op2_right = op2->value.op.op2;
2097 
2098 	      if (gfc_dep_compare_expr (op1_left, op2_left) == 0)
2099 		{
2100 		  /* Watch out for 'A ' // x vs. 'A' // x.  */
2101 
2102 		  if (op1_left->expr_type == EXPR_CONSTANT
2103 			&& op2_left->expr_type == EXPR_CONSTANT
2104 			&& op1_left->value.character.length
2105 			   != op2_left->value.character.length)
2106 		    return change;
2107 		  else
2108 		    {
2109 		      free (op1_left);
2110 		      free (op2_left);
2111 		      if (firstarg)
2112 			{
2113 			  firstarg->expr = op1_right;
2114 			  secondarg->expr = op2_right;
2115 			}
2116 		      else
2117 			{
2118 			  e->value.op.op1 = op1_right;
2119 			  e->value.op.op2 = op2_right;
2120 			}
2121 		      optimize_comparison (e, op);
2122 		      return true;
2123 		    }
2124 		}
2125 	      if (gfc_dep_compare_expr (op1_right, op2_right) == 0)
2126 		{
2127 		  free (op1_right);
2128 		  free (op2_right);
2129 		  if (firstarg)
2130 		    {
2131 		      firstarg->expr = op1_left;
2132 		      secondarg->expr = op2_left;
2133 		    }
2134 		  else
2135 		    {
2136 		      e->value.op.op1 = op1_left;
2137 		      e->value.op.op2 = op2_left;
2138 		    }
2139 
2140 		  optimize_comparison (e, op);
2141 		  return true;
2142 		}
2143 	    }
2144 	}
2145       else
2146 	{
2147 	  /* eq can only be -1, 0 or 1 at this point.  */
2148 	  switch (op)
2149 	    {
2150 	    case INTRINSIC_EQ:
2151 	      result = eq == 0;
2152 	      break;
2153 
2154 	    case INTRINSIC_GE:
2155 	      result = eq >= 0;
2156 	      break;
2157 
2158 	    case INTRINSIC_LE:
2159 	      result = eq <= 0;
2160 	      break;
2161 
2162 	    case INTRINSIC_NE:
2163 	      result = eq != 0;
2164 	      break;
2165 
2166 	    case INTRINSIC_GT:
2167 	      result = eq > 0;
2168 	      break;
2169 
2170 	    case INTRINSIC_LT:
2171 	      result = eq < 0;
2172 	      break;
2173 
2174 	    default:
2175 	      gfc_internal_error ("illegal OP in optimize_comparison");
2176 	      break;
2177 	    }
2178 
2179 	  /* Replace the expression by a constant expression.  The typespec
2180 	     and where remains the way it is.  */
2181 	  free (op1);
2182 	  free (op2);
2183 	  e->expr_type = EXPR_CONSTANT;
2184 	  e->value.logical = result;
2185 	  return true;
2186 	}
2187     }
2188 
2189   return change;
2190 }
2191 
2192 /* Optimize a trim function by replacing it with an equivalent substring
2193    involving a call to len_trim.  This only works for expressions where
2194    variables are trimmed.  Return true if anything was modified.  */
2195 
2196 static bool
optimize_trim(gfc_expr * e)2197 optimize_trim (gfc_expr *e)
2198 {
2199   gfc_expr *a;
2200   gfc_ref *ref;
2201   gfc_expr *fcn;
2202   gfc_ref **rr = NULL;
2203 
2204   /* Don't do this optimization within an argument list, because
2205      otherwise aliasing issues may occur.  */
2206 
2207   if (count_arglist != 1)
2208     return false;
2209 
2210   if (e->ts.type != BT_CHARACTER || e->expr_type != EXPR_FUNCTION
2211       || e->value.function.isym == NULL
2212       || e->value.function.isym->id != GFC_ISYM_TRIM)
2213     return false;
2214 
2215   a = e->value.function.actual->expr;
2216 
2217   if (a->expr_type != EXPR_VARIABLE)
2218     return false;
2219 
2220   /* This would pessimize the idiom a = trim(a) for reallocatable strings.  */
2221 
2222   if (a->symtree->n.sym->attr.allocatable)
2223     return false;
2224 
2225   /* Follow all references to find the correct place to put the newly
2226      created reference.  FIXME:  Also handle substring references and
2227      array references.  Array references cause strange regressions at
2228      the moment.  */
2229 
2230   if (a->ref)
2231     {
2232       for (rr = &(a->ref); *rr; rr = &((*rr)->next))
2233 	{
2234 	  if ((*rr)->type == REF_SUBSTRING || (*rr)->type == REF_ARRAY)
2235 	    return false;
2236 	}
2237     }
2238 
2239   strip_function_call (e);
2240 
2241   if (e->ref == NULL)
2242     rr = &(e->ref);
2243 
2244   /* Create the reference.  */
2245 
2246   ref = gfc_get_ref ();
2247   ref->type = REF_SUBSTRING;
2248 
2249   /* Set the start of the reference.  */
2250 
2251   ref->u.ss.start = gfc_get_int_expr (gfc_charlen_int_kind, NULL, 1);
2252 
2253   /* Build the function call to len_trim(x, gfc_default_integer_kind).  */
2254 
2255   fcn = get_len_trim_call (gfc_copy_expr (e), gfc_charlen_int_kind);
2256 
2257   /* Set the end of the reference to the call to len_trim.  */
2258 
2259   ref->u.ss.end = fcn;
2260   gcc_assert (rr != NULL && *rr == NULL);
2261   *rr = ref;
2262   return true;
2263 }
2264 
2265 /* Optimize minloc(b), where b is rank 1 array, into
2266    (/ minloc(b, dim=1) /), and similarly for maxloc,
2267    as the latter forms are expanded inline.  */
2268 
2269 static void
optimize_minmaxloc(gfc_expr ** e)2270 optimize_minmaxloc (gfc_expr **e)
2271 {
2272   gfc_expr *fn = *e;
2273   gfc_actual_arglist *a;
2274   char *name, *p;
2275 
2276   if (fn->rank != 1
2277       || fn->value.function.actual == NULL
2278       || fn->value.function.actual->expr == NULL
2279       || fn->value.function.actual->expr->ts.type == BT_CHARACTER
2280       || fn->value.function.actual->expr->rank != 1)
2281     return;
2282 
2283   *e = gfc_get_array_expr (fn->ts.type, fn->ts.kind, &fn->where);
2284   (*e)->shape = fn->shape;
2285   fn->rank = 0;
2286   fn->shape = NULL;
2287   gfc_constructor_append_expr (&(*e)->value.constructor, fn, &fn->where);
2288 
2289   name = XALLOCAVEC (char, strlen (fn->value.function.name) + 1);
2290   strcpy (name, fn->value.function.name);
2291   p = strstr (name, "loc0");
2292   p[3] = '1';
2293   fn->value.function.name = gfc_get_string ("%s", name);
2294   if (fn->value.function.actual->next)
2295     {
2296       a = fn->value.function.actual->next;
2297       gcc_assert (a->expr == NULL);
2298     }
2299   else
2300     {
2301       a = gfc_get_actual_arglist ();
2302       fn->value.function.actual->next = a;
2303     }
2304   a->expr = gfc_get_constant_expr (BT_INTEGER, gfc_default_integer_kind,
2305 				   &fn->where);
2306   mpz_set_ui (a->expr->value.integer, 1);
2307 }
2308 
2309 /* Data package to hand down for DO loop checks in a contained
2310    procedure.  */
2311 typedef struct contained_info
2312 {
2313   gfc_symbol *do_var;
2314   gfc_symbol *procedure;
2315   locus where_do;
2316 } contained_info;
2317 
2318 static enum gfc_exec_op last_io_op;
2319 
2320 /* Callback function to check for INTENT(OUT) and INTENT(INOUT) in a
2321    contained function call.  */
2322 
2323 static int
doloop_contained_function_call(gfc_expr ** e,int * walk_subtrees ATTRIBUTE_UNUSED,void * data)2324 doloop_contained_function_call (gfc_expr **e,
2325 				int *walk_subtrees ATTRIBUTE_UNUSED, void *data)
2326 {
2327   gfc_expr *expr = *e;
2328   gfc_formal_arglist *f;
2329   gfc_actual_arglist *a;
2330   gfc_symbol *sym, *do_var;
2331   contained_info *info;
2332 
2333   if (expr->expr_type != EXPR_FUNCTION || expr->value.function.isym
2334       || expr->value.function.esym == NULL)
2335     return 0;
2336 
2337   sym = expr->value.function.esym;
2338   f = gfc_sym_get_dummy_args (sym);
2339   if (f == NULL)
2340     return 0;
2341 
2342   info = (contained_info *) data;
2343   do_var = info->do_var;
2344   a = expr->value.function.actual;
2345 
2346   while (a && f)
2347     {
2348       if (a->expr && a->expr->symtree && a->expr->symtree->n.sym == do_var)
2349 	{
2350 	  if (f->sym->attr.intent == INTENT_OUT)
2351 	    {
2352 	      gfc_error_now ("Index variable %qs set to undefined as "
2353 			     "INTENT(OUT) argument at %L in procedure %qs "
2354 			     "called from within DO loop at %L", do_var->name,
2355 			     &a->expr->where, info->procedure->name,
2356 			     &info->where_do);
2357 	      return 1;
2358 	    }
2359 	  else if (f->sym->attr.intent == INTENT_INOUT)
2360 	    {
2361 	      gfc_error_now ("Index variable %qs not definable as "
2362 			     "INTENT(INOUT) argument at %L in procedure %qs "
2363 			     "called from within DO loop at %L", do_var->name,
2364 			     &a->expr->where, info->procedure->name,
2365 			     &info->where_do);
2366 	      return 1;
2367 	    }
2368 	}
2369       a = a->next;
2370       f = f->next;
2371     }
2372   return 0;
2373 }
2374 
2375 /* Callback function that goes through the code in a contained
2376    procedure to make sure it does not change a variable in a DO
2377    loop.  */
2378 
2379 static int
doloop_contained_procedure_code(gfc_code ** c,int * walk_subtrees ATTRIBUTE_UNUSED,void * data)2380 doloop_contained_procedure_code (gfc_code **c,
2381 				 int *walk_subtrees ATTRIBUTE_UNUSED,
2382 				 void *data)
2383 {
2384   gfc_code *co = *c;
2385   contained_info *info = (contained_info *) data;
2386   gfc_symbol *do_var = info->do_var;
2387   const char *errmsg = _("Index variable %qs redefined at %L in procedure %qs "
2388 			 "called from within DO loop at %L");
2389   static enum gfc_exec_op saved_io_op;
2390 
2391   switch (co->op)
2392     {
2393     case EXEC_ASSIGN:
2394       if (co->expr1->symtree && co->expr1->symtree->n.sym == do_var)
2395 	gfc_error_now (errmsg, do_var->name, &co->loc, info->procedure->name,
2396 		       &info->where_do);
2397       break;
2398 
2399     case EXEC_DO:
2400       if (co->ext.iterator && co->ext.iterator->var
2401 	  && co->ext.iterator->var->symtree->n.sym == do_var)
2402 	gfc_error (errmsg, do_var->name, &co->loc, info->procedure->name,
2403 		   &info->where_do);
2404       break;
2405 
2406     case EXEC_READ:
2407     case EXEC_WRITE:
2408     case EXEC_INQUIRE:
2409     case EXEC_IOLENGTH:
2410       saved_io_op = last_io_op;
2411       last_io_op = co->op;
2412       break;
2413 
2414     case EXEC_OPEN:
2415       if (co->ext.open && co->ext.open->iostat
2416 	  && co->ext.open->iostat->symtree->n.sym == do_var)
2417 	gfc_error_now (errmsg, do_var->name, &co->ext.open->iostat->where,
2418 		       info->procedure->name, &info->where_do);
2419       break;
2420 
2421     case EXEC_CLOSE:
2422       if (co->ext.close && co->ext.close->iostat
2423 	  && co->ext.close->iostat->symtree->n.sym == do_var)
2424 	gfc_error_now (errmsg, do_var->name, &co->ext.close->iostat->where,
2425 		       info->procedure->name, &info->where_do);
2426       break;
2427 
2428     case EXEC_TRANSFER:
2429       switch (last_io_op)
2430 	{
2431 
2432 	case EXEC_INQUIRE:
2433 #define CHECK_INQ(a) do { if (co->ext.inquire    &&			\
2434 			      co->ext.inquire->a &&			\
2435 			      co->ext.inquire->a->symtree->n.sym == do_var) \
2436 	      gfc_error_now (errmsg, do_var->name,			\
2437 			     &co->ext.inquire->a->where,		\
2438 			     info->procedure->name,			\
2439 			     &info->where_do);				\
2440 	  } while (0)
2441 
2442 	  CHECK_INQ(iostat);
2443 	  CHECK_INQ(number);
2444 	  CHECK_INQ(position);
2445 	  CHECK_INQ(recl);
2446 	  CHECK_INQ(position);
2447 	  CHECK_INQ(iolength);
2448 	  CHECK_INQ(strm_pos);
2449 	  break;
2450 #undef CHECK_INQ
2451 
2452 	case EXEC_READ:
2453 	  if (co->expr1 && co->expr1->symtree
2454 	      && co->expr1->symtree->n.sym == do_var)
2455 	    gfc_error_now (errmsg, do_var->name, &co->expr1->where,
2456 			   info->procedure->name, &info->where_do);
2457 
2458 	  /* Fallthrough.  */
2459 
2460 	case EXEC_WRITE:
2461 	  if (co->ext.dt && co->ext.dt->iostat && co->ext.dt->iostat->symtree
2462 	      && co->ext.dt->iostat->symtree->n.sym == do_var)
2463 	    gfc_error_now (errmsg, do_var->name, &co->ext.dt->iostat->where,
2464 			   info->procedure->name, &info->where_do);
2465 	  break;
2466 
2467 	case EXEC_IOLENGTH:
2468 	  if (co->expr1 && co->expr1->symtree
2469 	      && co->expr1->symtree->n.sym == do_var)
2470 	    gfc_error_now (errmsg, do_var->name, &co->expr1->where,
2471 			   info->procedure->name, &info->where_do);
2472 	  break;
2473 
2474 	default:
2475 	  gcc_unreachable ();
2476 	}
2477       break;
2478 
2479     case EXEC_DT_END:
2480       last_io_op = saved_io_op;
2481       break;
2482 
2483     case EXEC_CALL:
2484       gfc_formal_arglist *f;
2485       gfc_actual_arglist *a;
2486 
2487       f = gfc_sym_get_dummy_args (co->resolved_sym);
2488       if (f == NULL)
2489 	break;
2490       a = co->ext.actual;
2491       /* Slightly different error message here. If there is an error,
2492 	 return 1 to avoid an infinite loop.  */
2493       while (a && f)
2494 	{
2495 	  if (a->expr && a->expr->symtree && a->expr->symtree->n.sym == do_var)
2496 	    {
2497 	      if (f->sym->attr.intent == INTENT_OUT)
2498 		{
2499 		  gfc_error_now ("Index variable %qs set to undefined as "
2500 				 "INTENT(OUT) argument at %L in subroutine %qs "
2501 				 "called from within DO loop at %L",
2502 				 do_var->name, &a->expr->where,
2503 				 info->procedure->name, &info->where_do);
2504 		  return 1;
2505 		}
2506 	      else if (f->sym->attr.intent == INTENT_INOUT)
2507 		{
2508 		  gfc_error_now ("Index variable %qs not definable as "
2509 				 "INTENT(INOUT) argument at %L in subroutine %qs "
2510 				 "called from within DO loop at %L", do_var->name,
2511 				 &a->expr->where, info->procedure->name,
2512 				 &info->where_do);
2513 		  return 1;
2514 		}
2515 	    }
2516 	  a = a->next;
2517 	  f = f->next;
2518 	}
2519       break;
2520     default:
2521       break;
2522     }
2523   return 0;
2524 }
2525 
2526 /* Callback function for code checking that we do not pass a DO variable to an
2527    INTENT(OUT) or INTENT(INOUT) dummy variable.  */
2528 
2529 static int
doloop_code(gfc_code ** c,int * walk_subtrees ATTRIBUTE_UNUSED,void * data ATTRIBUTE_UNUSED)2530 doloop_code (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
2531 	 void *data ATTRIBUTE_UNUSED)
2532 {
2533   gfc_code *co;
2534   int i;
2535   gfc_formal_arglist *f;
2536   gfc_actual_arglist *a;
2537   gfc_code *cl;
2538   do_t loop, *lp;
2539   bool seen_goto;
2540 
2541   co = *c;
2542 
2543   /* If the doloop_list grew, we have to truncate it here.  */
2544 
2545   if ((unsigned) doloop_level < doloop_list.length())
2546     doloop_list.truncate (doloop_level);
2547 
2548   seen_goto = false;
2549   switch (co->op)
2550     {
2551     case EXEC_DO:
2552 
2553       if (co->ext.iterator && co->ext.iterator->var)
2554 	loop.c = co;
2555       else
2556 	loop.c = NULL;
2557 
2558       loop.branch_level = if_level + select_level;
2559       loop.seen_goto = false;
2560       doloop_list.safe_push (loop);
2561       break;
2562 
2563       /* If anything could transfer control away from a suspicious
2564 	 subscript, make sure to set seen_goto in the current DO loop
2565 	 (if any).  */
2566     case EXEC_GOTO:
2567     case EXEC_EXIT:
2568     case EXEC_STOP:
2569     case EXEC_ERROR_STOP:
2570     case EXEC_CYCLE:
2571       seen_goto = true;
2572       break;
2573 
2574     case EXEC_OPEN:
2575       if (co->ext.open->err)
2576 	seen_goto = true;
2577       break;
2578 
2579     case EXEC_CLOSE:
2580       if (co->ext.close->err)
2581 	seen_goto = true;
2582       break;
2583 
2584     case EXEC_BACKSPACE:
2585     case EXEC_ENDFILE:
2586     case EXEC_REWIND:
2587     case EXEC_FLUSH:
2588 
2589       if (co->ext.filepos->err)
2590 	seen_goto = true;
2591       break;
2592 
2593     case EXEC_INQUIRE:
2594       if (co->ext.filepos->err)
2595 	seen_goto = true;
2596       break;
2597 
2598     case EXEC_READ:
2599     case EXEC_WRITE:
2600       if (co->ext.dt->err || co->ext.dt->end || co->ext.dt->eor)
2601 	seen_goto = true;
2602       break;
2603 
2604     case EXEC_WAIT:
2605       if (co->ext.wait->err || co->ext.wait->end || co->ext.wait->eor)
2606 	loop.seen_goto = true;
2607       break;
2608 
2609     case EXEC_CALL:
2610       if (co->resolved_sym == NULL)
2611 	break;
2612 
2613       /* Test if somebody stealthily changes the DO variable from
2614 	 under us by changing it in a host-associated procedure.  */
2615       if (co->resolved_sym->attr.contained)
2616 	{
2617 	  FOR_EACH_VEC_ELT (doloop_list, i, lp)
2618 	    {
2619 	      gfc_symbol *sym = co->resolved_sym;
2620 	      contained_info info;
2621 	      gfc_namespace *ns;
2622 
2623 	      cl = lp->c;
2624 	      info.do_var = cl->ext.iterator->var->symtree->n.sym;
2625 	      info.procedure = co->resolved_sym;  /* sym? */
2626 	      info.where_do = co->loc;
2627 	      /* Look contained procedures under the namespace of the
2628 		 variable.  */
2629 	      for (ns = info.do_var->ns->contained; ns; ns = ns->sibling)
2630 		if (ns->proc_name && ns->proc_name == sym)
2631 		  gfc_code_walker (&ns->code, doloop_contained_procedure_code,
2632 				   doloop_contained_function_call, &info);
2633 	    }
2634 	}
2635 
2636       f = gfc_sym_get_dummy_args (co->resolved_sym);
2637 
2638       /* Withot a formal arglist, there is only unknown INTENT,
2639 	 which we don't check for.  */
2640       if (f == NULL)
2641 	break;
2642 
2643       a = co->ext.actual;
2644 
2645       while (a && f)
2646 	{
2647 	  FOR_EACH_VEC_ELT (doloop_list, i, lp)
2648 	    {
2649 	      gfc_symbol *do_sym;
2650 	      cl = lp->c;
2651 
2652 	      if (cl == NULL)
2653 		break;
2654 
2655 	      do_sym = cl->ext.iterator->var->symtree->n.sym;
2656 
2657 	      if (a->expr && a->expr->symtree && f->sym
2658 		  && a->expr->symtree->n.sym == do_sym)
2659 		{
2660 		  if (f->sym->attr.intent == INTENT_OUT)
2661 		    gfc_error_now ("Variable %qs at %L set to undefined "
2662 				   "value inside loop beginning at %L as "
2663 				   "INTENT(OUT) argument to subroutine %qs",
2664 				   do_sym->name, &a->expr->where,
2665 				   &(doloop_list[i].c->loc),
2666 				   co->symtree->n.sym->name);
2667 		  else if (f->sym->attr.intent == INTENT_INOUT)
2668 		    gfc_error_now ("Variable %qs at %L not definable inside "
2669 				   "loop beginning at %L as INTENT(INOUT) "
2670 				   "argument to subroutine %qs",
2671 				   do_sym->name, &a->expr->where,
2672 				   &(doloop_list[i].c->loc),
2673 				   co->symtree->n.sym->name);
2674 		}
2675 	    }
2676 	  a = a->next;
2677 	  f = f->next;
2678 	}
2679 
2680       break;
2681 
2682     default:
2683       break;
2684     }
2685   if (seen_goto && doloop_level > 0)
2686     doloop_list[doloop_level-1].seen_goto = true;
2687 
2688   return 0;
2689 }
2690 
2691 /* Callback function to warn about different things within DO loops.  */
2692 
2693 static int
do_function(gfc_expr ** e,int * walk_subtrees ATTRIBUTE_UNUSED,void * data ATTRIBUTE_UNUSED)2694 do_function (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
2695 	     void *data ATTRIBUTE_UNUSED)
2696 {
2697   do_t *last;
2698 
2699   if (doloop_list.length () == 0)
2700     return 0;
2701 
2702   if ((*e)->expr_type == EXPR_FUNCTION)
2703     do_intent (e);
2704 
2705   last = &doloop_list.last();
2706   if (last->seen_goto && !warn_do_subscript)
2707     return 0;
2708 
2709   if ((*e)->expr_type == EXPR_VARIABLE)
2710     do_subscript (e);
2711 
2712   return 0;
2713 }
2714 
2715 typedef struct
2716 {
2717   gfc_symbol *sym;
2718   mpz_t val;
2719 } insert_index_t;
2720 
2721 /* Callback function - if the expression is the variable in data->sym,
2722    replace it with a constant from data->val.  */
2723 
2724 static int
callback_insert_index(gfc_expr ** e,int * walk_subtrees ATTRIBUTE_UNUSED,void * data)2725 callback_insert_index (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
2726 		       void *data)
2727 {
2728   insert_index_t *d;
2729   gfc_expr *ex, *n;
2730 
2731   ex = (*e);
2732   if (ex->expr_type != EXPR_VARIABLE)
2733     return 0;
2734 
2735   d = (insert_index_t *) data;
2736   if (ex->symtree->n.sym != d->sym)
2737     return 0;
2738 
2739   n = gfc_get_constant_expr (BT_INTEGER, ex->ts.kind, &ex->where);
2740   mpz_set (n->value.integer, d->val);
2741 
2742   gfc_free_expr (ex);
2743   *e = n;
2744   return 0;
2745 }
2746 
2747 /* In the expression e, replace occurrences of the variable sym with
2748    val.  If this results in a constant expression, return true and
2749    return the value in ret.  Return false if the expression already
2750    is a constant.  Caller has to clear ret in that case.  */
2751 
2752 static bool
insert_index(gfc_expr * e,gfc_symbol * sym,mpz_t val,mpz_t ret)2753 insert_index (gfc_expr *e, gfc_symbol *sym, mpz_t val, mpz_t ret)
2754 {
2755   gfc_expr *n;
2756   insert_index_t data;
2757   bool rc;
2758 
2759   if (e->expr_type == EXPR_CONSTANT)
2760     return false;
2761 
2762   n = gfc_copy_expr (e);
2763   data.sym = sym;
2764   mpz_init_set (data.val, val);
2765   gfc_expr_walker (&n, callback_insert_index, (void *) &data);
2766 
2767   /* Suppress errors here - we could get errors here such as an
2768      out of bounds access for arrays, see PR 90563.  */
2769   gfc_push_suppress_errors ();
2770   gfc_simplify_expr (n, 0);
2771   gfc_pop_suppress_errors ();
2772 
2773   if (n->expr_type == EXPR_CONSTANT)
2774     {
2775       rc = true;
2776       mpz_init_set (ret, n->value.integer);
2777     }
2778   else
2779     rc = false;
2780 
2781   mpz_clear (data.val);
2782   gfc_free_expr (n);
2783   return rc;
2784 
2785 }
2786 
2787 /* Check array subscripts for possible out-of-bounds accesses in DO
2788    loops with constant bounds.  */
2789 
2790 static int
do_subscript(gfc_expr ** e)2791 do_subscript (gfc_expr **e)
2792 {
2793   gfc_expr *v;
2794   gfc_array_ref *ar;
2795   gfc_ref *ref;
2796   int i,j;
2797   gfc_code *dl;
2798   do_t *lp;
2799 
2800   v = *e;
2801   /* Constants are already checked.  */
2802   if (v->expr_type == EXPR_CONSTANT)
2803     return 0;
2804 
2805   /* Wrong warnings will be generated in an associate list.  */
2806   if (in_assoc_list)
2807     return 0;
2808 
2809   /* We already warned about this.  */
2810   if (v->do_not_warn)
2811     return 0;
2812 
2813   v->do_not_warn = 1;
2814 
2815   for (ref = v->ref; ref; ref = ref->next)
2816     {
2817       if (ref->type == REF_ARRAY && ref->u.ar.type == AR_ELEMENT)
2818 	{
2819 	  ar = & ref->u.ar;
2820 	  FOR_EACH_VEC_ELT (doloop_list, j, lp)
2821 	    {
2822 	      gfc_symbol *do_sym;
2823 	      mpz_t do_start, do_step, do_end;
2824 	      bool have_do_start, have_do_end;
2825 	      bool error_not_proven;
2826 	      int warn;
2827 	      int sgn;
2828 
2829 	      dl = lp->c;
2830 	      if (dl == NULL)
2831 		break;
2832 
2833 	      /* If we are within a branch, or a goto or equivalent
2834 		 was seen in the DO loop before, then we cannot prove that
2835 		 this expression is actually evaluated.  Don't do anything
2836 		 unless we want to see it all.  */
2837 	      error_not_proven = lp->seen_goto
2838 		|| lp->branch_level < if_level + select_level;
2839 
2840 	      if (error_not_proven && !warn_do_subscript)
2841 		break;
2842 
2843 	      if (error_not_proven)
2844 		warn = OPT_Wdo_subscript;
2845 	      else
2846 		warn = 0;
2847 
2848 	      do_sym = dl->ext.iterator->var->symtree->n.sym;
2849 	      if (do_sym->ts.type != BT_INTEGER)
2850 		continue;
2851 
2852 	      /* If we do not know about the stepsize, the loop may be zero trip.
2853 		 Do not warn in this case.  */
2854 
2855 	      if (dl->ext.iterator->step->expr_type == EXPR_CONSTANT)
2856 		{
2857 		  sgn = mpz_cmp_ui (dl->ext.iterator->step->value.integer, 0);
2858 		  /* This can happen, but then the error has been
2859 		     reported previously.  */
2860 		  if (sgn == 0)
2861 		    continue;
2862 
2863 		  mpz_init_set (do_step, dl->ext.iterator->step->value.integer);
2864 		}
2865 
2866 	      else
2867 		continue;
2868 
2869 	      if (dl->ext.iterator->start->expr_type == EXPR_CONSTANT)
2870 		{
2871 		  have_do_start = true;
2872 		  mpz_init_set (do_start, dl->ext.iterator->start->value.integer);
2873 		}
2874 	      else
2875 		have_do_start = false;
2876 
2877 	      if (dl->ext.iterator->end->expr_type == EXPR_CONSTANT)
2878 		{
2879 		  have_do_end = true;
2880 		  mpz_init_set (do_end, dl->ext.iterator->end->value.integer);
2881 		}
2882 	      else
2883 		have_do_end = false;
2884 
2885 	      if (!have_do_start && !have_do_end)
2886 		return 0;
2887 
2888 	      /* No warning inside a zero-trip loop.  */
2889 	      if (have_do_start && have_do_end)
2890 		{
2891 		  int cmp;
2892 
2893 		  cmp = mpz_cmp (do_end, do_start);
2894 		  if ((sgn > 0 && cmp < 0) || (sgn < 0 && cmp > 0))
2895 		    break;
2896 		}
2897 
2898 	      /* May have to correct the end value if the step does not equal
2899 		 one.  */
2900 	      if (have_do_start && have_do_end && mpz_cmp_ui (do_step, 1) != 0)
2901 		{
2902 		  mpz_t diff, rem;
2903 
2904 		  mpz_init (diff);
2905 		  mpz_init (rem);
2906 		  mpz_sub (diff, do_end, do_start);
2907 		  mpz_tdiv_r (rem, diff, do_step);
2908 		  mpz_sub (do_end, do_end, rem);
2909 		  mpz_clear (diff);
2910 		  mpz_clear (rem);
2911 		}
2912 
2913 	      for (i = 0; i< ar->dimen; i++)
2914 		{
2915 		  mpz_t val;
2916 		  if (ar->dimen_type[i] == DIMEN_ELEMENT && have_do_start
2917 		      && insert_index (ar->start[i], do_sym, do_start, val))
2918 		    {
2919 		      if (ar->as->lower[i]
2920 			  && ar->as->lower[i]->expr_type == EXPR_CONSTANT
2921 			  && ar->as->lower[i]->ts.type == BT_INTEGER
2922 			  && mpz_cmp (val, ar->as->lower[i]->value.integer) < 0)
2923 			gfc_warning (warn, "Array reference at %L out of bounds "
2924 				     "(%ld < %ld) in loop beginning at %L",
2925 				     &ar->start[i]->where, mpz_get_si (val),
2926 				     mpz_get_si (ar->as->lower[i]->value.integer),
2927 				     &doloop_list[j].c->loc);
2928 
2929 		      if (ar->as->upper[i]
2930 			  && ar->as->upper[i]->expr_type == EXPR_CONSTANT
2931 			  && ar->as->upper[i]->ts.type == BT_INTEGER
2932 			  && mpz_cmp (val, ar->as->upper[i]->value.integer) > 0)
2933 			    gfc_warning (warn, "Array reference at %L out of bounds "
2934 					 "(%ld > %ld) in loop beginning at %L",
2935 					 &ar->start[i]->where, mpz_get_si (val),
2936 					 mpz_get_si (ar->as->upper[i]->value.integer),
2937 					 &doloop_list[j].c->loc);
2938 
2939 		      mpz_clear (val);
2940 		    }
2941 
2942 		  if (ar->dimen_type[i] == DIMEN_ELEMENT && have_do_end
2943 		      && insert_index (ar->start[i], do_sym, do_end, val))
2944 		    {
2945 		      if (ar->as->lower[i]
2946 			  && ar->as->lower[i]->expr_type == EXPR_CONSTANT
2947 			  && ar->as->lower[i]->ts.type == BT_INTEGER
2948 			  && mpz_cmp (val, ar->as->lower[i]->value.integer) < 0)
2949 			gfc_warning (warn, "Array reference at %L out of bounds "
2950 				     "(%ld < %ld) in loop beginning at %L",
2951 				     &ar->start[i]->where, mpz_get_si (val),
2952 				     mpz_get_si (ar->as->lower[i]->value.integer),
2953 				     &doloop_list[j].c->loc);
2954 
2955 		      if (ar->as->upper[i]
2956 			  && ar->as->upper[i]->expr_type == EXPR_CONSTANT
2957 			  && ar->as->upper[i]->ts.type == BT_INTEGER
2958 			  && mpz_cmp (val, ar->as->upper[i]->value.integer) > 0)
2959 			gfc_warning (warn, "Array reference at %L out of bounds "
2960 				     "(%ld > %ld) in loop beginning at %L",
2961 				     &ar->start[i]->where, mpz_get_si (val),
2962 				     mpz_get_si (ar->as->upper[i]->value.integer),
2963 				     &doloop_list[j].c->loc);
2964 
2965 		      mpz_clear (val);
2966 		    }
2967 		}
2968 	    }
2969 	}
2970     }
2971   return 0;
2972 }
2973 /* Function for functions checking that we do not pass a DO variable
2974    to an INTENT(OUT) or INTENT(INOUT) dummy variable.  */
2975 
2976 static int
do_intent(gfc_expr ** e)2977 do_intent (gfc_expr **e)
2978 {
2979   gfc_formal_arglist *f;
2980   gfc_actual_arglist *a;
2981   gfc_expr *expr;
2982   gfc_code *dl;
2983   do_t *lp;
2984   int i;
2985   gfc_symbol *sym;
2986 
2987   expr = *e;
2988   if (expr->expr_type != EXPR_FUNCTION)
2989     return 0;
2990 
2991   /* Intrinsic functions don't modify their arguments.  */
2992 
2993   if (expr->value.function.isym)
2994     return 0;
2995 
2996   sym = expr->value.function.esym;
2997   if (sym == NULL)
2998     return 0;
2999 
3000   if (sym->attr.contained)
3001     {
3002       FOR_EACH_VEC_ELT (doloop_list, i, lp)
3003 	{
3004 	  contained_info info;
3005 	  gfc_namespace *ns;
3006 
3007 	  dl = lp->c;
3008 	  info.do_var = dl->ext.iterator->var->symtree->n.sym;
3009 	  info.procedure = sym;
3010 	  info.where_do = expr->where;
3011 	  /* Look contained procedures under the namespace of the
3012 		 variable.  */
3013 	  for (ns = info.do_var->ns->contained; ns; ns = ns->sibling)
3014 	    if (ns->proc_name && ns->proc_name == sym)
3015 	      gfc_code_walker (&ns->code, doloop_contained_procedure_code,
3016 			       dummy_expr_callback, &info);
3017 	}
3018     }
3019 
3020   f = gfc_sym_get_dummy_args (sym);
3021 
3022   /* Without a formal arglist, there is only unknown INTENT,
3023      which we don't check for.  */
3024   if (f == NULL)
3025     return 0;
3026 
3027   a = expr->value.function.actual;
3028 
3029   while (a && f)
3030     {
3031       FOR_EACH_VEC_ELT (doloop_list, i, lp)
3032 	{
3033 	  gfc_symbol *do_sym;
3034 	  dl = lp->c;
3035 	  if (dl == NULL)
3036 	    break;
3037 
3038 	  do_sym = dl->ext.iterator->var->symtree->n.sym;
3039 
3040 	  if (a->expr && a->expr->symtree
3041 	      && a->expr->symtree->n.sym == do_sym)
3042 	    {
3043 	      if (f->sym->attr.intent == INTENT_OUT)
3044 		gfc_error_now ("Variable %qs at %L set to undefined value "
3045 			       "inside loop beginning at %L as INTENT(OUT) "
3046 			       "argument to function %qs", do_sym->name,
3047 			       &a->expr->where, &doloop_list[i].c->loc,
3048 			       expr->symtree->n.sym->name);
3049 	      else if (f->sym->attr.intent == INTENT_INOUT)
3050 		gfc_error_now ("Variable %qs at %L not definable inside loop"
3051 			       " beginning at %L as INTENT(INOUT) argument to"
3052 			       " function %qs", do_sym->name,
3053 			       &a->expr->where, &doloop_list[i].c->loc,
3054 			       expr->symtree->n.sym->name);
3055 	    }
3056 	}
3057       a = a->next;
3058       f = f->next;
3059     }
3060 
3061   return 0;
3062 }
3063 
3064 static void
doloop_warn(gfc_namespace * ns)3065 doloop_warn (gfc_namespace *ns)
3066 {
3067   gfc_code_walker (&ns->code, doloop_code, do_function, NULL);
3068 
3069   for (ns = ns->contained; ns; ns = ns->sibling)
3070     {
3071       if (ns->code == NULL || ns->code->op != EXEC_BLOCK)
3072 	doloop_warn (ns);
3073     }
3074 }
3075 
3076 /* This selction deals with inlining calls to MATMUL.  */
3077 
3078 /* Replace calls to matmul outside of straight assignments with a temporary
3079    variable so that later inlining will work.  */
3080 
3081 static int
matmul_to_var_expr(gfc_expr ** ep,int * walk_subtrees ATTRIBUTE_UNUSED,void * data)3082 matmul_to_var_expr (gfc_expr **ep, int *walk_subtrees ATTRIBUTE_UNUSED,
3083 		    void *data)
3084 {
3085   gfc_expr *e, *n;
3086   bool *found = (bool *) data;
3087 
3088   e = *ep;
3089 
3090   if (e->expr_type != EXPR_FUNCTION
3091       || e->value.function.isym == NULL
3092       || e->value.function.isym->id != GFC_ISYM_MATMUL)
3093     return 0;
3094 
3095   if (forall_level > 0 || iterator_level > 0 || in_omp_workshare
3096       || in_omp_atomic || in_where || in_assoc_list)
3097     return 0;
3098 
3099   /* Check if this is already in the form c = matmul(a,b).  */
3100 
3101   if ((*current_code)->expr2 == e)
3102     return 0;
3103 
3104   n = create_var (e, "matmul");
3105 
3106   /* If create_var is unable to create a variable (for example if
3107      -fno-realloc-lhs is in force with a variable that does not have bounds
3108      known at compile-time), just return.  */
3109 
3110   if (n == NULL)
3111     return 0;
3112 
3113   *ep = n;
3114   *found = true;
3115   return 0;
3116 }
3117 
3118 /* Set current_code and associated variables so that matmul_to_var_expr can
3119    work.  */
3120 
3121 static int
matmul_to_var_code(gfc_code ** c,int * walk_subtrees ATTRIBUTE_UNUSED,void * data ATTRIBUTE_UNUSED)3122 matmul_to_var_code (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
3123 		    void *data ATTRIBUTE_UNUSED)
3124 {
3125   if (current_code != c)
3126     {
3127       current_code = c;
3128       inserted_block = NULL;
3129       changed_statement = NULL;
3130     }
3131 
3132   return 0;
3133 }
3134 
3135 
3136 /* Take a statement of the shape c = matmul(a,b) and create temporaries
3137    for a and b if there is a dependency between the arguments and the
3138    result variable or if a or b are the result of calculations that cannot
3139    be handled by the inliner.  */
3140 
3141 static int
matmul_temp_args(gfc_code ** c,int * walk_subtrees ATTRIBUTE_UNUSED,void * data ATTRIBUTE_UNUSED)3142 matmul_temp_args (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
3143 		  void *data ATTRIBUTE_UNUSED)
3144 {
3145   gfc_expr *expr1, *expr2;
3146   gfc_code *co;
3147   gfc_actual_arglist *a, *b;
3148   bool a_tmp, b_tmp;
3149   gfc_expr *matrix_a, *matrix_b;
3150   bool conjg_a, conjg_b, transpose_a, transpose_b;
3151 
3152   co = *c;
3153 
3154   if (co->op != EXEC_ASSIGN)
3155     return 0;
3156 
3157   if (forall_level > 0 || iterator_level > 0 || in_omp_workshare
3158       || in_omp_atomic || in_where)
3159     return 0;
3160 
3161   /* This has some duplication with inline_matmul_assign.  This
3162      is because the creation of temporary variables could still fail,
3163      and inline_matmul_assign still needs to be able to handle these
3164      cases.  */
3165   expr1 = co->expr1;
3166   expr2 = co->expr2;
3167 
3168   if (expr2->expr_type != EXPR_FUNCTION
3169       || expr2->value.function.isym == NULL
3170       || expr2->value.function.isym->id != GFC_ISYM_MATMUL)
3171     return 0;
3172 
3173   a_tmp = false;
3174   a = expr2->value.function.actual;
3175   matrix_a = check_conjg_transpose_variable (a->expr, &conjg_a, &transpose_a);
3176   if (matrix_a != NULL)
3177     {
3178       if (matrix_a->expr_type == EXPR_VARIABLE
3179 	  && (gfc_check_dependency (matrix_a, expr1, true)
3180 	      || gfc_has_dimen_vector_ref (matrix_a)))
3181 	a_tmp = true;
3182     }
3183   else
3184     a_tmp = true;
3185 
3186   b_tmp = false;
3187   b = a->next;
3188   matrix_b = check_conjg_transpose_variable (b->expr, &conjg_b, &transpose_b);
3189   if (matrix_b != NULL)
3190     {
3191       if (matrix_b->expr_type == EXPR_VARIABLE
3192 	  && (gfc_check_dependency (matrix_b, expr1, true)
3193 	      || gfc_has_dimen_vector_ref (matrix_b)))
3194 	b_tmp = true;
3195     }
3196   else
3197     b_tmp = true;
3198 
3199   if (!a_tmp && !b_tmp)
3200     return 0;
3201 
3202   current_code = c;
3203   inserted_block = NULL;
3204   changed_statement = NULL;
3205   if (a_tmp)
3206     {
3207       gfc_expr *at;
3208       at = create_var (a->expr,"mma");
3209       if (at)
3210 	a->expr = at;
3211     }
3212   if (b_tmp)
3213     {
3214       gfc_expr *bt;
3215       bt = create_var (b->expr,"mmb");
3216       if (bt)
3217 	b->expr = bt;
3218     }
3219   return 0;
3220 }
3221 
3222 /* Auxiliary function to build and simplify an array inquiry function.
3223    dim is zero-based.  */
3224 
3225 static gfc_expr *
get_array_inq_function(gfc_isym_id id,gfc_expr * e,int dim,int okind=0)3226 get_array_inq_function (gfc_isym_id id, gfc_expr *e, int dim, int okind = 0)
3227 {
3228   gfc_expr *fcn;
3229   gfc_expr *dim_arg, *kind;
3230   const char *name;
3231   gfc_expr *ec;
3232 
3233   switch (id)
3234     {
3235     case GFC_ISYM_LBOUND:
3236       name = "_gfortran_lbound";
3237       break;
3238 
3239     case GFC_ISYM_UBOUND:
3240       name = "_gfortran_ubound";
3241       break;
3242 
3243     case GFC_ISYM_SIZE:
3244       name = "_gfortran_size";
3245       break;
3246 
3247     default:
3248       gcc_unreachable ();
3249     }
3250 
3251   dim_arg =  gfc_get_int_expr (gfc_default_integer_kind, &e->where, dim);
3252   if (okind != 0)
3253     kind = gfc_get_int_expr (gfc_default_integer_kind, &e->where,
3254 			     okind);
3255   else
3256     kind = gfc_get_int_expr (gfc_default_integer_kind, &e->where,
3257 			     gfc_index_integer_kind);
3258 
3259   ec = gfc_copy_expr (e);
3260 
3261   /* No bounds checking, this will be done before the loops if -fcheck=bounds
3262      is in effect.  */
3263   ec->no_bounds_check = 1;
3264   fcn = gfc_build_intrinsic_call (current_ns, id, name, e->where, 3,
3265 				  ec, dim_arg,  kind);
3266   gfc_simplify_expr (fcn, 0);
3267   fcn->no_bounds_check = 1;
3268   return fcn;
3269 }
3270 
3271 /* Builds a logical expression.  */
3272 
3273 static gfc_expr*
build_logical_expr(gfc_intrinsic_op op,gfc_expr * e1,gfc_expr * e2)3274 build_logical_expr (gfc_intrinsic_op op, gfc_expr *e1, gfc_expr *e2)
3275 {
3276   gfc_typespec ts;
3277   gfc_expr *res;
3278 
3279   ts.type = BT_LOGICAL;
3280   ts.kind = gfc_default_logical_kind;
3281   res = gfc_get_expr ();
3282   res->where = e1->where;
3283   res->expr_type = EXPR_OP;
3284   res->value.op.op = op;
3285   res->value.op.op1 = e1;
3286   res->value.op.op2 = e2;
3287   res->ts = ts;
3288 
3289   return res;
3290 }
3291 
3292 
3293 /* Return an operation of one two gfc_expr (one if e2 is NULL). This assumes
3294    compatible typespecs.  */
3295 
3296 static gfc_expr *
get_operand(gfc_intrinsic_op op,gfc_expr * e1,gfc_expr * e2)3297 get_operand (gfc_intrinsic_op op, gfc_expr *e1, gfc_expr *e2)
3298 {
3299   gfc_expr *res;
3300 
3301   res = gfc_get_expr ();
3302   res->ts = e1->ts;
3303   res->where = e1->where;
3304   res->expr_type = EXPR_OP;
3305   res->value.op.op = op;
3306   res->value.op.op1 = e1;
3307   res->value.op.op2 = e2;
3308   gfc_simplify_expr (res, 0);
3309   return res;
3310 }
3311 
3312 /* Generate the IF statement for a runtime check if we want to do inlining or
3313    not - putting in the code for both branches and putting it into the syntax
3314    tree is the caller's responsibility.  For fixed array sizes, this should be
3315    removed by DCE. Only called for rank-two matrices A and B.  */
3316 
3317 static gfc_code *
inline_limit_check(gfc_expr * a,gfc_expr * b,int limit,int rank_a)3318 inline_limit_check (gfc_expr *a, gfc_expr *b, int limit, int rank_a)
3319 {
3320   gfc_expr *inline_limit;
3321   gfc_code *if_1, *if_2, *else_2;
3322   gfc_expr *b2, *a2, *a1, *m1, *m2;
3323   gfc_typespec ts;
3324   gfc_expr *cond;
3325 
3326   gcc_assert (rank_a == 1 || rank_a == 2);
3327 
3328   /* Calculation is done in real to avoid integer overflow.  */
3329 
3330   inline_limit = gfc_get_constant_expr (BT_REAL, gfc_default_real_kind,
3331 					&a->where);
3332   mpfr_set_si (inline_limit->value.real, limit, GFC_RND_MODE);
3333 
3334   /* Set the limit according to the rank.  */
3335   mpfr_pow_ui (inline_limit->value.real, inline_limit->value.real, rank_a + 1,
3336 	       GFC_RND_MODE);
3337 
3338   a1 = get_array_inq_function (GFC_ISYM_SIZE, a, 1);
3339 
3340   /* For a_rank = 1, must use one as the size of a along the second
3341      dimension as to avoid too much code duplication.  */
3342 
3343   if (rank_a == 2)
3344     a2 = get_array_inq_function (GFC_ISYM_SIZE, a, 2);
3345   else
3346     a2 = gfc_get_int_expr (gfc_index_integer_kind, &a->where, 1);
3347 
3348   b2 = get_array_inq_function (GFC_ISYM_SIZE, b, 2);
3349 
3350   gfc_clear_ts (&ts);
3351   ts.type = BT_REAL;
3352   ts.kind = gfc_default_real_kind;
3353   gfc_convert_type_warn (a1, &ts, 2, 0);
3354   gfc_convert_type_warn (a2, &ts, 2, 0);
3355   gfc_convert_type_warn (b2, &ts, 2, 0);
3356 
3357   m1 = get_operand (INTRINSIC_TIMES, a1, a2);
3358   m2 = get_operand (INTRINSIC_TIMES, m1, b2);
3359 
3360   cond = build_logical_expr (INTRINSIC_LE, m2, inline_limit);
3361   gfc_simplify_expr (cond, 0);
3362 
3363   else_2 = XCNEW (gfc_code);
3364   else_2->op = EXEC_IF;
3365   else_2->loc = a->where;
3366 
3367   if_2 = XCNEW (gfc_code);
3368   if_2->op = EXEC_IF;
3369   if_2->expr1 = cond;
3370   if_2->loc = a->where;
3371   if_2->block = else_2;
3372 
3373   if_1 = XCNEW (gfc_code);
3374   if_1->op = EXEC_IF;
3375   if_1->block = if_2;
3376   if_1->loc = a->where;
3377 
3378   return if_1;
3379 }
3380 
3381 
3382 /* Insert code to issue a runtime error if the expressions are not equal.  */
3383 
3384 static gfc_code *
runtime_error_ne(gfc_expr * e1,gfc_expr * e2,const char * msg)3385 runtime_error_ne (gfc_expr *e1, gfc_expr *e2, const char *msg)
3386 {
3387   gfc_expr *cond;
3388   gfc_code *if_1, *if_2;
3389   gfc_code *c;
3390   gfc_actual_arglist *a1, *a2, *a3;
3391 
3392   gcc_assert (e1->where.lb);
3393   /* Build the call to runtime_error.  */
3394   c = XCNEW (gfc_code);
3395   c->op = EXEC_CALL;
3396   c->loc = e1->where;
3397 
3398   /* Get a null-terminated message string.  */
3399 
3400   a1 = gfc_get_actual_arglist ();
3401   a1->expr = gfc_get_character_expr (gfc_default_character_kind, &e1->where,
3402 				     msg, strlen(msg)+1);
3403   c->ext.actual = a1;
3404 
3405   /* Pass the value of the first expression.  */
3406   a2 = gfc_get_actual_arglist ();
3407   a2->expr = gfc_copy_expr (e1);
3408   a1->next = a2;
3409 
3410   /* Pass the value of the second expression.  */
3411   a3 = gfc_get_actual_arglist ();
3412   a3->expr = gfc_copy_expr (e2);
3413   a2->next = a3;
3414 
3415   gfc_check_fe_runtime_error (c->ext.actual);
3416   gfc_resolve_fe_runtime_error (c);
3417 
3418   if_2 = XCNEW (gfc_code);
3419   if_2->op = EXEC_IF;
3420   if_2->loc = e1->where;
3421   if_2->next = c;
3422 
3423   if_1 = XCNEW (gfc_code);
3424   if_1->op = EXEC_IF;
3425   if_1->block = if_2;
3426   if_1->loc = e1->where;
3427 
3428   cond = build_logical_expr (INTRINSIC_NE, e1, e2);
3429   gfc_simplify_expr (cond, 0);
3430   if_2->expr1 = cond;
3431 
3432   return if_1;
3433 }
3434 
3435 /* Handle matrix reallocation.  Caller is responsible to insert into
3436    the code tree.
3437 
3438    For the two-dimensional case, build
3439 
3440   if (allocated(c)) then
3441      if (size(c,1) /= size(a,1) .or. size(c,2) /= size(b,2)) then
3442         deallocate(c)
3443         allocate (c(size(a,1), size(b,2)))
3444      end if
3445   else
3446      allocate (c(size(a,1),size(b,2)))
3447   end if
3448 
3449   and for the other cases correspondingly.
3450 */
3451 
3452 static gfc_code *
matmul_lhs_realloc(gfc_expr * c,gfc_expr * a,gfc_expr * b,enum matrix_case m_case)3453 matmul_lhs_realloc (gfc_expr *c, gfc_expr *a, gfc_expr *b,
3454 		    enum matrix_case m_case)
3455 {
3456 
3457   gfc_expr *allocated, *alloc_expr;
3458   gfc_code *if_alloc_1, *if_alloc_2, *if_size_1, *if_size_2;
3459   gfc_code *else_alloc;
3460   gfc_code *deallocate, *allocate1, *allocate_else;
3461   gfc_array_ref *ar;
3462   gfc_expr *cond, *ne1, *ne2;
3463 
3464   if (warn_realloc_lhs)
3465     gfc_warning (OPT_Wrealloc_lhs,
3466 		 "Code for reallocating the allocatable array at %L will "
3467 		 "be added", &c->where);
3468 
3469   alloc_expr = gfc_copy_expr (c);
3470 
3471   ar = gfc_find_array_ref (alloc_expr);
3472   gcc_assert (ar && ar->type == AR_FULL);
3473 
3474   /* c comes in as a full ref.  Change it into a copy and make it into an
3475      element ref so it has the right form for ALLOCATE.  In the same
3476      switch statement, also generate the size comparison for the secod IF
3477      statement.  */
3478 
3479   ar->type = AR_ELEMENT;
3480 
3481   switch (m_case)
3482     {
3483     case A2B2:
3484       ar->start[0] = get_array_inq_function (GFC_ISYM_SIZE, a, 1);
3485       ar->start[1] = get_array_inq_function (GFC_ISYM_SIZE, b, 2);
3486       ne1 = build_logical_expr (INTRINSIC_NE,
3487 				get_array_inq_function (GFC_ISYM_SIZE, c, 1),
3488 				get_array_inq_function (GFC_ISYM_SIZE, a, 1));
3489       ne2 = build_logical_expr (INTRINSIC_NE,
3490 				get_array_inq_function (GFC_ISYM_SIZE, c, 2),
3491 				get_array_inq_function (GFC_ISYM_SIZE, b, 2));
3492       cond = build_logical_expr (INTRINSIC_OR, ne1, ne2);
3493       break;
3494 
3495     case A2B2T:
3496       ar->start[0] = get_array_inq_function (GFC_ISYM_SIZE, a, 1);
3497       ar->start[1] = get_array_inq_function (GFC_ISYM_SIZE, b, 1);
3498 
3499       ne1 = build_logical_expr (INTRINSIC_NE,
3500 				get_array_inq_function (GFC_ISYM_SIZE, c, 1),
3501 				get_array_inq_function (GFC_ISYM_SIZE, a, 1));
3502       ne2 = build_logical_expr (INTRINSIC_NE,
3503 				get_array_inq_function (GFC_ISYM_SIZE, c, 2),
3504 				get_array_inq_function (GFC_ISYM_SIZE, b, 1));
3505       cond = build_logical_expr (INTRINSIC_OR, ne1, ne2);
3506       break;
3507 
3508     case A2TB2:
3509 
3510       ar->start[0] = get_array_inq_function (GFC_ISYM_SIZE, a, 2);
3511       ar->start[1] = get_array_inq_function (GFC_ISYM_SIZE, b, 2);
3512 
3513       ne1 = build_logical_expr (INTRINSIC_NE,
3514 				get_array_inq_function (GFC_ISYM_SIZE, c, 1),
3515 				get_array_inq_function (GFC_ISYM_SIZE, a, 2));
3516       ne2 = build_logical_expr (INTRINSIC_NE,
3517 				get_array_inq_function (GFC_ISYM_SIZE, c, 2),
3518 				get_array_inq_function (GFC_ISYM_SIZE, b, 2));
3519       cond = build_logical_expr (INTRINSIC_OR, ne1, ne2);
3520       break;
3521 
3522     case A2B1:
3523       ar->start[0] = get_array_inq_function (GFC_ISYM_SIZE, a, 1);
3524       cond = build_logical_expr (INTRINSIC_NE,
3525 				 get_array_inq_function (GFC_ISYM_SIZE, c, 1),
3526 				 get_array_inq_function (GFC_ISYM_SIZE, a, 2));
3527       break;
3528 
3529     case A1B2:
3530       ar->start[0] = get_array_inq_function (GFC_ISYM_SIZE, b, 2);
3531       cond = build_logical_expr (INTRINSIC_NE,
3532 				 get_array_inq_function (GFC_ISYM_SIZE, c, 1),
3533 				 get_array_inq_function (GFC_ISYM_SIZE, b, 2));
3534       break;
3535 
3536     case A2TB2T:
3537       /* This can only happen for BLAS, we do not handle that case in
3538 	 inline mamtul.  */
3539       ar->start[0] = get_array_inq_function (GFC_ISYM_SIZE, a, 2);
3540       ar->start[1] = get_array_inq_function (GFC_ISYM_SIZE, b, 1);
3541 
3542       ne1 = build_logical_expr (INTRINSIC_NE,
3543 				get_array_inq_function (GFC_ISYM_SIZE, c, 1),
3544 				get_array_inq_function (GFC_ISYM_SIZE, a, 2));
3545       ne2 = build_logical_expr (INTRINSIC_NE,
3546 				get_array_inq_function (GFC_ISYM_SIZE, c, 2),
3547 				get_array_inq_function (GFC_ISYM_SIZE, b, 1));
3548 
3549       cond = build_logical_expr (INTRINSIC_OR, ne1, ne2);
3550       break;
3551 
3552     default:
3553       gcc_unreachable();
3554 
3555     }
3556 
3557   gfc_simplify_expr (cond, 0);
3558 
3559   /* We need two identical allocate statements in two
3560      branches of the IF statement.  */
3561 
3562   allocate1 = XCNEW (gfc_code);
3563   allocate1->op = EXEC_ALLOCATE;
3564   allocate1->ext.alloc.list = gfc_get_alloc ();
3565   allocate1->loc = c->where;
3566   allocate1->ext.alloc.list->expr = gfc_copy_expr (alloc_expr);
3567 
3568   allocate_else = XCNEW (gfc_code);
3569   allocate_else->op = EXEC_ALLOCATE;
3570   allocate_else->ext.alloc.list = gfc_get_alloc ();
3571   allocate_else->loc = c->where;
3572   allocate_else->ext.alloc.list->expr = alloc_expr;
3573 
3574   allocated = gfc_build_intrinsic_call (current_ns, GFC_ISYM_ALLOCATED,
3575 					"_gfortran_allocated", c->where,
3576 					1, gfc_copy_expr (c));
3577 
3578   deallocate = XCNEW (gfc_code);
3579   deallocate->op = EXEC_DEALLOCATE;
3580   deallocate->ext.alloc.list = gfc_get_alloc ();
3581   deallocate->ext.alloc.list->expr = gfc_copy_expr (c);
3582   deallocate->next = allocate1;
3583   deallocate->loc = c->where;
3584 
3585   if_size_2 = XCNEW (gfc_code);
3586   if_size_2->op = EXEC_IF;
3587   if_size_2->expr1 = cond;
3588   if_size_2->loc = c->where;
3589   if_size_2->next = deallocate;
3590 
3591   if_size_1 = XCNEW (gfc_code);
3592   if_size_1->op = EXEC_IF;
3593   if_size_1->block = if_size_2;
3594   if_size_1->loc = c->where;
3595 
3596   else_alloc = XCNEW (gfc_code);
3597   else_alloc->op = EXEC_IF;
3598   else_alloc->loc = c->where;
3599   else_alloc->next = allocate_else;
3600 
3601   if_alloc_2 = XCNEW (gfc_code);
3602   if_alloc_2->op = EXEC_IF;
3603   if_alloc_2->expr1 = allocated;
3604   if_alloc_2->loc = c->where;
3605   if_alloc_2->next = if_size_1;
3606   if_alloc_2->block = else_alloc;
3607 
3608   if_alloc_1 = XCNEW (gfc_code);
3609   if_alloc_1->op = EXEC_IF;
3610   if_alloc_1->block = if_alloc_2;
3611   if_alloc_1->loc = c->where;
3612 
3613   return if_alloc_1;
3614 }
3615 
3616 /* Callback function for has_function_or_op.  */
3617 
3618 static int
is_function_or_op(gfc_expr ** e,int * walk_subtrees ATTRIBUTE_UNUSED,void * data ATTRIBUTE_UNUSED)3619 is_function_or_op (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
3620 	     void *data ATTRIBUTE_UNUSED)
3621 {
3622   if ((*e) == 0)
3623     return 0;
3624   else
3625     return (*e)->expr_type == EXPR_FUNCTION
3626       || (*e)->expr_type == EXPR_OP;
3627 }
3628 
3629 /* Returns true if the expression contains a function.  */
3630 
3631 static bool
has_function_or_op(gfc_expr ** e)3632 has_function_or_op (gfc_expr **e)
3633 {
3634   if (e == NULL)
3635     return false;
3636   else
3637     return gfc_expr_walker (e, is_function_or_op, NULL);
3638 }
3639 
3640 /* Freeze (assign to a temporary variable) a single expression.  */
3641 
3642 static void
freeze_expr(gfc_expr ** ep)3643 freeze_expr (gfc_expr **ep)
3644 {
3645   gfc_expr *ne;
3646   if (has_function_or_op (ep))
3647     {
3648       ne = create_var (*ep, "freeze");
3649       *ep = ne;
3650     }
3651 }
3652 
3653 /* Go through an expression's references and assign them to temporary
3654    variables if they contain functions.  This is usually done prior to
3655    front-end scalarization to avoid multiple invocations of functions.  */
3656 
3657 static void
freeze_references(gfc_expr * e)3658 freeze_references (gfc_expr *e)
3659 {
3660   gfc_ref *r;
3661   gfc_array_ref *ar;
3662   int i;
3663 
3664   for (r=e->ref; r; r=r->next)
3665     {
3666       if (r->type == REF_SUBSTRING)
3667 	{
3668 	  if (r->u.ss.start != NULL)
3669 	    freeze_expr (&r->u.ss.start);
3670 
3671 	  if (r->u.ss.end != NULL)
3672 	    freeze_expr (&r->u.ss.end);
3673 	}
3674       else if (r->type == REF_ARRAY)
3675 	{
3676 	  ar = &r->u.ar;
3677 	  switch (ar->type)
3678 	    {
3679 	    case AR_FULL:
3680 	      break;
3681 
3682 	    case AR_SECTION:
3683 	      for (i=0; i<ar->dimen; i++)
3684 		{
3685 		  if (ar->dimen_type[i] == DIMEN_RANGE)
3686 		    {
3687 		      freeze_expr (&ar->start[i]);
3688 		      freeze_expr (&ar->end[i]);
3689 		      freeze_expr (&ar->stride[i]);
3690 		    }
3691 		  else if (ar->dimen_type[i] == DIMEN_ELEMENT)
3692 		    {
3693 		      freeze_expr (&ar->start[i]);
3694 		    }
3695 		}
3696 	      break;
3697 
3698 	    case AR_ELEMENT:
3699 	      for (i=0; i<ar->dimen; i++)
3700 		freeze_expr (&ar->start[i]);
3701 	      break;
3702 
3703 	    default:
3704 	      break;
3705 	    }
3706 	}
3707     }
3708 }
3709 
3710 /* Convert to gfc_index_integer_kind if needed, just do a copy otherwise.  */
3711 
3712 static gfc_expr *
convert_to_index_kind(gfc_expr * e)3713 convert_to_index_kind (gfc_expr *e)
3714 {
3715   gfc_expr *res;
3716 
3717   gcc_assert (e != NULL);
3718 
3719   res = gfc_copy_expr (e);
3720 
3721   gcc_assert (e->ts.type == BT_INTEGER);
3722 
3723   if (res->ts.kind != gfc_index_integer_kind)
3724     {
3725       gfc_typespec ts;
3726       gfc_clear_ts (&ts);
3727       ts.type = BT_INTEGER;
3728       ts.kind = gfc_index_integer_kind;
3729 
3730       gfc_convert_type_warn (e, &ts, 2, 0);
3731     }
3732 
3733   return res;
3734 }
3735 
3736 /* Function to create a DO loop including creation of the
3737    iteration variable.  gfc_expr are copied.*/
3738 
3739 static gfc_code *
create_do_loop(gfc_expr * start,gfc_expr * end,gfc_expr * step,locus * where,gfc_namespace * ns,char * vname)3740 create_do_loop (gfc_expr *start, gfc_expr *end, gfc_expr *step, locus *where,
3741 		gfc_namespace *ns, char *vname)
3742 {
3743 
3744   char name[GFC_MAX_SYMBOL_LEN +1];
3745   gfc_symtree *symtree;
3746   gfc_symbol *symbol;
3747   gfc_expr *i;
3748   gfc_code *n, *n2;
3749 
3750   /* Create an expression for the iteration variable.  */
3751   if (vname)
3752     sprintf (name, "__var_%d_do_%s", var_num++, vname);
3753   else
3754     sprintf (name, "__var_%d_do", var_num++);
3755 
3756 
3757   if (gfc_get_sym_tree (name, ns, &symtree, false) != 0)
3758     gcc_unreachable ();
3759 
3760   /* Create the loop variable.  */
3761 
3762   symbol = symtree->n.sym;
3763   symbol->ts.type = BT_INTEGER;
3764   symbol->ts.kind = gfc_index_integer_kind;
3765   symbol->attr.flavor = FL_VARIABLE;
3766   symbol->attr.referenced = 1;
3767   symbol->attr.dimension = 0;
3768   symbol->attr.fe_temp = 1;
3769   gfc_commit_symbol (symbol);
3770 
3771   i = gfc_get_expr ();
3772   i->expr_type = EXPR_VARIABLE;
3773   i->ts = symbol->ts;
3774   i->rank = 0;
3775   i->where = *where;
3776   i->symtree = symtree;
3777 
3778   /* ... and the nested DO statements.  */
3779   n = XCNEW (gfc_code);
3780   n->op = EXEC_DO;
3781   n->loc = *where;
3782   n->ext.iterator = gfc_get_iterator ();
3783   n->ext.iterator->var = i;
3784   n->ext.iterator->start = convert_to_index_kind (start);
3785   n->ext.iterator->end = convert_to_index_kind (end);
3786   if (step)
3787     n->ext.iterator->step = convert_to_index_kind (step);
3788   else
3789     n->ext.iterator->step = gfc_get_int_expr (gfc_index_integer_kind,
3790 					      where, 1);
3791 
3792   n2 = XCNEW (gfc_code);
3793   n2->op = EXEC_DO;
3794   n2->loc = *where;
3795   n2->next = NULL;
3796   n->block = n2;
3797   return n;
3798 }
3799 
3800 /* Get the upper bound of the DO loops for matmul along a dimension.  This
3801  is one-based.  */
3802 
3803 static gfc_expr*
get_size_m1(gfc_expr * e,int dimen)3804 get_size_m1 (gfc_expr *e, int dimen)
3805 {
3806   mpz_t size;
3807   gfc_expr *res;
3808 
3809   if (gfc_array_dimen_size (e, dimen - 1, &size))
3810     {
3811       res = gfc_get_constant_expr (BT_INTEGER,
3812 				   gfc_index_integer_kind, &e->where);
3813       mpz_sub_ui (res->value.integer, size, 1);
3814       mpz_clear (size);
3815     }
3816   else
3817     {
3818       res = get_operand (INTRINSIC_MINUS,
3819 			 get_array_inq_function (GFC_ISYM_SIZE, e, dimen),
3820 			 gfc_get_int_expr (gfc_index_integer_kind,
3821 					   &e->where, 1));
3822       gfc_simplify_expr (res, 0);
3823     }
3824 
3825   return res;
3826 }
3827 
3828 /* Function to return a scalarized expression. It is assumed that indices are
3829  zero based to make generation of DO loops easier.  A zero as index will
3830  access the first element along a dimension.  Single element references will
3831  be skipped.  A NULL as an expression will be replaced by a full reference.
3832  This assumes that the index loops have gfc_index_integer_kind, and that all
3833  references have been frozen.  */
3834 
3835 static gfc_expr*
scalarized_expr(gfc_expr * e_in,gfc_expr ** index,int count_index)3836 scalarized_expr (gfc_expr *e_in, gfc_expr **index, int count_index)
3837 {
3838   gfc_array_ref *ar;
3839   int i;
3840   int rank;
3841   gfc_expr *e;
3842   int i_index;
3843   bool was_fullref;
3844 
3845   e = gfc_copy_expr(e_in);
3846 
3847   rank = e->rank;
3848 
3849   ar = gfc_find_array_ref (e);
3850 
3851   /* We scalarize count_index variables, reducing the rank by count_index.  */
3852 
3853   e->rank = rank - count_index;
3854 
3855   was_fullref = ar->type == AR_FULL;
3856 
3857   if (e->rank == 0)
3858     ar->type = AR_ELEMENT;
3859   else
3860     ar->type = AR_SECTION;
3861 
3862   /* Loop over the indices.  For each index, create the expression
3863      index * stride + lbound(e, dim).  */
3864 
3865   i_index = 0;
3866   for (i=0; i < ar->dimen; i++)
3867     {
3868       if (was_fullref || ar->dimen_type[i] == DIMEN_RANGE)
3869 	{
3870 	  if (index[i_index] != NULL)
3871 	    {
3872 	      gfc_expr *lbound, *nindex;
3873 	      gfc_expr *loopvar;
3874 
3875 	      loopvar = gfc_copy_expr (index[i_index]);
3876 
3877 	      if (ar->stride[i])
3878 		{
3879 		  gfc_expr *tmp;
3880 
3881 		  tmp = gfc_copy_expr(ar->stride[i]);
3882 		  if (tmp->ts.kind != gfc_index_integer_kind)
3883 		    {
3884 		      gfc_typespec ts;
3885 		      gfc_clear_ts (&ts);
3886 		      ts.type = BT_INTEGER;
3887 		      ts.kind = gfc_index_integer_kind;
3888 		      gfc_convert_type (tmp, &ts, 2);
3889 		    }
3890 		  nindex = get_operand (INTRINSIC_TIMES, loopvar, tmp);
3891 		}
3892 	      else
3893 		nindex = loopvar;
3894 
3895 	      /* Calculate the lower bound of the expression.  */
3896 	      if (ar->start[i])
3897 		{
3898 		  lbound = gfc_copy_expr (ar->start[i]);
3899 		  if (lbound->ts.kind != gfc_index_integer_kind)
3900 		    {
3901 		      gfc_typespec ts;
3902 		      gfc_clear_ts (&ts);
3903 		      ts.type = BT_INTEGER;
3904 		      ts.kind = gfc_index_integer_kind;
3905 		      gfc_convert_type (lbound, &ts, 2);
3906 
3907 		    }
3908 		}
3909 	      else
3910 		{
3911 		  gfc_expr *lbound_e;
3912 		  gfc_ref *ref;
3913 
3914 		  lbound_e = gfc_copy_expr (e_in);
3915 
3916 		  for (ref = lbound_e->ref; ref; ref = ref->next)
3917 		    if (ref->type == REF_ARRAY
3918 			&& (ref->u.ar.type == AR_FULL
3919 			    || ref->u.ar.type == AR_SECTION))
3920 		      break;
3921 
3922 		  if (ref->next)
3923 		    {
3924 		      gfc_free_ref_list (ref->next);
3925 		      ref->next = NULL;
3926 		    }
3927 
3928 		  if (!was_fullref)
3929 		    {
3930 		      /* Look at full individual sections, like a(:).  The first index
3931 			 is the lbound of a full ref.  */
3932 		      int j;
3933 		      gfc_array_ref *ar;
3934 		      int to;
3935 
3936 		      ar = &ref->u.ar;
3937 
3938 		      /* For assumed size, we need to keep around the final
3939 			 reference in order not to get an error on resolution
3940 			 below, and we cannot use AR_FULL.  */
3941 
3942 		      if (ar->as->type == AS_ASSUMED_SIZE)
3943 			{
3944 			  ar->type = AR_SECTION;
3945 			  to = ar->dimen - 1;
3946 			}
3947 		      else
3948 			{
3949 			  to = ar->dimen;
3950 			  ar->type = AR_FULL;
3951 			}
3952 
3953 		      for (j = 0; j < to; j++)
3954 			{
3955 			  gfc_free_expr (ar->start[j]);
3956 			  ar->start[j] = NULL;
3957 			  gfc_free_expr (ar->end[j]);
3958 			  ar->end[j] = NULL;
3959 			  gfc_free_expr (ar->stride[j]);
3960 			  ar->stride[j] = NULL;
3961 			}
3962 
3963 		      /* We have to get rid of the shape, if there is one.  Do
3964 			 so by freeing it and calling gfc_resolve to rebuild
3965 			 it, if necessary.  */
3966 
3967 		      if (lbound_e->shape)
3968 			gfc_free_shape (&(lbound_e->shape), lbound_e->rank);
3969 
3970 		      lbound_e->rank = ar->dimen;
3971 		      gfc_resolve_expr (lbound_e);
3972 		    }
3973 		  lbound = get_array_inq_function (GFC_ISYM_LBOUND, lbound_e,
3974 						   i + 1);
3975 		  gfc_free_expr (lbound_e);
3976 		}
3977 
3978 	      ar->dimen_type[i] = DIMEN_ELEMENT;
3979 
3980 	      gfc_free_expr (ar->start[i]);
3981 	      ar->start[i] = get_operand (INTRINSIC_PLUS, nindex, lbound);
3982 
3983 	      gfc_free_expr (ar->end[i]);
3984 	      ar->end[i] = NULL;
3985 	      gfc_free_expr (ar->stride[i]);
3986 	      ar->stride[i] = NULL;
3987 	      gfc_simplify_expr (ar->start[i], 0);
3988 	    }
3989 	  else if (was_fullref)
3990 	    {
3991 	      gfc_internal_error ("Scalarization using DIMEN_RANGE unimplemented");
3992 	    }
3993 	  i_index ++;
3994 	}
3995     }
3996 
3997   /* Bounds checking will be done before the loops if -fcheck=bounds
3998      is in effect. */
3999   e->no_bounds_check = 1;
4000   return e;
4001 }
4002 
4003 /* Helper function to check for a dimen vector as subscript.  */
4004 
4005 bool
gfc_has_dimen_vector_ref(gfc_expr * e)4006 gfc_has_dimen_vector_ref (gfc_expr *e)
4007 {
4008   gfc_array_ref *ar;
4009   int i;
4010 
4011   ar = gfc_find_array_ref (e);
4012   gcc_assert (ar);
4013   if (ar->type == AR_FULL)
4014     return false;
4015 
4016   for (i=0; i<ar->dimen; i++)
4017     if (ar->dimen_type[i] == DIMEN_VECTOR)
4018       return true;
4019 
4020   return false;
4021 }
4022 
4023 /* If handed an expression of the form
4024 
4025    TRANSPOSE(CONJG(A))
4026 
4027    check if A can be handled by matmul and return if there is an uneven number
4028    of CONJG calls.  Return a pointer to the array when everything is OK, NULL
4029    otherwise. The caller has to check for the correct rank.  */
4030 
4031 static gfc_expr*
check_conjg_transpose_variable(gfc_expr * e,bool * conjg,bool * transpose)4032 check_conjg_transpose_variable (gfc_expr *e, bool *conjg, bool *transpose)
4033 {
4034   *conjg = false;
4035   *transpose = false;
4036 
4037   do
4038     {
4039       if (e->expr_type == EXPR_VARIABLE)
4040 	{
4041 	  gcc_assert (e->rank == 1 || e->rank == 2);
4042 	  return e;
4043 	}
4044       else if (e->expr_type == EXPR_FUNCTION)
4045 	{
4046 	  if (e->value.function.isym == NULL)
4047 	    return NULL;
4048 
4049 	  if (e->value.function.isym->id == GFC_ISYM_CONJG)
4050 	    *conjg = !*conjg;
4051 	  else if (e->value.function.isym->id == GFC_ISYM_TRANSPOSE)
4052 	    *transpose = !*transpose;
4053 	  else return NULL;
4054 	}
4055       else
4056 	return NULL;
4057 
4058       e = e->value.function.actual->expr;
4059     }
4060   while(1);
4061 
4062   return NULL;
4063 }
4064 
4065 /* Macros for unified error messages.  */
4066 
4067 #define B_ERROR_1 _("Incorrect extent in argument B in MATMUL intrinsic in " \
4068 		     "dimension 1: is %ld, should be %ld")
4069 
4070 #define C_ERROR_1 _("Array bound mismatch for dimension 1 of array " \
4071 		    "(%ld/%ld)")
4072 
4073 #define C_ERROR_2 _("Array bound mismatch for dimension 2 of array " \
4074 		    "(%ld/%ld)")
4075 
4076 
4077 /* Inline assignments of the form c = matmul(a,b).
4078    Handle only the cases currently where b and c are rank-two arrays.
4079 
4080    This basically translates the code to
4081 
4082    BLOCK
4083      integer i,j,k
4084      c = 0
4085      do j=0, size(b,2)-1
4086        do k=0, size(a, 2)-1
4087          do i=0, size(a, 1)-1
4088             c(i * stride(c,1) + lbound(c,1), j * stride(c,2) + lbound(c,2)) =
4089 	    c(i * stride(c,1) + lbound(c,1), j * stride(c,2) + lbound(c,2)) +
4090             a(i * stride(a,1) + lbound(a,1), k * stride(a,2) + lbound(a,2)) *
4091             b(k * stride(b,1) + lbound(b,1), j * stride(b,2) + lbound(b,2))
4092          end do
4093        end do
4094      end do
4095    END BLOCK
4096 
4097 */
4098 
4099 static int
inline_matmul_assign(gfc_code ** c,int * walk_subtrees,void * data ATTRIBUTE_UNUSED)4100 inline_matmul_assign (gfc_code **c, int *walk_subtrees,
4101 			  void *data ATTRIBUTE_UNUSED)
4102 {
4103   gfc_code *co = *c;
4104   gfc_expr *expr1, *expr2;
4105   gfc_expr *matrix_a, *matrix_b;
4106   gfc_actual_arglist *a, *b;
4107   gfc_code *do_1, *do_2, *do_3, *assign_zero, *assign_matmul;
4108   gfc_expr *zero_e;
4109   gfc_expr *u1, *u2, *u3;
4110   gfc_expr *list[2];
4111   gfc_expr *ascalar, *bscalar, *cscalar;
4112   gfc_expr *mult;
4113   gfc_expr *var_1, *var_2, *var_3;
4114   gfc_expr *zero;
4115   gfc_namespace *ns;
4116   gfc_intrinsic_op op_times, op_plus;
4117   enum matrix_case m_case;
4118   int i;
4119   gfc_code *if_limit = NULL;
4120   gfc_code **next_code_point;
4121   bool conjg_a, conjg_b, transpose_a, transpose_b;
4122   bool realloc_c;
4123 
4124   if (co->op != EXEC_ASSIGN)
4125     return 0;
4126 
4127   if (in_where || in_assoc_list)
4128     return 0;
4129 
4130   /* The BLOCKS generated for the temporary variables and FORALL don't
4131      mix.  */
4132   if (forall_level > 0)
4133     return 0;
4134 
4135   /* For now don't do anything in OpenMP workshare, it confuses
4136      its translation, which expects only the allowed statements in there.
4137      We should figure out how to parallelize this eventually.  */
4138   if (in_omp_workshare || in_omp_atomic)
4139     return 0;
4140 
4141   expr1 = co->expr1;
4142   expr2 = co->expr2;
4143   if (expr2->expr_type != EXPR_FUNCTION
4144       || expr2->value.function.isym == NULL
4145       || expr2->value.function.isym->id != GFC_ISYM_MATMUL)
4146     return 0;
4147 
4148   current_code = c;
4149   inserted_block = NULL;
4150   changed_statement = NULL;
4151 
4152   a = expr2->value.function.actual;
4153   matrix_a = check_conjg_transpose_variable (a->expr, &conjg_a, &transpose_a);
4154   if (matrix_a == NULL)
4155     return 0;
4156 
4157   b = a->next;
4158   matrix_b = check_conjg_transpose_variable (b->expr, &conjg_b, &transpose_b);
4159   if (matrix_b == NULL)
4160     return 0;
4161 
4162   if (gfc_has_dimen_vector_ref (expr1) || gfc_has_dimen_vector_ref (matrix_a)
4163       || gfc_has_dimen_vector_ref (matrix_b))
4164     return 0;
4165 
4166   /* We do not handle data dependencies yet.  */
4167   if (gfc_check_dependency (expr1, matrix_a, true)
4168       || gfc_check_dependency (expr1, matrix_b, true))
4169     return 0;
4170 
4171   m_case = none;
4172   if (matrix_a->rank == 2)
4173     {
4174       if (transpose_a)
4175 	{
4176 	  if (matrix_b->rank == 2 && !transpose_b)
4177 	    m_case = A2TB2;
4178 	}
4179       else
4180 	{
4181 	  if (matrix_b->rank == 1)
4182 	    m_case = A2B1;
4183 	  else /* matrix_b->rank == 2 */
4184 	    {
4185 	      if (transpose_b)
4186 		m_case = A2B2T;
4187 	      else
4188 		m_case = A2B2;
4189 	    }
4190 	}
4191     }
4192   else /* matrix_a->rank == 1 */
4193     {
4194       if (matrix_b->rank == 2)
4195 	{
4196 	  if (!transpose_b)
4197 	    m_case = A1B2;
4198 	}
4199     }
4200 
4201   if (m_case == none)
4202     return 0;
4203 
4204   /* We only handle assignment to numeric or logical variables.  */
4205   switch(expr1->ts.type)
4206     {
4207     case BT_INTEGER:
4208     case BT_LOGICAL:
4209     case BT_REAL:
4210     case BT_COMPLEX:
4211       break;
4212 
4213     default:
4214       return 0;
4215     }
4216 
4217   ns = insert_block ();
4218 
4219   /* Assign the type of the zero expression for initializing the resulting
4220      array, and the expression (+ and * for real, integer and complex;
4221      .and. and .or for logical.  */
4222 
4223   switch(expr1->ts.type)
4224     {
4225     case BT_INTEGER:
4226       zero_e = gfc_get_int_expr (expr1->ts.kind, &expr1->where, 0);
4227       op_times = INTRINSIC_TIMES;
4228       op_plus = INTRINSIC_PLUS;
4229       break;
4230 
4231     case BT_LOGICAL:
4232       op_times = INTRINSIC_AND;
4233       op_plus = INTRINSIC_OR;
4234       zero_e = gfc_get_logical_expr (expr1->ts.kind, &expr1->where,
4235 				     0);
4236       break;
4237     case BT_REAL:
4238       zero_e = gfc_get_constant_expr (BT_REAL, expr1->ts.kind,
4239 				      &expr1->where);
4240       mpfr_set_si (zero_e->value.real, 0, GFC_RND_MODE);
4241       op_times = INTRINSIC_TIMES;
4242       op_plus = INTRINSIC_PLUS;
4243       break;
4244 
4245     case BT_COMPLEX:
4246       zero_e = gfc_get_constant_expr (BT_COMPLEX, expr1->ts.kind,
4247 				      &expr1->where);
4248       mpc_set_si_si (zero_e->value.complex, 0, 0, GFC_RND_MODE);
4249       op_times = INTRINSIC_TIMES;
4250       op_plus = INTRINSIC_PLUS;
4251 
4252       break;
4253 
4254     default:
4255       gcc_unreachable();
4256     }
4257 
4258   current_code = &ns->code;
4259 
4260   /* Freeze the references, keeping track of how many temporary variables were
4261      created.  */
4262   n_vars = 0;
4263   freeze_references (matrix_a);
4264   freeze_references (matrix_b);
4265   freeze_references (expr1);
4266 
4267   if (n_vars == 0)
4268     next_code_point = current_code;
4269   else
4270     {
4271       next_code_point = &ns->code;
4272       for (i=0; i<n_vars; i++)
4273 	next_code_point = &(*next_code_point)->next;
4274     }
4275 
4276   /* Take care of the inline flag.  If the limit check evaluates to a
4277      constant, dead code elimination will eliminate the unneeded branch.  */
4278 
4279   if (flag_inline_matmul_limit > 0
4280       && (matrix_a->rank == 1 || matrix_a->rank == 2)
4281       && matrix_b->rank == 2)
4282     {
4283       if_limit = inline_limit_check (matrix_a, matrix_b,
4284 				     flag_inline_matmul_limit,
4285 				     matrix_a->rank);
4286 
4287       /* Insert the original statement into the else branch.  */
4288       if_limit->block->block->next = co;
4289       co->next = NULL;
4290 
4291       /* ... and the new ones go into the original one.  */
4292       *next_code_point = if_limit;
4293       next_code_point = &if_limit->block->next;
4294     }
4295 
4296   zero_e->no_bounds_check = 1;
4297 
4298   assign_zero = XCNEW (gfc_code);
4299   assign_zero->op = EXEC_ASSIGN;
4300   assign_zero->loc = co->loc;
4301   assign_zero->expr1 = gfc_copy_expr (expr1);
4302   assign_zero->expr1->no_bounds_check = 1;
4303   assign_zero->expr2 = zero_e;
4304 
4305   realloc_c = flag_realloc_lhs && gfc_is_reallocatable_lhs (expr1);
4306 
4307   if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
4308     {
4309       gfc_code *test;
4310       gfc_expr *a2, *b1, *c1, *c2, *a1, *b2;
4311 
4312       switch (m_case)
4313 	{
4314 	case A2B1:
4315 
4316 	  b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1);
4317 	  a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2);
4318 	  test = runtime_error_ne (b1, a2, B_ERROR_1);
4319 	  *next_code_point = test;
4320 	  next_code_point = &test->next;
4321 
4322 	  if (!realloc_c)
4323 	    {
4324 	      c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1);
4325 	      a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1);
4326 	      test = runtime_error_ne (c1, a1, C_ERROR_1);
4327 	      *next_code_point = test;
4328 	      next_code_point = &test->next;
4329 	    }
4330 	  break;
4331 
4332 	case A1B2:
4333 
4334 	  b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1);
4335 	  a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1);
4336 	  test = runtime_error_ne (b1, a1, B_ERROR_1);
4337 	  *next_code_point = test;
4338 	  next_code_point = &test->next;
4339 
4340 	  if (!realloc_c)
4341 	    {
4342 	      c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1);
4343 	      b2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 2);
4344 	      test = runtime_error_ne (c1, b2, C_ERROR_1);
4345 	      *next_code_point = test;
4346 	      next_code_point = &test->next;
4347 	    }
4348 	  break;
4349 
4350 	case A2B2:
4351 
4352 	  b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1);
4353 	  a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2);
4354 	  test = runtime_error_ne (b1, a2, B_ERROR_1);
4355 	  *next_code_point = test;
4356 	  next_code_point = &test->next;
4357 
4358 	  if (!realloc_c)
4359 	    {
4360 	      c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1);
4361 	      a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1);
4362 	      test = runtime_error_ne (c1, a1, C_ERROR_1);
4363 	      *next_code_point = test;
4364 	      next_code_point = &test->next;
4365 
4366 	      c2 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 2);
4367 	      b2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 2);
4368 	      test = runtime_error_ne (c2, b2, C_ERROR_2);
4369 	      *next_code_point = test;
4370 	      next_code_point = &test->next;
4371 	    }
4372 	  break;
4373 
4374 	case A2B2T:
4375 
4376 	  b2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 2);
4377 	  a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2);
4378 	  /* matrix_b is transposed, hence dimension 1 for the error message.  */
4379 	  test = runtime_error_ne (b2, a2, B_ERROR_1);
4380 	  *next_code_point = test;
4381 	  next_code_point = &test->next;
4382 
4383 	  if (!realloc_c)
4384 	    {
4385 	      c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1);
4386 	      a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1);
4387 	      test = runtime_error_ne (c1, a1, C_ERROR_1);
4388 	      *next_code_point = test;
4389 	      next_code_point = &test->next;
4390 
4391 	      c2 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 2);
4392 	      b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1);
4393 	      test = runtime_error_ne (c2, b1, C_ERROR_2);
4394 	      *next_code_point = test;
4395 	      next_code_point = &test->next;
4396 	    }
4397 	  break;
4398 
4399 	case A2TB2:
4400 
4401 	  b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1);
4402 	  a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1);
4403 	  test = runtime_error_ne (b1, a1, B_ERROR_1);
4404 	  *next_code_point = test;
4405 	  next_code_point = &test->next;
4406 
4407 	  if (!realloc_c)
4408 	    {
4409 	      c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1);
4410 	      a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2);
4411 	      test = runtime_error_ne (c1, a2, C_ERROR_1);
4412 	      *next_code_point = test;
4413 	      next_code_point = &test->next;
4414 
4415 	      c2 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 2);
4416 	      b2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 2);
4417 	      test = runtime_error_ne (c2, b2, C_ERROR_2);
4418 	      *next_code_point = test;
4419 	      next_code_point = &test->next;
4420 	    }
4421 	  break;
4422 
4423 	default:
4424 	  gcc_unreachable ();
4425 	}
4426     }
4427 
4428   /* Handle the reallocation, if needed.  */
4429 
4430   if (realloc_c)
4431     {
4432       gfc_code *lhs_alloc;
4433 
4434       lhs_alloc = matmul_lhs_realloc (expr1, matrix_a, matrix_b, m_case);
4435 
4436       *next_code_point = lhs_alloc;
4437       next_code_point = &lhs_alloc->next;
4438 
4439     }
4440 
4441   *next_code_point = assign_zero;
4442 
4443   zero = gfc_get_int_expr (gfc_index_integer_kind, &co->loc, 0);
4444 
4445   assign_matmul = XCNEW (gfc_code);
4446   assign_matmul->op = EXEC_ASSIGN;
4447   assign_matmul->loc = co->loc;
4448 
4449   /* Get the bounds for the loops, create them and create the scalarized
4450      expressions.  */
4451 
4452   switch (m_case)
4453     {
4454     case A2B2:
4455 
4456       u1 = get_size_m1 (matrix_b, 2);
4457       u2 = get_size_m1 (matrix_a, 2);
4458       u3 = get_size_m1 (matrix_a, 1);
4459 
4460       do_1 = create_do_loop (gfc_copy_expr (zero), u1, NULL, &co->loc, ns);
4461       do_2 = create_do_loop (gfc_copy_expr (zero), u2, NULL, &co->loc, ns);
4462       do_3 = create_do_loop (gfc_copy_expr (zero), u3, NULL, &co->loc, ns);
4463 
4464       do_1->block->next = do_2;
4465       do_2->block->next = do_3;
4466       do_3->block->next = assign_matmul;
4467 
4468       var_1 = do_1->ext.iterator->var;
4469       var_2 = do_2->ext.iterator->var;
4470       var_3 = do_3->ext.iterator->var;
4471 
4472       list[0] = var_3;
4473       list[1] = var_1;
4474       cscalar = scalarized_expr (co->expr1, list, 2);
4475 
4476       list[0] = var_3;
4477       list[1] = var_2;
4478       ascalar = scalarized_expr (matrix_a, list, 2);
4479 
4480       list[0] = var_2;
4481       list[1] = var_1;
4482       bscalar = scalarized_expr (matrix_b, list, 2);
4483 
4484       break;
4485 
4486     case A2B2T:
4487 
4488       u1 = get_size_m1 (matrix_b, 1);
4489       u2 = get_size_m1 (matrix_a, 2);
4490       u3 = get_size_m1 (matrix_a, 1);
4491 
4492       do_1 = create_do_loop (gfc_copy_expr (zero), u1, NULL, &co->loc, ns);
4493       do_2 = create_do_loop (gfc_copy_expr (zero), u2, NULL, &co->loc, ns);
4494       do_3 = create_do_loop (gfc_copy_expr (zero), u3, NULL, &co->loc, ns);
4495 
4496       do_1->block->next = do_2;
4497       do_2->block->next = do_3;
4498       do_3->block->next = assign_matmul;
4499 
4500       var_1 = do_1->ext.iterator->var;
4501       var_2 = do_2->ext.iterator->var;
4502       var_3 = do_3->ext.iterator->var;
4503 
4504       list[0] = var_3;
4505       list[1] = var_1;
4506       cscalar = scalarized_expr (co->expr1, list, 2);
4507 
4508       list[0] = var_3;
4509       list[1] = var_2;
4510       ascalar = scalarized_expr (matrix_a, list, 2);
4511 
4512       list[0] = var_1;
4513       list[1] = var_2;
4514       bscalar = scalarized_expr (matrix_b, list, 2);
4515 
4516       break;
4517 
4518     case A2TB2:
4519 
4520       u1 = get_size_m1 (matrix_a, 2);
4521       u2 = get_size_m1 (matrix_b, 2);
4522       u3 = get_size_m1 (matrix_a, 1);
4523 
4524       do_1 = create_do_loop (gfc_copy_expr (zero), u1, NULL, &co->loc, ns);
4525       do_2 = create_do_loop (gfc_copy_expr (zero), u2, NULL, &co->loc, ns);
4526       do_3 = create_do_loop (gfc_copy_expr (zero), u3, NULL, &co->loc, ns);
4527 
4528       do_1->block->next = do_2;
4529       do_2->block->next = do_3;
4530       do_3->block->next = assign_matmul;
4531 
4532       var_1 = do_1->ext.iterator->var;
4533       var_2 = do_2->ext.iterator->var;
4534       var_3 = do_3->ext.iterator->var;
4535 
4536       list[0] = var_1;
4537       list[1] = var_2;
4538       cscalar = scalarized_expr (co->expr1, list, 2);
4539 
4540       list[0] = var_3;
4541       list[1] = var_1;
4542       ascalar = scalarized_expr (matrix_a, list, 2);
4543 
4544       list[0] = var_3;
4545       list[1] = var_2;
4546       bscalar = scalarized_expr (matrix_b, list, 2);
4547 
4548       break;
4549 
4550     case A2B1:
4551       u1 = get_size_m1 (matrix_b, 1);
4552       u2 = get_size_m1 (matrix_a, 1);
4553 
4554       do_1 = create_do_loop (gfc_copy_expr (zero), u1, NULL, &co->loc, ns);
4555       do_2 = create_do_loop (gfc_copy_expr (zero), u2, NULL, &co->loc, ns);
4556 
4557       do_1->block->next = do_2;
4558       do_2->block->next = assign_matmul;
4559 
4560       var_1 = do_1->ext.iterator->var;
4561       var_2 = do_2->ext.iterator->var;
4562 
4563       list[0] = var_2;
4564       cscalar = scalarized_expr (co->expr1, list, 1);
4565 
4566       list[0] = var_2;
4567       list[1] = var_1;
4568       ascalar = scalarized_expr (matrix_a, list, 2);
4569 
4570       list[0] = var_1;
4571       bscalar = scalarized_expr (matrix_b, list, 1);
4572 
4573       break;
4574 
4575     case A1B2:
4576       u1 = get_size_m1 (matrix_b, 2);
4577       u2 = get_size_m1 (matrix_a, 1);
4578 
4579       do_1 = create_do_loop (gfc_copy_expr (zero), u1, NULL, &co->loc, ns);
4580       do_2 = create_do_loop (gfc_copy_expr (zero), u2, NULL, &co->loc, ns);
4581 
4582       do_1->block->next = do_2;
4583       do_2->block->next = assign_matmul;
4584 
4585       var_1 = do_1->ext.iterator->var;
4586       var_2 = do_2->ext.iterator->var;
4587 
4588       list[0] = var_1;
4589       cscalar = scalarized_expr (co->expr1, list, 1);
4590 
4591       list[0] = var_2;
4592       ascalar = scalarized_expr (matrix_a, list, 1);
4593 
4594       list[0] = var_2;
4595       list[1] = var_1;
4596       bscalar = scalarized_expr (matrix_b, list, 2);
4597 
4598       break;
4599 
4600     default:
4601       gcc_unreachable();
4602     }
4603 
4604   /* Build the conjg call around the variables.  Set the typespec manually
4605      because gfc_build_intrinsic_call sometimes gets this wrong.  */
4606   if (conjg_a)
4607     {
4608       gfc_typespec ts;
4609       ts = matrix_a->ts;
4610       ascalar = gfc_build_intrinsic_call (ns, GFC_ISYM_CONJG, "conjg",
4611 					  matrix_a->where, 1, ascalar);
4612       ascalar->ts = ts;
4613     }
4614 
4615   if (conjg_b)
4616     {
4617       gfc_typespec ts;
4618       ts = matrix_b->ts;
4619       bscalar = gfc_build_intrinsic_call (ns, GFC_ISYM_CONJG, "conjg",
4620 					  matrix_b->where, 1, bscalar);
4621       bscalar->ts = ts;
4622     }
4623   /* First loop comes after the zero assignment.  */
4624   assign_zero->next = do_1;
4625 
4626   /* Build the assignment expression in the loop.  */
4627   assign_matmul->expr1 = gfc_copy_expr (cscalar);
4628 
4629   mult = get_operand (op_times, ascalar, bscalar);
4630   assign_matmul->expr2 = get_operand (op_plus, cscalar, mult);
4631 
4632   /* If we don't want to keep the original statement around in
4633      the else branch, we can free it.  */
4634 
4635   if (if_limit == NULL)
4636     gfc_free_statements(co);
4637   else
4638     co->next = NULL;
4639 
4640   gfc_free_expr (zero);
4641   *walk_subtrees = 0;
4642   return 0;
4643 }
4644 
4645 /* Change matmul function calls in the form of
4646 
4647    c = matmul(a,b)
4648 
4649    to the corresponding call to a BLAS routine, if applicable.  */
4650 
4651 static int
call_external_blas(gfc_code ** c,int * walk_subtrees ATTRIBUTE_UNUSED,void * data ATTRIBUTE_UNUSED)4652 call_external_blas (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
4653 		    void *data ATTRIBUTE_UNUSED)
4654 {
4655   gfc_code *co, *co_next;
4656   gfc_expr *expr1, *expr2;
4657   gfc_expr *matrix_a, *matrix_b;
4658   gfc_code *if_limit = NULL;
4659   gfc_actual_arglist *a, *b;
4660   bool conjg_a, conjg_b, transpose_a, transpose_b;
4661   gfc_code *call;
4662   const char *blas_name;
4663   const char *transa, *transb;
4664   gfc_expr *c1, *c2, *b1;
4665   gfc_actual_arglist *actual, *next;
4666   bt type;
4667   int kind;
4668   enum matrix_case m_case;
4669   bool realloc_c;
4670   gfc_code **next_code_point;
4671 
4672   /* Many of the tests for inline matmul also apply here.  */
4673 
4674   co = *c;
4675 
4676   if (co->op != EXEC_ASSIGN)
4677     return 0;
4678 
4679   if (in_where || in_assoc_list)
4680     return 0;
4681 
4682   /* The BLOCKS generated for the temporary variables and FORALL don't
4683      mix.  */
4684   if (forall_level > 0)
4685     return 0;
4686 
4687   /* For now don't do anything in OpenMP workshare, it confuses
4688      its translation, which expects only the allowed statements in there. */
4689 
4690   if (in_omp_workshare || in_omp_atomic)
4691     return 0;
4692 
4693   expr1 = co->expr1;
4694   expr2 = co->expr2;
4695   if (expr2->expr_type != EXPR_FUNCTION
4696       || expr2->value.function.isym == NULL
4697       || expr2->value.function.isym->id != GFC_ISYM_MATMUL)
4698     return 0;
4699 
4700   type = expr2->ts.type;
4701   kind = expr2->ts.kind;
4702 
4703   /* Guard against recursion. */
4704 
4705   if (expr2->external_blas)
4706     return 0;
4707 
4708   if (type != expr1->ts.type || kind != expr1->ts.kind)
4709     return 0;
4710 
4711   if (type == BT_REAL)
4712     {
4713       if (kind == 4)
4714 	blas_name = "sgemm";
4715       else if (kind == 8)
4716 	blas_name = "dgemm";
4717       else
4718 	return 0;
4719     }
4720   else if (type == BT_COMPLEX)
4721     {
4722       if (kind == 4)
4723 	blas_name = "cgemm";
4724       else if (kind == 8)
4725 	blas_name = "zgemm";
4726       else
4727 	return 0;
4728     }
4729   else
4730     return 0;
4731 
4732   a = expr2->value.function.actual;
4733   if (a->expr->rank != 2)
4734     return 0;
4735 
4736   b = a->next;
4737   if (b->expr->rank != 2)
4738     return 0;
4739 
4740   matrix_a = check_conjg_transpose_variable (a->expr, &conjg_a, &transpose_a);
4741   if (matrix_a == NULL)
4742     return 0;
4743 
4744   if (transpose_a)
4745     {
4746       if (conjg_a)
4747 	transa = "C";
4748       else
4749 	transa = "T";
4750     }
4751   else
4752     transa = "N";
4753 
4754   matrix_b = check_conjg_transpose_variable (b->expr, &conjg_b, &transpose_b);
4755   if (matrix_b == NULL)
4756     return 0;
4757 
4758   if (transpose_b)
4759     {
4760       if (conjg_b)
4761 	transb = "C";
4762       else
4763 	transb = "T";
4764     }
4765   else
4766     transb = "N";
4767 
4768   if (transpose_a)
4769     {
4770       if (transpose_b)
4771 	m_case = A2TB2T;
4772       else
4773 	m_case = A2TB2;
4774     }
4775   else
4776     {
4777       if (transpose_b)
4778 	m_case = A2B2T;
4779       else
4780 	m_case = A2B2;
4781     }
4782 
4783   current_code = c;
4784   inserted_block = NULL;
4785   changed_statement = NULL;
4786 
4787   expr2->external_blas = 1;
4788 
4789   /* We do not handle data dependencies yet.  */
4790   if (gfc_check_dependency (expr1, matrix_a, true)
4791       || gfc_check_dependency (expr1, matrix_b, true))
4792     return 0;
4793 
4794   /* Generate the if statement and hang it into the tree.  */
4795   if_limit = inline_limit_check (matrix_a, matrix_b, flag_blas_matmul_limit, 2);
4796   co_next = co->next;
4797   (*current_code) = if_limit;
4798   co->next = NULL;
4799   if_limit->block->next = co;
4800 
4801   call = XCNEW (gfc_code);
4802   call->loc = co->loc;
4803 
4804   /* Bounds checking - a bit simpler than for inlining since we only
4805      have to take care of two-dimensional arrays here.  */
4806 
4807   realloc_c = flag_realloc_lhs && gfc_is_reallocatable_lhs (expr1);
4808   next_code_point = &(if_limit->block->block->next);
4809 
4810   if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
4811     {
4812       gfc_code *test;
4813       //      gfc_expr *a2, *b1, *c1, *c2, *a1, *b2;
4814       gfc_expr *c1, *a1, *c2, *b2, *a2;
4815       switch (m_case)
4816 	{
4817 	case A2B2:
4818 	  b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1);
4819 	  a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2);
4820 	  test = runtime_error_ne (b1, a2, B_ERROR_1);
4821 	  *next_code_point = test;
4822 	  next_code_point = &test->next;
4823 
4824 	  if (!realloc_c)
4825 	    {
4826 	      c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1);
4827 	      a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1);
4828 	      test = runtime_error_ne (c1, a1, C_ERROR_1);
4829 	      *next_code_point = test;
4830 	      next_code_point = &test->next;
4831 
4832 	      c2 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 2);
4833 	      b2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 2);
4834 	      test = runtime_error_ne (c2, b2, C_ERROR_2);
4835 	      *next_code_point = test;
4836 	      next_code_point = &test->next;
4837 	    }
4838 	  break;
4839 
4840 	case A2B2T:
4841 
4842 	  b2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 2);
4843 	  a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2);
4844 	  /* matrix_b is transposed, hence dimension 1 for the error message.  */
4845 	  test = runtime_error_ne (b2, a2, B_ERROR_1);
4846 	  *next_code_point = test;
4847 	  next_code_point = &test->next;
4848 
4849 	  if (!realloc_c)
4850 	    {
4851 	      c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1);
4852 	      a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1);
4853 	      test = runtime_error_ne (c1, a1, C_ERROR_1);
4854 	      *next_code_point = test;
4855 	      next_code_point = &test->next;
4856 
4857 	      c2 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 2);
4858 	      b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1);
4859 	      test = runtime_error_ne (c2, b1, C_ERROR_2);
4860 	      *next_code_point = test;
4861 	      next_code_point = &test->next;
4862 	    }
4863 	  break;
4864 
4865 	case A2TB2:
4866 
4867 	  b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1);
4868 	  a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1);
4869 	  test = runtime_error_ne (b1, a1, B_ERROR_1);
4870 	  *next_code_point = test;
4871 	  next_code_point = &test->next;
4872 
4873 	  if (!realloc_c)
4874 	    {
4875 	      c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1);
4876 	      a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2);
4877 	      test = runtime_error_ne (c1, a2, C_ERROR_1);
4878 	      *next_code_point = test;
4879 	      next_code_point = &test->next;
4880 
4881 	      c2 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 2);
4882 	      b2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 2);
4883 	      test = runtime_error_ne (c2, b2, C_ERROR_2);
4884 	      *next_code_point = test;
4885 	      next_code_point = &test->next;
4886 	    }
4887 	  break;
4888 
4889 	case A2TB2T:
4890 	  b2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 2);
4891 	  a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1);
4892 	  test = runtime_error_ne (b2, a1, B_ERROR_1);
4893 	  *next_code_point = test;
4894 	  next_code_point = &test->next;
4895 
4896 	  if (!realloc_c)
4897 	    {
4898 	      c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1);
4899 	      a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2);
4900 	      test = runtime_error_ne (c1, a2, C_ERROR_1);
4901 	      *next_code_point = test;
4902 	      next_code_point = &test->next;
4903 
4904 	      c2 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 2);
4905 	      b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1);
4906 	      test = runtime_error_ne (c2, b1, C_ERROR_2);
4907 	      *next_code_point = test;
4908 	      next_code_point = &test->next;
4909 	    }
4910 	  break;
4911 
4912 	default:
4913 	  gcc_unreachable ();
4914 	}
4915     }
4916 
4917   /* Handle the reallocation, if needed.  */
4918 
4919   if (realloc_c)
4920     {
4921       gfc_code *lhs_alloc;
4922 
4923       lhs_alloc = matmul_lhs_realloc (expr1, matrix_a, matrix_b, m_case);
4924       *next_code_point = lhs_alloc;
4925       next_code_point = &lhs_alloc->next;
4926     }
4927 
4928   *next_code_point = call;
4929   if_limit->next = co_next;
4930 
4931   /* Set up the BLAS call.  */
4932 
4933   call->op = EXEC_CALL;
4934 
4935   gfc_get_sym_tree (blas_name, current_ns, &(call->symtree), true);
4936   call->symtree->n.sym->attr.subroutine = 1;
4937   call->symtree->n.sym->attr.procedure = 1;
4938   call->symtree->n.sym->attr.flavor = FL_PROCEDURE;
4939   call->resolved_sym = call->symtree->n.sym;
4940   gfc_commit_symbol (call->resolved_sym);
4941 
4942   /* Argument TRANSA.  */
4943   next = gfc_get_actual_arglist ();
4944   next->expr = gfc_get_character_expr (gfc_default_character_kind, &co->loc,
4945 				       transa, 1);
4946 
4947   call->ext.actual = next;
4948 
4949   /* Argument TRANSB.  */
4950   actual = next;
4951   next = gfc_get_actual_arglist ();
4952   next->expr = gfc_get_character_expr (gfc_default_character_kind, &co->loc,
4953 				       transb, 1);
4954   actual->next = next;
4955 
4956   c1 = get_array_inq_function (GFC_ISYM_SIZE, gfc_copy_expr (a->expr), 1,
4957 			       gfc_integer_4_kind);
4958   c2 = get_array_inq_function (GFC_ISYM_SIZE, gfc_copy_expr (b->expr), 2,
4959 			       gfc_integer_4_kind);
4960 
4961   b1 = get_array_inq_function (GFC_ISYM_SIZE, gfc_copy_expr (b->expr), 1,
4962 			       gfc_integer_4_kind);
4963 
4964   /* Argument M. */
4965   actual = next;
4966   next = gfc_get_actual_arglist ();
4967   next->expr = c1;
4968   actual->next = next;
4969 
4970   /* Argument N. */
4971   actual = next;
4972   next = gfc_get_actual_arglist ();
4973   next->expr = c2;
4974   actual->next = next;
4975 
4976   /* Argument K.  */
4977   actual = next;
4978   next = gfc_get_actual_arglist ();
4979   next->expr = b1;
4980   actual->next = next;
4981 
4982   /* Argument ALPHA - set to one.  */
4983   actual = next;
4984   next = gfc_get_actual_arglist ();
4985   next->expr = gfc_get_constant_expr (type, kind, &co->loc);
4986   if (type == BT_REAL)
4987     mpfr_set_ui (next->expr->value.real, 1, GFC_RND_MODE);
4988   else
4989     mpc_set_ui (next->expr->value.complex, 1, GFC_MPC_RND_MODE);
4990   actual->next = next;
4991 
4992   /* Argument A.  */
4993   actual = next;
4994   next = gfc_get_actual_arglist ();
4995   next->expr = gfc_copy_expr (matrix_a);
4996   actual->next = next;
4997 
4998   /* Argument LDA.  */
4999   actual = next;
5000   next = gfc_get_actual_arglist ();
5001   next->expr = get_array_inq_function (GFC_ISYM_SIZE, gfc_copy_expr (matrix_a),
5002 				       1, gfc_integer_4_kind);
5003   actual->next = next;
5004 
5005   /* Argument B.  */
5006   actual = next;
5007   next = gfc_get_actual_arglist ();
5008   next->expr = gfc_copy_expr (matrix_b);
5009   actual->next = next;
5010 
5011   /* Argument LDB.  */
5012   actual = next;
5013   next = gfc_get_actual_arglist ();
5014   next->expr = get_array_inq_function (GFC_ISYM_SIZE, gfc_copy_expr (matrix_b),
5015 				       1, gfc_integer_4_kind);
5016   actual->next = next;
5017 
5018   /* Argument BETA - set to zero.  */
5019   actual = next;
5020   next = gfc_get_actual_arglist ();
5021   next->expr = gfc_get_constant_expr (type, kind, &co->loc);
5022   if (type == BT_REAL)
5023     mpfr_set_ui (next->expr->value.real, 0, GFC_RND_MODE);
5024   else
5025     mpc_set_ui (next->expr->value.complex, 0, GFC_MPC_RND_MODE);
5026   actual->next = next;
5027 
5028   /* Argument C.  */
5029 
5030   actual = next;
5031   next = gfc_get_actual_arglist ();
5032   next->expr = gfc_copy_expr (expr1);
5033   actual->next = next;
5034 
5035   /* Argument LDC.  */
5036   actual = next;
5037   next = gfc_get_actual_arglist ();
5038   next->expr = get_array_inq_function (GFC_ISYM_SIZE, gfc_copy_expr (expr1),
5039 				       1, gfc_integer_4_kind);
5040   actual->next = next;
5041 
5042   return 0;
5043 }
5044 
5045 
5046 /* Code for index interchange for loops which are grouped together in DO
5047    CONCURRENT or FORALL statements.  This is currently only applied if the
5048    iterations are grouped together in a single statement.
5049 
5050    For this transformation, it is assumed that memory access in strides is
5051    expensive, and that loops which access later indices (which access memory
5052    in bigger strides) should be moved to the first loops.
5053 
5054    For this, a loop over all the statements is executed, counting the times
5055    that the loop iteration values are accessed in each index.  The loop
5056    indices are then sorted to minimize access to later indices from inner
5057    loops.  */
5058 
5059 /* Type for holding index information.  */
5060 
5061 typedef struct {
5062   gfc_symbol *sym;
5063   gfc_forall_iterator *fa;
5064   int num;
5065   int n[GFC_MAX_DIMENSIONS];
5066 } ind_type;
5067 
5068 /* Callback function to determine if an expression is the
5069    corresponding variable.  */
5070 
5071 static int
has_var(gfc_expr ** e,int * walk_subtrees ATTRIBUTE_UNUSED,void * data)5072 has_var (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED, void *data)
5073 {
5074   gfc_expr *expr = *e;
5075   gfc_symbol *sym;
5076 
5077   if (expr->expr_type != EXPR_VARIABLE)
5078     return 0;
5079 
5080   sym = (gfc_symbol *) data;
5081   return sym == expr->symtree->n.sym;
5082 }
5083 
5084 /* Callback function to calculate the cost of a certain index.  */
5085 
5086 static int
index_cost(gfc_expr ** e,int * walk_subtrees ATTRIBUTE_UNUSED,void * data)5087 index_cost (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
5088 	    void *data)
5089 {
5090   ind_type *ind;
5091   gfc_expr *expr;
5092   gfc_array_ref *ar;
5093   gfc_ref *ref;
5094   int i,j;
5095 
5096   expr = *e;
5097   if (expr->expr_type != EXPR_VARIABLE)
5098     return 0;
5099 
5100   ar = NULL;
5101   for (ref = expr->ref; ref; ref = ref->next)
5102     {
5103       if (ref->type == REF_ARRAY)
5104 	{
5105 	  ar = &ref->u.ar;
5106 	  break;
5107 	}
5108     }
5109   if (ar == NULL || ar->type != AR_ELEMENT)
5110     return 0;
5111 
5112   ind = (ind_type *) data;
5113   for (i = 0; i < ar->dimen; i++)
5114     {
5115       for (j=0; ind[j].sym != NULL; j++)
5116 	{
5117 	  if (gfc_expr_walker (&ar->start[i], has_var, (void *) (ind[j].sym)))
5118 	      ind[j].n[i]++;
5119 	}
5120     }
5121   return 0;
5122 }
5123 
5124 /* Callback function for qsort, to sort the loop indices. */
5125 
5126 static int
loop_comp(const void * e1,const void * e2)5127 loop_comp (const void *e1, const void *e2)
5128 {
5129   const ind_type *i1 = (const ind_type *) e1;
5130   const ind_type *i2 = (const ind_type *) e2;
5131   int i;
5132 
5133   for (i=GFC_MAX_DIMENSIONS-1; i >= 0; i--)
5134     {
5135       if (i1->n[i] != i2->n[i])
5136 	return i1->n[i] - i2->n[i];
5137     }
5138   /* All other things being equal, let's not change the ordering.  */
5139   return i2->num - i1->num;
5140 }
5141 
5142 /* Main function to do the index interchange.  */
5143 
5144 static int
index_interchange(gfc_code ** c,int * walk_subtrees ATTRIBUTE_UNUSED,void * data ATTRIBUTE_UNUSED)5145 index_interchange (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
5146 		  void *data ATTRIBUTE_UNUSED)
5147 {
5148   gfc_code *co;
5149   co = *c;
5150   int n_iter;
5151   gfc_forall_iterator *fa;
5152   ind_type *ind;
5153   int i, j;
5154 
5155   if (co->op != EXEC_FORALL && co->op != EXEC_DO_CONCURRENT)
5156     return 0;
5157 
5158   n_iter = 0;
5159   for (fa = co->ext.forall_iterator; fa; fa = fa->next)
5160     n_iter ++;
5161 
5162   /* Nothing to reorder. */
5163   if (n_iter < 2)
5164     return 0;
5165 
5166   ind = XALLOCAVEC (ind_type, n_iter + 1);
5167 
5168   i = 0;
5169   for (fa = co->ext.forall_iterator; fa; fa = fa->next)
5170     {
5171       ind[i].sym = fa->var->symtree->n.sym;
5172       ind[i].fa = fa;
5173       for (j=0; j<GFC_MAX_DIMENSIONS; j++)
5174 	ind[i].n[j] = 0;
5175       ind[i].num = i;
5176       i++;
5177     }
5178   ind[n_iter].sym = NULL;
5179   ind[n_iter].fa = NULL;
5180 
5181   gfc_code_walker (c, gfc_dummy_code_callback, index_cost, (void *) ind);
5182   qsort ((void *) ind, n_iter, sizeof (ind_type), loop_comp);
5183 
5184   /* Do the actual index interchange.  */
5185   co->ext.forall_iterator = fa = ind[0].fa;
5186   for (i=1; i<n_iter; i++)
5187     {
5188       fa->next = ind[i].fa;
5189       fa = fa->next;
5190     }
5191   fa->next = NULL;
5192 
5193   if (flag_warn_frontend_loop_interchange)
5194     {
5195       for (i=1; i<n_iter; i++)
5196 	{
5197 	  if (ind[i-1].num > ind[i].num)
5198 	    {
5199 	      gfc_warning (OPT_Wfrontend_loop_interchange,
5200 			   "Interchanging loops at %L", &co->loc);
5201 	      break;
5202 	    }
5203 	}
5204     }
5205 
5206   return 0;
5207 }
5208 
5209 #define WALK_SUBEXPR(NODE) \
5210   do							\
5211     {							\
5212       result = gfc_expr_walker (&(NODE), exprfn, data);	\
5213       if (result)					\
5214 	return result;					\
5215     }							\
5216   while (0)
5217 #define WALK_SUBEXPR_TAIL(NODE) e = &(NODE); continue
5218 
5219 /* Walk expression *E, calling EXPRFN on each expression in it.  */
5220 
5221 int
gfc_expr_walker(gfc_expr ** e,walk_expr_fn_t exprfn,void * data)5222 gfc_expr_walker (gfc_expr **e, walk_expr_fn_t exprfn, void *data)
5223 {
5224   while (*e)
5225     {
5226       int walk_subtrees = 1;
5227       gfc_actual_arglist *a;
5228       gfc_ref *r;
5229       gfc_constructor *c;
5230 
5231       int result = exprfn (e, &walk_subtrees, data);
5232       if (result)
5233 	return result;
5234       if (walk_subtrees)
5235 	switch ((*e)->expr_type)
5236 	  {
5237 	  case EXPR_OP:
5238 	    WALK_SUBEXPR ((*e)->value.op.op1);
5239 	    WALK_SUBEXPR_TAIL ((*e)->value.op.op2);
5240 	    /* No fallthru because of the tail recursion above.  */
5241 	  case EXPR_FUNCTION:
5242 	    for (a = (*e)->value.function.actual; a; a = a->next)
5243 	      WALK_SUBEXPR (a->expr);
5244 	    break;
5245 	  case EXPR_COMPCALL:
5246 	  case EXPR_PPC:
5247 	    WALK_SUBEXPR ((*e)->value.compcall.base_object);
5248 	    for (a = (*e)->value.compcall.actual; a; a = a->next)
5249 	      WALK_SUBEXPR (a->expr);
5250 	    break;
5251 
5252 	  case EXPR_STRUCTURE:
5253 	  case EXPR_ARRAY:
5254 	    for (c = gfc_constructor_first ((*e)->value.constructor); c;
5255 		 c = gfc_constructor_next (c))
5256 	      {
5257 		if (c->iterator == NULL)
5258 		  WALK_SUBEXPR (c->expr);
5259 		else
5260 		  {
5261 		    iterator_level ++;
5262 		    WALK_SUBEXPR (c->expr);
5263 		    iterator_level --;
5264 		    WALK_SUBEXPR (c->iterator->var);
5265 		    WALK_SUBEXPR (c->iterator->start);
5266 		    WALK_SUBEXPR (c->iterator->end);
5267 		    WALK_SUBEXPR (c->iterator->step);
5268 		  }
5269 	      }
5270 
5271 	    if ((*e)->expr_type != EXPR_ARRAY)
5272 	      break;
5273 
5274 	    /* Fall through to the variable case in order to walk the
5275 	       reference.  */
5276 	    gcc_fallthrough ();
5277 
5278 	  case EXPR_SUBSTRING:
5279 	  case EXPR_VARIABLE:
5280 	    for (r = (*e)->ref; r; r = r->next)
5281 	      {
5282 		gfc_array_ref *ar;
5283 		int i;
5284 
5285 		switch (r->type)
5286 		  {
5287 		  case REF_ARRAY:
5288 		    ar = &r->u.ar;
5289 		    if (ar->type == AR_SECTION || ar->type == AR_ELEMENT)
5290 		      {
5291 			for (i=0; i< ar->dimen; i++)
5292 			  {
5293 			    WALK_SUBEXPR (ar->start[i]);
5294 			    WALK_SUBEXPR (ar->end[i]);
5295 			    WALK_SUBEXPR (ar->stride[i]);
5296 			  }
5297 		      }
5298 
5299 		    break;
5300 
5301 		  case REF_SUBSTRING:
5302 		    WALK_SUBEXPR (r->u.ss.start);
5303 		    WALK_SUBEXPR (r->u.ss.end);
5304 		    break;
5305 
5306 		  case REF_COMPONENT:
5307 		  case REF_INQUIRY:
5308 		    break;
5309 		  }
5310 	      }
5311 
5312 	  default:
5313 	    break;
5314 	  }
5315       return 0;
5316     }
5317   return 0;
5318 }
5319 
5320 #define WALK_SUBCODE(NODE) \
5321   do								\
5322     {								\
5323       result = gfc_code_walker (&(NODE), codefn, exprfn, data);	\
5324       if (result)						\
5325 	return result;						\
5326     }								\
5327   while (0)
5328 
5329 /* Walk code *C, calling CODEFN on each gfc_code node in it and calling EXPRFN
5330    on each expression in it.  If any of the hooks returns non-zero, that
5331    value is immediately returned.  If the hook sets *WALK_SUBTREES to 0,
5332    no subcodes or subexpressions are traversed.  */
5333 
5334 int
gfc_code_walker(gfc_code ** c,walk_code_fn_t codefn,walk_expr_fn_t exprfn,void * data)5335 gfc_code_walker (gfc_code **c, walk_code_fn_t codefn, walk_expr_fn_t exprfn,
5336 		 void *data)
5337 {
5338   for (; *c; c = &(*c)->next)
5339     {
5340       int walk_subtrees = 1;
5341       int result = codefn (c, &walk_subtrees, data);
5342       if (result)
5343 	return result;
5344 
5345       if (walk_subtrees)
5346 	{
5347 	  gfc_code *b;
5348 	  gfc_actual_arglist *a;
5349 	  gfc_code *co;
5350 	  gfc_association_list *alist;
5351 	  bool saved_in_omp_workshare;
5352 	  bool saved_in_omp_atomic;
5353 	  bool saved_in_where;
5354 
5355 	  /* There might be statement insertions before the current code,
5356 	     which must not affect the expression walker.  */
5357 
5358 	  co = *c;
5359 	  saved_in_omp_workshare = in_omp_workshare;
5360 	  saved_in_omp_atomic = in_omp_atomic;
5361 	  saved_in_where = in_where;
5362 
5363 	  switch (co->op)
5364 	    {
5365 
5366 	    case EXEC_BLOCK:
5367 	      WALK_SUBCODE (co->ext.block.ns->code);
5368 	      if (co->ext.block.assoc)
5369 		{
5370 		  bool saved_in_assoc_list = in_assoc_list;
5371 
5372 		  in_assoc_list = true;
5373 		  for (alist = co->ext.block.assoc; alist; alist = alist->next)
5374 		    WALK_SUBEXPR (alist->target);
5375 
5376 		  in_assoc_list = saved_in_assoc_list;
5377 		}
5378 
5379 	      break;
5380 
5381 	    case EXEC_DO:
5382 	      doloop_level ++;
5383 	      WALK_SUBEXPR (co->ext.iterator->var);
5384 	      WALK_SUBEXPR (co->ext.iterator->start);
5385 	      WALK_SUBEXPR (co->ext.iterator->end);
5386 	      WALK_SUBEXPR (co->ext.iterator->step);
5387 	      break;
5388 
5389 	    case EXEC_IF:
5390 	      if_level ++;
5391 	      break;
5392 
5393 	    case EXEC_WHERE:
5394 	      in_where = true;
5395 	      break;
5396 
5397 	    case EXEC_CALL:
5398 	    case EXEC_ASSIGN_CALL:
5399 	      for (a = co->ext.actual; a; a = a->next)
5400 		WALK_SUBEXPR (a->expr);
5401 	      break;
5402 
5403 	    case EXEC_CALL_PPC:
5404 	      WALK_SUBEXPR (co->expr1);
5405 	      for (a = co->ext.actual; a; a = a->next)
5406 		WALK_SUBEXPR (a->expr);
5407 	      break;
5408 
5409 	    case EXEC_SELECT:
5410 	      WALK_SUBEXPR (co->expr1);
5411 	      select_level ++;
5412 	      for (b = co->block; b; b = b->block)
5413 		{
5414 		  gfc_case *cp;
5415 		  for (cp = b->ext.block.case_list; cp; cp = cp->next)
5416 		    {
5417 		      WALK_SUBEXPR (cp->low);
5418 		      WALK_SUBEXPR (cp->high);
5419 		    }
5420 		  WALK_SUBCODE (b->next);
5421 		}
5422 	      continue;
5423 
5424 	    case EXEC_ALLOCATE:
5425 	    case EXEC_DEALLOCATE:
5426 	      {
5427 		gfc_alloc *a;
5428 		for (a = co->ext.alloc.list; a; a = a->next)
5429 		  WALK_SUBEXPR (a->expr);
5430 		break;
5431 	      }
5432 
5433 	    case EXEC_FORALL:
5434 	    case EXEC_DO_CONCURRENT:
5435 	      {
5436 		gfc_forall_iterator *fa;
5437 		for (fa = co->ext.forall_iterator; fa; fa = fa->next)
5438 		  {
5439 		    WALK_SUBEXPR (fa->var);
5440 		    WALK_SUBEXPR (fa->start);
5441 		    WALK_SUBEXPR (fa->end);
5442 		    WALK_SUBEXPR (fa->stride);
5443 		  }
5444 		if (co->op == EXEC_FORALL)
5445 		  forall_level ++;
5446 		break;
5447 	      }
5448 
5449 	    case EXEC_OPEN:
5450 	      WALK_SUBEXPR (co->ext.open->unit);
5451 	      WALK_SUBEXPR (co->ext.open->file);
5452 	      WALK_SUBEXPR (co->ext.open->status);
5453 	      WALK_SUBEXPR (co->ext.open->access);
5454 	      WALK_SUBEXPR (co->ext.open->form);
5455 	      WALK_SUBEXPR (co->ext.open->recl);
5456 	      WALK_SUBEXPR (co->ext.open->blank);
5457 	      WALK_SUBEXPR (co->ext.open->position);
5458 	      WALK_SUBEXPR (co->ext.open->action);
5459 	      WALK_SUBEXPR (co->ext.open->delim);
5460 	      WALK_SUBEXPR (co->ext.open->pad);
5461 	      WALK_SUBEXPR (co->ext.open->iostat);
5462 	      WALK_SUBEXPR (co->ext.open->iomsg);
5463 	      WALK_SUBEXPR (co->ext.open->convert);
5464 	      WALK_SUBEXPR (co->ext.open->decimal);
5465 	      WALK_SUBEXPR (co->ext.open->encoding);
5466 	      WALK_SUBEXPR (co->ext.open->round);
5467 	      WALK_SUBEXPR (co->ext.open->sign);
5468 	      WALK_SUBEXPR (co->ext.open->asynchronous);
5469 	      WALK_SUBEXPR (co->ext.open->id);
5470 	      WALK_SUBEXPR (co->ext.open->newunit);
5471 	      WALK_SUBEXPR (co->ext.open->share);
5472 	      WALK_SUBEXPR (co->ext.open->cc);
5473 	      break;
5474 
5475 	    case EXEC_CLOSE:
5476 	      WALK_SUBEXPR (co->ext.close->unit);
5477 	      WALK_SUBEXPR (co->ext.close->status);
5478 	      WALK_SUBEXPR (co->ext.close->iostat);
5479 	      WALK_SUBEXPR (co->ext.close->iomsg);
5480 	      break;
5481 
5482 	    case EXEC_BACKSPACE:
5483 	    case EXEC_ENDFILE:
5484 	    case EXEC_REWIND:
5485 	    case EXEC_FLUSH:
5486 	      WALK_SUBEXPR (co->ext.filepos->unit);
5487 	      WALK_SUBEXPR (co->ext.filepos->iostat);
5488 	      WALK_SUBEXPR (co->ext.filepos->iomsg);
5489 	      break;
5490 
5491 	    case EXEC_INQUIRE:
5492 	      WALK_SUBEXPR (co->ext.inquire->unit);
5493 	      WALK_SUBEXPR (co->ext.inquire->file);
5494 	      WALK_SUBEXPR (co->ext.inquire->iomsg);
5495 	      WALK_SUBEXPR (co->ext.inquire->iostat);
5496 	      WALK_SUBEXPR (co->ext.inquire->exist);
5497 	      WALK_SUBEXPR (co->ext.inquire->opened);
5498 	      WALK_SUBEXPR (co->ext.inquire->number);
5499 	      WALK_SUBEXPR (co->ext.inquire->named);
5500 	      WALK_SUBEXPR (co->ext.inquire->name);
5501 	      WALK_SUBEXPR (co->ext.inquire->access);
5502 	      WALK_SUBEXPR (co->ext.inquire->sequential);
5503 	      WALK_SUBEXPR (co->ext.inquire->direct);
5504 	      WALK_SUBEXPR (co->ext.inquire->form);
5505 	      WALK_SUBEXPR (co->ext.inquire->formatted);
5506 	      WALK_SUBEXPR (co->ext.inquire->unformatted);
5507 	      WALK_SUBEXPR (co->ext.inquire->recl);
5508 	      WALK_SUBEXPR (co->ext.inquire->nextrec);
5509 	      WALK_SUBEXPR (co->ext.inquire->blank);
5510 	      WALK_SUBEXPR (co->ext.inquire->position);
5511 	      WALK_SUBEXPR (co->ext.inquire->action);
5512 	      WALK_SUBEXPR (co->ext.inquire->read);
5513 	      WALK_SUBEXPR (co->ext.inquire->write);
5514 	      WALK_SUBEXPR (co->ext.inquire->readwrite);
5515 	      WALK_SUBEXPR (co->ext.inquire->delim);
5516 	      WALK_SUBEXPR (co->ext.inquire->encoding);
5517 	      WALK_SUBEXPR (co->ext.inquire->pad);
5518 	      WALK_SUBEXPR (co->ext.inquire->iolength);
5519 	      WALK_SUBEXPR (co->ext.inquire->convert);
5520 	      WALK_SUBEXPR (co->ext.inquire->strm_pos);
5521 	      WALK_SUBEXPR (co->ext.inquire->asynchronous);
5522 	      WALK_SUBEXPR (co->ext.inquire->decimal);
5523 	      WALK_SUBEXPR (co->ext.inquire->pending);
5524 	      WALK_SUBEXPR (co->ext.inquire->id);
5525 	      WALK_SUBEXPR (co->ext.inquire->sign);
5526 	      WALK_SUBEXPR (co->ext.inquire->size);
5527 	      WALK_SUBEXPR (co->ext.inquire->round);
5528 	      break;
5529 
5530 	    case EXEC_WAIT:
5531 	      WALK_SUBEXPR (co->ext.wait->unit);
5532 	      WALK_SUBEXPR (co->ext.wait->iostat);
5533 	      WALK_SUBEXPR (co->ext.wait->iomsg);
5534 	      WALK_SUBEXPR (co->ext.wait->id);
5535 	      break;
5536 
5537 	    case EXEC_READ:
5538 	    case EXEC_WRITE:
5539 	      WALK_SUBEXPR (co->ext.dt->io_unit);
5540 	      WALK_SUBEXPR (co->ext.dt->format_expr);
5541 	      WALK_SUBEXPR (co->ext.dt->rec);
5542 	      WALK_SUBEXPR (co->ext.dt->advance);
5543 	      WALK_SUBEXPR (co->ext.dt->iostat);
5544 	      WALK_SUBEXPR (co->ext.dt->size);
5545 	      WALK_SUBEXPR (co->ext.dt->iomsg);
5546 	      WALK_SUBEXPR (co->ext.dt->id);
5547 	      WALK_SUBEXPR (co->ext.dt->pos);
5548 	      WALK_SUBEXPR (co->ext.dt->asynchronous);
5549 	      WALK_SUBEXPR (co->ext.dt->blank);
5550 	      WALK_SUBEXPR (co->ext.dt->decimal);
5551 	      WALK_SUBEXPR (co->ext.dt->delim);
5552 	      WALK_SUBEXPR (co->ext.dt->pad);
5553 	      WALK_SUBEXPR (co->ext.dt->round);
5554 	      WALK_SUBEXPR (co->ext.dt->sign);
5555 	      WALK_SUBEXPR (co->ext.dt->extra_comma);
5556 	      break;
5557 
5558 	    case EXEC_OACC_ATOMIC:
5559 	    case EXEC_OMP_ATOMIC:
5560 	      in_omp_atomic = true;
5561 	      break;
5562 
5563 	    case EXEC_OMP_PARALLEL:
5564 	    case EXEC_OMP_PARALLEL_DO:
5565 	    case EXEC_OMP_PARALLEL_DO_SIMD:
5566 	    case EXEC_OMP_PARALLEL_LOOP:
5567 	    case EXEC_OMP_PARALLEL_MASKED:
5568 	    case EXEC_OMP_PARALLEL_MASKED_TASKLOOP:
5569 	    case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD:
5570 	    case EXEC_OMP_PARALLEL_MASTER:
5571 	    case EXEC_OMP_PARALLEL_MASTER_TASKLOOP:
5572 	    case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD:
5573 	    case EXEC_OMP_PARALLEL_SECTIONS:
5574 
5575 	      in_omp_workshare = false;
5576 
5577 	      /* This goto serves as a shortcut to avoid code
5578 		 duplication or a larger if or switch statement.  */
5579 	      goto check_omp_clauses;
5580 
5581 	    case EXEC_OMP_WORKSHARE:
5582 	    case EXEC_OMP_PARALLEL_WORKSHARE:
5583 
5584 	      in_omp_workshare = true;
5585 
5586 	      /* Fall through  */
5587 
5588 	    case EXEC_OMP_CRITICAL:
5589 	    case EXEC_OMP_DISTRIBUTE:
5590 	    case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
5591 	    case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
5592 	    case EXEC_OMP_DISTRIBUTE_SIMD:
5593 	    case EXEC_OMP_DO:
5594 	    case EXEC_OMP_DO_SIMD:
5595 	    case EXEC_OMP_LOOP:
5596 	    case EXEC_OMP_ORDERED:
5597 	    case EXEC_OMP_SECTIONS:
5598 	    case EXEC_OMP_SINGLE:
5599 	    case EXEC_OMP_END_SINGLE:
5600 	    case EXEC_OMP_SIMD:
5601 	    case EXEC_OMP_TASKLOOP:
5602 	    case EXEC_OMP_TASKLOOP_SIMD:
5603 	    case EXEC_OMP_TARGET:
5604 	    case EXEC_OMP_TARGET_DATA:
5605 	    case EXEC_OMP_TARGET_ENTER_DATA:
5606 	    case EXEC_OMP_TARGET_EXIT_DATA:
5607 	    case EXEC_OMP_TARGET_PARALLEL:
5608 	    case EXEC_OMP_TARGET_PARALLEL_DO:
5609 	    case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
5610 	    case EXEC_OMP_TARGET_PARALLEL_LOOP:
5611 	    case EXEC_OMP_TARGET_SIMD:
5612 	    case EXEC_OMP_TARGET_TEAMS:
5613 	    case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
5614 	    case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
5615 	    case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
5616 	    case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
5617 	    case EXEC_OMP_TARGET_TEAMS_LOOP:
5618 	    case EXEC_OMP_TARGET_UPDATE:
5619 	    case EXEC_OMP_TASK:
5620 	    case EXEC_OMP_TEAMS:
5621 	    case EXEC_OMP_TEAMS_DISTRIBUTE:
5622 	    case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
5623 	    case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
5624 	    case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
5625 	    case EXEC_OMP_TEAMS_LOOP:
5626 
5627 	      /* Come to this label only from the
5628 		 EXEC_OMP_PARALLEL_* cases above.  */
5629 
5630 	    check_omp_clauses:
5631 
5632 	      if (co->ext.omp_clauses)
5633 		{
5634 		  gfc_omp_namelist *n;
5635 		  static int list_types[]
5636 		    = { OMP_LIST_ALIGNED, OMP_LIST_LINEAR, OMP_LIST_DEPEND,
5637 			OMP_LIST_MAP, OMP_LIST_TO, OMP_LIST_FROM };
5638 		  size_t idx;
5639 		  WALK_SUBEXPR (co->ext.omp_clauses->if_expr);
5640 		  WALK_SUBEXPR (co->ext.omp_clauses->final_expr);
5641 		  WALK_SUBEXPR (co->ext.omp_clauses->num_threads);
5642 		  WALK_SUBEXPR (co->ext.omp_clauses->chunk_size);
5643 		  WALK_SUBEXPR (co->ext.omp_clauses->safelen_expr);
5644 		  WALK_SUBEXPR (co->ext.omp_clauses->simdlen_expr);
5645 		  WALK_SUBEXPR (co->ext.omp_clauses->num_teams_lower);
5646 		  WALK_SUBEXPR (co->ext.omp_clauses->num_teams_upper);
5647 		  WALK_SUBEXPR (co->ext.omp_clauses->device);
5648 		  WALK_SUBEXPR (co->ext.omp_clauses->thread_limit);
5649 		  WALK_SUBEXPR (co->ext.omp_clauses->dist_chunk_size);
5650 		  WALK_SUBEXPR (co->ext.omp_clauses->grainsize);
5651 		  WALK_SUBEXPR (co->ext.omp_clauses->hint);
5652 		  WALK_SUBEXPR (co->ext.omp_clauses->num_tasks);
5653 		  WALK_SUBEXPR (co->ext.omp_clauses->priority);
5654 		  WALK_SUBEXPR (co->ext.omp_clauses->detach);
5655 		  for (idx = 0; idx < OMP_IF_LAST; idx++)
5656 		    WALK_SUBEXPR (co->ext.omp_clauses->if_exprs[idx]);
5657 		  for (idx = 0;
5658 		       idx < sizeof (list_types) / sizeof (list_types[0]);
5659 		       idx++)
5660 		    for (n = co->ext.omp_clauses->lists[list_types[idx]];
5661 			 n; n = n->next)
5662 		      WALK_SUBEXPR (n->expr);
5663 		}
5664 	      break;
5665 	    default:
5666 	      break;
5667 	    }
5668 
5669 	  WALK_SUBEXPR (co->expr1);
5670 	  WALK_SUBEXPR (co->expr2);
5671 	  WALK_SUBEXPR (co->expr3);
5672 	  WALK_SUBEXPR (co->expr4);
5673 	  for (b = co->block; b; b = b->block)
5674 	    {
5675 	      WALK_SUBEXPR (b->expr1);
5676 	      WALK_SUBEXPR (b->expr2);
5677 	      WALK_SUBCODE (b->next);
5678 	    }
5679 
5680 	  if (co->op == EXEC_FORALL)
5681 	    forall_level --;
5682 
5683 	  if (co->op == EXEC_DO)
5684 	    doloop_level --;
5685 
5686 	  if (co->op == EXEC_IF)
5687 	    if_level --;
5688 
5689 	  if (co->op == EXEC_SELECT)
5690 	    select_level --;
5691 
5692 	  in_omp_workshare = saved_in_omp_workshare;
5693 	  in_omp_atomic = saved_in_omp_atomic;
5694 	  in_where = saved_in_where;
5695 	}
5696     }
5697   return 0;
5698 }
5699 
5700 /* As a post-resolution step, check that all global symbols which are
5701    not declared in the source file match in their call signatures.
5702    We do this by looping over the code (and expressions). The first call
5703    we happen to find is assumed to be canonical.  */
5704 
5705 
5706 /* Common tests for argument checking for both functions and subroutines.  */
5707 
5708 static int
check_externals_procedure(gfc_symbol * sym,locus * loc,gfc_actual_arglist * actual)5709 check_externals_procedure (gfc_symbol *sym, locus *loc,
5710 			   gfc_actual_arglist *actual)
5711 {
5712   gfc_gsymbol *gsym;
5713   gfc_symbol *def_sym = NULL;
5714 
5715  if (sym == NULL || sym->attr.is_bind_c)
5716     return 0;
5717 
5718   if (sym->attr.proc != PROC_EXTERNAL && sym->attr.proc != PROC_UNKNOWN)
5719     return 0;
5720 
5721   if (sym->attr.if_source == IFSRC_IFBODY || sym->attr.if_source == IFSRC_DECL)
5722     return 0;
5723 
5724   gsym = gfc_find_gsymbol (gfc_gsym_root, sym->name);
5725   if (gsym == NULL)
5726     return 0;
5727 
5728   if (gsym->ns)
5729     gfc_find_symbol (sym->name, gsym->ns, 0, &def_sym);
5730 
5731   if (def_sym)
5732     {
5733       gfc_compare_actual_formal (&actual, def_sym->formal, 0, 0, 0, loc);
5734       return 0;
5735     }
5736 
5737   /* First time we have seen this procedure called. Let's create an
5738      "interface" from the call and put it into a new namespace.  */
5739   gfc_namespace *save_ns;
5740   gfc_symbol *new_sym;
5741 
5742   gsym->where = *loc;
5743   save_ns = gfc_current_ns;
5744   gsym->ns = gfc_get_namespace (gfc_current_ns, 0);
5745   gsym->ns->proc_name = sym;
5746 
5747   gfc_get_symbol (sym->name, gsym->ns, &new_sym);
5748   gcc_assert (new_sym);
5749   new_sym->attr = sym->attr;
5750   new_sym->attr.if_source = IFSRC_DECL;
5751   gfc_current_ns = gsym->ns;
5752 
5753   gfc_get_formal_from_actual_arglist (new_sym, actual);
5754   new_sym->declared_at = *loc;
5755   gfc_current_ns = save_ns;
5756 
5757   return 0;
5758 
5759 }
5760 
5761 /* Callback for calls of external routines.  */
5762 
5763 static int
check_externals_code(gfc_code ** c,int * walk_subtrees ATTRIBUTE_UNUSED,void * data ATTRIBUTE_UNUSED)5764 check_externals_code (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
5765 		      void *data ATTRIBUTE_UNUSED)
5766 {
5767   gfc_code *co = *c;
5768   gfc_symbol *sym;
5769   locus *loc;
5770   gfc_actual_arglist *actual;
5771 
5772   if (co->op != EXEC_CALL)
5773     return 0;
5774 
5775   sym = co->resolved_sym;
5776   loc = &co->loc;
5777   actual = co->ext.actual;
5778 
5779   return check_externals_procedure (sym, loc, actual);
5780 
5781 }
5782 
5783 /* Callback for external functions.  */
5784 
5785 static int
check_externals_expr(gfc_expr ** ep,int * walk_subtrees ATTRIBUTE_UNUSED,void * data ATTRIBUTE_UNUSED)5786 check_externals_expr (gfc_expr **ep, int *walk_subtrees ATTRIBUTE_UNUSED,
5787 		      void *data ATTRIBUTE_UNUSED)
5788 {
5789   gfc_expr *e = *ep;
5790   gfc_symbol *sym;
5791   locus *loc;
5792   gfc_actual_arglist *actual;
5793 
5794   if (e->expr_type != EXPR_FUNCTION)
5795     return 0;
5796 
5797   if (e->symtree && e->symtree->n.sym->attr.subroutine)
5798     return 0;
5799 
5800   sym = e->value.function.esym;
5801   if (sym == NULL)
5802     return 0;
5803 
5804   loc = &e->where;
5805   actual = e->value.function.actual;
5806 
5807   return check_externals_procedure (sym, loc, actual);
5808 }
5809 
5810 /* Function to check if any interface clashes with a global
5811    identifier, to be invoked via gfc_traverse_ns.  */
5812 
5813 static void
check_against_globals(gfc_symbol * sym)5814 check_against_globals (gfc_symbol *sym)
5815 {
5816   gfc_gsymbol *gsym;
5817   gfc_symbol *def_sym = NULL;
5818   const char *sym_name;
5819   char buf  [200];
5820 
5821   if (sym->attr.if_source != IFSRC_IFBODY || sym->attr.flavor != FL_PROCEDURE
5822       || sym->attr.generic || sym->error)
5823     return;
5824 
5825   if (sym->binding_label)
5826     sym_name = sym->binding_label;
5827   else
5828     sym_name = sym->name;
5829 
5830   gsym = gfc_find_gsymbol (gfc_gsym_root, sym_name);
5831   if (gsym && gsym->ns)
5832     gfc_find_symbol (sym->name, gsym->ns, 0, &def_sym);
5833 
5834   if (!def_sym || def_sym->error || def_sym->attr.generic)
5835     return;
5836 
5837   buf[0] = 0;
5838   gfc_compare_interfaces (sym, def_sym, sym->name, 0, 1, buf, sizeof(buf),
5839 			  NULL, NULL, NULL);
5840   if (buf[0] != 0)
5841     {
5842       gfc_warning (0, "%s between %L and %L", buf, &def_sym->declared_at,
5843 		   &sym->declared_at);
5844       sym->error = 1;
5845       def_sym->error = 1;
5846     }
5847 
5848 }
5849 
5850 /* Do the code-walkling part for gfc_check_externals.  */
5851 
5852 static void
gfc_check_externals0(gfc_namespace * ns)5853 gfc_check_externals0 (gfc_namespace *ns)
5854 {
5855   gfc_code_walker (&ns->code, check_externals_code, check_externals_expr, NULL);
5856 
5857   for (ns = ns->contained; ns; ns = ns->sibling)
5858     {
5859       if (ns->code == NULL || ns->code->op != EXEC_BLOCK)
5860 	gfc_check_externals0 (ns);
5861     }
5862 
5863 }
5864 
5865 /* Called routine.  */
5866 
5867 void
gfc_check_externals(gfc_namespace * ns)5868 gfc_check_externals (gfc_namespace *ns)
5869 {
5870   gfc_clear_error ();
5871 
5872   /* Turn errors into warnings if the user indicated this.  */
5873 
5874   if (!pedantic && flag_allow_argument_mismatch)
5875     gfc_errors_to_warnings (true);
5876 
5877   gfc_check_externals0 (ns);
5878   gfc_traverse_ns (ns, check_against_globals);
5879 
5880   gfc_errors_to_warnings (false);
5881 }
5882 
5883 /* Callback function. If there is a call to a subroutine which is
5884    neither pure nor implicit_pure, unset the implicit_pure flag for
5885    the caller and return -1.  */
5886 
5887 static int
implicit_pure_call(gfc_code ** c,int * walk_subtrees ATTRIBUTE_UNUSED,void * sym_data)5888 implicit_pure_call (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
5889 		    void *sym_data)
5890 {
5891   gfc_code *co = *c;
5892   gfc_symbol *caller_sym;
5893   symbol_attribute *a;
5894 
5895   if (co->op != EXEC_CALL || co->resolved_sym == NULL)
5896     return 0;
5897 
5898   a = &co->resolved_sym->attr;
5899   if (a->intrinsic || a->pure || a->implicit_pure)
5900     return 0;
5901 
5902   caller_sym = (gfc_symbol *) sym_data;
5903   gfc_unset_implicit_pure (caller_sym);
5904   return 1;
5905 }
5906 
5907 /* Callback function. If there is a call to a function which is
5908    neither pure nor implicit_pure, unset the implicit_pure flag for
5909    the caller and return 1.  */
5910 
5911 static int
implicit_pure_expr(gfc_expr ** e,int * walk ATTRIBUTE_UNUSED,void * sym_data)5912 implicit_pure_expr (gfc_expr **e, int *walk ATTRIBUTE_UNUSED, void *sym_data)
5913 {
5914   gfc_expr *expr = *e;
5915   gfc_symbol *caller_sym;
5916   gfc_symbol *sym;
5917   symbol_attribute *a;
5918 
5919   if (expr->expr_type != EXPR_FUNCTION || expr->value.function.isym)
5920     return 0;
5921 
5922   sym = expr->symtree->n.sym;
5923   a = &sym->attr;
5924   if (a->pure || a->implicit_pure)
5925     return 0;
5926 
5927   caller_sym = (gfc_symbol *) sym_data;
5928   gfc_unset_implicit_pure (caller_sym);
5929   return 1;
5930 }
5931 
5932 /* Go through all procedures in the namespace and unset the
5933    implicit_pure attribute for any procedure that calls something not
5934    pure or implicit pure.  */
5935 
5936 bool
gfc_fix_implicit_pure(gfc_namespace * ns)5937 gfc_fix_implicit_pure (gfc_namespace *ns)
5938 {
5939   bool changed = false;
5940   gfc_symbol *proc = ns->proc_name;
5941 
5942   if (proc && proc->attr.flavor == FL_PROCEDURE && proc->attr.implicit_pure
5943       && ns->code
5944       && gfc_code_walker (&ns->code, implicit_pure_call, implicit_pure_expr,
5945 			  (void *) ns->proc_name))
5946     changed = true;
5947 
5948   for (ns = ns->contained; ns; ns = ns->sibling)
5949     {
5950       if (gfc_fix_implicit_pure (ns))
5951 	changed = true;
5952     }
5953 
5954   return changed;
5955 }
5956