diff options
author | rsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-12-13 05:23:12 +0000 |
---|---|---|
committer | rsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-12-13 05:23:12 +0000 |
commit | 018ef8b85510566d031e3b6cec1709d41221da87 (patch) | |
tree | 8b430f1a509f3fecd45aafac44d2707a38eb02d2 /gcc/fortran/dependency.c | |
parent | 6e24d2a7cfd1fc5190a77f34b75594c2ce92627f (diff) | |
download | gcc-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.c | 132 |
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; |