xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/fortran/frontend-passes.c (revision 4c3eb207d36f67d31994830c0a694161fc1ca39b)
1 /* Pass manager for Fortran front end.
2    Copyright (C) 2010-2020 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 intrnisics.  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 assigment 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 = i - 1; 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->rank != 1)
2280     return;
2281 
2282   *e = gfc_get_array_expr (fn->ts.type, fn->ts.kind, &fn->where);
2283   (*e)->shape = fn->shape;
2284   fn->rank = 0;
2285   fn->shape = NULL;
2286   gfc_constructor_append_expr (&(*e)->value.constructor, fn, &fn->where);
2287 
2288   name = XALLOCAVEC (char, strlen (fn->value.function.name) + 1);
2289   strcpy (name, fn->value.function.name);
2290   p = strstr (name, "loc0");
2291   p[3] = '1';
2292   fn->value.function.name = gfc_get_string ("%s", name);
2293   if (fn->value.function.actual->next)
2294     {
2295       a = fn->value.function.actual->next;
2296       gcc_assert (a->expr == NULL);
2297     }
2298   else
2299     {
2300       a = gfc_get_actual_arglist ();
2301       fn->value.function.actual->next = a;
2302     }
2303   a->expr = gfc_get_constant_expr (BT_INTEGER, gfc_default_integer_kind,
2304 				   &fn->where);
2305   mpz_set_ui (a->expr->value.integer, 1);
2306 }
2307 
2308 /* Callback function for code checking that we do not pass a DO variable to an
2309    INTENT(OUT) or INTENT(INOUT) dummy variable.  */
2310 
2311 static int
doloop_code(gfc_code ** c,int * walk_subtrees ATTRIBUTE_UNUSED,void * data ATTRIBUTE_UNUSED)2312 doloop_code (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
2313 	 void *data ATTRIBUTE_UNUSED)
2314 {
2315   gfc_code *co;
2316   int i;
2317   gfc_formal_arglist *f;
2318   gfc_actual_arglist *a;
2319   gfc_code *cl;
2320   do_t loop, *lp;
2321   bool seen_goto;
2322 
2323   co = *c;
2324 
2325   /* If the doloop_list grew, we have to truncate it here.  */
2326 
2327   if ((unsigned) doloop_level < doloop_list.length())
2328     doloop_list.truncate (doloop_level);
2329 
2330   seen_goto = false;
2331   switch (co->op)
2332     {
2333     case EXEC_DO:
2334 
2335       if (co->ext.iterator && co->ext.iterator->var)
2336 	loop.c = co;
2337       else
2338 	loop.c = NULL;
2339 
2340       loop.branch_level = if_level + select_level;
2341       loop.seen_goto = false;
2342       doloop_list.safe_push (loop);
2343       break;
2344 
2345       /* If anything could transfer control away from a suspicious
2346 	 subscript, make sure to set seen_goto in the current DO loop
2347 	 (if any).  */
2348     case EXEC_GOTO:
2349     case EXEC_EXIT:
2350     case EXEC_STOP:
2351     case EXEC_ERROR_STOP:
2352     case EXEC_CYCLE:
2353       seen_goto = true;
2354       break;
2355 
2356     case EXEC_OPEN:
2357       if (co->ext.open->err)
2358 	seen_goto = true;
2359       break;
2360 
2361     case EXEC_CLOSE:
2362       if (co->ext.close->err)
2363 	seen_goto = true;
2364       break;
2365 
2366     case EXEC_BACKSPACE:
2367     case EXEC_ENDFILE:
2368     case EXEC_REWIND:
2369     case EXEC_FLUSH:
2370 
2371       if (co->ext.filepos->err)
2372 	seen_goto = true;
2373       break;
2374 
2375     case EXEC_INQUIRE:
2376       if (co->ext.filepos->err)
2377 	seen_goto = true;
2378       break;
2379 
2380     case EXEC_READ:
2381     case EXEC_WRITE:
2382       if (co->ext.dt->err || co->ext.dt->end || co->ext.dt->eor)
2383 	seen_goto = true;
2384       break;
2385 
2386     case EXEC_WAIT:
2387       if (co->ext.wait->err || co->ext.wait->end || co->ext.wait->eor)
2388 	loop.seen_goto = true;
2389       break;
2390 
2391     case EXEC_CALL:
2392 
2393       if (co->resolved_sym == NULL)
2394 	break;
2395 
2396       f = gfc_sym_get_dummy_args (co->resolved_sym);
2397 
2398       /* Withot a formal arglist, there is only unknown INTENT,
2399 	 which we don't check for.  */
2400       if (f == NULL)
2401 	break;
2402 
2403       a = co->ext.actual;
2404 
2405       while (a && f)
2406 	{
2407 	  FOR_EACH_VEC_ELT (doloop_list, i, lp)
2408 	    {
2409 	      gfc_symbol *do_sym;
2410 	      cl = lp->c;
2411 
2412 	      if (cl == NULL)
2413 		break;
2414 
2415 	      do_sym = cl->ext.iterator->var->symtree->n.sym;
2416 
2417 	      if (a->expr && a->expr->symtree && f->sym
2418 		  && a->expr->symtree->n.sym == do_sym)
2419 		{
2420 		  if (f->sym->attr.intent == INTENT_OUT)
2421 		    gfc_error_now ("Variable %qs at %L set to undefined "
2422 				   "value inside loop  beginning at %L as "
2423 				   "INTENT(OUT) argument to subroutine %qs",
2424 				   do_sym->name, &a->expr->where,
2425 				   &(doloop_list[i].c->loc),
2426 				   co->symtree->n.sym->name);
2427 		  else if (f->sym->attr.intent == INTENT_INOUT)
2428 		    gfc_error_now ("Variable %qs at %L not definable inside "
2429 				   "loop beginning at %L as INTENT(INOUT) "
2430 				   "argument to subroutine %qs",
2431 				   do_sym->name, &a->expr->where,
2432 				   &(doloop_list[i].c->loc),
2433 				   co->symtree->n.sym->name);
2434 		}
2435 	    }
2436 	  a = a->next;
2437 	  f = f->next;
2438 	}
2439       break;
2440 
2441     default:
2442       break;
2443     }
2444   if (seen_goto && doloop_level > 0)
2445     doloop_list[doloop_level-1].seen_goto = true;
2446 
2447   return 0;
2448 }
2449 
2450 /* Callback function to warn about different things within DO loops.  */
2451 
2452 static int
do_function(gfc_expr ** e,int * walk_subtrees ATTRIBUTE_UNUSED,void * data ATTRIBUTE_UNUSED)2453 do_function (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
2454 	     void *data ATTRIBUTE_UNUSED)
2455 {
2456   do_t *last;
2457 
2458   if (doloop_list.length () == 0)
2459     return 0;
2460 
2461   if ((*e)->expr_type == EXPR_FUNCTION)
2462     do_intent (e);
2463 
2464   last = &doloop_list.last();
2465   if (last->seen_goto && !warn_do_subscript)
2466     return 0;
2467 
2468   if ((*e)->expr_type == EXPR_VARIABLE)
2469     do_subscript (e);
2470 
2471   return 0;
2472 }
2473 
2474 typedef struct
2475 {
2476   gfc_symbol *sym;
2477   mpz_t val;
2478 } insert_index_t;
2479 
2480 /* Callback function - if the expression is the variable in data->sym,
2481    replace it with a constant from data->val.  */
2482 
2483 static int
callback_insert_index(gfc_expr ** e,int * walk_subtrees ATTRIBUTE_UNUSED,void * data)2484 callback_insert_index (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
2485 		       void *data)
2486 {
2487   insert_index_t *d;
2488   gfc_expr *ex, *n;
2489 
2490   ex = (*e);
2491   if (ex->expr_type != EXPR_VARIABLE)
2492     return 0;
2493 
2494   d = (insert_index_t *) data;
2495   if (ex->symtree->n.sym != d->sym)
2496     return 0;
2497 
2498   n = gfc_get_constant_expr (BT_INTEGER, ex->ts.kind, &ex->where);
2499   mpz_set (n->value.integer, d->val);
2500 
2501   gfc_free_expr (ex);
2502   *e = n;
2503   return 0;
2504 }
2505 
2506 /* In the expression e, replace occurrences of the variable sym with
2507    val.  If this results in a constant expression, return true and
2508    return the value in ret.  Return false if the expression already
2509    is a constant.  Caller has to clear ret in that case.  */
2510 
2511 static bool
insert_index(gfc_expr * e,gfc_symbol * sym,mpz_t val,mpz_t ret)2512 insert_index (gfc_expr *e, gfc_symbol *sym, mpz_t val, mpz_t ret)
2513 {
2514   gfc_expr *n;
2515   insert_index_t data;
2516   bool rc;
2517 
2518   if (e->expr_type == EXPR_CONSTANT)
2519     return false;
2520 
2521   n = gfc_copy_expr (e);
2522   data.sym = sym;
2523   mpz_init_set (data.val, val);
2524   gfc_expr_walker (&n, callback_insert_index, (void *) &data);
2525 
2526   /* Suppress errors here - we could get errors here such as an
2527      out of bounds access for arrays, see PR 90563.  */
2528   gfc_push_suppress_errors ();
2529   gfc_simplify_expr (n, 0);
2530   gfc_pop_suppress_errors ();
2531 
2532   if (n->expr_type == EXPR_CONSTANT)
2533     {
2534       rc = true;
2535       mpz_init_set (ret, n->value.integer);
2536     }
2537   else
2538     rc = false;
2539 
2540   mpz_clear (data.val);
2541   gfc_free_expr (n);
2542   return rc;
2543 
2544 }
2545 
2546 /* Check array subscripts for possible out-of-bounds accesses in DO
2547    loops with constant bounds.  */
2548 
2549 static int
do_subscript(gfc_expr ** e)2550 do_subscript (gfc_expr **e)
2551 {
2552   gfc_expr *v;
2553   gfc_array_ref *ar;
2554   gfc_ref *ref;
2555   int i,j;
2556   gfc_code *dl;
2557   do_t *lp;
2558 
2559   v = *e;
2560   /* Constants are already checked.  */
2561   if (v->expr_type == EXPR_CONSTANT)
2562     return 0;
2563 
2564   /* Wrong warnings will be generated in an associate list.  */
2565   if (in_assoc_list)
2566     return 0;
2567 
2568   /* We already warned about this.  */
2569   if (v->do_not_warn)
2570     return 0;
2571 
2572   v->do_not_warn = 1;
2573 
2574   for (ref = v->ref; ref; ref = ref->next)
2575     {
2576       if (ref->type == REF_ARRAY && ref->u.ar.type == AR_ELEMENT)
2577 	{
2578 	  ar = & ref->u.ar;
2579 	  FOR_EACH_VEC_ELT (doloop_list, j, lp)
2580 	    {
2581 	      gfc_symbol *do_sym;
2582 	      mpz_t do_start, do_step, do_end;
2583 	      bool have_do_start, have_do_end;
2584 	      bool error_not_proven;
2585 	      int warn;
2586 	      int sgn;
2587 
2588 	      dl = lp->c;
2589 	      if (dl == NULL)
2590 		break;
2591 
2592 	      /* If we are within a branch, or a goto or equivalent
2593 		 was seen in the DO loop before, then we cannot prove that
2594 		 this expression is actually evaluated.  Don't do anything
2595 		 unless we want to see it all.  */
2596 	      error_not_proven = lp->seen_goto
2597 		|| lp->branch_level < if_level + select_level;
2598 
2599 	      if (error_not_proven && !warn_do_subscript)
2600 		break;
2601 
2602 	      if (error_not_proven)
2603 		warn = OPT_Wdo_subscript;
2604 	      else
2605 		warn = 0;
2606 
2607 	      do_sym = dl->ext.iterator->var->symtree->n.sym;
2608 	      if (do_sym->ts.type != BT_INTEGER)
2609 		continue;
2610 
2611 	      /* If we do not know about the stepsize, the loop may be zero trip.
2612 		 Do not warn in this case.  */
2613 
2614 	      if (dl->ext.iterator->step->expr_type == EXPR_CONSTANT)
2615 		{
2616 		  sgn = mpz_cmp_ui (dl->ext.iterator->step->value.integer, 0);
2617 		  /* This can happen, but then the error has been
2618 		     reported previously.  */
2619 		  if (sgn == 0)
2620 		    continue;
2621 
2622 		  mpz_init_set (do_step, dl->ext.iterator->step->value.integer);
2623 		}
2624 
2625 	      else
2626 		continue;
2627 
2628 	      if (dl->ext.iterator->start->expr_type == EXPR_CONSTANT)
2629 		{
2630 		  have_do_start = true;
2631 		  mpz_init_set (do_start, dl->ext.iterator->start->value.integer);
2632 		}
2633 	      else
2634 		have_do_start = false;
2635 
2636 	      if (dl->ext.iterator->end->expr_type == EXPR_CONSTANT)
2637 		{
2638 		  have_do_end = true;
2639 		  mpz_init_set (do_end, dl->ext.iterator->end->value.integer);
2640 		}
2641 	      else
2642 		have_do_end = false;
2643 
2644 	      if (!have_do_start && !have_do_end)
2645 		return 0;
2646 
2647 	      /* No warning inside a zero-trip loop.  */
2648 	      if (have_do_start && have_do_end)
2649 		{
2650 		  int cmp;
2651 
2652 		  cmp = mpz_cmp (do_end, do_start);
2653 		  if ((sgn > 0 && cmp < 0) || (sgn < 0 && cmp > 0))
2654 		    break;
2655 		}
2656 
2657 	      /* May have to correct the end value if the step does not equal
2658 		 one.  */
2659 	      if (have_do_start && have_do_end && mpz_cmp_ui (do_step, 1) != 0)
2660 		{
2661 		  mpz_t diff, rem;
2662 
2663 		  mpz_init (diff);
2664 		  mpz_init (rem);
2665 		  mpz_sub (diff, do_end, do_start);
2666 		  mpz_tdiv_r (rem, diff, do_step);
2667 		  mpz_sub (do_end, do_end, rem);
2668 		  mpz_clear (diff);
2669 		  mpz_clear (rem);
2670 		}
2671 
2672 	      for (i = 0; i< ar->dimen; i++)
2673 		{
2674 		  mpz_t val;
2675 		  if (ar->dimen_type[i] == DIMEN_ELEMENT && have_do_start
2676 		      && insert_index (ar->start[i], do_sym, do_start, val))
2677 		    {
2678 		      if (ar->as->lower[i]
2679 			  && ar->as->lower[i]->expr_type == EXPR_CONSTANT
2680 			  && ar->as->lower[i]->ts.type == BT_INTEGER
2681 			  && mpz_cmp (val, ar->as->lower[i]->value.integer) < 0)
2682 			gfc_warning (warn, "Array reference at %L out of bounds "
2683 				     "(%ld < %ld) in loop beginning at %L",
2684 				     &ar->start[i]->where, mpz_get_si (val),
2685 				     mpz_get_si (ar->as->lower[i]->value.integer),
2686 				     &doloop_list[j].c->loc);
2687 
2688 		      if (ar->as->upper[i]
2689 			  && ar->as->upper[i]->expr_type == EXPR_CONSTANT
2690 			  && ar->as->upper[i]->ts.type == BT_INTEGER
2691 			  && mpz_cmp (val, ar->as->upper[i]->value.integer) > 0)
2692 			    gfc_warning (warn, "Array reference at %L out of bounds "
2693 					 "(%ld > %ld) in loop beginning at %L",
2694 					 &ar->start[i]->where, mpz_get_si (val),
2695 					 mpz_get_si (ar->as->upper[i]->value.integer),
2696 					 &doloop_list[j].c->loc);
2697 
2698 		      mpz_clear (val);
2699 		    }
2700 
2701 		  if (ar->dimen_type[i] == DIMEN_ELEMENT && have_do_end
2702 		      && insert_index (ar->start[i], do_sym, do_end, val))
2703 		    {
2704 		      if (ar->as->lower[i]
2705 			  && ar->as->lower[i]->expr_type == EXPR_CONSTANT
2706 			  && ar->as->lower[i]->ts.type == BT_INTEGER
2707 			  && mpz_cmp (val, ar->as->lower[i]->value.integer) < 0)
2708 			gfc_warning (warn, "Array reference at %L out of bounds "
2709 				     "(%ld < %ld) in loop beginning at %L",
2710 				     &ar->start[i]->where, mpz_get_si (val),
2711 				     mpz_get_si (ar->as->lower[i]->value.integer),
2712 				     &doloop_list[j].c->loc);
2713 
2714 		      if (ar->as->upper[i]
2715 			  && ar->as->upper[i]->expr_type == EXPR_CONSTANT
2716 			  && ar->as->upper[i]->ts.type == BT_INTEGER
2717 			  && mpz_cmp (val, ar->as->upper[i]->value.integer) > 0)
2718 			gfc_warning (warn, "Array reference at %L out of bounds "
2719 				     "(%ld > %ld) in loop beginning at %L",
2720 				     &ar->start[i]->where, mpz_get_si (val),
2721 				     mpz_get_si (ar->as->upper[i]->value.integer),
2722 				     &doloop_list[j].c->loc);
2723 
2724 		      mpz_clear (val);
2725 		    }
2726 		}
2727 	    }
2728 	}
2729     }
2730   return 0;
2731 }
2732 /* Function for functions checking that we do not pass a DO variable
2733    to an INTENT(OUT) or INTENT(INOUT) dummy variable.  */
2734 
2735 static int
do_intent(gfc_expr ** e)2736 do_intent (gfc_expr **e)
2737 {
2738   gfc_formal_arglist *f;
2739   gfc_actual_arglist *a;
2740   gfc_expr *expr;
2741   gfc_code *dl;
2742   do_t *lp;
2743   int i;
2744 
2745   expr = *e;
2746   if (expr->expr_type != EXPR_FUNCTION)
2747     return 0;
2748 
2749   /* Intrinsic functions don't modify their arguments.  */
2750 
2751   if (expr->value.function.isym)
2752     return 0;
2753 
2754   f = gfc_sym_get_dummy_args (expr->symtree->n.sym);
2755 
2756   /* Without a formal arglist, there is only unknown INTENT,
2757      which we don't check for.  */
2758   if (f == NULL)
2759     return 0;
2760 
2761   a = expr->value.function.actual;
2762 
2763   while (a && f)
2764     {
2765       FOR_EACH_VEC_ELT (doloop_list, i, lp)
2766 	{
2767 	  gfc_symbol *do_sym;
2768 	  dl = lp->c;
2769 	  if (dl == NULL)
2770 	    break;
2771 
2772 	  do_sym = dl->ext.iterator->var->symtree->n.sym;
2773 
2774 	  if (a->expr && a->expr->symtree
2775 	      && a->expr->symtree->n.sym == do_sym)
2776 	    {
2777 	      if (f->sym->attr.intent == INTENT_OUT)
2778 		gfc_error_now ("Variable %qs at %L set to undefined value "
2779 			       "inside loop beginning at %L as INTENT(OUT) "
2780 			       "argument to function %qs", do_sym->name,
2781 			       &a->expr->where, &doloop_list[i].c->loc,
2782 			       expr->symtree->n.sym->name);
2783 	      else if (f->sym->attr.intent == INTENT_INOUT)
2784 		gfc_error_now ("Variable %qs at %L not definable inside loop"
2785 			       " beginning at %L as INTENT(INOUT) argument to"
2786 			       " function %qs", do_sym->name,
2787 			       &a->expr->where, &doloop_list[i].c->loc,
2788 			       expr->symtree->n.sym->name);
2789 	    }
2790 	}
2791       a = a->next;
2792       f = f->next;
2793     }
2794 
2795   return 0;
2796 }
2797 
2798 static void
doloop_warn(gfc_namespace * ns)2799 doloop_warn (gfc_namespace *ns)
2800 {
2801   gfc_code_walker (&ns->code, doloop_code, do_function, NULL);
2802 
2803   for (ns = ns->contained; ns; ns = ns->sibling)
2804     {
2805       if (ns->code == NULL || ns->code->op != EXEC_BLOCK)
2806 	doloop_warn (ns);
2807     }
2808 }
2809 
2810 /* This selction deals with inlining calls to MATMUL.  */
2811 
2812 /* Replace calls to matmul outside of straight assignments with a temporary
2813    variable so that later inlining will work.  */
2814 
2815 static int
matmul_to_var_expr(gfc_expr ** ep,int * walk_subtrees ATTRIBUTE_UNUSED,void * data)2816 matmul_to_var_expr (gfc_expr **ep, int *walk_subtrees ATTRIBUTE_UNUSED,
2817 		    void *data)
2818 {
2819   gfc_expr *e, *n;
2820   bool *found = (bool *) data;
2821 
2822   e = *ep;
2823 
2824   if (e->expr_type != EXPR_FUNCTION
2825       || e->value.function.isym == NULL
2826       || e->value.function.isym->id != GFC_ISYM_MATMUL)
2827     return 0;
2828 
2829   if (forall_level > 0 || iterator_level > 0 || in_omp_workshare
2830       || in_omp_atomic || in_where || in_assoc_list)
2831     return 0;
2832 
2833   /* Check if this is already in the form c = matmul(a,b).  */
2834 
2835   if ((*current_code)->expr2 == e)
2836     return 0;
2837 
2838   n = create_var (e, "matmul");
2839 
2840   /* If create_var is unable to create a variable (for example if
2841      -fno-realloc-lhs is in force with a variable that does not have bounds
2842      known at compile-time), just return.  */
2843 
2844   if (n == NULL)
2845     return 0;
2846 
2847   *ep = n;
2848   *found = true;
2849   return 0;
2850 }
2851 
2852 /* Set current_code and associated variables so that matmul_to_var_expr can
2853    work.  */
2854 
2855 static int
matmul_to_var_code(gfc_code ** c,int * walk_subtrees ATTRIBUTE_UNUSED,void * data ATTRIBUTE_UNUSED)2856 matmul_to_var_code (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
2857 		    void *data ATTRIBUTE_UNUSED)
2858 {
2859   if (current_code != c)
2860     {
2861       current_code = c;
2862       inserted_block = NULL;
2863       changed_statement = NULL;
2864     }
2865 
2866   return 0;
2867 }
2868 
2869 
2870 /* Take a statement of the shape c = matmul(a,b) and create temporaries
2871    for a and b if there is a dependency between the arguments and the
2872    result variable or if a or b are the result of calculations that cannot
2873    be handled by the inliner.  */
2874 
2875 static int
matmul_temp_args(gfc_code ** c,int * walk_subtrees ATTRIBUTE_UNUSED,void * data ATTRIBUTE_UNUSED)2876 matmul_temp_args (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
2877 		  void *data ATTRIBUTE_UNUSED)
2878 {
2879   gfc_expr *expr1, *expr2;
2880   gfc_code *co;
2881   gfc_actual_arglist *a, *b;
2882   bool a_tmp, b_tmp;
2883   gfc_expr *matrix_a, *matrix_b;
2884   bool conjg_a, conjg_b, transpose_a, transpose_b;
2885 
2886   co = *c;
2887 
2888   if (co->op != EXEC_ASSIGN)
2889     return 0;
2890 
2891   if (forall_level > 0 || iterator_level > 0 || in_omp_workshare
2892       || in_omp_atomic || in_where)
2893     return 0;
2894 
2895   /* This has some duplication with inline_matmul_assign.  This
2896      is because the creation of temporary variables could still fail,
2897      and inline_matmul_assign still needs to be able to handle these
2898      cases.  */
2899   expr1 = co->expr1;
2900   expr2 = co->expr2;
2901 
2902   if (expr2->expr_type != EXPR_FUNCTION
2903       || expr2->value.function.isym == NULL
2904       || expr2->value.function.isym->id != GFC_ISYM_MATMUL)
2905     return 0;
2906 
2907   a_tmp = false;
2908   a = expr2->value.function.actual;
2909   matrix_a = check_conjg_transpose_variable (a->expr, &conjg_a, &transpose_a);
2910   if (matrix_a != NULL)
2911     {
2912       if (matrix_a->expr_type == EXPR_VARIABLE
2913 	  && (gfc_check_dependency (matrix_a, expr1, true)
2914 	      || gfc_has_dimen_vector_ref (matrix_a)))
2915 	a_tmp = true;
2916     }
2917   else
2918     a_tmp = true;
2919 
2920   b_tmp = false;
2921   b = a->next;
2922   matrix_b = check_conjg_transpose_variable (b->expr, &conjg_b, &transpose_b);
2923   if (matrix_b != NULL)
2924     {
2925       if (matrix_b->expr_type == EXPR_VARIABLE
2926 	  && (gfc_check_dependency (matrix_b, expr1, true)
2927 	      || gfc_has_dimen_vector_ref (matrix_b)))
2928 	b_tmp = true;
2929     }
2930   else
2931     b_tmp = true;
2932 
2933   if (!a_tmp && !b_tmp)
2934     return 0;
2935 
2936   current_code = c;
2937   inserted_block = NULL;
2938   changed_statement = NULL;
2939   if (a_tmp)
2940     {
2941       gfc_expr *at;
2942       at = create_var (a->expr,"mma");
2943       if (at)
2944 	a->expr = at;
2945     }
2946   if (b_tmp)
2947     {
2948       gfc_expr *bt;
2949       bt = create_var (b->expr,"mmb");
2950       if (bt)
2951 	b->expr = bt;
2952     }
2953   return 0;
2954 }
2955 
2956 /* Auxiliary function to build and simplify an array inquiry function.
2957    dim is zero-based.  */
2958 
2959 static gfc_expr *
2960 get_array_inq_function (gfc_isym_id id, gfc_expr *e, int dim, int okind = 0)
2961 {
2962   gfc_expr *fcn;
2963   gfc_expr *dim_arg, *kind;
2964   const char *name;
2965   gfc_expr *ec;
2966 
2967   switch (id)
2968     {
2969     case GFC_ISYM_LBOUND:
2970       name = "_gfortran_lbound";
2971       break;
2972 
2973     case GFC_ISYM_UBOUND:
2974       name = "_gfortran_ubound";
2975       break;
2976 
2977     case GFC_ISYM_SIZE:
2978       name = "_gfortran_size";
2979       break;
2980 
2981     default:
2982       gcc_unreachable ();
2983     }
2984 
2985   dim_arg =  gfc_get_int_expr (gfc_default_integer_kind, &e->where, dim);
2986   if (okind != 0)
2987     kind = gfc_get_int_expr (gfc_default_integer_kind, &e->where,
2988 			     okind);
2989   else
2990     kind = gfc_get_int_expr (gfc_default_integer_kind, &e->where,
2991 			     gfc_index_integer_kind);
2992 
2993   ec = gfc_copy_expr (e);
2994 
2995   /* No bounds checking, this will be done before the loops if -fcheck=bounds
2996      is in effect.  */
2997   ec->no_bounds_check = 1;
2998   fcn = gfc_build_intrinsic_call (current_ns, id, name, e->where, 3,
2999 				  ec, dim_arg,  kind);
3000   gfc_simplify_expr (fcn, 0);
3001   fcn->no_bounds_check = 1;
3002   return fcn;
3003 }
3004 
3005 /* Builds a logical expression.  */
3006 
3007 static gfc_expr*
build_logical_expr(gfc_intrinsic_op op,gfc_expr * e1,gfc_expr * e2)3008 build_logical_expr (gfc_intrinsic_op op, gfc_expr *e1, gfc_expr *e2)
3009 {
3010   gfc_typespec ts;
3011   gfc_expr *res;
3012 
3013   ts.type = BT_LOGICAL;
3014   ts.kind = gfc_default_logical_kind;
3015   res = gfc_get_expr ();
3016   res->where = e1->where;
3017   res->expr_type = EXPR_OP;
3018   res->value.op.op = op;
3019   res->value.op.op1 = e1;
3020   res->value.op.op2 = e2;
3021   res->ts = ts;
3022 
3023   return res;
3024 }
3025 
3026 
3027 /* Return an operation of one two gfc_expr (one if e2 is NULL). This assumes
3028    compatible typespecs.  */
3029 
3030 static gfc_expr *
get_operand(gfc_intrinsic_op op,gfc_expr * e1,gfc_expr * e2)3031 get_operand (gfc_intrinsic_op op, gfc_expr *e1, gfc_expr *e2)
3032 {
3033   gfc_expr *res;
3034 
3035   res = gfc_get_expr ();
3036   res->ts = e1->ts;
3037   res->where = e1->where;
3038   res->expr_type = EXPR_OP;
3039   res->value.op.op = op;
3040   res->value.op.op1 = e1;
3041   res->value.op.op2 = e2;
3042   gfc_simplify_expr (res, 0);
3043   return res;
3044 }
3045 
3046 /* Generate the IF statement for a runtime check if we want to do inlining or
3047    not - putting in the code for both branches and putting it into the syntax
3048    tree is the caller's responsibility.  For fixed array sizes, this should be
3049    removed by DCE. Only called for rank-two matrices A and B.  */
3050 
3051 static gfc_code *
inline_limit_check(gfc_expr * a,gfc_expr * b,int limit)3052 inline_limit_check (gfc_expr *a, gfc_expr *b, int limit)
3053 {
3054   gfc_expr *inline_limit;
3055   gfc_code *if_1, *if_2, *else_2;
3056   gfc_expr *b2, *a2, *a1, *m1, *m2;
3057   gfc_typespec ts;
3058   gfc_expr *cond;
3059 
3060   /* Calculation is done in real to avoid integer overflow.  */
3061 
3062   inline_limit = gfc_get_constant_expr (BT_REAL, gfc_default_real_kind,
3063 					&a->where);
3064   mpfr_set_si (inline_limit->value.real, limit, GFC_RND_MODE);
3065   mpfr_pow_ui (inline_limit->value.real, inline_limit->value.real, 3,
3066 	       GFC_RND_MODE);
3067 
3068   a1 = get_array_inq_function (GFC_ISYM_SIZE, a, 1);
3069   a2 = get_array_inq_function (GFC_ISYM_SIZE, a, 2);
3070   b2 = get_array_inq_function (GFC_ISYM_SIZE, b, 2);
3071 
3072   gfc_clear_ts (&ts);
3073   ts.type = BT_REAL;
3074   ts.kind = gfc_default_real_kind;
3075   gfc_convert_type_warn (a1, &ts, 2, 0);
3076   gfc_convert_type_warn (a2, &ts, 2, 0);
3077   gfc_convert_type_warn (b2, &ts, 2, 0);
3078 
3079   m1 = get_operand (INTRINSIC_TIMES, a1, a2);
3080   m2 = get_operand (INTRINSIC_TIMES, m1, b2);
3081 
3082   cond = build_logical_expr (INTRINSIC_LE, m2, inline_limit);
3083   gfc_simplify_expr (cond, 0);
3084 
3085   else_2 = XCNEW (gfc_code);
3086   else_2->op = EXEC_IF;
3087   else_2->loc = a->where;
3088 
3089   if_2 = XCNEW (gfc_code);
3090   if_2->op = EXEC_IF;
3091   if_2->expr1 = cond;
3092   if_2->loc = a->where;
3093   if_2->block = else_2;
3094 
3095   if_1 = XCNEW (gfc_code);
3096   if_1->op = EXEC_IF;
3097   if_1->block = if_2;
3098   if_1->loc = a->where;
3099 
3100   return if_1;
3101 }
3102 
3103 
3104 /* Insert code to issue a runtime error if the expressions are not equal.  */
3105 
3106 static gfc_code *
runtime_error_ne(gfc_expr * e1,gfc_expr * e2,const char * msg)3107 runtime_error_ne (gfc_expr *e1, gfc_expr *e2, const char *msg)
3108 {
3109   gfc_expr *cond;
3110   gfc_code *if_1, *if_2;
3111   gfc_code *c;
3112   gfc_actual_arglist *a1, *a2, *a3;
3113 
3114   gcc_assert (e1->where.lb);
3115   /* Build the call to runtime_error.  */
3116   c = XCNEW (gfc_code);
3117   c->op = EXEC_CALL;
3118   c->loc = e1->where;
3119 
3120   /* Get a null-terminated message string.  */
3121 
3122   a1 = gfc_get_actual_arglist ();
3123   a1->expr = gfc_get_character_expr (gfc_default_character_kind, &e1->where,
3124 				     msg, strlen(msg)+1);
3125   c->ext.actual = a1;
3126 
3127   /* Pass the value of the first expression.  */
3128   a2 = gfc_get_actual_arglist ();
3129   a2->expr = gfc_copy_expr (e1);
3130   a1->next = a2;
3131 
3132   /* Pass the value of the second expression.  */
3133   a3 = gfc_get_actual_arglist ();
3134   a3->expr = gfc_copy_expr (e2);
3135   a2->next = a3;
3136 
3137   gfc_check_fe_runtime_error (c->ext.actual);
3138   gfc_resolve_fe_runtime_error (c);
3139 
3140   if_2 = XCNEW (gfc_code);
3141   if_2->op = EXEC_IF;
3142   if_2->loc = e1->where;
3143   if_2->next = c;
3144 
3145   if_1 = XCNEW (gfc_code);
3146   if_1->op = EXEC_IF;
3147   if_1->block = if_2;
3148   if_1->loc = e1->where;
3149 
3150   cond = build_logical_expr (INTRINSIC_NE, e1, e2);
3151   gfc_simplify_expr (cond, 0);
3152   if_2->expr1 = cond;
3153 
3154   return if_1;
3155 }
3156 
3157 /* Handle matrix reallocation.  Caller is responsible to insert into
3158    the code tree.
3159 
3160    For the two-dimensional case, build
3161 
3162   if (allocated(c)) then
3163      if (size(c,1) /= size(a,1) .or. size(c,2) /= size(b,2)) then
3164         deallocate(c)
3165         allocate (c(size(a,1), size(b,2)))
3166      end if
3167   else
3168      allocate (c(size(a,1),size(b,2)))
3169   end if
3170 
3171   and for the other cases correspondingly.
3172 */
3173 
3174 static gfc_code *
matmul_lhs_realloc(gfc_expr * c,gfc_expr * a,gfc_expr * b,enum matrix_case m_case)3175 matmul_lhs_realloc (gfc_expr *c, gfc_expr *a, gfc_expr *b,
3176 		    enum matrix_case m_case)
3177 {
3178 
3179   gfc_expr *allocated, *alloc_expr;
3180   gfc_code *if_alloc_1, *if_alloc_2, *if_size_1, *if_size_2;
3181   gfc_code *else_alloc;
3182   gfc_code *deallocate, *allocate1, *allocate_else;
3183   gfc_array_ref *ar;
3184   gfc_expr *cond, *ne1, *ne2;
3185 
3186   if (warn_realloc_lhs)
3187     gfc_warning (OPT_Wrealloc_lhs,
3188 		 "Code for reallocating the allocatable array at %L will "
3189 		 "be added", &c->where);
3190 
3191   alloc_expr = gfc_copy_expr (c);
3192 
3193   ar = gfc_find_array_ref (alloc_expr);
3194   gcc_assert (ar && ar->type == AR_FULL);
3195 
3196   /* c comes in as a full ref.  Change it into a copy and make it into an
3197      element ref so it has the right form for ALLOCATE.  In the same
3198      switch statement, also generate the size comparison for the secod IF
3199      statement.  */
3200 
3201   ar->type = AR_ELEMENT;
3202 
3203   switch (m_case)
3204     {
3205     case A2B2:
3206       ar->start[0] = get_array_inq_function (GFC_ISYM_SIZE, a, 1);
3207       ar->start[1] = get_array_inq_function (GFC_ISYM_SIZE, b, 2);
3208       ne1 = build_logical_expr (INTRINSIC_NE,
3209 				get_array_inq_function (GFC_ISYM_SIZE, c, 1),
3210 				get_array_inq_function (GFC_ISYM_SIZE, a, 1));
3211       ne2 = build_logical_expr (INTRINSIC_NE,
3212 				get_array_inq_function (GFC_ISYM_SIZE, c, 2),
3213 				get_array_inq_function (GFC_ISYM_SIZE, b, 2));
3214       cond = build_logical_expr (INTRINSIC_OR, ne1, ne2);
3215       break;
3216 
3217     case A2B2T:
3218       ar->start[0] = get_array_inq_function (GFC_ISYM_SIZE, a, 1);
3219       ar->start[1] = get_array_inq_function (GFC_ISYM_SIZE, b, 1);
3220 
3221       ne1 = build_logical_expr (INTRINSIC_NE,
3222 				get_array_inq_function (GFC_ISYM_SIZE, c, 1),
3223 				get_array_inq_function (GFC_ISYM_SIZE, a, 1));
3224       ne2 = build_logical_expr (INTRINSIC_NE,
3225 				get_array_inq_function (GFC_ISYM_SIZE, c, 2),
3226 				get_array_inq_function (GFC_ISYM_SIZE, b, 1));
3227       cond = build_logical_expr (INTRINSIC_OR, ne1, ne2);
3228       break;
3229 
3230     case A2TB2:
3231 
3232       ar->start[0] = get_array_inq_function (GFC_ISYM_SIZE, a, 2);
3233       ar->start[1] = get_array_inq_function (GFC_ISYM_SIZE, b, 2);
3234 
3235       ne1 = build_logical_expr (INTRINSIC_NE,
3236 				get_array_inq_function (GFC_ISYM_SIZE, c, 1),
3237 				get_array_inq_function (GFC_ISYM_SIZE, a, 2));
3238       ne2 = build_logical_expr (INTRINSIC_NE,
3239 				get_array_inq_function (GFC_ISYM_SIZE, c, 2),
3240 				get_array_inq_function (GFC_ISYM_SIZE, b, 2));
3241       cond = build_logical_expr (INTRINSIC_OR, ne1, ne2);
3242       break;
3243 
3244     case A2B1:
3245       ar->start[0] = get_array_inq_function (GFC_ISYM_SIZE, a, 1);
3246       cond = build_logical_expr (INTRINSIC_NE,
3247 				 get_array_inq_function (GFC_ISYM_SIZE, c, 1),
3248 				 get_array_inq_function (GFC_ISYM_SIZE, a, 2));
3249       break;
3250 
3251     case A1B2:
3252       ar->start[0] = get_array_inq_function (GFC_ISYM_SIZE, b, 2);
3253       cond = build_logical_expr (INTRINSIC_NE,
3254 				 get_array_inq_function (GFC_ISYM_SIZE, c, 1),
3255 				 get_array_inq_function (GFC_ISYM_SIZE, b, 2));
3256       break;
3257 
3258     case A2TB2T:
3259       /* This can only happen for BLAS, we do not handle that case in
3260 	 inline mamtul.  */
3261       ar->start[0] = get_array_inq_function (GFC_ISYM_SIZE, a, 2);
3262       ar->start[1] = get_array_inq_function (GFC_ISYM_SIZE, b, 1);
3263 
3264       ne1 = build_logical_expr (INTRINSIC_NE,
3265 				get_array_inq_function (GFC_ISYM_SIZE, c, 1),
3266 				get_array_inq_function (GFC_ISYM_SIZE, a, 2));
3267       ne2 = build_logical_expr (INTRINSIC_NE,
3268 				get_array_inq_function (GFC_ISYM_SIZE, c, 2),
3269 				get_array_inq_function (GFC_ISYM_SIZE, b, 1));
3270 
3271       cond = build_logical_expr (INTRINSIC_OR, ne1, ne2);
3272       break;
3273 
3274     default:
3275       gcc_unreachable();
3276 
3277     }
3278 
3279   gfc_simplify_expr (cond, 0);
3280 
3281   /* We need two identical allocate statements in two
3282      branches of the IF statement.  */
3283 
3284   allocate1 = XCNEW (gfc_code);
3285   allocate1->op = EXEC_ALLOCATE;
3286   allocate1->ext.alloc.list = gfc_get_alloc ();
3287   allocate1->loc = c->where;
3288   allocate1->ext.alloc.list->expr = gfc_copy_expr (alloc_expr);
3289 
3290   allocate_else = XCNEW (gfc_code);
3291   allocate_else->op = EXEC_ALLOCATE;
3292   allocate_else->ext.alloc.list = gfc_get_alloc ();
3293   allocate_else->loc = c->where;
3294   allocate_else->ext.alloc.list->expr = alloc_expr;
3295 
3296   allocated = gfc_build_intrinsic_call (current_ns, GFC_ISYM_ALLOCATED,
3297 					"_gfortran_allocated", c->where,
3298 					1, gfc_copy_expr (c));
3299 
3300   deallocate = XCNEW (gfc_code);
3301   deallocate->op = EXEC_DEALLOCATE;
3302   deallocate->ext.alloc.list = gfc_get_alloc ();
3303   deallocate->ext.alloc.list->expr = gfc_copy_expr (c);
3304   deallocate->next = allocate1;
3305   deallocate->loc = c->where;
3306 
3307   if_size_2 = XCNEW (gfc_code);
3308   if_size_2->op = EXEC_IF;
3309   if_size_2->expr1 = cond;
3310   if_size_2->loc = c->where;
3311   if_size_2->next = deallocate;
3312 
3313   if_size_1 = XCNEW (gfc_code);
3314   if_size_1->op = EXEC_IF;
3315   if_size_1->block = if_size_2;
3316   if_size_1->loc = c->where;
3317 
3318   else_alloc = XCNEW (gfc_code);
3319   else_alloc->op = EXEC_IF;
3320   else_alloc->loc = c->where;
3321   else_alloc->next = allocate_else;
3322 
3323   if_alloc_2 = XCNEW (gfc_code);
3324   if_alloc_2->op = EXEC_IF;
3325   if_alloc_2->expr1 = allocated;
3326   if_alloc_2->loc = c->where;
3327   if_alloc_2->next = if_size_1;
3328   if_alloc_2->block = else_alloc;
3329 
3330   if_alloc_1 = XCNEW (gfc_code);
3331   if_alloc_1->op = EXEC_IF;
3332   if_alloc_1->block = if_alloc_2;
3333   if_alloc_1->loc = c->where;
3334 
3335   return if_alloc_1;
3336 }
3337 
3338 /* Callback function for has_function_or_op.  */
3339 
3340 static int
is_function_or_op(gfc_expr ** e,int * walk_subtrees ATTRIBUTE_UNUSED,void * data ATTRIBUTE_UNUSED)3341 is_function_or_op (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
3342 	     void *data ATTRIBUTE_UNUSED)
3343 {
3344   if ((*e) == 0)
3345     return 0;
3346   else
3347     return (*e)->expr_type == EXPR_FUNCTION
3348       || (*e)->expr_type == EXPR_OP;
3349 }
3350 
3351 /* Returns true if the expression contains a function.  */
3352 
3353 static bool
has_function_or_op(gfc_expr ** e)3354 has_function_or_op (gfc_expr **e)
3355 {
3356   if (e == NULL)
3357     return false;
3358   else
3359     return gfc_expr_walker (e, is_function_or_op, NULL);
3360 }
3361 
3362 /* Freeze (assign to a temporary variable) a single expression.  */
3363 
3364 static void
freeze_expr(gfc_expr ** ep)3365 freeze_expr (gfc_expr **ep)
3366 {
3367   gfc_expr *ne;
3368   if (has_function_or_op (ep))
3369     {
3370       ne = create_var (*ep, "freeze");
3371       *ep = ne;
3372     }
3373 }
3374 
3375 /* Go through an expression's references and assign them to temporary
3376    variables if they contain functions.  This is usually done prior to
3377    front-end scalarization to avoid multiple invocations of functions.  */
3378 
3379 static void
freeze_references(gfc_expr * e)3380 freeze_references (gfc_expr *e)
3381 {
3382   gfc_ref *r;
3383   gfc_array_ref *ar;
3384   int i;
3385 
3386   for (r=e->ref; r; r=r->next)
3387     {
3388       if (r->type == REF_SUBSTRING)
3389 	{
3390 	  if (r->u.ss.start != NULL)
3391 	    freeze_expr (&r->u.ss.start);
3392 
3393 	  if (r->u.ss.end != NULL)
3394 	    freeze_expr (&r->u.ss.end);
3395 	}
3396       else if (r->type == REF_ARRAY)
3397 	{
3398 	  ar = &r->u.ar;
3399 	  switch (ar->type)
3400 	    {
3401 	    case AR_FULL:
3402 	      break;
3403 
3404 	    case AR_SECTION:
3405 	      for (i=0; i<ar->dimen; i++)
3406 		{
3407 		  if (ar->dimen_type[i] == DIMEN_RANGE)
3408 		    {
3409 		      freeze_expr (&ar->start[i]);
3410 		      freeze_expr (&ar->end[i]);
3411 		      freeze_expr (&ar->stride[i]);
3412 		    }
3413 		  else if (ar->dimen_type[i] == DIMEN_ELEMENT)
3414 		    {
3415 		      freeze_expr (&ar->start[i]);
3416 		    }
3417 		}
3418 	      break;
3419 
3420 	    case AR_ELEMENT:
3421 	      for (i=0; i<ar->dimen; i++)
3422 		freeze_expr (&ar->start[i]);
3423 	      break;
3424 
3425 	    default:
3426 	      break;
3427 	    }
3428 	}
3429     }
3430 }
3431 
3432 /* Convert to gfc_index_integer_kind if needed, just do a copy otherwise.  */
3433 
3434 static gfc_expr *
convert_to_index_kind(gfc_expr * e)3435 convert_to_index_kind (gfc_expr *e)
3436 {
3437   gfc_expr *res;
3438 
3439   gcc_assert (e != NULL);
3440 
3441   res = gfc_copy_expr (e);
3442 
3443   gcc_assert (e->ts.type == BT_INTEGER);
3444 
3445   if (res->ts.kind != gfc_index_integer_kind)
3446     {
3447       gfc_typespec ts;
3448       gfc_clear_ts (&ts);
3449       ts.type = BT_INTEGER;
3450       ts.kind = gfc_index_integer_kind;
3451 
3452       gfc_convert_type_warn (e, &ts, 2, 0);
3453     }
3454 
3455   return res;
3456 }
3457 
3458 /* Function to create a DO loop including creation of the
3459    iteration variable.  gfc_expr are copied.*/
3460 
3461 static gfc_code *
create_do_loop(gfc_expr * start,gfc_expr * end,gfc_expr * step,locus * where,gfc_namespace * ns,char * vname)3462 create_do_loop (gfc_expr *start, gfc_expr *end, gfc_expr *step, locus *where,
3463 		gfc_namespace *ns, char *vname)
3464 {
3465 
3466   char name[GFC_MAX_SYMBOL_LEN +1];
3467   gfc_symtree *symtree;
3468   gfc_symbol *symbol;
3469   gfc_expr *i;
3470   gfc_code *n, *n2;
3471 
3472   /* Create an expression for the iteration variable.  */
3473   if (vname)
3474     sprintf (name, "__var_%d_do_%s", var_num++, vname);
3475   else
3476     sprintf (name, "__var_%d_do", var_num++);
3477 
3478 
3479   if (gfc_get_sym_tree (name, ns, &symtree, false) != 0)
3480     gcc_unreachable ();
3481 
3482   /* Create the loop variable.  */
3483 
3484   symbol = symtree->n.sym;
3485   symbol->ts.type = BT_INTEGER;
3486   symbol->ts.kind = gfc_index_integer_kind;
3487   symbol->attr.flavor = FL_VARIABLE;
3488   symbol->attr.referenced = 1;
3489   symbol->attr.dimension = 0;
3490   symbol->attr.fe_temp = 1;
3491   gfc_commit_symbol (symbol);
3492 
3493   i = gfc_get_expr ();
3494   i->expr_type = EXPR_VARIABLE;
3495   i->ts = symbol->ts;
3496   i->rank = 0;
3497   i->where = *where;
3498   i->symtree = symtree;
3499 
3500   /* ... and the nested DO statements.  */
3501   n = XCNEW (gfc_code);
3502   n->op = EXEC_DO;
3503   n->loc = *where;
3504   n->ext.iterator = gfc_get_iterator ();
3505   n->ext.iterator->var = i;
3506   n->ext.iterator->start = convert_to_index_kind (start);
3507   n->ext.iterator->end = convert_to_index_kind (end);
3508   if (step)
3509     n->ext.iterator->step = convert_to_index_kind (step);
3510   else
3511     n->ext.iterator->step = gfc_get_int_expr (gfc_index_integer_kind,
3512 					      where, 1);
3513 
3514   n2 = XCNEW (gfc_code);
3515   n2->op = EXEC_DO;
3516   n2->loc = *where;
3517   n2->next = NULL;
3518   n->block = n2;
3519   return n;
3520 }
3521 
3522 /* Get the upper bound of the DO loops for matmul along a dimension.  This
3523  is one-based.  */
3524 
3525 static gfc_expr*
get_size_m1(gfc_expr * e,int dimen)3526 get_size_m1 (gfc_expr *e, int dimen)
3527 {
3528   mpz_t size;
3529   gfc_expr *res;
3530 
3531   if (gfc_array_dimen_size (e, dimen - 1, &size))
3532     {
3533       res = gfc_get_constant_expr (BT_INTEGER,
3534 				   gfc_index_integer_kind, &e->where);
3535       mpz_sub_ui (res->value.integer, size, 1);
3536       mpz_clear (size);
3537     }
3538   else
3539     {
3540       res = get_operand (INTRINSIC_MINUS,
3541 			 get_array_inq_function (GFC_ISYM_SIZE, e, dimen),
3542 			 gfc_get_int_expr (gfc_index_integer_kind,
3543 					   &e->where, 1));
3544       gfc_simplify_expr (res, 0);
3545     }
3546 
3547   return res;
3548 }
3549 
3550 /* Function to return a scalarized expression. It is assumed that indices are
3551  zero based to make generation of DO loops easier.  A zero as index will
3552  access the first element along a dimension.  Single element references will
3553  be skipped.  A NULL as an expression will be replaced by a full reference.
3554  This assumes that the index loops have gfc_index_integer_kind, and that all
3555  references have been frozen.  */
3556 
3557 static gfc_expr*
scalarized_expr(gfc_expr * e_in,gfc_expr ** index,int count_index)3558 scalarized_expr (gfc_expr *e_in, gfc_expr **index, int count_index)
3559 {
3560   gfc_array_ref *ar;
3561   int i;
3562   int rank;
3563   gfc_expr *e;
3564   int i_index;
3565   bool was_fullref;
3566 
3567   e = gfc_copy_expr(e_in);
3568 
3569   rank = e->rank;
3570 
3571   ar = gfc_find_array_ref (e);
3572 
3573   /* We scalarize count_index variables, reducing the rank by count_index.  */
3574 
3575   e->rank = rank - count_index;
3576 
3577   was_fullref = ar->type == AR_FULL;
3578 
3579   if (e->rank == 0)
3580     ar->type = AR_ELEMENT;
3581   else
3582     ar->type = AR_SECTION;
3583 
3584   /* Loop over the indices.  For each index, create the expression
3585      index * stride + lbound(e, dim).  */
3586 
3587   i_index = 0;
3588   for (i=0; i < ar->dimen; i++)
3589     {
3590       if (was_fullref || ar->dimen_type[i] == DIMEN_RANGE)
3591 	{
3592 	  if (index[i_index] != NULL)
3593 	    {
3594 	      gfc_expr *lbound, *nindex;
3595 	      gfc_expr *loopvar;
3596 
3597 	      loopvar = gfc_copy_expr (index[i_index]);
3598 
3599 	      if (ar->stride[i])
3600 		{
3601 		  gfc_expr *tmp;
3602 
3603 		  tmp = gfc_copy_expr(ar->stride[i]);
3604 		  if (tmp->ts.kind != gfc_index_integer_kind)
3605 		    {
3606 		      gfc_typespec ts;
3607 		      gfc_clear_ts (&ts);
3608 		      ts.type = BT_INTEGER;
3609 		      ts.kind = gfc_index_integer_kind;
3610 		      gfc_convert_type (tmp, &ts, 2);
3611 		    }
3612 		  nindex = get_operand (INTRINSIC_TIMES, loopvar, tmp);
3613 		}
3614 	      else
3615 		nindex = loopvar;
3616 
3617 	      /* Calculate the lower bound of the expression.  */
3618 	      if (ar->start[i])
3619 		{
3620 		  lbound = gfc_copy_expr (ar->start[i]);
3621 		  if (lbound->ts.kind != gfc_index_integer_kind)
3622 		    {
3623 		      gfc_typespec ts;
3624 		      gfc_clear_ts (&ts);
3625 		      ts.type = BT_INTEGER;
3626 		      ts.kind = gfc_index_integer_kind;
3627 		      gfc_convert_type (lbound, &ts, 2);
3628 
3629 		    }
3630 		}
3631 	      else
3632 		{
3633 		  gfc_expr *lbound_e;
3634 		  gfc_ref *ref;
3635 
3636 		  lbound_e = gfc_copy_expr (e_in);
3637 
3638 		  for (ref = lbound_e->ref; ref; ref = ref->next)
3639 		    if (ref->type == REF_ARRAY
3640 			&& (ref->u.ar.type == AR_FULL
3641 			    || ref->u.ar.type == AR_SECTION))
3642 		      break;
3643 
3644 		  if (ref->next)
3645 		    {
3646 		      gfc_free_ref_list (ref->next);
3647 		      ref->next = NULL;
3648 		    }
3649 
3650 		  if (!was_fullref)
3651 		    {
3652 		      /* Look at full individual sections, like a(:).  The first index
3653 			 is the lbound of a full ref.  */
3654 		      int j;
3655 		      gfc_array_ref *ar;
3656 		      int to;
3657 
3658 		      ar = &ref->u.ar;
3659 
3660 		      /* For assumed size, we need to keep around the final
3661 			 reference in order not to get an error on resolution
3662 			 below, and we cannot use AR_FULL.  */
3663 
3664 		      if (ar->as->type == AS_ASSUMED_SIZE)
3665 			{
3666 			  ar->type = AR_SECTION;
3667 			  to = ar->dimen - 1;
3668 			}
3669 		      else
3670 			{
3671 			  to = ar->dimen;
3672 			  ar->type = AR_FULL;
3673 			}
3674 
3675 		      for (j = 0; j < to; j++)
3676 			{
3677 			  gfc_free_expr (ar->start[j]);
3678 			  ar->start[j] = NULL;
3679 			  gfc_free_expr (ar->end[j]);
3680 			  ar->end[j] = NULL;
3681 			  gfc_free_expr (ar->stride[j]);
3682 			  ar->stride[j] = NULL;
3683 			}
3684 
3685 		      /* We have to get rid of the shape, if there is one.  Do
3686 			 so by freeing it and calling gfc_resolve to rebuild
3687 			 it, if necessary.  */
3688 
3689 		      if (lbound_e->shape)
3690 			gfc_free_shape (&(lbound_e->shape), lbound_e->rank);
3691 
3692 		      lbound_e->rank = ar->dimen;
3693 		      gfc_resolve_expr (lbound_e);
3694 		    }
3695 		  lbound = get_array_inq_function (GFC_ISYM_LBOUND, lbound_e,
3696 						   i + 1);
3697 		  gfc_free_expr (lbound_e);
3698 		}
3699 
3700 	      ar->dimen_type[i] = DIMEN_ELEMENT;
3701 
3702 	      gfc_free_expr (ar->start[i]);
3703 	      ar->start[i] = get_operand (INTRINSIC_PLUS, nindex, lbound);
3704 
3705 	      gfc_free_expr (ar->end[i]);
3706 	      ar->end[i] = NULL;
3707 	      gfc_free_expr (ar->stride[i]);
3708 	      ar->stride[i] = NULL;
3709 	      gfc_simplify_expr (ar->start[i], 0);
3710 	    }
3711 	  else if (was_fullref)
3712 	    {
3713 	      gfc_internal_error ("Scalarization using DIMEN_RANGE unimplemented");
3714 	    }
3715 	  i_index ++;
3716 	}
3717     }
3718 
3719   /* Bounds checking will be done before the loops if -fcheck=bounds
3720      is in effect. */
3721   e->no_bounds_check = 1;
3722   return e;
3723 }
3724 
3725 /* Helper function to check for a dimen vector as subscript.  */
3726 
3727 bool
gfc_has_dimen_vector_ref(gfc_expr * e)3728 gfc_has_dimen_vector_ref (gfc_expr *e)
3729 {
3730   gfc_array_ref *ar;
3731   int i;
3732 
3733   ar = gfc_find_array_ref (e);
3734   gcc_assert (ar);
3735   if (ar->type == AR_FULL)
3736     return false;
3737 
3738   for (i=0; i<ar->dimen; i++)
3739     if (ar->dimen_type[i] == DIMEN_VECTOR)
3740       return true;
3741 
3742   return false;
3743 }
3744 
3745 /* If handed an expression of the form
3746 
3747    TRANSPOSE(CONJG(A))
3748 
3749    check if A can be handled by matmul and return if there is an uneven number
3750    of CONJG calls.  Return a pointer to the array when everything is OK, NULL
3751    otherwise. The caller has to check for the correct rank.  */
3752 
3753 static gfc_expr*
check_conjg_transpose_variable(gfc_expr * e,bool * conjg,bool * transpose)3754 check_conjg_transpose_variable (gfc_expr *e, bool *conjg, bool *transpose)
3755 {
3756   *conjg = false;
3757   *transpose = false;
3758 
3759   do
3760     {
3761       if (e->expr_type == EXPR_VARIABLE)
3762 	{
3763 	  gcc_assert (e->rank == 1 || e->rank == 2);
3764 	  return e;
3765 	}
3766       else if (e->expr_type == EXPR_FUNCTION)
3767 	{
3768 	  if (e->value.function.isym == NULL)
3769 	    return NULL;
3770 
3771 	  if (e->value.function.isym->id == GFC_ISYM_CONJG)
3772 	    *conjg = !*conjg;
3773 	  else if (e->value.function.isym->id == GFC_ISYM_TRANSPOSE)
3774 	    *transpose = !*transpose;
3775 	  else return NULL;
3776 	}
3777       else
3778 	return NULL;
3779 
3780       e = e->value.function.actual->expr;
3781     }
3782   while(1);
3783 
3784   return NULL;
3785 }
3786 
3787 /* Macros for unified error messages.  */
3788 
3789 #define B_ERROR_1 _("Incorrect extent in argument B in MATMUL intrinsic in " \
3790 		     "dimension 1: is %ld, should be %ld")
3791 
3792 #define C_ERROR_1 _("Array bound mismatch for dimension 1 of array " \
3793 		    "(%ld/%ld)")
3794 
3795 #define C_ERROR_2 _("Array bound mismatch for dimension 2 of array " \
3796 		    "(%ld/%ld)")
3797 
3798 
3799 /* Inline assignments of the form c = matmul(a,b).
3800    Handle only the cases currently where b and c are rank-two arrays.
3801 
3802    This basically translates the code to
3803 
3804    BLOCK
3805      integer i,j,k
3806      c = 0
3807      do j=0, size(b,2)-1
3808        do k=0, size(a, 2)-1
3809          do i=0, size(a, 1)-1
3810             c(i * stride(c,1) + lbound(c,1), j * stride(c,2) + lbound(c,2)) =
3811 	    c(i * stride(c,1) + lbound(c,1), j * stride(c,2) + lbound(c,2)) +
3812             a(i * stride(a,1) + lbound(a,1), k * stride(a,2) + lbound(a,2)) *
3813             b(k * stride(b,1) + lbound(b,1), j * stride(b,2) + lbound(b,2))
3814          end do
3815        end do
3816      end do
3817    END BLOCK
3818 
3819 */
3820 
3821 static int
inline_matmul_assign(gfc_code ** c,int * walk_subtrees,void * data ATTRIBUTE_UNUSED)3822 inline_matmul_assign (gfc_code **c, int *walk_subtrees,
3823 			  void *data ATTRIBUTE_UNUSED)
3824 {
3825   gfc_code *co = *c;
3826   gfc_expr *expr1, *expr2;
3827   gfc_expr *matrix_a, *matrix_b;
3828   gfc_actual_arglist *a, *b;
3829   gfc_code *do_1, *do_2, *do_3, *assign_zero, *assign_matmul;
3830   gfc_expr *zero_e;
3831   gfc_expr *u1, *u2, *u3;
3832   gfc_expr *list[2];
3833   gfc_expr *ascalar, *bscalar, *cscalar;
3834   gfc_expr *mult;
3835   gfc_expr *var_1, *var_2, *var_3;
3836   gfc_expr *zero;
3837   gfc_namespace *ns;
3838   gfc_intrinsic_op op_times, op_plus;
3839   enum matrix_case m_case;
3840   int i;
3841   gfc_code *if_limit = NULL;
3842   gfc_code **next_code_point;
3843   bool conjg_a, conjg_b, transpose_a, transpose_b;
3844   bool realloc_c;
3845 
3846   if (co->op != EXEC_ASSIGN)
3847     return 0;
3848 
3849   if (in_where || in_assoc_list)
3850     return 0;
3851 
3852   /* The BLOCKS generated for the temporary variables and FORALL don't
3853      mix.  */
3854   if (forall_level > 0)
3855     return 0;
3856 
3857   /* For now don't do anything in OpenMP workshare, it confuses
3858      its translation, which expects only the allowed statements in there.
3859      We should figure out how to parallelize this eventually.  */
3860   if (in_omp_workshare || in_omp_atomic)
3861     return 0;
3862 
3863   expr1 = co->expr1;
3864   expr2 = co->expr2;
3865   if (expr2->expr_type != EXPR_FUNCTION
3866       || expr2->value.function.isym == NULL
3867       || expr2->value.function.isym->id != GFC_ISYM_MATMUL)
3868     return 0;
3869 
3870   current_code = c;
3871   inserted_block = NULL;
3872   changed_statement = NULL;
3873 
3874   a = expr2->value.function.actual;
3875   matrix_a = check_conjg_transpose_variable (a->expr, &conjg_a, &transpose_a);
3876   if (matrix_a == NULL)
3877     return 0;
3878 
3879   b = a->next;
3880   matrix_b = check_conjg_transpose_variable (b->expr, &conjg_b, &transpose_b);
3881   if (matrix_b == NULL)
3882     return 0;
3883 
3884   if (gfc_has_dimen_vector_ref (expr1) || gfc_has_dimen_vector_ref (matrix_a)
3885       || gfc_has_dimen_vector_ref (matrix_b))
3886     return 0;
3887 
3888   /* We do not handle data dependencies yet.  */
3889   if (gfc_check_dependency (expr1, matrix_a, true)
3890       || gfc_check_dependency (expr1, matrix_b, true))
3891     return 0;
3892 
3893   m_case = none;
3894   if (matrix_a->rank == 2)
3895     {
3896       if (transpose_a)
3897 	{
3898 	  if (matrix_b->rank == 2 && !transpose_b)
3899 	    m_case = A2TB2;
3900 	}
3901       else
3902 	{
3903 	  if (matrix_b->rank == 1)
3904 	    m_case = A2B1;
3905 	  else /* matrix_b->rank == 2 */
3906 	    {
3907 	      if (transpose_b)
3908 		m_case = A2B2T;
3909 	      else
3910 		m_case = A2B2;
3911 	    }
3912 	}
3913     }
3914   else /* matrix_a->rank == 1 */
3915     {
3916       if (matrix_b->rank == 2)
3917 	{
3918 	  if (!transpose_b)
3919 	    m_case = A1B2;
3920 	}
3921     }
3922 
3923   if (m_case == none)
3924     return 0;
3925 
3926   /* We only handle assignment to numeric or logical variables.  */
3927   switch(expr1->ts.type)
3928     {
3929     case BT_INTEGER:
3930     case BT_LOGICAL:
3931     case BT_REAL:
3932     case BT_COMPLEX:
3933       break;
3934 
3935     default:
3936       return 0;
3937     }
3938 
3939   ns = insert_block ();
3940 
3941   /* Assign the type of the zero expression for initializing the resulting
3942      array, and the expression (+ and * for real, integer and complex;
3943      .and. and .or for logical.  */
3944 
3945   switch(expr1->ts.type)
3946     {
3947     case BT_INTEGER:
3948       zero_e = gfc_get_int_expr (expr1->ts.kind, &expr1->where, 0);
3949       op_times = INTRINSIC_TIMES;
3950       op_plus = INTRINSIC_PLUS;
3951       break;
3952 
3953     case BT_LOGICAL:
3954       op_times = INTRINSIC_AND;
3955       op_plus = INTRINSIC_OR;
3956       zero_e = gfc_get_logical_expr (expr1->ts.kind, &expr1->where,
3957 				     0);
3958       break;
3959     case BT_REAL:
3960       zero_e = gfc_get_constant_expr (BT_REAL, expr1->ts.kind,
3961 				      &expr1->where);
3962       mpfr_set_si (zero_e->value.real, 0, GFC_RND_MODE);
3963       op_times = INTRINSIC_TIMES;
3964       op_plus = INTRINSIC_PLUS;
3965       break;
3966 
3967     case BT_COMPLEX:
3968       zero_e = gfc_get_constant_expr (BT_COMPLEX, expr1->ts.kind,
3969 				      &expr1->where);
3970       mpc_set_si_si (zero_e->value.complex, 0, 0, GFC_RND_MODE);
3971       op_times = INTRINSIC_TIMES;
3972       op_plus = INTRINSIC_PLUS;
3973 
3974       break;
3975 
3976     default:
3977       gcc_unreachable();
3978     }
3979 
3980   current_code = &ns->code;
3981 
3982   /* Freeze the references, keeping track of how many temporary variables were
3983      created.  */
3984   n_vars = 0;
3985   freeze_references (matrix_a);
3986   freeze_references (matrix_b);
3987   freeze_references (expr1);
3988 
3989   if (n_vars == 0)
3990     next_code_point = current_code;
3991   else
3992     {
3993       next_code_point = &ns->code;
3994       for (i=0; i<n_vars; i++)
3995 	next_code_point = &(*next_code_point)->next;
3996     }
3997 
3998   /* Take care of the inline flag.  If the limit check evaluates to a
3999      constant, dead code elimination will eliminate the unneeded branch.  */
4000 
4001   if (flag_inline_matmul_limit > 0 && matrix_a->rank == 2
4002       && matrix_b->rank == 2)
4003     {
4004       if_limit = inline_limit_check (matrix_a, matrix_b,
4005 				     flag_inline_matmul_limit);
4006 
4007       /* Insert the original statement into the else branch.  */
4008       if_limit->block->block->next = co;
4009       co->next = NULL;
4010 
4011       /* ... and the new ones go into the original one.  */
4012       *next_code_point = if_limit;
4013       next_code_point = &if_limit->block->next;
4014     }
4015 
4016   zero_e->no_bounds_check = 1;
4017 
4018   assign_zero = XCNEW (gfc_code);
4019   assign_zero->op = EXEC_ASSIGN;
4020   assign_zero->loc = co->loc;
4021   assign_zero->expr1 = gfc_copy_expr (expr1);
4022   assign_zero->expr1->no_bounds_check = 1;
4023   assign_zero->expr2 = zero_e;
4024 
4025   realloc_c = flag_realloc_lhs && gfc_is_reallocatable_lhs (expr1);
4026 
4027   if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
4028     {
4029       gfc_code *test;
4030       gfc_expr *a2, *b1, *c1, *c2, *a1, *b2;
4031 
4032       switch (m_case)
4033 	{
4034 	case A2B1:
4035 
4036 	  b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1);
4037 	  a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2);
4038 	  test = runtime_error_ne (b1, a2, B_ERROR_1);
4039 	  *next_code_point = test;
4040 	  next_code_point = &test->next;
4041 
4042 	  if (!realloc_c)
4043 	    {
4044 	      c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1);
4045 	      a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1);
4046 	      test = runtime_error_ne (c1, a1, C_ERROR_1);
4047 	      *next_code_point = test;
4048 	      next_code_point = &test->next;
4049 	    }
4050 	  break;
4051 
4052 	case A1B2:
4053 
4054 	  b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1);
4055 	  a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1);
4056 	  test = runtime_error_ne (b1, a1, B_ERROR_1);
4057 	  *next_code_point = test;
4058 	  next_code_point = &test->next;
4059 
4060 	  if (!realloc_c)
4061 	    {
4062 	      c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1);
4063 	      b2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 2);
4064 	      test = runtime_error_ne (c1, b2, C_ERROR_1);
4065 	      *next_code_point = test;
4066 	      next_code_point = &test->next;
4067 	    }
4068 	  break;
4069 
4070 	case A2B2:
4071 
4072 	  b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1);
4073 	  a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2);
4074 	  test = runtime_error_ne (b1, a2, B_ERROR_1);
4075 	  *next_code_point = test;
4076 	  next_code_point = &test->next;
4077 
4078 	  if (!realloc_c)
4079 	    {
4080 	      c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1);
4081 	      a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1);
4082 	      test = runtime_error_ne (c1, a1, C_ERROR_1);
4083 	      *next_code_point = test;
4084 	      next_code_point = &test->next;
4085 
4086 	      c2 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 2);
4087 	      b2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 2);
4088 	      test = runtime_error_ne (c2, b2, C_ERROR_2);
4089 	      *next_code_point = test;
4090 	      next_code_point = &test->next;
4091 	    }
4092 	  break;
4093 
4094 	case A2B2T:
4095 
4096 	  b2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 2);
4097 	  a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2);
4098 	  /* matrix_b is transposed, hence dimension 1 for the error message.  */
4099 	  test = runtime_error_ne (b2, a2, B_ERROR_1);
4100 	  *next_code_point = test;
4101 	  next_code_point = &test->next;
4102 
4103 	  if (!realloc_c)
4104 	    {
4105 	      c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1);
4106 	      a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1);
4107 	      test = runtime_error_ne (c1, a1, C_ERROR_1);
4108 	      *next_code_point = test;
4109 	      next_code_point = &test->next;
4110 
4111 	      c2 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 2);
4112 	      b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1);
4113 	      test = runtime_error_ne (c2, b1, C_ERROR_2);
4114 	      *next_code_point = test;
4115 	      next_code_point = &test->next;
4116 	    }
4117 	  break;
4118 
4119 	case A2TB2:
4120 
4121 	  b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1);
4122 	  a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1);
4123 	  test = runtime_error_ne (b1, a1, B_ERROR_1);
4124 	  *next_code_point = test;
4125 	  next_code_point = &test->next;
4126 
4127 	  if (!realloc_c)
4128 	    {
4129 	      c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1);
4130 	      a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2);
4131 	      test = runtime_error_ne (c1, a2, C_ERROR_1);
4132 	      *next_code_point = test;
4133 	      next_code_point = &test->next;
4134 
4135 	      c2 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 2);
4136 	      b2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 2);
4137 	      test = runtime_error_ne (c2, b2, C_ERROR_2);
4138 	      *next_code_point = test;
4139 	      next_code_point = &test->next;
4140 	    }
4141 	  break;
4142 
4143 	default:
4144 	  gcc_unreachable ();
4145 	}
4146     }
4147 
4148   /* Handle the reallocation, if needed.  */
4149 
4150   if (realloc_c)
4151     {
4152       gfc_code *lhs_alloc;
4153 
4154       lhs_alloc = matmul_lhs_realloc (expr1, matrix_a, matrix_b, m_case);
4155 
4156       *next_code_point = lhs_alloc;
4157       next_code_point = &lhs_alloc->next;
4158 
4159     }
4160 
4161   *next_code_point = assign_zero;
4162 
4163   zero = gfc_get_int_expr (gfc_index_integer_kind, &co->loc, 0);
4164 
4165   assign_matmul = XCNEW (gfc_code);
4166   assign_matmul->op = EXEC_ASSIGN;
4167   assign_matmul->loc = co->loc;
4168 
4169   /* Get the bounds for the loops, create them and create the scalarized
4170      expressions.  */
4171 
4172   switch (m_case)
4173     {
4174     case A2B2:
4175 
4176       u1 = get_size_m1 (matrix_b, 2);
4177       u2 = get_size_m1 (matrix_a, 2);
4178       u3 = get_size_m1 (matrix_a, 1);
4179 
4180       do_1 = create_do_loop (gfc_copy_expr (zero), u1, NULL, &co->loc, ns);
4181       do_2 = create_do_loop (gfc_copy_expr (zero), u2, NULL, &co->loc, ns);
4182       do_3 = create_do_loop (gfc_copy_expr (zero), u3, NULL, &co->loc, ns);
4183 
4184       do_1->block->next = do_2;
4185       do_2->block->next = do_3;
4186       do_3->block->next = assign_matmul;
4187 
4188       var_1 = do_1->ext.iterator->var;
4189       var_2 = do_2->ext.iterator->var;
4190       var_3 = do_3->ext.iterator->var;
4191 
4192       list[0] = var_3;
4193       list[1] = var_1;
4194       cscalar = scalarized_expr (co->expr1, list, 2);
4195 
4196       list[0] = var_3;
4197       list[1] = var_2;
4198       ascalar = scalarized_expr (matrix_a, list, 2);
4199 
4200       list[0] = var_2;
4201       list[1] = var_1;
4202       bscalar = scalarized_expr (matrix_b, list, 2);
4203 
4204       break;
4205 
4206     case A2B2T:
4207 
4208       u1 = get_size_m1 (matrix_b, 1);
4209       u2 = get_size_m1 (matrix_a, 2);
4210       u3 = get_size_m1 (matrix_a, 1);
4211 
4212       do_1 = create_do_loop (gfc_copy_expr (zero), u1, NULL, &co->loc, ns);
4213       do_2 = create_do_loop (gfc_copy_expr (zero), u2, NULL, &co->loc, ns);
4214       do_3 = create_do_loop (gfc_copy_expr (zero), u3, NULL, &co->loc, ns);
4215 
4216       do_1->block->next = do_2;
4217       do_2->block->next = do_3;
4218       do_3->block->next = assign_matmul;
4219 
4220       var_1 = do_1->ext.iterator->var;
4221       var_2 = do_2->ext.iterator->var;
4222       var_3 = do_3->ext.iterator->var;
4223 
4224       list[0] = var_3;
4225       list[1] = var_1;
4226       cscalar = scalarized_expr (co->expr1, list, 2);
4227 
4228       list[0] = var_3;
4229       list[1] = var_2;
4230       ascalar = scalarized_expr (matrix_a, list, 2);
4231 
4232       list[0] = var_1;
4233       list[1] = var_2;
4234       bscalar = scalarized_expr (matrix_b, list, 2);
4235 
4236       break;
4237 
4238     case A2TB2:
4239 
4240       u1 = get_size_m1 (matrix_a, 2);
4241       u2 = get_size_m1 (matrix_b, 2);
4242       u3 = get_size_m1 (matrix_a, 1);
4243 
4244       do_1 = create_do_loop (gfc_copy_expr (zero), u1, NULL, &co->loc, ns);
4245       do_2 = create_do_loop (gfc_copy_expr (zero), u2, NULL, &co->loc, ns);
4246       do_3 = create_do_loop (gfc_copy_expr (zero), u3, NULL, &co->loc, ns);
4247 
4248       do_1->block->next = do_2;
4249       do_2->block->next = do_3;
4250       do_3->block->next = assign_matmul;
4251 
4252       var_1 = do_1->ext.iterator->var;
4253       var_2 = do_2->ext.iterator->var;
4254       var_3 = do_3->ext.iterator->var;
4255 
4256       list[0] = var_1;
4257       list[1] = var_2;
4258       cscalar = scalarized_expr (co->expr1, list, 2);
4259 
4260       list[0] = var_3;
4261       list[1] = var_1;
4262       ascalar = scalarized_expr (matrix_a, list, 2);
4263 
4264       list[0] = var_3;
4265       list[1] = var_2;
4266       bscalar = scalarized_expr (matrix_b, list, 2);
4267 
4268       break;
4269 
4270     case A2B1:
4271       u1 = get_size_m1 (matrix_b, 1);
4272       u2 = get_size_m1 (matrix_a, 1);
4273 
4274       do_1 = create_do_loop (gfc_copy_expr (zero), u1, NULL, &co->loc, ns);
4275       do_2 = create_do_loop (gfc_copy_expr (zero), u2, NULL, &co->loc, ns);
4276 
4277       do_1->block->next = do_2;
4278       do_2->block->next = assign_matmul;
4279 
4280       var_1 = do_1->ext.iterator->var;
4281       var_2 = do_2->ext.iterator->var;
4282 
4283       list[0] = var_2;
4284       cscalar = scalarized_expr (co->expr1, list, 1);
4285 
4286       list[0] = var_2;
4287       list[1] = var_1;
4288       ascalar = scalarized_expr (matrix_a, list, 2);
4289 
4290       list[0] = var_1;
4291       bscalar = scalarized_expr (matrix_b, list, 1);
4292 
4293       break;
4294 
4295     case A1B2:
4296       u1 = get_size_m1 (matrix_b, 2);
4297       u2 = get_size_m1 (matrix_a, 1);
4298 
4299       do_1 = create_do_loop (gfc_copy_expr (zero), u1, NULL, &co->loc, ns);
4300       do_2 = create_do_loop (gfc_copy_expr (zero), u2, NULL, &co->loc, ns);
4301 
4302       do_1->block->next = do_2;
4303       do_2->block->next = assign_matmul;
4304 
4305       var_1 = do_1->ext.iterator->var;
4306       var_2 = do_2->ext.iterator->var;
4307 
4308       list[0] = var_1;
4309       cscalar = scalarized_expr (co->expr1, list, 1);
4310 
4311       list[0] = var_2;
4312       ascalar = scalarized_expr (matrix_a, list, 1);
4313 
4314       list[0] = var_2;
4315       list[1] = var_1;
4316       bscalar = scalarized_expr (matrix_b, list, 2);
4317 
4318       break;
4319 
4320     default:
4321       gcc_unreachable();
4322     }
4323 
4324   /* Build the conjg call around the variables.  Set the typespec manually
4325      because gfc_build_intrinsic_call sometimes gets this wrong.  */
4326   if (conjg_a)
4327     {
4328       gfc_typespec ts;
4329       ts = matrix_a->ts;
4330       ascalar = gfc_build_intrinsic_call (ns, GFC_ISYM_CONJG, "conjg",
4331 					  matrix_a->where, 1, ascalar);
4332       ascalar->ts = ts;
4333     }
4334 
4335   if (conjg_b)
4336     {
4337       gfc_typespec ts;
4338       ts = matrix_b->ts;
4339       bscalar = gfc_build_intrinsic_call (ns, GFC_ISYM_CONJG, "conjg",
4340 					  matrix_b->where, 1, bscalar);
4341       bscalar->ts = ts;
4342     }
4343   /* First loop comes after the zero assignment.  */
4344   assign_zero->next = do_1;
4345 
4346   /* Build the assignment expression in the loop.  */
4347   assign_matmul->expr1 = gfc_copy_expr (cscalar);
4348 
4349   mult = get_operand (op_times, ascalar, bscalar);
4350   assign_matmul->expr2 = get_operand (op_plus, cscalar, mult);
4351 
4352   /* If we don't want to keep the original statement around in
4353      the else branch, we can free it.  */
4354 
4355   if (if_limit == NULL)
4356     gfc_free_statements(co);
4357   else
4358     co->next = NULL;
4359 
4360   gfc_free_expr (zero);
4361   *walk_subtrees = 0;
4362   return 0;
4363 }
4364 
4365 /* Change matmul function calls in the form of
4366 
4367    c = matmul(a,b)
4368 
4369    to the corresponding call to a BLAS routine, if applicable.  */
4370 
4371 static int
call_external_blas(gfc_code ** c,int * walk_subtrees ATTRIBUTE_UNUSED,void * data ATTRIBUTE_UNUSED)4372 call_external_blas (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
4373 		    void *data ATTRIBUTE_UNUSED)
4374 {
4375   gfc_code *co, *co_next;
4376   gfc_expr *expr1, *expr2;
4377   gfc_expr *matrix_a, *matrix_b;
4378   gfc_code *if_limit = NULL;
4379   gfc_actual_arglist *a, *b;
4380   bool conjg_a, conjg_b, transpose_a, transpose_b;
4381   gfc_code *call;
4382   const char *blas_name;
4383   const char *transa, *transb;
4384   gfc_expr *c1, *c2, *b1;
4385   gfc_actual_arglist *actual, *next;
4386   bt type;
4387   int kind;
4388   enum matrix_case m_case;
4389   bool realloc_c;
4390   gfc_code **next_code_point;
4391 
4392   /* Many of the tests for inline matmul also apply here.  */
4393 
4394   co = *c;
4395 
4396   if (co->op != EXEC_ASSIGN)
4397     return 0;
4398 
4399   if (in_where || in_assoc_list)
4400     return 0;
4401 
4402   /* The BLOCKS generated for the temporary variables and FORALL don't
4403      mix.  */
4404   if (forall_level > 0)
4405     return 0;
4406 
4407   /* For now don't do anything in OpenMP workshare, it confuses
4408      its translation, which expects only the allowed statements in there. */
4409 
4410   if (in_omp_workshare || in_omp_atomic)
4411     return 0;
4412 
4413   expr1 = co->expr1;
4414   expr2 = co->expr2;
4415   if (expr2->expr_type != EXPR_FUNCTION
4416       || expr2->value.function.isym == NULL
4417       || expr2->value.function.isym->id != GFC_ISYM_MATMUL)
4418     return 0;
4419 
4420   type = expr2->ts.type;
4421   kind = expr2->ts.kind;
4422 
4423   /* Guard against recursion. */
4424 
4425   if (expr2->external_blas)
4426     return 0;
4427 
4428   if (type != expr1->ts.type || kind != expr1->ts.kind)
4429     return 0;
4430 
4431   if (type == BT_REAL)
4432     {
4433       if (kind == 4)
4434 	blas_name = "sgemm";
4435       else if (kind == 8)
4436 	blas_name = "dgemm";
4437       else
4438 	return 0;
4439     }
4440   else if (type == BT_COMPLEX)
4441     {
4442       if (kind == 4)
4443 	blas_name = "cgemm";
4444       else if (kind == 8)
4445 	blas_name = "zgemm";
4446       else
4447 	return 0;
4448     }
4449   else
4450     return 0;
4451 
4452   a = expr2->value.function.actual;
4453   if (a->expr->rank != 2)
4454     return 0;
4455 
4456   b = a->next;
4457   if (b->expr->rank != 2)
4458     return 0;
4459 
4460   matrix_a = check_conjg_transpose_variable (a->expr, &conjg_a, &transpose_a);
4461   if (matrix_a == NULL)
4462     return 0;
4463 
4464   if (transpose_a)
4465     {
4466       if (conjg_a)
4467 	transa = "C";
4468       else
4469 	transa = "T";
4470     }
4471   else
4472     transa = "N";
4473 
4474   matrix_b = check_conjg_transpose_variable (b->expr, &conjg_b, &transpose_b);
4475   if (matrix_b == NULL)
4476     return 0;
4477 
4478   if (transpose_b)
4479     {
4480       if (conjg_b)
4481 	transb = "C";
4482       else
4483 	transb = "T";
4484     }
4485   else
4486     transb = "N";
4487 
4488   if (transpose_a)
4489     {
4490       if (transpose_b)
4491 	m_case = A2TB2T;
4492       else
4493 	m_case = A2TB2;
4494     }
4495   else
4496     {
4497       if (transpose_b)
4498 	m_case = A2B2T;
4499       else
4500 	m_case = A2B2;
4501     }
4502 
4503   current_code = c;
4504   inserted_block = NULL;
4505   changed_statement = NULL;
4506 
4507   expr2->external_blas = 1;
4508 
4509   /* We do not handle data dependencies yet.  */
4510   if (gfc_check_dependency (expr1, matrix_a, true)
4511       || gfc_check_dependency (expr1, matrix_b, true))
4512     return 0;
4513 
4514   /* Generate the if statement and hang it into the tree.  */
4515   if_limit = inline_limit_check (matrix_a, matrix_b, flag_blas_matmul_limit);
4516   co_next = co->next;
4517   (*current_code) = if_limit;
4518   co->next = NULL;
4519   if_limit->block->next = co;
4520 
4521   call = XCNEW (gfc_code);
4522   call->loc = co->loc;
4523 
4524   /* Bounds checking - a bit simpler than for inlining since we only
4525      have to take care of two-dimensional arrays here.  */
4526 
4527   realloc_c = flag_realloc_lhs && gfc_is_reallocatable_lhs (expr1);
4528   next_code_point = &(if_limit->block->block->next);
4529 
4530   if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
4531     {
4532       gfc_code *test;
4533       //      gfc_expr *a2, *b1, *c1, *c2, *a1, *b2;
4534       gfc_expr *c1, *a1, *c2, *b2, *a2;
4535       switch (m_case)
4536 	{
4537 	case A2B2:
4538 	  b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1);
4539 	  a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2);
4540 	  test = runtime_error_ne (b1, a2, B_ERROR_1);
4541 	  *next_code_point = test;
4542 	  next_code_point = &test->next;
4543 
4544 	  if (!realloc_c)
4545 	    {
4546 	      c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1);
4547 	      a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1);
4548 	      test = runtime_error_ne (c1, a1, C_ERROR_1);
4549 	      *next_code_point = test;
4550 	      next_code_point = &test->next;
4551 
4552 	      c2 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 2);
4553 	      b2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 2);
4554 	      test = runtime_error_ne (c2, b2, C_ERROR_2);
4555 	      *next_code_point = test;
4556 	      next_code_point = &test->next;
4557 	    }
4558 	  break;
4559 
4560 	case A2B2T:
4561 
4562 	  b2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 2);
4563 	  a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2);
4564 	  /* matrix_b is transposed, hence dimension 1 for the error message.  */
4565 	  test = runtime_error_ne (b2, a2, B_ERROR_1);
4566 	  *next_code_point = test;
4567 	  next_code_point = &test->next;
4568 
4569 	  if (!realloc_c)
4570 	    {
4571 	      c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1);
4572 	      a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1);
4573 	      test = runtime_error_ne (c1, a1, C_ERROR_1);
4574 	      *next_code_point = test;
4575 	      next_code_point = &test->next;
4576 
4577 	      c2 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 2);
4578 	      b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1);
4579 	      test = runtime_error_ne (c2, b1, C_ERROR_2);
4580 	      *next_code_point = test;
4581 	      next_code_point = &test->next;
4582 	    }
4583 	  break;
4584 
4585 	case A2TB2:
4586 
4587 	  b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1);
4588 	  a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1);
4589 	  test = runtime_error_ne (b1, a1, B_ERROR_1);
4590 	  *next_code_point = test;
4591 	  next_code_point = &test->next;
4592 
4593 	  if (!realloc_c)
4594 	    {
4595 	      c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1);
4596 	      a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2);
4597 	      test = runtime_error_ne (c1, a2, C_ERROR_1);
4598 	      *next_code_point = test;
4599 	      next_code_point = &test->next;
4600 
4601 	      c2 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 2);
4602 	      b2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 2);
4603 	      test = runtime_error_ne (c2, b2, C_ERROR_2);
4604 	      *next_code_point = test;
4605 	      next_code_point = &test->next;
4606 	    }
4607 	  break;
4608 
4609 	case A2TB2T:
4610 	  b2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 2);
4611 	  a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1);
4612 	  test = runtime_error_ne (b2, a1, B_ERROR_1);
4613 	  *next_code_point = test;
4614 	  next_code_point = &test->next;
4615 
4616 	  if (!realloc_c)
4617 	    {
4618 	      c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1);
4619 	      a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2);
4620 	      test = runtime_error_ne (c1, a2, C_ERROR_1);
4621 	      *next_code_point = test;
4622 	      next_code_point = &test->next;
4623 
4624 	      c2 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 2);
4625 	      b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1);
4626 	      test = runtime_error_ne (c2, b1, C_ERROR_2);
4627 	      *next_code_point = test;
4628 	      next_code_point = &test->next;
4629 	    }
4630 	  break;
4631 
4632 	default:
4633 	  gcc_unreachable ();
4634 	}
4635     }
4636 
4637   /* Handle the reallocation, if needed.  */
4638 
4639   if (realloc_c)
4640     {
4641       gfc_code *lhs_alloc;
4642 
4643       lhs_alloc = matmul_lhs_realloc (expr1, matrix_a, matrix_b, m_case);
4644       *next_code_point = lhs_alloc;
4645       next_code_point = &lhs_alloc->next;
4646     }
4647 
4648   *next_code_point = call;
4649   if_limit->next = co_next;
4650 
4651   /* Set up the BLAS call.  */
4652 
4653   call->op = EXEC_CALL;
4654 
4655   gfc_get_sym_tree (blas_name, current_ns, &(call->symtree), true);
4656   call->symtree->n.sym->attr.subroutine = 1;
4657   call->symtree->n.sym->attr.procedure = 1;
4658   call->symtree->n.sym->attr.flavor = FL_PROCEDURE;
4659   call->resolved_sym = call->symtree->n.sym;
4660   gfc_commit_symbol (call->resolved_sym);
4661 
4662   /* Argument TRANSA.  */
4663   next = gfc_get_actual_arglist ();
4664   next->expr = gfc_get_character_expr (gfc_default_character_kind, &co->loc,
4665 				       transa, 1);
4666 
4667   call->ext.actual = next;
4668 
4669   /* Argument TRANSB.  */
4670   actual = next;
4671   next = gfc_get_actual_arglist ();
4672   next->expr = gfc_get_character_expr (gfc_default_character_kind, &co->loc,
4673 				       transb, 1);
4674   actual->next = next;
4675 
4676   c1 = get_array_inq_function (GFC_ISYM_SIZE, gfc_copy_expr (a->expr), 1,
4677 			       gfc_integer_4_kind);
4678   c2 = get_array_inq_function (GFC_ISYM_SIZE, gfc_copy_expr (b->expr), 2,
4679 			       gfc_integer_4_kind);
4680 
4681   b1 = get_array_inq_function (GFC_ISYM_SIZE, gfc_copy_expr (b->expr), 1,
4682 			       gfc_integer_4_kind);
4683 
4684   /* Argument M. */
4685   actual = next;
4686   next = gfc_get_actual_arglist ();
4687   next->expr = c1;
4688   actual->next = next;
4689 
4690   /* Argument N. */
4691   actual = next;
4692   next = gfc_get_actual_arglist ();
4693   next->expr = c2;
4694   actual->next = next;
4695 
4696   /* Argument K.  */
4697   actual = next;
4698   next = gfc_get_actual_arglist ();
4699   next->expr = b1;
4700   actual->next = next;
4701 
4702   /* Argument ALPHA - set to one.  */
4703   actual = next;
4704   next = gfc_get_actual_arglist ();
4705   next->expr = gfc_get_constant_expr (type, kind, &co->loc);
4706   if (type == BT_REAL)
4707     mpfr_set_ui (next->expr->value.real, 1, GFC_RND_MODE);
4708   else
4709     mpc_set_ui (next->expr->value.complex, 1, GFC_MPC_RND_MODE);
4710   actual->next = next;
4711 
4712   /* Argument A.  */
4713   actual = next;
4714   next = gfc_get_actual_arglist ();
4715   next->expr = gfc_copy_expr (matrix_a);
4716   actual->next = next;
4717 
4718   /* Argument LDA.  */
4719   actual = next;
4720   next = gfc_get_actual_arglist ();
4721   next->expr = get_array_inq_function (GFC_ISYM_SIZE, gfc_copy_expr (matrix_a),
4722 				       1, gfc_integer_4_kind);
4723   actual->next = next;
4724 
4725   /* Argument B.  */
4726   actual = next;
4727   next = gfc_get_actual_arglist ();
4728   next->expr = gfc_copy_expr (matrix_b);
4729   actual->next = next;
4730 
4731   /* Argument LDB.  */
4732   actual = next;
4733   next = gfc_get_actual_arglist ();
4734   next->expr = get_array_inq_function (GFC_ISYM_SIZE, gfc_copy_expr (matrix_b),
4735 				       1, gfc_integer_4_kind);
4736   actual->next = next;
4737 
4738   /* Argument BETA - set to zero.  */
4739   actual = next;
4740   next = gfc_get_actual_arglist ();
4741   next->expr = gfc_get_constant_expr (type, kind, &co->loc);
4742   if (type == BT_REAL)
4743     mpfr_set_ui (next->expr->value.real, 0, GFC_RND_MODE);
4744   else
4745     mpc_set_ui (next->expr->value.complex, 0, GFC_MPC_RND_MODE);
4746   actual->next = next;
4747 
4748   /* Argument C.  */
4749 
4750   actual = next;
4751   next = gfc_get_actual_arglist ();
4752   next->expr = gfc_copy_expr (expr1);
4753   actual->next = next;
4754 
4755   /* Argument LDC.  */
4756   actual = next;
4757   next = gfc_get_actual_arglist ();
4758   next->expr = get_array_inq_function (GFC_ISYM_SIZE, gfc_copy_expr (expr1),
4759 				       1, gfc_integer_4_kind);
4760   actual->next = next;
4761 
4762   return 0;
4763 }
4764 
4765 
4766 /* Code for index interchange for loops which are grouped together in DO
4767    CONCURRENT or FORALL statements.  This is currently only applied if the
4768    iterations are grouped together in a single statement.
4769 
4770    For this transformation, it is assumed that memory access in strides is
4771    expensive, and that loops which access later indices (which access memory
4772    in bigger strides) should be moved to the first loops.
4773 
4774    For this, a loop over all the statements is executed, counting the times
4775    that the loop iteration values are accessed in each index.  The loop
4776    indices are then sorted to minimize access to later indices from inner
4777    loops.  */
4778 
4779 /* Type for holding index information.  */
4780 
4781 typedef struct {
4782   gfc_symbol *sym;
4783   gfc_forall_iterator *fa;
4784   int num;
4785   int n[GFC_MAX_DIMENSIONS];
4786 } ind_type;
4787 
4788 /* Callback function to determine if an expression is the
4789    corresponding variable.  */
4790 
4791 static int
has_var(gfc_expr ** e,int * walk_subtrees ATTRIBUTE_UNUSED,void * data)4792 has_var (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED, void *data)
4793 {
4794   gfc_expr *expr = *e;
4795   gfc_symbol *sym;
4796 
4797   if (expr->expr_type != EXPR_VARIABLE)
4798     return 0;
4799 
4800   sym = (gfc_symbol *) data;
4801   return sym == expr->symtree->n.sym;
4802 }
4803 
4804 /* Callback function to calculate the cost of a certain index.  */
4805 
4806 static int
index_cost(gfc_expr ** e,int * walk_subtrees ATTRIBUTE_UNUSED,void * data)4807 index_cost (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
4808 	    void *data)
4809 {
4810   ind_type *ind;
4811   gfc_expr *expr;
4812   gfc_array_ref *ar;
4813   gfc_ref *ref;
4814   int i,j;
4815 
4816   expr = *e;
4817   if (expr->expr_type != EXPR_VARIABLE)
4818     return 0;
4819 
4820   ar = NULL;
4821   for (ref = expr->ref; ref; ref = ref->next)
4822     {
4823       if (ref->type == REF_ARRAY)
4824 	{
4825 	  ar = &ref->u.ar;
4826 	  break;
4827 	}
4828     }
4829   if (ar == NULL || ar->type != AR_ELEMENT)
4830     return 0;
4831 
4832   ind = (ind_type *) data;
4833   for (i = 0; i < ar->dimen; i++)
4834     {
4835       for (j=0; ind[j].sym != NULL; j++)
4836 	{
4837 	  if (gfc_expr_walker (&ar->start[i], has_var, (void *) (ind[j].sym)))
4838 	      ind[j].n[i]++;
4839 	}
4840     }
4841   return 0;
4842 }
4843 
4844 /* Callback function for qsort, to sort the loop indices. */
4845 
4846 static int
loop_comp(const void * e1,const void * e2)4847 loop_comp (const void *e1, const void *e2)
4848 {
4849   const ind_type *i1 = (const ind_type *) e1;
4850   const ind_type *i2 = (const ind_type *) e2;
4851   int i;
4852 
4853   for (i=GFC_MAX_DIMENSIONS-1; i >= 0; i--)
4854     {
4855       if (i1->n[i] != i2->n[i])
4856 	return i1->n[i] - i2->n[i];
4857     }
4858   /* All other things being equal, let's not change the ordering.  */
4859   return i2->num - i1->num;
4860 }
4861 
4862 /* Main function to do the index interchange.  */
4863 
4864 static int
index_interchange(gfc_code ** c,int * walk_subtrees ATTRIBUTE_UNUSED,void * data ATTRIBUTE_UNUSED)4865 index_interchange (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
4866 		  void *data ATTRIBUTE_UNUSED)
4867 {
4868   gfc_code *co;
4869   co = *c;
4870   int n_iter;
4871   gfc_forall_iterator *fa;
4872   ind_type *ind;
4873   int i, j;
4874 
4875   if (co->op != EXEC_FORALL && co->op != EXEC_DO_CONCURRENT)
4876     return 0;
4877 
4878   n_iter = 0;
4879   for (fa = co->ext.forall_iterator; fa; fa = fa->next)
4880     n_iter ++;
4881 
4882   /* Nothing to reorder. */
4883   if (n_iter < 2)
4884     return 0;
4885 
4886   ind = XALLOCAVEC (ind_type, n_iter + 1);
4887 
4888   i = 0;
4889   for (fa = co->ext.forall_iterator; fa; fa = fa->next)
4890     {
4891       ind[i].sym = fa->var->symtree->n.sym;
4892       ind[i].fa = fa;
4893       for (j=0; j<GFC_MAX_DIMENSIONS; j++)
4894 	ind[i].n[j] = 0;
4895       ind[i].num = i;
4896       i++;
4897     }
4898   ind[n_iter].sym = NULL;
4899   ind[n_iter].fa = NULL;
4900 
4901   gfc_code_walker (c, gfc_dummy_code_callback, index_cost, (void *) ind);
4902   qsort ((void *) ind, n_iter, sizeof (ind_type), loop_comp);
4903 
4904   /* Do the actual index interchange.  */
4905   co->ext.forall_iterator = fa = ind[0].fa;
4906   for (i=1; i<n_iter; i++)
4907     {
4908       fa->next = ind[i].fa;
4909       fa = fa->next;
4910     }
4911   fa->next = NULL;
4912 
4913   if (flag_warn_frontend_loop_interchange)
4914     {
4915       for (i=1; i<n_iter; i++)
4916 	{
4917 	  if (ind[i-1].num > ind[i].num)
4918 	    {
4919 	      gfc_warning (OPT_Wfrontend_loop_interchange,
4920 			   "Interchanging loops at %L", &co->loc);
4921 	      break;
4922 	    }
4923 	}
4924     }
4925 
4926   return 0;
4927 }
4928 
4929 #define WALK_SUBEXPR(NODE) \
4930   do							\
4931     {							\
4932       result = gfc_expr_walker (&(NODE), exprfn, data);	\
4933       if (result)					\
4934 	return result;					\
4935     }							\
4936   while (0)
4937 #define WALK_SUBEXPR_TAIL(NODE) e = &(NODE); continue
4938 
4939 /* Walk expression *E, calling EXPRFN on each expression in it.  */
4940 
4941 int
gfc_expr_walker(gfc_expr ** e,walk_expr_fn_t exprfn,void * data)4942 gfc_expr_walker (gfc_expr **e, walk_expr_fn_t exprfn, void *data)
4943 {
4944   while (*e)
4945     {
4946       int walk_subtrees = 1;
4947       gfc_actual_arglist *a;
4948       gfc_ref *r;
4949       gfc_constructor *c;
4950 
4951       int result = exprfn (e, &walk_subtrees, data);
4952       if (result)
4953 	return result;
4954       if (walk_subtrees)
4955 	switch ((*e)->expr_type)
4956 	  {
4957 	  case EXPR_OP:
4958 	    WALK_SUBEXPR ((*e)->value.op.op1);
4959 	    WALK_SUBEXPR_TAIL ((*e)->value.op.op2);
4960 	    break;
4961 	  case EXPR_FUNCTION:
4962 	    for (a = (*e)->value.function.actual; a; a = a->next)
4963 	      WALK_SUBEXPR (a->expr);
4964 	    break;
4965 	  case EXPR_COMPCALL:
4966 	  case EXPR_PPC:
4967 	    WALK_SUBEXPR ((*e)->value.compcall.base_object);
4968 	    for (a = (*e)->value.compcall.actual; a; a = a->next)
4969 	      WALK_SUBEXPR (a->expr);
4970 	    break;
4971 
4972 	  case EXPR_STRUCTURE:
4973 	  case EXPR_ARRAY:
4974 	    for (c = gfc_constructor_first ((*e)->value.constructor); c;
4975 		 c = gfc_constructor_next (c))
4976 	      {
4977 		if (c->iterator == NULL)
4978 		  WALK_SUBEXPR (c->expr);
4979 		else
4980 		  {
4981 		    iterator_level ++;
4982 		    WALK_SUBEXPR (c->expr);
4983 		    iterator_level --;
4984 		    WALK_SUBEXPR (c->iterator->var);
4985 		    WALK_SUBEXPR (c->iterator->start);
4986 		    WALK_SUBEXPR (c->iterator->end);
4987 		    WALK_SUBEXPR (c->iterator->step);
4988 		  }
4989 	      }
4990 
4991 	    if ((*e)->expr_type != EXPR_ARRAY)
4992 	      break;
4993 
4994 	    /* Fall through to the variable case in order to walk the
4995 	       reference.  */
4996 	    gcc_fallthrough ();
4997 
4998 	  case EXPR_SUBSTRING:
4999 	  case EXPR_VARIABLE:
5000 	    for (r = (*e)->ref; r; r = r->next)
5001 	      {
5002 		gfc_array_ref *ar;
5003 		int i;
5004 
5005 		switch (r->type)
5006 		  {
5007 		  case REF_ARRAY:
5008 		    ar = &r->u.ar;
5009 		    if (ar->type == AR_SECTION || ar->type == AR_ELEMENT)
5010 		      {
5011 			for (i=0; i< ar->dimen; i++)
5012 			  {
5013 			    WALK_SUBEXPR (ar->start[i]);
5014 			    WALK_SUBEXPR (ar->end[i]);
5015 			    WALK_SUBEXPR (ar->stride[i]);
5016 			  }
5017 		      }
5018 
5019 		    break;
5020 
5021 		  case REF_SUBSTRING:
5022 		    WALK_SUBEXPR (r->u.ss.start);
5023 		    WALK_SUBEXPR (r->u.ss.end);
5024 		    break;
5025 
5026 		  case REF_COMPONENT:
5027 		  case REF_INQUIRY:
5028 		    break;
5029 		  }
5030 	      }
5031 
5032 	  default:
5033 	    break;
5034 	  }
5035       return 0;
5036     }
5037   return 0;
5038 }
5039 
5040 #define WALK_SUBCODE(NODE) \
5041   do								\
5042     {								\
5043       result = gfc_code_walker (&(NODE), codefn, exprfn, data);	\
5044       if (result)						\
5045 	return result;						\
5046     }								\
5047   while (0)
5048 
5049 /* Walk code *C, calling CODEFN on each gfc_code node in it and calling EXPRFN
5050    on each expression in it.  If any of the hooks returns non-zero, that
5051    value is immediately returned.  If the hook sets *WALK_SUBTREES to 0,
5052    no subcodes or subexpressions are traversed.  */
5053 
5054 int
gfc_code_walker(gfc_code ** c,walk_code_fn_t codefn,walk_expr_fn_t exprfn,void * data)5055 gfc_code_walker (gfc_code **c, walk_code_fn_t codefn, walk_expr_fn_t exprfn,
5056 		 void *data)
5057 {
5058   for (; *c; c = &(*c)->next)
5059     {
5060       int walk_subtrees = 1;
5061       int result = codefn (c, &walk_subtrees, data);
5062       if (result)
5063 	return result;
5064 
5065       if (walk_subtrees)
5066 	{
5067 	  gfc_code *b;
5068 	  gfc_actual_arglist *a;
5069 	  gfc_code *co;
5070 	  gfc_association_list *alist;
5071 	  bool saved_in_omp_workshare;
5072 	  bool saved_in_omp_atomic;
5073 	  bool saved_in_where;
5074 
5075 	  /* There might be statement insertions before the current code,
5076 	     which must not affect the expression walker.  */
5077 
5078 	  co = *c;
5079 	  saved_in_omp_workshare = in_omp_workshare;
5080 	  saved_in_omp_atomic = in_omp_atomic;
5081 	  saved_in_where = in_where;
5082 
5083 	  switch (co->op)
5084 	    {
5085 
5086 	    case EXEC_BLOCK:
5087 	      WALK_SUBCODE (co->ext.block.ns->code);
5088 	      if (co->ext.block.assoc)
5089 		{
5090 		  bool saved_in_assoc_list = in_assoc_list;
5091 
5092 		  in_assoc_list = true;
5093 		  for (alist = co->ext.block.assoc; alist; alist = alist->next)
5094 		    WALK_SUBEXPR (alist->target);
5095 
5096 		  in_assoc_list = saved_in_assoc_list;
5097 		}
5098 
5099 	      break;
5100 
5101 	    case EXEC_DO:
5102 	      doloop_level ++;
5103 	      WALK_SUBEXPR (co->ext.iterator->var);
5104 	      WALK_SUBEXPR (co->ext.iterator->start);
5105 	      WALK_SUBEXPR (co->ext.iterator->end);
5106 	      WALK_SUBEXPR (co->ext.iterator->step);
5107 	      break;
5108 
5109 	    case EXEC_IF:
5110 	      if_level ++;
5111 	      break;
5112 
5113 	    case EXEC_WHERE:
5114 	      in_where = true;
5115 	      break;
5116 
5117 	    case EXEC_CALL:
5118 	    case EXEC_ASSIGN_CALL:
5119 	      for (a = co->ext.actual; a; a = a->next)
5120 		WALK_SUBEXPR (a->expr);
5121 	      break;
5122 
5123 	    case EXEC_CALL_PPC:
5124 	      WALK_SUBEXPR (co->expr1);
5125 	      for (a = co->ext.actual; a; a = a->next)
5126 		WALK_SUBEXPR (a->expr);
5127 	      break;
5128 
5129 	    case EXEC_SELECT:
5130 	      WALK_SUBEXPR (co->expr1);
5131 	      select_level ++;
5132 	      for (b = co->block; b; b = b->block)
5133 		{
5134 		  gfc_case *cp;
5135 		  for (cp = b->ext.block.case_list; cp; cp = cp->next)
5136 		    {
5137 		      WALK_SUBEXPR (cp->low);
5138 		      WALK_SUBEXPR (cp->high);
5139 		    }
5140 		  WALK_SUBCODE (b->next);
5141 		}
5142 	      continue;
5143 
5144 	    case EXEC_ALLOCATE:
5145 	    case EXEC_DEALLOCATE:
5146 	      {
5147 		gfc_alloc *a;
5148 		for (a = co->ext.alloc.list; a; a = a->next)
5149 		  WALK_SUBEXPR (a->expr);
5150 		break;
5151 	      }
5152 
5153 	    case EXEC_FORALL:
5154 	    case EXEC_DO_CONCURRENT:
5155 	      {
5156 		gfc_forall_iterator *fa;
5157 		for (fa = co->ext.forall_iterator; fa; fa = fa->next)
5158 		  {
5159 		    WALK_SUBEXPR (fa->var);
5160 		    WALK_SUBEXPR (fa->start);
5161 		    WALK_SUBEXPR (fa->end);
5162 		    WALK_SUBEXPR (fa->stride);
5163 		  }
5164 		if (co->op == EXEC_FORALL)
5165 		  forall_level ++;
5166 		break;
5167 	      }
5168 
5169 	    case EXEC_OPEN:
5170 	      WALK_SUBEXPR (co->ext.open->unit);
5171 	      WALK_SUBEXPR (co->ext.open->file);
5172 	      WALK_SUBEXPR (co->ext.open->status);
5173 	      WALK_SUBEXPR (co->ext.open->access);
5174 	      WALK_SUBEXPR (co->ext.open->form);
5175 	      WALK_SUBEXPR (co->ext.open->recl);
5176 	      WALK_SUBEXPR (co->ext.open->blank);
5177 	      WALK_SUBEXPR (co->ext.open->position);
5178 	      WALK_SUBEXPR (co->ext.open->action);
5179 	      WALK_SUBEXPR (co->ext.open->delim);
5180 	      WALK_SUBEXPR (co->ext.open->pad);
5181 	      WALK_SUBEXPR (co->ext.open->iostat);
5182 	      WALK_SUBEXPR (co->ext.open->iomsg);
5183 	      WALK_SUBEXPR (co->ext.open->convert);
5184 	      WALK_SUBEXPR (co->ext.open->decimal);
5185 	      WALK_SUBEXPR (co->ext.open->encoding);
5186 	      WALK_SUBEXPR (co->ext.open->round);
5187 	      WALK_SUBEXPR (co->ext.open->sign);
5188 	      WALK_SUBEXPR (co->ext.open->asynchronous);
5189 	      WALK_SUBEXPR (co->ext.open->id);
5190 	      WALK_SUBEXPR (co->ext.open->newunit);
5191 	      WALK_SUBEXPR (co->ext.open->share);
5192 	      WALK_SUBEXPR (co->ext.open->cc);
5193 	      break;
5194 
5195 	    case EXEC_CLOSE:
5196 	      WALK_SUBEXPR (co->ext.close->unit);
5197 	      WALK_SUBEXPR (co->ext.close->status);
5198 	      WALK_SUBEXPR (co->ext.close->iostat);
5199 	      WALK_SUBEXPR (co->ext.close->iomsg);
5200 	      break;
5201 
5202 	    case EXEC_BACKSPACE:
5203 	    case EXEC_ENDFILE:
5204 	    case EXEC_REWIND:
5205 	    case EXEC_FLUSH:
5206 	      WALK_SUBEXPR (co->ext.filepos->unit);
5207 	      WALK_SUBEXPR (co->ext.filepos->iostat);
5208 	      WALK_SUBEXPR (co->ext.filepos->iomsg);
5209 	      break;
5210 
5211 	    case EXEC_INQUIRE:
5212 	      WALK_SUBEXPR (co->ext.inquire->unit);
5213 	      WALK_SUBEXPR (co->ext.inquire->file);
5214 	      WALK_SUBEXPR (co->ext.inquire->iomsg);
5215 	      WALK_SUBEXPR (co->ext.inquire->iostat);
5216 	      WALK_SUBEXPR (co->ext.inquire->exist);
5217 	      WALK_SUBEXPR (co->ext.inquire->opened);
5218 	      WALK_SUBEXPR (co->ext.inquire->number);
5219 	      WALK_SUBEXPR (co->ext.inquire->named);
5220 	      WALK_SUBEXPR (co->ext.inquire->name);
5221 	      WALK_SUBEXPR (co->ext.inquire->access);
5222 	      WALK_SUBEXPR (co->ext.inquire->sequential);
5223 	      WALK_SUBEXPR (co->ext.inquire->direct);
5224 	      WALK_SUBEXPR (co->ext.inquire->form);
5225 	      WALK_SUBEXPR (co->ext.inquire->formatted);
5226 	      WALK_SUBEXPR (co->ext.inquire->unformatted);
5227 	      WALK_SUBEXPR (co->ext.inquire->recl);
5228 	      WALK_SUBEXPR (co->ext.inquire->nextrec);
5229 	      WALK_SUBEXPR (co->ext.inquire->blank);
5230 	      WALK_SUBEXPR (co->ext.inquire->position);
5231 	      WALK_SUBEXPR (co->ext.inquire->action);
5232 	      WALK_SUBEXPR (co->ext.inquire->read);
5233 	      WALK_SUBEXPR (co->ext.inquire->write);
5234 	      WALK_SUBEXPR (co->ext.inquire->readwrite);
5235 	      WALK_SUBEXPR (co->ext.inquire->delim);
5236 	      WALK_SUBEXPR (co->ext.inquire->encoding);
5237 	      WALK_SUBEXPR (co->ext.inquire->pad);
5238 	      WALK_SUBEXPR (co->ext.inquire->iolength);
5239 	      WALK_SUBEXPR (co->ext.inquire->convert);
5240 	      WALK_SUBEXPR (co->ext.inquire->strm_pos);
5241 	      WALK_SUBEXPR (co->ext.inquire->asynchronous);
5242 	      WALK_SUBEXPR (co->ext.inquire->decimal);
5243 	      WALK_SUBEXPR (co->ext.inquire->pending);
5244 	      WALK_SUBEXPR (co->ext.inquire->id);
5245 	      WALK_SUBEXPR (co->ext.inquire->sign);
5246 	      WALK_SUBEXPR (co->ext.inquire->size);
5247 	      WALK_SUBEXPR (co->ext.inquire->round);
5248 	      break;
5249 
5250 	    case EXEC_WAIT:
5251 	      WALK_SUBEXPR (co->ext.wait->unit);
5252 	      WALK_SUBEXPR (co->ext.wait->iostat);
5253 	      WALK_SUBEXPR (co->ext.wait->iomsg);
5254 	      WALK_SUBEXPR (co->ext.wait->id);
5255 	      break;
5256 
5257 	    case EXEC_READ:
5258 	    case EXEC_WRITE:
5259 	      WALK_SUBEXPR (co->ext.dt->io_unit);
5260 	      WALK_SUBEXPR (co->ext.dt->format_expr);
5261 	      WALK_SUBEXPR (co->ext.dt->rec);
5262 	      WALK_SUBEXPR (co->ext.dt->advance);
5263 	      WALK_SUBEXPR (co->ext.dt->iostat);
5264 	      WALK_SUBEXPR (co->ext.dt->size);
5265 	      WALK_SUBEXPR (co->ext.dt->iomsg);
5266 	      WALK_SUBEXPR (co->ext.dt->id);
5267 	      WALK_SUBEXPR (co->ext.dt->pos);
5268 	      WALK_SUBEXPR (co->ext.dt->asynchronous);
5269 	      WALK_SUBEXPR (co->ext.dt->blank);
5270 	      WALK_SUBEXPR (co->ext.dt->decimal);
5271 	      WALK_SUBEXPR (co->ext.dt->delim);
5272 	      WALK_SUBEXPR (co->ext.dt->pad);
5273 	      WALK_SUBEXPR (co->ext.dt->round);
5274 	      WALK_SUBEXPR (co->ext.dt->sign);
5275 	      WALK_SUBEXPR (co->ext.dt->extra_comma);
5276 	      break;
5277 
5278 	    case EXEC_OACC_ATOMIC:
5279 	    case EXEC_OMP_ATOMIC:
5280 	      in_omp_atomic = true;
5281 	      break;
5282 
5283 	    case EXEC_OMP_PARALLEL:
5284 	    case EXEC_OMP_PARALLEL_DO:
5285 	    case EXEC_OMP_PARALLEL_DO_SIMD:
5286 	    case EXEC_OMP_PARALLEL_SECTIONS:
5287 
5288 	      in_omp_workshare = false;
5289 
5290 	      /* This goto serves as a shortcut to avoid code
5291 		 duplication or a larger if or switch statement.  */
5292 	      goto check_omp_clauses;
5293 
5294 	    case EXEC_OMP_WORKSHARE:
5295 	    case EXEC_OMP_PARALLEL_WORKSHARE:
5296 
5297 	      in_omp_workshare = true;
5298 
5299 	      /* Fall through  */
5300 
5301 	    case EXEC_OMP_CRITICAL:
5302 	    case EXEC_OMP_DISTRIBUTE:
5303 	    case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
5304 	    case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
5305 	    case EXEC_OMP_DISTRIBUTE_SIMD:
5306 	    case EXEC_OMP_DO:
5307 	    case EXEC_OMP_DO_SIMD:
5308 	    case EXEC_OMP_ORDERED:
5309 	    case EXEC_OMP_SECTIONS:
5310 	    case EXEC_OMP_SINGLE:
5311 	    case EXEC_OMP_END_SINGLE:
5312 	    case EXEC_OMP_SIMD:
5313 	    case EXEC_OMP_TASKLOOP:
5314 	    case EXEC_OMP_TASKLOOP_SIMD:
5315 	    case EXEC_OMP_TARGET:
5316 	    case EXEC_OMP_TARGET_DATA:
5317 	    case EXEC_OMP_TARGET_ENTER_DATA:
5318 	    case EXEC_OMP_TARGET_EXIT_DATA:
5319 	    case EXEC_OMP_TARGET_PARALLEL:
5320 	    case EXEC_OMP_TARGET_PARALLEL_DO:
5321 	    case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
5322 	    case EXEC_OMP_TARGET_SIMD:
5323 	    case EXEC_OMP_TARGET_TEAMS:
5324 	    case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
5325 	    case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
5326 	    case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
5327 	    case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
5328 	    case EXEC_OMP_TARGET_UPDATE:
5329 	    case EXEC_OMP_TASK:
5330 	    case EXEC_OMP_TEAMS:
5331 	    case EXEC_OMP_TEAMS_DISTRIBUTE:
5332 	    case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
5333 	    case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
5334 	    case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
5335 
5336 	      /* Come to this label only from the
5337 		 EXEC_OMP_PARALLEL_* cases above.  */
5338 
5339 	    check_omp_clauses:
5340 
5341 	      if (co->ext.omp_clauses)
5342 		{
5343 		  gfc_omp_namelist *n;
5344 		  static int list_types[]
5345 		    = { OMP_LIST_ALIGNED, OMP_LIST_LINEAR, OMP_LIST_DEPEND,
5346 			OMP_LIST_MAP, OMP_LIST_TO, OMP_LIST_FROM };
5347 		  size_t idx;
5348 		  WALK_SUBEXPR (co->ext.omp_clauses->if_expr);
5349 		  WALK_SUBEXPR (co->ext.omp_clauses->final_expr);
5350 		  WALK_SUBEXPR (co->ext.omp_clauses->num_threads);
5351 		  WALK_SUBEXPR (co->ext.omp_clauses->chunk_size);
5352 		  WALK_SUBEXPR (co->ext.omp_clauses->safelen_expr);
5353 		  WALK_SUBEXPR (co->ext.omp_clauses->simdlen_expr);
5354 		  WALK_SUBEXPR (co->ext.omp_clauses->num_teams);
5355 		  WALK_SUBEXPR (co->ext.omp_clauses->device);
5356 		  WALK_SUBEXPR (co->ext.omp_clauses->thread_limit);
5357 		  WALK_SUBEXPR (co->ext.omp_clauses->dist_chunk_size);
5358 		  WALK_SUBEXPR (co->ext.omp_clauses->grainsize);
5359 		  WALK_SUBEXPR (co->ext.omp_clauses->hint);
5360 		  WALK_SUBEXPR (co->ext.omp_clauses->num_tasks);
5361 		  WALK_SUBEXPR (co->ext.omp_clauses->priority);
5362 		  for (idx = 0; idx < OMP_IF_LAST; idx++)
5363 		    WALK_SUBEXPR (co->ext.omp_clauses->if_exprs[idx]);
5364 		  for (idx = 0;
5365 		       idx < sizeof (list_types) / sizeof (list_types[0]);
5366 		       idx++)
5367 		    for (n = co->ext.omp_clauses->lists[list_types[idx]];
5368 			 n; n = n->next)
5369 		      WALK_SUBEXPR (n->expr);
5370 		}
5371 	      break;
5372 	    default:
5373 	      break;
5374 	    }
5375 
5376 	  WALK_SUBEXPR (co->expr1);
5377 	  WALK_SUBEXPR (co->expr2);
5378 	  WALK_SUBEXPR (co->expr3);
5379 	  WALK_SUBEXPR (co->expr4);
5380 	  for (b = co->block; b; b = b->block)
5381 	    {
5382 	      WALK_SUBEXPR (b->expr1);
5383 	      WALK_SUBEXPR (b->expr2);
5384 	      WALK_SUBCODE (b->next);
5385 	    }
5386 
5387 	  if (co->op == EXEC_FORALL)
5388 	    forall_level --;
5389 
5390 	  if (co->op == EXEC_DO)
5391 	    doloop_level --;
5392 
5393 	  if (co->op == EXEC_IF)
5394 	    if_level --;
5395 
5396 	  if (co->op == EXEC_SELECT)
5397 	    select_level --;
5398 
5399 	  in_omp_workshare = saved_in_omp_workshare;
5400 	  in_omp_atomic = saved_in_omp_atomic;
5401 	  in_where = saved_in_where;
5402 	}
5403     }
5404   return 0;
5405 }
5406 
5407 /* As a post-resolution step, check that all global symbols which are
5408    not declared in the source file match in their call signatures.
5409    We do this by looping over the code (and expressions). The first call
5410    we happen to find is assumed to be canonical.  */
5411 
5412 
5413 /* Common tests for argument checking for both functions and subroutines.  */
5414 
5415 static int
check_externals_procedure(gfc_symbol * sym,locus * loc,gfc_actual_arglist * actual)5416 check_externals_procedure (gfc_symbol *sym, locus *loc,
5417 			   gfc_actual_arglist *actual)
5418 {
5419   gfc_gsymbol *gsym;
5420   gfc_symbol *def_sym = NULL;
5421 
5422  if (sym == NULL || sym->attr.is_bind_c)
5423     return 0;
5424 
5425   if (sym->attr.proc != PROC_EXTERNAL && sym->attr.proc != PROC_UNKNOWN)
5426     return 0;
5427 
5428   if (sym->attr.if_source == IFSRC_IFBODY || sym->attr.if_source == IFSRC_DECL)
5429     return 0;
5430 
5431   gsym = gfc_find_gsymbol (gfc_gsym_root, sym->name);
5432   if (gsym == NULL)
5433     return 0;
5434 
5435   if (gsym->ns)
5436     gfc_find_symbol (sym->name, gsym->ns, 0, &def_sym);
5437 
5438   if (def_sym)
5439     {
5440       gfc_compare_actual_formal (&actual, def_sym->formal, 0, 0, 0, loc);
5441       return 0;
5442     }
5443 
5444   /* First time we have seen this procedure called. Let's create an
5445      "interface" from the call and put it into a new namespace.  */
5446   gfc_namespace *save_ns;
5447   gfc_symbol *new_sym;
5448 
5449   gsym->where = *loc;
5450   save_ns = gfc_current_ns;
5451   gsym->ns = gfc_get_namespace (gfc_current_ns, 0);
5452   gsym->ns->proc_name = sym;
5453 
5454   gfc_get_symbol (sym->name, gsym->ns, &new_sym);
5455   gcc_assert (new_sym);
5456   new_sym->attr = sym->attr;
5457   new_sym->attr.if_source = IFSRC_DECL;
5458   gfc_current_ns = gsym->ns;
5459 
5460   gfc_get_formal_from_actual_arglist (new_sym, actual);
5461   gfc_current_ns = save_ns;
5462 
5463   return 0;
5464 
5465 }
5466 
5467 /* Callback for calls of external routines.  */
5468 
5469 static int
check_externals_code(gfc_code ** c,int * walk_subtrees ATTRIBUTE_UNUSED,void * data ATTRIBUTE_UNUSED)5470 check_externals_code (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
5471 		      void *data ATTRIBUTE_UNUSED)
5472 {
5473   gfc_code *co = *c;
5474   gfc_symbol *sym;
5475   locus *loc;
5476   gfc_actual_arglist *actual;
5477 
5478   if (co->op != EXEC_CALL)
5479     return 0;
5480 
5481   sym = co->resolved_sym;
5482   loc = &co->loc;
5483   actual = co->ext.actual;
5484 
5485   return check_externals_procedure (sym, loc, actual);
5486 
5487 }
5488 
5489 /* Callback for external functions.  */
5490 
5491 static int
check_externals_expr(gfc_expr ** ep,int * walk_subtrees ATTRIBUTE_UNUSED,void * data ATTRIBUTE_UNUSED)5492 check_externals_expr (gfc_expr **ep, int *walk_subtrees ATTRIBUTE_UNUSED,
5493 		      void *data ATTRIBUTE_UNUSED)
5494 {
5495   gfc_expr *e = *ep;
5496   gfc_symbol *sym;
5497   locus *loc;
5498   gfc_actual_arglist *actual;
5499 
5500   if (e->expr_type != EXPR_FUNCTION)
5501     return 0;
5502 
5503   sym = e->value.function.esym;
5504   if (sym == NULL)
5505     return 0;
5506 
5507   loc = &e->where;
5508   actual = e->value.function.actual;
5509 
5510   return check_externals_procedure (sym, loc, actual);
5511 }
5512 
5513 /* Called routine.  */
5514 
5515 void
gfc_check_externals(gfc_namespace * ns)5516 gfc_check_externals (gfc_namespace *ns)
5517 {
5518 
5519   gfc_clear_error ();
5520 
5521   /* Turn errors into warnings if the user indicated this.  */
5522 
5523   if (!pedantic && flag_allow_argument_mismatch)
5524     gfc_errors_to_warnings (true);
5525 
5526   gfc_code_walker (&ns->code, check_externals_code, check_externals_expr, NULL);
5527 
5528   for (ns = ns->contained; ns; ns = ns->sibling)
5529     {
5530       if (ns->code == NULL || ns->code->op != EXEC_BLOCK)
5531 	gfc_check_externals (ns);
5532     }
5533 
5534   gfc_errors_to_warnings (false);
5535 }
5536 
5537 /* Callback function. If there is a call to a subroutine which is
5538    neither pure nor implicit_pure, unset the implicit_pure flag for
5539    the caller and return -1.  */
5540 
5541 static int
implicit_pure_call(gfc_code ** c,int * walk_subtrees ATTRIBUTE_UNUSED,void * sym_data)5542 implicit_pure_call (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
5543 		    void *sym_data)
5544 {
5545   gfc_code *co = *c;
5546   gfc_symbol *caller_sym;
5547   symbol_attribute *a;
5548 
5549   if (co->op != EXEC_CALL || co->resolved_sym == NULL)
5550     return 0;
5551 
5552   a = &co->resolved_sym->attr;
5553   if (a->intrinsic || a->pure || a->implicit_pure)
5554     return 0;
5555 
5556   caller_sym = (gfc_symbol *) sym_data;
5557   gfc_unset_implicit_pure (caller_sym);
5558   return 1;
5559 }
5560 
5561 /* Callback function. If there is a call to a function which is
5562    neither pure nor implicit_pure, unset the implicit_pure flag for
5563    the caller and return 1.  */
5564 
5565 static int
implicit_pure_expr(gfc_expr ** e,int * walk ATTRIBUTE_UNUSED,void * sym_data)5566 implicit_pure_expr (gfc_expr **e, int *walk ATTRIBUTE_UNUSED, void *sym_data)
5567 {
5568   gfc_expr *expr = *e;
5569   gfc_symbol *caller_sym;
5570   gfc_symbol *sym;
5571   symbol_attribute *a;
5572 
5573   if (expr->expr_type != EXPR_FUNCTION || expr->value.function.isym)
5574     return 0;
5575 
5576   sym = expr->symtree->n.sym;
5577   a = &sym->attr;
5578   if (a->pure || a->implicit_pure)
5579     return 0;
5580 
5581   caller_sym = (gfc_symbol *) sym_data;
5582   gfc_unset_implicit_pure (caller_sym);
5583   return 1;
5584 }
5585 
5586 /* Go through all procedures in the namespace and unset the
5587    implicit_pure attribute for any procedure that calls something not
5588    pure or implicit pure.  */
5589 
5590 bool
gfc_fix_implicit_pure(gfc_namespace * ns)5591 gfc_fix_implicit_pure (gfc_namespace *ns)
5592 {
5593   bool changed = false;
5594   gfc_symbol *proc = ns->proc_name;
5595 
5596   if (proc && proc->attr.flavor == FL_PROCEDURE && proc->attr.implicit_pure
5597       && ns->code
5598       && gfc_code_walker (&ns->code, implicit_pure_call, implicit_pure_expr,
5599 			  (void *) ns->proc_name))
5600     changed = true;
5601 
5602   for (ns = ns->contained; ns; ns = ns->sibling)
5603     {
5604       if (gfc_fix_implicit_pure (ns))
5605 	changed = true;
5606     }
5607 
5608   return changed;
5609 }
5610