]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/fortran/frontend-passes.c
decl.c: Reorder #include's and remove duplicates.
[thirdparty/gcc.git] / gcc / fortran / frontend-passes.c
1 /* Pass manager for Fortran front end.
2 Copyright (C) 2010-2015 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 "arith.h"
27 #include "dependency.h"
28 #include "constructor.h"
29 #include "opts.h"
30 #include "intrinsic.h"
31
32 /* Forward declarations. */
33
34 static void strip_function_call (gfc_expr *);
35 static void optimize_namespace (gfc_namespace *);
36 static void optimize_assignment (gfc_code *);
37 static bool optimize_op (gfc_expr *);
38 static bool optimize_comparison (gfc_expr *, gfc_intrinsic_op);
39 static bool optimize_trim (gfc_expr *);
40 static bool optimize_lexical_comparison (gfc_expr *);
41 static void optimize_minmaxloc (gfc_expr **);
42 static bool is_empty_string (gfc_expr *e);
43 static void doloop_warn (gfc_namespace *);
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 inline_matmul_assign (gfc_code **, int *, void *);
49 static gfc_code * create_do_loop (gfc_expr *, gfc_expr *, gfc_expr *,
50 locus *, gfc_namespace *,
51 char *vname=NULL);
52
53 /* How deep we are inside an argument list. */
54
55 static int count_arglist;
56
57 /* Vector of gfc_expr ** we operate on. */
58
59 static vec<gfc_expr **> expr_array;
60
61 /* Pointer to the gfc_code we currently work on - to be able to insert
62 a block before the statement. */
63
64 static gfc_code **current_code;
65
66 /* Pointer to the block to be inserted, and the statement we are
67 changing within the block. */
68
69 static gfc_code *inserted_block, **changed_statement;
70
71 /* The namespace we are currently dealing with. */
72
73 static gfc_namespace *current_ns;
74
75 /* If we are within any forall loop. */
76
77 static int forall_level;
78
79 /* Keep track of whether we are within an OMP workshare. */
80
81 static bool in_omp_workshare;
82
83 /* Keep track of iterators for array constructors. */
84
85 static int iterator_level;
86
87 /* Keep track of DO loop levels. */
88
89 static vec<gfc_code *> doloop_list;
90
91 static int doloop_level;
92
93 /* Vector of gfc_expr * to keep track of DO loops. */
94
95 struct my_struct *evec;
96
97 /* Keep track of association lists. */
98
99 static bool in_assoc_list;
100
101 /* Counter for temporary variables. */
102
103 static int var_num = 1;
104
105 /* What sort of matrix we are dealing with when inlining MATMUL. */
106
107 enum matrix_case { none=0, A2B2, A2B1, A1B2 };
108
109 /* Keep track of the number of expressions we have inserted so far
110 using create_var. */
111
112 int n_vars;
113
114 /* Entry point - run all passes for a namespace. */
115
116 void
117 gfc_run_passes (gfc_namespace *ns)
118 {
119
120 /* Warn about dubious DO loops where the index might
121 change. */
122
123 doloop_level = 0;
124 doloop_warn (ns);
125 doloop_list.release ();
126
127 if (flag_frontend_optimize)
128 {
129 optimize_namespace (ns);
130 optimize_reduction (ns);
131 if (flag_dump_fortran_optimized)
132 gfc_dump_parse_tree (ns, stdout);
133
134 expr_array.release ();
135 }
136
137 if (flag_realloc_lhs)
138 realloc_strings (ns);
139 }
140
141 /* Callback for each gfc_code node invoked from check_realloc_strings.
142 For an allocatable LHS string which also appears as a variable on
143 the RHS, replace
144
145 a = a(x:y)
146
147 with
148
149 tmp = a(x:y)
150 a = tmp
151 */
152
153 static int
154 realloc_string_callback (gfc_code **c, int *walk_subtrees,
155 void *data ATTRIBUTE_UNUSED)
156 {
157 gfc_expr *expr1, *expr2;
158 gfc_code *co = *c;
159 gfc_expr *n;
160
161 *walk_subtrees = 0;
162 if (co->op != EXEC_ASSIGN)
163 return 0;
164
165 expr1 = co->expr1;
166 if (expr1->ts.type != BT_CHARACTER || expr1->rank != 0
167 || !expr1->symtree->n.sym->attr.allocatable)
168 return 0;
169
170 expr2 = gfc_discard_nops (co->expr2);
171 if (expr2->expr_type != EXPR_VARIABLE)
172 return 0;
173
174 if (!gfc_check_dependency (expr1, expr2, true))
175 return 0;
176
177 current_code = c;
178 n = create_var (expr2, "trim");
179 co->expr2 = n;
180 return 0;
181 }
182
183 /* Callback for each gfc_code node invoked through gfc_code_walker
184 from optimize_namespace. */
185
186 static int
187 optimize_code (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
188 void *data ATTRIBUTE_UNUSED)
189 {
190
191 gfc_exec_op op;
192
193 op = (*c)->op;
194
195 if (op == EXEC_CALL || op == EXEC_COMPCALL || op == EXEC_ASSIGN_CALL
196 || op == EXEC_CALL_PPC)
197 count_arglist = 1;
198 else
199 count_arglist = 0;
200
201 current_code = c;
202 inserted_block = NULL;
203 changed_statement = NULL;
204
205 if (op == EXEC_ASSIGN)
206 optimize_assignment (*c);
207 return 0;
208 }
209
210 /* Callback for each gfc_expr node invoked through gfc_code_walker
211 from optimize_namespace. */
212
213 static int
214 optimize_expr (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
215 void *data ATTRIBUTE_UNUSED)
216 {
217 bool function_expr;
218
219 if ((*e)->expr_type == EXPR_FUNCTION)
220 {
221 count_arglist ++;
222 function_expr = true;
223 }
224 else
225 function_expr = false;
226
227 if (optimize_trim (*e))
228 gfc_simplify_expr (*e, 0);
229
230 if (optimize_lexical_comparison (*e))
231 gfc_simplify_expr (*e, 0);
232
233 if ((*e)->expr_type == EXPR_OP && optimize_op (*e))
234 gfc_simplify_expr (*e, 0);
235
236 if ((*e)->expr_type == EXPR_FUNCTION && (*e)->value.function.isym)
237 switch ((*e)->value.function.isym->id)
238 {
239 case GFC_ISYM_MINLOC:
240 case GFC_ISYM_MAXLOC:
241 optimize_minmaxloc (e);
242 break;
243 default:
244 break;
245 }
246
247 if (function_expr)
248 count_arglist --;
249
250 return 0;
251 }
252
253 /* Auxiliary function to handle the arguments to reduction intrnisics. If the
254 function is a scalar, just copy it; otherwise returns the new element, the
255 old one can be freed. */
256
257 static gfc_expr *
258 copy_walk_reduction_arg (gfc_constructor *c, gfc_expr *fn)
259 {
260 gfc_expr *fcn, *e = c->expr;
261
262 fcn = gfc_copy_expr (e);
263 if (c->iterator)
264 {
265 gfc_constructor_base newbase;
266 gfc_expr *new_expr;
267 gfc_constructor *new_c;
268
269 newbase = NULL;
270 new_expr = gfc_get_expr ();
271 new_expr->expr_type = EXPR_ARRAY;
272 new_expr->ts = e->ts;
273 new_expr->where = e->where;
274 new_expr->rank = 1;
275 new_c = gfc_constructor_append_expr (&newbase, fcn, &(e->where));
276 new_c->iterator = c->iterator;
277 new_expr->value.constructor = newbase;
278 c->iterator = NULL;
279
280 fcn = new_expr;
281 }
282
283 if (fcn->rank != 0)
284 {
285 gfc_isym_id id = fn->value.function.isym->id;
286
287 if (id == GFC_ISYM_SUM || id == GFC_ISYM_PRODUCT)
288 fcn = gfc_build_intrinsic_call (current_ns, id,
289 fn->value.function.isym->name,
290 fn->where, 3, fcn, NULL, NULL);
291 else if (id == GFC_ISYM_ANY || id == GFC_ISYM_ALL)
292 fcn = gfc_build_intrinsic_call (current_ns, id,
293 fn->value.function.isym->name,
294 fn->where, 2, fcn, NULL);
295 else
296 gfc_internal_error ("Illegal id in copy_walk_reduction_arg");
297
298 fcn->symtree->n.sym->attr.access = ACCESS_PRIVATE;
299 }
300
301 return fcn;
302 }
303
304 /* Callback function for optimzation of reductions to scalars. Transform ANY
305 ([f1,f2,f3, ...]) to f1 .or. f2 .or. f3 .or. ..., with ANY, SUM and PRODUCT
306 correspondingly. Handly only the simple cases without MASK and DIM. */
307
308 static int
309 callback_reduction (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
310 void *data ATTRIBUTE_UNUSED)
311 {
312 gfc_expr *fn, *arg;
313 gfc_intrinsic_op op;
314 gfc_isym_id id;
315 gfc_actual_arglist *a;
316 gfc_actual_arglist *dim;
317 gfc_constructor *c;
318 gfc_expr *res, *new_expr;
319 gfc_actual_arglist *mask;
320
321 fn = *e;
322
323 if (fn->rank != 0 || fn->expr_type != EXPR_FUNCTION
324 || fn->value.function.isym == NULL)
325 return 0;
326
327 id = fn->value.function.isym->id;
328
329 if (id != GFC_ISYM_SUM && id != GFC_ISYM_PRODUCT
330 && id != GFC_ISYM_ANY && id != GFC_ISYM_ALL)
331 return 0;
332
333 a = fn->value.function.actual;
334
335 /* Don't handle MASK or DIM. */
336
337 dim = a->next;
338
339 if (dim->expr != NULL)
340 return 0;
341
342 if (id == GFC_ISYM_SUM || id == GFC_ISYM_PRODUCT)
343 {
344 mask = dim->next;
345 if ( mask->expr != NULL)
346 return 0;
347 }
348
349 arg = a->expr;
350
351 if (arg->expr_type != EXPR_ARRAY)
352 return 0;
353
354 switch (id)
355 {
356 case GFC_ISYM_SUM:
357 op = INTRINSIC_PLUS;
358 break;
359
360 case GFC_ISYM_PRODUCT:
361 op = INTRINSIC_TIMES;
362 break;
363
364 case GFC_ISYM_ANY:
365 op = INTRINSIC_OR;
366 break;
367
368 case GFC_ISYM_ALL:
369 op = INTRINSIC_AND;
370 break;
371
372 default:
373 return 0;
374 }
375
376 c = gfc_constructor_first (arg->value.constructor);
377
378 /* Don't do any simplififcation if we have
379 - no element in the constructor or
380 - only have a single element in the array which contains an
381 iterator. */
382
383 if (c == NULL)
384 return 0;
385
386 res = copy_walk_reduction_arg (c, fn);
387
388 c = gfc_constructor_next (c);
389 while (c)
390 {
391 new_expr = gfc_get_expr ();
392 new_expr->ts = fn->ts;
393 new_expr->expr_type = EXPR_OP;
394 new_expr->rank = fn->rank;
395 new_expr->where = fn->where;
396 new_expr->value.op.op = op;
397 new_expr->value.op.op1 = res;
398 new_expr->value.op.op2 = copy_walk_reduction_arg (c, fn);
399 res = new_expr;
400 c = gfc_constructor_next (c);
401 }
402
403 gfc_simplify_expr (res, 0);
404 *e = res;
405 gfc_free_expr (fn);
406
407 return 0;
408 }
409
410 /* Callback function for common function elimination, called from cfe_expr_0.
411 Put all eligible function expressions into expr_array. */
412
413 static int
414 cfe_register_funcs (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
415 void *data ATTRIBUTE_UNUSED)
416 {
417
418 if ((*e)->expr_type != EXPR_FUNCTION)
419 return 0;
420
421 /* We don't do character functions with unknown charlens. */
422 if ((*e)->ts.type == BT_CHARACTER
423 && ((*e)->ts.u.cl == NULL || (*e)->ts.u.cl->length == NULL
424 || (*e)->ts.u.cl->length->expr_type != EXPR_CONSTANT))
425 return 0;
426
427 /* We don't do function elimination within FORALL statements, it can
428 lead to wrong-code in certain circumstances. */
429
430 if (forall_level > 0)
431 return 0;
432
433 /* Function elimination inside an iterator could lead to functions which
434 depend on iterator variables being moved outside. FIXME: We should check
435 if the functions do indeed depend on the iterator variable. */
436
437 if (iterator_level > 0)
438 return 0;
439
440 /* If we don't know the shape at compile time, we create an allocatable
441 temporary variable to hold the intermediate result, but only if
442 allocation on assignment is active. */
443
444 if ((*e)->rank > 0 && (*e)->shape == NULL && !flag_realloc_lhs)
445 return 0;
446
447 /* Skip the test for pure functions if -faggressive-function-elimination
448 is specified. */
449 if ((*e)->value.function.esym)
450 {
451 /* Don't create an array temporary for elemental functions. */
452 if ((*e)->value.function.esym->attr.elemental && (*e)->rank > 0)
453 return 0;
454
455 /* Only eliminate potentially impure functions if the
456 user specifically requested it. */
457 if (!flag_aggressive_function_elimination
458 && !(*e)->value.function.esym->attr.pure
459 && !(*e)->value.function.esym->attr.implicit_pure)
460 return 0;
461 }
462
463 if ((*e)->value.function.isym)
464 {
465 /* Conversions are handled on the fly by the middle end,
466 transpose during trans-* stages and TRANSFER by the middle end. */
467 if ((*e)->value.function.isym->id == GFC_ISYM_CONVERSION
468 || (*e)->value.function.isym->id == GFC_ISYM_TRANSFER
469 || gfc_inline_intrinsic_function_p (*e))
470 return 0;
471
472 /* Don't create an array temporary for elemental functions,
473 as this would be wasteful of memory.
474 FIXME: Create a scalar temporary during scalarization. */
475 if ((*e)->value.function.isym->elemental && (*e)->rank > 0)
476 return 0;
477
478 if (!(*e)->value.function.isym->pure)
479 return 0;
480 }
481
482 expr_array.safe_push (e);
483 return 0;
484 }
485
486 /* Auxiliary function to check if an expression is a temporary created by
487 create var. */
488
489 static bool
490 is_fe_temp (gfc_expr *e)
491 {
492 if (e->expr_type != EXPR_VARIABLE)
493 return false;
494
495 return e->symtree->n.sym->attr.fe_temp;
496 }
497
498 /* Determine the length of a string, if it can be evaluated as a constant
499 expression. Return a newly allocated gfc_expr or NULL on failure.
500 If the user specified a substring which is potentially longer than
501 the string itself, the string will be padded with spaces, which
502 is harmless. */
503
504 static gfc_expr *
505 constant_string_length (gfc_expr *e)
506 {
507
508 gfc_expr *length;
509 gfc_ref *ref;
510 gfc_expr *res;
511 mpz_t value;
512
513 if (e->ts.u.cl)
514 {
515 length = e->ts.u.cl->length;
516 if (length && length->expr_type == EXPR_CONSTANT)
517 return gfc_copy_expr(length);
518 }
519
520 /* Return length of substring, if constant. */
521 for (ref = e->ref; ref; ref = ref->next)
522 {
523 if (ref->type == REF_SUBSTRING
524 && gfc_dep_difference (ref->u.ss.end, ref->u.ss.start, &value))
525 {
526 res = gfc_get_constant_expr (BT_INTEGER, gfc_charlen_int_kind,
527 &e->where);
528
529 mpz_add_ui (res->value.integer, value, 1);
530 mpz_clear (value);
531 return res;
532 }
533 }
534
535 /* Return length of char symbol, if constant. */
536
537 if (e->symtree->n.sym->ts.u.cl && e->symtree->n.sym->ts.u.cl->length
538 && e->symtree->n.sym->ts.u.cl->length->expr_type == EXPR_CONSTANT)
539 return gfc_copy_expr (e->symtree->n.sym->ts.u.cl->length);
540
541 return NULL;
542
543 }
544
545 /* Insert a block at the current position unless it has already
546 been inserted; in this case use the one already there. */
547
548 static gfc_namespace*
549 insert_block ()
550 {
551 gfc_namespace *ns;
552
553 /* If the block hasn't already been created, do so. */
554 if (inserted_block == NULL)
555 {
556 inserted_block = XCNEW (gfc_code);
557 inserted_block->op = EXEC_BLOCK;
558 inserted_block->loc = (*current_code)->loc;
559 ns = gfc_build_block_ns (current_ns);
560 inserted_block->ext.block.ns = ns;
561 inserted_block->ext.block.assoc = NULL;
562
563 ns->code = *current_code;
564
565 /* If the statement has a label, make sure it is transferred to
566 the newly created block. */
567
568 if ((*current_code)->here)
569 {
570 inserted_block->here = (*current_code)->here;
571 (*current_code)->here = NULL;
572 }
573
574 inserted_block->next = (*current_code)->next;
575 changed_statement = &(inserted_block->ext.block.ns->code);
576 (*current_code)->next = NULL;
577 /* Insert the BLOCK at the right position. */
578 *current_code = inserted_block;
579 ns->parent = current_ns;
580 }
581 else
582 ns = inserted_block->ext.block.ns;
583
584 return ns;
585 }
586
587 /* Returns a new expression (a variable) to be used in place of the old one,
588 with an optional assignment statement before the current statement to set
589 the value of the variable. Creates a new BLOCK for the statement if that
590 hasn't already been done and puts the statement, plus the newly created
591 variables, in that block. Special cases: If the expression is constant or
592 a temporary which has already been created, just copy it. */
593
594 static gfc_expr*
595 create_var (gfc_expr * e, const char *vname)
596 {
597 char name[GFC_MAX_SYMBOL_LEN +1];
598 gfc_symtree *symtree;
599 gfc_symbol *symbol;
600 gfc_expr *result;
601 gfc_code *n;
602 gfc_namespace *ns;
603 int i;
604
605 if (e->expr_type == EXPR_CONSTANT || is_fe_temp (e))
606 return gfc_copy_expr (e);
607
608 ns = insert_block ();
609
610 if (vname)
611 snprintf (name, GFC_MAX_SYMBOL_LEN, "__var_%d_%s", var_num++, vname);
612 else
613 snprintf (name, GFC_MAX_SYMBOL_LEN, "__var_%d", var_num++);
614
615 if (gfc_get_sym_tree (name, ns, &symtree, false) != 0)
616 gcc_unreachable ();
617
618 symbol = symtree->n.sym;
619 symbol->ts = e->ts;
620
621 if (e->rank > 0)
622 {
623 symbol->as = gfc_get_array_spec ();
624 symbol->as->rank = e->rank;
625
626 if (e->shape == NULL)
627 {
628 /* We don't know the shape at compile time, so we use an
629 allocatable. */
630 symbol->as->type = AS_DEFERRED;
631 symbol->attr.allocatable = 1;
632 }
633 else
634 {
635 symbol->as->type = AS_EXPLICIT;
636 /* Copy the shape. */
637 for (i=0; i<e->rank; i++)
638 {
639 gfc_expr *p, *q;
640
641 p = gfc_get_constant_expr (BT_INTEGER, gfc_default_integer_kind,
642 &(e->where));
643 mpz_set_si (p->value.integer, 1);
644 symbol->as->lower[i] = p;
645
646 q = gfc_get_constant_expr (BT_INTEGER, gfc_index_integer_kind,
647 &(e->where));
648 mpz_set (q->value.integer, e->shape[i]);
649 symbol->as->upper[i] = q;
650 }
651 }
652 }
653
654 if (e->ts.type == BT_CHARACTER && e->rank == 0)
655 {
656 gfc_expr *length;
657
658 length = constant_string_length (e);
659 if (length)
660 {
661 symbol->ts.u.cl = gfc_new_charlen (ns, NULL);
662 symbol->ts.u.cl->length = length;
663 }
664 else
665 symbol->attr.allocatable = 1;
666 }
667
668 symbol->attr.flavor = FL_VARIABLE;
669 symbol->attr.referenced = 1;
670 symbol->attr.dimension = e->rank > 0;
671 symbol->attr.fe_temp = 1;
672 gfc_commit_symbol (symbol);
673
674 result = gfc_get_expr ();
675 result->expr_type = EXPR_VARIABLE;
676 result->ts = e->ts;
677 result->rank = e->rank;
678 result->shape = gfc_copy_shape (e->shape, e->rank);
679 result->symtree = symtree;
680 result->where = e->where;
681 if (e->rank > 0)
682 {
683 result->ref = gfc_get_ref ();
684 result->ref->type = REF_ARRAY;
685 result->ref->u.ar.type = AR_FULL;
686 result->ref->u.ar.where = e->where;
687 result->ref->u.ar.dimen = e->rank;
688 result->ref->u.ar.as = symbol->ts.type == BT_CLASS
689 ? CLASS_DATA (symbol)->as : symbol->as;
690 if (warn_array_temporaries)
691 gfc_warning (OPT_Warray_temporaries,
692 "Creating array temporary at %L", &(e->where));
693 }
694
695 /* Generate the new assignment. */
696 n = XCNEW (gfc_code);
697 n->op = EXEC_ASSIGN;
698 n->loc = (*current_code)->loc;
699 n->next = *changed_statement;
700 n->expr1 = gfc_copy_expr (result);
701 n->expr2 = e;
702 *changed_statement = n;
703 n_vars ++;
704
705 return result;
706 }
707
708 /* Warn about function elimination. */
709
710 static void
711 do_warn_function_elimination (gfc_expr *e)
712 {
713 if (e->expr_type != EXPR_FUNCTION)
714 return;
715 if (e->value.function.esym)
716 gfc_warning (0, "Removing call to function %qs at %L",
717 e->value.function.esym->name, &(e->where));
718 else if (e->value.function.isym)
719 gfc_warning (0, "Removing call to function %qs at %L",
720 e->value.function.isym->name, &(e->where));
721 }
722 /* Callback function for the code walker for doing common function
723 elimination. This builds up the list of functions in the expression
724 and goes through them to detect duplicates, which it then replaces
725 by variables. */
726
727 static int
728 cfe_expr_0 (gfc_expr **e, int *walk_subtrees,
729 void *data ATTRIBUTE_UNUSED)
730 {
731 int i,j;
732 gfc_expr *newvar;
733 gfc_expr **ei, **ej;
734
735 /* Don't do this optimization within OMP workshare. */
736
737 if (in_omp_workshare)
738 {
739 *walk_subtrees = 0;
740 return 0;
741 }
742
743 expr_array.release ();
744
745 gfc_expr_walker (e, cfe_register_funcs, NULL);
746
747 /* Walk through all the functions. */
748
749 FOR_EACH_VEC_ELT_FROM (expr_array, i, ei, 1)
750 {
751 /* Skip if the function has been replaced by a variable already. */
752 if ((*ei)->expr_type == EXPR_VARIABLE)
753 continue;
754
755 newvar = NULL;
756 for (j=0; j<i; j++)
757 {
758 ej = expr_array[j];
759 if (gfc_dep_compare_functions (*ei, *ej, true) == 0)
760 {
761 if (newvar == NULL)
762 newvar = create_var (*ei, "fcn");
763
764 if (warn_function_elimination)
765 do_warn_function_elimination (*ej);
766
767 free (*ej);
768 *ej = gfc_copy_expr (newvar);
769 }
770 }
771 if (newvar)
772 *ei = newvar;
773 }
774
775 /* We did all the necessary walking in this function. */
776 *walk_subtrees = 0;
777 return 0;
778 }
779
780 /* Callback function for common function elimination, called from
781 gfc_code_walker. This keeps track of the current code, in order
782 to insert statements as needed. */
783
784 static int
785 cfe_code (gfc_code **c, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
786 {
787 current_code = c;
788 inserted_block = NULL;
789 changed_statement = NULL;
790
791 /* Do not do anything inside a WHERE statement; scalar assignments, BLOCKs
792 and allocation on assigment are prohibited inside WHERE, and finally
793 masking an expression would lead to wrong-code when replacing
794
795 WHERE (a>0)
796 b = sum(foo(a) + foo(a))
797 END WHERE
798
799 with
800
801 WHERE (a > 0)
802 tmp = foo(a)
803 b = sum(tmp + tmp)
804 END WHERE
805 */
806
807 if ((*c)->op == EXEC_WHERE)
808 {
809 *walk_subtrees = 0;
810 return 0;
811 }
812
813
814 return 0;
815 }
816
817 /* Dummy function for expression call back, for use when we
818 really don't want to do any walking. */
819
820 static int
821 dummy_expr_callback (gfc_expr **e ATTRIBUTE_UNUSED, int *walk_subtrees,
822 void *data ATTRIBUTE_UNUSED)
823 {
824 *walk_subtrees = 0;
825 return 0;
826 }
827
828 /* Dummy function for code callback, for use when we really
829 don't want to do anything. */
830 int
831 gfc_dummy_code_callback (gfc_code **e ATTRIBUTE_UNUSED,
832 int *walk_subtrees ATTRIBUTE_UNUSED,
833 void *data ATTRIBUTE_UNUSED)
834 {
835 return 0;
836 }
837
838 /* Code callback function for converting
839 do while(a)
840 end do
841 into the equivalent
842 do
843 if (.not. a) exit
844 end do
845 This is because common function elimination would otherwise place the
846 temporary variables outside the loop. */
847
848 static int
849 convert_do_while (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
850 void *data ATTRIBUTE_UNUSED)
851 {
852 gfc_code *co = *c;
853 gfc_code *c_if1, *c_if2, *c_exit;
854 gfc_code *loopblock;
855 gfc_expr *e_not, *e_cond;
856
857 if (co->op != EXEC_DO_WHILE)
858 return 0;
859
860 if (co->expr1 == NULL || co->expr1->expr_type == EXPR_CONSTANT)
861 return 0;
862
863 e_cond = co->expr1;
864
865 /* Generate the condition of the if statement, which is .not. the original
866 statement. */
867 e_not = gfc_get_expr ();
868 e_not->ts = e_cond->ts;
869 e_not->where = e_cond->where;
870 e_not->expr_type = EXPR_OP;
871 e_not->value.op.op = INTRINSIC_NOT;
872 e_not->value.op.op1 = e_cond;
873
874 /* Generate the EXIT statement. */
875 c_exit = XCNEW (gfc_code);
876 c_exit->op = EXEC_EXIT;
877 c_exit->ext.which_construct = co;
878 c_exit->loc = co->loc;
879
880 /* Generate the IF statement. */
881 c_if2 = XCNEW (gfc_code);
882 c_if2->op = EXEC_IF;
883 c_if2->expr1 = e_not;
884 c_if2->next = c_exit;
885 c_if2->loc = co->loc;
886
887 /* ... plus the one to chain it to. */
888 c_if1 = XCNEW (gfc_code);
889 c_if1->op = EXEC_IF;
890 c_if1->block = c_if2;
891 c_if1->loc = co->loc;
892
893 /* Make the DO WHILE loop into a DO block by replacing the condition
894 with a true constant. */
895 co->expr1 = gfc_get_logical_expr (gfc_default_integer_kind, &co->loc, true);
896
897 /* Hang the generated if statement into the loop body. */
898
899 loopblock = co->block->next;
900 co->block->next = c_if1;
901 c_if1->next = loopblock;
902
903 return 0;
904 }
905
906 /* Code callback function for converting
907 if (a) then
908 ...
909 else if (b) then
910 end if
911
912 into
913 if (a) then
914 else
915 if (b) then
916 end if
917 end if
918
919 because otherwise common function elimination would place the BLOCKs
920 into the wrong place. */
921
922 static int
923 convert_elseif (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
924 void *data ATTRIBUTE_UNUSED)
925 {
926 gfc_code *co = *c;
927 gfc_code *c_if1, *c_if2, *else_stmt;
928
929 if (co->op != EXEC_IF)
930 return 0;
931
932 /* This loop starts out with the first ELSE statement. */
933 else_stmt = co->block->block;
934
935 while (else_stmt != NULL)
936 {
937 gfc_code *next_else;
938
939 /* If there is no condition, we're done. */
940 if (else_stmt->expr1 == NULL)
941 break;
942
943 next_else = else_stmt->block;
944
945 /* Generate the new IF statement. */
946 c_if2 = XCNEW (gfc_code);
947 c_if2->op = EXEC_IF;
948 c_if2->expr1 = else_stmt->expr1;
949 c_if2->next = else_stmt->next;
950 c_if2->loc = else_stmt->loc;
951 c_if2->block = next_else;
952
953 /* ... plus the one to chain it to. */
954 c_if1 = XCNEW (gfc_code);
955 c_if1->op = EXEC_IF;
956 c_if1->block = c_if2;
957 c_if1->loc = else_stmt->loc;
958
959 /* Insert the new IF after the ELSE. */
960 else_stmt->expr1 = NULL;
961 else_stmt->next = c_if1;
962 else_stmt->block = NULL;
963
964 else_stmt = next_else;
965 }
966 /* Don't walk subtrees. */
967 return 0;
968 }
969
970 /* Optimize a namespace, including all contained namespaces. */
971
972 static void
973 optimize_namespace (gfc_namespace *ns)
974 {
975 gfc_namespace *saved_ns = gfc_current_ns;
976 current_ns = ns;
977 gfc_current_ns = ns;
978 forall_level = 0;
979 iterator_level = 0;
980 in_assoc_list = false;
981 in_omp_workshare = false;
982
983 gfc_code_walker (&ns->code, convert_do_while, dummy_expr_callback, NULL);
984 gfc_code_walker (&ns->code, convert_elseif, dummy_expr_callback, NULL);
985 gfc_code_walker (&ns->code, cfe_code, cfe_expr_0, NULL);
986 gfc_code_walker (&ns->code, optimize_code, optimize_expr, NULL);
987 if (flag_inline_matmul_limit != 0)
988 gfc_code_walker (&ns->code, inline_matmul_assign, dummy_expr_callback,
989 NULL);
990
991 /* BLOCKs are handled in the expression walker below. */
992 for (ns = ns->contained; ns; ns = ns->sibling)
993 {
994 if (ns->code == NULL || ns->code->op != EXEC_BLOCK)
995 optimize_namespace (ns);
996 }
997 gfc_current_ns = saved_ns;
998 }
999
1000 /* Handle dependencies for allocatable strings which potentially redefine
1001 themselves in an assignment. */
1002
1003 static void
1004 realloc_strings (gfc_namespace *ns)
1005 {
1006 current_ns = ns;
1007 gfc_code_walker (&ns->code, realloc_string_callback, dummy_expr_callback, NULL);
1008
1009 for (ns = ns->contained; ns; ns = ns->sibling)
1010 {
1011 if (ns->code == NULL || ns->code->op != EXEC_BLOCK)
1012 realloc_strings (ns);
1013 }
1014
1015 }
1016
1017 static void
1018 optimize_reduction (gfc_namespace *ns)
1019 {
1020 current_ns = ns;
1021 gfc_code_walker (&ns->code, gfc_dummy_code_callback,
1022 callback_reduction, NULL);
1023
1024 /* BLOCKs are handled in the expression walker below. */
1025 for (ns = ns->contained; ns; ns = ns->sibling)
1026 {
1027 if (ns->code == NULL || ns->code->op != EXEC_BLOCK)
1028 optimize_reduction (ns);
1029 }
1030 }
1031
1032 /* Replace code like
1033 a = matmul(b,c) + d
1034 with
1035 a = matmul(b,c) ; a = a + d
1036 where the array function is not elemental and not allocatable
1037 and does not depend on the left-hand side.
1038 */
1039
1040 static bool
1041 optimize_binop_array_assignment (gfc_code *c, gfc_expr **rhs, bool seen_op)
1042 {
1043 gfc_expr *e;
1044
1045 e = *rhs;
1046 if (e->expr_type == EXPR_OP)
1047 {
1048 switch (e->value.op.op)
1049 {
1050 /* Unary operators and exponentiation: Only look at a single
1051 operand. */
1052 case INTRINSIC_NOT:
1053 case INTRINSIC_UPLUS:
1054 case INTRINSIC_UMINUS:
1055 case INTRINSIC_PARENTHESES:
1056 case INTRINSIC_POWER:
1057 if (optimize_binop_array_assignment (c, &e->value.op.op1, seen_op))
1058 return true;
1059 break;
1060
1061 case INTRINSIC_CONCAT:
1062 /* Do not do string concatenations. */
1063 break;
1064
1065 default:
1066 /* Binary operators. */
1067 if (optimize_binop_array_assignment (c, &e->value.op.op1, true))
1068 return true;
1069
1070 if (optimize_binop_array_assignment (c, &e->value.op.op2, true))
1071 return true;
1072
1073 break;
1074 }
1075 }
1076 else if (seen_op && e->expr_type == EXPR_FUNCTION && e->rank > 0
1077 && ! (e->value.function.esym
1078 && (e->value.function.esym->attr.elemental
1079 || e->value.function.esym->attr.allocatable
1080 || e->value.function.esym->ts.type != c->expr1->ts.type
1081 || e->value.function.esym->ts.kind != c->expr1->ts.kind))
1082 && ! (e->value.function.isym
1083 && (e->value.function.isym->elemental
1084 || e->ts.type != c->expr1->ts.type
1085 || e->ts.kind != c->expr1->ts.kind))
1086 && ! gfc_inline_intrinsic_function_p (e))
1087 {
1088
1089 gfc_code *n;
1090 gfc_expr *new_expr;
1091
1092 /* Insert a new assignment statement after the current one. */
1093 n = XCNEW (gfc_code);
1094 n->op = EXEC_ASSIGN;
1095 n->loc = c->loc;
1096 n->next = c->next;
1097 c->next = n;
1098
1099 n->expr1 = gfc_copy_expr (c->expr1);
1100 n->expr2 = c->expr2;
1101 new_expr = gfc_copy_expr (c->expr1);
1102 c->expr2 = e;
1103 *rhs = new_expr;
1104
1105 return true;
1106
1107 }
1108
1109 /* Nothing to optimize. */
1110 return false;
1111 }
1112
1113 /* Remove unneeded TRIMs at the end of expressions. */
1114
1115 static bool
1116 remove_trim (gfc_expr *rhs)
1117 {
1118 bool ret;
1119
1120 ret = false;
1121
1122 /* Check for a // b // trim(c). Looping is probably not
1123 necessary because the parser usually generates
1124 (// (// a b ) trim(c) ) , but better safe than sorry. */
1125
1126 while (rhs->expr_type == EXPR_OP
1127 && rhs->value.op.op == INTRINSIC_CONCAT)
1128 rhs = rhs->value.op.op2;
1129
1130 while (rhs->expr_type == EXPR_FUNCTION && rhs->value.function.isym
1131 && rhs->value.function.isym->id == GFC_ISYM_TRIM)
1132 {
1133 strip_function_call (rhs);
1134 /* Recursive call to catch silly stuff like trim ( a // trim(b)). */
1135 remove_trim (rhs);
1136 ret = true;
1137 }
1138
1139 return ret;
1140 }
1141
1142 /* Optimizations for an assignment. */
1143
1144 static void
1145 optimize_assignment (gfc_code * c)
1146 {
1147 gfc_expr *lhs, *rhs;
1148
1149 lhs = c->expr1;
1150 rhs = c->expr2;
1151
1152 if (lhs->ts.type == BT_CHARACTER && !lhs->ts.deferred)
1153 {
1154 /* Optimize a = trim(b) to a = b. */
1155 remove_trim (rhs);
1156
1157 /* Replace a = ' ' by a = '' to optimize away a memcpy. */
1158 if (is_empty_string (rhs))
1159 rhs->value.character.length = 0;
1160 }
1161
1162 if (lhs->rank > 0 && gfc_check_dependency (lhs, rhs, true) == 0)
1163 optimize_binop_array_assignment (c, &rhs, false);
1164 }
1165
1166
1167 /* Remove an unneeded function call, modifying the expression.
1168 This replaces the function call with the value of its
1169 first argument. The rest of the argument list is freed. */
1170
1171 static void
1172 strip_function_call (gfc_expr *e)
1173 {
1174 gfc_expr *e1;
1175 gfc_actual_arglist *a;
1176
1177 a = e->value.function.actual;
1178
1179 /* We should have at least one argument. */
1180 gcc_assert (a->expr != NULL);
1181
1182 e1 = a->expr;
1183
1184 /* Free the remaining arglist, if any. */
1185 if (a->next)
1186 gfc_free_actual_arglist (a->next);
1187
1188 /* Graft the argument expression onto the original function. */
1189 *e = *e1;
1190 free (e1);
1191
1192 }
1193
1194 /* Optimization of lexical comparison functions. */
1195
1196 static bool
1197 optimize_lexical_comparison (gfc_expr *e)
1198 {
1199 if (e->expr_type != EXPR_FUNCTION || e->value.function.isym == NULL)
1200 return false;
1201
1202 switch (e->value.function.isym->id)
1203 {
1204 case GFC_ISYM_LLE:
1205 return optimize_comparison (e, INTRINSIC_LE);
1206
1207 case GFC_ISYM_LGE:
1208 return optimize_comparison (e, INTRINSIC_GE);
1209
1210 case GFC_ISYM_LGT:
1211 return optimize_comparison (e, INTRINSIC_GT);
1212
1213 case GFC_ISYM_LLT:
1214 return optimize_comparison (e, INTRINSIC_LT);
1215
1216 default:
1217 break;
1218 }
1219 return false;
1220 }
1221
1222 /* Combine stuff like [a]>b into [a>b], for easier optimization later. Do not
1223 do CHARACTER because of possible pessimization involving character
1224 lengths. */
1225
1226 static bool
1227 combine_array_constructor (gfc_expr *e)
1228 {
1229
1230 gfc_expr *op1, *op2;
1231 gfc_expr *scalar;
1232 gfc_expr *new_expr;
1233 gfc_constructor *c, *new_c;
1234 gfc_constructor_base oldbase, newbase;
1235 bool scalar_first;
1236
1237 /* Array constructors have rank one. */
1238 if (e->rank != 1)
1239 return false;
1240
1241 /* Don't try to combine association lists, this makes no sense
1242 and leads to an ICE. */
1243 if (in_assoc_list)
1244 return false;
1245
1246 /* With FORALL, the BLOCKS created by create_var will cause an ICE. */
1247 if (forall_level > 0)
1248 return false;
1249
1250 op1 = e->value.op.op1;
1251 op2 = e->value.op.op2;
1252
1253 if (op1->expr_type == EXPR_ARRAY && op2->rank == 0)
1254 scalar_first = false;
1255 else if (op2->expr_type == EXPR_ARRAY && op1->rank == 0)
1256 {
1257 scalar_first = true;
1258 op1 = e->value.op.op2;
1259 op2 = e->value.op.op1;
1260 }
1261 else
1262 return false;
1263
1264 if (op2->ts.type == BT_CHARACTER)
1265 return false;
1266
1267 scalar = create_var (gfc_copy_expr (op2), "constr");
1268
1269 oldbase = op1->value.constructor;
1270 newbase = NULL;
1271 e->expr_type = EXPR_ARRAY;
1272
1273 for (c = gfc_constructor_first (oldbase); c;
1274 c = gfc_constructor_next (c))
1275 {
1276 new_expr = gfc_get_expr ();
1277 new_expr->ts = e->ts;
1278 new_expr->expr_type = EXPR_OP;
1279 new_expr->rank = c->expr->rank;
1280 new_expr->where = c->where;
1281 new_expr->value.op.op = e->value.op.op;
1282
1283 if (scalar_first)
1284 {
1285 new_expr->value.op.op1 = gfc_copy_expr (scalar);
1286 new_expr->value.op.op2 = gfc_copy_expr (c->expr);
1287 }
1288 else
1289 {
1290 new_expr->value.op.op1 = gfc_copy_expr (c->expr);
1291 new_expr->value.op.op2 = gfc_copy_expr (scalar);
1292 }
1293
1294 new_c = gfc_constructor_append_expr (&newbase, new_expr, &(e->where));
1295 new_c->iterator = c->iterator;
1296 c->iterator = NULL;
1297 }
1298
1299 gfc_free_expr (op1);
1300 gfc_free_expr (op2);
1301 gfc_free_expr (scalar);
1302
1303 e->value.constructor = newbase;
1304 return true;
1305 }
1306
1307 /* Change (-1)**k into 1-ishift(iand(k,1),1) and
1308 2**k into ishift(1,k) */
1309
1310 static bool
1311 optimize_power (gfc_expr *e)
1312 {
1313 gfc_expr *op1, *op2;
1314 gfc_expr *iand, *ishft;
1315
1316 if (e->ts.type != BT_INTEGER)
1317 return false;
1318
1319 op1 = e->value.op.op1;
1320
1321 if (op1 == NULL || op1->expr_type != EXPR_CONSTANT)
1322 return false;
1323
1324 if (mpz_cmp_si (op1->value.integer, -1L) == 0)
1325 {
1326 gfc_free_expr (op1);
1327
1328 op2 = e->value.op.op2;
1329
1330 if (op2 == NULL)
1331 return false;
1332
1333 iand = gfc_build_intrinsic_call (current_ns, GFC_ISYM_IAND,
1334 "_internal_iand", e->where, 2, op2,
1335 gfc_get_int_expr (e->ts.kind,
1336 &e->where, 1));
1337
1338 ishft = gfc_build_intrinsic_call (current_ns, GFC_ISYM_ISHFT,
1339 "_internal_ishft", e->where, 2, iand,
1340 gfc_get_int_expr (e->ts.kind,
1341 &e->where, 1));
1342
1343 e->value.op.op = INTRINSIC_MINUS;
1344 e->value.op.op1 = gfc_get_int_expr (e->ts.kind, &e->where, 1);
1345 e->value.op.op2 = ishft;
1346 return true;
1347 }
1348 else if (mpz_cmp_si (op1->value.integer, 2L) == 0)
1349 {
1350 gfc_free_expr (op1);
1351
1352 op2 = e->value.op.op2;
1353 if (op2 == NULL)
1354 return false;
1355
1356 ishft = gfc_build_intrinsic_call (current_ns, GFC_ISYM_ISHFT,
1357 "_internal_ishft", e->where, 2,
1358 gfc_get_int_expr (e->ts.kind,
1359 &e->where, 1),
1360 op2);
1361 *e = *ishft;
1362 return true;
1363 }
1364
1365 else if (mpz_cmp_si (op1->value.integer, 1L) == 0)
1366 {
1367 op2 = e->value.op.op2;
1368 if (op2 == NULL)
1369 return false;
1370
1371 gfc_free_expr (op1);
1372 gfc_free_expr (op2);
1373
1374 e->expr_type = EXPR_CONSTANT;
1375 e->value.op.op1 = NULL;
1376 e->value.op.op2 = NULL;
1377 mpz_init_set_si (e->value.integer, 1);
1378 /* Typespec and location are still OK. */
1379 return true;
1380 }
1381
1382 return false;
1383 }
1384
1385 /* Recursive optimization of operators. */
1386
1387 static bool
1388 optimize_op (gfc_expr *e)
1389 {
1390 bool changed;
1391
1392 gfc_intrinsic_op op = e->value.op.op;
1393
1394 changed = false;
1395
1396 /* Only use new-style comparisons. */
1397 switch(op)
1398 {
1399 case INTRINSIC_EQ_OS:
1400 op = INTRINSIC_EQ;
1401 break;
1402
1403 case INTRINSIC_GE_OS:
1404 op = INTRINSIC_GE;
1405 break;
1406
1407 case INTRINSIC_LE_OS:
1408 op = INTRINSIC_LE;
1409 break;
1410
1411 case INTRINSIC_NE_OS:
1412 op = INTRINSIC_NE;
1413 break;
1414
1415 case INTRINSIC_GT_OS:
1416 op = INTRINSIC_GT;
1417 break;
1418
1419 case INTRINSIC_LT_OS:
1420 op = INTRINSIC_LT;
1421 break;
1422
1423 default:
1424 break;
1425 }
1426
1427 switch (op)
1428 {
1429 case INTRINSIC_EQ:
1430 case INTRINSIC_GE:
1431 case INTRINSIC_LE:
1432 case INTRINSIC_NE:
1433 case INTRINSIC_GT:
1434 case INTRINSIC_LT:
1435 changed = optimize_comparison (e, op);
1436
1437 /* Fall through */
1438 /* Look at array constructors. */
1439 case INTRINSIC_PLUS:
1440 case INTRINSIC_MINUS:
1441 case INTRINSIC_TIMES:
1442 case INTRINSIC_DIVIDE:
1443 return combine_array_constructor (e) || changed;
1444
1445 case INTRINSIC_POWER:
1446 return optimize_power (e);
1447 break;
1448
1449 default:
1450 break;
1451 }
1452
1453 return false;
1454 }
1455
1456
1457 /* Return true if a constant string contains only blanks. */
1458
1459 static bool
1460 is_empty_string (gfc_expr *e)
1461 {
1462 int i;
1463
1464 if (e->ts.type != BT_CHARACTER || e->expr_type != EXPR_CONSTANT)
1465 return false;
1466
1467 for (i=0; i < e->value.character.length; i++)
1468 {
1469 if (e->value.character.string[i] != ' ')
1470 return false;
1471 }
1472
1473 return true;
1474 }
1475
1476
1477 /* Insert a call to the intrinsic len_trim. Use a different name for
1478 the symbol tree so we don't run into trouble when the user has
1479 renamed len_trim for some reason. */
1480
1481 static gfc_expr*
1482 get_len_trim_call (gfc_expr *str, int kind)
1483 {
1484 gfc_expr *fcn;
1485 gfc_actual_arglist *actual_arglist, *next;
1486
1487 fcn = gfc_get_expr ();
1488 fcn->expr_type = EXPR_FUNCTION;
1489 fcn->value.function.isym = gfc_intrinsic_function_by_id (GFC_ISYM_LEN_TRIM);
1490 actual_arglist = gfc_get_actual_arglist ();
1491 actual_arglist->expr = str;
1492 next = gfc_get_actual_arglist ();
1493 next->expr = gfc_get_int_expr (gfc_default_integer_kind, NULL, kind);
1494 actual_arglist->next = next;
1495
1496 fcn->value.function.actual = actual_arglist;
1497 fcn->where = str->where;
1498 fcn->ts.type = BT_INTEGER;
1499 fcn->ts.kind = gfc_charlen_int_kind;
1500
1501 gfc_get_sym_tree ("__internal_len_trim", current_ns, &fcn->symtree, false);
1502 fcn->symtree->n.sym->ts = fcn->ts;
1503 fcn->symtree->n.sym->attr.flavor = FL_PROCEDURE;
1504 fcn->symtree->n.sym->attr.function = 1;
1505 fcn->symtree->n.sym->attr.elemental = 1;
1506 fcn->symtree->n.sym->attr.referenced = 1;
1507 fcn->symtree->n.sym->attr.access = ACCESS_PRIVATE;
1508 gfc_commit_symbol (fcn->symtree->n.sym);
1509
1510 return fcn;
1511 }
1512
1513 /* Optimize expressions for equality. */
1514
1515 static bool
1516 optimize_comparison (gfc_expr *e, gfc_intrinsic_op op)
1517 {
1518 gfc_expr *op1, *op2;
1519 bool change;
1520 int eq;
1521 bool result;
1522 gfc_actual_arglist *firstarg, *secondarg;
1523
1524 if (e->expr_type == EXPR_OP)
1525 {
1526 firstarg = NULL;
1527 secondarg = NULL;
1528 op1 = e->value.op.op1;
1529 op2 = e->value.op.op2;
1530 }
1531 else if (e->expr_type == EXPR_FUNCTION)
1532 {
1533 /* One of the lexical comparison functions. */
1534 firstarg = e->value.function.actual;
1535 secondarg = firstarg->next;
1536 op1 = firstarg->expr;
1537 op2 = secondarg->expr;
1538 }
1539 else
1540 gcc_unreachable ();
1541
1542 /* Strip off unneeded TRIM calls from string comparisons. */
1543
1544 change = remove_trim (op1);
1545
1546 if (remove_trim (op2))
1547 change = true;
1548
1549 /* An expression of type EXPR_CONSTANT is only valid for scalars. */
1550 /* TODO: A scalar constant may be acceptable in some cases (the scalarizer
1551 handles them well). However, there are also cases that need a non-scalar
1552 argument. For example the any intrinsic. See PR 45380. */
1553 if (e->rank > 0)
1554 return change;
1555
1556 /* Replace a == '' with len_trim(a) == 0 and a /= '' with
1557 len_trim(a) != 0 */
1558 if (op1->ts.type == BT_CHARACTER && op2->ts.type == BT_CHARACTER
1559 && (op == INTRINSIC_EQ || op == INTRINSIC_NE))
1560 {
1561 bool empty_op1, empty_op2;
1562 empty_op1 = is_empty_string (op1);
1563 empty_op2 = is_empty_string (op2);
1564
1565 if (empty_op1 || empty_op2)
1566 {
1567 gfc_expr *fcn;
1568 gfc_expr *zero;
1569 gfc_expr *str;
1570
1571 /* This can only happen when an error for comparing
1572 characters of different kinds has already been issued. */
1573 if (empty_op1 && empty_op2)
1574 return false;
1575
1576 zero = gfc_get_int_expr (gfc_charlen_int_kind, &e->where, 0);
1577 str = empty_op1 ? op2 : op1;
1578
1579 fcn = get_len_trim_call (str, gfc_charlen_int_kind);
1580
1581
1582 if (empty_op1)
1583 gfc_free_expr (op1);
1584 else
1585 gfc_free_expr (op2);
1586
1587 op1 = fcn;
1588 op2 = zero;
1589 e->value.op.op1 = fcn;
1590 e->value.op.op2 = zero;
1591 }
1592 }
1593
1594
1595 /* Don't compare REAL or COMPLEX expressions when honoring NaNs. */
1596
1597 if (flag_finite_math_only
1598 || (op1->ts.type != BT_REAL && op2->ts.type != BT_REAL
1599 && op1->ts.type != BT_COMPLEX && op2->ts.type != BT_COMPLEX))
1600 {
1601 eq = gfc_dep_compare_expr (op1, op2);
1602 if (eq <= -2)
1603 {
1604 /* Replace A // B < A // C with B < C, and A // B < C // B
1605 with A < C. */
1606 if (op1->ts.type == BT_CHARACTER && op2->ts.type == BT_CHARACTER
1607 && op1->expr_type == EXPR_OP
1608 && op1->value.op.op == INTRINSIC_CONCAT
1609 && op2->expr_type == EXPR_OP
1610 && op2->value.op.op == INTRINSIC_CONCAT)
1611 {
1612 gfc_expr *op1_left = op1->value.op.op1;
1613 gfc_expr *op2_left = op2->value.op.op1;
1614 gfc_expr *op1_right = op1->value.op.op2;
1615 gfc_expr *op2_right = op2->value.op.op2;
1616
1617 if (gfc_dep_compare_expr (op1_left, op2_left) == 0)
1618 {
1619 /* Watch out for 'A ' // x vs. 'A' // x. */
1620
1621 if (op1_left->expr_type == EXPR_CONSTANT
1622 && op2_left->expr_type == EXPR_CONSTANT
1623 && op1_left->value.character.length
1624 != op2_left->value.character.length)
1625 return change;
1626 else
1627 {
1628 free (op1_left);
1629 free (op2_left);
1630 if (firstarg)
1631 {
1632 firstarg->expr = op1_right;
1633 secondarg->expr = op2_right;
1634 }
1635 else
1636 {
1637 e->value.op.op1 = op1_right;
1638 e->value.op.op2 = op2_right;
1639 }
1640 optimize_comparison (e, op);
1641 return true;
1642 }
1643 }
1644 if (gfc_dep_compare_expr (op1_right, op2_right) == 0)
1645 {
1646 free (op1_right);
1647 free (op2_right);
1648 if (firstarg)
1649 {
1650 firstarg->expr = op1_left;
1651 secondarg->expr = op2_left;
1652 }
1653 else
1654 {
1655 e->value.op.op1 = op1_left;
1656 e->value.op.op2 = op2_left;
1657 }
1658
1659 optimize_comparison (e, op);
1660 return true;
1661 }
1662 }
1663 }
1664 else
1665 {
1666 /* eq can only be -1, 0 or 1 at this point. */
1667 switch (op)
1668 {
1669 case INTRINSIC_EQ:
1670 result = eq == 0;
1671 break;
1672
1673 case INTRINSIC_GE:
1674 result = eq >= 0;
1675 break;
1676
1677 case INTRINSIC_LE:
1678 result = eq <= 0;
1679 break;
1680
1681 case INTRINSIC_NE:
1682 result = eq != 0;
1683 break;
1684
1685 case INTRINSIC_GT:
1686 result = eq > 0;
1687 break;
1688
1689 case INTRINSIC_LT:
1690 result = eq < 0;
1691 break;
1692
1693 default:
1694 gfc_internal_error ("illegal OP in optimize_comparison");
1695 break;
1696 }
1697
1698 /* Replace the expression by a constant expression. The typespec
1699 and where remains the way it is. */
1700 free (op1);
1701 free (op2);
1702 e->expr_type = EXPR_CONSTANT;
1703 e->value.logical = result;
1704 return true;
1705 }
1706 }
1707
1708 return change;
1709 }
1710
1711 /* Optimize a trim function by replacing it with an equivalent substring
1712 involving a call to len_trim. This only works for expressions where
1713 variables are trimmed. Return true if anything was modified. */
1714
1715 static bool
1716 optimize_trim (gfc_expr *e)
1717 {
1718 gfc_expr *a;
1719 gfc_ref *ref;
1720 gfc_expr *fcn;
1721 gfc_ref **rr = NULL;
1722
1723 /* Don't do this optimization within an argument list, because
1724 otherwise aliasing issues may occur. */
1725
1726 if (count_arglist != 1)
1727 return false;
1728
1729 if (e->ts.type != BT_CHARACTER || e->expr_type != EXPR_FUNCTION
1730 || e->value.function.isym == NULL
1731 || e->value.function.isym->id != GFC_ISYM_TRIM)
1732 return false;
1733
1734 a = e->value.function.actual->expr;
1735
1736 if (a->expr_type != EXPR_VARIABLE)
1737 return false;
1738
1739 /* This would pessimize the idiom a = trim(a) for reallocatable strings. */
1740
1741 if (a->symtree->n.sym->attr.allocatable)
1742 return false;
1743
1744 /* Follow all references to find the correct place to put the newly
1745 created reference. FIXME: Also handle substring references and
1746 array references. Array references cause strange regressions at
1747 the moment. */
1748
1749 if (a->ref)
1750 {
1751 for (rr = &(a->ref); *rr; rr = &((*rr)->next))
1752 {
1753 if ((*rr)->type == REF_SUBSTRING || (*rr)->type == REF_ARRAY)
1754 return false;
1755 }
1756 }
1757
1758 strip_function_call (e);
1759
1760 if (e->ref == NULL)
1761 rr = &(e->ref);
1762
1763 /* Create the reference. */
1764
1765 ref = gfc_get_ref ();
1766 ref->type = REF_SUBSTRING;
1767
1768 /* Set the start of the reference. */
1769
1770 ref->u.ss.start = gfc_get_int_expr (gfc_default_integer_kind, NULL, 1);
1771
1772 /* Build the function call to len_trim(x, gfc_default_integer_kind). */
1773
1774 fcn = get_len_trim_call (gfc_copy_expr (e), gfc_default_integer_kind);
1775
1776 /* Set the end of the reference to the call to len_trim. */
1777
1778 ref->u.ss.end = fcn;
1779 gcc_assert (rr != NULL && *rr == NULL);
1780 *rr = ref;
1781 return true;
1782 }
1783
1784 /* Optimize minloc(b), where b is rank 1 array, into
1785 (/ minloc(b, dim=1) /), and similarly for maxloc,
1786 as the latter forms are expanded inline. */
1787
1788 static void
1789 optimize_minmaxloc (gfc_expr **e)
1790 {
1791 gfc_expr *fn = *e;
1792 gfc_actual_arglist *a;
1793 char *name, *p;
1794
1795 if (fn->rank != 1
1796 || fn->value.function.actual == NULL
1797 || fn->value.function.actual->expr == NULL
1798 || fn->value.function.actual->expr->rank != 1)
1799 return;
1800
1801 *e = gfc_get_array_expr (fn->ts.type, fn->ts.kind, &fn->where);
1802 (*e)->shape = fn->shape;
1803 fn->rank = 0;
1804 fn->shape = NULL;
1805 gfc_constructor_append_expr (&(*e)->value.constructor, fn, &fn->where);
1806
1807 name = XALLOCAVEC (char, strlen (fn->value.function.name) + 1);
1808 strcpy (name, fn->value.function.name);
1809 p = strstr (name, "loc0");
1810 p[3] = '1';
1811 fn->value.function.name = gfc_get_string (name);
1812 if (fn->value.function.actual->next)
1813 {
1814 a = fn->value.function.actual->next;
1815 gcc_assert (a->expr == NULL);
1816 }
1817 else
1818 {
1819 a = gfc_get_actual_arglist ();
1820 fn->value.function.actual->next = a;
1821 }
1822 a->expr = gfc_get_constant_expr (BT_INTEGER, gfc_default_integer_kind,
1823 &fn->where);
1824 mpz_set_ui (a->expr->value.integer, 1);
1825 }
1826
1827 /* Callback function for code checking that we do not pass a DO variable to an
1828 INTENT(OUT) or INTENT(INOUT) dummy variable. */
1829
1830 static int
1831 doloop_code (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
1832 void *data ATTRIBUTE_UNUSED)
1833 {
1834 gfc_code *co;
1835 int i;
1836 gfc_formal_arglist *f;
1837 gfc_actual_arglist *a;
1838 gfc_code *cl;
1839
1840 co = *c;
1841
1842 /* If the doloop_list grew, we have to truncate it here. */
1843
1844 if ((unsigned) doloop_level < doloop_list.length())
1845 doloop_list.truncate (doloop_level);
1846
1847 switch (co->op)
1848 {
1849 case EXEC_DO:
1850
1851 if (co->ext.iterator && co->ext.iterator->var)
1852 doloop_list.safe_push (co);
1853 else
1854 doloop_list.safe_push ((gfc_code *) NULL);
1855 break;
1856
1857 case EXEC_CALL:
1858
1859 if (co->resolved_sym == NULL)
1860 break;
1861
1862 f = gfc_sym_get_dummy_args (co->resolved_sym);
1863
1864 /* Withot a formal arglist, there is only unknown INTENT,
1865 which we don't check for. */
1866 if (f == NULL)
1867 break;
1868
1869 a = co->ext.actual;
1870
1871 while (a && f)
1872 {
1873 FOR_EACH_VEC_ELT (doloop_list, i, cl)
1874 {
1875 gfc_symbol *do_sym;
1876
1877 if (cl == NULL)
1878 break;
1879
1880 do_sym = cl->ext.iterator->var->symtree->n.sym;
1881
1882 if (a->expr && a->expr->symtree
1883 && a->expr->symtree->n.sym == do_sym)
1884 {
1885 if (f->sym->attr.intent == INTENT_OUT)
1886 gfc_error_now ("Variable %qs at %L set to undefined "
1887 "value inside loop beginning at %L as "
1888 "INTENT(OUT) argument to subroutine %qs",
1889 do_sym->name, &a->expr->where,
1890 &doloop_list[i]->loc,
1891 co->symtree->n.sym->name);
1892 else if (f->sym->attr.intent == INTENT_INOUT)
1893 gfc_error_now ("Variable %qs at %L not definable inside "
1894 "loop beginning at %L as INTENT(INOUT) "
1895 "argument to subroutine %qs",
1896 do_sym->name, &a->expr->where,
1897 &doloop_list[i]->loc,
1898 co->symtree->n.sym->name);
1899 }
1900 }
1901 a = a->next;
1902 f = f->next;
1903 }
1904 break;
1905
1906 default:
1907 break;
1908 }
1909 return 0;
1910 }
1911
1912 /* Callback function for functions checking that we do not pass a DO variable
1913 to an INTENT(OUT) or INTENT(INOUT) dummy variable. */
1914
1915 static int
1916 do_function (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
1917 void *data ATTRIBUTE_UNUSED)
1918 {
1919 gfc_formal_arglist *f;
1920 gfc_actual_arglist *a;
1921 gfc_expr *expr;
1922 gfc_code *dl;
1923 int i;
1924
1925 expr = *e;
1926 if (expr->expr_type != EXPR_FUNCTION)
1927 return 0;
1928
1929 /* Intrinsic functions don't modify their arguments. */
1930
1931 if (expr->value.function.isym)
1932 return 0;
1933
1934 f = gfc_sym_get_dummy_args (expr->symtree->n.sym);
1935
1936 /* Without a formal arglist, there is only unknown INTENT,
1937 which we don't check for. */
1938 if (f == NULL)
1939 return 0;
1940
1941 a = expr->value.function.actual;
1942
1943 while (a && f)
1944 {
1945 FOR_EACH_VEC_ELT (doloop_list, i, dl)
1946 {
1947 gfc_symbol *do_sym;
1948
1949 if (dl == NULL)
1950 break;
1951
1952 do_sym = dl->ext.iterator->var->symtree->n.sym;
1953
1954 if (a->expr && a->expr->symtree
1955 && a->expr->symtree->n.sym == do_sym)
1956 {
1957 if (f->sym->attr.intent == INTENT_OUT)
1958 gfc_error_now ("Variable %qs at %L set to undefined value "
1959 "inside loop beginning at %L as INTENT(OUT) "
1960 "argument to function %qs", do_sym->name,
1961 &a->expr->where, &doloop_list[i]->loc,
1962 expr->symtree->n.sym->name);
1963 else if (f->sym->attr.intent == INTENT_INOUT)
1964 gfc_error_now ("Variable %qs at %L not definable inside loop"
1965 " beginning at %L as INTENT(INOUT) argument to"
1966 " function %qs", do_sym->name,
1967 &a->expr->where, &doloop_list[i]->loc,
1968 expr->symtree->n.sym->name);
1969 }
1970 }
1971 a = a->next;
1972 f = f->next;
1973 }
1974
1975 return 0;
1976 }
1977
1978 static void
1979 doloop_warn (gfc_namespace *ns)
1980 {
1981 gfc_code_walker (&ns->code, doloop_code, do_function, NULL);
1982 }
1983
1984 /* This selction deals with inlining calls to MATMUL. */
1985
1986 /* Auxiliary function to build and simplify an array inquiry function.
1987 dim is zero-based. */
1988
1989 static gfc_expr *
1990 get_array_inq_function (gfc_isym_id id, gfc_expr *e, int dim)
1991 {
1992 gfc_expr *fcn;
1993 gfc_expr *dim_arg, *kind;
1994 const char *name;
1995 gfc_expr *ec;
1996
1997 switch (id)
1998 {
1999 case GFC_ISYM_LBOUND:
2000 name = "_gfortran_lbound";
2001 break;
2002
2003 case GFC_ISYM_UBOUND:
2004 name = "_gfortran_ubound";
2005 break;
2006
2007 case GFC_ISYM_SIZE:
2008 name = "_gfortran_size";
2009 break;
2010
2011 default:
2012 gcc_unreachable ();
2013 }
2014
2015 dim_arg = gfc_get_int_expr (gfc_default_integer_kind, &e->where, dim);
2016 kind = gfc_get_int_expr (gfc_default_integer_kind, &e->where,
2017 gfc_index_integer_kind);
2018
2019 ec = gfc_copy_expr (e);
2020 fcn = gfc_build_intrinsic_call (current_ns, id, name, e->where, 3,
2021 ec, dim_arg, kind);
2022 gfc_simplify_expr (fcn, 0);
2023 return fcn;
2024 }
2025
2026 /* Builds a logical expression. */
2027
2028 static gfc_expr*
2029 build_logical_expr (gfc_intrinsic_op op, gfc_expr *e1, gfc_expr *e2)
2030 {
2031 gfc_typespec ts;
2032 gfc_expr *res;
2033
2034 ts.type = BT_LOGICAL;
2035 ts.kind = gfc_default_logical_kind;
2036 res = gfc_get_expr ();
2037 res->where = e1->where;
2038 res->expr_type = EXPR_OP;
2039 res->value.op.op = op;
2040 res->value.op.op1 = e1;
2041 res->value.op.op2 = e2;
2042 res->ts = ts;
2043
2044 return res;
2045 }
2046
2047
2048 /* Return an operation of one two gfc_expr (one if e2 is NULL). This assumes
2049 compatible typespecs. */
2050
2051 static gfc_expr *
2052 get_operand (gfc_intrinsic_op op, gfc_expr *e1, gfc_expr *e2)
2053 {
2054 gfc_expr *res;
2055
2056 res = gfc_get_expr ();
2057 res->ts = e1->ts;
2058 res->where = e1->where;
2059 res->expr_type = EXPR_OP;
2060 res->value.op.op = op;
2061 res->value.op.op1 = e1;
2062 res->value.op.op2 = e2;
2063 gfc_simplify_expr (res, 0);
2064 return res;
2065 }
2066
2067 /* Generate the IF statement for a runtime check if we want to do inlining or
2068 not - putting in the code for both branches and putting it into the syntax
2069 tree is the caller's responsibility. For fixed array sizes, this should be
2070 removed by DCE. Only called for rank-two matrices A and B. */
2071
2072 static gfc_code *
2073 inline_limit_check (gfc_expr *a, gfc_expr *b, enum matrix_case m_case)
2074 {
2075 gfc_expr *inline_limit;
2076 gfc_code *if_1, *if_2, *else_2;
2077 gfc_expr *b2, *a2, *a1, *m1, *m2;
2078 gfc_typespec ts;
2079 gfc_expr *cond;
2080
2081 gcc_assert (m_case == A2B2);
2082
2083 /* Calculation is done in real to avoid integer overflow. */
2084
2085 inline_limit = gfc_get_constant_expr (BT_REAL, gfc_default_real_kind,
2086 &a->where);
2087 mpfr_set_si (inline_limit->value.real, flag_inline_matmul_limit,
2088 GFC_RND_MODE);
2089 mpfr_pow_ui (inline_limit->value.real, inline_limit->value.real, 3,
2090 GFC_RND_MODE);
2091
2092 a1 = get_array_inq_function (GFC_ISYM_SIZE, a, 1);
2093 a2 = get_array_inq_function (GFC_ISYM_SIZE, a, 2);
2094 b2 = get_array_inq_function (GFC_ISYM_SIZE, b, 2);
2095
2096 gfc_clear_ts (&ts);
2097 ts.type = BT_REAL;
2098 ts.kind = gfc_default_real_kind;
2099 gfc_convert_type_warn (a1, &ts, 2, 0);
2100 gfc_convert_type_warn (a2, &ts, 2, 0);
2101 gfc_convert_type_warn (b2, &ts, 2, 0);
2102
2103 m1 = get_operand (INTRINSIC_TIMES, a1, a2);
2104 m2 = get_operand (INTRINSIC_TIMES, m1, b2);
2105
2106 cond = build_logical_expr (INTRINSIC_LE, m2, inline_limit);
2107 gfc_simplify_expr (cond, 0);
2108
2109 else_2 = XCNEW (gfc_code);
2110 else_2->op = EXEC_IF;
2111 else_2->loc = a->where;
2112
2113 if_2 = XCNEW (gfc_code);
2114 if_2->op = EXEC_IF;
2115 if_2->expr1 = cond;
2116 if_2->loc = a->where;
2117 if_2->block = else_2;
2118
2119 if_1 = XCNEW (gfc_code);
2120 if_1->op = EXEC_IF;
2121 if_1->block = if_2;
2122 if_1->loc = a->where;
2123
2124 return if_1;
2125 }
2126
2127
2128 /* Insert code to issue a runtime error if the expressions are not equal. */
2129
2130 static gfc_code *
2131 runtime_error_ne (gfc_expr *e1, gfc_expr *e2, const char *msg)
2132 {
2133 gfc_expr *cond;
2134 gfc_code *if_1, *if_2;
2135 gfc_code *c;
2136 gfc_actual_arglist *a1, *a2, *a3;
2137
2138 gcc_assert (e1->where.lb);
2139 /* Build the call to runtime_error. */
2140 c = XCNEW (gfc_code);
2141 c->op = EXEC_CALL;
2142 c->loc = e1->where;
2143
2144 /* Get a null-terminated message string. */
2145
2146 a1 = gfc_get_actual_arglist ();
2147 a1->expr = gfc_get_character_expr (gfc_default_character_kind, &e1->where,
2148 msg, strlen(msg)+1);
2149 c->ext.actual = a1;
2150
2151 /* Pass the value of the first expression. */
2152 a2 = gfc_get_actual_arglist ();
2153 a2->expr = gfc_copy_expr (e1);
2154 a1->next = a2;
2155
2156 /* Pass the value of the second expression. */
2157 a3 = gfc_get_actual_arglist ();
2158 a3->expr = gfc_copy_expr (e2);
2159 a2->next = a3;
2160
2161 gfc_check_fe_runtime_error (c->ext.actual);
2162 gfc_resolve_fe_runtime_error (c);
2163
2164 if_2 = XCNEW (gfc_code);
2165 if_2->op = EXEC_IF;
2166 if_2->loc = e1->where;
2167 if_2->next = c;
2168
2169 if_1 = XCNEW (gfc_code);
2170 if_1->op = EXEC_IF;
2171 if_1->block = if_2;
2172 if_1->loc = e1->where;
2173
2174 cond = build_logical_expr (INTRINSIC_NE, e1, e2);
2175 gfc_simplify_expr (cond, 0);
2176 if_2->expr1 = cond;
2177
2178 return if_1;
2179 }
2180
2181 /* Handle matrix reallocation. Caller is responsible to insert into
2182 the code tree.
2183
2184 For the two-dimensional case, build
2185
2186 if (allocated(c)) then
2187 if (size(c,1) /= size(a,1) .or. size(c,2) /= size(b,2)) then
2188 deallocate(c)
2189 allocate (c(size(a,1), size(b,2)))
2190 end if
2191 else
2192 allocate (c(size(a,1),size(b,2)))
2193 end if
2194
2195 and for the other cases correspondingly.
2196 */
2197
2198 static gfc_code *
2199 matmul_lhs_realloc (gfc_expr *c, gfc_expr *a, gfc_expr *b,
2200 enum matrix_case m_case)
2201 {
2202
2203 gfc_expr *allocated, *alloc_expr;
2204 gfc_code *if_alloc_1, *if_alloc_2, *if_size_1, *if_size_2;
2205 gfc_code *else_alloc;
2206 gfc_code *deallocate, *allocate1, *allocate_else;
2207 gfc_array_ref *ar;
2208 gfc_expr *cond, *ne1, *ne2;
2209
2210 if (warn_realloc_lhs)
2211 gfc_warning (OPT_Wrealloc_lhs,
2212 "Code for reallocating the allocatable array at %L will "
2213 "be added", &c->where);
2214
2215 alloc_expr = gfc_copy_expr (c);
2216
2217 ar = gfc_find_array_ref (alloc_expr);
2218 gcc_assert (ar && ar->type == AR_FULL);
2219
2220 /* c comes in as a full ref. Change it into a copy and make it into an
2221 element ref so it has the right form for for ALLOCATE. In the same
2222 switch statement, also generate the size comparison for the secod IF
2223 statement. */
2224
2225 ar->type = AR_ELEMENT;
2226
2227 switch (m_case)
2228 {
2229 case A2B2:
2230 ar->start[0] = get_array_inq_function (GFC_ISYM_SIZE, a, 1);
2231 ar->start[1] = get_array_inq_function (GFC_ISYM_SIZE, b, 2);
2232 ne1 = build_logical_expr (INTRINSIC_NE,
2233 get_array_inq_function (GFC_ISYM_SIZE, c, 1),
2234 get_array_inq_function (GFC_ISYM_SIZE, a, 1));
2235 ne2 = build_logical_expr (INTRINSIC_NE,
2236 get_array_inq_function (GFC_ISYM_SIZE, c, 2),
2237 get_array_inq_function (GFC_ISYM_SIZE, b, 2));
2238 cond = build_logical_expr (INTRINSIC_OR, ne1, ne2);
2239 break;
2240
2241 case A2B1:
2242 ar->start[0] = get_array_inq_function (GFC_ISYM_SIZE, a, 1);
2243 cond = build_logical_expr (INTRINSIC_NE,
2244 get_array_inq_function (GFC_ISYM_SIZE, c, 1),
2245 get_array_inq_function (GFC_ISYM_SIZE, a, 2));
2246 break;
2247
2248 case A1B2:
2249 ar->start[0] = get_array_inq_function (GFC_ISYM_SIZE, b, 1);
2250 cond = build_logical_expr (INTRINSIC_NE,
2251 get_array_inq_function (GFC_ISYM_SIZE, c, 1),
2252 get_array_inq_function (GFC_ISYM_SIZE, b, 2));
2253 break;
2254
2255 default:
2256 gcc_unreachable();
2257
2258 }
2259
2260 gfc_simplify_expr (cond, 0);
2261
2262 /* We need two identical allocate statements in two
2263 branches of the IF statement. */
2264
2265 allocate1 = XCNEW (gfc_code);
2266 allocate1->op = EXEC_ALLOCATE;
2267 allocate1->ext.alloc.list = gfc_get_alloc ();
2268 allocate1->loc = c->where;
2269 allocate1->ext.alloc.list->expr = gfc_copy_expr (alloc_expr);
2270
2271 allocate_else = XCNEW (gfc_code);
2272 allocate_else->op = EXEC_ALLOCATE;
2273 allocate_else->ext.alloc.list = gfc_get_alloc ();
2274 allocate_else->loc = c->where;
2275 allocate_else->ext.alloc.list->expr = alloc_expr;
2276
2277 allocated = gfc_build_intrinsic_call (current_ns, GFC_ISYM_ALLOCATED,
2278 "_gfortran_allocated", c->where,
2279 1, gfc_copy_expr (c));
2280
2281 deallocate = XCNEW (gfc_code);
2282 deallocate->op = EXEC_DEALLOCATE;
2283 deallocate->ext.alloc.list = gfc_get_alloc ();
2284 deallocate->ext.alloc.list->expr = gfc_copy_expr (c);
2285 deallocate->next = allocate1;
2286 deallocate->loc = c->where;
2287
2288 if_size_2 = XCNEW (gfc_code);
2289 if_size_2->op = EXEC_IF;
2290 if_size_2->expr1 = cond;
2291 if_size_2->loc = c->where;
2292 if_size_2->next = deallocate;
2293
2294 if_size_1 = XCNEW (gfc_code);
2295 if_size_1->op = EXEC_IF;
2296 if_size_1->block = if_size_2;
2297 if_size_1->loc = c->where;
2298
2299 else_alloc = XCNEW (gfc_code);
2300 else_alloc->op = EXEC_IF;
2301 else_alloc->loc = c->where;
2302 else_alloc->next = allocate_else;
2303
2304 if_alloc_2 = XCNEW (gfc_code);
2305 if_alloc_2->op = EXEC_IF;
2306 if_alloc_2->expr1 = allocated;
2307 if_alloc_2->loc = c->where;
2308 if_alloc_2->next = if_size_1;
2309 if_alloc_2->block = else_alloc;
2310
2311 if_alloc_1 = XCNEW (gfc_code);
2312 if_alloc_1->op = EXEC_IF;
2313 if_alloc_1->block = if_alloc_2;
2314 if_alloc_1->loc = c->where;
2315
2316 return if_alloc_1;
2317 }
2318
2319 /* Callback function for has_function_or_op. */
2320
2321 static int
2322 is_function_or_op (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
2323 void *data ATTRIBUTE_UNUSED)
2324 {
2325 if ((*e) == 0)
2326 return 0;
2327 else
2328 return (*e)->expr_type == EXPR_FUNCTION
2329 || (*e)->expr_type == EXPR_OP;
2330 }
2331
2332 /* Returns true if the expression contains a function. */
2333
2334 static bool
2335 has_function_or_op (gfc_expr **e)
2336 {
2337 if (e == NULL)
2338 return false;
2339 else
2340 return gfc_expr_walker (e, is_function_or_op, NULL);
2341 }
2342
2343 /* Freeze (assign to a temporary variable) a single expression. */
2344
2345 static void
2346 freeze_expr (gfc_expr **ep)
2347 {
2348 gfc_expr *ne;
2349 if (has_function_or_op (ep))
2350 {
2351 ne = create_var (*ep, "freeze");
2352 *ep = ne;
2353 }
2354 }
2355
2356 /* Go through an expression's references and assign them to temporary
2357 variables if they contain functions. This is usually done prior to
2358 front-end scalarization to avoid multiple invocations of functions. */
2359
2360 static void
2361 freeze_references (gfc_expr *e)
2362 {
2363 gfc_ref *r;
2364 gfc_array_ref *ar;
2365 int i;
2366
2367 for (r=e->ref; r; r=r->next)
2368 {
2369 if (r->type == REF_SUBSTRING)
2370 {
2371 if (r->u.ss.start != NULL)
2372 freeze_expr (&r->u.ss.start);
2373
2374 if (r->u.ss.end != NULL)
2375 freeze_expr (&r->u.ss.end);
2376 }
2377 else if (r->type == REF_ARRAY)
2378 {
2379 ar = &r->u.ar;
2380 switch (ar->type)
2381 {
2382 case AR_FULL:
2383 break;
2384
2385 case AR_SECTION:
2386 for (i=0; i<ar->dimen; i++)
2387 {
2388 if (ar->dimen_type[i] == DIMEN_RANGE)
2389 {
2390 freeze_expr (&ar->start[i]);
2391 freeze_expr (&ar->end[i]);
2392 freeze_expr (&ar->stride[i]);
2393 }
2394 else if (ar->dimen_type[i] == DIMEN_ELEMENT)
2395 {
2396 freeze_expr (&ar->start[i]);
2397 }
2398 }
2399 break;
2400
2401 case AR_ELEMENT:
2402 for (i=0; i<ar->dimen; i++)
2403 freeze_expr (&ar->start[i]);
2404 break;
2405
2406 default:
2407 break;
2408 }
2409 }
2410 }
2411 }
2412
2413 /* Convert to gfc_index_integer_kind if needed, just do a copy otherwise. */
2414
2415 static gfc_expr *
2416 convert_to_index_kind (gfc_expr *e)
2417 {
2418 gfc_expr *res;
2419
2420 gcc_assert (e != NULL);
2421
2422 res = gfc_copy_expr (e);
2423
2424 gcc_assert (e->ts.type == BT_INTEGER);
2425
2426 if (res->ts.kind != gfc_index_integer_kind)
2427 {
2428 gfc_typespec ts;
2429 gfc_clear_ts (&ts);
2430 ts.type = BT_INTEGER;
2431 ts.kind = gfc_index_integer_kind;
2432
2433 gfc_convert_type_warn (e, &ts, 2, 0);
2434 }
2435
2436 return res;
2437 }
2438
2439 /* Function to create a DO loop including creation of the
2440 iteration variable. gfc_expr are copied.*/
2441
2442 static gfc_code *
2443 create_do_loop (gfc_expr *start, gfc_expr *end, gfc_expr *step, locus *where,
2444 gfc_namespace *ns, char *vname)
2445 {
2446
2447 char name[GFC_MAX_SYMBOL_LEN +1];
2448 gfc_symtree *symtree;
2449 gfc_symbol *symbol;
2450 gfc_expr *i;
2451 gfc_code *n, *n2;
2452
2453 /* Create an expression for the iteration variable. */
2454 if (vname)
2455 sprintf (name, "__var_%d_do_%s", var_num++, vname);
2456 else
2457 sprintf (name, "__var_%d_do", var_num++);
2458
2459
2460 if (gfc_get_sym_tree (name, ns, &symtree, false) != 0)
2461 gcc_unreachable ();
2462
2463 /* Create the loop variable. */
2464
2465 symbol = symtree->n.sym;
2466 symbol->ts.type = BT_INTEGER;
2467 symbol->ts.kind = gfc_index_integer_kind;
2468 symbol->attr.flavor = FL_VARIABLE;
2469 symbol->attr.referenced = 1;
2470 symbol->attr.dimension = 0;
2471 symbol->attr.fe_temp = 1;
2472 gfc_commit_symbol (symbol);
2473
2474 i = gfc_get_expr ();
2475 i->expr_type = EXPR_VARIABLE;
2476 i->ts = symbol->ts;
2477 i->rank = 0;
2478 i->where = *where;
2479 i->symtree = symtree;
2480
2481 /* ... and the nested DO statements. */
2482 n = XCNEW (gfc_code);
2483 n->op = EXEC_DO;
2484 n->loc = *where;
2485 n->ext.iterator = gfc_get_iterator ();
2486 n->ext.iterator->var = i;
2487 n->ext.iterator->start = convert_to_index_kind (start);
2488 n->ext.iterator->end = convert_to_index_kind (end);
2489 if (step)
2490 n->ext.iterator->step = convert_to_index_kind (step);
2491 else
2492 n->ext.iterator->step = gfc_get_int_expr (gfc_index_integer_kind,
2493 where, 1);
2494
2495 n2 = XCNEW (gfc_code);
2496 n2->op = EXEC_DO;
2497 n2->loc = *where;
2498 n2->next = NULL;
2499 n->block = n2;
2500 return n;
2501 }
2502
2503 /* Get the upper bound of the DO loops for matmul along a dimension. This
2504 is one-based. */
2505
2506 static gfc_expr*
2507 get_size_m1 (gfc_expr *e, int dimen)
2508 {
2509 mpz_t size;
2510 gfc_expr *res;
2511
2512 if (gfc_array_dimen_size (e, dimen - 1, &size))
2513 {
2514 res = gfc_get_constant_expr (BT_INTEGER,
2515 gfc_index_integer_kind, &e->where);
2516 mpz_sub_ui (res->value.integer, size, 1);
2517 mpz_clear (size);
2518 }
2519 else
2520 {
2521 res = get_operand (INTRINSIC_MINUS,
2522 get_array_inq_function (GFC_ISYM_SIZE, e, dimen),
2523 gfc_get_int_expr (gfc_index_integer_kind,
2524 &e->where, 1));
2525 gfc_simplify_expr (res, 0);
2526 }
2527
2528 return res;
2529 }
2530
2531 /* Function to return a scalarized expression. It is assumed that indices are
2532 zero based to make generation of DO loops easier. A zero as index will
2533 access the first element along a dimension. Single element references will
2534 be skipped. A NULL as an expression will be replaced by a full reference.
2535 This assumes that the index loops have gfc_index_integer_kind, and that all
2536 references have been frozen. */
2537
2538 static gfc_expr*
2539 scalarized_expr (gfc_expr *e_in, gfc_expr **index, int count_index)
2540 {
2541 gfc_array_ref *ar;
2542 int i;
2543 int rank;
2544 gfc_expr *e;
2545 int i_index;
2546 bool was_fullref;
2547
2548 e = gfc_copy_expr(e_in);
2549
2550 rank = e->rank;
2551
2552 ar = gfc_find_array_ref (e);
2553
2554 /* We scalarize count_index variables, reducing the rank by count_index. */
2555
2556 e->rank = rank - count_index;
2557
2558 was_fullref = ar->type == AR_FULL;
2559
2560 if (e->rank == 0)
2561 ar->type = AR_ELEMENT;
2562 else
2563 ar->type = AR_SECTION;
2564
2565 /* Loop over the indices. For each index, create the expression
2566 index * stride + lbound(e, dim). */
2567
2568 i_index = 0;
2569 for (i=0; i < ar->dimen; i++)
2570 {
2571 if (was_fullref || ar->dimen_type[i] == DIMEN_RANGE)
2572 {
2573 if (index[i_index] != NULL)
2574 {
2575 gfc_expr *lbound, *nindex;
2576 gfc_expr *loopvar;
2577
2578 loopvar = gfc_copy_expr (index[i_index]);
2579
2580 if (ar->stride[i])
2581 {
2582 gfc_expr *tmp;
2583
2584 tmp = gfc_copy_expr(ar->stride[i]);
2585 if (tmp->ts.kind != gfc_index_integer_kind)
2586 {
2587 gfc_typespec ts;
2588 gfc_clear_ts (&ts);
2589 ts.type = BT_INTEGER;
2590 ts.kind = gfc_index_integer_kind;
2591 gfc_convert_type (tmp, &ts, 2);
2592 }
2593 nindex = get_operand (INTRINSIC_TIMES, loopvar, tmp);
2594 }
2595 else
2596 nindex = loopvar;
2597
2598 /* Calculate the lower bound of the expression. */
2599 if (ar->start[i])
2600 {
2601 lbound = gfc_copy_expr (ar->start[i]);
2602 if (lbound->ts.kind != gfc_index_integer_kind)
2603 {
2604 gfc_typespec ts;
2605 gfc_clear_ts (&ts);
2606 ts.type = BT_INTEGER;
2607 ts.kind = gfc_index_integer_kind;
2608 gfc_convert_type (lbound, &ts, 2);
2609
2610 }
2611 }
2612 else
2613 {
2614 gfc_expr *lbound_e;
2615 gfc_ref *ref;
2616
2617 lbound_e = gfc_copy_expr (e_in);
2618
2619 for (ref = lbound_e->ref; ref; ref = ref->next)
2620 if (ref->type == REF_ARRAY
2621 && (ref->u.ar.type == AR_FULL
2622 || ref->u.ar.type == AR_SECTION))
2623 break;
2624
2625 if (ref->next)
2626 {
2627 gfc_free_ref_list (ref->next);
2628 ref->next = NULL;
2629 }
2630
2631 if (!was_fullref)
2632 {
2633 /* Look at full individual sections, like a(:). The first index
2634 is the lbound of a full ref. */
2635 int j;
2636 gfc_array_ref *ar;
2637
2638 ar = &ref->u.ar;
2639 ar->type = AR_FULL;
2640 for (j = 0; j < ar->dimen; j++)
2641 {
2642 gfc_free_expr (ar->start[j]);
2643 ar->start[j] = NULL;
2644 gfc_free_expr (ar->end[j]);
2645 ar->end[j] = NULL;
2646 gfc_free_expr (ar->stride[j]);
2647 ar->stride[j] = NULL;
2648 }
2649
2650 /* We have to get rid of the shape, if there is one. Do
2651 so by freeing it and calling gfc_resolve to rebuild
2652 it, if necessary. */
2653
2654 if (lbound_e->shape)
2655 gfc_free_shape (&(lbound_e->shape), lbound_e->rank);
2656
2657 lbound_e->rank = ar->dimen;
2658 gfc_resolve_expr (lbound_e);
2659 }
2660 lbound = get_array_inq_function (GFC_ISYM_LBOUND, lbound_e,
2661 i + 1);
2662 gfc_free_expr (lbound_e);
2663 }
2664
2665 ar->dimen_type[i] = DIMEN_ELEMENT;
2666
2667 gfc_free_expr (ar->start[i]);
2668 ar->start[i] = get_operand (INTRINSIC_PLUS, nindex, lbound);
2669
2670 gfc_free_expr (ar->end[i]);
2671 ar->end[i] = NULL;
2672 gfc_free_expr (ar->stride[i]);
2673 ar->stride[i] = NULL;
2674 gfc_simplify_expr (ar->start[i], 0);
2675 }
2676 else if (was_fullref)
2677 {
2678 gfc_internal_error ("Scalarization using DIMEN_RANGE unimplemented");
2679 }
2680 i_index ++;
2681 }
2682 }
2683
2684 return e;
2685 }
2686
2687 /* Helper function to check for a dimen vector as subscript. */
2688
2689 static bool
2690 has_dimen_vector_ref (gfc_expr *e)
2691 {
2692 gfc_array_ref *ar;
2693 int i;
2694
2695 ar = gfc_find_array_ref (e);
2696 gcc_assert (ar);
2697 if (ar->type == AR_FULL)
2698 return false;
2699
2700 for (i=0; i<ar->dimen; i++)
2701 if (ar->dimen_type[i] == DIMEN_VECTOR)
2702 return true;
2703
2704 return false;
2705 }
2706
2707 /* If handed an expression of the form
2708
2709 CONJG(A)
2710
2711 check if A can be handled by matmul and return if there is an uneven number
2712 of CONJG calls. Return a pointer to the array when everything is OK, NULL
2713 otherwise. The caller has to check for the correct rank. */
2714
2715 static gfc_expr*
2716 check_conjg_variable (gfc_expr *e, bool *conjg)
2717 {
2718 *conjg = false;
2719
2720 do
2721 {
2722 if (e->expr_type == EXPR_VARIABLE)
2723 {
2724 gcc_assert (e->rank == 1 || e->rank == 2);
2725 return e;
2726 }
2727 else if (e->expr_type == EXPR_FUNCTION)
2728 {
2729 if (e->value.function.isym == NULL)
2730 return NULL;
2731
2732 if (e->value.function.isym->id == GFC_ISYM_CONJG)
2733 *conjg = !*conjg;
2734 else return NULL;
2735 }
2736 else
2737 return NULL;
2738
2739 e = e->value.function.actual->expr;
2740 }
2741 while(1);
2742
2743 return NULL;
2744 }
2745
2746 /* Inline assignments of the form c = matmul(a,b).
2747 Handle only the cases currently where b and c are rank-two arrays.
2748
2749 This basically translates the code to
2750
2751 BLOCK
2752 integer i,j,k
2753 c = 0
2754 do j=0, size(b,2)-1
2755 do k=0, size(a, 2)-1
2756 do i=0, size(a, 1)-1
2757 c(i * stride(c,1) + lbound(c,1), j * stride(c,2) + lbound(c,2)) =
2758 c(i * stride(c,1) + lbound(c,1), j * stride(c,2) + lbound(c,2)) +
2759 a(i * stride(a,1) + lbound(a,1), k * stride(a,2) + lbound(a,2)) *
2760 b(k * stride(b,1) + lbound(b,1), j * stride(b,2) + lbound(b,2))
2761 end do
2762 end do
2763 end do
2764 END BLOCK
2765
2766 */
2767
2768 static int
2769 inline_matmul_assign (gfc_code **c, int *walk_subtrees,
2770 void *data ATTRIBUTE_UNUSED)
2771 {
2772 gfc_code *co = *c;
2773 gfc_expr *expr1, *expr2;
2774 gfc_expr *matrix_a, *matrix_b;
2775 gfc_actual_arglist *a, *b;
2776 gfc_code *do_1, *do_2, *do_3, *assign_zero, *assign_matmul;
2777 gfc_expr *zero_e;
2778 gfc_expr *u1, *u2, *u3;
2779 gfc_expr *list[2];
2780 gfc_expr *ascalar, *bscalar, *cscalar;
2781 gfc_expr *mult;
2782 gfc_expr *var_1, *var_2, *var_3;
2783 gfc_expr *zero;
2784 gfc_namespace *ns;
2785 gfc_intrinsic_op op_times, op_plus;
2786 enum matrix_case m_case;
2787 int i;
2788 gfc_code *if_limit = NULL;
2789 gfc_code **next_code_point;
2790 bool conjg_a, conjg_b;
2791
2792 if (co->op != EXEC_ASSIGN)
2793 return 0;
2794
2795 expr1 = co->expr1;
2796 expr2 = co->expr2;
2797 if (expr2->expr_type != EXPR_FUNCTION
2798 || expr2->value.function.isym == NULL
2799 || expr2->value.function.isym->id != GFC_ISYM_MATMUL)
2800 return 0;
2801
2802 current_code = c;
2803 inserted_block = NULL;
2804 changed_statement = NULL;
2805
2806 a = expr2->value.function.actual;
2807 matrix_a = check_conjg_variable (a->expr, &conjg_a);
2808 if (matrix_a == NULL)
2809 return 0;
2810
2811 b = a->next;
2812 matrix_b = check_conjg_variable (b->expr, &conjg_b);
2813 if (matrix_b == NULL)
2814 return 0;
2815
2816 if (has_dimen_vector_ref (expr1) || has_dimen_vector_ref (matrix_a)
2817 || has_dimen_vector_ref (matrix_b))
2818 return 0;
2819
2820 /* We do not handle data dependencies yet. */
2821 if (gfc_check_dependency (expr1, matrix_a, true)
2822 || gfc_check_dependency (expr1, matrix_b, true))
2823 return 0;
2824
2825 if (matrix_a->rank == 2)
2826 m_case = matrix_b->rank == 1 ? A2B1 : A2B2;
2827 else
2828 m_case = A1B2;
2829
2830
2831 ns = insert_block ();
2832
2833 /* Assign the type of the zero expression for initializing the resulting
2834 array, and the expression (+ and * for real, integer and complex;
2835 .and. and .or for logical. */
2836
2837 switch(expr1->ts.type)
2838 {
2839 case BT_INTEGER:
2840 zero_e = gfc_get_int_expr (expr1->ts.kind, &expr1->where, 0);
2841 op_times = INTRINSIC_TIMES;
2842 op_plus = INTRINSIC_PLUS;
2843 break;
2844
2845 case BT_LOGICAL:
2846 op_times = INTRINSIC_AND;
2847 op_plus = INTRINSIC_OR;
2848 zero_e = gfc_get_logical_expr (expr1->ts.kind, &expr1->where,
2849 0);
2850 break;
2851 case BT_REAL:
2852 zero_e = gfc_get_constant_expr (BT_REAL, expr1->ts.kind,
2853 &expr1->where);
2854 mpfr_set_si (zero_e->value.real, 0, GFC_RND_MODE);
2855 op_times = INTRINSIC_TIMES;
2856 op_plus = INTRINSIC_PLUS;
2857 break;
2858
2859 case BT_COMPLEX:
2860 zero_e = gfc_get_constant_expr (BT_COMPLEX, expr1->ts.kind,
2861 &expr1->where);
2862 mpc_set_si_si (zero_e->value.complex, 0, 0, GFC_RND_MODE);
2863 op_times = INTRINSIC_TIMES;
2864 op_plus = INTRINSIC_PLUS;
2865
2866 break;
2867
2868 default:
2869 gcc_unreachable();
2870 }
2871
2872 current_code = &ns->code;
2873
2874 /* Freeze the references, keeping track of how many temporary variables were
2875 created. */
2876 n_vars = 0;
2877 freeze_references (matrix_a);
2878 freeze_references (matrix_b);
2879 freeze_references (expr1);
2880
2881 if (n_vars == 0)
2882 next_code_point = current_code;
2883 else
2884 {
2885 next_code_point = &ns->code;
2886 for (i=0; i<n_vars; i++)
2887 next_code_point = &(*next_code_point)->next;
2888 }
2889
2890 /* Take care of the inline flag. If the limit check evaluates to a
2891 constant, dead code elimination will eliminate the unneeded branch. */
2892
2893 if (m_case == A2B2 && flag_inline_matmul_limit > 0)
2894 {
2895 if_limit = inline_limit_check (matrix_a, matrix_b, m_case);
2896
2897 /* Insert the original statement into the else branch. */
2898 if_limit->block->block->next = co;
2899 co->next = NULL;
2900
2901 /* ... and the new ones go into the original one. */
2902 *next_code_point = if_limit;
2903 next_code_point = &if_limit->block->next;
2904 }
2905
2906 assign_zero = XCNEW (gfc_code);
2907 assign_zero->op = EXEC_ASSIGN;
2908 assign_zero->loc = co->loc;
2909 assign_zero->expr1 = gfc_copy_expr (expr1);
2910 assign_zero->expr2 = zero_e;
2911
2912 /* Handle the reallocation, if needed. */
2913 if (flag_realloc_lhs && gfc_is_reallocatable_lhs (expr1))
2914 {
2915 gfc_code *lhs_alloc;
2916
2917 /* Only need to check a single dimension for the A2B2 case for
2918 bounds checking, the rest will be allocated. */
2919
2920 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS && m_case == A2B2)
2921 {
2922 gfc_code *test;
2923 gfc_expr *a2, *b1;
2924
2925 a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2);
2926 b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1);
2927 test = runtime_error_ne (b1, a2, "Dimension of array B incorrect "
2928 "in MATMUL intrinsic: Is %ld, should be %ld");
2929 *next_code_point = test;
2930 next_code_point = &test->next;
2931 }
2932
2933
2934 lhs_alloc = matmul_lhs_realloc (expr1, matrix_a, matrix_b, m_case);
2935
2936 *next_code_point = lhs_alloc;
2937 next_code_point = &lhs_alloc->next;
2938
2939 }
2940 else if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
2941 {
2942 gfc_code *test;
2943 gfc_expr *a2, *b1, *c1, *c2, *a1, *b2;
2944
2945 if (m_case == A2B2 || m_case == A2B1)
2946 {
2947 a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2);
2948 b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1);
2949 test = runtime_error_ne (b1, a2, "Dimension of array B incorrect "
2950 "in MATMUL intrinsic: Is %ld, should be %ld");
2951 *next_code_point = test;
2952 next_code_point = &test->next;
2953
2954 c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1);
2955 a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1);
2956
2957 if (m_case == A2B2)
2958 test = runtime_error_ne (c1, a1, "Incorrect extent in return array in "
2959 "MATMUL intrinsic for dimension 1: "
2960 "is %ld, should be %ld");
2961 else if (m_case == A2B1)
2962 test = runtime_error_ne (c1, a1, "Incorrect extent in return array in "
2963 "MATMUL intrinsic: "
2964 "is %ld, should be %ld");
2965
2966
2967 *next_code_point = test;
2968 next_code_point = &test->next;
2969 }
2970 else if (m_case == A1B2)
2971 {
2972 a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1);
2973 b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1);
2974 test = runtime_error_ne (b1, a1, "Dimension of array B incorrect "
2975 "in MATMUL intrinsic: Is %ld, should be %ld");
2976 *next_code_point = test;
2977 next_code_point = &test->next;
2978
2979 c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1);
2980 b2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 2);
2981
2982 test = runtime_error_ne (c1, b2, "Incorrect extent in return array in "
2983 "MATMUL intrinsic: "
2984 "is %ld, should be %ld");
2985
2986 *next_code_point = test;
2987 next_code_point = &test->next;
2988 }
2989
2990 if (m_case == A2B2)
2991 {
2992 c2 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 2);
2993 b2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 2);
2994 test = runtime_error_ne (c2, b2, "Incorrect extent in return array in "
2995 "MATMUL intrinsic for dimension 2: is %ld, should be %ld");
2996
2997 *next_code_point = test;
2998 next_code_point = &test->next;
2999 }
3000 }
3001
3002 *next_code_point = assign_zero;
3003
3004 zero = gfc_get_int_expr (gfc_index_integer_kind, &co->loc, 0);
3005
3006 assign_matmul = XCNEW (gfc_code);
3007 assign_matmul->op = EXEC_ASSIGN;
3008 assign_matmul->loc = co->loc;
3009
3010 /* Get the bounds for the loops, create them and create the scalarized
3011 expressions. */
3012
3013 switch (m_case)
3014 {
3015 case A2B2:
3016 inline_limit_check (matrix_a, matrix_b, m_case);
3017
3018 u1 = get_size_m1 (matrix_b, 2);
3019 u2 = get_size_m1 (matrix_a, 2);
3020 u3 = get_size_m1 (matrix_a, 1);
3021
3022 do_1 = create_do_loop (gfc_copy_expr (zero), u1, NULL, &co->loc, ns);
3023 do_2 = create_do_loop (gfc_copy_expr (zero), u2, NULL, &co->loc, ns);
3024 do_3 = create_do_loop (gfc_copy_expr (zero), u3, NULL, &co->loc, ns);
3025
3026 do_1->block->next = do_2;
3027 do_2->block->next = do_3;
3028 do_3->block->next = assign_matmul;
3029
3030 var_1 = do_1->ext.iterator->var;
3031 var_2 = do_2->ext.iterator->var;
3032 var_3 = do_3->ext.iterator->var;
3033
3034 list[0] = var_3;
3035 list[1] = var_1;
3036 cscalar = scalarized_expr (co->expr1, list, 2);
3037
3038 list[0] = var_3;
3039 list[1] = var_2;
3040 ascalar = scalarized_expr (matrix_a, list, 2);
3041
3042 list[0] = var_2;
3043 list[1] = var_1;
3044 bscalar = scalarized_expr (matrix_b, list, 2);
3045
3046 break;
3047
3048 case A2B1:
3049 u1 = get_size_m1 (matrix_b, 1);
3050 u2 = get_size_m1 (matrix_a, 1);
3051
3052 do_1 = create_do_loop (gfc_copy_expr (zero), u1, NULL, &co->loc, ns);
3053 do_2 = create_do_loop (gfc_copy_expr (zero), u2, NULL, &co->loc, ns);
3054
3055 do_1->block->next = do_2;
3056 do_2->block->next = assign_matmul;
3057
3058 var_1 = do_1->ext.iterator->var;
3059 var_2 = do_2->ext.iterator->var;
3060
3061 list[0] = var_2;
3062 cscalar = scalarized_expr (co->expr1, list, 1);
3063
3064 list[0] = var_2;
3065 list[1] = var_1;
3066 ascalar = scalarized_expr (matrix_a, list, 2);
3067
3068 list[0] = var_1;
3069 bscalar = scalarized_expr (matrix_b, list, 1);
3070
3071 break;
3072
3073 case A1B2:
3074 u1 = get_size_m1 (matrix_b, 2);
3075 u2 = get_size_m1 (matrix_a, 1);
3076
3077 do_1 = create_do_loop (gfc_copy_expr (zero), u1, NULL, &co->loc, ns);
3078 do_2 = create_do_loop (gfc_copy_expr (zero), u2, NULL, &co->loc, ns);
3079
3080 do_1->block->next = do_2;
3081 do_2->block->next = assign_matmul;
3082
3083 var_1 = do_1->ext.iterator->var;
3084 var_2 = do_2->ext.iterator->var;
3085
3086 list[0] = var_1;
3087 cscalar = scalarized_expr (co->expr1, list, 1);
3088
3089 list[0] = var_2;
3090 ascalar = scalarized_expr (matrix_a, list, 1);
3091
3092 list[0] = var_2;
3093 list[1] = var_1;
3094 bscalar = scalarized_expr (matrix_b, list, 2);
3095
3096 break;
3097
3098 default:
3099 gcc_unreachable();
3100 }
3101
3102 if (conjg_a)
3103 ascalar = gfc_build_intrinsic_call (ns, GFC_ISYM_CONJG, "conjg",
3104 matrix_a->where, 1, ascalar);
3105
3106 if (conjg_b)
3107 bscalar = gfc_build_intrinsic_call (ns, GFC_ISYM_CONJG, "conjg",
3108 matrix_b->where, 1, bscalar);
3109
3110 /* First loop comes after the zero assignment. */
3111 assign_zero->next = do_1;
3112
3113 /* Build the assignment expression in the loop. */
3114 assign_matmul->expr1 = gfc_copy_expr (cscalar);
3115
3116 mult = get_operand (op_times, ascalar, bscalar);
3117 assign_matmul->expr2 = get_operand (op_plus, cscalar, mult);
3118
3119 /* If we don't want to keep the original statement around in
3120 the else branch, we can free it. */
3121
3122 if (if_limit == NULL)
3123 gfc_free_statements(co);
3124 else
3125 co->next = NULL;
3126
3127 gfc_free_expr (zero);
3128 *walk_subtrees = 0;
3129 return 0;
3130 }
3131
3132 #define WALK_SUBEXPR(NODE) \
3133 do \
3134 { \
3135 result = gfc_expr_walker (&(NODE), exprfn, data); \
3136 if (result) \
3137 return result; \
3138 } \
3139 while (0)
3140 #define WALK_SUBEXPR_TAIL(NODE) e = &(NODE); continue
3141
3142 /* Walk expression *E, calling EXPRFN on each expression in it. */
3143
3144 int
3145 gfc_expr_walker (gfc_expr **e, walk_expr_fn_t exprfn, void *data)
3146 {
3147 while (*e)
3148 {
3149 int walk_subtrees = 1;
3150 gfc_actual_arglist *a;
3151 gfc_ref *r;
3152 gfc_constructor *c;
3153
3154 int result = exprfn (e, &walk_subtrees, data);
3155 if (result)
3156 return result;
3157 if (walk_subtrees)
3158 switch ((*e)->expr_type)
3159 {
3160 case EXPR_OP:
3161 WALK_SUBEXPR ((*e)->value.op.op1);
3162 WALK_SUBEXPR_TAIL ((*e)->value.op.op2);
3163 break;
3164 case EXPR_FUNCTION:
3165 for (a = (*e)->value.function.actual; a; a = a->next)
3166 WALK_SUBEXPR (a->expr);
3167 break;
3168 case EXPR_COMPCALL:
3169 case EXPR_PPC:
3170 WALK_SUBEXPR ((*e)->value.compcall.base_object);
3171 for (a = (*e)->value.compcall.actual; a; a = a->next)
3172 WALK_SUBEXPR (a->expr);
3173 break;
3174
3175 case EXPR_STRUCTURE:
3176 case EXPR_ARRAY:
3177 for (c = gfc_constructor_first ((*e)->value.constructor); c;
3178 c = gfc_constructor_next (c))
3179 {
3180 if (c->iterator == NULL)
3181 WALK_SUBEXPR (c->expr);
3182 else
3183 {
3184 iterator_level ++;
3185 WALK_SUBEXPR (c->expr);
3186 iterator_level --;
3187 WALK_SUBEXPR (c->iterator->var);
3188 WALK_SUBEXPR (c->iterator->start);
3189 WALK_SUBEXPR (c->iterator->end);
3190 WALK_SUBEXPR (c->iterator->step);
3191 }
3192 }
3193
3194 if ((*e)->expr_type != EXPR_ARRAY)
3195 break;
3196
3197 /* Fall through to the variable case in order to walk the
3198 reference. */
3199
3200 case EXPR_SUBSTRING:
3201 case EXPR_VARIABLE:
3202 for (r = (*e)->ref; r; r = r->next)
3203 {
3204 gfc_array_ref *ar;
3205 int i;
3206
3207 switch (r->type)
3208 {
3209 case REF_ARRAY:
3210 ar = &r->u.ar;
3211 if (ar->type == AR_SECTION || ar->type == AR_ELEMENT)
3212 {
3213 for (i=0; i< ar->dimen; i++)
3214 {
3215 WALK_SUBEXPR (ar->start[i]);
3216 WALK_SUBEXPR (ar->end[i]);
3217 WALK_SUBEXPR (ar->stride[i]);
3218 }
3219 }
3220
3221 break;
3222
3223 case REF_SUBSTRING:
3224 WALK_SUBEXPR (r->u.ss.start);
3225 WALK_SUBEXPR (r->u.ss.end);
3226 break;
3227
3228 case REF_COMPONENT:
3229 break;
3230 }
3231 }
3232
3233 default:
3234 break;
3235 }
3236 return 0;
3237 }
3238 return 0;
3239 }
3240
3241 #define WALK_SUBCODE(NODE) \
3242 do \
3243 { \
3244 result = gfc_code_walker (&(NODE), codefn, exprfn, data); \
3245 if (result) \
3246 return result; \
3247 } \
3248 while (0)
3249
3250 /* Walk code *C, calling CODEFN on each gfc_code node in it and calling EXPRFN
3251 on each expression in it. If any of the hooks returns non-zero, that
3252 value is immediately returned. If the hook sets *WALK_SUBTREES to 0,
3253 no subcodes or subexpressions are traversed. */
3254
3255 int
3256 gfc_code_walker (gfc_code **c, walk_code_fn_t codefn, walk_expr_fn_t exprfn,
3257 void *data)
3258 {
3259 for (; *c; c = &(*c)->next)
3260 {
3261 int walk_subtrees = 1;
3262 int result = codefn (c, &walk_subtrees, data);
3263 if (result)
3264 return result;
3265
3266 if (walk_subtrees)
3267 {
3268 gfc_code *b;
3269 gfc_actual_arglist *a;
3270 gfc_code *co;
3271 gfc_association_list *alist;
3272 bool saved_in_omp_workshare;
3273
3274 /* There might be statement insertions before the current code,
3275 which must not affect the expression walker. */
3276
3277 co = *c;
3278 saved_in_omp_workshare = in_omp_workshare;
3279
3280 switch (co->op)
3281 {
3282
3283 case EXEC_BLOCK:
3284 WALK_SUBCODE (co->ext.block.ns->code);
3285 if (co->ext.block.assoc)
3286 {
3287 bool saved_in_assoc_list = in_assoc_list;
3288
3289 in_assoc_list = true;
3290 for (alist = co->ext.block.assoc; alist; alist = alist->next)
3291 WALK_SUBEXPR (alist->target);
3292
3293 in_assoc_list = saved_in_assoc_list;
3294 }
3295
3296 break;
3297
3298 case EXEC_DO:
3299 doloop_level ++;
3300 WALK_SUBEXPR (co->ext.iterator->var);
3301 WALK_SUBEXPR (co->ext.iterator->start);
3302 WALK_SUBEXPR (co->ext.iterator->end);
3303 WALK_SUBEXPR (co->ext.iterator->step);
3304 break;
3305
3306 case EXEC_CALL:
3307 case EXEC_ASSIGN_CALL:
3308 for (a = co->ext.actual; a; a = a->next)
3309 WALK_SUBEXPR (a->expr);
3310 break;
3311
3312 case EXEC_CALL_PPC:
3313 WALK_SUBEXPR (co->expr1);
3314 for (a = co->ext.actual; a; a = a->next)
3315 WALK_SUBEXPR (a->expr);
3316 break;
3317
3318 case EXEC_SELECT:
3319 WALK_SUBEXPR (co->expr1);
3320 for (b = co->block; b; b = b->block)
3321 {
3322 gfc_case *cp;
3323 for (cp = b->ext.block.case_list; cp; cp = cp->next)
3324 {
3325 WALK_SUBEXPR (cp->low);
3326 WALK_SUBEXPR (cp->high);
3327 }
3328 WALK_SUBCODE (b->next);
3329 }
3330 continue;
3331
3332 case EXEC_ALLOCATE:
3333 case EXEC_DEALLOCATE:
3334 {
3335 gfc_alloc *a;
3336 for (a = co->ext.alloc.list; a; a = a->next)
3337 WALK_SUBEXPR (a->expr);
3338 break;
3339 }
3340
3341 case EXEC_FORALL:
3342 case EXEC_DO_CONCURRENT:
3343 {
3344 gfc_forall_iterator *fa;
3345 for (fa = co->ext.forall_iterator; fa; fa = fa->next)
3346 {
3347 WALK_SUBEXPR (fa->var);
3348 WALK_SUBEXPR (fa->start);
3349 WALK_SUBEXPR (fa->end);
3350 WALK_SUBEXPR (fa->stride);
3351 }
3352 if (co->op == EXEC_FORALL)
3353 forall_level ++;
3354 break;
3355 }
3356
3357 case EXEC_OPEN:
3358 WALK_SUBEXPR (co->ext.open->unit);
3359 WALK_SUBEXPR (co->ext.open->file);
3360 WALK_SUBEXPR (co->ext.open->status);
3361 WALK_SUBEXPR (co->ext.open->access);
3362 WALK_SUBEXPR (co->ext.open->form);
3363 WALK_SUBEXPR (co->ext.open->recl);
3364 WALK_SUBEXPR (co->ext.open->blank);
3365 WALK_SUBEXPR (co->ext.open->position);
3366 WALK_SUBEXPR (co->ext.open->action);
3367 WALK_SUBEXPR (co->ext.open->delim);
3368 WALK_SUBEXPR (co->ext.open->pad);
3369 WALK_SUBEXPR (co->ext.open->iostat);
3370 WALK_SUBEXPR (co->ext.open->iomsg);
3371 WALK_SUBEXPR (co->ext.open->convert);
3372 WALK_SUBEXPR (co->ext.open->decimal);
3373 WALK_SUBEXPR (co->ext.open->encoding);
3374 WALK_SUBEXPR (co->ext.open->round);
3375 WALK_SUBEXPR (co->ext.open->sign);
3376 WALK_SUBEXPR (co->ext.open->asynchronous);
3377 WALK_SUBEXPR (co->ext.open->id);
3378 WALK_SUBEXPR (co->ext.open->newunit);
3379 break;
3380
3381 case EXEC_CLOSE:
3382 WALK_SUBEXPR (co->ext.close->unit);
3383 WALK_SUBEXPR (co->ext.close->status);
3384 WALK_SUBEXPR (co->ext.close->iostat);
3385 WALK_SUBEXPR (co->ext.close->iomsg);
3386 break;
3387
3388 case EXEC_BACKSPACE:
3389 case EXEC_ENDFILE:
3390 case EXEC_REWIND:
3391 case EXEC_FLUSH:
3392 WALK_SUBEXPR (co->ext.filepos->unit);
3393 WALK_SUBEXPR (co->ext.filepos->iostat);
3394 WALK_SUBEXPR (co->ext.filepos->iomsg);
3395 break;
3396
3397 case EXEC_INQUIRE:
3398 WALK_SUBEXPR (co->ext.inquire->unit);
3399 WALK_SUBEXPR (co->ext.inquire->file);
3400 WALK_SUBEXPR (co->ext.inquire->iomsg);
3401 WALK_SUBEXPR (co->ext.inquire->iostat);
3402 WALK_SUBEXPR (co->ext.inquire->exist);
3403 WALK_SUBEXPR (co->ext.inquire->opened);
3404 WALK_SUBEXPR (co->ext.inquire->number);
3405 WALK_SUBEXPR (co->ext.inquire->named);
3406 WALK_SUBEXPR (co->ext.inquire->name);
3407 WALK_SUBEXPR (co->ext.inquire->access);
3408 WALK_SUBEXPR (co->ext.inquire->sequential);
3409 WALK_SUBEXPR (co->ext.inquire->direct);
3410 WALK_SUBEXPR (co->ext.inquire->form);
3411 WALK_SUBEXPR (co->ext.inquire->formatted);
3412 WALK_SUBEXPR (co->ext.inquire->unformatted);
3413 WALK_SUBEXPR (co->ext.inquire->recl);
3414 WALK_SUBEXPR (co->ext.inquire->nextrec);
3415 WALK_SUBEXPR (co->ext.inquire->blank);
3416 WALK_SUBEXPR (co->ext.inquire->position);
3417 WALK_SUBEXPR (co->ext.inquire->action);
3418 WALK_SUBEXPR (co->ext.inquire->read);
3419 WALK_SUBEXPR (co->ext.inquire->write);
3420 WALK_SUBEXPR (co->ext.inquire->readwrite);
3421 WALK_SUBEXPR (co->ext.inquire->delim);
3422 WALK_SUBEXPR (co->ext.inquire->encoding);
3423 WALK_SUBEXPR (co->ext.inquire->pad);
3424 WALK_SUBEXPR (co->ext.inquire->iolength);
3425 WALK_SUBEXPR (co->ext.inquire->convert);
3426 WALK_SUBEXPR (co->ext.inquire->strm_pos);
3427 WALK_SUBEXPR (co->ext.inquire->asynchronous);
3428 WALK_SUBEXPR (co->ext.inquire->decimal);
3429 WALK_SUBEXPR (co->ext.inquire->pending);
3430 WALK_SUBEXPR (co->ext.inquire->id);
3431 WALK_SUBEXPR (co->ext.inquire->sign);
3432 WALK_SUBEXPR (co->ext.inquire->size);
3433 WALK_SUBEXPR (co->ext.inquire->round);
3434 break;
3435
3436 case EXEC_WAIT:
3437 WALK_SUBEXPR (co->ext.wait->unit);
3438 WALK_SUBEXPR (co->ext.wait->iostat);
3439 WALK_SUBEXPR (co->ext.wait->iomsg);
3440 WALK_SUBEXPR (co->ext.wait->id);
3441 break;
3442
3443 case EXEC_READ:
3444 case EXEC_WRITE:
3445 WALK_SUBEXPR (co->ext.dt->io_unit);
3446 WALK_SUBEXPR (co->ext.dt->format_expr);
3447 WALK_SUBEXPR (co->ext.dt->rec);
3448 WALK_SUBEXPR (co->ext.dt->advance);
3449 WALK_SUBEXPR (co->ext.dt->iostat);
3450 WALK_SUBEXPR (co->ext.dt->size);
3451 WALK_SUBEXPR (co->ext.dt->iomsg);
3452 WALK_SUBEXPR (co->ext.dt->id);
3453 WALK_SUBEXPR (co->ext.dt->pos);
3454 WALK_SUBEXPR (co->ext.dt->asynchronous);
3455 WALK_SUBEXPR (co->ext.dt->blank);
3456 WALK_SUBEXPR (co->ext.dt->decimal);
3457 WALK_SUBEXPR (co->ext.dt->delim);
3458 WALK_SUBEXPR (co->ext.dt->pad);
3459 WALK_SUBEXPR (co->ext.dt->round);
3460 WALK_SUBEXPR (co->ext.dt->sign);
3461 WALK_SUBEXPR (co->ext.dt->extra_comma);
3462 break;
3463
3464 case EXEC_OMP_PARALLEL:
3465 case EXEC_OMP_PARALLEL_DO:
3466 case EXEC_OMP_PARALLEL_DO_SIMD:
3467 case EXEC_OMP_PARALLEL_SECTIONS:
3468
3469 in_omp_workshare = false;
3470
3471 /* This goto serves as a shortcut to avoid code
3472 duplication or a larger if or switch statement. */
3473 goto check_omp_clauses;
3474
3475 case EXEC_OMP_WORKSHARE:
3476 case EXEC_OMP_PARALLEL_WORKSHARE:
3477
3478 in_omp_workshare = true;
3479
3480 /* Fall through */
3481
3482 case EXEC_OMP_DISTRIBUTE:
3483 case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
3484 case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
3485 case EXEC_OMP_DISTRIBUTE_SIMD:
3486 case EXEC_OMP_DO:
3487 case EXEC_OMP_DO_SIMD:
3488 case EXEC_OMP_SECTIONS:
3489 case EXEC_OMP_SINGLE:
3490 case EXEC_OMP_END_SINGLE:
3491 case EXEC_OMP_SIMD:
3492 case EXEC_OMP_TARGET:
3493 case EXEC_OMP_TARGET_DATA:
3494 case EXEC_OMP_TARGET_TEAMS:
3495 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
3496 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
3497 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
3498 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
3499 case EXEC_OMP_TARGET_UPDATE:
3500 case EXEC_OMP_TASK:
3501 case EXEC_OMP_TEAMS:
3502 case EXEC_OMP_TEAMS_DISTRIBUTE:
3503 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
3504 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
3505 case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
3506
3507 /* Come to this label only from the
3508 EXEC_OMP_PARALLEL_* cases above. */
3509
3510 check_omp_clauses:
3511
3512 if (co->ext.omp_clauses)
3513 {
3514 gfc_omp_namelist *n;
3515 static int list_types[]
3516 = { OMP_LIST_ALIGNED, OMP_LIST_LINEAR, OMP_LIST_DEPEND,
3517 OMP_LIST_MAP, OMP_LIST_TO, OMP_LIST_FROM };
3518 size_t idx;
3519 WALK_SUBEXPR (co->ext.omp_clauses->if_expr);
3520 WALK_SUBEXPR (co->ext.omp_clauses->final_expr);
3521 WALK_SUBEXPR (co->ext.omp_clauses->num_threads);
3522 WALK_SUBEXPR (co->ext.omp_clauses->chunk_size);
3523 WALK_SUBEXPR (co->ext.omp_clauses->safelen_expr);
3524 WALK_SUBEXPR (co->ext.omp_clauses->simdlen_expr);
3525 WALK_SUBEXPR (co->ext.omp_clauses->num_teams);
3526 WALK_SUBEXPR (co->ext.omp_clauses->device);
3527 WALK_SUBEXPR (co->ext.omp_clauses->thread_limit);
3528 WALK_SUBEXPR (co->ext.omp_clauses->dist_chunk_size);
3529 for (idx = 0;
3530 idx < sizeof (list_types) / sizeof (list_types[0]);
3531 idx++)
3532 for (n = co->ext.omp_clauses->lists[list_types[idx]];
3533 n; n = n->next)
3534 WALK_SUBEXPR (n->expr);
3535 }
3536 break;
3537 default:
3538 break;
3539 }
3540
3541 WALK_SUBEXPR (co->expr1);
3542 WALK_SUBEXPR (co->expr2);
3543 WALK_SUBEXPR (co->expr3);
3544 WALK_SUBEXPR (co->expr4);
3545 for (b = co->block; b; b = b->block)
3546 {
3547 WALK_SUBEXPR (b->expr1);
3548 WALK_SUBEXPR (b->expr2);
3549 WALK_SUBCODE (b->next);
3550 }
3551
3552 if (co->op == EXEC_FORALL)
3553 forall_level --;
3554
3555 if (co->op == EXEC_DO)
3556 doloop_level --;
3557
3558 in_omp_workshare = saved_in_omp_workshare;
3559 }
3560 }
3561 return 0;
3562 }