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
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
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/>. */
23 #include "coretypes.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 matmul_to_var_expr (gfc_expr
**, int *, void *);
47 static int matmul_to_var_code (gfc_code
**, int *, void *);
48 static int inline_matmul_assign (gfc_code
**, int *, void *);
49 static gfc_code
* create_do_loop (gfc_expr
*, gfc_expr
*, gfc_expr
*,
50 locus
*, gfc_namespace
*,
52 static gfc_expr
* check_conjg_transpose_variable (gfc_expr
*, bool *,
54 static bool has_dimen_vector_ref (gfc_expr
*);
55 static int matmul_temp_args (gfc_code
**, int *,void *data
);
58 static void check_locus (gfc_namespace
*);
61 /* How deep we are inside an argument list. */
63 static int count_arglist
;
65 /* Vector of gfc_expr ** we operate on. */
67 static vec
<gfc_expr
**> expr_array
;
69 /* Pointer to the gfc_code we currently work on - to be able to insert
70 a block before the statement. */
72 static gfc_code
**current_code
;
74 /* Pointer to the block to be inserted, and the statement we are
75 changing within the block. */
77 static gfc_code
*inserted_block
, **changed_statement
;
79 /* The namespace we are currently dealing with. */
81 static gfc_namespace
*current_ns
;
83 /* If we are within any forall loop. */
85 static int forall_level
;
87 /* Keep track of whether we are within an OMP workshare. */
89 static bool in_omp_workshare
;
91 /* Keep track of whether we are within a WHERE statement. */
95 /* Keep track of iterators for array constructors. */
97 static int iterator_level
;
99 /* Keep track of DO loop levels. */
101 static vec
<gfc_code
*> doloop_list
;
103 static int doloop_level
;
105 /* Vector of gfc_expr * to keep track of DO loops. */
107 struct my_struct
*evec
;
109 /* Keep track of association lists. */
111 static bool in_assoc_list
;
113 /* Counter for temporary variables. */
115 static int var_num
= 1;
117 /* What sort of matrix we are dealing with when inlining MATMUL. */
119 enum matrix_case
{ none
=0, A2B2
, A2B1
, A1B2
, A2B2T
, A2TB2
};
121 /* Keep track of the number of expressions we have inserted so far
126 /* Entry point - run all passes for a namespace. */
129 gfc_run_passes (gfc_namespace
*ns
)
132 /* Warn about dubious DO loops where the index might
137 doloop_list
.release ();
144 if (flag_frontend_optimize
)
146 optimize_namespace (ns
);
147 optimize_reduction (ns
);
148 if (flag_dump_fortran_optimized
)
149 gfc_dump_parse_tree (ns
, stdout
);
151 expr_array
.release ();
154 gfc_get_errors (&w
, &e
);
158 if (flag_realloc_lhs
)
159 realloc_strings (ns
);
164 /* Callback function: Warn if there is no location information in a
168 check_locus_code (gfc_code
**c
, int *walk_subtrees ATTRIBUTE_UNUSED
,
169 void *data ATTRIBUTE_UNUSED
)
172 if (c
&& *c
&& (((*c
)->loc
.nextc
== NULL
) || ((*c
)->loc
.lb
== NULL
)))
173 gfc_warning_internal (0, "No location in statement");
179 /* Callback function: Warn if there is no location information in an
183 check_locus_expr (gfc_expr
**e
, int *walk_subtrees ATTRIBUTE_UNUSED
,
184 void *data ATTRIBUTE_UNUSED
)
187 if (e
&& *e
&& (((*e
)->where
.nextc
== NULL
|| (*e
)->where
.lb
== NULL
)))
188 gfc_warning_internal (0, "No location in expression near %L",
189 &((*current_code
)->loc
));
193 /* Run check for missing location information. */
196 check_locus (gfc_namespace
*ns
)
198 gfc_code_walker (&ns
->code
, check_locus_code
, check_locus_expr
, NULL
);
200 for (ns
= ns
->contained
; ns
; ns
= ns
->sibling
)
202 if (ns
->code
== NULL
|| ns
->code
->op
!= EXEC_BLOCK
)
209 /* Callback for each gfc_code node invoked from check_realloc_strings.
210 For an allocatable LHS string which also appears as a variable on
222 realloc_string_callback (gfc_code
**c
, int *walk_subtrees ATTRIBUTE_UNUSED
,
223 void *data ATTRIBUTE_UNUSED
)
225 gfc_expr
*expr1
, *expr2
;
231 if (co
->op
!= EXEC_ASSIGN
)
235 if (expr1
->ts
.type
!= BT_CHARACTER
|| expr1
->rank
!= 0
236 || !gfc_expr_attr(expr1
).allocatable
237 || !expr1
->ts
.deferred
)
240 expr2
= gfc_discard_nops (co
->expr2
);
241 if (expr2
->expr_type
!= EXPR_VARIABLE
)
244 found_substr
= false;
245 for (ref
= expr2
->ref
; ref
; ref
= ref
->next
)
247 if (ref
->type
== REF_SUBSTRING
)
256 if (!gfc_check_dependency (expr1
, expr2
, true))
259 /* gfc_check_dependency doesn't always pick up identical expressions.
260 However, eliminating the above sends the compiler into an infinite
261 loop on valid expressions. Without this check, the gimplifier emits
262 an ICE for a = a, where a is deferred character length. */
263 if (!gfc_dep_compare_expr (expr1
, expr2
))
267 inserted_block
= NULL
;
268 changed_statement
= NULL
;
269 n
= create_var (expr2
, "realloc_string");
274 /* Callback for each gfc_code node invoked through gfc_code_walker
275 from optimize_namespace. */
278 optimize_code (gfc_code
**c
, int *walk_subtrees ATTRIBUTE_UNUSED
,
279 void *data ATTRIBUTE_UNUSED
)
286 if (op
== EXEC_CALL
|| op
== EXEC_COMPCALL
|| op
== EXEC_ASSIGN_CALL
287 || op
== EXEC_CALL_PPC
)
293 inserted_block
= NULL
;
294 changed_statement
= NULL
;
296 if (op
== EXEC_ASSIGN
)
297 optimize_assignment (*c
);
301 /* Callback for each gfc_expr node invoked through gfc_code_walker
302 from optimize_namespace. */
305 optimize_expr (gfc_expr
**e
, int *walk_subtrees ATTRIBUTE_UNUSED
,
306 void *data ATTRIBUTE_UNUSED
)
310 if ((*e
)->expr_type
== EXPR_FUNCTION
)
313 function_expr
= true;
316 function_expr
= false;
318 if (optimize_trim (*e
))
319 gfc_simplify_expr (*e
, 0);
321 if (optimize_lexical_comparison (*e
))
322 gfc_simplify_expr (*e
, 0);
324 if ((*e
)->expr_type
== EXPR_OP
&& optimize_op (*e
))
325 gfc_simplify_expr (*e
, 0);
327 if ((*e
)->expr_type
== EXPR_FUNCTION
&& (*e
)->value
.function
.isym
)
328 switch ((*e
)->value
.function
.isym
->id
)
330 case GFC_ISYM_MINLOC
:
331 case GFC_ISYM_MAXLOC
:
332 optimize_minmaxloc (e
);
344 /* Auxiliary function to handle the arguments to reduction intrnisics. If the
345 function is a scalar, just copy it; otherwise returns the new element, the
346 old one can be freed. */
349 copy_walk_reduction_arg (gfc_constructor
*c
, gfc_expr
*fn
)
351 gfc_expr
*fcn
, *e
= c
->expr
;
353 fcn
= gfc_copy_expr (e
);
356 gfc_constructor_base newbase
;
358 gfc_constructor
*new_c
;
361 new_expr
= gfc_get_expr ();
362 new_expr
->expr_type
= EXPR_ARRAY
;
363 new_expr
->ts
= e
->ts
;
364 new_expr
->where
= e
->where
;
366 new_c
= gfc_constructor_append_expr (&newbase
, fcn
, &(e
->where
));
367 new_c
->iterator
= c
->iterator
;
368 new_expr
->value
.constructor
= newbase
;
376 gfc_isym_id id
= fn
->value
.function
.isym
->id
;
378 if (id
== GFC_ISYM_SUM
|| id
== GFC_ISYM_PRODUCT
)
379 fcn
= gfc_build_intrinsic_call (current_ns
, id
,
380 fn
->value
.function
.isym
->name
,
381 fn
->where
, 3, fcn
, NULL
, NULL
);
382 else if (id
== GFC_ISYM_ANY
|| id
== GFC_ISYM_ALL
)
383 fcn
= gfc_build_intrinsic_call (current_ns
, id
,
384 fn
->value
.function
.isym
->name
,
385 fn
->where
, 2, fcn
, NULL
);
387 gfc_internal_error ("Illegal id in copy_walk_reduction_arg");
389 fcn
->symtree
->n
.sym
->attr
.access
= ACCESS_PRIVATE
;
395 /* Callback function for optimzation of reductions to scalars. Transform ANY
396 ([f1,f2,f3, ...]) to f1 .or. f2 .or. f3 .or. ..., with ANY, SUM and PRODUCT
397 correspondingly. Handly only the simple cases without MASK and DIM. */
400 callback_reduction (gfc_expr
**e
, int *walk_subtrees ATTRIBUTE_UNUSED
,
401 void *data ATTRIBUTE_UNUSED
)
406 gfc_actual_arglist
*a
;
407 gfc_actual_arglist
*dim
;
409 gfc_expr
*res
, *new_expr
;
410 gfc_actual_arglist
*mask
;
414 if (fn
->rank
!= 0 || fn
->expr_type
!= EXPR_FUNCTION
415 || fn
->value
.function
.isym
== NULL
)
418 id
= fn
->value
.function
.isym
->id
;
420 if (id
!= GFC_ISYM_SUM
&& id
!= GFC_ISYM_PRODUCT
421 && id
!= GFC_ISYM_ANY
&& id
!= GFC_ISYM_ALL
)
424 a
= fn
->value
.function
.actual
;
426 /* Don't handle MASK or DIM. */
430 if (dim
->expr
!= NULL
)
433 if (id
== GFC_ISYM_SUM
|| id
== GFC_ISYM_PRODUCT
)
436 if ( mask
->expr
!= NULL
)
442 if (arg
->expr_type
!= EXPR_ARRAY
)
451 case GFC_ISYM_PRODUCT
:
452 op
= INTRINSIC_TIMES
;
467 c
= gfc_constructor_first (arg
->value
.constructor
);
469 /* Don't do any simplififcation if we have
470 - no element in the constructor or
471 - only have a single element in the array which contains an
477 res
= copy_walk_reduction_arg (c
, fn
);
479 c
= gfc_constructor_next (c
);
482 new_expr
= gfc_get_expr ();
483 new_expr
->ts
= fn
->ts
;
484 new_expr
->expr_type
= EXPR_OP
;
485 new_expr
->rank
= fn
->rank
;
486 new_expr
->where
= fn
->where
;
487 new_expr
->value
.op
.op
= op
;
488 new_expr
->value
.op
.op1
= res
;
489 new_expr
->value
.op
.op2
= copy_walk_reduction_arg (c
, fn
);
491 c
= gfc_constructor_next (c
);
494 gfc_simplify_expr (res
, 0);
501 /* Callback function for common function elimination, called from cfe_expr_0.
502 Put all eligible function expressions into expr_array. */
505 cfe_register_funcs (gfc_expr
**e
, int *walk_subtrees ATTRIBUTE_UNUSED
,
506 void *data ATTRIBUTE_UNUSED
)
509 if ((*e
)->expr_type
!= EXPR_FUNCTION
)
512 /* We don't do character functions with unknown charlens. */
513 if ((*e
)->ts
.type
== BT_CHARACTER
514 && ((*e
)->ts
.u
.cl
== NULL
|| (*e
)->ts
.u
.cl
->length
== NULL
515 || (*e
)->ts
.u
.cl
->length
->expr_type
!= EXPR_CONSTANT
))
518 /* We don't do function elimination within FORALL statements, it can
519 lead to wrong-code in certain circumstances. */
521 if (forall_level
> 0)
524 /* Function elimination inside an iterator could lead to functions which
525 depend on iterator variables being moved outside. FIXME: We should check
526 if the functions do indeed depend on the iterator variable. */
528 if (iterator_level
> 0)
531 /* If we don't know the shape at compile time, we create an allocatable
532 temporary variable to hold the intermediate result, but only if
533 allocation on assignment is active. */
535 if ((*e
)->rank
> 0 && (*e
)->shape
== NULL
&& !flag_realloc_lhs
)
538 /* Skip the test for pure functions if -faggressive-function-elimination
540 if ((*e
)->value
.function
.esym
)
542 /* Don't create an array temporary for elemental functions. */
543 if ((*e
)->value
.function
.esym
->attr
.elemental
&& (*e
)->rank
> 0)
546 /* Only eliminate potentially impure functions if the
547 user specifically requested it. */
548 if (!flag_aggressive_function_elimination
549 && !(*e
)->value
.function
.esym
->attr
.pure
550 && !(*e
)->value
.function
.esym
->attr
.implicit_pure
)
554 if ((*e
)->value
.function
.isym
)
556 /* Conversions are handled on the fly by the middle end,
557 transpose during trans-* stages and TRANSFER by the middle end. */
558 if ((*e
)->value
.function
.isym
->id
== GFC_ISYM_CONVERSION
559 || (*e
)->value
.function
.isym
->id
== GFC_ISYM_TRANSFER
560 || gfc_inline_intrinsic_function_p (*e
))
563 /* Don't create an array temporary for elemental functions,
564 as this would be wasteful of memory.
565 FIXME: Create a scalar temporary during scalarization. */
566 if ((*e
)->value
.function
.isym
->elemental
&& (*e
)->rank
> 0)
569 if (!(*e
)->value
.function
.isym
->pure
)
573 expr_array
.safe_push (e
);
577 /* Auxiliary function to check if an expression is a temporary created by
581 is_fe_temp (gfc_expr
*e
)
583 if (e
->expr_type
!= EXPR_VARIABLE
)
586 return e
->symtree
->n
.sym
->attr
.fe_temp
;
589 /* Determine the length of a string, if it can be evaluated as a constant
590 expression. Return a newly allocated gfc_expr or NULL on failure.
591 If the user specified a substring which is potentially longer than
592 the string itself, the string will be padded with spaces, which
596 constant_string_length (gfc_expr
*e
)
606 length
= e
->ts
.u
.cl
->length
;
607 if (length
&& length
->expr_type
== EXPR_CONSTANT
)
608 return gfc_copy_expr(length
);
611 /* Return length of substring, if constant. */
612 for (ref
= e
->ref
; ref
; ref
= ref
->next
)
614 if (ref
->type
== REF_SUBSTRING
615 && gfc_dep_difference (ref
->u
.ss
.end
, ref
->u
.ss
.start
, &value
))
617 res
= gfc_get_constant_expr (BT_INTEGER
, gfc_charlen_int_kind
,
620 mpz_add_ui (res
->value
.integer
, value
, 1);
626 /* Return length of char symbol, if constant. */
628 if (e
->symtree
->n
.sym
->ts
.u
.cl
&& e
->symtree
->n
.sym
->ts
.u
.cl
->length
629 && e
->symtree
->n
.sym
->ts
.u
.cl
->length
->expr_type
== EXPR_CONSTANT
)
630 return gfc_copy_expr (e
->symtree
->n
.sym
->ts
.u
.cl
->length
);
636 /* Insert a block at the current position unless it has already
637 been inserted; in this case use the one already there. */
639 static gfc_namespace
*
644 /* If the block hasn't already been created, do so. */
645 if (inserted_block
== NULL
)
647 inserted_block
= XCNEW (gfc_code
);
648 inserted_block
->op
= EXEC_BLOCK
;
649 inserted_block
->loc
= (*current_code
)->loc
;
650 ns
= gfc_build_block_ns (current_ns
);
651 inserted_block
->ext
.block
.ns
= ns
;
652 inserted_block
->ext
.block
.assoc
= NULL
;
654 ns
->code
= *current_code
;
656 /* If the statement has a label, make sure it is transferred to
657 the newly created block. */
659 if ((*current_code
)->here
)
661 inserted_block
->here
= (*current_code
)->here
;
662 (*current_code
)->here
= NULL
;
665 inserted_block
->next
= (*current_code
)->next
;
666 changed_statement
= &(inserted_block
->ext
.block
.ns
->code
);
667 (*current_code
)->next
= NULL
;
668 /* Insert the BLOCK at the right position. */
669 *current_code
= inserted_block
;
670 ns
->parent
= current_ns
;
673 ns
= inserted_block
->ext
.block
.ns
;
678 /* Returns a new expression (a variable) to be used in place of the old one,
679 with an optional assignment statement before the current statement to set
680 the value of the variable. Creates a new BLOCK for the statement if that
681 hasn't already been done and puts the statement, plus the newly created
682 variables, in that block. Special cases: If the expression is constant or
683 a temporary which has already been created, just copy it. */
686 create_var (gfc_expr
* e
, const char *vname
)
688 char name
[GFC_MAX_SYMBOL_LEN
+1];
689 gfc_symtree
*symtree
;
697 if (e
->expr_type
== EXPR_CONSTANT
|| is_fe_temp (e
))
698 return gfc_copy_expr (e
);
700 ns
= insert_block ();
703 snprintf (name
, GFC_MAX_SYMBOL_LEN
, "__var_%d_%s", var_num
++, vname
);
705 snprintf (name
, GFC_MAX_SYMBOL_LEN
, "__var_%d", var_num
++);
707 if (gfc_get_sym_tree (name
, ns
, &symtree
, false) != 0)
710 symbol
= symtree
->n
.sym
;
715 symbol
->as
= gfc_get_array_spec ();
716 symbol
->as
->rank
= e
->rank
;
718 if (e
->shape
== NULL
)
720 /* We don't know the shape at compile time, so we use an
722 symbol
->as
->type
= AS_DEFERRED
;
723 symbol
->attr
.allocatable
= 1;
727 symbol
->as
->type
= AS_EXPLICIT
;
728 /* Copy the shape. */
729 for (i
=0; i
<e
->rank
; i
++)
733 p
= gfc_get_constant_expr (BT_INTEGER
, gfc_default_integer_kind
,
735 mpz_set_si (p
->value
.integer
, 1);
736 symbol
->as
->lower
[i
] = p
;
738 q
= gfc_get_constant_expr (BT_INTEGER
, gfc_index_integer_kind
,
740 mpz_set (q
->value
.integer
, e
->shape
[i
]);
741 symbol
->as
->upper
[i
] = q
;
747 if (e
->ts
.type
== BT_CHARACTER
&& e
->rank
== 0)
751 symbol
->ts
.u
.cl
= gfc_new_charlen (ns
, NULL
);
752 length
= constant_string_length (e
);
754 symbol
->ts
.u
.cl
->length
= length
;
757 symbol
->attr
.allocatable
= 1;
762 symbol
->attr
.flavor
= FL_VARIABLE
;
763 symbol
->attr
.referenced
= 1;
764 symbol
->attr
.dimension
= e
->rank
> 0;
765 symbol
->attr
.fe_temp
= 1;
766 gfc_commit_symbol (symbol
);
768 result
= gfc_get_expr ();
769 result
->expr_type
= EXPR_VARIABLE
;
771 result
->ts
.deferred
= deferred
;
772 result
->rank
= e
->rank
;
773 result
->shape
= gfc_copy_shape (e
->shape
, e
->rank
);
774 result
->symtree
= symtree
;
775 result
->where
= e
->where
;
778 result
->ref
= gfc_get_ref ();
779 result
->ref
->type
= REF_ARRAY
;
780 result
->ref
->u
.ar
.type
= AR_FULL
;
781 result
->ref
->u
.ar
.where
= e
->where
;
782 result
->ref
->u
.ar
.dimen
= e
->rank
;
783 result
->ref
->u
.ar
.as
= symbol
->ts
.type
== BT_CLASS
784 ? CLASS_DATA (symbol
)->as
: symbol
->as
;
785 if (warn_array_temporaries
)
786 gfc_warning (OPT_Warray_temporaries
,
787 "Creating array temporary at %L", &(e
->where
));
790 /* Generate the new assignment. */
791 n
= XCNEW (gfc_code
);
793 n
->loc
= (*current_code
)->loc
;
794 n
->next
= *changed_statement
;
795 n
->expr1
= gfc_copy_expr (result
);
797 *changed_statement
= n
;
803 /* Warn about function elimination. */
806 do_warn_function_elimination (gfc_expr
*e
)
808 if (e
->expr_type
!= EXPR_FUNCTION
)
810 if (e
->value
.function
.esym
)
811 gfc_warning (OPT_Wfunction_elimination
,
812 "Removing call to function %qs at %L",
813 e
->value
.function
.esym
->name
, &(e
->where
));
814 else if (e
->value
.function
.isym
)
815 gfc_warning (OPT_Wfunction_elimination
,
816 "Removing call to function %qs at %L",
817 e
->value
.function
.isym
->name
, &(e
->where
));
819 /* Callback function for the code walker for doing common function
820 elimination. This builds up the list of functions in the expression
821 and goes through them to detect duplicates, which it then replaces
825 cfe_expr_0 (gfc_expr
**e
, int *walk_subtrees
,
826 void *data ATTRIBUTE_UNUSED
)
832 /* Don't do this optimization within OMP workshare or ASSOC lists. */
834 if (in_omp_workshare
|| in_assoc_list
)
840 expr_array
.release ();
842 gfc_expr_walker (e
, cfe_register_funcs
, NULL
);
844 /* Walk through all the functions. */
846 FOR_EACH_VEC_ELT_FROM (expr_array
, i
, ei
, 1)
848 /* Skip if the function has been replaced by a variable already. */
849 if ((*ei
)->expr_type
== EXPR_VARIABLE
)
856 if (gfc_dep_compare_functions (*ei
, *ej
, true) == 0)
859 newvar
= create_var (*ei
, "fcn");
861 if (warn_function_elimination
)
862 do_warn_function_elimination (*ej
);
865 *ej
= gfc_copy_expr (newvar
);
872 /* We did all the necessary walking in this function. */
877 /* Callback function for common function elimination, called from
878 gfc_code_walker. This keeps track of the current code, in order
879 to insert statements as needed. */
882 cfe_code (gfc_code
**c
, int *walk_subtrees
, void *data ATTRIBUTE_UNUSED
)
885 inserted_block
= NULL
;
886 changed_statement
= NULL
;
888 /* Do not do anything inside a WHERE statement; scalar assignments, BLOCKs
889 and allocation on assigment are prohibited inside WHERE, and finally
890 masking an expression would lead to wrong-code when replacing
893 b = sum(foo(a) + foo(a))
904 if ((*c
)->op
== EXEC_WHERE
)
914 /* Dummy function for expression call back, for use when we
915 really don't want to do any walking. */
918 dummy_expr_callback (gfc_expr
**e ATTRIBUTE_UNUSED
, int *walk_subtrees
,
919 void *data ATTRIBUTE_UNUSED
)
925 /* Dummy function for code callback, for use when we really
926 don't want to do anything. */
928 gfc_dummy_code_callback (gfc_code
**e ATTRIBUTE_UNUSED
,
929 int *walk_subtrees ATTRIBUTE_UNUSED
,
930 void *data ATTRIBUTE_UNUSED
)
935 /* Code callback function for converting
942 This is because common function elimination would otherwise place the
943 temporary variables outside the loop. */
946 convert_do_while (gfc_code
**c
, int *walk_subtrees ATTRIBUTE_UNUSED
,
947 void *data ATTRIBUTE_UNUSED
)
950 gfc_code
*c_if1
, *c_if2
, *c_exit
;
952 gfc_expr
*e_not
, *e_cond
;
954 if (co
->op
!= EXEC_DO_WHILE
)
957 if (co
->expr1
== NULL
|| co
->expr1
->expr_type
== EXPR_CONSTANT
)
962 /* Generate the condition of the if statement, which is .not. the original
964 e_not
= gfc_get_expr ();
965 e_not
->ts
= e_cond
->ts
;
966 e_not
->where
= e_cond
->where
;
967 e_not
->expr_type
= EXPR_OP
;
968 e_not
->value
.op
.op
= INTRINSIC_NOT
;
969 e_not
->value
.op
.op1
= e_cond
;
971 /* Generate the EXIT statement. */
972 c_exit
= XCNEW (gfc_code
);
973 c_exit
->op
= EXEC_EXIT
;
974 c_exit
->ext
.which_construct
= co
;
975 c_exit
->loc
= co
->loc
;
977 /* Generate the IF statement. */
978 c_if2
= XCNEW (gfc_code
);
980 c_if2
->expr1
= e_not
;
981 c_if2
->next
= c_exit
;
982 c_if2
->loc
= co
->loc
;
984 /* ... plus the one to chain it to. */
985 c_if1
= XCNEW (gfc_code
);
987 c_if1
->block
= c_if2
;
988 c_if1
->loc
= co
->loc
;
990 /* Make the DO WHILE loop into a DO block by replacing the condition
991 with a true constant. */
992 co
->expr1
= gfc_get_logical_expr (gfc_default_integer_kind
, &co
->loc
, true);
994 /* Hang the generated if statement into the loop body. */
996 loopblock
= co
->block
->next
;
997 co
->block
->next
= c_if1
;
998 c_if1
->next
= loopblock
;
1003 /* Code callback function for converting
1016 because otherwise common function elimination would place the BLOCKs
1017 into the wrong place. */
1020 convert_elseif (gfc_code
**c
, int *walk_subtrees ATTRIBUTE_UNUSED
,
1021 void *data ATTRIBUTE_UNUSED
)
1024 gfc_code
*c_if1
, *c_if2
, *else_stmt
;
1026 if (co
->op
!= EXEC_IF
)
1029 /* This loop starts out with the first ELSE statement. */
1030 else_stmt
= co
->block
->block
;
1032 while (else_stmt
!= NULL
)
1034 gfc_code
*next_else
;
1036 /* If there is no condition, we're done. */
1037 if (else_stmt
->expr1
== NULL
)
1040 next_else
= else_stmt
->block
;
1042 /* Generate the new IF statement. */
1043 c_if2
= XCNEW (gfc_code
);
1044 c_if2
->op
= EXEC_IF
;
1045 c_if2
->expr1
= else_stmt
->expr1
;
1046 c_if2
->next
= else_stmt
->next
;
1047 c_if2
->loc
= else_stmt
->loc
;
1048 c_if2
->block
= next_else
;
1050 /* ... plus the one to chain it to. */
1051 c_if1
= XCNEW (gfc_code
);
1052 c_if1
->op
= EXEC_IF
;
1053 c_if1
->block
= c_if2
;
1054 c_if1
->loc
= else_stmt
->loc
;
1056 /* Insert the new IF after the ELSE. */
1057 else_stmt
->expr1
= NULL
;
1058 else_stmt
->next
= c_if1
;
1059 else_stmt
->block
= NULL
;
1061 else_stmt
= next_else
;
1063 /* Don't walk subtrees. */
1069 struct do_stack
*prev
;
1074 /* Recursively traverse the block of a WRITE or READ statement, and maybe
1075 optimize by replacing do loops with their analog array slices. For
1078 write (*,*) (a(i), i=1,4)
1082 write (*,*) a(1:4:1) . */
1085 traverse_io_block (gfc_code
*code
, bool *has_reached
, gfc_code
*prev
)
1088 gfc_expr
*new_e
, *expr
, *start
;
1090 struct do_stack ds_push
;
1091 int i
, future_rank
= 0;
1092 gfc_iterator
*iters
[GFC_MAX_DIMENSIONS
];
1095 /* Find the first transfer/do statement. */
1096 for (curr
= code
; curr
; curr
= curr
->next
)
1098 if (curr
->op
== EXEC_DO
|| curr
->op
== EXEC_TRANSFER
)
1102 /* Ensure it is the only transfer/do statement because cases like
1104 write (*,*) (a(i), b(i), i=1,4)
1106 cannot be optimized. */
1108 if (!curr
|| curr
->next
)
1111 if (curr
->op
== EXEC_DO
)
1113 if (curr
->ext
.iterator
->var
->ref
)
1115 ds_push
.prev
= stack_top
;
1116 ds_push
.iter
= curr
->ext
.iterator
;
1117 ds_push
.code
= curr
;
1118 stack_top
= &ds_push
;
1119 if (traverse_io_block (curr
->block
->next
, has_reached
, prev
))
1121 if (curr
!= stack_top
->code
&& !*has_reached
)
1123 curr
->block
->next
= NULL
;
1124 gfc_free_statements (curr
);
1127 *has_reached
= true;
1133 gcc_assert (curr
->op
== EXEC_TRANSFER
);
1135 /* FIXME: Workaround for PR 80945 - array slices with deferred character
1136 lenghts do not work. Remove this section when the PR is fixed. */
1138 if (e
->expr_type
== EXPR_VARIABLE
&& e
->ts
.type
== BT_CHARACTER
1141 /* End of section to be removed. */
1144 if (!ref
|| ref
->type
!= REF_ARRAY
|| ref
->u
.ar
.codimen
!= 0 || ref
->next
)
1147 /* Find the iterators belonging to each variable and check conditions. */
1148 for (i
= 0; i
< ref
->u
.ar
.dimen
; i
++)
1150 if (!ref
->u
.ar
.start
[i
] || ref
->u
.ar
.start
[i
]->ref
1151 || ref
->u
.ar
.dimen_type
[i
] != DIMEN_ELEMENT
)
1154 start
= ref
->u
.ar
.start
[i
];
1155 gfc_simplify_expr (start
, 0);
1156 switch (start
->expr_type
)
1160 /* write (*,*) (a(i), i=a%b,1) not handled yet. */
1164 /* Check for (a(k), i=1,4) or ((a(j, i), i=1,4), j=1,4). */
1165 if (!stack_top
|| !stack_top
->iter
1166 || stack_top
->iter
->var
->symtree
!= start
->symtree
)
1168 /* Check for (a(i,i), i=1,3). */
1172 if (iters
[j
] && iters
[j
]->var
->symtree
== start
->symtree
)
1179 iters
[i
] = stack_top
->iter
;
1180 stack_top
= stack_top
->prev
;
1188 switch (start
->value
.op
.op
)
1190 case INTRINSIC_PLUS
:
1191 case INTRINSIC_TIMES
:
1192 if (start
->value
.op
.op1
->expr_type
!= EXPR_VARIABLE
)
1193 std::swap (start
->value
.op
.op1
, start
->value
.op
.op2
);
1195 case INTRINSIC_MINUS
:
1196 if ((start
->value
.op
.op1
->expr_type
!= EXPR_VARIABLE
1197 && start
->value
.op
.op2
->expr_type
!= EXPR_CONSTANT
)
1198 || start
->value
.op
.op1
->ref
)
1200 if (!stack_top
|| !stack_top
->iter
1201 || stack_top
->iter
->var
->symtree
1202 != start
->value
.op
.op1
->symtree
)
1204 iters
[i
] = stack_top
->iter
;
1205 stack_top
= stack_top
->prev
;
1217 /* Create new expr. */
1218 new_e
= gfc_copy_expr (curr
->expr1
);
1219 new_e
->expr_type
= EXPR_VARIABLE
;
1220 new_e
->rank
= future_rank
;
1221 if (curr
->expr1
->shape
)
1222 new_e
->shape
= gfc_get_shape (new_e
->rank
);
1224 /* Assign new starts, ends and strides if necessary. */
1225 for (i
= 0; i
< ref
->u
.ar
.dimen
; i
++)
1229 start
= ref
->u
.ar
.start
[i
];
1230 switch (start
->expr_type
)
1233 gfc_internal_error ("bad expression");
1236 new_e
->ref
->u
.ar
.dimen_type
[i
] = DIMEN_RANGE
;
1237 new_e
->ref
->u
.ar
.type
= AR_SECTION
;
1238 gfc_free_expr (new_e
->ref
->u
.ar
.start
[i
]);
1239 new_e
->ref
->u
.ar
.start
[i
] = gfc_copy_expr (iters
[i
]->start
);
1240 new_e
->ref
->u
.ar
.end
[i
] = gfc_copy_expr (iters
[i
]->end
);
1241 new_e
->ref
->u
.ar
.stride
[i
] = gfc_copy_expr (iters
[i
]->step
);
1244 new_e
->ref
->u
.ar
.dimen_type
[i
] = DIMEN_RANGE
;
1245 new_e
->ref
->u
.ar
.type
= AR_SECTION
;
1246 gfc_free_expr (new_e
->ref
->u
.ar
.start
[i
]);
1247 expr
= gfc_copy_expr (start
);
1248 expr
->value
.op
.op1
= gfc_copy_expr (iters
[i
]->start
);
1249 new_e
->ref
->u
.ar
.start
[i
] = expr
;
1250 gfc_simplify_expr (new_e
->ref
->u
.ar
.start
[i
], 0);
1251 expr
= gfc_copy_expr (start
);
1252 expr
->value
.op
.op1
= gfc_copy_expr (iters
[i
]->end
);
1253 new_e
->ref
->u
.ar
.end
[i
] = expr
;
1254 gfc_simplify_expr (new_e
->ref
->u
.ar
.end
[i
], 0);
1255 switch (start
->value
.op
.op
)
1257 case INTRINSIC_MINUS
:
1258 case INTRINSIC_PLUS
:
1259 new_e
->ref
->u
.ar
.stride
[i
] = gfc_copy_expr (iters
[i
]->step
);
1261 case INTRINSIC_TIMES
:
1262 expr
= gfc_copy_expr (start
);
1263 expr
->value
.op
.op1
= gfc_copy_expr (iters
[i
]->step
);
1264 new_e
->ref
->u
.ar
.stride
[i
] = expr
;
1265 gfc_simplify_expr (new_e
->ref
->u
.ar
.stride
[i
], 0);
1268 gfc_internal_error ("bad op");
1272 gfc_internal_error ("bad expression");
1275 curr
->expr1
= new_e
;
1277 /* Insert modified statement. Check whether the statement needs to be
1278 inserted at the lowest level. */
1279 if (!stack_top
->iter
)
1283 curr
->next
= prev
->next
->next
;
1288 curr
->next
= stack_top
->code
->block
->next
->next
->next
;
1289 stack_top
->code
->block
->next
= curr
;
1293 stack_top
->code
->block
->next
= curr
;
1297 /* Function for the gfc_code_walker. If code is a READ or WRITE statement, it
1298 tries to optimize its block. */
1301 simplify_io_impl_do (gfc_code
**code
, int *walk_subtrees
,
1302 void *data ATTRIBUTE_UNUSED
)
1304 gfc_code
**curr
, *prev
= NULL
;
1305 struct do_stack write
, first
;
1309 || ((*code
)->block
->op
!= EXEC_WRITE
1310 && (*code
)->block
->op
!= EXEC_READ
))
1318 for (curr
= &(*code
)->block
; *curr
; curr
= &(*curr
)->next
)
1320 if ((*curr
)->op
== EXEC_DO
)
1322 first
.prev
= &write
;
1323 first
.iter
= (*curr
)->ext
.iterator
;
1326 traverse_io_block ((*curr
)->block
->next
, &b
, prev
);
1334 /* Optimize a namespace, including all contained namespaces. */
1337 optimize_namespace (gfc_namespace
*ns
)
1339 gfc_namespace
*saved_ns
= gfc_current_ns
;
1341 gfc_current_ns
= ns
;
1344 in_assoc_list
= false;
1345 in_omp_workshare
= false;
1347 gfc_code_walker (&ns
->code
, simplify_io_impl_do
, dummy_expr_callback
, NULL
);
1348 gfc_code_walker (&ns
->code
, convert_do_while
, dummy_expr_callback
, NULL
);
1349 gfc_code_walker (&ns
->code
, convert_elseif
, dummy_expr_callback
, NULL
);
1350 gfc_code_walker (&ns
->code
, cfe_code
, cfe_expr_0
, NULL
);
1351 gfc_code_walker (&ns
->code
, optimize_code
, optimize_expr
, NULL
);
1352 if (flag_inline_matmul_limit
!= 0)
1358 gfc_code_walker (&ns
->code
, matmul_to_var_code
, matmul_to_var_expr
,
1363 gfc_code_walker (&ns
->code
, matmul_temp_args
, dummy_expr_callback
,
1365 gfc_code_walker (&ns
->code
, inline_matmul_assign
, dummy_expr_callback
,
1369 /* BLOCKs are handled in the expression walker below. */
1370 for (ns
= ns
->contained
; ns
; ns
= ns
->sibling
)
1372 if (ns
->code
== NULL
|| ns
->code
->op
!= EXEC_BLOCK
)
1373 optimize_namespace (ns
);
1375 gfc_current_ns
= saved_ns
;
1378 /* Handle dependencies for allocatable strings which potentially redefine
1379 themselves in an assignment. */
1382 realloc_strings (gfc_namespace
*ns
)
1385 gfc_code_walker (&ns
->code
, realloc_string_callback
, dummy_expr_callback
, NULL
);
1387 for (ns
= ns
->contained
; ns
; ns
= ns
->sibling
)
1389 if (ns
->code
== NULL
|| ns
->code
->op
!= EXEC_BLOCK
)
1390 realloc_strings (ns
);
1396 optimize_reduction (gfc_namespace
*ns
)
1399 gfc_code_walker (&ns
->code
, gfc_dummy_code_callback
,
1400 callback_reduction
, NULL
);
1402 /* BLOCKs are handled in the expression walker below. */
1403 for (ns
= ns
->contained
; ns
; ns
= ns
->sibling
)
1405 if (ns
->code
== NULL
|| ns
->code
->op
!= EXEC_BLOCK
)
1406 optimize_reduction (ns
);
1410 /* Replace code like
1413 a = matmul(b,c) ; a = a + d
1414 where the array function is not elemental and not allocatable
1415 and does not depend on the left-hand side.
1419 optimize_binop_array_assignment (gfc_code
*c
, gfc_expr
**rhs
, bool seen_op
)
1427 if (e
->expr_type
== EXPR_OP
)
1429 switch (e
->value
.op
.op
)
1431 /* Unary operators and exponentiation: Only look at a single
1434 case INTRINSIC_UPLUS
:
1435 case INTRINSIC_UMINUS
:
1436 case INTRINSIC_PARENTHESES
:
1437 case INTRINSIC_POWER
:
1438 if (optimize_binop_array_assignment (c
, &e
->value
.op
.op1
, seen_op
))
1442 case INTRINSIC_CONCAT
:
1443 /* Do not do string concatenations. */
1447 /* Binary operators. */
1448 if (optimize_binop_array_assignment (c
, &e
->value
.op
.op1
, true))
1451 if (optimize_binop_array_assignment (c
, &e
->value
.op
.op2
, true))
1457 else if (seen_op
&& e
->expr_type
== EXPR_FUNCTION
&& e
->rank
> 0
1458 && ! (e
->value
.function
.esym
1459 && (e
->value
.function
.esym
->attr
.elemental
1460 || e
->value
.function
.esym
->attr
.allocatable
1461 || e
->value
.function
.esym
->ts
.type
!= c
->expr1
->ts
.type
1462 || e
->value
.function
.esym
->ts
.kind
!= c
->expr1
->ts
.kind
))
1463 && ! (e
->value
.function
.isym
1464 && (e
->value
.function
.isym
->elemental
1465 || e
->ts
.type
!= c
->expr1
->ts
.type
1466 || e
->ts
.kind
!= c
->expr1
->ts
.kind
))
1467 && ! gfc_inline_intrinsic_function_p (e
))
1473 /* Insert a new assignment statement after the current one. */
1474 n
= XCNEW (gfc_code
);
1475 n
->op
= EXEC_ASSIGN
;
1480 n
->expr1
= gfc_copy_expr (c
->expr1
);
1481 n
->expr2
= c
->expr2
;
1482 new_expr
= gfc_copy_expr (c
->expr1
);
1490 /* Nothing to optimize. */
1494 /* Remove unneeded TRIMs at the end of expressions. */
1497 remove_trim (gfc_expr
*rhs
)
1505 /* Check for a // b // trim(c). Looping is probably not
1506 necessary because the parser usually generates
1507 (// (// a b ) trim(c) ) , but better safe than sorry. */
1509 while (rhs
->expr_type
== EXPR_OP
1510 && rhs
->value
.op
.op
== INTRINSIC_CONCAT
)
1511 rhs
= rhs
->value
.op
.op2
;
1513 while (rhs
->expr_type
== EXPR_FUNCTION
&& rhs
->value
.function
.isym
1514 && rhs
->value
.function
.isym
->id
== GFC_ISYM_TRIM
)
1516 strip_function_call (rhs
);
1517 /* Recursive call to catch silly stuff like trim ( a // trim(b)). */
1525 /* Optimizations for an assignment. */
1528 optimize_assignment (gfc_code
* c
)
1530 gfc_expr
*lhs
, *rhs
;
1535 if (lhs
->ts
.type
== BT_CHARACTER
&& !lhs
->ts
.deferred
)
1537 /* Optimize a = trim(b) to a = b. */
1540 /* Replace a = ' ' by a = '' to optimize away a memcpy. */
1541 if (is_empty_string (rhs
))
1542 rhs
->value
.character
.length
= 0;
1545 if (lhs
->rank
> 0 && gfc_check_dependency (lhs
, rhs
, true) == 0)
1546 optimize_binop_array_assignment (c
, &rhs
, false);
1550 /* Remove an unneeded function call, modifying the expression.
1551 This replaces the function call with the value of its
1552 first argument. The rest of the argument list is freed. */
1555 strip_function_call (gfc_expr
*e
)
1558 gfc_actual_arglist
*a
;
1560 a
= e
->value
.function
.actual
;
1562 /* We should have at least one argument. */
1563 gcc_assert (a
->expr
!= NULL
);
1567 /* Free the remaining arglist, if any. */
1569 gfc_free_actual_arglist (a
->next
);
1571 /* Graft the argument expression onto the original function. */
1577 /* Optimization of lexical comparison functions. */
1580 optimize_lexical_comparison (gfc_expr
*e
)
1582 if (e
->expr_type
!= EXPR_FUNCTION
|| e
->value
.function
.isym
== NULL
)
1585 switch (e
->value
.function
.isym
->id
)
1588 return optimize_comparison (e
, INTRINSIC_LE
);
1591 return optimize_comparison (e
, INTRINSIC_GE
);
1594 return optimize_comparison (e
, INTRINSIC_GT
);
1597 return optimize_comparison (e
, INTRINSIC_LT
);
1605 /* Combine stuff like [a]>b into [a>b], for easier optimization later. Do not
1606 do CHARACTER because of possible pessimization involving character
1610 combine_array_constructor (gfc_expr
*e
)
1613 gfc_expr
*op1
, *op2
;
1616 gfc_constructor
*c
, *new_c
;
1617 gfc_constructor_base oldbase
, newbase
;
1620 /* Array constructors have rank one. */
1624 /* Don't try to combine association lists, this makes no sense
1625 and leads to an ICE. */
1629 /* With FORALL, the BLOCKS created by create_var will cause an ICE. */
1630 if (forall_level
> 0)
1633 /* Inside an iterator, things can get hairy; we are likely to create
1634 an invalid temporary variable. */
1635 if (iterator_level
> 0)
1638 op1
= e
->value
.op
.op1
;
1639 op2
= e
->value
.op
.op2
;
1644 if (op1
->expr_type
== EXPR_ARRAY
&& op2
->rank
== 0)
1645 scalar_first
= false;
1646 else if (op2
->expr_type
== EXPR_ARRAY
&& op1
->rank
== 0)
1648 scalar_first
= true;
1649 op1
= e
->value
.op
.op2
;
1650 op2
= e
->value
.op
.op1
;
1655 if (op2
->ts
.type
== BT_CHARACTER
)
1658 scalar
= create_var (gfc_copy_expr (op2
), "constr");
1660 oldbase
= op1
->value
.constructor
;
1662 e
->expr_type
= EXPR_ARRAY
;
1664 for (c
= gfc_constructor_first (oldbase
); c
;
1665 c
= gfc_constructor_next (c
))
1667 new_expr
= gfc_get_expr ();
1668 new_expr
->ts
= e
->ts
;
1669 new_expr
->expr_type
= EXPR_OP
;
1670 new_expr
->rank
= c
->expr
->rank
;
1671 new_expr
->where
= c
->expr
->where
;
1672 new_expr
->value
.op
.op
= e
->value
.op
.op
;
1676 new_expr
->value
.op
.op1
= gfc_copy_expr (scalar
);
1677 new_expr
->value
.op
.op2
= gfc_copy_expr (c
->expr
);
1681 new_expr
->value
.op
.op1
= gfc_copy_expr (c
->expr
);
1682 new_expr
->value
.op
.op2
= gfc_copy_expr (scalar
);
1685 new_c
= gfc_constructor_append_expr (&newbase
, new_expr
, &(e
->where
));
1686 new_c
->iterator
= c
->iterator
;
1690 gfc_free_expr (op1
);
1691 gfc_free_expr (op2
);
1692 gfc_free_expr (scalar
);
1694 e
->value
.constructor
= newbase
;
1698 /* Change (-1)**k into 1-ishift(iand(k,1),1) and
1699 2**k into ishift(1,k) */
1702 optimize_power (gfc_expr
*e
)
1704 gfc_expr
*op1
, *op2
;
1705 gfc_expr
*iand
, *ishft
;
1707 if (e
->ts
.type
!= BT_INTEGER
)
1710 op1
= e
->value
.op
.op1
;
1712 if (op1
== NULL
|| op1
->expr_type
!= EXPR_CONSTANT
)
1715 if (mpz_cmp_si (op1
->value
.integer
, -1L) == 0)
1717 gfc_free_expr (op1
);
1719 op2
= e
->value
.op
.op2
;
1724 iand
= gfc_build_intrinsic_call (current_ns
, GFC_ISYM_IAND
,
1725 "_internal_iand", e
->where
, 2, op2
,
1726 gfc_get_int_expr (e
->ts
.kind
,
1729 ishft
= gfc_build_intrinsic_call (current_ns
, GFC_ISYM_ISHFT
,
1730 "_internal_ishft", e
->where
, 2, iand
,
1731 gfc_get_int_expr (e
->ts
.kind
,
1734 e
->value
.op
.op
= INTRINSIC_MINUS
;
1735 e
->value
.op
.op1
= gfc_get_int_expr (e
->ts
.kind
, &e
->where
, 1);
1736 e
->value
.op
.op2
= ishft
;
1739 else if (mpz_cmp_si (op1
->value
.integer
, 2L) == 0)
1741 gfc_free_expr (op1
);
1743 op2
= e
->value
.op
.op2
;
1747 ishft
= gfc_build_intrinsic_call (current_ns
, GFC_ISYM_ISHFT
,
1748 "_internal_ishft", e
->where
, 2,
1749 gfc_get_int_expr (e
->ts
.kind
,
1756 else if (mpz_cmp_si (op1
->value
.integer
, 1L) == 0)
1758 op2
= e
->value
.op
.op2
;
1762 gfc_free_expr (op1
);
1763 gfc_free_expr (op2
);
1765 e
->expr_type
= EXPR_CONSTANT
;
1766 e
->value
.op
.op1
= NULL
;
1767 e
->value
.op
.op2
= NULL
;
1768 mpz_init_set_si (e
->value
.integer
, 1);
1769 /* Typespec and location are still OK. */
1776 /* Recursive optimization of operators. */
1779 optimize_op (gfc_expr
*e
)
1783 gfc_intrinsic_op op
= e
->value
.op
.op
;
1787 /* Only use new-style comparisons. */
1790 case INTRINSIC_EQ_OS
:
1794 case INTRINSIC_GE_OS
:
1798 case INTRINSIC_LE_OS
:
1802 case INTRINSIC_NE_OS
:
1806 case INTRINSIC_GT_OS
:
1810 case INTRINSIC_LT_OS
:
1826 changed
= optimize_comparison (e
, op
);
1829 /* Look at array constructors. */
1830 case INTRINSIC_PLUS
:
1831 case INTRINSIC_MINUS
:
1832 case INTRINSIC_TIMES
:
1833 case INTRINSIC_DIVIDE
:
1834 return combine_array_constructor (e
) || changed
;
1836 case INTRINSIC_POWER
:
1837 return optimize_power (e
);
1847 /* Return true if a constant string contains only blanks. */
1850 is_empty_string (gfc_expr
*e
)
1854 if (e
->ts
.type
!= BT_CHARACTER
|| e
->expr_type
!= EXPR_CONSTANT
)
1857 for (i
=0; i
< e
->value
.character
.length
; i
++)
1859 if (e
->value
.character
.string
[i
] != ' ')
1867 /* Insert a call to the intrinsic len_trim. Use a different name for
1868 the symbol tree so we don't run into trouble when the user has
1869 renamed len_trim for some reason. */
1872 get_len_trim_call (gfc_expr
*str
, int kind
)
1875 gfc_actual_arglist
*actual_arglist
, *next
;
1877 fcn
= gfc_get_expr ();
1878 fcn
->expr_type
= EXPR_FUNCTION
;
1879 fcn
->value
.function
.isym
= gfc_intrinsic_function_by_id (GFC_ISYM_LEN_TRIM
);
1880 actual_arglist
= gfc_get_actual_arglist ();
1881 actual_arglist
->expr
= str
;
1882 next
= gfc_get_actual_arglist ();
1883 next
->expr
= gfc_get_int_expr (gfc_default_integer_kind
, NULL
, kind
);
1884 actual_arglist
->next
= next
;
1886 fcn
->value
.function
.actual
= actual_arglist
;
1887 fcn
->where
= str
->where
;
1888 fcn
->ts
.type
= BT_INTEGER
;
1889 fcn
->ts
.kind
= gfc_charlen_int_kind
;
1891 gfc_get_sym_tree ("__internal_len_trim", current_ns
, &fcn
->symtree
, false);
1892 fcn
->symtree
->n
.sym
->ts
= fcn
->ts
;
1893 fcn
->symtree
->n
.sym
->attr
.flavor
= FL_PROCEDURE
;
1894 fcn
->symtree
->n
.sym
->attr
.function
= 1;
1895 fcn
->symtree
->n
.sym
->attr
.elemental
= 1;
1896 fcn
->symtree
->n
.sym
->attr
.referenced
= 1;
1897 fcn
->symtree
->n
.sym
->attr
.access
= ACCESS_PRIVATE
;
1898 gfc_commit_symbol (fcn
->symtree
->n
.sym
);
1903 /* Optimize expressions for equality. */
1906 optimize_comparison (gfc_expr
*e
, gfc_intrinsic_op op
)
1908 gfc_expr
*op1
, *op2
;
1912 gfc_actual_arglist
*firstarg
, *secondarg
;
1914 if (e
->expr_type
== EXPR_OP
)
1918 op1
= e
->value
.op
.op1
;
1919 op2
= e
->value
.op
.op2
;
1921 else if (e
->expr_type
== EXPR_FUNCTION
)
1923 /* One of the lexical comparison functions. */
1924 firstarg
= e
->value
.function
.actual
;
1925 secondarg
= firstarg
->next
;
1926 op1
= firstarg
->expr
;
1927 op2
= secondarg
->expr
;
1932 /* Strip off unneeded TRIM calls from string comparisons. */
1934 change
= remove_trim (op1
);
1936 if (remove_trim (op2
))
1939 /* An expression of type EXPR_CONSTANT is only valid for scalars. */
1940 /* TODO: A scalar constant may be acceptable in some cases (the scalarizer
1941 handles them well). However, there are also cases that need a non-scalar
1942 argument. For example the any intrinsic. See PR 45380. */
1946 /* Replace a == '' with len_trim(a) == 0 and a /= '' with
1948 if (op1
->ts
.type
== BT_CHARACTER
&& op2
->ts
.type
== BT_CHARACTER
1949 && (op
== INTRINSIC_EQ
|| op
== INTRINSIC_NE
))
1951 bool empty_op1
, empty_op2
;
1952 empty_op1
= is_empty_string (op1
);
1953 empty_op2
= is_empty_string (op2
);
1955 if (empty_op1
|| empty_op2
)
1961 /* This can only happen when an error for comparing
1962 characters of different kinds has already been issued. */
1963 if (empty_op1
&& empty_op2
)
1966 zero
= gfc_get_int_expr (gfc_charlen_int_kind
, &e
->where
, 0);
1967 str
= empty_op1
? op2
: op1
;
1969 fcn
= get_len_trim_call (str
, gfc_charlen_int_kind
);
1973 gfc_free_expr (op1
);
1975 gfc_free_expr (op2
);
1979 e
->value
.op
.op1
= fcn
;
1980 e
->value
.op
.op2
= zero
;
1985 /* Don't compare REAL or COMPLEX expressions when honoring NaNs. */
1987 if (flag_finite_math_only
1988 || (op1
->ts
.type
!= BT_REAL
&& op2
->ts
.type
!= BT_REAL
1989 && op1
->ts
.type
!= BT_COMPLEX
&& op2
->ts
.type
!= BT_COMPLEX
))
1991 eq
= gfc_dep_compare_expr (op1
, op2
);
1994 /* Replace A // B < A // C with B < C, and A // B < C // B
1996 if (op1
->ts
.type
== BT_CHARACTER
&& op2
->ts
.type
== BT_CHARACTER
1997 && op1
->expr_type
== EXPR_OP
1998 && op1
->value
.op
.op
== INTRINSIC_CONCAT
1999 && op2
->expr_type
== EXPR_OP
2000 && op2
->value
.op
.op
== INTRINSIC_CONCAT
)
2002 gfc_expr
*op1_left
= op1
->value
.op
.op1
;
2003 gfc_expr
*op2_left
= op2
->value
.op
.op1
;
2004 gfc_expr
*op1_right
= op1
->value
.op
.op2
;
2005 gfc_expr
*op2_right
= op2
->value
.op
.op2
;
2007 if (gfc_dep_compare_expr (op1_left
, op2_left
) == 0)
2009 /* Watch out for 'A ' // x vs. 'A' // x. */
2011 if (op1_left
->expr_type
== EXPR_CONSTANT
2012 && op2_left
->expr_type
== EXPR_CONSTANT
2013 && op1_left
->value
.character
.length
2014 != op2_left
->value
.character
.length
)
2022 firstarg
->expr
= op1_right
;
2023 secondarg
->expr
= op2_right
;
2027 e
->value
.op
.op1
= op1_right
;
2028 e
->value
.op
.op2
= op2_right
;
2030 optimize_comparison (e
, op
);
2034 if (gfc_dep_compare_expr (op1_right
, op2_right
) == 0)
2040 firstarg
->expr
= op1_left
;
2041 secondarg
->expr
= op2_left
;
2045 e
->value
.op
.op1
= op1_left
;
2046 e
->value
.op
.op2
= op2_left
;
2049 optimize_comparison (e
, op
);
2056 /* eq can only be -1, 0 or 1 at this point. */
2084 gfc_internal_error ("illegal OP in optimize_comparison");
2088 /* Replace the expression by a constant expression. The typespec
2089 and where remains the way it is. */
2092 e
->expr_type
= EXPR_CONSTANT
;
2093 e
->value
.logical
= result
;
2101 /* Optimize a trim function by replacing it with an equivalent substring
2102 involving a call to len_trim. This only works for expressions where
2103 variables are trimmed. Return true if anything was modified. */
2106 optimize_trim (gfc_expr
*e
)
2111 gfc_ref
**rr
= NULL
;
2113 /* Don't do this optimization within an argument list, because
2114 otherwise aliasing issues may occur. */
2116 if (count_arglist
!= 1)
2119 if (e
->ts
.type
!= BT_CHARACTER
|| e
->expr_type
!= EXPR_FUNCTION
2120 || e
->value
.function
.isym
== NULL
2121 || e
->value
.function
.isym
->id
!= GFC_ISYM_TRIM
)
2124 a
= e
->value
.function
.actual
->expr
;
2126 if (a
->expr_type
!= EXPR_VARIABLE
)
2129 /* This would pessimize the idiom a = trim(a) for reallocatable strings. */
2131 if (a
->symtree
->n
.sym
->attr
.allocatable
)
2134 /* Follow all references to find the correct place to put the newly
2135 created reference. FIXME: Also handle substring references and
2136 array references. Array references cause strange regressions at
2141 for (rr
= &(a
->ref
); *rr
; rr
= &((*rr
)->next
))
2143 if ((*rr
)->type
== REF_SUBSTRING
|| (*rr
)->type
== REF_ARRAY
)
2148 strip_function_call (e
);
2153 /* Create the reference. */
2155 ref
= gfc_get_ref ();
2156 ref
->type
= REF_SUBSTRING
;
2158 /* Set the start of the reference. */
2160 ref
->u
.ss
.start
= gfc_get_int_expr (gfc_default_integer_kind
, NULL
, 1);
2162 /* Build the function call to len_trim(x, gfc_default_integer_kind). */
2164 fcn
= get_len_trim_call (gfc_copy_expr (e
), gfc_default_integer_kind
);
2166 /* Set the end of the reference to the call to len_trim. */
2168 ref
->u
.ss
.end
= fcn
;
2169 gcc_assert (rr
!= NULL
&& *rr
== NULL
);
2174 /* Optimize minloc(b), where b is rank 1 array, into
2175 (/ minloc(b, dim=1) /), and similarly for maxloc,
2176 as the latter forms are expanded inline. */
2179 optimize_minmaxloc (gfc_expr
**e
)
2182 gfc_actual_arglist
*a
;
2186 || fn
->value
.function
.actual
== NULL
2187 || fn
->value
.function
.actual
->expr
== NULL
2188 || fn
->value
.function
.actual
->expr
->rank
!= 1)
2191 *e
= gfc_get_array_expr (fn
->ts
.type
, fn
->ts
.kind
, &fn
->where
);
2192 (*e
)->shape
= fn
->shape
;
2195 gfc_constructor_append_expr (&(*e
)->value
.constructor
, fn
, &fn
->where
);
2197 name
= XALLOCAVEC (char, strlen (fn
->value
.function
.name
) + 1);
2198 strcpy (name
, fn
->value
.function
.name
);
2199 p
= strstr (name
, "loc0");
2201 fn
->value
.function
.name
= gfc_get_string ("%s", name
);
2202 if (fn
->value
.function
.actual
->next
)
2204 a
= fn
->value
.function
.actual
->next
;
2205 gcc_assert (a
->expr
== NULL
);
2209 a
= gfc_get_actual_arglist ();
2210 fn
->value
.function
.actual
->next
= a
;
2212 a
->expr
= gfc_get_constant_expr (BT_INTEGER
, gfc_default_integer_kind
,
2214 mpz_set_ui (a
->expr
->value
.integer
, 1);
2217 /* Callback function for code checking that we do not pass a DO variable to an
2218 INTENT(OUT) or INTENT(INOUT) dummy variable. */
2221 doloop_code (gfc_code
**c
, int *walk_subtrees ATTRIBUTE_UNUSED
,
2222 void *data ATTRIBUTE_UNUSED
)
2226 gfc_formal_arglist
*f
;
2227 gfc_actual_arglist
*a
;
2232 /* If the doloop_list grew, we have to truncate it here. */
2234 if ((unsigned) doloop_level
< doloop_list
.length())
2235 doloop_list
.truncate (doloop_level
);
2241 if (co
->ext
.iterator
&& co
->ext
.iterator
->var
)
2242 doloop_list
.safe_push (co
);
2244 doloop_list
.safe_push ((gfc_code
*) NULL
);
2249 if (co
->resolved_sym
== NULL
)
2252 f
= gfc_sym_get_dummy_args (co
->resolved_sym
);
2254 /* Withot a formal arglist, there is only unknown INTENT,
2255 which we don't check for. */
2263 FOR_EACH_VEC_ELT (doloop_list
, i
, cl
)
2270 do_sym
= cl
->ext
.iterator
->var
->symtree
->n
.sym
;
2272 if (a
->expr
&& a
->expr
->symtree
2273 && a
->expr
->symtree
->n
.sym
== do_sym
)
2275 if (f
->sym
->attr
.intent
== INTENT_OUT
)
2276 gfc_error_now ("Variable %qs at %L set to undefined "
2277 "value inside loop beginning at %L as "
2278 "INTENT(OUT) argument to subroutine %qs",
2279 do_sym
->name
, &a
->expr
->where
,
2280 &doloop_list
[i
]->loc
,
2281 co
->symtree
->n
.sym
->name
);
2282 else if (f
->sym
->attr
.intent
== INTENT_INOUT
)
2283 gfc_error_now ("Variable %qs at %L not definable inside "
2284 "loop beginning at %L as INTENT(INOUT) "
2285 "argument to subroutine %qs",
2286 do_sym
->name
, &a
->expr
->where
,
2287 &doloop_list
[i
]->loc
,
2288 co
->symtree
->n
.sym
->name
);
2302 /* Callback function for functions checking that we do not pass a DO variable
2303 to an INTENT(OUT) or INTENT(INOUT) dummy variable. */
2306 do_function (gfc_expr
**e
, int *walk_subtrees ATTRIBUTE_UNUSED
,
2307 void *data ATTRIBUTE_UNUSED
)
2309 gfc_formal_arglist
*f
;
2310 gfc_actual_arglist
*a
;
2316 if (expr
->expr_type
!= EXPR_FUNCTION
)
2319 /* Intrinsic functions don't modify their arguments. */
2321 if (expr
->value
.function
.isym
)
2324 f
= gfc_sym_get_dummy_args (expr
->symtree
->n
.sym
);
2326 /* Without a formal arglist, there is only unknown INTENT,
2327 which we don't check for. */
2331 a
= expr
->value
.function
.actual
;
2335 FOR_EACH_VEC_ELT (doloop_list
, i
, dl
)
2342 do_sym
= dl
->ext
.iterator
->var
->symtree
->n
.sym
;
2344 if (a
->expr
&& a
->expr
->symtree
2345 && a
->expr
->symtree
->n
.sym
== do_sym
)
2347 if (f
->sym
->attr
.intent
== INTENT_OUT
)
2348 gfc_error_now ("Variable %qs at %L set to undefined value "
2349 "inside loop beginning at %L as INTENT(OUT) "
2350 "argument to function %qs", do_sym
->name
,
2351 &a
->expr
->where
, &doloop_list
[i
]->loc
,
2352 expr
->symtree
->n
.sym
->name
);
2353 else if (f
->sym
->attr
.intent
== INTENT_INOUT
)
2354 gfc_error_now ("Variable %qs at %L not definable inside loop"
2355 " beginning at %L as INTENT(INOUT) argument to"
2356 " function %qs", do_sym
->name
,
2357 &a
->expr
->where
, &doloop_list
[i
]->loc
,
2358 expr
->symtree
->n
.sym
->name
);
2369 doloop_warn (gfc_namespace
*ns
)
2371 gfc_code_walker (&ns
->code
, doloop_code
, do_function
, NULL
);
2374 /* This selction deals with inlining calls to MATMUL. */
2376 /* Replace calls to matmul outside of straight assignments with a temporary
2377 variable so that later inlining will work. */
2380 matmul_to_var_expr (gfc_expr
**ep
, int *walk_subtrees ATTRIBUTE_UNUSED
,
2384 bool *found
= (bool *) data
;
2388 if (e
->expr_type
!= EXPR_FUNCTION
2389 || e
->value
.function
.isym
== NULL
2390 || e
->value
.function
.isym
->id
!= GFC_ISYM_MATMUL
)
2393 if (forall_level
> 0 || iterator_level
> 0 || in_omp_workshare
2397 /* Check if this is already in the form c = matmul(a,b). */
2399 if ((*current_code
)->expr2
== e
)
2402 n
= create_var (e
, "matmul");
2404 /* If create_var is unable to create a variable (for example if
2405 -fno-realloc-lhs is in force with a variable that does not have bounds
2406 known at compile-time), just return. */
2416 /* Set current_code and associated variables so that matmul_to_var_expr can
2420 matmul_to_var_code (gfc_code
**c
, int *walk_subtrees ATTRIBUTE_UNUSED
,
2421 void *data ATTRIBUTE_UNUSED
)
2423 if (current_code
!= c
)
2426 inserted_block
= NULL
;
2427 changed_statement
= NULL
;
2434 /* Take a statement of the shape c = matmul(a,b) and create temporaries
2435 for a and b if there is a dependency between the arguments and the
2436 result variable or if a or b are the result of calculations that cannot
2437 be handled by the inliner. */
2440 matmul_temp_args (gfc_code
**c
, int *walk_subtrees ATTRIBUTE_UNUSED
,
2441 void *data ATTRIBUTE_UNUSED
)
2443 gfc_expr
*expr1
, *expr2
;
2445 gfc_actual_arglist
*a
, *b
;
2447 gfc_expr
*matrix_a
, *matrix_b
;
2448 bool conjg_a
, conjg_b
, transpose_a
, transpose_b
;
2452 if (co
->op
!= EXEC_ASSIGN
)
2455 if (forall_level
> 0 || iterator_level
> 0 || in_omp_workshare
2459 /* This has some duplication with inline_matmul_assign. This
2460 is because the creation of temporary variables could still fail,
2461 and inline_matmul_assign still needs to be able to handle these
2466 if (expr2
->expr_type
!= EXPR_FUNCTION
2467 || expr2
->value
.function
.isym
== NULL
2468 || expr2
->value
.function
.isym
->id
!= GFC_ISYM_MATMUL
)
2472 a
= expr2
->value
.function
.actual
;
2473 matrix_a
= check_conjg_transpose_variable (a
->expr
, &conjg_a
, &transpose_a
);
2474 if (matrix_a
!= NULL
)
2476 if (matrix_a
->expr_type
== EXPR_VARIABLE
2477 && (gfc_check_dependency (matrix_a
, expr1
, true)
2478 || has_dimen_vector_ref (matrix_a
)))
2486 matrix_b
= check_conjg_transpose_variable (b
->expr
, &conjg_b
, &transpose_b
);
2487 if (matrix_b
!= NULL
)
2489 if (matrix_b
->expr_type
== EXPR_VARIABLE
2490 && (gfc_check_dependency (matrix_b
, expr1
, true)
2491 || has_dimen_vector_ref (matrix_b
)))
2497 if (!a_tmp
&& !b_tmp
)
2501 inserted_block
= NULL
;
2502 changed_statement
= NULL
;
2506 at
= create_var (a
->expr
,"mma");
2513 bt
= create_var (b
->expr
,"mmb");
2520 /* Auxiliary function to build and simplify an array inquiry function.
2521 dim is zero-based. */
2524 get_array_inq_function (gfc_isym_id id
, gfc_expr
*e
, int dim
)
2527 gfc_expr
*dim_arg
, *kind
;
2533 case GFC_ISYM_LBOUND
:
2534 name
= "_gfortran_lbound";
2537 case GFC_ISYM_UBOUND
:
2538 name
= "_gfortran_ubound";
2542 name
= "_gfortran_size";
2549 dim_arg
= gfc_get_int_expr (gfc_default_integer_kind
, &e
->where
, dim
);
2550 kind
= gfc_get_int_expr (gfc_default_integer_kind
, &e
->where
,
2551 gfc_index_integer_kind
);
2553 ec
= gfc_copy_expr (e
);
2554 fcn
= gfc_build_intrinsic_call (current_ns
, id
, name
, e
->where
, 3,
2556 gfc_simplify_expr (fcn
, 0);
2560 /* Builds a logical expression. */
2563 build_logical_expr (gfc_intrinsic_op op
, gfc_expr
*e1
, gfc_expr
*e2
)
2568 ts
.type
= BT_LOGICAL
;
2569 ts
.kind
= gfc_default_logical_kind
;
2570 res
= gfc_get_expr ();
2571 res
->where
= e1
->where
;
2572 res
->expr_type
= EXPR_OP
;
2573 res
->value
.op
.op
= op
;
2574 res
->value
.op
.op1
= e1
;
2575 res
->value
.op
.op2
= e2
;
2582 /* Return an operation of one two gfc_expr (one if e2 is NULL). This assumes
2583 compatible typespecs. */
2586 get_operand (gfc_intrinsic_op op
, gfc_expr
*e1
, gfc_expr
*e2
)
2590 res
= gfc_get_expr ();
2592 res
->where
= e1
->where
;
2593 res
->expr_type
= EXPR_OP
;
2594 res
->value
.op
.op
= op
;
2595 res
->value
.op
.op1
= e1
;
2596 res
->value
.op
.op2
= e2
;
2597 gfc_simplify_expr (res
, 0);
2601 /* Generate the IF statement for a runtime check if we want to do inlining or
2602 not - putting in the code for both branches and putting it into the syntax
2603 tree is the caller's responsibility. For fixed array sizes, this should be
2604 removed by DCE. Only called for rank-two matrices A and B. */
2607 inline_limit_check (gfc_expr
*a
, gfc_expr
*b
, enum matrix_case m_case
)
2609 gfc_expr
*inline_limit
;
2610 gfc_code
*if_1
, *if_2
, *else_2
;
2611 gfc_expr
*b2
, *a2
, *a1
, *m1
, *m2
;
2615 gcc_assert (m_case
== A2B2
|| m_case
== A2B2T
|| m_case
== A2TB2
);
2617 /* Calculation is done in real to avoid integer overflow. */
2619 inline_limit
= gfc_get_constant_expr (BT_REAL
, gfc_default_real_kind
,
2621 mpfr_set_si (inline_limit
->value
.real
, flag_inline_matmul_limit
,
2623 mpfr_pow_ui (inline_limit
->value
.real
, inline_limit
->value
.real
, 3,
2626 a1
= get_array_inq_function (GFC_ISYM_SIZE
, a
, 1);
2627 a2
= get_array_inq_function (GFC_ISYM_SIZE
, a
, 2);
2628 b2
= get_array_inq_function (GFC_ISYM_SIZE
, b
, 2);
2632 ts
.kind
= gfc_default_real_kind
;
2633 gfc_convert_type_warn (a1
, &ts
, 2, 0);
2634 gfc_convert_type_warn (a2
, &ts
, 2, 0);
2635 gfc_convert_type_warn (b2
, &ts
, 2, 0);
2637 m1
= get_operand (INTRINSIC_TIMES
, a1
, a2
);
2638 m2
= get_operand (INTRINSIC_TIMES
, m1
, b2
);
2640 cond
= build_logical_expr (INTRINSIC_LE
, m2
, inline_limit
);
2641 gfc_simplify_expr (cond
, 0);
2643 else_2
= XCNEW (gfc_code
);
2644 else_2
->op
= EXEC_IF
;
2645 else_2
->loc
= a
->where
;
2647 if_2
= XCNEW (gfc_code
);
2650 if_2
->loc
= a
->where
;
2651 if_2
->block
= else_2
;
2653 if_1
= XCNEW (gfc_code
);
2656 if_1
->loc
= a
->where
;
2662 /* Insert code to issue a runtime error if the expressions are not equal. */
2665 runtime_error_ne (gfc_expr
*e1
, gfc_expr
*e2
, const char *msg
)
2668 gfc_code
*if_1
, *if_2
;
2670 gfc_actual_arglist
*a1
, *a2
, *a3
;
2672 gcc_assert (e1
->where
.lb
);
2673 /* Build the call to runtime_error. */
2674 c
= XCNEW (gfc_code
);
2678 /* Get a null-terminated message string. */
2680 a1
= gfc_get_actual_arglist ();
2681 a1
->expr
= gfc_get_character_expr (gfc_default_character_kind
, &e1
->where
,
2682 msg
, strlen(msg
)+1);
2685 /* Pass the value of the first expression. */
2686 a2
= gfc_get_actual_arglist ();
2687 a2
->expr
= gfc_copy_expr (e1
);
2690 /* Pass the value of the second expression. */
2691 a3
= gfc_get_actual_arglist ();
2692 a3
->expr
= gfc_copy_expr (e2
);
2695 gfc_check_fe_runtime_error (c
->ext
.actual
);
2696 gfc_resolve_fe_runtime_error (c
);
2698 if_2
= XCNEW (gfc_code
);
2700 if_2
->loc
= e1
->where
;
2703 if_1
= XCNEW (gfc_code
);
2706 if_1
->loc
= e1
->where
;
2708 cond
= build_logical_expr (INTRINSIC_NE
, e1
, e2
);
2709 gfc_simplify_expr (cond
, 0);
2715 /* Handle matrix reallocation. Caller is responsible to insert into
2718 For the two-dimensional case, build
2720 if (allocated(c)) then
2721 if (size(c,1) /= size(a,1) .or. size(c,2) /= size(b,2)) then
2723 allocate (c(size(a,1), size(b,2)))
2726 allocate (c(size(a,1),size(b,2)))
2729 and for the other cases correspondingly.
2733 matmul_lhs_realloc (gfc_expr
*c
, gfc_expr
*a
, gfc_expr
*b
,
2734 enum matrix_case m_case
)
2737 gfc_expr
*allocated
, *alloc_expr
;
2738 gfc_code
*if_alloc_1
, *if_alloc_2
, *if_size_1
, *if_size_2
;
2739 gfc_code
*else_alloc
;
2740 gfc_code
*deallocate
, *allocate1
, *allocate_else
;
2742 gfc_expr
*cond
, *ne1
, *ne2
;
2744 if (warn_realloc_lhs
)
2745 gfc_warning (OPT_Wrealloc_lhs
,
2746 "Code for reallocating the allocatable array at %L will "
2747 "be added", &c
->where
);
2749 alloc_expr
= gfc_copy_expr (c
);
2751 ar
= gfc_find_array_ref (alloc_expr
);
2752 gcc_assert (ar
&& ar
->type
== AR_FULL
);
2754 /* c comes in as a full ref. Change it into a copy and make it into an
2755 element ref so it has the right form for for ALLOCATE. In the same
2756 switch statement, also generate the size comparison for the secod IF
2759 ar
->type
= AR_ELEMENT
;
2764 ar
->start
[0] = get_array_inq_function (GFC_ISYM_SIZE
, a
, 1);
2765 ar
->start
[1] = get_array_inq_function (GFC_ISYM_SIZE
, b
, 2);
2766 ne1
= build_logical_expr (INTRINSIC_NE
,
2767 get_array_inq_function (GFC_ISYM_SIZE
, c
, 1),
2768 get_array_inq_function (GFC_ISYM_SIZE
, a
, 1));
2769 ne2
= build_logical_expr (INTRINSIC_NE
,
2770 get_array_inq_function (GFC_ISYM_SIZE
, c
, 2),
2771 get_array_inq_function (GFC_ISYM_SIZE
, b
, 2));
2772 cond
= build_logical_expr (INTRINSIC_OR
, ne1
, ne2
);
2776 ar
->start
[0] = get_array_inq_function (GFC_ISYM_SIZE
, a
, 1);
2777 ar
->start
[1] = get_array_inq_function (GFC_ISYM_SIZE
, b
, 1);
2779 ne1
= build_logical_expr (INTRINSIC_NE
,
2780 get_array_inq_function (GFC_ISYM_SIZE
, c
, 1),
2781 get_array_inq_function (GFC_ISYM_SIZE
, a
, 1));
2782 ne2
= build_logical_expr (INTRINSIC_NE
,
2783 get_array_inq_function (GFC_ISYM_SIZE
, c
, 2),
2784 get_array_inq_function (GFC_ISYM_SIZE
, b
, 1));
2785 cond
= build_logical_expr (INTRINSIC_OR
, ne1
, ne2
);
2790 ar
->start
[0] = get_array_inq_function (GFC_ISYM_SIZE
, a
, 2);
2791 ar
->start
[1] = get_array_inq_function (GFC_ISYM_SIZE
, b
, 2);
2793 ne1
= build_logical_expr (INTRINSIC_NE
,
2794 get_array_inq_function (GFC_ISYM_SIZE
, c
, 1),
2795 get_array_inq_function (GFC_ISYM_SIZE
, a
, 2));
2796 ne2
= build_logical_expr (INTRINSIC_NE
,
2797 get_array_inq_function (GFC_ISYM_SIZE
, c
, 2),
2798 get_array_inq_function (GFC_ISYM_SIZE
, b
, 2));
2799 cond
= build_logical_expr (INTRINSIC_OR
, ne1
, ne2
);
2803 ar
->start
[0] = get_array_inq_function (GFC_ISYM_SIZE
, a
, 1);
2804 cond
= build_logical_expr (INTRINSIC_NE
,
2805 get_array_inq_function (GFC_ISYM_SIZE
, c
, 1),
2806 get_array_inq_function (GFC_ISYM_SIZE
, a
, 2));
2810 ar
->start
[0] = get_array_inq_function (GFC_ISYM_SIZE
, b
, 2);
2811 cond
= build_logical_expr (INTRINSIC_NE
,
2812 get_array_inq_function (GFC_ISYM_SIZE
, c
, 1),
2813 get_array_inq_function (GFC_ISYM_SIZE
, b
, 2));
2821 gfc_simplify_expr (cond
, 0);
2823 /* We need two identical allocate statements in two
2824 branches of the IF statement. */
2826 allocate1
= XCNEW (gfc_code
);
2827 allocate1
->op
= EXEC_ALLOCATE
;
2828 allocate1
->ext
.alloc
.list
= gfc_get_alloc ();
2829 allocate1
->loc
= c
->where
;
2830 allocate1
->ext
.alloc
.list
->expr
= gfc_copy_expr (alloc_expr
);
2832 allocate_else
= XCNEW (gfc_code
);
2833 allocate_else
->op
= EXEC_ALLOCATE
;
2834 allocate_else
->ext
.alloc
.list
= gfc_get_alloc ();
2835 allocate_else
->loc
= c
->where
;
2836 allocate_else
->ext
.alloc
.list
->expr
= alloc_expr
;
2838 allocated
= gfc_build_intrinsic_call (current_ns
, GFC_ISYM_ALLOCATED
,
2839 "_gfortran_allocated", c
->where
,
2840 1, gfc_copy_expr (c
));
2842 deallocate
= XCNEW (gfc_code
);
2843 deallocate
->op
= EXEC_DEALLOCATE
;
2844 deallocate
->ext
.alloc
.list
= gfc_get_alloc ();
2845 deallocate
->ext
.alloc
.list
->expr
= gfc_copy_expr (c
);
2846 deallocate
->next
= allocate1
;
2847 deallocate
->loc
= c
->where
;
2849 if_size_2
= XCNEW (gfc_code
);
2850 if_size_2
->op
= EXEC_IF
;
2851 if_size_2
->expr1
= cond
;
2852 if_size_2
->loc
= c
->where
;
2853 if_size_2
->next
= deallocate
;
2855 if_size_1
= XCNEW (gfc_code
);
2856 if_size_1
->op
= EXEC_IF
;
2857 if_size_1
->block
= if_size_2
;
2858 if_size_1
->loc
= c
->where
;
2860 else_alloc
= XCNEW (gfc_code
);
2861 else_alloc
->op
= EXEC_IF
;
2862 else_alloc
->loc
= c
->where
;
2863 else_alloc
->next
= allocate_else
;
2865 if_alloc_2
= XCNEW (gfc_code
);
2866 if_alloc_2
->op
= EXEC_IF
;
2867 if_alloc_2
->expr1
= allocated
;
2868 if_alloc_2
->loc
= c
->where
;
2869 if_alloc_2
->next
= if_size_1
;
2870 if_alloc_2
->block
= else_alloc
;
2872 if_alloc_1
= XCNEW (gfc_code
);
2873 if_alloc_1
->op
= EXEC_IF
;
2874 if_alloc_1
->block
= if_alloc_2
;
2875 if_alloc_1
->loc
= c
->where
;
2880 /* Callback function for has_function_or_op. */
2883 is_function_or_op (gfc_expr
**e
, int *walk_subtrees ATTRIBUTE_UNUSED
,
2884 void *data ATTRIBUTE_UNUSED
)
2889 return (*e
)->expr_type
== EXPR_FUNCTION
2890 || (*e
)->expr_type
== EXPR_OP
;
2893 /* Returns true if the expression contains a function. */
2896 has_function_or_op (gfc_expr
**e
)
2901 return gfc_expr_walker (e
, is_function_or_op
, NULL
);
2904 /* Freeze (assign to a temporary variable) a single expression. */
2907 freeze_expr (gfc_expr
**ep
)
2910 if (has_function_or_op (ep
))
2912 ne
= create_var (*ep
, "freeze");
2917 /* Go through an expression's references and assign them to temporary
2918 variables if they contain functions. This is usually done prior to
2919 front-end scalarization to avoid multiple invocations of functions. */
2922 freeze_references (gfc_expr
*e
)
2928 for (r
=e
->ref
; r
; r
=r
->next
)
2930 if (r
->type
== REF_SUBSTRING
)
2932 if (r
->u
.ss
.start
!= NULL
)
2933 freeze_expr (&r
->u
.ss
.start
);
2935 if (r
->u
.ss
.end
!= NULL
)
2936 freeze_expr (&r
->u
.ss
.end
);
2938 else if (r
->type
== REF_ARRAY
)
2947 for (i
=0; i
<ar
->dimen
; i
++)
2949 if (ar
->dimen_type
[i
] == DIMEN_RANGE
)
2951 freeze_expr (&ar
->start
[i
]);
2952 freeze_expr (&ar
->end
[i
]);
2953 freeze_expr (&ar
->stride
[i
]);
2955 else if (ar
->dimen_type
[i
] == DIMEN_ELEMENT
)
2957 freeze_expr (&ar
->start
[i
]);
2963 for (i
=0; i
<ar
->dimen
; i
++)
2964 freeze_expr (&ar
->start
[i
]);
2974 /* Convert to gfc_index_integer_kind if needed, just do a copy otherwise. */
2977 convert_to_index_kind (gfc_expr
*e
)
2981 gcc_assert (e
!= NULL
);
2983 res
= gfc_copy_expr (e
);
2985 gcc_assert (e
->ts
.type
== BT_INTEGER
);
2987 if (res
->ts
.kind
!= gfc_index_integer_kind
)
2991 ts
.type
= BT_INTEGER
;
2992 ts
.kind
= gfc_index_integer_kind
;
2994 gfc_convert_type_warn (e
, &ts
, 2, 0);
3000 /* Function to create a DO loop including creation of the
3001 iteration variable. gfc_expr are copied.*/
3004 create_do_loop (gfc_expr
*start
, gfc_expr
*end
, gfc_expr
*step
, locus
*where
,
3005 gfc_namespace
*ns
, char *vname
)
3008 char name
[GFC_MAX_SYMBOL_LEN
+1];
3009 gfc_symtree
*symtree
;
3014 /* Create an expression for the iteration variable. */
3016 sprintf (name
, "__var_%d_do_%s", var_num
++, vname
);
3018 sprintf (name
, "__var_%d_do", var_num
++);
3021 if (gfc_get_sym_tree (name
, ns
, &symtree
, false) != 0)
3024 /* Create the loop variable. */
3026 symbol
= symtree
->n
.sym
;
3027 symbol
->ts
.type
= BT_INTEGER
;
3028 symbol
->ts
.kind
= gfc_index_integer_kind
;
3029 symbol
->attr
.flavor
= FL_VARIABLE
;
3030 symbol
->attr
.referenced
= 1;
3031 symbol
->attr
.dimension
= 0;
3032 symbol
->attr
.fe_temp
= 1;
3033 gfc_commit_symbol (symbol
);
3035 i
= gfc_get_expr ();
3036 i
->expr_type
= EXPR_VARIABLE
;
3040 i
->symtree
= symtree
;
3042 /* ... and the nested DO statements. */
3043 n
= XCNEW (gfc_code
);
3046 n
->ext
.iterator
= gfc_get_iterator ();
3047 n
->ext
.iterator
->var
= i
;
3048 n
->ext
.iterator
->start
= convert_to_index_kind (start
);
3049 n
->ext
.iterator
->end
= convert_to_index_kind (end
);
3051 n
->ext
.iterator
->step
= convert_to_index_kind (step
);
3053 n
->ext
.iterator
->step
= gfc_get_int_expr (gfc_index_integer_kind
,
3056 n2
= XCNEW (gfc_code
);
3064 /* Get the upper bound of the DO loops for matmul along a dimension. This
3068 get_size_m1 (gfc_expr
*e
, int dimen
)
3073 if (gfc_array_dimen_size (e
, dimen
- 1, &size
))
3075 res
= gfc_get_constant_expr (BT_INTEGER
,
3076 gfc_index_integer_kind
, &e
->where
);
3077 mpz_sub_ui (res
->value
.integer
, size
, 1);
3082 res
= get_operand (INTRINSIC_MINUS
,
3083 get_array_inq_function (GFC_ISYM_SIZE
, e
, dimen
),
3084 gfc_get_int_expr (gfc_index_integer_kind
,
3086 gfc_simplify_expr (res
, 0);
3092 /* Function to return a scalarized expression. It is assumed that indices are
3093 zero based to make generation of DO loops easier. A zero as index will
3094 access the first element along a dimension. Single element references will
3095 be skipped. A NULL as an expression will be replaced by a full reference.
3096 This assumes that the index loops have gfc_index_integer_kind, and that all
3097 references have been frozen. */
3100 scalarized_expr (gfc_expr
*e_in
, gfc_expr
**index
, int count_index
)
3109 e
= gfc_copy_expr(e_in
);
3113 ar
= gfc_find_array_ref (e
);
3115 /* We scalarize count_index variables, reducing the rank by count_index. */
3117 e
->rank
= rank
- count_index
;
3119 was_fullref
= ar
->type
== AR_FULL
;
3122 ar
->type
= AR_ELEMENT
;
3124 ar
->type
= AR_SECTION
;
3126 /* Loop over the indices. For each index, create the expression
3127 index * stride + lbound(e, dim). */
3130 for (i
=0; i
< ar
->dimen
; i
++)
3132 if (was_fullref
|| ar
->dimen_type
[i
] == DIMEN_RANGE
)
3134 if (index
[i_index
] != NULL
)
3136 gfc_expr
*lbound
, *nindex
;
3139 loopvar
= gfc_copy_expr (index
[i_index
]);
3145 tmp
= gfc_copy_expr(ar
->stride
[i
]);
3146 if (tmp
->ts
.kind
!= gfc_index_integer_kind
)
3150 ts
.type
= BT_INTEGER
;
3151 ts
.kind
= gfc_index_integer_kind
;
3152 gfc_convert_type (tmp
, &ts
, 2);
3154 nindex
= get_operand (INTRINSIC_TIMES
, loopvar
, tmp
);
3159 /* Calculate the lower bound of the expression. */
3162 lbound
= gfc_copy_expr (ar
->start
[i
]);
3163 if (lbound
->ts
.kind
!= gfc_index_integer_kind
)
3167 ts
.type
= BT_INTEGER
;
3168 ts
.kind
= gfc_index_integer_kind
;
3169 gfc_convert_type (lbound
, &ts
, 2);
3178 lbound_e
= gfc_copy_expr (e_in
);
3180 for (ref
= lbound_e
->ref
; ref
; ref
= ref
->next
)
3181 if (ref
->type
== REF_ARRAY
3182 && (ref
->u
.ar
.type
== AR_FULL
3183 || ref
->u
.ar
.type
== AR_SECTION
))
3188 gfc_free_ref_list (ref
->next
);
3194 /* Look at full individual sections, like a(:). The first index
3195 is the lbound of a full ref. */
3201 for (j
= 0; j
< ar
->dimen
; j
++)
3203 gfc_free_expr (ar
->start
[j
]);
3204 ar
->start
[j
] = NULL
;
3205 gfc_free_expr (ar
->end
[j
]);
3207 gfc_free_expr (ar
->stride
[j
]);
3208 ar
->stride
[j
] = NULL
;
3211 /* We have to get rid of the shape, if there is one. Do
3212 so by freeing it and calling gfc_resolve to rebuild
3213 it, if necessary. */
3215 if (lbound_e
->shape
)
3216 gfc_free_shape (&(lbound_e
->shape
), lbound_e
->rank
);
3218 lbound_e
->rank
= ar
->dimen
;
3219 gfc_resolve_expr (lbound_e
);
3221 lbound
= get_array_inq_function (GFC_ISYM_LBOUND
, lbound_e
,
3223 gfc_free_expr (lbound_e
);
3226 ar
->dimen_type
[i
] = DIMEN_ELEMENT
;
3228 gfc_free_expr (ar
->start
[i
]);
3229 ar
->start
[i
] = get_operand (INTRINSIC_PLUS
, nindex
, lbound
);
3231 gfc_free_expr (ar
->end
[i
]);
3233 gfc_free_expr (ar
->stride
[i
]);
3234 ar
->stride
[i
] = NULL
;
3235 gfc_simplify_expr (ar
->start
[i
], 0);
3237 else if (was_fullref
)
3239 gfc_internal_error ("Scalarization using DIMEN_RANGE unimplemented");
3248 /* Helper function to check for a dimen vector as subscript. */
3251 has_dimen_vector_ref (gfc_expr
*e
)
3256 ar
= gfc_find_array_ref (e
);
3258 if (ar
->type
== AR_FULL
)
3261 for (i
=0; i
<ar
->dimen
; i
++)
3262 if (ar
->dimen_type
[i
] == DIMEN_VECTOR
)
3268 /* If handed an expression of the form
3272 check if A can be handled by matmul and return if there is an uneven number
3273 of CONJG calls. Return a pointer to the array when everything is OK, NULL
3274 otherwise. The caller has to check for the correct rank. */
3277 check_conjg_transpose_variable (gfc_expr
*e
, bool *conjg
, bool *transpose
)
3284 if (e
->expr_type
== EXPR_VARIABLE
)
3286 gcc_assert (e
->rank
== 1 || e
->rank
== 2);
3289 else if (e
->expr_type
== EXPR_FUNCTION
)
3291 if (e
->value
.function
.isym
== NULL
)
3294 if (e
->value
.function
.isym
->id
== GFC_ISYM_CONJG
)
3296 else if (e
->value
.function
.isym
->id
== GFC_ISYM_TRANSPOSE
)
3297 *transpose
= !*transpose
;
3303 e
= e
->value
.function
.actual
->expr
;
3310 /* Inline assignments of the form c = matmul(a,b).
3311 Handle only the cases currently where b and c are rank-two arrays.
3313 This basically translates the code to
3319 do k=0, size(a, 2)-1
3320 do i=0, size(a, 1)-1
3321 c(i * stride(c,1) + lbound(c,1), j * stride(c,2) + lbound(c,2)) =
3322 c(i * stride(c,1) + lbound(c,1), j * stride(c,2) + lbound(c,2)) +
3323 a(i * stride(a,1) + lbound(a,1), k * stride(a,2) + lbound(a,2)) *
3324 b(k * stride(b,1) + lbound(b,1), j * stride(b,2) + lbound(b,2))
3333 inline_matmul_assign (gfc_code
**c
, int *walk_subtrees
,
3334 void *data ATTRIBUTE_UNUSED
)
3337 gfc_expr
*expr1
, *expr2
;
3338 gfc_expr
*matrix_a
, *matrix_b
;
3339 gfc_actual_arglist
*a
, *b
;
3340 gfc_code
*do_1
, *do_2
, *do_3
, *assign_zero
, *assign_matmul
;
3342 gfc_expr
*u1
, *u2
, *u3
;
3344 gfc_expr
*ascalar
, *bscalar
, *cscalar
;
3346 gfc_expr
*var_1
, *var_2
, *var_3
;
3349 gfc_intrinsic_op op_times
, op_plus
;
3350 enum matrix_case m_case
;
3352 gfc_code
*if_limit
= NULL
;
3353 gfc_code
**next_code_point
;
3354 bool conjg_a
, conjg_b
, transpose_a
, transpose_b
;
3356 if (co
->op
!= EXEC_ASSIGN
)
3362 /* The BLOCKS generated for the temporary variables and FORALL don't
3364 if (forall_level
> 0)
3367 /* For now don't do anything in OpenMP workshare, it confuses
3368 its translation, which expects only the allowed statements in there.
3369 We should figure out how to parallelize this eventually. */
3370 if (in_omp_workshare
)
3375 if (expr2
->expr_type
!= EXPR_FUNCTION
3376 || expr2
->value
.function
.isym
== NULL
3377 || expr2
->value
.function
.isym
->id
!= GFC_ISYM_MATMUL
)
3381 inserted_block
= NULL
;
3382 changed_statement
= NULL
;
3384 a
= expr2
->value
.function
.actual
;
3385 matrix_a
= check_conjg_transpose_variable (a
->expr
, &conjg_a
, &transpose_a
);
3386 if (matrix_a
== NULL
)
3390 matrix_b
= check_conjg_transpose_variable (b
->expr
, &conjg_b
, &transpose_b
);
3391 if (matrix_b
== NULL
)
3394 if (has_dimen_vector_ref (expr1
) || has_dimen_vector_ref (matrix_a
)
3395 || has_dimen_vector_ref (matrix_b
))
3398 /* We do not handle data dependencies yet. */
3399 if (gfc_check_dependency (expr1
, matrix_a
, true)
3400 || gfc_check_dependency (expr1
, matrix_b
, true))
3404 if (matrix_a
->rank
== 2)
3408 if (matrix_b
->rank
== 2 && !transpose_b
)
3413 if (matrix_b
->rank
== 1)
3415 else /* matrix_b->rank == 2 */
3424 else /* matrix_a->rank == 1 */
3426 if (matrix_b
->rank
== 2)
3436 ns
= insert_block ();
3438 /* Assign the type of the zero expression for initializing the resulting
3439 array, and the expression (+ and * for real, integer and complex;
3440 .and. and .or for logical. */
3442 switch(expr1
->ts
.type
)
3445 zero_e
= gfc_get_int_expr (expr1
->ts
.kind
, &expr1
->where
, 0);
3446 op_times
= INTRINSIC_TIMES
;
3447 op_plus
= INTRINSIC_PLUS
;
3451 op_times
= INTRINSIC_AND
;
3452 op_plus
= INTRINSIC_OR
;
3453 zero_e
= gfc_get_logical_expr (expr1
->ts
.kind
, &expr1
->where
,
3457 zero_e
= gfc_get_constant_expr (BT_REAL
, expr1
->ts
.kind
,
3459 mpfr_set_si (zero_e
->value
.real
, 0, GFC_RND_MODE
);
3460 op_times
= INTRINSIC_TIMES
;
3461 op_plus
= INTRINSIC_PLUS
;
3465 zero_e
= gfc_get_constant_expr (BT_COMPLEX
, expr1
->ts
.kind
,
3467 mpc_set_si_si (zero_e
->value
.complex, 0, 0, GFC_RND_MODE
);
3468 op_times
= INTRINSIC_TIMES
;
3469 op_plus
= INTRINSIC_PLUS
;
3477 current_code
= &ns
->code
;
3479 /* Freeze the references, keeping track of how many temporary variables were
3482 freeze_references (matrix_a
);
3483 freeze_references (matrix_b
);
3484 freeze_references (expr1
);
3487 next_code_point
= current_code
;
3490 next_code_point
= &ns
->code
;
3491 for (i
=0; i
<n_vars
; i
++)
3492 next_code_point
= &(*next_code_point
)->next
;
3495 /* Take care of the inline flag. If the limit check evaluates to a
3496 constant, dead code elimination will eliminate the unneeded branch. */
3498 if (m_case
== A2B2
&& flag_inline_matmul_limit
> 0)
3500 if_limit
= inline_limit_check (matrix_a
, matrix_b
, m_case
);
3502 /* Insert the original statement into the else branch. */
3503 if_limit
->block
->block
->next
= co
;
3506 /* ... and the new ones go into the original one. */
3507 *next_code_point
= if_limit
;
3508 next_code_point
= &if_limit
->block
->next
;
3511 assign_zero
= XCNEW (gfc_code
);
3512 assign_zero
->op
= EXEC_ASSIGN
;
3513 assign_zero
->loc
= co
->loc
;
3514 assign_zero
->expr1
= gfc_copy_expr (expr1
);
3515 assign_zero
->expr2
= zero_e
;
3517 /* Handle the reallocation, if needed. */
3518 if (flag_realloc_lhs
&& gfc_is_reallocatable_lhs (expr1
))
3520 gfc_code
*lhs_alloc
;
3522 /* Only need to check a single dimension for the A2B2 case for
3523 bounds checking, the rest will be allocated. Also check this
3526 if ((gfc_option
.rtcheck
& GFC_RTCHECK_BOUNDS
) && (m_case
== A2B2
|| m_case
== A2B1
))
3531 a2
= get_array_inq_function (GFC_ISYM_SIZE
, matrix_a
, 2);
3532 b1
= get_array_inq_function (GFC_ISYM_SIZE
, matrix_b
, 1);
3533 test
= runtime_error_ne (b1
, a2
, "Dimension of array B incorrect "
3534 "in MATMUL intrinsic: Is %ld, should be %ld");
3535 *next_code_point
= test
;
3536 next_code_point
= &test
->next
;
3540 lhs_alloc
= matmul_lhs_realloc (expr1
, matrix_a
, matrix_b
, m_case
);
3542 *next_code_point
= lhs_alloc
;
3543 next_code_point
= &lhs_alloc
->next
;
3546 else if (gfc_option
.rtcheck
& GFC_RTCHECK_BOUNDS
)
3549 gfc_expr
*a2
, *b1
, *c1
, *c2
, *a1
, *b2
;
3551 if (m_case
== A2B2
|| m_case
== A2B1
)
3553 a2
= get_array_inq_function (GFC_ISYM_SIZE
, matrix_a
, 2);
3554 b1
= get_array_inq_function (GFC_ISYM_SIZE
, matrix_b
, 1);
3555 test
= runtime_error_ne (b1
, a2
, "Dimension of array B incorrect "
3556 "in MATMUL intrinsic: Is %ld, should be %ld");
3557 *next_code_point
= test
;
3558 next_code_point
= &test
->next
;
3560 c1
= get_array_inq_function (GFC_ISYM_SIZE
, expr1
, 1);
3561 a1
= get_array_inq_function (GFC_ISYM_SIZE
, matrix_a
, 1);
3564 test
= runtime_error_ne (c1
, a1
, "Incorrect extent in return array in "
3565 "MATMUL intrinsic for dimension 1: "
3566 "is %ld, should be %ld");
3567 else if (m_case
== A2B1
)
3568 test
= runtime_error_ne (c1
, a1
, "Incorrect extent in return array in "
3569 "MATMUL intrinsic: "
3570 "is %ld, should be %ld");
3573 *next_code_point
= test
;
3574 next_code_point
= &test
->next
;
3576 else if (m_case
== A1B2
)
3578 a1
= get_array_inq_function (GFC_ISYM_SIZE
, matrix_a
, 1);
3579 b1
= get_array_inq_function (GFC_ISYM_SIZE
, matrix_b
, 1);
3580 test
= runtime_error_ne (b1
, a1
, "Dimension of array B incorrect "
3581 "in MATMUL intrinsic: Is %ld, should be %ld");
3582 *next_code_point
= test
;
3583 next_code_point
= &test
->next
;
3585 c1
= get_array_inq_function (GFC_ISYM_SIZE
, expr1
, 1);
3586 b2
= get_array_inq_function (GFC_ISYM_SIZE
, matrix_b
, 2);
3588 test
= runtime_error_ne (c1
, b2
, "Incorrect extent in return array in "
3589 "MATMUL intrinsic: "
3590 "is %ld, should be %ld");
3592 *next_code_point
= test
;
3593 next_code_point
= &test
->next
;
3598 c2
= get_array_inq_function (GFC_ISYM_SIZE
, expr1
, 2);
3599 b2
= get_array_inq_function (GFC_ISYM_SIZE
, matrix_b
, 2);
3600 test
= runtime_error_ne (c2
, b2
, "Incorrect extent in return array in "
3601 "MATMUL intrinsic for dimension 2: is %ld, should be %ld");
3603 *next_code_point
= test
;
3604 next_code_point
= &test
->next
;
3607 if (m_case
== A2B2T
)
3609 c1
= get_array_inq_function (GFC_ISYM_SIZE
, expr1
, 1);
3610 a1
= get_array_inq_function (GFC_ISYM_SIZE
, matrix_a
, 1);
3611 test
= runtime_error_ne (c1
, a1
, "Incorrect extent in return array in "
3612 "MATMUL intrinsic for dimension 1: "
3613 "is %ld, should be %ld");
3615 *next_code_point
= test
;
3616 next_code_point
= &test
->next
;
3618 c2
= get_array_inq_function (GFC_ISYM_SIZE
, expr1
, 2);
3619 b1
= get_array_inq_function (GFC_ISYM_SIZE
, matrix_b
, 1);
3620 test
= runtime_error_ne (c2
, b1
, "Incorrect extent in return array in "
3621 "MATMUL intrinsic for dimension 2: "
3622 "is %ld, should be %ld");
3623 *next_code_point
= test
;
3624 next_code_point
= &test
->next
;
3626 a2
= get_array_inq_function (GFC_ISYM_SIZE
, matrix_a
, 2);
3627 b2
= get_array_inq_function (GFC_ISYM_SIZE
, matrix_b
, 2);
3629 test
= runtime_error_ne (b2
, a2
, "Incorrect extent in argument B in "
3630 "MATMUL intrnisic for dimension 2: "
3631 "is %ld, should be %ld");
3632 *next_code_point
= test
;
3633 next_code_point
= &test
->next
;
3637 if (m_case
== A2TB2
)
3639 c1
= get_array_inq_function (GFC_ISYM_SIZE
, expr1
, 1);
3640 a2
= get_array_inq_function (GFC_ISYM_SIZE
, matrix_a
, 2);
3642 test
= runtime_error_ne (c1
, a2
, "Incorrect extent in return array in "
3643 "MATMUL intrinsic for dimension 1: "
3644 "is %ld, should be %ld");
3646 *next_code_point
= test
;
3647 next_code_point
= &test
->next
;
3649 c2
= get_array_inq_function (GFC_ISYM_SIZE
, expr1
, 2);
3650 b2
= get_array_inq_function (GFC_ISYM_SIZE
, matrix_b
, 2);
3651 test
= runtime_error_ne (c2
, b2
, "Incorrect extent in return array in "
3652 "MATMUL intrinsic for dimension 2: "
3653 "is %ld, should be %ld");
3654 *next_code_point
= test
;
3655 next_code_point
= &test
->next
;
3657 a1
= get_array_inq_function (GFC_ISYM_SIZE
, matrix_a
, 1);
3658 b1
= get_array_inq_function (GFC_ISYM_SIZE
, matrix_b
, 1);
3660 test
= runtime_error_ne (b1
, a1
, "Incorrect extent in argument B in "
3661 "MATMUL intrnisic for dimension 2: "
3662 "is %ld, should be %ld");
3663 *next_code_point
= test
;
3664 next_code_point
= &test
->next
;
3669 *next_code_point
= assign_zero
;
3671 zero
= gfc_get_int_expr (gfc_index_integer_kind
, &co
->loc
, 0);
3673 assign_matmul
= XCNEW (gfc_code
);
3674 assign_matmul
->op
= EXEC_ASSIGN
;
3675 assign_matmul
->loc
= co
->loc
;
3677 /* Get the bounds for the loops, create them and create the scalarized
3683 inline_limit_check (matrix_a
, matrix_b
, m_case
);
3685 u1
= get_size_m1 (matrix_b
, 2);
3686 u2
= get_size_m1 (matrix_a
, 2);
3687 u3
= get_size_m1 (matrix_a
, 1);
3689 do_1
= create_do_loop (gfc_copy_expr (zero
), u1
, NULL
, &co
->loc
, ns
);
3690 do_2
= create_do_loop (gfc_copy_expr (zero
), u2
, NULL
, &co
->loc
, ns
);
3691 do_3
= create_do_loop (gfc_copy_expr (zero
), u3
, NULL
, &co
->loc
, ns
);
3693 do_1
->block
->next
= do_2
;
3694 do_2
->block
->next
= do_3
;
3695 do_3
->block
->next
= assign_matmul
;
3697 var_1
= do_1
->ext
.iterator
->var
;
3698 var_2
= do_2
->ext
.iterator
->var
;
3699 var_3
= do_3
->ext
.iterator
->var
;
3703 cscalar
= scalarized_expr (co
->expr1
, list
, 2);
3707 ascalar
= scalarized_expr (matrix_a
, list
, 2);
3711 bscalar
= scalarized_expr (matrix_b
, list
, 2);
3716 inline_limit_check (matrix_a
, matrix_b
, m_case
);
3718 u1
= get_size_m1 (matrix_b
, 1);
3719 u2
= get_size_m1 (matrix_a
, 2);
3720 u3
= get_size_m1 (matrix_a
, 1);
3722 do_1
= create_do_loop (gfc_copy_expr (zero
), u1
, NULL
, &co
->loc
, ns
);
3723 do_2
= create_do_loop (gfc_copy_expr (zero
), u2
, NULL
, &co
->loc
, ns
);
3724 do_3
= create_do_loop (gfc_copy_expr (zero
), u3
, NULL
, &co
->loc
, ns
);
3726 do_1
->block
->next
= do_2
;
3727 do_2
->block
->next
= do_3
;
3728 do_3
->block
->next
= assign_matmul
;
3730 var_1
= do_1
->ext
.iterator
->var
;
3731 var_2
= do_2
->ext
.iterator
->var
;
3732 var_3
= do_3
->ext
.iterator
->var
;
3736 cscalar
= scalarized_expr (co
->expr1
, list
, 2);
3740 ascalar
= scalarized_expr (matrix_a
, list
, 2);
3744 bscalar
= scalarized_expr (matrix_b
, list
, 2);
3749 inline_limit_check (matrix_a
, matrix_b
, m_case
);
3751 u1
= get_size_m1 (matrix_a
, 2);
3752 u2
= get_size_m1 (matrix_b
, 2);
3753 u3
= get_size_m1 (matrix_a
, 1);
3755 do_1
= create_do_loop (gfc_copy_expr (zero
), u1
, NULL
, &co
->loc
, ns
);
3756 do_2
= create_do_loop (gfc_copy_expr (zero
), u2
, NULL
, &co
->loc
, ns
);
3757 do_3
= create_do_loop (gfc_copy_expr (zero
), u3
, NULL
, &co
->loc
, ns
);
3759 do_1
->block
->next
= do_2
;
3760 do_2
->block
->next
= do_3
;
3761 do_3
->block
->next
= assign_matmul
;
3763 var_1
= do_1
->ext
.iterator
->var
;
3764 var_2
= do_2
->ext
.iterator
->var
;
3765 var_3
= do_3
->ext
.iterator
->var
;
3769 cscalar
= scalarized_expr (co
->expr1
, list
, 2);
3773 ascalar
= scalarized_expr (matrix_a
, list
, 2);
3777 bscalar
= scalarized_expr (matrix_b
, list
, 2);
3782 u1
= get_size_m1 (matrix_b
, 1);
3783 u2
= get_size_m1 (matrix_a
, 1);
3785 do_1
= create_do_loop (gfc_copy_expr (zero
), u1
, NULL
, &co
->loc
, ns
);
3786 do_2
= create_do_loop (gfc_copy_expr (zero
), u2
, NULL
, &co
->loc
, ns
);
3788 do_1
->block
->next
= do_2
;
3789 do_2
->block
->next
= assign_matmul
;
3791 var_1
= do_1
->ext
.iterator
->var
;
3792 var_2
= do_2
->ext
.iterator
->var
;
3795 cscalar
= scalarized_expr (co
->expr1
, list
, 1);
3799 ascalar
= scalarized_expr (matrix_a
, list
, 2);
3802 bscalar
= scalarized_expr (matrix_b
, list
, 1);
3807 u1
= get_size_m1 (matrix_b
, 2);
3808 u2
= get_size_m1 (matrix_a
, 1);
3810 do_1
= create_do_loop (gfc_copy_expr (zero
), u1
, NULL
, &co
->loc
, ns
);
3811 do_2
= create_do_loop (gfc_copy_expr (zero
), u2
, NULL
, &co
->loc
, ns
);
3813 do_1
->block
->next
= do_2
;
3814 do_2
->block
->next
= assign_matmul
;
3816 var_1
= do_1
->ext
.iterator
->var
;
3817 var_2
= do_2
->ext
.iterator
->var
;
3820 cscalar
= scalarized_expr (co
->expr1
, list
, 1);
3823 ascalar
= scalarized_expr (matrix_a
, list
, 1);
3827 bscalar
= scalarized_expr (matrix_b
, list
, 2);
3836 ascalar
= gfc_build_intrinsic_call (ns
, GFC_ISYM_CONJG
, "conjg",
3837 matrix_a
->where
, 1, ascalar
);
3840 bscalar
= gfc_build_intrinsic_call (ns
, GFC_ISYM_CONJG
, "conjg",
3841 matrix_b
->where
, 1, bscalar
);
3843 /* First loop comes after the zero assignment. */
3844 assign_zero
->next
= do_1
;
3846 /* Build the assignment expression in the loop. */
3847 assign_matmul
->expr1
= gfc_copy_expr (cscalar
);
3849 mult
= get_operand (op_times
, ascalar
, bscalar
);
3850 assign_matmul
->expr2
= get_operand (op_plus
, cscalar
, mult
);
3852 /* If we don't want to keep the original statement around in
3853 the else branch, we can free it. */
3855 if (if_limit
== NULL
)
3856 gfc_free_statements(co
);
3860 gfc_free_expr (zero
);
3865 #define WALK_SUBEXPR(NODE) \
3868 result = gfc_expr_walker (&(NODE), exprfn, data); \
3873 #define WALK_SUBEXPR_TAIL(NODE) e = &(NODE); continue
3875 /* Walk expression *E, calling EXPRFN on each expression in it. */
3878 gfc_expr_walker (gfc_expr
**e
, walk_expr_fn_t exprfn
, void *data
)
3882 int walk_subtrees
= 1;
3883 gfc_actual_arglist
*a
;
3887 int result
= exprfn (e
, &walk_subtrees
, data
);
3891 switch ((*e
)->expr_type
)
3894 WALK_SUBEXPR ((*e
)->value
.op
.op1
);
3895 WALK_SUBEXPR_TAIL ((*e
)->value
.op
.op2
);
3898 for (a
= (*e
)->value
.function
.actual
; a
; a
= a
->next
)
3899 WALK_SUBEXPR (a
->expr
);
3903 WALK_SUBEXPR ((*e
)->value
.compcall
.base_object
);
3904 for (a
= (*e
)->value
.compcall
.actual
; a
; a
= a
->next
)
3905 WALK_SUBEXPR (a
->expr
);
3908 case EXPR_STRUCTURE
:
3910 for (c
= gfc_constructor_first ((*e
)->value
.constructor
); c
;
3911 c
= gfc_constructor_next (c
))
3913 if (c
->iterator
== NULL
)
3914 WALK_SUBEXPR (c
->expr
);
3918 WALK_SUBEXPR (c
->expr
);
3920 WALK_SUBEXPR (c
->iterator
->var
);
3921 WALK_SUBEXPR (c
->iterator
->start
);
3922 WALK_SUBEXPR (c
->iterator
->end
);
3923 WALK_SUBEXPR (c
->iterator
->step
);
3927 if ((*e
)->expr_type
!= EXPR_ARRAY
)
3930 /* Fall through to the variable case in order to walk the
3934 case EXPR_SUBSTRING
:
3936 for (r
= (*e
)->ref
; r
; r
= r
->next
)
3945 if (ar
->type
== AR_SECTION
|| ar
->type
== AR_ELEMENT
)
3947 for (i
=0; i
< ar
->dimen
; i
++)
3949 WALK_SUBEXPR (ar
->start
[i
]);
3950 WALK_SUBEXPR (ar
->end
[i
]);
3951 WALK_SUBEXPR (ar
->stride
[i
]);
3958 WALK_SUBEXPR (r
->u
.ss
.start
);
3959 WALK_SUBEXPR (r
->u
.ss
.end
);
3975 #define WALK_SUBCODE(NODE) \
3978 result = gfc_code_walker (&(NODE), codefn, exprfn, data); \
3984 /* Walk code *C, calling CODEFN on each gfc_code node in it and calling EXPRFN
3985 on each expression in it. If any of the hooks returns non-zero, that
3986 value is immediately returned. If the hook sets *WALK_SUBTREES to 0,
3987 no subcodes or subexpressions are traversed. */
3990 gfc_code_walker (gfc_code
**c
, walk_code_fn_t codefn
, walk_expr_fn_t exprfn
,
3993 for (; *c
; c
= &(*c
)->next
)
3995 int walk_subtrees
= 1;
3996 int result
= codefn (c
, &walk_subtrees
, data
);
4003 gfc_actual_arglist
*a
;
4005 gfc_association_list
*alist
;
4006 bool saved_in_omp_workshare
;
4007 bool saved_in_where
;
4009 /* There might be statement insertions before the current code,
4010 which must not affect the expression walker. */
4013 saved_in_omp_workshare
= in_omp_workshare
;
4014 saved_in_where
= in_where
;
4020 WALK_SUBCODE (co
->ext
.block
.ns
->code
);
4021 if (co
->ext
.block
.assoc
)
4023 bool saved_in_assoc_list
= in_assoc_list
;
4025 in_assoc_list
= true;
4026 for (alist
= co
->ext
.block
.assoc
; alist
; alist
= alist
->next
)
4027 WALK_SUBEXPR (alist
->target
);
4029 in_assoc_list
= saved_in_assoc_list
;
4036 WALK_SUBEXPR (co
->ext
.iterator
->var
);
4037 WALK_SUBEXPR (co
->ext
.iterator
->start
);
4038 WALK_SUBEXPR (co
->ext
.iterator
->end
);
4039 WALK_SUBEXPR (co
->ext
.iterator
->step
);
4047 case EXEC_ASSIGN_CALL
:
4048 for (a
= co
->ext
.actual
; a
; a
= a
->next
)
4049 WALK_SUBEXPR (a
->expr
);
4053 WALK_SUBEXPR (co
->expr1
);
4054 for (a
= co
->ext
.actual
; a
; a
= a
->next
)
4055 WALK_SUBEXPR (a
->expr
);
4059 WALK_SUBEXPR (co
->expr1
);
4060 for (b
= co
->block
; b
; b
= b
->block
)
4063 for (cp
= b
->ext
.block
.case_list
; cp
; cp
= cp
->next
)
4065 WALK_SUBEXPR (cp
->low
);
4066 WALK_SUBEXPR (cp
->high
);
4068 WALK_SUBCODE (b
->next
);
4073 case EXEC_DEALLOCATE
:
4076 for (a
= co
->ext
.alloc
.list
; a
; a
= a
->next
)
4077 WALK_SUBEXPR (a
->expr
);
4082 case EXEC_DO_CONCURRENT
:
4084 gfc_forall_iterator
*fa
;
4085 for (fa
= co
->ext
.forall_iterator
; fa
; fa
= fa
->next
)
4087 WALK_SUBEXPR (fa
->var
);
4088 WALK_SUBEXPR (fa
->start
);
4089 WALK_SUBEXPR (fa
->end
);
4090 WALK_SUBEXPR (fa
->stride
);
4092 if (co
->op
== EXEC_FORALL
)
4098 WALK_SUBEXPR (co
->ext
.open
->unit
);
4099 WALK_SUBEXPR (co
->ext
.open
->file
);
4100 WALK_SUBEXPR (co
->ext
.open
->status
);
4101 WALK_SUBEXPR (co
->ext
.open
->access
);
4102 WALK_SUBEXPR (co
->ext
.open
->form
);
4103 WALK_SUBEXPR (co
->ext
.open
->recl
);
4104 WALK_SUBEXPR (co
->ext
.open
->blank
);
4105 WALK_SUBEXPR (co
->ext
.open
->position
);
4106 WALK_SUBEXPR (co
->ext
.open
->action
);
4107 WALK_SUBEXPR (co
->ext
.open
->delim
);
4108 WALK_SUBEXPR (co
->ext
.open
->pad
);
4109 WALK_SUBEXPR (co
->ext
.open
->iostat
);
4110 WALK_SUBEXPR (co
->ext
.open
->iomsg
);
4111 WALK_SUBEXPR (co
->ext
.open
->convert
);
4112 WALK_SUBEXPR (co
->ext
.open
->decimal
);
4113 WALK_SUBEXPR (co
->ext
.open
->encoding
);
4114 WALK_SUBEXPR (co
->ext
.open
->round
);
4115 WALK_SUBEXPR (co
->ext
.open
->sign
);
4116 WALK_SUBEXPR (co
->ext
.open
->asynchronous
);
4117 WALK_SUBEXPR (co
->ext
.open
->id
);
4118 WALK_SUBEXPR (co
->ext
.open
->newunit
);
4119 WALK_SUBEXPR (co
->ext
.open
->share
);
4120 WALK_SUBEXPR (co
->ext
.open
->cc
);
4124 WALK_SUBEXPR (co
->ext
.close
->unit
);
4125 WALK_SUBEXPR (co
->ext
.close
->status
);
4126 WALK_SUBEXPR (co
->ext
.close
->iostat
);
4127 WALK_SUBEXPR (co
->ext
.close
->iomsg
);
4130 case EXEC_BACKSPACE
:
4134 WALK_SUBEXPR (co
->ext
.filepos
->unit
);
4135 WALK_SUBEXPR (co
->ext
.filepos
->iostat
);
4136 WALK_SUBEXPR (co
->ext
.filepos
->iomsg
);
4140 WALK_SUBEXPR (co
->ext
.inquire
->unit
);
4141 WALK_SUBEXPR (co
->ext
.inquire
->file
);
4142 WALK_SUBEXPR (co
->ext
.inquire
->iomsg
);
4143 WALK_SUBEXPR (co
->ext
.inquire
->iostat
);
4144 WALK_SUBEXPR (co
->ext
.inquire
->exist
);
4145 WALK_SUBEXPR (co
->ext
.inquire
->opened
);
4146 WALK_SUBEXPR (co
->ext
.inquire
->number
);
4147 WALK_SUBEXPR (co
->ext
.inquire
->named
);
4148 WALK_SUBEXPR (co
->ext
.inquire
->name
);
4149 WALK_SUBEXPR (co
->ext
.inquire
->access
);
4150 WALK_SUBEXPR (co
->ext
.inquire
->sequential
);
4151 WALK_SUBEXPR (co
->ext
.inquire
->direct
);
4152 WALK_SUBEXPR (co
->ext
.inquire
->form
);
4153 WALK_SUBEXPR (co
->ext
.inquire
->formatted
);
4154 WALK_SUBEXPR (co
->ext
.inquire
->unformatted
);
4155 WALK_SUBEXPR (co
->ext
.inquire
->recl
);
4156 WALK_SUBEXPR (co
->ext
.inquire
->nextrec
);
4157 WALK_SUBEXPR (co
->ext
.inquire
->blank
);
4158 WALK_SUBEXPR (co
->ext
.inquire
->position
);
4159 WALK_SUBEXPR (co
->ext
.inquire
->action
);
4160 WALK_SUBEXPR (co
->ext
.inquire
->read
);
4161 WALK_SUBEXPR (co
->ext
.inquire
->write
);
4162 WALK_SUBEXPR (co
->ext
.inquire
->readwrite
);
4163 WALK_SUBEXPR (co
->ext
.inquire
->delim
);
4164 WALK_SUBEXPR (co
->ext
.inquire
->encoding
);
4165 WALK_SUBEXPR (co
->ext
.inquire
->pad
);
4166 WALK_SUBEXPR (co
->ext
.inquire
->iolength
);
4167 WALK_SUBEXPR (co
->ext
.inquire
->convert
);
4168 WALK_SUBEXPR (co
->ext
.inquire
->strm_pos
);
4169 WALK_SUBEXPR (co
->ext
.inquire
->asynchronous
);
4170 WALK_SUBEXPR (co
->ext
.inquire
->decimal
);
4171 WALK_SUBEXPR (co
->ext
.inquire
->pending
);
4172 WALK_SUBEXPR (co
->ext
.inquire
->id
);
4173 WALK_SUBEXPR (co
->ext
.inquire
->sign
);
4174 WALK_SUBEXPR (co
->ext
.inquire
->size
);
4175 WALK_SUBEXPR (co
->ext
.inquire
->round
);
4179 WALK_SUBEXPR (co
->ext
.wait
->unit
);
4180 WALK_SUBEXPR (co
->ext
.wait
->iostat
);
4181 WALK_SUBEXPR (co
->ext
.wait
->iomsg
);
4182 WALK_SUBEXPR (co
->ext
.wait
->id
);
4187 WALK_SUBEXPR (co
->ext
.dt
->io_unit
);
4188 WALK_SUBEXPR (co
->ext
.dt
->format_expr
);
4189 WALK_SUBEXPR (co
->ext
.dt
->rec
);
4190 WALK_SUBEXPR (co
->ext
.dt
->advance
);
4191 WALK_SUBEXPR (co
->ext
.dt
->iostat
);
4192 WALK_SUBEXPR (co
->ext
.dt
->size
);
4193 WALK_SUBEXPR (co
->ext
.dt
->iomsg
);
4194 WALK_SUBEXPR (co
->ext
.dt
->id
);
4195 WALK_SUBEXPR (co
->ext
.dt
->pos
);
4196 WALK_SUBEXPR (co
->ext
.dt
->asynchronous
);
4197 WALK_SUBEXPR (co
->ext
.dt
->blank
);
4198 WALK_SUBEXPR (co
->ext
.dt
->decimal
);
4199 WALK_SUBEXPR (co
->ext
.dt
->delim
);
4200 WALK_SUBEXPR (co
->ext
.dt
->pad
);
4201 WALK_SUBEXPR (co
->ext
.dt
->round
);
4202 WALK_SUBEXPR (co
->ext
.dt
->sign
);
4203 WALK_SUBEXPR (co
->ext
.dt
->extra_comma
);
4206 case EXEC_OMP_PARALLEL
:
4207 case EXEC_OMP_PARALLEL_DO
:
4208 case EXEC_OMP_PARALLEL_DO_SIMD
:
4209 case EXEC_OMP_PARALLEL_SECTIONS
:
4211 in_omp_workshare
= false;
4213 /* This goto serves as a shortcut to avoid code
4214 duplication or a larger if or switch statement. */
4215 goto check_omp_clauses
;
4217 case EXEC_OMP_WORKSHARE
:
4218 case EXEC_OMP_PARALLEL_WORKSHARE
:
4220 in_omp_workshare
= true;
4224 case EXEC_OMP_CRITICAL
:
4225 case EXEC_OMP_DISTRIBUTE
:
4226 case EXEC_OMP_DISTRIBUTE_PARALLEL_DO
:
4227 case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD
:
4228 case EXEC_OMP_DISTRIBUTE_SIMD
:
4230 case EXEC_OMP_DO_SIMD
:
4231 case EXEC_OMP_ORDERED
:
4232 case EXEC_OMP_SECTIONS
:
4233 case EXEC_OMP_SINGLE
:
4234 case EXEC_OMP_END_SINGLE
:
4236 case EXEC_OMP_TASKLOOP
:
4237 case EXEC_OMP_TASKLOOP_SIMD
:
4238 case EXEC_OMP_TARGET
:
4239 case EXEC_OMP_TARGET_DATA
:
4240 case EXEC_OMP_TARGET_ENTER_DATA
:
4241 case EXEC_OMP_TARGET_EXIT_DATA
:
4242 case EXEC_OMP_TARGET_PARALLEL
:
4243 case EXEC_OMP_TARGET_PARALLEL_DO
:
4244 case EXEC_OMP_TARGET_PARALLEL_DO_SIMD
:
4245 case EXEC_OMP_TARGET_SIMD
:
4246 case EXEC_OMP_TARGET_TEAMS
:
4247 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE
:
4248 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO
:
4249 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD
:
4250 case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD
:
4251 case EXEC_OMP_TARGET_UPDATE
:
4253 case EXEC_OMP_TEAMS
:
4254 case EXEC_OMP_TEAMS_DISTRIBUTE
:
4255 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO
:
4256 case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD
:
4257 case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD
:
4259 /* Come to this label only from the
4260 EXEC_OMP_PARALLEL_* cases above. */
4264 if (co
->ext
.omp_clauses
)
4266 gfc_omp_namelist
*n
;
4267 static int list_types
[]
4268 = { OMP_LIST_ALIGNED
, OMP_LIST_LINEAR
, OMP_LIST_DEPEND
,
4269 OMP_LIST_MAP
, OMP_LIST_TO
, OMP_LIST_FROM
};
4271 WALK_SUBEXPR (co
->ext
.omp_clauses
->if_expr
);
4272 WALK_SUBEXPR (co
->ext
.omp_clauses
->final_expr
);
4273 WALK_SUBEXPR (co
->ext
.omp_clauses
->num_threads
);
4274 WALK_SUBEXPR (co
->ext
.omp_clauses
->chunk_size
);
4275 WALK_SUBEXPR (co
->ext
.omp_clauses
->safelen_expr
);
4276 WALK_SUBEXPR (co
->ext
.omp_clauses
->simdlen_expr
);
4277 WALK_SUBEXPR (co
->ext
.omp_clauses
->num_teams
);
4278 WALK_SUBEXPR (co
->ext
.omp_clauses
->device
);
4279 WALK_SUBEXPR (co
->ext
.omp_clauses
->thread_limit
);
4280 WALK_SUBEXPR (co
->ext
.omp_clauses
->dist_chunk_size
);
4281 WALK_SUBEXPR (co
->ext
.omp_clauses
->grainsize
);
4282 WALK_SUBEXPR (co
->ext
.omp_clauses
->hint
);
4283 WALK_SUBEXPR (co
->ext
.omp_clauses
->num_tasks
);
4284 WALK_SUBEXPR (co
->ext
.omp_clauses
->priority
);
4285 for (idx
= 0; idx
< OMP_IF_LAST
; idx
++)
4286 WALK_SUBEXPR (co
->ext
.omp_clauses
->if_exprs
[idx
]);
4288 idx
< sizeof (list_types
) / sizeof (list_types
[0]);
4290 for (n
= co
->ext
.omp_clauses
->lists
[list_types
[idx
]];
4292 WALK_SUBEXPR (n
->expr
);
4299 WALK_SUBEXPR (co
->expr1
);
4300 WALK_SUBEXPR (co
->expr2
);
4301 WALK_SUBEXPR (co
->expr3
);
4302 WALK_SUBEXPR (co
->expr4
);
4303 for (b
= co
->block
; b
; b
= b
->block
)
4305 WALK_SUBEXPR (b
->expr1
);
4306 WALK_SUBEXPR (b
->expr2
);
4307 WALK_SUBCODE (b
->next
);
4310 if (co
->op
== EXEC_FORALL
)
4313 if (co
->op
== EXEC_DO
)
4316 in_omp_workshare
= saved_in_omp_workshare
;
4317 in_where
= saved_in_where
;