Add function part to a same comdat group (PR ipa/80212).
[official-gcc.git] / gcc / fortran / frontend-passes.c
blob459967d5c35b62471aecce1c0b592e985fd80b37
1 /* Pass manager for Fortran front end.
2 Copyright (C) 2010-2017 Free Software Foundation, Inc.
3 Contributed by Thomas König.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
10 version.
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "options.h"
25 #include "gfortran.h"
26 #include "dependency.h"
27 #include "constructor.h"
28 #include "intrinsic.h"
30 /* Forward declarations. */
32 static void strip_function_call (gfc_expr *);
33 static void optimize_namespace (gfc_namespace *);
34 static void optimize_assignment (gfc_code *);
35 static bool optimize_op (gfc_expr *);
36 static bool optimize_comparison (gfc_expr *, gfc_intrinsic_op);
37 static bool optimize_trim (gfc_expr *);
38 static bool optimize_lexical_comparison (gfc_expr *);
39 static void optimize_minmaxloc (gfc_expr **);
40 static bool is_empty_string (gfc_expr *e);
41 static void doloop_warn (gfc_namespace *);
42 static void optimize_reduction (gfc_namespace *);
43 static int callback_reduction (gfc_expr **, int *, void *);
44 static void realloc_strings (gfc_namespace *);
45 static gfc_expr *create_var (gfc_expr *, const char *vname=NULL);
46 static int inline_matmul_assign (gfc_code **, int *, void *);
47 static gfc_code * create_do_loop (gfc_expr *, gfc_expr *, gfc_expr *,
48 locus *, gfc_namespace *,
49 char *vname=NULL);
51 #ifdef CHECKING_P
52 static void check_locus (gfc_namespace *);
53 #endif
55 /* How deep we are inside an argument list. */
57 static int count_arglist;
59 /* Vector of gfc_expr ** we operate on. */
61 static vec<gfc_expr **> expr_array;
63 /* Pointer to the gfc_code we currently work on - to be able to insert
64 a block before the statement. */
66 static gfc_code **current_code;
68 /* Pointer to the block to be inserted, and the statement we are
69 changing within the block. */
71 static gfc_code *inserted_block, **changed_statement;
73 /* The namespace we are currently dealing with. */
75 static gfc_namespace *current_ns;
77 /* If we are within any forall loop. */
79 static int forall_level;
81 /* Keep track of whether we are within an OMP workshare. */
83 static bool in_omp_workshare;
85 /* Keep track of whether we are within a WHERE statement. */
87 static bool in_where;
89 /* Keep track of iterators for array constructors. */
91 static int iterator_level;
93 /* Keep track of DO loop levels. */
95 static vec<gfc_code *> doloop_list;
97 static int doloop_level;
99 /* Vector of gfc_expr * to keep track of DO loops. */
101 struct my_struct *evec;
103 /* Keep track of association lists. */
105 static bool in_assoc_list;
107 /* Counter for temporary variables. */
109 static int var_num = 1;
111 /* What sort of matrix we are dealing with when inlining MATMUL. */
113 enum matrix_case { none=0, A2B2, A2B1, A1B2, A2B2T };
115 /* Keep track of the number of expressions we have inserted so far
116 using create_var. */
118 int n_vars;
120 /* Entry point - run all passes for a namespace. */
122 void
123 gfc_run_passes (gfc_namespace *ns)
126 /* Warn about dubious DO loops where the index might
127 change. */
129 doloop_level = 0;
130 doloop_warn (ns);
131 doloop_list.release ();
132 int w, e;
134 #ifdef CHECKING_P
135 check_locus (ns);
136 #endif
138 if (flag_frontend_optimize)
140 optimize_namespace (ns);
141 optimize_reduction (ns);
142 if (flag_dump_fortran_optimized)
143 gfc_dump_parse_tree (ns, stdout);
145 expr_array.release ();
148 gfc_get_errors (&w, &e);
149 if (e > 0)
150 return;
152 if (flag_realloc_lhs)
153 realloc_strings (ns);
156 #ifdef CHECKING_P
158 /* Callback function: Warn if there is no location information in a
159 statement. */
161 static int
162 check_locus_code (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
163 void *data ATTRIBUTE_UNUSED)
165 current_code = c;
166 if (c && *c && (((*c)->loc.nextc == NULL) || ((*c)->loc.lb == NULL)))
167 gfc_warning_internal (0, "No location in statement");
169 return 0;
173 /* Callback function: Warn if there is no location information in an
174 expression. */
176 static int
177 check_locus_expr (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
178 void *data ATTRIBUTE_UNUSED)
181 if (e && *e && (((*e)->where.nextc == NULL || (*e)->where.lb == NULL)))
182 gfc_warning_internal (0, "No location in expression near %L",
183 &((*current_code)->loc));
184 return 0;
187 /* Run check for missing location information. */
189 static void
190 check_locus (gfc_namespace *ns)
192 gfc_code_walker (&ns->code, check_locus_code, check_locus_expr, NULL);
194 for (ns = ns->contained; ns; ns = ns->sibling)
196 if (ns->code == NULL || ns->code->op != EXEC_BLOCK)
197 check_locus (ns);
201 #endif
203 /* Callback for each gfc_code node invoked from check_realloc_strings.
204 For an allocatable LHS string which also appears as a variable on
205 the RHS, replace
207 a = a(x:y)
209 with
211 tmp = a(x:y)
212 a = tmp
215 static int
216 realloc_string_callback (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
217 void *data ATTRIBUTE_UNUSED)
219 gfc_expr *expr1, *expr2;
220 gfc_code *co = *c;
221 gfc_expr *n;
222 gfc_ref *ref;
223 bool found_substr;
225 if (co->op != EXEC_ASSIGN)
226 return 0;
228 expr1 = co->expr1;
229 if (expr1->ts.type != BT_CHARACTER || expr1->rank != 0
230 || !gfc_expr_attr(expr1).allocatable
231 || !expr1->ts.deferred)
232 return 0;
234 expr2 = gfc_discard_nops (co->expr2);
235 if (expr2->expr_type != EXPR_VARIABLE)
236 return 0;
238 found_substr = false;
239 for (ref = expr2->ref; ref; ref = ref->next)
241 if (ref->type == REF_SUBSTRING)
243 found_substr = true;
244 break;
247 if (!found_substr)
248 return 0;
250 if (!gfc_check_dependency (expr1, expr2, true))
251 return 0;
253 /* gfc_check_dependency doesn't always pick up identical expressions.
254 However, eliminating the above sends the compiler into an infinite
255 loop on valid expressions. Without this check, the gimplifier emits
256 an ICE for a = a, where a is deferred character length. */
257 if (!gfc_dep_compare_expr (expr1, expr2))
258 return 0;
260 current_code = c;
261 inserted_block = NULL;
262 changed_statement = NULL;
263 n = create_var (expr2, "realloc_string");
264 co->expr2 = n;
265 return 0;
268 /* Callback for each gfc_code node invoked through gfc_code_walker
269 from optimize_namespace. */
271 static int
272 optimize_code (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
273 void *data ATTRIBUTE_UNUSED)
276 gfc_exec_op op;
278 op = (*c)->op;
280 if (op == EXEC_CALL || op == EXEC_COMPCALL || op == EXEC_ASSIGN_CALL
281 || op == EXEC_CALL_PPC)
282 count_arglist = 1;
283 else
284 count_arglist = 0;
286 current_code = c;
287 inserted_block = NULL;
288 changed_statement = NULL;
290 if (op == EXEC_ASSIGN)
291 optimize_assignment (*c);
292 return 0;
295 /* Callback for each gfc_expr node invoked through gfc_code_walker
296 from optimize_namespace. */
298 static int
299 optimize_expr (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
300 void *data ATTRIBUTE_UNUSED)
302 bool function_expr;
304 if ((*e)->expr_type == EXPR_FUNCTION)
306 count_arglist ++;
307 function_expr = true;
309 else
310 function_expr = false;
312 if (optimize_trim (*e))
313 gfc_simplify_expr (*e, 0);
315 if (optimize_lexical_comparison (*e))
316 gfc_simplify_expr (*e, 0);
318 if ((*e)->expr_type == EXPR_OP && optimize_op (*e))
319 gfc_simplify_expr (*e, 0);
321 if ((*e)->expr_type == EXPR_FUNCTION && (*e)->value.function.isym)
322 switch ((*e)->value.function.isym->id)
324 case GFC_ISYM_MINLOC:
325 case GFC_ISYM_MAXLOC:
326 optimize_minmaxloc (e);
327 break;
328 default:
329 break;
332 if (function_expr)
333 count_arglist --;
335 return 0;
338 /* Auxiliary function to handle the arguments to reduction intrnisics. If the
339 function is a scalar, just copy it; otherwise returns the new element, the
340 old one can be freed. */
342 static gfc_expr *
343 copy_walk_reduction_arg (gfc_constructor *c, gfc_expr *fn)
345 gfc_expr *fcn, *e = c->expr;
347 fcn = gfc_copy_expr (e);
348 if (c->iterator)
350 gfc_constructor_base newbase;
351 gfc_expr *new_expr;
352 gfc_constructor *new_c;
354 newbase = NULL;
355 new_expr = gfc_get_expr ();
356 new_expr->expr_type = EXPR_ARRAY;
357 new_expr->ts = e->ts;
358 new_expr->where = e->where;
359 new_expr->rank = 1;
360 new_c = gfc_constructor_append_expr (&newbase, fcn, &(e->where));
361 new_c->iterator = c->iterator;
362 new_expr->value.constructor = newbase;
363 c->iterator = NULL;
365 fcn = new_expr;
368 if (fcn->rank != 0)
370 gfc_isym_id id = fn->value.function.isym->id;
372 if (id == GFC_ISYM_SUM || id == GFC_ISYM_PRODUCT)
373 fcn = gfc_build_intrinsic_call (current_ns, id,
374 fn->value.function.isym->name,
375 fn->where, 3, fcn, NULL, NULL);
376 else if (id == GFC_ISYM_ANY || id == GFC_ISYM_ALL)
377 fcn = gfc_build_intrinsic_call (current_ns, id,
378 fn->value.function.isym->name,
379 fn->where, 2, fcn, NULL);
380 else
381 gfc_internal_error ("Illegal id in copy_walk_reduction_arg");
383 fcn->symtree->n.sym->attr.access = ACCESS_PRIVATE;
386 return fcn;
389 /* Callback function for optimzation of reductions to scalars. Transform ANY
390 ([f1,f2,f3, ...]) to f1 .or. f2 .or. f3 .or. ..., with ANY, SUM and PRODUCT
391 correspondingly. Handly only the simple cases without MASK and DIM. */
393 static int
394 callback_reduction (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
395 void *data ATTRIBUTE_UNUSED)
397 gfc_expr *fn, *arg;
398 gfc_intrinsic_op op;
399 gfc_isym_id id;
400 gfc_actual_arglist *a;
401 gfc_actual_arglist *dim;
402 gfc_constructor *c;
403 gfc_expr *res, *new_expr;
404 gfc_actual_arglist *mask;
406 fn = *e;
408 if (fn->rank != 0 || fn->expr_type != EXPR_FUNCTION
409 || fn->value.function.isym == NULL)
410 return 0;
412 id = fn->value.function.isym->id;
414 if (id != GFC_ISYM_SUM && id != GFC_ISYM_PRODUCT
415 && id != GFC_ISYM_ANY && id != GFC_ISYM_ALL)
416 return 0;
418 a = fn->value.function.actual;
420 /* Don't handle MASK or DIM. */
422 dim = a->next;
424 if (dim->expr != NULL)
425 return 0;
427 if (id == GFC_ISYM_SUM || id == GFC_ISYM_PRODUCT)
429 mask = dim->next;
430 if ( mask->expr != NULL)
431 return 0;
434 arg = a->expr;
436 if (arg->expr_type != EXPR_ARRAY)
437 return 0;
439 switch (id)
441 case GFC_ISYM_SUM:
442 op = INTRINSIC_PLUS;
443 break;
445 case GFC_ISYM_PRODUCT:
446 op = INTRINSIC_TIMES;
447 break;
449 case GFC_ISYM_ANY:
450 op = INTRINSIC_OR;
451 break;
453 case GFC_ISYM_ALL:
454 op = INTRINSIC_AND;
455 break;
457 default:
458 return 0;
461 c = gfc_constructor_first (arg->value.constructor);
463 /* Don't do any simplififcation if we have
464 - no element in the constructor or
465 - only have a single element in the array which contains an
466 iterator. */
468 if (c == NULL)
469 return 0;
471 res = copy_walk_reduction_arg (c, fn);
473 c = gfc_constructor_next (c);
474 while (c)
476 new_expr = gfc_get_expr ();
477 new_expr->ts = fn->ts;
478 new_expr->expr_type = EXPR_OP;
479 new_expr->rank = fn->rank;
480 new_expr->where = fn->where;
481 new_expr->value.op.op = op;
482 new_expr->value.op.op1 = res;
483 new_expr->value.op.op2 = copy_walk_reduction_arg (c, fn);
484 res = new_expr;
485 c = gfc_constructor_next (c);
488 gfc_simplify_expr (res, 0);
489 *e = res;
490 gfc_free_expr (fn);
492 return 0;
495 /* Callback function for common function elimination, called from cfe_expr_0.
496 Put all eligible function expressions into expr_array. */
498 static int
499 cfe_register_funcs (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
500 void *data ATTRIBUTE_UNUSED)
503 if ((*e)->expr_type != EXPR_FUNCTION)
504 return 0;
506 /* We don't do character functions with unknown charlens. */
507 if ((*e)->ts.type == BT_CHARACTER
508 && ((*e)->ts.u.cl == NULL || (*e)->ts.u.cl->length == NULL
509 || (*e)->ts.u.cl->length->expr_type != EXPR_CONSTANT))
510 return 0;
512 /* We don't do function elimination within FORALL statements, it can
513 lead to wrong-code in certain circumstances. */
515 if (forall_level > 0)
516 return 0;
518 /* Function elimination inside an iterator could lead to functions which
519 depend on iterator variables being moved outside. FIXME: We should check
520 if the functions do indeed depend on the iterator variable. */
522 if (iterator_level > 0)
523 return 0;
525 /* If we don't know the shape at compile time, we create an allocatable
526 temporary variable to hold the intermediate result, but only if
527 allocation on assignment is active. */
529 if ((*e)->rank > 0 && (*e)->shape == NULL && !flag_realloc_lhs)
530 return 0;
532 /* Skip the test for pure functions if -faggressive-function-elimination
533 is specified. */
534 if ((*e)->value.function.esym)
536 /* Don't create an array temporary for elemental functions. */
537 if ((*e)->value.function.esym->attr.elemental && (*e)->rank > 0)
538 return 0;
540 /* Only eliminate potentially impure functions if the
541 user specifically requested it. */
542 if (!flag_aggressive_function_elimination
543 && !(*e)->value.function.esym->attr.pure
544 && !(*e)->value.function.esym->attr.implicit_pure)
545 return 0;
548 if ((*e)->value.function.isym)
550 /* Conversions are handled on the fly by the middle end,
551 transpose during trans-* stages and TRANSFER by the middle end. */
552 if ((*e)->value.function.isym->id == GFC_ISYM_CONVERSION
553 || (*e)->value.function.isym->id == GFC_ISYM_TRANSFER
554 || gfc_inline_intrinsic_function_p (*e))
555 return 0;
557 /* Don't create an array temporary for elemental functions,
558 as this would be wasteful of memory.
559 FIXME: Create a scalar temporary during scalarization. */
560 if ((*e)->value.function.isym->elemental && (*e)->rank > 0)
561 return 0;
563 if (!(*e)->value.function.isym->pure)
564 return 0;
567 expr_array.safe_push (e);
568 return 0;
571 /* Auxiliary function to check if an expression is a temporary created by
572 create var. */
574 static bool
575 is_fe_temp (gfc_expr *e)
577 if (e->expr_type != EXPR_VARIABLE)
578 return false;
580 return e->symtree->n.sym->attr.fe_temp;
583 /* Determine the length of a string, if it can be evaluated as a constant
584 expression. Return a newly allocated gfc_expr or NULL on failure.
585 If the user specified a substring which is potentially longer than
586 the string itself, the string will be padded with spaces, which
587 is harmless. */
589 static gfc_expr *
590 constant_string_length (gfc_expr *e)
593 gfc_expr *length;
594 gfc_ref *ref;
595 gfc_expr *res;
596 mpz_t value;
598 if (e->ts.u.cl)
600 length = e->ts.u.cl->length;
601 if (length && length->expr_type == EXPR_CONSTANT)
602 return gfc_copy_expr(length);
605 /* Return length of substring, if constant. */
606 for (ref = e->ref; ref; ref = ref->next)
608 if (ref->type == REF_SUBSTRING
609 && gfc_dep_difference (ref->u.ss.end, ref->u.ss.start, &value))
611 res = gfc_get_constant_expr (BT_INTEGER, gfc_charlen_int_kind,
612 &e->where);
614 mpz_add_ui (res->value.integer, value, 1);
615 mpz_clear (value);
616 return res;
620 /* Return length of char symbol, if constant. */
622 if (e->symtree->n.sym->ts.u.cl && e->symtree->n.sym->ts.u.cl->length
623 && e->symtree->n.sym->ts.u.cl->length->expr_type == EXPR_CONSTANT)
624 return gfc_copy_expr (e->symtree->n.sym->ts.u.cl->length);
626 return NULL;
630 /* Insert a block at the current position unless it has already
631 been inserted; in this case use the one already there. */
633 static gfc_namespace*
634 insert_block ()
636 gfc_namespace *ns;
638 /* If the block hasn't already been created, do so. */
639 if (inserted_block == NULL)
641 inserted_block = XCNEW (gfc_code);
642 inserted_block->op = EXEC_BLOCK;
643 inserted_block->loc = (*current_code)->loc;
644 ns = gfc_build_block_ns (current_ns);
645 inserted_block->ext.block.ns = ns;
646 inserted_block->ext.block.assoc = NULL;
648 ns->code = *current_code;
650 /* If the statement has a label, make sure it is transferred to
651 the newly created block. */
653 if ((*current_code)->here)
655 inserted_block->here = (*current_code)->here;
656 (*current_code)->here = NULL;
659 inserted_block->next = (*current_code)->next;
660 changed_statement = &(inserted_block->ext.block.ns->code);
661 (*current_code)->next = NULL;
662 /* Insert the BLOCK at the right position. */
663 *current_code = inserted_block;
664 ns->parent = current_ns;
666 else
667 ns = inserted_block->ext.block.ns;
669 return ns;
672 /* Returns a new expression (a variable) to be used in place of the old one,
673 with an optional assignment statement before the current statement to set
674 the value of the variable. Creates a new BLOCK for the statement if that
675 hasn't already been done and puts the statement, plus the newly created
676 variables, in that block. Special cases: If the expression is constant or
677 a temporary which has already been created, just copy it. */
679 static gfc_expr*
680 create_var (gfc_expr * e, const char *vname)
682 char name[GFC_MAX_SYMBOL_LEN +1];
683 gfc_symtree *symtree;
684 gfc_symbol *symbol;
685 gfc_expr *result;
686 gfc_code *n;
687 gfc_namespace *ns;
688 int i;
689 bool deferred;
691 if (e->expr_type == EXPR_CONSTANT || is_fe_temp (e))
692 return gfc_copy_expr (e);
694 ns = insert_block ();
696 if (vname)
697 snprintf (name, GFC_MAX_SYMBOL_LEN, "__var_%d_%s", var_num++, vname);
698 else
699 snprintf (name, GFC_MAX_SYMBOL_LEN, "__var_%d", var_num++);
701 if (gfc_get_sym_tree (name, ns, &symtree, false) != 0)
702 gcc_unreachable ();
704 symbol = symtree->n.sym;
705 symbol->ts = e->ts;
707 if (e->rank > 0)
709 symbol->as = gfc_get_array_spec ();
710 symbol->as->rank = e->rank;
712 if (e->shape == NULL)
714 /* We don't know the shape at compile time, so we use an
715 allocatable. */
716 symbol->as->type = AS_DEFERRED;
717 symbol->attr.allocatable = 1;
719 else
721 symbol->as->type = AS_EXPLICIT;
722 /* Copy the shape. */
723 for (i=0; i<e->rank; i++)
725 gfc_expr *p, *q;
727 p = gfc_get_constant_expr (BT_INTEGER, gfc_default_integer_kind,
728 &(e->where));
729 mpz_set_si (p->value.integer, 1);
730 symbol->as->lower[i] = p;
732 q = gfc_get_constant_expr (BT_INTEGER, gfc_index_integer_kind,
733 &(e->where));
734 mpz_set (q->value.integer, e->shape[i]);
735 symbol->as->upper[i] = q;
740 deferred = 0;
741 if (e->ts.type == BT_CHARACTER && e->rank == 0)
743 gfc_expr *length;
745 symbol->ts.u.cl = gfc_new_charlen (ns, NULL);
746 length = constant_string_length (e);
747 if (length)
748 symbol->ts.u.cl->length = length;
749 else
751 symbol->attr.allocatable = 1;
752 deferred = 1;
756 symbol->attr.flavor = FL_VARIABLE;
757 symbol->attr.referenced = 1;
758 symbol->attr.dimension = e->rank > 0;
759 symbol->attr.fe_temp = 1;
760 gfc_commit_symbol (symbol);
762 result = gfc_get_expr ();
763 result->expr_type = EXPR_VARIABLE;
764 result->ts = e->ts;
765 result->ts.deferred = deferred;
766 result->rank = e->rank;
767 result->shape = gfc_copy_shape (e->shape, e->rank);
768 result->symtree = symtree;
769 result->where = e->where;
770 if (e->rank > 0)
772 result->ref = gfc_get_ref ();
773 result->ref->type = REF_ARRAY;
774 result->ref->u.ar.type = AR_FULL;
775 result->ref->u.ar.where = e->where;
776 result->ref->u.ar.dimen = e->rank;
777 result->ref->u.ar.as = symbol->ts.type == BT_CLASS
778 ? CLASS_DATA (symbol)->as : symbol->as;
779 if (warn_array_temporaries)
780 gfc_warning (OPT_Warray_temporaries,
781 "Creating array temporary at %L", &(e->where));
784 /* Generate the new assignment. */
785 n = XCNEW (gfc_code);
786 n->op = EXEC_ASSIGN;
787 n->loc = (*current_code)->loc;
788 n->next = *changed_statement;
789 n->expr1 = gfc_copy_expr (result);
790 n->expr2 = e;
791 *changed_statement = n;
792 n_vars ++;
794 return result;
797 /* Warn about function elimination. */
799 static void
800 do_warn_function_elimination (gfc_expr *e)
802 if (e->expr_type != EXPR_FUNCTION)
803 return;
804 if (e->value.function.esym)
805 gfc_warning (OPT_Wfunction_elimination,
806 "Removing call to function %qs at %L",
807 e->value.function.esym->name, &(e->where));
808 else if (e->value.function.isym)
809 gfc_warning (OPT_Wfunction_elimination,
810 "Removing call to function %qs at %L",
811 e->value.function.isym->name, &(e->where));
813 /* Callback function for the code walker for doing common function
814 elimination. This builds up the list of functions in the expression
815 and goes through them to detect duplicates, which it then replaces
816 by variables. */
818 static int
819 cfe_expr_0 (gfc_expr **e, int *walk_subtrees,
820 void *data ATTRIBUTE_UNUSED)
822 int i,j;
823 gfc_expr *newvar;
824 gfc_expr **ei, **ej;
826 /* Don't do this optimization within OMP workshare or ASSOC lists. */
828 if (in_omp_workshare || in_assoc_list)
830 *walk_subtrees = 0;
831 return 0;
834 expr_array.release ();
836 gfc_expr_walker (e, cfe_register_funcs, NULL);
838 /* Walk through all the functions. */
840 FOR_EACH_VEC_ELT_FROM (expr_array, i, ei, 1)
842 /* Skip if the function has been replaced by a variable already. */
843 if ((*ei)->expr_type == EXPR_VARIABLE)
844 continue;
846 newvar = NULL;
847 for (j=0; j<i; j++)
849 ej = expr_array[j];
850 if (gfc_dep_compare_functions (*ei, *ej, true) == 0)
852 if (newvar == NULL)
853 newvar = create_var (*ei, "fcn");
855 if (warn_function_elimination)
856 do_warn_function_elimination (*ej);
858 free (*ej);
859 *ej = gfc_copy_expr (newvar);
862 if (newvar)
863 *ei = newvar;
866 /* We did all the necessary walking in this function. */
867 *walk_subtrees = 0;
868 return 0;
871 /* Callback function for common function elimination, called from
872 gfc_code_walker. This keeps track of the current code, in order
873 to insert statements as needed. */
875 static int
876 cfe_code (gfc_code **c, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
878 current_code = c;
879 inserted_block = NULL;
880 changed_statement = NULL;
882 /* Do not do anything inside a WHERE statement; scalar assignments, BLOCKs
883 and allocation on assigment are prohibited inside WHERE, and finally
884 masking an expression would lead to wrong-code when replacing
886 WHERE (a>0)
887 b = sum(foo(a) + foo(a))
888 END WHERE
890 with
892 WHERE (a > 0)
893 tmp = foo(a)
894 b = sum(tmp + tmp)
895 END WHERE
898 if ((*c)->op == EXEC_WHERE)
900 *walk_subtrees = 0;
901 return 0;
905 return 0;
908 /* Dummy function for expression call back, for use when we
909 really don't want to do any walking. */
911 static int
912 dummy_expr_callback (gfc_expr **e ATTRIBUTE_UNUSED, int *walk_subtrees,
913 void *data ATTRIBUTE_UNUSED)
915 *walk_subtrees = 0;
916 return 0;
919 /* Dummy function for code callback, for use when we really
920 don't want to do anything. */
922 gfc_dummy_code_callback (gfc_code **e ATTRIBUTE_UNUSED,
923 int *walk_subtrees ATTRIBUTE_UNUSED,
924 void *data ATTRIBUTE_UNUSED)
926 return 0;
929 /* Code callback function for converting
930 do while(a)
931 end do
932 into the equivalent
934 if (.not. a) exit
935 end do
936 This is because common function elimination would otherwise place the
937 temporary variables outside the loop. */
939 static int
940 convert_do_while (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
941 void *data ATTRIBUTE_UNUSED)
943 gfc_code *co = *c;
944 gfc_code *c_if1, *c_if2, *c_exit;
945 gfc_code *loopblock;
946 gfc_expr *e_not, *e_cond;
948 if (co->op != EXEC_DO_WHILE)
949 return 0;
951 if (co->expr1 == NULL || co->expr1->expr_type == EXPR_CONSTANT)
952 return 0;
954 e_cond = co->expr1;
956 /* Generate the condition of the if statement, which is .not. the original
957 statement. */
958 e_not = gfc_get_expr ();
959 e_not->ts = e_cond->ts;
960 e_not->where = e_cond->where;
961 e_not->expr_type = EXPR_OP;
962 e_not->value.op.op = INTRINSIC_NOT;
963 e_not->value.op.op1 = e_cond;
965 /* Generate the EXIT statement. */
966 c_exit = XCNEW (gfc_code);
967 c_exit->op = EXEC_EXIT;
968 c_exit->ext.which_construct = co;
969 c_exit->loc = co->loc;
971 /* Generate the IF statement. */
972 c_if2 = XCNEW (gfc_code);
973 c_if2->op = EXEC_IF;
974 c_if2->expr1 = e_not;
975 c_if2->next = c_exit;
976 c_if2->loc = co->loc;
978 /* ... plus the one to chain it to. */
979 c_if1 = XCNEW (gfc_code);
980 c_if1->op = EXEC_IF;
981 c_if1->block = c_if2;
982 c_if1->loc = co->loc;
984 /* Make the DO WHILE loop into a DO block by replacing the condition
985 with a true constant. */
986 co->expr1 = gfc_get_logical_expr (gfc_default_integer_kind, &co->loc, true);
988 /* Hang the generated if statement into the loop body. */
990 loopblock = co->block->next;
991 co->block->next = c_if1;
992 c_if1->next = loopblock;
994 return 0;
997 /* Code callback function for converting
998 if (a) then
1000 else if (b) then
1001 end if
1003 into
1004 if (a) then
1005 else
1006 if (b) then
1007 end if
1008 end if
1010 because otherwise common function elimination would place the BLOCKs
1011 into the wrong place. */
1013 static int
1014 convert_elseif (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
1015 void *data ATTRIBUTE_UNUSED)
1017 gfc_code *co = *c;
1018 gfc_code *c_if1, *c_if2, *else_stmt;
1020 if (co->op != EXEC_IF)
1021 return 0;
1023 /* This loop starts out with the first ELSE statement. */
1024 else_stmt = co->block->block;
1026 while (else_stmt != NULL)
1028 gfc_code *next_else;
1030 /* If there is no condition, we're done. */
1031 if (else_stmt->expr1 == NULL)
1032 break;
1034 next_else = else_stmt->block;
1036 /* Generate the new IF statement. */
1037 c_if2 = XCNEW (gfc_code);
1038 c_if2->op = EXEC_IF;
1039 c_if2->expr1 = else_stmt->expr1;
1040 c_if2->next = else_stmt->next;
1041 c_if2->loc = else_stmt->loc;
1042 c_if2->block = next_else;
1044 /* ... plus the one to chain it to. */
1045 c_if1 = XCNEW (gfc_code);
1046 c_if1->op = EXEC_IF;
1047 c_if1->block = c_if2;
1048 c_if1->loc = else_stmt->loc;
1050 /* Insert the new IF after the ELSE. */
1051 else_stmt->expr1 = NULL;
1052 else_stmt->next = c_if1;
1053 else_stmt->block = NULL;
1055 else_stmt = next_else;
1057 /* Don't walk subtrees. */
1058 return 0;
1061 /* Optimize a namespace, including all contained namespaces. */
1063 static void
1064 optimize_namespace (gfc_namespace *ns)
1066 gfc_namespace *saved_ns = gfc_current_ns;
1067 current_ns = ns;
1068 gfc_current_ns = ns;
1069 forall_level = 0;
1070 iterator_level = 0;
1071 in_assoc_list = false;
1072 in_omp_workshare = false;
1074 gfc_code_walker (&ns->code, convert_do_while, dummy_expr_callback, NULL);
1075 gfc_code_walker (&ns->code, convert_elseif, dummy_expr_callback, NULL);
1076 gfc_code_walker (&ns->code, cfe_code, cfe_expr_0, NULL);
1077 gfc_code_walker (&ns->code, optimize_code, optimize_expr, NULL);
1078 if (flag_inline_matmul_limit != 0)
1079 gfc_code_walker (&ns->code, inline_matmul_assign, dummy_expr_callback,
1080 NULL);
1082 /* BLOCKs are handled in the expression walker below. */
1083 for (ns = ns->contained; ns; ns = ns->sibling)
1085 if (ns->code == NULL || ns->code->op != EXEC_BLOCK)
1086 optimize_namespace (ns);
1088 gfc_current_ns = saved_ns;
1091 /* Handle dependencies for allocatable strings which potentially redefine
1092 themselves in an assignment. */
1094 static void
1095 realloc_strings (gfc_namespace *ns)
1097 current_ns = ns;
1098 gfc_code_walker (&ns->code, realloc_string_callback, dummy_expr_callback, NULL);
1100 for (ns = ns->contained; ns; ns = ns->sibling)
1102 if (ns->code == NULL || ns->code->op != EXEC_BLOCK)
1103 realloc_strings (ns);
1108 static void
1109 optimize_reduction (gfc_namespace *ns)
1111 current_ns = ns;
1112 gfc_code_walker (&ns->code, gfc_dummy_code_callback,
1113 callback_reduction, NULL);
1115 /* BLOCKs are handled in the expression walker below. */
1116 for (ns = ns->contained; ns; ns = ns->sibling)
1118 if (ns->code == NULL || ns->code->op != EXEC_BLOCK)
1119 optimize_reduction (ns);
1123 /* Replace code like
1124 a = matmul(b,c) + d
1125 with
1126 a = matmul(b,c) ; a = a + d
1127 where the array function is not elemental and not allocatable
1128 and does not depend on the left-hand side.
1131 static bool
1132 optimize_binop_array_assignment (gfc_code *c, gfc_expr **rhs, bool seen_op)
1134 gfc_expr *e;
1136 if (!*rhs)
1137 return false;
1139 e = *rhs;
1140 if (e->expr_type == EXPR_OP)
1142 switch (e->value.op.op)
1144 /* Unary operators and exponentiation: Only look at a single
1145 operand. */
1146 case INTRINSIC_NOT:
1147 case INTRINSIC_UPLUS:
1148 case INTRINSIC_UMINUS:
1149 case INTRINSIC_PARENTHESES:
1150 case INTRINSIC_POWER:
1151 if (optimize_binop_array_assignment (c, &e->value.op.op1, seen_op))
1152 return true;
1153 break;
1155 case INTRINSIC_CONCAT:
1156 /* Do not do string concatenations. */
1157 break;
1159 default:
1160 /* Binary operators. */
1161 if (optimize_binop_array_assignment (c, &e->value.op.op1, true))
1162 return true;
1164 if (optimize_binop_array_assignment (c, &e->value.op.op2, true))
1165 return true;
1167 break;
1170 else if (seen_op && e->expr_type == EXPR_FUNCTION && e->rank > 0
1171 && ! (e->value.function.esym
1172 && (e->value.function.esym->attr.elemental
1173 || e->value.function.esym->attr.allocatable
1174 || e->value.function.esym->ts.type != c->expr1->ts.type
1175 || e->value.function.esym->ts.kind != c->expr1->ts.kind))
1176 && ! (e->value.function.isym
1177 && (e->value.function.isym->elemental
1178 || e->ts.type != c->expr1->ts.type
1179 || e->ts.kind != c->expr1->ts.kind))
1180 && ! gfc_inline_intrinsic_function_p (e))
1183 gfc_code *n;
1184 gfc_expr *new_expr;
1186 /* Insert a new assignment statement after the current one. */
1187 n = XCNEW (gfc_code);
1188 n->op = EXEC_ASSIGN;
1189 n->loc = c->loc;
1190 n->next = c->next;
1191 c->next = n;
1193 n->expr1 = gfc_copy_expr (c->expr1);
1194 n->expr2 = c->expr2;
1195 new_expr = gfc_copy_expr (c->expr1);
1196 c->expr2 = e;
1197 *rhs = new_expr;
1199 return true;
1203 /* Nothing to optimize. */
1204 return false;
1207 /* Remove unneeded TRIMs at the end of expressions. */
1209 static bool
1210 remove_trim (gfc_expr *rhs)
1212 bool ret;
1214 ret = false;
1215 if (!rhs)
1216 return ret;
1218 /* Check for a // b // trim(c). Looping is probably not
1219 necessary because the parser usually generates
1220 (// (// a b ) trim(c) ) , but better safe than sorry. */
1222 while (rhs->expr_type == EXPR_OP
1223 && rhs->value.op.op == INTRINSIC_CONCAT)
1224 rhs = rhs->value.op.op2;
1226 while (rhs->expr_type == EXPR_FUNCTION && rhs->value.function.isym
1227 && rhs->value.function.isym->id == GFC_ISYM_TRIM)
1229 strip_function_call (rhs);
1230 /* Recursive call to catch silly stuff like trim ( a // trim(b)). */
1231 remove_trim (rhs);
1232 ret = true;
1235 return ret;
1238 /* Optimizations for an assignment. */
1240 static void
1241 optimize_assignment (gfc_code * c)
1243 gfc_expr *lhs, *rhs;
1245 lhs = c->expr1;
1246 rhs = c->expr2;
1248 if (lhs->ts.type == BT_CHARACTER && !lhs->ts.deferred)
1250 /* Optimize a = trim(b) to a = b. */
1251 remove_trim (rhs);
1253 /* Replace a = ' ' by a = '' to optimize away a memcpy. */
1254 if (is_empty_string (rhs))
1255 rhs->value.character.length = 0;
1258 if (lhs->rank > 0 && gfc_check_dependency (lhs, rhs, true) == 0)
1259 optimize_binop_array_assignment (c, &rhs, false);
1263 /* Remove an unneeded function call, modifying the expression.
1264 This replaces the function call with the value of its
1265 first argument. The rest of the argument list is freed. */
1267 static void
1268 strip_function_call (gfc_expr *e)
1270 gfc_expr *e1;
1271 gfc_actual_arglist *a;
1273 a = e->value.function.actual;
1275 /* We should have at least one argument. */
1276 gcc_assert (a->expr != NULL);
1278 e1 = a->expr;
1280 /* Free the remaining arglist, if any. */
1281 if (a->next)
1282 gfc_free_actual_arglist (a->next);
1284 /* Graft the argument expression onto the original function. */
1285 *e = *e1;
1286 free (e1);
1290 /* Optimization of lexical comparison functions. */
1292 static bool
1293 optimize_lexical_comparison (gfc_expr *e)
1295 if (e->expr_type != EXPR_FUNCTION || e->value.function.isym == NULL)
1296 return false;
1298 switch (e->value.function.isym->id)
1300 case GFC_ISYM_LLE:
1301 return optimize_comparison (e, INTRINSIC_LE);
1303 case GFC_ISYM_LGE:
1304 return optimize_comparison (e, INTRINSIC_GE);
1306 case GFC_ISYM_LGT:
1307 return optimize_comparison (e, INTRINSIC_GT);
1309 case GFC_ISYM_LLT:
1310 return optimize_comparison (e, INTRINSIC_LT);
1312 default:
1313 break;
1315 return false;
1318 /* Combine stuff like [a]>b into [a>b], for easier optimization later. Do not
1319 do CHARACTER because of possible pessimization involving character
1320 lengths. */
1322 static bool
1323 combine_array_constructor (gfc_expr *e)
1326 gfc_expr *op1, *op2;
1327 gfc_expr *scalar;
1328 gfc_expr *new_expr;
1329 gfc_constructor *c, *new_c;
1330 gfc_constructor_base oldbase, newbase;
1331 bool scalar_first;
1333 /* Array constructors have rank one. */
1334 if (e->rank != 1)
1335 return false;
1337 /* Don't try to combine association lists, this makes no sense
1338 and leads to an ICE. */
1339 if (in_assoc_list)
1340 return false;
1342 /* With FORALL, the BLOCKS created by create_var will cause an ICE. */
1343 if (forall_level > 0)
1344 return false;
1346 /* Inside an iterator, things can get hairy; we are likely to create
1347 an invalid temporary variable. */
1348 if (iterator_level > 0)
1349 return false;
1351 op1 = e->value.op.op1;
1352 op2 = e->value.op.op2;
1354 if (!op1 || !op2)
1355 return false;
1357 if (op1->expr_type == EXPR_ARRAY && op2->rank == 0)
1358 scalar_first = false;
1359 else if (op2->expr_type == EXPR_ARRAY && op1->rank == 0)
1361 scalar_first = true;
1362 op1 = e->value.op.op2;
1363 op2 = e->value.op.op1;
1365 else
1366 return false;
1368 if (op2->ts.type == BT_CHARACTER)
1369 return false;
1371 scalar = create_var (gfc_copy_expr (op2), "constr");
1373 oldbase = op1->value.constructor;
1374 newbase = NULL;
1375 e->expr_type = EXPR_ARRAY;
1377 for (c = gfc_constructor_first (oldbase); c;
1378 c = gfc_constructor_next (c))
1380 new_expr = gfc_get_expr ();
1381 new_expr->ts = e->ts;
1382 new_expr->expr_type = EXPR_OP;
1383 new_expr->rank = c->expr->rank;
1384 new_expr->where = c->expr->where;
1385 new_expr->value.op.op = e->value.op.op;
1387 if (scalar_first)
1389 new_expr->value.op.op1 = gfc_copy_expr (scalar);
1390 new_expr->value.op.op2 = gfc_copy_expr (c->expr);
1392 else
1394 new_expr->value.op.op1 = gfc_copy_expr (c->expr);
1395 new_expr->value.op.op2 = gfc_copy_expr (scalar);
1398 new_c = gfc_constructor_append_expr (&newbase, new_expr, &(e->where));
1399 new_c->iterator = c->iterator;
1400 c->iterator = NULL;
1403 gfc_free_expr (op1);
1404 gfc_free_expr (op2);
1405 gfc_free_expr (scalar);
1407 e->value.constructor = newbase;
1408 return true;
1411 /* Change (-1)**k into 1-ishift(iand(k,1),1) and
1412 2**k into ishift(1,k) */
1414 static bool
1415 optimize_power (gfc_expr *e)
1417 gfc_expr *op1, *op2;
1418 gfc_expr *iand, *ishft;
1420 if (e->ts.type != BT_INTEGER)
1421 return false;
1423 op1 = e->value.op.op1;
1425 if (op1 == NULL || op1->expr_type != EXPR_CONSTANT)
1426 return false;
1428 if (mpz_cmp_si (op1->value.integer, -1L) == 0)
1430 gfc_free_expr (op1);
1432 op2 = e->value.op.op2;
1434 if (op2 == NULL)
1435 return false;
1437 iand = gfc_build_intrinsic_call (current_ns, GFC_ISYM_IAND,
1438 "_internal_iand", e->where, 2, op2,
1439 gfc_get_int_expr (e->ts.kind,
1440 &e->where, 1));
1442 ishft = gfc_build_intrinsic_call (current_ns, GFC_ISYM_ISHFT,
1443 "_internal_ishft", e->where, 2, iand,
1444 gfc_get_int_expr (e->ts.kind,
1445 &e->where, 1));
1447 e->value.op.op = INTRINSIC_MINUS;
1448 e->value.op.op1 = gfc_get_int_expr (e->ts.kind, &e->where, 1);
1449 e->value.op.op2 = ishft;
1450 return true;
1452 else if (mpz_cmp_si (op1->value.integer, 2L) == 0)
1454 gfc_free_expr (op1);
1456 op2 = e->value.op.op2;
1457 if (op2 == NULL)
1458 return false;
1460 ishft = gfc_build_intrinsic_call (current_ns, GFC_ISYM_ISHFT,
1461 "_internal_ishft", e->where, 2,
1462 gfc_get_int_expr (e->ts.kind,
1463 &e->where, 1),
1464 op2);
1465 *e = *ishft;
1466 return true;
1469 else if (mpz_cmp_si (op1->value.integer, 1L) == 0)
1471 op2 = e->value.op.op2;
1472 if (op2 == NULL)
1473 return false;
1475 gfc_free_expr (op1);
1476 gfc_free_expr (op2);
1478 e->expr_type = EXPR_CONSTANT;
1479 e->value.op.op1 = NULL;
1480 e->value.op.op2 = NULL;
1481 mpz_init_set_si (e->value.integer, 1);
1482 /* Typespec and location are still OK. */
1483 return true;
1486 return false;
1489 /* Recursive optimization of operators. */
1491 static bool
1492 optimize_op (gfc_expr *e)
1494 bool changed;
1496 gfc_intrinsic_op op = e->value.op.op;
1498 changed = false;
1500 /* Only use new-style comparisons. */
1501 switch(op)
1503 case INTRINSIC_EQ_OS:
1504 op = INTRINSIC_EQ;
1505 break;
1507 case INTRINSIC_GE_OS:
1508 op = INTRINSIC_GE;
1509 break;
1511 case INTRINSIC_LE_OS:
1512 op = INTRINSIC_LE;
1513 break;
1515 case INTRINSIC_NE_OS:
1516 op = INTRINSIC_NE;
1517 break;
1519 case INTRINSIC_GT_OS:
1520 op = INTRINSIC_GT;
1521 break;
1523 case INTRINSIC_LT_OS:
1524 op = INTRINSIC_LT;
1525 break;
1527 default:
1528 break;
1531 switch (op)
1533 case INTRINSIC_EQ:
1534 case INTRINSIC_GE:
1535 case INTRINSIC_LE:
1536 case INTRINSIC_NE:
1537 case INTRINSIC_GT:
1538 case INTRINSIC_LT:
1539 changed = optimize_comparison (e, op);
1541 gcc_fallthrough ();
1542 /* Look at array constructors. */
1543 case INTRINSIC_PLUS:
1544 case INTRINSIC_MINUS:
1545 case INTRINSIC_TIMES:
1546 case INTRINSIC_DIVIDE:
1547 return combine_array_constructor (e) || changed;
1549 case INTRINSIC_POWER:
1550 return optimize_power (e);
1552 default:
1553 break;
1556 return false;
1560 /* Return true if a constant string contains only blanks. */
1562 static bool
1563 is_empty_string (gfc_expr *e)
1565 int i;
1567 if (e->ts.type != BT_CHARACTER || e->expr_type != EXPR_CONSTANT)
1568 return false;
1570 for (i=0; i < e->value.character.length; i++)
1572 if (e->value.character.string[i] != ' ')
1573 return false;
1576 return true;
1580 /* Insert a call to the intrinsic len_trim. Use a different name for
1581 the symbol tree so we don't run into trouble when the user has
1582 renamed len_trim for some reason. */
1584 static gfc_expr*
1585 get_len_trim_call (gfc_expr *str, int kind)
1587 gfc_expr *fcn;
1588 gfc_actual_arglist *actual_arglist, *next;
1590 fcn = gfc_get_expr ();
1591 fcn->expr_type = EXPR_FUNCTION;
1592 fcn->value.function.isym = gfc_intrinsic_function_by_id (GFC_ISYM_LEN_TRIM);
1593 actual_arglist = gfc_get_actual_arglist ();
1594 actual_arglist->expr = str;
1595 next = gfc_get_actual_arglist ();
1596 next->expr = gfc_get_int_expr (gfc_default_integer_kind, NULL, kind);
1597 actual_arglist->next = next;
1599 fcn->value.function.actual = actual_arglist;
1600 fcn->where = str->where;
1601 fcn->ts.type = BT_INTEGER;
1602 fcn->ts.kind = gfc_charlen_int_kind;
1604 gfc_get_sym_tree ("__internal_len_trim", current_ns, &fcn->symtree, false);
1605 fcn->symtree->n.sym->ts = fcn->ts;
1606 fcn->symtree->n.sym->attr.flavor = FL_PROCEDURE;
1607 fcn->symtree->n.sym->attr.function = 1;
1608 fcn->symtree->n.sym->attr.elemental = 1;
1609 fcn->symtree->n.sym->attr.referenced = 1;
1610 fcn->symtree->n.sym->attr.access = ACCESS_PRIVATE;
1611 gfc_commit_symbol (fcn->symtree->n.sym);
1613 return fcn;
1616 /* Optimize expressions for equality. */
1618 static bool
1619 optimize_comparison (gfc_expr *e, gfc_intrinsic_op op)
1621 gfc_expr *op1, *op2;
1622 bool change;
1623 int eq;
1624 bool result;
1625 gfc_actual_arglist *firstarg, *secondarg;
1627 if (e->expr_type == EXPR_OP)
1629 firstarg = NULL;
1630 secondarg = NULL;
1631 op1 = e->value.op.op1;
1632 op2 = e->value.op.op2;
1634 else if (e->expr_type == EXPR_FUNCTION)
1636 /* One of the lexical comparison functions. */
1637 firstarg = e->value.function.actual;
1638 secondarg = firstarg->next;
1639 op1 = firstarg->expr;
1640 op2 = secondarg->expr;
1642 else
1643 gcc_unreachable ();
1645 /* Strip off unneeded TRIM calls from string comparisons. */
1647 change = remove_trim (op1);
1649 if (remove_trim (op2))
1650 change = true;
1652 /* An expression of type EXPR_CONSTANT is only valid for scalars. */
1653 /* TODO: A scalar constant may be acceptable in some cases (the scalarizer
1654 handles them well). However, there are also cases that need a non-scalar
1655 argument. For example the any intrinsic. See PR 45380. */
1656 if (e->rank > 0)
1657 return change;
1659 /* Replace a == '' with len_trim(a) == 0 and a /= '' with
1660 len_trim(a) != 0 */
1661 if (op1->ts.type == BT_CHARACTER && op2->ts.type == BT_CHARACTER
1662 && (op == INTRINSIC_EQ || op == INTRINSIC_NE))
1664 bool empty_op1, empty_op2;
1665 empty_op1 = is_empty_string (op1);
1666 empty_op2 = is_empty_string (op2);
1668 if (empty_op1 || empty_op2)
1670 gfc_expr *fcn;
1671 gfc_expr *zero;
1672 gfc_expr *str;
1674 /* This can only happen when an error for comparing
1675 characters of different kinds has already been issued. */
1676 if (empty_op1 && empty_op2)
1677 return false;
1679 zero = gfc_get_int_expr (gfc_charlen_int_kind, &e->where, 0);
1680 str = empty_op1 ? op2 : op1;
1682 fcn = get_len_trim_call (str, gfc_charlen_int_kind);
1685 if (empty_op1)
1686 gfc_free_expr (op1);
1687 else
1688 gfc_free_expr (op2);
1690 op1 = fcn;
1691 op2 = zero;
1692 e->value.op.op1 = fcn;
1693 e->value.op.op2 = zero;
1698 /* Don't compare REAL or COMPLEX expressions when honoring NaNs. */
1700 if (flag_finite_math_only
1701 || (op1->ts.type != BT_REAL && op2->ts.type != BT_REAL
1702 && op1->ts.type != BT_COMPLEX && op2->ts.type != BT_COMPLEX))
1704 eq = gfc_dep_compare_expr (op1, op2);
1705 if (eq <= -2)
1707 /* Replace A // B < A // C with B < C, and A // B < C // B
1708 with A < C. */
1709 if (op1->ts.type == BT_CHARACTER && op2->ts.type == BT_CHARACTER
1710 && op1->expr_type == EXPR_OP
1711 && op1->value.op.op == INTRINSIC_CONCAT
1712 && op2->expr_type == EXPR_OP
1713 && op2->value.op.op == INTRINSIC_CONCAT)
1715 gfc_expr *op1_left = op1->value.op.op1;
1716 gfc_expr *op2_left = op2->value.op.op1;
1717 gfc_expr *op1_right = op1->value.op.op2;
1718 gfc_expr *op2_right = op2->value.op.op2;
1720 if (gfc_dep_compare_expr (op1_left, op2_left) == 0)
1722 /* Watch out for 'A ' // x vs. 'A' // x. */
1724 if (op1_left->expr_type == EXPR_CONSTANT
1725 && op2_left->expr_type == EXPR_CONSTANT
1726 && op1_left->value.character.length
1727 != op2_left->value.character.length)
1728 return change;
1729 else
1731 free (op1_left);
1732 free (op2_left);
1733 if (firstarg)
1735 firstarg->expr = op1_right;
1736 secondarg->expr = op2_right;
1738 else
1740 e->value.op.op1 = op1_right;
1741 e->value.op.op2 = op2_right;
1743 optimize_comparison (e, op);
1744 return true;
1747 if (gfc_dep_compare_expr (op1_right, op2_right) == 0)
1749 free (op1_right);
1750 free (op2_right);
1751 if (firstarg)
1753 firstarg->expr = op1_left;
1754 secondarg->expr = op2_left;
1756 else
1758 e->value.op.op1 = op1_left;
1759 e->value.op.op2 = op2_left;
1762 optimize_comparison (e, op);
1763 return true;
1767 else
1769 /* eq can only be -1, 0 or 1 at this point. */
1770 switch (op)
1772 case INTRINSIC_EQ:
1773 result = eq == 0;
1774 break;
1776 case INTRINSIC_GE:
1777 result = eq >= 0;
1778 break;
1780 case INTRINSIC_LE:
1781 result = eq <= 0;
1782 break;
1784 case INTRINSIC_NE:
1785 result = eq != 0;
1786 break;
1788 case INTRINSIC_GT:
1789 result = eq > 0;
1790 break;
1792 case INTRINSIC_LT:
1793 result = eq < 0;
1794 break;
1796 default:
1797 gfc_internal_error ("illegal OP in optimize_comparison");
1798 break;
1801 /* Replace the expression by a constant expression. The typespec
1802 and where remains the way it is. */
1803 free (op1);
1804 free (op2);
1805 e->expr_type = EXPR_CONSTANT;
1806 e->value.logical = result;
1807 return true;
1811 return change;
1814 /* Optimize a trim function by replacing it with an equivalent substring
1815 involving a call to len_trim. This only works for expressions where
1816 variables are trimmed. Return true if anything was modified. */
1818 static bool
1819 optimize_trim (gfc_expr *e)
1821 gfc_expr *a;
1822 gfc_ref *ref;
1823 gfc_expr *fcn;
1824 gfc_ref **rr = NULL;
1826 /* Don't do this optimization within an argument list, because
1827 otherwise aliasing issues may occur. */
1829 if (count_arglist != 1)
1830 return false;
1832 if (e->ts.type != BT_CHARACTER || e->expr_type != EXPR_FUNCTION
1833 || e->value.function.isym == NULL
1834 || e->value.function.isym->id != GFC_ISYM_TRIM)
1835 return false;
1837 a = e->value.function.actual->expr;
1839 if (a->expr_type != EXPR_VARIABLE)
1840 return false;
1842 /* This would pessimize the idiom a = trim(a) for reallocatable strings. */
1844 if (a->symtree->n.sym->attr.allocatable)
1845 return false;
1847 /* Follow all references to find the correct place to put the newly
1848 created reference. FIXME: Also handle substring references and
1849 array references. Array references cause strange regressions at
1850 the moment. */
1852 if (a->ref)
1854 for (rr = &(a->ref); *rr; rr = &((*rr)->next))
1856 if ((*rr)->type == REF_SUBSTRING || (*rr)->type == REF_ARRAY)
1857 return false;
1861 strip_function_call (e);
1863 if (e->ref == NULL)
1864 rr = &(e->ref);
1866 /* Create the reference. */
1868 ref = gfc_get_ref ();
1869 ref->type = REF_SUBSTRING;
1871 /* Set the start of the reference. */
1873 ref->u.ss.start = gfc_get_int_expr (gfc_default_integer_kind, NULL, 1);
1875 /* Build the function call to len_trim(x, gfc_default_integer_kind). */
1877 fcn = get_len_trim_call (gfc_copy_expr (e), gfc_default_integer_kind);
1879 /* Set the end of the reference to the call to len_trim. */
1881 ref->u.ss.end = fcn;
1882 gcc_assert (rr != NULL && *rr == NULL);
1883 *rr = ref;
1884 return true;
1887 /* Optimize minloc(b), where b is rank 1 array, into
1888 (/ minloc(b, dim=1) /), and similarly for maxloc,
1889 as the latter forms are expanded inline. */
1891 static void
1892 optimize_minmaxloc (gfc_expr **e)
1894 gfc_expr *fn = *e;
1895 gfc_actual_arglist *a;
1896 char *name, *p;
1898 if (fn->rank != 1
1899 || fn->value.function.actual == NULL
1900 || fn->value.function.actual->expr == NULL
1901 || fn->value.function.actual->expr->rank != 1)
1902 return;
1904 *e = gfc_get_array_expr (fn->ts.type, fn->ts.kind, &fn->where);
1905 (*e)->shape = fn->shape;
1906 fn->rank = 0;
1907 fn->shape = NULL;
1908 gfc_constructor_append_expr (&(*e)->value.constructor, fn, &fn->where);
1910 name = XALLOCAVEC (char, strlen (fn->value.function.name) + 1);
1911 strcpy (name, fn->value.function.name);
1912 p = strstr (name, "loc0");
1913 p[3] = '1';
1914 fn->value.function.name = gfc_get_string ("%s", name);
1915 if (fn->value.function.actual->next)
1917 a = fn->value.function.actual->next;
1918 gcc_assert (a->expr == NULL);
1920 else
1922 a = gfc_get_actual_arglist ();
1923 fn->value.function.actual->next = a;
1925 a->expr = gfc_get_constant_expr (BT_INTEGER, gfc_default_integer_kind,
1926 &fn->where);
1927 mpz_set_ui (a->expr->value.integer, 1);
1930 /* Callback function for code checking that we do not pass a DO variable to an
1931 INTENT(OUT) or INTENT(INOUT) dummy variable. */
1933 static int
1934 doloop_code (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
1935 void *data ATTRIBUTE_UNUSED)
1937 gfc_code *co;
1938 int i;
1939 gfc_formal_arglist *f;
1940 gfc_actual_arglist *a;
1941 gfc_code *cl;
1943 co = *c;
1945 /* If the doloop_list grew, we have to truncate it here. */
1947 if ((unsigned) doloop_level < doloop_list.length())
1948 doloop_list.truncate (doloop_level);
1950 switch (co->op)
1952 case EXEC_DO:
1954 if (co->ext.iterator && co->ext.iterator->var)
1955 doloop_list.safe_push (co);
1956 else
1957 doloop_list.safe_push ((gfc_code *) NULL);
1958 break;
1960 case EXEC_CALL:
1962 if (co->resolved_sym == NULL)
1963 break;
1965 f = gfc_sym_get_dummy_args (co->resolved_sym);
1967 /* Withot a formal arglist, there is only unknown INTENT,
1968 which we don't check for. */
1969 if (f == NULL)
1970 break;
1972 a = co->ext.actual;
1974 while (a && f)
1976 FOR_EACH_VEC_ELT (doloop_list, i, cl)
1978 gfc_symbol *do_sym;
1980 if (cl == NULL)
1981 break;
1983 do_sym = cl->ext.iterator->var->symtree->n.sym;
1985 if (a->expr && a->expr->symtree
1986 && a->expr->symtree->n.sym == do_sym)
1988 if (f->sym->attr.intent == INTENT_OUT)
1989 gfc_error_now ("Variable %qs at %L set to undefined "
1990 "value inside loop beginning at %L as "
1991 "INTENT(OUT) argument to subroutine %qs",
1992 do_sym->name, &a->expr->where,
1993 &doloop_list[i]->loc,
1994 co->symtree->n.sym->name);
1995 else if (f->sym->attr.intent == INTENT_INOUT)
1996 gfc_error_now ("Variable %qs at %L not definable inside "
1997 "loop beginning at %L as INTENT(INOUT) "
1998 "argument to subroutine %qs",
1999 do_sym->name, &a->expr->where,
2000 &doloop_list[i]->loc,
2001 co->symtree->n.sym->name);
2004 a = a->next;
2005 f = f->next;
2007 break;
2009 default:
2010 break;
2012 return 0;
2015 /* Callback function for functions checking that we do not pass a DO variable
2016 to an INTENT(OUT) or INTENT(INOUT) dummy variable. */
2018 static int
2019 do_function (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
2020 void *data ATTRIBUTE_UNUSED)
2022 gfc_formal_arglist *f;
2023 gfc_actual_arglist *a;
2024 gfc_expr *expr;
2025 gfc_code *dl;
2026 int i;
2028 expr = *e;
2029 if (expr->expr_type != EXPR_FUNCTION)
2030 return 0;
2032 /* Intrinsic functions don't modify their arguments. */
2034 if (expr->value.function.isym)
2035 return 0;
2037 f = gfc_sym_get_dummy_args (expr->symtree->n.sym);
2039 /* Without a formal arglist, there is only unknown INTENT,
2040 which we don't check for. */
2041 if (f == NULL)
2042 return 0;
2044 a = expr->value.function.actual;
2046 while (a && f)
2048 FOR_EACH_VEC_ELT (doloop_list, i, dl)
2050 gfc_symbol *do_sym;
2052 if (dl == NULL)
2053 break;
2055 do_sym = dl->ext.iterator->var->symtree->n.sym;
2057 if (a->expr && a->expr->symtree
2058 && a->expr->symtree->n.sym == do_sym)
2060 if (f->sym->attr.intent == INTENT_OUT)
2061 gfc_error_now ("Variable %qs at %L set to undefined value "
2062 "inside loop beginning at %L as INTENT(OUT) "
2063 "argument to function %qs", do_sym->name,
2064 &a->expr->where, &doloop_list[i]->loc,
2065 expr->symtree->n.sym->name);
2066 else if (f->sym->attr.intent == INTENT_INOUT)
2067 gfc_error_now ("Variable %qs at %L not definable inside loop"
2068 " beginning at %L as INTENT(INOUT) argument to"
2069 " function %qs", do_sym->name,
2070 &a->expr->where, &doloop_list[i]->loc,
2071 expr->symtree->n.sym->name);
2074 a = a->next;
2075 f = f->next;
2078 return 0;
2081 static void
2082 doloop_warn (gfc_namespace *ns)
2084 gfc_code_walker (&ns->code, doloop_code, do_function, NULL);
2087 /* This selction deals with inlining calls to MATMUL. */
2089 /* Auxiliary function to build and simplify an array inquiry function.
2090 dim is zero-based. */
2092 static gfc_expr *
2093 get_array_inq_function (gfc_isym_id id, gfc_expr *e, int dim)
2095 gfc_expr *fcn;
2096 gfc_expr *dim_arg, *kind;
2097 const char *name;
2098 gfc_expr *ec;
2100 switch (id)
2102 case GFC_ISYM_LBOUND:
2103 name = "_gfortran_lbound";
2104 break;
2106 case GFC_ISYM_UBOUND:
2107 name = "_gfortran_ubound";
2108 break;
2110 case GFC_ISYM_SIZE:
2111 name = "_gfortran_size";
2112 break;
2114 default:
2115 gcc_unreachable ();
2118 dim_arg = gfc_get_int_expr (gfc_default_integer_kind, &e->where, dim);
2119 kind = gfc_get_int_expr (gfc_default_integer_kind, &e->where,
2120 gfc_index_integer_kind);
2122 ec = gfc_copy_expr (e);
2123 fcn = gfc_build_intrinsic_call (current_ns, id, name, e->where, 3,
2124 ec, dim_arg, kind);
2125 gfc_simplify_expr (fcn, 0);
2126 return fcn;
2129 /* Builds a logical expression. */
2131 static gfc_expr*
2132 build_logical_expr (gfc_intrinsic_op op, gfc_expr *e1, gfc_expr *e2)
2134 gfc_typespec ts;
2135 gfc_expr *res;
2137 ts.type = BT_LOGICAL;
2138 ts.kind = gfc_default_logical_kind;
2139 res = gfc_get_expr ();
2140 res->where = e1->where;
2141 res->expr_type = EXPR_OP;
2142 res->value.op.op = op;
2143 res->value.op.op1 = e1;
2144 res->value.op.op2 = e2;
2145 res->ts = ts;
2147 return res;
2151 /* Return an operation of one two gfc_expr (one if e2 is NULL). This assumes
2152 compatible typespecs. */
2154 static gfc_expr *
2155 get_operand (gfc_intrinsic_op op, gfc_expr *e1, gfc_expr *e2)
2157 gfc_expr *res;
2159 res = gfc_get_expr ();
2160 res->ts = e1->ts;
2161 res->where = e1->where;
2162 res->expr_type = EXPR_OP;
2163 res->value.op.op = op;
2164 res->value.op.op1 = e1;
2165 res->value.op.op2 = e2;
2166 gfc_simplify_expr (res, 0);
2167 return res;
2170 /* Generate the IF statement for a runtime check if we want to do inlining or
2171 not - putting in the code for both branches and putting it into the syntax
2172 tree is the caller's responsibility. For fixed array sizes, this should be
2173 removed by DCE. Only called for rank-two matrices A and B. */
2175 static gfc_code *
2176 inline_limit_check (gfc_expr *a, gfc_expr *b, enum matrix_case m_case)
2178 gfc_expr *inline_limit;
2179 gfc_code *if_1, *if_2, *else_2;
2180 gfc_expr *b2, *a2, *a1, *m1, *m2;
2181 gfc_typespec ts;
2182 gfc_expr *cond;
2184 gcc_assert (m_case == A2B2 || m_case == A2B2T);
2186 /* Calculation is done in real to avoid integer overflow. */
2188 inline_limit = gfc_get_constant_expr (BT_REAL, gfc_default_real_kind,
2189 &a->where);
2190 mpfr_set_si (inline_limit->value.real, flag_inline_matmul_limit,
2191 GFC_RND_MODE);
2192 mpfr_pow_ui (inline_limit->value.real, inline_limit->value.real, 3,
2193 GFC_RND_MODE);
2195 a1 = get_array_inq_function (GFC_ISYM_SIZE, a, 1);
2196 a2 = get_array_inq_function (GFC_ISYM_SIZE, a, 2);
2197 b2 = get_array_inq_function (GFC_ISYM_SIZE, b, 2);
2199 gfc_clear_ts (&ts);
2200 ts.type = BT_REAL;
2201 ts.kind = gfc_default_real_kind;
2202 gfc_convert_type_warn (a1, &ts, 2, 0);
2203 gfc_convert_type_warn (a2, &ts, 2, 0);
2204 gfc_convert_type_warn (b2, &ts, 2, 0);
2206 m1 = get_operand (INTRINSIC_TIMES, a1, a2);
2207 m2 = get_operand (INTRINSIC_TIMES, m1, b2);
2209 cond = build_logical_expr (INTRINSIC_LE, m2, inline_limit);
2210 gfc_simplify_expr (cond, 0);
2212 else_2 = XCNEW (gfc_code);
2213 else_2->op = EXEC_IF;
2214 else_2->loc = a->where;
2216 if_2 = XCNEW (gfc_code);
2217 if_2->op = EXEC_IF;
2218 if_2->expr1 = cond;
2219 if_2->loc = a->where;
2220 if_2->block = else_2;
2222 if_1 = XCNEW (gfc_code);
2223 if_1->op = EXEC_IF;
2224 if_1->block = if_2;
2225 if_1->loc = a->where;
2227 return if_1;
2231 /* Insert code to issue a runtime error if the expressions are not equal. */
2233 static gfc_code *
2234 runtime_error_ne (gfc_expr *e1, gfc_expr *e2, const char *msg)
2236 gfc_expr *cond;
2237 gfc_code *if_1, *if_2;
2238 gfc_code *c;
2239 gfc_actual_arglist *a1, *a2, *a3;
2241 gcc_assert (e1->where.lb);
2242 /* Build the call to runtime_error. */
2243 c = XCNEW (gfc_code);
2244 c->op = EXEC_CALL;
2245 c->loc = e1->where;
2247 /* Get a null-terminated message string. */
2249 a1 = gfc_get_actual_arglist ();
2250 a1->expr = gfc_get_character_expr (gfc_default_character_kind, &e1->where,
2251 msg, strlen(msg)+1);
2252 c->ext.actual = a1;
2254 /* Pass the value of the first expression. */
2255 a2 = gfc_get_actual_arglist ();
2256 a2->expr = gfc_copy_expr (e1);
2257 a1->next = a2;
2259 /* Pass the value of the second expression. */
2260 a3 = gfc_get_actual_arglist ();
2261 a3->expr = gfc_copy_expr (e2);
2262 a2->next = a3;
2264 gfc_check_fe_runtime_error (c->ext.actual);
2265 gfc_resolve_fe_runtime_error (c);
2267 if_2 = XCNEW (gfc_code);
2268 if_2->op = EXEC_IF;
2269 if_2->loc = e1->where;
2270 if_2->next = c;
2272 if_1 = XCNEW (gfc_code);
2273 if_1->op = EXEC_IF;
2274 if_1->block = if_2;
2275 if_1->loc = e1->where;
2277 cond = build_logical_expr (INTRINSIC_NE, e1, e2);
2278 gfc_simplify_expr (cond, 0);
2279 if_2->expr1 = cond;
2281 return if_1;
2284 /* Handle matrix reallocation. Caller is responsible to insert into
2285 the code tree.
2287 For the two-dimensional case, build
2289 if (allocated(c)) then
2290 if (size(c,1) /= size(a,1) .or. size(c,2) /= size(b,2)) then
2291 deallocate(c)
2292 allocate (c(size(a,1), size(b,2)))
2293 end if
2294 else
2295 allocate (c(size(a,1),size(b,2)))
2296 end if
2298 and for the other cases correspondingly.
2301 static gfc_code *
2302 matmul_lhs_realloc (gfc_expr *c, gfc_expr *a, gfc_expr *b,
2303 enum matrix_case m_case)
2306 gfc_expr *allocated, *alloc_expr;
2307 gfc_code *if_alloc_1, *if_alloc_2, *if_size_1, *if_size_2;
2308 gfc_code *else_alloc;
2309 gfc_code *deallocate, *allocate1, *allocate_else;
2310 gfc_array_ref *ar;
2311 gfc_expr *cond, *ne1, *ne2;
2313 if (warn_realloc_lhs)
2314 gfc_warning (OPT_Wrealloc_lhs,
2315 "Code for reallocating the allocatable array at %L will "
2316 "be added", &c->where);
2318 alloc_expr = gfc_copy_expr (c);
2320 ar = gfc_find_array_ref (alloc_expr);
2321 gcc_assert (ar && ar->type == AR_FULL);
2323 /* c comes in as a full ref. Change it into a copy and make it into an
2324 element ref so it has the right form for for ALLOCATE. In the same
2325 switch statement, also generate the size comparison for the secod IF
2326 statement. */
2328 ar->type = AR_ELEMENT;
2330 switch (m_case)
2332 case A2B2:
2333 ar->start[0] = get_array_inq_function (GFC_ISYM_SIZE, a, 1);
2334 ar->start[1] = get_array_inq_function (GFC_ISYM_SIZE, b, 2);
2335 ne1 = build_logical_expr (INTRINSIC_NE,
2336 get_array_inq_function (GFC_ISYM_SIZE, c, 1),
2337 get_array_inq_function (GFC_ISYM_SIZE, a, 1));
2338 ne2 = build_logical_expr (INTRINSIC_NE,
2339 get_array_inq_function (GFC_ISYM_SIZE, c, 2),
2340 get_array_inq_function (GFC_ISYM_SIZE, b, 2));
2341 cond = build_logical_expr (INTRINSIC_OR, ne1, ne2);
2342 break;
2344 case A2B2T:
2345 ar->start[0] = get_array_inq_function (GFC_ISYM_SIZE, a, 1);
2346 ar->start[1] = get_array_inq_function (GFC_ISYM_SIZE, b, 1);
2348 ne1 = build_logical_expr (INTRINSIC_NE,
2349 get_array_inq_function (GFC_ISYM_SIZE, c, 1),
2350 get_array_inq_function (GFC_ISYM_SIZE, a, 1));
2351 ne2 = build_logical_expr (INTRINSIC_NE,
2352 get_array_inq_function (GFC_ISYM_SIZE, c, 2),
2353 get_array_inq_function (GFC_ISYM_SIZE, b, 1));
2354 cond = build_logical_expr (INTRINSIC_OR, ne1, ne2);
2355 break;
2357 case A2B1:
2358 ar->start[0] = get_array_inq_function (GFC_ISYM_SIZE, a, 1);
2359 cond = build_logical_expr (INTRINSIC_NE,
2360 get_array_inq_function (GFC_ISYM_SIZE, c, 1),
2361 get_array_inq_function (GFC_ISYM_SIZE, a, 2));
2362 break;
2364 case A1B2:
2365 ar->start[0] = get_array_inq_function (GFC_ISYM_SIZE, b, 1);
2366 cond = build_logical_expr (INTRINSIC_NE,
2367 get_array_inq_function (GFC_ISYM_SIZE, c, 1),
2368 get_array_inq_function (GFC_ISYM_SIZE, b, 2));
2369 break;
2371 default:
2372 gcc_unreachable();
2376 gfc_simplify_expr (cond, 0);
2378 /* We need two identical allocate statements in two
2379 branches of the IF statement. */
2381 allocate1 = XCNEW (gfc_code);
2382 allocate1->op = EXEC_ALLOCATE;
2383 allocate1->ext.alloc.list = gfc_get_alloc ();
2384 allocate1->loc = c->where;
2385 allocate1->ext.alloc.list->expr = gfc_copy_expr (alloc_expr);
2387 allocate_else = XCNEW (gfc_code);
2388 allocate_else->op = EXEC_ALLOCATE;
2389 allocate_else->ext.alloc.list = gfc_get_alloc ();
2390 allocate_else->loc = c->where;
2391 allocate_else->ext.alloc.list->expr = alloc_expr;
2393 allocated = gfc_build_intrinsic_call (current_ns, GFC_ISYM_ALLOCATED,
2394 "_gfortran_allocated", c->where,
2395 1, gfc_copy_expr (c));
2397 deallocate = XCNEW (gfc_code);
2398 deallocate->op = EXEC_DEALLOCATE;
2399 deallocate->ext.alloc.list = gfc_get_alloc ();
2400 deallocate->ext.alloc.list->expr = gfc_copy_expr (c);
2401 deallocate->next = allocate1;
2402 deallocate->loc = c->where;
2404 if_size_2 = XCNEW (gfc_code);
2405 if_size_2->op = EXEC_IF;
2406 if_size_2->expr1 = cond;
2407 if_size_2->loc = c->where;
2408 if_size_2->next = deallocate;
2410 if_size_1 = XCNEW (gfc_code);
2411 if_size_1->op = EXEC_IF;
2412 if_size_1->block = if_size_2;
2413 if_size_1->loc = c->where;
2415 else_alloc = XCNEW (gfc_code);
2416 else_alloc->op = EXEC_IF;
2417 else_alloc->loc = c->where;
2418 else_alloc->next = allocate_else;
2420 if_alloc_2 = XCNEW (gfc_code);
2421 if_alloc_2->op = EXEC_IF;
2422 if_alloc_2->expr1 = allocated;
2423 if_alloc_2->loc = c->where;
2424 if_alloc_2->next = if_size_1;
2425 if_alloc_2->block = else_alloc;
2427 if_alloc_1 = XCNEW (gfc_code);
2428 if_alloc_1->op = EXEC_IF;
2429 if_alloc_1->block = if_alloc_2;
2430 if_alloc_1->loc = c->where;
2432 return if_alloc_1;
2435 /* Callback function for has_function_or_op. */
2437 static int
2438 is_function_or_op (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
2439 void *data ATTRIBUTE_UNUSED)
2441 if ((*e) == 0)
2442 return 0;
2443 else
2444 return (*e)->expr_type == EXPR_FUNCTION
2445 || (*e)->expr_type == EXPR_OP;
2448 /* Returns true if the expression contains a function. */
2450 static bool
2451 has_function_or_op (gfc_expr **e)
2453 if (e == NULL)
2454 return false;
2455 else
2456 return gfc_expr_walker (e, is_function_or_op, NULL);
2459 /* Freeze (assign to a temporary variable) a single expression. */
2461 static void
2462 freeze_expr (gfc_expr **ep)
2464 gfc_expr *ne;
2465 if (has_function_or_op (ep))
2467 ne = create_var (*ep, "freeze");
2468 *ep = ne;
2472 /* Go through an expression's references and assign them to temporary
2473 variables if they contain functions. This is usually done prior to
2474 front-end scalarization to avoid multiple invocations of functions. */
2476 static void
2477 freeze_references (gfc_expr *e)
2479 gfc_ref *r;
2480 gfc_array_ref *ar;
2481 int i;
2483 for (r=e->ref; r; r=r->next)
2485 if (r->type == REF_SUBSTRING)
2487 if (r->u.ss.start != NULL)
2488 freeze_expr (&r->u.ss.start);
2490 if (r->u.ss.end != NULL)
2491 freeze_expr (&r->u.ss.end);
2493 else if (r->type == REF_ARRAY)
2495 ar = &r->u.ar;
2496 switch (ar->type)
2498 case AR_FULL:
2499 break;
2501 case AR_SECTION:
2502 for (i=0; i<ar->dimen; i++)
2504 if (ar->dimen_type[i] == DIMEN_RANGE)
2506 freeze_expr (&ar->start[i]);
2507 freeze_expr (&ar->end[i]);
2508 freeze_expr (&ar->stride[i]);
2510 else if (ar->dimen_type[i] == DIMEN_ELEMENT)
2512 freeze_expr (&ar->start[i]);
2515 break;
2517 case AR_ELEMENT:
2518 for (i=0; i<ar->dimen; i++)
2519 freeze_expr (&ar->start[i]);
2520 break;
2522 default:
2523 break;
2529 /* Convert to gfc_index_integer_kind if needed, just do a copy otherwise. */
2531 static gfc_expr *
2532 convert_to_index_kind (gfc_expr *e)
2534 gfc_expr *res;
2536 gcc_assert (e != NULL);
2538 res = gfc_copy_expr (e);
2540 gcc_assert (e->ts.type == BT_INTEGER);
2542 if (res->ts.kind != gfc_index_integer_kind)
2544 gfc_typespec ts;
2545 gfc_clear_ts (&ts);
2546 ts.type = BT_INTEGER;
2547 ts.kind = gfc_index_integer_kind;
2549 gfc_convert_type_warn (e, &ts, 2, 0);
2552 return res;
2555 /* Function to create a DO loop including creation of the
2556 iteration variable. gfc_expr are copied.*/
2558 static gfc_code *
2559 create_do_loop (gfc_expr *start, gfc_expr *end, gfc_expr *step, locus *where,
2560 gfc_namespace *ns, char *vname)
2563 char name[GFC_MAX_SYMBOL_LEN +1];
2564 gfc_symtree *symtree;
2565 gfc_symbol *symbol;
2566 gfc_expr *i;
2567 gfc_code *n, *n2;
2569 /* Create an expression for the iteration variable. */
2570 if (vname)
2571 sprintf (name, "__var_%d_do_%s", var_num++, vname);
2572 else
2573 sprintf (name, "__var_%d_do", var_num++);
2576 if (gfc_get_sym_tree (name, ns, &symtree, false) != 0)
2577 gcc_unreachable ();
2579 /* Create the loop variable. */
2581 symbol = symtree->n.sym;
2582 symbol->ts.type = BT_INTEGER;
2583 symbol->ts.kind = gfc_index_integer_kind;
2584 symbol->attr.flavor = FL_VARIABLE;
2585 symbol->attr.referenced = 1;
2586 symbol->attr.dimension = 0;
2587 symbol->attr.fe_temp = 1;
2588 gfc_commit_symbol (symbol);
2590 i = gfc_get_expr ();
2591 i->expr_type = EXPR_VARIABLE;
2592 i->ts = symbol->ts;
2593 i->rank = 0;
2594 i->where = *where;
2595 i->symtree = symtree;
2597 /* ... and the nested DO statements. */
2598 n = XCNEW (gfc_code);
2599 n->op = EXEC_DO;
2600 n->loc = *where;
2601 n->ext.iterator = gfc_get_iterator ();
2602 n->ext.iterator->var = i;
2603 n->ext.iterator->start = convert_to_index_kind (start);
2604 n->ext.iterator->end = convert_to_index_kind (end);
2605 if (step)
2606 n->ext.iterator->step = convert_to_index_kind (step);
2607 else
2608 n->ext.iterator->step = gfc_get_int_expr (gfc_index_integer_kind,
2609 where, 1);
2611 n2 = XCNEW (gfc_code);
2612 n2->op = EXEC_DO;
2613 n2->loc = *where;
2614 n2->next = NULL;
2615 n->block = n2;
2616 return n;
2619 /* Get the upper bound of the DO loops for matmul along a dimension. This
2620 is one-based. */
2622 static gfc_expr*
2623 get_size_m1 (gfc_expr *e, int dimen)
2625 mpz_t size;
2626 gfc_expr *res;
2628 if (gfc_array_dimen_size (e, dimen - 1, &size))
2630 res = gfc_get_constant_expr (BT_INTEGER,
2631 gfc_index_integer_kind, &e->where);
2632 mpz_sub_ui (res->value.integer, size, 1);
2633 mpz_clear (size);
2635 else
2637 res = get_operand (INTRINSIC_MINUS,
2638 get_array_inq_function (GFC_ISYM_SIZE, e, dimen),
2639 gfc_get_int_expr (gfc_index_integer_kind,
2640 &e->where, 1));
2641 gfc_simplify_expr (res, 0);
2644 return res;
2647 /* Function to return a scalarized expression. It is assumed that indices are
2648 zero based to make generation of DO loops easier. A zero as index will
2649 access the first element along a dimension. Single element references will
2650 be skipped. A NULL as an expression will be replaced by a full reference.
2651 This assumes that the index loops have gfc_index_integer_kind, and that all
2652 references have been frozen. */
2654 static gfc_expr*
2655 scalarized_expr (gfc_expr *e_in, gfc_expr **index, int count_index)
2657 gfc_array_ref *ar;
2658 int i;
2659 int rank;
2660 gfc_expr *e;
2661 int i_index;
2662 bool was_fullref;
2664 e = gfc_copy_expr(e_in);
2666 rank = e->rank;
2668 ar = gfc_find_array_ref (e);
2670 /* We scalarize count_index variables, reducing the rank by count_index. */
2672 e->rank = rank - count_index;
2674 was_fullref = ar->type == AR_FULL;
2676 if (e->rank == 0)
2677 ar->type = AR_ELEMENT;
2678 else
2679 ar->type = AR_SECTION;
2681 /* Loop over the indices. For each index, create the expression
2682 index * stride + lbound(e, dim). */
2684 i_index = 0;
2685 for (i=0; i < ar->dimen; i++)
2687 if (was_fullref || ar->dimen_type[i] == DIMEN_RANGE)
2689 if (index[i_index] != NULL)
2691 gfc_expr *lbound, *nindex;
2692 gfc_expr *loopvar;
2694 loopvar = gfc_copy_expr (index[i_index]);
2696 if (ar->stride[i])
2698 gfc_expr *tmp;
2700 tmp = gfc_copy_expr(ar->stride[i]);
2701 if (tmp->ts.kind != gfc_index_integer_kind)
2703 gfc_typespec ts;
2704 gfc_clear_ts (&ts);
2705 ts.type = BT_INTEGER;
2706 ts.kind = gfc_index_integer_kind;
2707 gfc_convert_type (tmp, &ts, 2);
2709 nindex = get_operand (INTRINSIC_TIMES, loopvar, tmp);
2711 else
2712 nindex = loopvar;
2714 /* Calculate the lower bound of the expression. */
2715 if (ar->start[i])
2717 lbound = gfc_copy_expr (ar->start[i]);
2718 if (lbound->ts.kind != gfc_index_integer_kind)
2720 gfc_typespec ts;
2721 gfc_clear_ts (&ts);
2722 ts.type = BT_INTEGER;
2723 ts.kind = gfc_index_integer_kind;
2724 gfc_convert_type (lbound, &ts, 2);
2728 else
2730 gfc_expr *lbound_e;
2731 gfc_ref *ref;
2733 lbound_e = gfc_copy_expr (e_in);
2735 for (ref = lbound_e->ref; ref; ref = ref->next)
2736 if (ref->type == REF_ARRAY
2737 && (ref->u.ar.type == AR_FULL
2738 || ref->u.ar.type == AR_SECTION))
2739 break;
2741 if (ref->next)
2743 gfc_free_ref_list (ref->next);
2744 ref->next = NULL;
2747 if (!was_fullref)
2749 /* Look at full individual sections, like a(:). The first index
2750 is the lbound of a full ref. */
2751 int j;
2752 gfc_array_ref *ar;
2754 ar = &ref->u.ar;
2755 ar->type = AR_FULL;
2756 for (j = 0; j < ar->dimen; j++)
2758 gfc_free_expr (ar->start[j]);
2759 ar->start[j] = NULL;
2760 gfc_free_expr (ar->end[j]);
2761 ar->end[j] = NULL;
2762 gfc_free_expr (ar->stride[j]);
2763 ar->stride[j] = NULL;
2766 /* We have to get rid of the shape, if there is one. Do
2767 so by freeing it and calling gfc_resolve to rebuild
2768 it, if necessary. */
2770 if (lbound_e->shape)
2771 gfc_free_shape (&(lbound_e->shape), lbound_e->rank);
2773 lbound_e->rank = ar->dimen;
2774 gfc_resolve_expr (lbound_e);
2776 lbound = get_array_inq_function (GFC_ISYM_LBOUND, lbound_e,
2777 i + 1);
2778 gfc_free_expr (lbound_e);
2781 ar->dimen_type[i] = DIMEN_ELEMENT;
2783 gfc_free_expr (ar->start[i]);
2784 ar->start[i] = get_operand (INTRINSIC_PLUS, nindex, lbound);
2786 gfc_free_expr (ar->end[i]);
2787 ar->end[i] = NULL;
2788 gfc_free_expr (ar->stride[i]);
2789 ar->stride[i] = NULL;
2790 gfc_simplify_expr (ar->start[i], 0);
2792 else if (was_fullref)
2794 gfc_internal_error ("Scalarization using DIMEN_RANGE unimplemented");
2796 i_index ++;
2800 return e;
2803 /* Helper function to check for a dimen vector as subscript. */
2805 static bool
2806 has_dimen_vector_ref (gfc_expr *e)
2808 gfc_array_ref *ar;
2809 int i;
2811 ar = gfc_find_array_ref (e);
2812 gcc_assert (ar);
2813 if (ar->type == AR_FULL)
2814 return false;
2816 for (i=0; i<ar->dimen; i++)
2817 if (ar->dimen_type[i] == DIMEN_VECTOR)
2818 return true;
2820 return false;
2823 /* If handed an expression of the form
2825 TRANSPOSE(CONJG(A))
2827 check if A can be handled by matmul and return if there is an uneven number
2828 of CONJG calls. Return a pointer to the array when everything is OK, NULL
2829 otherwise. The caller has to check for the correct rank. */
2831 static gfc_expr*
2832 check_conjg_transpose_variable (gfc_expr *e, bool *conjg, bool *transpose)
2834 *conjg = false;
2835 *transpose = false;
2839 if (e->expr_type == EXPR_VARIABLE)
2841 gcc_assert (e->rank == 1 || e->rank == 2);
2842 return e;
2844 else if (e->expr_type == EXPR_FUNCTION)
2846 if (e->value.function.isym == NULL)
2847 return NULL;
2849 if (e->value.function.isym->id == GFC_ISYM_CONJG)
2850 *conjg = !*conjg;
2851 else if (e->value.function.isym->id == GFC_ISYM_TRANSPOSE)
2852 *transpose = !*transpose;
2853 else return NULL;
2855 else
2856 return NULL;
2858 e = e->value.function.actual->expr;
2860 while(1);
2862 return NULL;
2865 /* Inline assignments of the form c = matmul(a,b).
2866 Handle only the cases currently where b and c are rank-two arrays.
2868 This basically translates the code to
2870 BLOCK
2871 integer i,j,k
2872 c = 0
2873 do j=0, size(b,2)-1
2874 do k=0, size(a, 2)-1
2875 do i=0, size(a, 1)-1
2876 c(i * stride(c,1) + lbound(c,1), j * stride(c,2) + lbound(c,2)) =
2877 c(i * stride(c,1) + lbound(c,1), j * stride(c,2) + lbound(c,2)) +
2878 a(i * stride(a,1) + lbound(a,1), k * stride(a,2) + lbound(a,2)) *
2879 b(k * stride(b,1) + lbound(b,1), j * stride(b,2) + lbound(b,2))
2880 end do
2881 end do
2882 end do
2883 END BLOCK
2887 static int
2888 inline_matmul_assign (gfc_code **c, int *walk_subtrees,
2889 void *data ATTRIBUTE_UNUSED)
2891 gfc_code *co = *c;
2892 gfc_expr *expr1, *expr2;
2893 gfc_expr *matrix_a, *matrix_b;
2894 gfc_actual_arglist *a, *b;
2895 gfc_code *do_1, *do_2, *do_3, *assign_zero, *assign_matmul;
2896 gfc_expr *zero_e;
2897 gfc_expr *u1, *u2, *u3;
2898 gfc_expr *list[2];
2899 gfc_expr *ascalar, *bscalar, *cscalar;
2900 gfc_expr *mult;
2901 gfc_expr *var_1, *var_2, *var_3;
2902 gfc_expr *zero;
2903 gfc_namespace *ns;
2904 gfc_intrinsic_op op_times, op_plus;
2905 enum matrix_case m_case;
2906 int i;
2907 gfc_code *if_limit = NULL;
2908 gfc_code **next_code_point;
2909 bool conjg_a, conjg_b, transpose_a, transpose_b;
2911 if (co->op != EXEC_ASSIGN)
2912 return 0;
2914 if (in_where)
2915 return 0;
2917 /* The BLOCKS generated for the temporary variables and FORALL don't
2918 mix. */
2919 if (forall_level > 0)
2920 return 0;
2922 /* For now don't do anything in OpenMP workshare, it confuses
2923 its translation, which expects only the allowed statements in there.
2924 We should figure out how to parallelize this eventually. */
2925 if (in_omp_workshare)
2926 return 0;
2928 expr1 = co->expr1;
2929 expr2 = co->expr2;
2930 if (expr2->expr_type != EXPR_FUNCTION
2931 || expr2->value.function.isym == NULL
2932 || expr2->value.function.isym->id != GFC_ISYM_MATMUL)
2933 return 0;
2935 current_code = c;
2936 inserted_block = NULL;
2937 changed_statement = NULL;
2939 a = expr2->value.function.actual;
2940 matrix_a = check_conjg_transpose_variable (a->expr, &conjg_a, &transpose_a);
2941 if (transpose_a || matrix_a == NULL)
2942 return 0;
2944 b = a->next;
2945 matrix_b = check_conjg_transpose_variable (b->expr, &conjg_b, &transpose_b);
2946 if (matrix_b == NULL)
2947 return 0;
2949 if (has_dimen_vector_ref (expr1) || has_dimen_vector_ref (matrix_a)
2950 || has_dimen_vector_ref (matrix_b))
2951 return 0;
2953 /* We do not handle data dependencies yet. */
2954 if (gfc_check_dependency (expr1, matrix_a, true)
2955 || gfc_check_dependency (expr1, matrix_b, true))
2956 return 0;
2958 if (matrix_a->rank == 2)
2960 if (matrix_b->rank == 1)
2961 m_case = A2B1;
2962 else
2964 if (transpose_b)
2965 m_case = A2B2T;
2966 else
2967 m_case = A2B2;
2970 else
2972 /* Vector * Transpose(B) not handled yet. */
2973 if (transpose_b)
2974 m_case = none;
2975 else
2976 m_case = A1B2;
2979 if (m_case == none)
2980 return 0;
2982 ns = insert_block ();
2984 /* Assign the type of the zero expression for initializing the resulting
2985 array, and the expression (+ and * for real, integer and complex;
2986 .and. and .or for logical. */
2988 switch(expr1->ts.type)
2990 case BT_INTEGER:
2991 zero_e = gfc_get_int_expr (expr1->ts.kind, &expr1->where, 0);
2992 op_times = INTRINSIC_TIMES;
2993 op_plus = INTRINSIC_PLUS;
2994 break;
2996 case BT_LOGICAL:
2997 op_times = INTRINSIC_AND;
2998 op_plus = INTRINSIC_OR;
2999 zero_e = gfc_get_logical_expr (expr1->ts.kind, &expr1->where,
3001 break;
3002 case BT_REAL:
3003 zero_e = gfc_get_constant_expr (BT_REAL, expr1->ts.kind,
3004 &expr1->where);
3005 mpfr_set_si (zero_e->value.real, 0, GFC_RND_MODE);
3006 op_times = INTRINSIC_TIMES;
3007 op_plus = INTRINSIC_PLUS;
3008 break;
3010 case BT_COMPLEX:
3011 zero_e = gfc_get_constant_expr (BT_COMPLEX, expr1->ts.kind,
3012 &expr1->where);
3013 mpc_set_si_si (zero_e->value.complex, 0, 0, GFC_RND_MODE);
3014 op_times = INTRINSIC_TIMES;
3015 op_plus = INTRINSIC_PLUS;
3017 break;
3019 default:
3020 gcc_unreachable();
3023 current_code = &ns->code;
3025 /* Freeze the references, keeping track of how many temporary variables were
3026 created. */
3027 n_vars = 0;
3028 freeze_references (matrix_a);
3029 freeze_references (matrix_b);
3030 freeze_references (expr1);
3032 if (n_vars == 0)
3033 next_code_point = current_code;
3034 else
3036 next_code_point = &ns->code;
3037 for (i=0; i<n_vars; i++)
3038 next_code_point = &(*next_code_point)->next;
3041 /* Take care of the inline flag. If the limit check evaluates to a
3042 constant, dead code elimination will eliminate the unneeded branch. */
3044 if (m_case == A2B2 && flag_inline_matmul_limit > 0)
3046 if_limit = inline_limit_check (matrix_a, matrix_b, m_case);
3048 /* Insert the original statement into the else branch. */
3049 if_limit->block->block->next = co;
3050 co->next = NULL;
3052 /* ... and the new ones go into the original one. */
3053 *next_code_point = if_limit;
3054 next_code_point = &if_limit->block->next;
3057 assign_zero = XCNEW (gfc_code);
3058 assign_zero->op = EXEC_ASSIGN;
3059 assign_zero->loc = co->loc;
3060 assign_zero->expr1 = gfc_copy_expr (expr1);
3061 assign_zero->expr2 = zero_e;
3063 /* Handle the reallocation, if needed. */
3064 if (flag_realloc_lhs && gfc_is_reallocatable_lhs (expr1))
3066 gfc_code *lhs_alloc;
3068 /* Only need to check a single dimension for the A2B2 case for
3069 bounds checking, the rest will be allocated. */
3071 if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS && m_case == A2B2)
3073 gfc_code *test;
3074 gfc_expr *a2, *b1;
3076 a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2);
3077 b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1);
3078 test = runtime_error_ne (b1, a2, "Dimension of array B incorrect "
3079 "in MATMUL intrinsic: Is %ld, should be %ld");
3080 *next_code_point = test;
3081 next_code_point = &test->next;
3085 lhs_alloc = matmul_lhs_realloc (expr1, matrix_a, matrix_b, m_case);
3087 *next_code_point = lhs_alloc;
3088 next_code_point = &lhs_alloc->next;
3091 else if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
3093 gfc_code *test;
3094 gfc_expr *a2, *b1, *c1, *c2, *a1, *b2;
3096 if (m_case == A2B2 || m_case == A2B1)
3098 a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2);
3099 b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1);
3100 test = runtime_error_ne (b1, a2, "Dimension of array B incorrect "
3101 "in MATMUL intrinsic: Is %ld, should be %ld");
3102 *next_code_point = test;
3103 next_code_point = &test->next;
3105 c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1);
3106 a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1);
3108 if (m_case == A2B2)
3109 test = runtime_error_ne (c1, a1, "Incorrect extent in return array in "
3110 "MATMUL intrinsic for dimension 1: "
3111 "is %ld, should be %ld");
3112 else if (m_case == A2B1)
3113 test = runtime_error_ne (c1, a1, "Incorrect extent in return array in "
3114 "MATMUL intrinsic: "
3115 "is %ld, should be %ld");
3118 *next_code_point = test;
3119 next_code_point = &test->next;
3121 else if (m_case == A1B2)
3123 a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1);
3124 b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1);
3125 test = runtime_error_ne (b1, a1, "Dimension of array B incorrect "
3126 "in MATMUL intrinsic: Is %ld, should be %ld");
3127 *next_code_point = test;
3128 next_code_point = &test->next;
3130 c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1);
3131 b2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 2);
3133 test = runtime_error_ne (c1, b2, "Incorrect extent in return array in "
3134 "MATMUL intrinsic: "
3135 "is %ld, should be %ld");
3137 *next_code_point = test;
3138 next_code_point = &test->next;
3141 if (m_case == A2B2)
3143 c2 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 2);
3144 b2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 2);
3145 test = runtime_error_ne (c2, b2, "Incorrect extent in return array in "
3146 "MATMUL intrinsic for dimension 2: is %ld, should be %ld");
3148 *next_code_point = test;
3149 next_code_point = &test->next;
3152 if (m_case == A2B2T)
3154 c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1);
3155 a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1);
3156 test = runtime_error_ne (c1, a1, "Incorrect extent in return array in "
3157 "MATMUL intrinsic for dimension 1: "
3158 "is %ld, should be %ld");
3160 *next_code_point = test;
3161 next_code_point = &test->next;
3163 c2 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 2);
3164 b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1);
3165 test = runtime_error_ne (c2, b1, "Incorrect extent in return array in "
3166 "MATMUL intrinsic for dimension 2: "
3167 "is %ld, should be %ld");
3168 *next_code_point = test;
3169 next_code_point = &test->next;
3171 a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2);
3172 b2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 2);
3174 test = runtime_error_ne (b2, a2, "Incorrect extent in argument B in "
3175 "MATMUL intrnisic for dimension 2: "
3176 "is %ld, should be %ld");
3177 *next_code_point = test;
3178 next_code_point = &test->next;
3183 *next_code_point = assign_zero;
3185 zero = gfc_get_int_expr (gfc_index_integer_kind, &co->loc, 0);
3187 assign_matmul = XCNEW (gfc_code);
3188 assign_matmul->op = EXEC_ASSIGN;
3189 assign_matmul->loc = co->loc;
3191 /* Get the bounds for the loops, create them and create the scalarized
3192 expressions. */
3194 switch (m_case)
3196 case A2B2:
3197 inline_limit_check (matrix_a, matrix_b, m_case);
3199 u1 = get_size_m1 (matrix_b, 2);
3200 u2 = get_size_m1 (matrix_a, 2);
3201 u3 = get_size_m1 (matrix_a, 1);
3203 do_1 = create_do_loop (gfc_copy_expr (zero), u1, NULL, &co->loc, ns);
3204 do_2 = create_do_loop (gfc_copy_expr (zero), u2, NULL, &co->loc, ns);
3205 do_3 = create_do_loop (gfc_copy_expr (zero), u3, NULL, &co->loc, ns);
3207 do_1->block->next = do_2;
3208 do_2->block->next = do_3;
3209 do_3->block->next = assign_matmul;
3211 var_1 = do_1->ext.iterator->var;
3212 var_2 = do_2->ext.iterator->var;
3213 var_3 = do_3->ext.iterator->var;
3215 list[0] = var_3;
3216 list[1] = var_1;
3217 cscalar = scalarized_expr (co->expr1, list, 2);
3219 list[0] = var_3;
3220 list[1] = var_2;
3221 ascalar = scalarized_expr (matrix_a, list, 2);
3223 list[0] = var_2;
3224 list[1] = var_1;
3225 bscalar = scalarized_expr (matrix_b, list, 2);
3227 break;
3229 case A2B2T:
3230 inline_limit_check (matrix_a, matrix_b, m_case);
3232 u1 = get_size_m1 (matrix_b, 1);
3233 u2 = get_size_m1 (matrix_a, 2);
3234 u3 = get_size_m1 (matrix_a, 1);
3236 do_1 = create_do_loop (gfc_copy_expr (zero), u1, NULL, &co->loc, ns);
3237 do_2 = create_do_loop (gfc_copy_expr (zero), u2, NULL, &co->loc, ns);
3238 do_3 = create_do_loop (gfc_copy_expr (zero), u3, NULL, &co->loc, ns);
3240 do_1->block->next = do_2;
3241 do_2->block->next = do_3;
3242 do_3->block->next = assign_matmul;
3244 var_1 = do_1->ext.iterator->var;
3245 var_2 = do_2->ext.iterator->var;
3246 var_3 = do_3->ext.iterator->var;
3248 list[0] = var_3;
3249 list[1] = var_1;
3250 cscalar = scalarized_expr (co->expr1, list, 2);
3252 list[0] = var_3;
3253 list[1] = var_2;
3254 ascalar = scalarized_expr (matrix_a, list, 2);
3256 list[0] = var_1;
3257 list[1] = var_2;
3258 bscalar = scalarized_expr (matrix_b, list, 2);
3260 break;
3262 case A2B1:
3263 u1 = get_size_m1 (matrix_b, 1);
3264 u2 = get_size_m1 (matrix_a, 1);
3266 do_1 = create_do_loop (gfc_copy_expr (zero), u1, NULL, &co->loc, ns);
3267 do_2 = create_do_loop (gfc_copy_expr (zero), u2, NULL, &co->loc, ns);
3269 do_1->block->next = do_2;
3270 do_2->block->next = assign_matmul;
3272 var_1 = do_1->ext.iterator->var;
3273 var_2 = do_2->ext.iterator->var;
3275 list[0] = var_2;
3276 cscalar = scalarized_expr (co->expr1, list, 1);
3278 list[0] = var_2;
3279 list[1] = var_1;
3280 ascalar = scalarized_expr (matrix_a, list, 2);
3282 list[0] = var_1;
3283 bscalar = scalarized_expr (matrix_b, list, 1);
3285 break;
3287 case A1B2:
3288 u1 = get_size_m1 (matrix_b, 2);
3289 u2 = get_size_m1 (matrix_a, 1);
3291 do_1 = create_do_loop (gfc_copy_expr (zero), u1, NULL, &co->loc, ns);
3292 do_2 = create_do_loop (gfc_copy_expr (zero), u2, NULL, &co->loc, ns);
3294 do_1->block->next = do_2;
3295 do_2->block->next = assign_matmul;
3297 var_1 = do_1->ext.iterator->var;
3298 var_2 = do_2->ext.iterator->var;
3300 list[0] = var_1;
3301 cscalar = scalarized_expr (co->expr1, list, 1);
3303 list[0] = var_2;
3304 ascalar = scalarized_expr (matrix_a, list, 1);
3306 list[0] = var_2;
3307 list[1] = var_1;
3308 bscalar = scalarized_expr (matrix_b, list, 2);
3310 break;
3312 default:
3313 gcc_unreachable();
3316 if (conjg_a)
3317 ascalar = gfc_build_intrinsic_call (ns, GFC_ISYM_CONJG, "conjg",
3318 matrix_a->where, 1, ascalar);
3320 if (conjg_b)
3321 bscalar = gfc_build_intrinsic_call (ns, GFC_ISYM_CONJG, "conjg",
3322 matrix_b->where, 1, bscalar);
3324 /* First loop comes after the zero assignment. */
3325 assign_zero->next = do_1;
3327 /* Build the assignment expression in the loop. */
3328 assign_matmul->expr1 = gfc_copy_expr (cscalar);
3330 mult = get_operand (op_times, ascalar, bscalar);
3331 assign_matmul->expr2 = get_operand (op_plus, cscalar, mult);
3333 /* If we don't want to keep the original statement around in
3334 the else branch, we can free it. */
3336 if (if_limit == NULL)
3337 gfc_free_statements(co);
3338 else
3339 co->next = NULL;
3341 gfc_free_expr (zero);
3342 *walk_subtrees = 0;
3343 return 0;
3346 #define WALK_SUBEXPR(NODE) \
3347 do \
3349 result = gfc_expr_walker (&(NODE), exprfn, data); \
3350 if (result) \
3351 return result; \
3353 while (0)
3354 #define WALK_SUBEXPR_TAIL(NODE) e = &(NODE); continue
3356 /* Walk expression *E, calling EXPRFN on each expression in it. */
3359 gfc_expr_walker (gfc_expr **e, walk_expr_fn_t exprfn, void *data)
3361 while (*e)
3363 int walk_subtrees = 1;
3364 gfc_actual_arglist *a;
3365 gfc_ref *r;
3366 gfc_constructor *c;
3368 int result = exprfn (e, &walk_subtrees, data);
3369 if (result)
3370 return result;
3371 if (walk_subtrees)
3372 switch ((*e)->expr_type)
3374 case EXPR_OP:
3375 WALK_SUBEXPR ((*e)->value.op.op1);
3376 WALK_SUBEXPR_TAIL ((*e)->value.op.op2);
3377 break;
3378 case EXPR_FUNCTION:
3379 for (a = (*e)->value.function.actual; a; a = a->next)
3380 WALK_SUBEXPR (a->expr);
3381 break;
3382 case EXPR_COMPCALL:
3383 case EXPR_PPC:
3384 WALK_SUBEXPR ((*e)->value.compcall.base_object);
3385 for (a = (*e)->value.compcall.actual; a; a = a->next)
3386 WALK_SUBEXPR (a->expr);
3387 break;
3389 case EXPR_STRUCTURE:
3390 case EXPR_ARRAY:
3391 for (c = gfc_constructor_first ((*e)->value.constructor); c;
3392 c = gfc_constructor_next (c))
3394 if (c->iterator == NULL)
3395 WALK_SUBEXPR (c->expr);
3396 else
3398 iterator_level ++;
3399 WALK_SUBEXPR (c->expr);
3400 iterator_level --;
3401 WALK_SUBEXPR (c->iterator->var);
3402 WALK_SUBEXPR (c->iterator->start);
3403 WALK_SUBEXPR (c->iterator->end);
3404 WALK_SUBEXPR (c->iterator->step);
3408 if ((*e)->expr_type != EXPR_ARRAY)
3409 break;
3411 /* Fall through to the variable case in order to walk the
3412 reference. */
3413 gcc_fallthrough ();
3415 case EXPR_SUBSTRING:
3416 case EXPR_VARIABLE:
3417 for (r = (*e)->ref; r; r = r->next)
3419 gfc_array_ref *ar;
3420 int i;
3422 switch (r->type)
3424 case REF_ARRAY:
3425 ar = &r->u.ar;
3426 if (ar->type == AR_SECTION || ar->type == AR_ELEMENT)
3428 for (i=0; i< ar->dimen; i++)
3430 WALK_SUBEXPR (ar->start[i]);
3431 WALK_SUBEXPR (ar->end[i]);
3432 WALK_SUBEXPR (ar->stride[i]);
3436 break;
3438 case REF_SUBSTRING:
3439 WALK_SUBEXPR (r->u.ss.start);
3440 WALK_SUBEXPR (r->u.ss.end);
3441 break;
3443 case REF_COMPONENT:
3444 break;
3448 default:
3449 break;
3451 return 0;
3453 return 0;
3456 #define WALK_SUBCODE(NODE) \
3457 do \
3459 result = gfc_code_walker (&(NODE), codefn, exprfn, data); \
3460 if (result) \
3461 return result; \
3463 while (0)
3465 /* Walk code *C, calling CODEFN on each gfc_code node in it and calling EXPRFN
3466 on each expression in it. If any of the hooks returns non-zero, that
3467 value is immediately returned. If the hook sets *WALK_SUBTREES to 0,
3468 no subcodes or subexpressions are traversed. */
3471 gfc_code_walker (gfc_code **c, walk_code_fn_t codefn, walk_expr_fn_t exprfn,
3472 void *data)
3474 for (; *c; c = &(*c)->next)
3476 int walk_subtrees = 1;
3477 int result = codefn (c, &walk_subtrees, data);
3478 if (result)
3479 return result;
3481 if (walk_subtrees)
3483 gfc_code *b;
3484 gfc_actual_arglist *a;
3485 gfc_code *co;
3486 gfc_association_list *alist;
3487 bool saved_in_omp_workshare;
3488 bool saved_in_where;
3490 /* There might be statement insertions before the current code,
3491 which must not affect the expression walker. */
3493 co = *c;
3494 saved_in_omp_workshare = in_omp_workshare;
3495 saved_in_where = in_where;
3497 switch (co->op)
3500 case EXEC_BLOCK:
3501 WALK_SUBCODE (co->ext.block.ns->code);
3502 if (co->ext.block.assoc)
3504 bool saved_in_assoc_list = in_assoc_list;
3506 in_assoc_list = true;
3507 for (alist = co->ext.block.assoc; alist; alist = alist->next)
3508 WALK_SUBEXPR (alist->target);
3510 in_assoc_list = saved_in_assoc_list;
3513 break;
3515 case EXEC_DO:
3516 doloop_level ++;
3517 WALK_SUBEXPR (co->ext.iterator->var);
3518 WALK_SUBEXPR (co->ext.iterator->start);
3519 WALK_SUBEXPR (co->ext.iterator->end);
3520 WALK_SUBEXPR (co->ext.iterator->step);
3521 break;
3523 case EXEC_WHERE:
3524 in_where = true;
3525 break;
3527 case EXEC_CALL:
3528 case EXEC_ASSIGN_CALL:
3529 for (a = co->ext.actual; a; a = a->next)
3530 WALK_SUBEXPR (a->expr);
3531 break;
3533 case EXEC_CALL_PPC:
3534 WALK_SUBEXPR (co->expr1);
3535 for (a = co->ext.actual; a; a = a->next)
3536 WALK_SUBEXPR (a->expr);
3537 break;
3539 case EXEC_SELECT:
3540 WALK_SUBEXPR (co->expr1);
3541 for (b = co->block; b; b = b->block)
3543 gfc_case *cp;
3544 for (cp = b->ext.block.case_list; cp; cp = cp->next)
3546 WALK_SUBEXPR (cp->low);
3547 WALK_SUBEXPR (cp->high);
3549 WALK_SUBCODE (b->next);
3551 continue;
3553 case EXEC_ALLOCATE:
3554 case EXEC_DEALLOCATE:
3556 gfc_alloc *a;
3557 for (a = co->ext.alloc.list; a; a = a->next)
3558 WALK_SUBEXPR (a->expr);
3559 break;
3562 case EXEC_FORALL:
3563 case EXEC_DO_CONCURRENT:
3565 gfc_forall_iterator *fa;
3566 for (fa = co->ext.forall_iterator; fa; fa = fa->next)
3568 WALK_SUBEXPR (fa->var);
3569 WALK_SUBEXPR (fa->start);
3570 WALK_SUBEXPR (fa->end);
3571 WALK_SUBEXPR (fa->stride);
3573 if (co->op == EXEC_FORALL)
3574 forall_level ++;
3575 break;
3578 case EXEC_OPEN:
3579 WALK_SUBEXPR (co->ext.open->unit);
3580 WALK_SUBEXPR (co->ext.open->file);
3581 WALK_SUBEXPR (co->ext.open->status);
3582 WALK_SUBEXPR (co->ext.open->access);
3583 WALK_SUBEXPR (co->ext.open->form);
3584 WALK_SUBEXPR (co->ext.open->recl);
3585 WALK_SUBEXPR (co->ext.open->blank);
3586 WALK_SUBEXPR (co->ext.open->position);
3587 WALK_SUBEXPR (co->ext.open->action);
3588 WALK_SUBEXPR (co->ext.open->delim);
3589 WALK_SUBEXPR (co->ext.open->pad);
3590 WALK_SUBEXPR (co->ext.open->iostat);
3591 WALK_SUBEXPR (co->ext.open->iomsg);
3592 WALK_SUBEXPR (co->ext.open->convert);
3593 WALK_SUBEXPR (co->ext.open->decimal);
3594 WALK_SUBEXPR (co->ext.open->encoding);
3595 WALK_SUBEXPR (co->ext.open->round);
3596 WALK_SUBEXPR (co->ext.open->sign);
3597 WALK_SUBEXPR (co->ext.open->asynchronous);
3598 WALK_SUBEXPR (co->ext.open->id);
3599 WALK_SUBEXPR (co->ext.open->newunit);
3600 WALK_SUBEXPR (co->ext.open->share);
3601 WALK_SUBEXPR (co->ext.open->cc);
3602 break;
3604 case EXEC_CLOSE:
3605 WALK_SUBEXPR (co->ext.close->unit);
3606 WALK_SUBEXPR (co->ext.close->status);
3607 WALK_SUBEXPR (co->ext.close->iostat);
3608 WALK_SUBEXPR (co->ext.close->iomsg);
3609 break;
3611 case EXEC_BACKSPACE:
3612 case EXEC_ENDFILE:
3613 case EXEC_REWIND:
3614 case EXEC_FLUSH:
3615 WALK_SUBEXPR (co->ext.filepos->unit);
3616 WALK_SUBEXPR (co->ext.filepos->iostat);
3617 WALK_SUBEXPR (co->ext.filepos->iomsg);
3618 break;
3620 case EXEC_INQUIRE:
3621 WALK_SUBEXPR (co->ext.inquire->unit);
3622 WALK_SUBEXPR (co->ext.inquire->file);
3623 WALK_SUBEXPR (co->ext.inquire->iomsg);
3624 WALK_SUBEXPR (co->ext.inquire->iostat);
3625 WALK_SUBEXPR (co->ext.inquire->exist);
3626 WALK_SUBEXPR (co->ext.inquire->opened);
3627 WALK_SUBEXPR (co->ext.inquire->number);
3628 WALK_SUBEXPR (co->ext.inquire->named);
3629 WALK_SUBEXPR (co->ext.inquire->name);
3630 WALK_SUBEXPR (co->ext.inquire->access);
3631 WALK_SUBEXPR (co->ext.inquire->sequential);
3632 WALK_SUBEXPR (co->ext.inquire->direct);
3633 WALK_SUBEXPR (co->ext.inquire->form);
3634 WALK_SUBEXPR (co->ext.inquire->formatted);
3635 WALK_SUBEXPR (co->ext.inquire->unformatted);
3636 WALK_SUBEXPR (co->ext.inquire->recl);
3637 WALK_SUBEXPR (co->ext.inquire->nextrec);
3638 WALK_SUBEXPR (co->ext.inquire->blank);
3639 WALK_SUBEXPR (co->ext.inquire->position);
3640 WALK_SUBEXPR (co->ext.inquire->action);
3641 WALK_SUBEXPR (co->ext.inquire->read);
3642 WALK_SUBEXPR (co->ext.inquire->write);
3643 WALK_SUBEXPR (co->ext.inquire->readwrite);
3644 WALK_SUBEXPR (co->ext.inquire->delim);
3645 WALK_SUBEXPR (co->ext.inquire->encoding);
3646 WALK_SUBEXPR (co->ext.inquire->pad);
3647 WALK_SUBEXPR (co->ext.inquire->iolength);
3648 WALK_SUBEXPR (co->ext.inquire->convert);
3649 WALK_SUBEXPR (co->ext.inquire->strm_pos);
3650 WALK_SUBEXPR (co->ext.inquire->asynchronous);
3651 WALK_SUBEXPR (co->ext.inquire->decimal);
3652 WALK_SUBEXPR (co->ext.inquire->pending);
3653 WALK_SUBEXPR (co->ext.inquire->id);
3654 WALK_SUBEXPR (co->ext.inquire->sign);
3655 WALK_SUBEXPR (co->ext.inquire->size);
3656 WALK_SUBEXPR (co->ext.inquire->round);
3657 break;
3659 case EXEC_WAIT:
3660 WALK_SUBEXPR (co->ext.wait->unit);
3661 WALK_SUBEXPR (co->ext.wait->iostat);
3662 WALK_SUBEXPR (co->ext.wait->iomsg);
3663 WALK_SUBEXPR (co->ext.wait->id);
3664 break;
3666 case EXEC_READ:
3667 case EXEC_WRITE:
3668 WALK_SUBEXPR (co->ext.dt->io_unit);
3669 WALK_SUBEXPR (co->ext.dt->format_expr);
3670 WALK_SUBEXPR (co->ext.dt->rec);
3671 WALK_SUBEXPR (co->ext.dt->advance);
3672 WALK_SUBEXPR (co->ext.dt->iostat);
3673 WALK_SUBEXPR (co->ext.dt->size);
3674 WALK_SUBEXPR (co->ext.dt->iomsg);
3675 WALK_SUBEXPR (co->ext.dt->id);
3676 WALK_SUBEXPR (co->ext.dt->pos);
3677 WALK_SUBEXPR (co->ext.dt->asynchronous);
3678 WALK_SUBEXPR (co->ext.dt->blank);
3679 WALK_SUBEXPR (co->ext.dt->decimal);
3680 WALK_SUBEXPR (co->ext.dt->delim);
3681 WALK_SUBEXPR (co->ext.dt->pad);
3682 WALK_SUBEXPR (co->ext.dt->round);
3683 WALK_SUBEXPR (co->ext.dt->sign);
3684 WALK_SUBEXPR (co->ext.dt->extra_comma);
3685 break;
3687 case EXEC_OMP_PARALLEL:
3688 case EXEC_OMP_PARALLEL_DO:
3689 case EXEC_OMP_PARALLEL_DO_SIMD:
3690 case EXEC_OMP_PARALLEL_SECTIONS:
3692 in_omp_workshare = false;
3694 /* This goto serves as a shortcut to avoid code
3695 duplication or a larger if or switch statement. */
3696 goto check_omp_clauses;
3698 case EXEC_OMP_WORKSHARE:
3699 case EXEC_OMP_PARALLEL_WORKSHARE:
3701 in_omp_workshare = true;
3703 /* Fall through */
3705 case EXEC_OMP_CRITICAL:
3706 case EXEC_OMP_DISTRIBUTE:
3707 case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
3708 case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
3709 case EXEC_OMP_DISTRIBUTE_SIMD:
3710 case EXEC_OMP_DO:
3711 case EXEC_OMP_DO_SIMD:
3712 case EXEC_OMP_ORDERED:
3713 case EXEC_OMP_SECTIONS:
3714 case EXEC_OMP_SINGLE:
3715 case EXEC_OMP_END_SINGLE:
3716 case EXEC_OMP_SIMD:
3717 case EXEC_OMP_TASKLOOP:
3718 case EXEC_OMP_TASKLOOP_SIMD:
3719 case EXEC_OMP_TARGET:
3720 case EXEC_OMP_TARGET_DATA:
3721 case EXEC_OMP_TARGET_ENTER_DATA:
3722 case EXEC_OMP_TARGET_EXIT_DATA:
3723 case EXEC_OMP_TARGET_PARALLEL:
3724 case EXEC_OMP_TARGET_PARALLEL_DO:
3725 case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
3726 case EXEC_OMP_TARGET_SIMD:
3727 case EXEC_OMP_TARGET_TEAMS:
3728 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
3729 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
3730 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
3731 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
3732 case EXEC_OMP_TARGET_UPDATE:
3733 case EXEC_OMP_TASK:
3734 case EXEC_OMP_TEAMS:
3735 case EXEC_OMP_TEAMS_DISTRIBUTE:
3736 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
3737 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
3738 case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
3740 /* Come to this label only from the
3741 EXEC_OMP_PARALLEL_* cases above. */
3743 check_omp_clauses:
3745 if (co->ext.omp_clauses)
3747 gfc_omp_namelist *n;
3748 static int list_types[]
3749 = { OMP_LIST_ALIGNED, OMP_LIST_LINEAR, OMP_LIST_DEPEND,
3750 OMP_LIST_MAP, OMP_LIST_TO, OMP_LIST_FROM };
3751 size_t idx;
3752 WALK_SUBEXPR (co->ext.omp_clauses->if_expr);
3753 WALK_SUBEXPR (co->ext.omp_clauses->final_expr);
3754 WALK_SUBEXPR (co->ext.omp_clauses->num_threads);
3755 WALK_SUBEXPR (co->ext.omp_clauses->chunk_size);
3756 WALK_SUBEXPR (co->ext.omp_clauses->safelen_expr);
3757 WALK_SUBEXPR (co->ext.omp_clauses->simdlen_expr);
3758 WALK_SUBEXPR (co->ext.omp_clauses->num_teams);
3759 WALK_SUBEXPR (co->ext.omp_clauses->device);
3760 WALK_SUBEXPR (co->ext.omp_clauses->thread_limit);
3761 WALK_SUBEXPR (co->ext.omp_clauses->dist_chunk_size);
3762 WALK_SUBEXPR (co->ext.omp_clauses->grainsize);
3763 WALK_SUBEXPR (co->ext.omp_clauses->hint);
3764 WALK_SUBEXPR (co->ext.omp_clauses->num_tasks);
3765 WALK_SUBEXPR (co->ext.omp_clauses->priority);
3766 for (idx = 0; idx < OMP_IF_LAST; idx++)
3767 WALK_SUBEXPR (co->ext.omp_clauses->if_exprs[idx]);
3768 for (idx = 0;
3769 idx < sizeof (list_types) / sizeof (list_types[0]);
3770 idx++)
3771 for (n = co->ext.omp_clauses->lists[list_types[idx]];
3772 n; n = n->next)
3773 WALK_SUBEXPR (n->expr);
3775 break;
3776 default:
3777 break;
3780 WALK_SUBEXPR (co->expr1);
3781 WALK_SUBEXPR (co->expr2);
3782 WALK_SUBEXPR (co->expr3);
3783 WALK_SUBEXPR (co->expr4);
3784 for (b = co->block; b; b = b->block)
3786 WALK_SUBEXPR (b->expr1);
3787 WALK_SUBEXPR (b->expr2);
3788 WALK_SUBCODE (b->next);
3791 if (co->op == EXEC_FORALL)
3792 forall_level --;
3794 if (co->op == EXEC_DO)
3795 doloop_level --;
3797 in_omp_workshare = saved_in_omp_workshare;
3798 in_where = saved_in_where;
3801 return 0;