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