summaryrefslogtreecommitdiff
path: root/gcc/fortran/dependency.c
diff options
context:
space:
mode:
authorrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>2005-12-13 05:23:12 +0000
committerrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>2005-12-13 05:23:12 +0000
commit018ef8b85510566d031e3b6cec1709d41221da87 (patch)
tree8b430f1a509f3fecd45aafac44d2707a38eb02d2 /gcc/fortran/dependency.c
parent6e24d2a7cfd1fc5190a77f34b75594c2ce92627f (diff)
downloadgcc-018ef8b85510566d031e3b6cec1709d41221da87.tar.gz
gcc/fortran/
* Make-lang.in (fortran/trans-resolve.o): Depend on fortran/dependency.h. * gfortran.h (gfc_expr): Add an "inline_noncopying_intrinsic" flag. * dependency.h (gfc_get_noncopying_intrinsic_argument): Declare. (gfc_check_fncall_dependency): Change prototype. * dependency.c (gfc_get_noncopying_intrinsic_argument): New function. (gfc_check_argument_var_dependency): New function, split from gfc_check_fncall_dependency. (gfc_check_argument_dependency): New function. (gfc_check_fncall_dependency): Replace the expression parameter with separate symbol and argument list parameters. Generalize the function to handle dependencies for any type of expression, not just variables. Accept a further argument giving the intent of the expression being tested. Ignore intent(in) arguments if that expression is also intent(in). * resolve.c: Include dependency.h. (find_noncopying_intrinsics): New function. (resolve_function, resolve_call): Call it on success. * trans-array.h (gfc_conv_array_transpose): Declare. (gfc_check_fncall_dependency): Remove prototype. * trans-array.c (gfc_conv_array_transpose): New function. * trans-intrinsic.c (gfc_conv_intrinsic_function): Don't use the libcall handling if the expression is to be evaluated inline. Add a case for handling inline transpose()s. * trans-expr.c (gfc_trans_arrayfunc_assign): Adjust for the new interface provided by gfc_check_fncall_dependency. libgfortran/ * m4/matmul.m4: Use a different order in the special case of a transposed first argument. * generated/matmul_c4.c, generated/matmul_c8.c, generated/matmul_c10.c, * generated/matmul_c16.c, generated/matmul_i4.c, generated/matmul_i8.c, * generated/matmul_i10.c, generated/matmul_r4.c, generated/matmul_r8.c * generated/matmul_r10.c, generated/matmul_r16.c: Regenerated. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@108459 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/fortran/dependency.c')
-rw-r--r--gcc/fortran/dependency.c132
1 files changed, 104 insertions, 28 deletions
diff --git a/gcc/fortran/dependency.c b/gcc/fortran/dependency.c
index b93808a2bce..d3a486e28f6 100644
--- a/gcc/fortran/dependency.c
+++ b/gcc/fortran/dependency.c
@@ -175,6 +175,32 @@ gfc_is_same_range (gfc_array_ref * ar1, gfc_array_ref * ar2, int n, int def)
}
+/* Some array-returning intrinsics can be implemented by reusing the
+ data from one of the array arguments. For example, TRANPOSE does
+ not necessarily need to allocate new data: it can be implemented
+ by copying the original array's descriptor and simply swapping the
+ two dimension specifications.
+
+ If EXPR is a call to such an intrinsic, return the argument
+ whose data can be reused, otherwise return NULL. */
+
+gfc_expr *
+gfc_get_noncopying_intrinsic_argument (gfc_expr * expr)
+{
+ if (expr->expr_type != EXPR_FUNCTION || !expr->value.function.isym)
+ return NULL;
+
+ switch (expr->value.function.isym->generic_id)
+ {
+ case GFC_ISYM_TRANSPOSE:
+ return expr->value.function.actual->expr;
+
+ default:
+ return NULL;
+ }
+}
+
+
/* Return true if the result of reference REF can only be constructed
using a temporary array. */
@@ -214,23 +240,82 @@ gfc_ref_needs_temporary_p (gfc_ref *ref)
}
-/* Dependency checking for direct function return by reference.
- Returns true if the arguments of the function depend on the
- destination. This is considerably less conservative than other
- dependencies because many function arguments will already be
- copied into a temporary. */
+/* Return true if array variable VAR could be passed to the same function
+ as argument EXPR without interfering with EXPR. INTENT is the intent
+ of VAR.
+
+ This is considerably less conservative than other dependencies
+ because many function arguments will already be copied into a
+ temporary. */
+
+static int
+gfc_check_argument_var_dependency (gfc_expr * var, sym_intent intent,
+ gfc_expr * expr)
+{
+ gcc_assert (var->expr_type == EXPR_VARIABLE);
+ gcc_assert (var->rank > 0);
+
+ switch (expr->expr_type)
+ {
+ case EXPR_VARIABLE:
+ return (gfc_ref_needs_temporary_p (expr->ref)
+ || gfc_check_dependency (var, expr, NULL, 0));
+
+ case EXPR_ARRAY:
+ return gfc_check_dependency (var, expr, NULL, 0);
+
+ case EXPR_FUNCTION:
+ if (intent != INTENT_IN && expr->inline_noncopying_intrinsic)
+ {
+ expr = gfc_get_noncopying_intrinsic_argument (expr);
+ return gfc_check_argument_var_dependency (var, intent, expr);
+ }
+ return 0;
+
+ default:
+ return 0;
+ }
+}
+
+
+/* Like gfc_check_argument_var_dependency, but extended to any
+ array expression OTHER, not just variables. */
+
+static int
+gfc_check_argument_dependency (gfc_expr * other, sym_intent intent,
+ gfc_expr * expr)
+{
+ switch (other->expr_type)
+ {
+ case EXPR_VARIABLE:
+ return gfc_check_argument_var_dependency (other, intent, expr);
+
+ case EXPR_FUNCTION:
+ if (other->inline_noncopying_intrinsic)
+ {
+ other = gfc_get_noncopying_intrinsic_argument (other);
+ return gfc_check_argument_dependency (other, INTENT_IN, expr);
+ }
+ return 0;
+
+ default:
+ return 0;
+ }
+}
+
+
+/* Like gfc_check_argument_dependency, but check all the arguments in ACTUAL.
+ FNSYM is the function being called, or NULL if not known. */
int
-gfc_check_fncall_dependency (gfc_expr * dest, gfc_expr * fncall)
+gfc_check_fncall_dependency (gfc_expr * other, sym_intent intent,
+ gfc_symbol * fnsym, gfc_actual_arglist * actual)
{
- gfc_actual_arglist *actual;
+ gfc_formal_arglist *formal;
gfc_expr *expr;
- gcc_assert (dest->expr_type == EXPR_VARIABLE
- && fncall->expr_type == EXPR_FUNCTION);
- gcc_assert (fncall->rank > 0);
-
- for (actual = fncall->value.function.actual; actual; actual = actual->next)
+ formal = fnsym ? fnsym->formal : NULL;
+ for (; actual; actual = actual->next, formal = formal ? formal->next : NULL)
{
expr = actual->expr;
@@ -238,23 +323,14 @@ gfc_check_fncall_dependency (gfc_expr * dest, gfc_expr * fncall)
if (!expr)
continue;
- /* Non-variable expressions will be allocated temporaries anyway. */
- switch (expr->expr_type)
- {
- case EXPR_VARIABLE:
- if (!gfc_ref_needs_temporary_p (expr->ref)
- && gfc_check_dependency (dest, expr, NULL, 0))
- return 1;
- break;
-
- case EXPR_ARRAY:
- if (gfc_check_dependency (dest, expr, NULL, 0))
- return 1;
- break;
+ /* Skip intent(in) arguments if OTHER itself is intent(in). */
+ if (formal
+ && intent == INTENT_IN
+ && formal->sym->attr.intent == INTENT_IN)
+ continue;
- default:
- break;
- }
+ if (gfc_check_argument_dependency (other, intent, expr))
+ return 1;
}
return 0;