aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran
diff options
context:
space:
mode:
authormikael <mikael@138bc75d-0d04-0410-961f-82ee72b054a4>2015-03-23 07:53:31 +0000
committermikael <mikael@138bc75d-0d04-0410-961f-82ee72b054a4>2015-03-23 07:53:31 +0000
commit9e578cf5f5e9b5d6433b1320a1934e8967f5a3fe (patch)
tree59f7139307675a6ddd88e7d11153ba3460ac0019 /gcc/fortran
parentd2ac64b1dc466a14ddc17ea30e43088650199613 (diff)
2015-03-23 Paul Thomas <pault@gcc.gnu.org>
Mikael Morin <mikael@gcc.gnu.org> PR fortran/64952 fortran/ * gfortran.h (struct symbol_attribute) : New field 'array_outer_dependency'. * trans.h (struct gfc_ss_info): New field 'array_outer_dependency'. * module.c (enum ab_attribute): New value AB_ARRAY_OUTER_DEPENDENCY. (attr_bits): Append same value to initializer. (mio_symbol_attribute): Handle 'array_outer_dependency' attr in module read and write. * resolve.c (update_current_proc_outer_array_dependency): New function. (resolve_function, resolve_call): Add code to update current procedure's 'array_outer_dependency' attribute. (resolve_variable): Mark current procedure with attribute array_outer_dependency if the variable is an array coming from outside the current namespace. (resolve_fl_procedure): Mark a procedure without body with attribute 'array_outer_dependency'. * trans-array.c (gfc_conv_resolve_dependencies): If any ss is marked as 'array_outer_dependency' generate a temporary. (gfc_walk_function_expr): If the function may reference external arrays, mark the head gfc_ss with flag 'array_outer_dependency'. testsuite/ * gfortran.dg/elemental_dependency_4.f90: New. * gfortran.dg/elemental_dependency_5.f90: New. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@221586 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/fortran')
-rw-r--r--gcc/fortran/ChangeLog24
-rw-r--r--gcc/fortran/gfortran.h7
-rw-r--r--gcc/fortran/module.c9
-rw-r--r--gcc/fortran/resolve.c55
-rw-r--r--gcc/fortran/trans-array.c19
-rw-r--r--gcc/fortran/trans.h4
6 files changed, 116 insertions, 2 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index c8c030844fd..473d3192a92 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,27 @@
+2015-03-23 Paul Thomas <pault@gcc.gnu.org>
+ Mikael Morin <mikael@gcc.gnu.org>
+
+ PR fortran/64952
+ * gfortran.h (struct symbol_attribute) : New field
+ 'array_outer_dependency'.
+ * trans.h (struct gfc_ss_info): New field 'array_outer_dependency'.
+ * module.c (enum ab_attribute): New value AB_ARRAY_OUTER_DEPENDENCY.
+ (attr_bits): Append same value to initializer.
+ (mio_symbol_attribute): Handle 'array_outer_dependency' attr
+ in module read and write.
+ * resolve.c (update_current_proc_outer_array_dependency): New function.
+ (resolve_function, resolve_call): Add code to update current procedure's
+ 'array_outer_dependency' attribute.
+ (resolve_variable): Mark current procedure with attribute
+ array_outer_dependency if the variable is an array coming from outside
+ the current namespace.
+ (resolve_fl_procedure): Mark a procedure without body with attribute
+ 'array_outer_dependency'.
+ * trans-array.c (gfc_conv_resolve_dependencies): If any ss is
+ marked as 'array_outer_dependency' generate a temporary.
+ (gfc_walk_function_expr): If the function may reference external arrays,
+ mark the head gfc_ss with flag 'array_outer_dependency'.
+
2015-03-22 Jerry DeLisle <jvdelisle@gcc.gnu.org>
PR libgfortran/59513
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index ff0054e7029..9be20109bf6 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -789,6 +789,13 @@ typedef struct
cannot alias. Note that this is zero for PURE procedures. */
unsigned implicit_pure:1;
+ /* This is set for a procedure that contains expressions referencing
+ arrays coming from outside its namespace.
+ This is used to force the creation of a temporary when the LHS of
+ an array assignment may be used by an elemental procedure appearing
+ on the RHS. */
+ unsigned array_outer_dependency:1;
+
/* This is set if the subroutine doesn't return. Currently, this
is only possible for intrinsic subroutines. */
unsigned noreturn:1;
diff --git a/gcc/fortran/module.c b/gcc/fortran/module.c
index b12f8247a91..1abfc46d7a5 100644
--- a/gcc/fortran/module.c
+++ b/gcc/fortran/module.c
@@ -1893,7 +1893,8 @@ typedef enum
AB_IS_BIND_C, AB_IS_C_INTEROP, AB_IS_ISO_C, AB_ABSTRACT, AB_ZERO_COMP,
AB_IS_CLASS, AB_PROCEDURE, AB_PROC_POINTER, AB_ASYNCHRONOUS, AB_CODIMENSION,
AB_COARRAY_COMP, AB_VTYPE, AB_VTAB, AB_CONTIGUOUS, AB_CLASS_POINTER,
- AB_IMPLICIT_PURE, AB_ARTIFICIAL, AB_UNLIMITED_POLY, AB_OMP_DECLARE_TARGET
+ AB_IMPLICIT_PURE, AB_ARTIFICIAL, AB_UNLIMITED_POLY, AB_OMP_DECLARE_TARGET,
+ AB_ARRAY_OUTER_DEPENDENCY
}
ab_attribute;
@@ -1949,6 +1950,7 @@ static const mstring attr_bits[] =
minit ("IMPLICIT_PURE", AB_IMPLICIT_PURE),
minit ("UNLIMITED_POLY", AB_UNLIMITED_POLY),
minit ("OMP_DECLARE_TARGET", AB_OMP_DECLARE_TARGET),
+ minit ("ARRAY_OUTER_DEPENDENCY", AB_ARRAY_OUTER_DEPENDENCY),
minit (NULL, -1)
};
@@ -2129,6 +2131,8 @@ mio_symbol_attribute (symbol_attribute *attr)
MIO_NAME (ab_attribute) (AB_VTAB, attr_bits);
if (attr->omp_declare_target)
MIO_NAME (ab_attribute) (AB_OMP_DECLARE_TARGET, attr_bits);
+ if (attr->array_outer_dependency)
+ MIO_NAME (ab_attribute) (AB_ARRAY_OUTER_DEPENDENCY, attr_bits);
mio_rparen ();
@@ -2295,6 +2299,9 @@ mio_symbol_attribute (symbol_attribute *attr)
case AB_OMP_DECLARE_TARGET:
attr->omp_declare_target = 1;
break;
+ case AB_ARRAY_OUTER_DEPENDENCY:
+ attr->array_outer_dependency =1;
+ break;
}
}
}
diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c
index 465cf2ba8cf..2a24dfd8eda 100644
--- a/gcc/fortran/resolve.c
+++ b/gcc/fortran/resolve.c
@@ -2866,6 +2866,32 @@ static bool check_pure_function (gfc_expr *e)
}
+/* Update current procedure's array_outer_dependency flag, considering
+ a call to procedure SYM. */
+
+static void
+update_current_proc_array_outer_dependency (gfc_symbol *sym)
+{
+ /* Check to see if this is a sibling function that has not yet
+ been resolved. */
+ gfc_namespace *sibling = gfc_current_ns->sibling;
+ for (; sibling; sibling = sibling->sibling)
+ {
+ if (sibling->proc_name == sym)
+ {
+ gfc_resolve (sibling);
+ break;
+ }
+ }
+
+ /* If SYM has references to outer arrays, so has the procedure calling
+ SYM. If SYM is a procedure pointer, we can assume the worst. */
+ if (sym->attr.array_outer_dependency
+ || sym->attr.proc_pointer)
+ gfc_current_ns->proc_name->attr.array_outer_dependency = 1;
+}
+
+
/* Resolve a function call, which means resolving the arguments, then figuring
out which entity the name refers to. */
@@ -3090,6 +3116,17 @@ resolve_function (gfc_expr *expr)
expr->ts = expr->symtree->n.sym->result->ts;
}
+ if (!expr->ref && !expr->value.function.isym)
+ {
+ if (expr->value.function.esym)
+ update_current_proc_array_outer_dependency (expr->value.function.esym);
+ else
+ update_current_proc_array_outer_dependency (sym);
+ }
+ else if (expr->ref)
+ /* typebound procedure: Assume the worst. */
+ gfc_current_ns->proc_name->attr.array_outer_dependency = 1;
+
return t;
}
@@ -3427,6 +3464,12 @@ resolve_call (gfc_code *c)
if (!resolve_elemental_actual (NULL, c))
return false;
+ if (!c->expr1)
+ update_current_proc_array_outer_dependency (csym);
+ else
+ /* Typebound procedure: Assume the worst. */
+ gfc_current_ns->proc_name->attr.array_outer_dependency = 1;
+
return t;
}
@@ -5058,6 +5101,13 @@ resolve_variable (gfc_expr *e)
&& gfc_current_ns->parent->parent == sym->ns)))
sym->attr.host_assoc = 1;
+ if (gfc_current_ns->proc_name
+ && sym->attr.dimension
+ && (sym->ns != gfc_current_ns
+ || sym->attr.use_assoc
+ || sym->attr.in_common))
+ gfc_current_ns->proc_name->attr.array_outer_dependency = 1;
+
resolve_procedure:
if (t && !resolve_procedure_expression (e))
t = false;
@@ -11494,6 +11544,11 @@ resolve_fl_procedure (gfc_symbol *sym, int mp_flag)
}
}
+ /* Assume that a procedure whose body is not known has references
+ to external arrays. */
+ if (sym->attr.if_source != IFSRC_DECL)
+ sym->attr.array_outer_dependency = 1;
+
return true;
}
diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c
index 642110dc41f..0dbfdaab1b2 100644
--- a/gcc/fortran/trans-array.c
+++ b/gcc/fortran/trans-array.c
@@ -4391,6 +4391,12 @@ gfc_conv_resolve_dependencies (gfc_loopinfo * loop, gfc_ss * dest,
{
ss_expr = ss->info->expr;
+ if (ss->info->array_outer_dependency)
+ {
+ nDepend = 1;
+ break;
+ }
+
if (ss->info->type != GFC_SS_SECTION)
{
if (flag_realloc_lhs
@@ -9096,9 +9102,20 @@ gfc_walk_function_expr (gfc_ss * ss, gfc_expr * expr)
/* Walk the parameters of an elemental function. For now we always pass
by reference. */
if (sym->attr.elemental || (comp && comp->attr.elemental))
- return gfc_walk_elemental_function_args (ss, expr->value.function.actual,
+ {
+ gfc_ss *old_ss = ss;
+
+ ss = gfc_walk_elemental_function_args (old_ss,
+ expr->value.function.actual,
gfc_get_proc_ifc_for_expr (expr),
GFC_SS_REFERENCE);
+ if (ss != old_ss
+ && (comp
+ || sym->attr.proc_pointer
+ || sym->attr.if_source != IFSRC_DECL
+ || sym->attr.array_outer_dependency))
+ ss->info->array_outer_dependency = 1;
+ }
/* Scalar functions are OK as these are evaluated outside the scalarization
loop. Pass back and let the caller deal with it. */
diff --git a/gcc/fortran/trans.h b/gcc/fortran/trans.h
index 3ba2f88f0fd..be1136382ae 100644
--- a/gcc/fortran/trans.h
+++ b/gcc/fortran/trans.h
@@ -226,6 +226,10 @@ typedef struct gfc_ss_info
/* Suppresses precalculation of scalars in WHERE assignments. */
unsigned where:1;
+ /* This set for an elemental function that contains expressions for
+ external arrays, thereby triggering creation of a temporary. */
+ unsigned array_outer_dependency:1;
+
/* Tells whether the SS is for an actual argument which can be a NULL
reference. In other words, the associated dummy argument is OPTIONAL.
Used to handle elemental procedures. */