Commit 712efae1 by Mikael Morin

gfortran.h (gfc_expr): Remove inline_noncopying_intrinsic attribute.

2010-09-11  Mikael Morin  <mikael@gcc.gnu.org>

	* gfortran.h (gfc_expr): Remove inline_noncopying_intrinsic attribute.
	* dependency.c (gfc_check_dependency): Don't depend on
	expr's inline_noncopying_intrinsic_attribute.
	* dependency.c (gfc_check_argument_var_dependency,
	gfc_check_argument_dependency): Ditto. Recursively check dependency
	as NOT_ELEMENTAL in the non-copying (=transpose) case.
	* trans-intrinsic.c (gfc_conv_intrinsic_function): Ditto.
	* resolve.c (find_noncopying_intrinsics): Remove.
	(resolve_function, resolve_call): Remove call to
	find_noncopying_intrinsics.

	* trans-array.c (gfc_conv_array_transpose): Remove.
	(gfc_walk_subexpr): Make non-static. Move prototype...
	* trans-array.h (gfc_walk_subexpr): ... here.
	* trans-intrinsic.c (gfc_conv_intrinsic_function): Update transpose
	handling.
	(walk_inline_intrinsic_transpose, walk_inline_intrinsic_function,
	gfc_inline_intrinsic_function_p): New.
	(gfc_is_intrinsic_libcall): Return early in inline intrinsic case.
	Remove transpose from the libcall list.
	(gfc_walk_intrinsic_function): Special case inline intrinsic.
	* trans.h (gfc_inline_intrinsic_function_p): New prototype.

2010-09-11  Mikael Morin  <mikael@gcc.gnu.org>

	* gfortran.dg/inline_transpose_1.f90: Update temporary's locations
	and counts. Check that transpose is not called.
	* gfortran.dg/transpose_2.f90: Update error message.

From-SVN: r164205
parent 48255616
2010-09-11 Mikael Morin <mikael@gcc.gnu.org>
* gfortran.h (gfc_expr): Remove inline_noncopying_intrinsic attribute.
* dependency.c (gfc_check_dependency): Don't depend on
expr's inline_noncopying_intrinsic_attribute.
* dependency.c (gfc_check_argument_var_dependency,
gfc_check_argument_dependency): Ditto. Recursively check dependency
as NOT_ELEMENTAL in the non-copying (=transpose) case.
* trans-intrinsic.c (gfc_conv_intrinsic_function): Ditto.
* resolve.c (find_noncopying_intrinsics): Remove.
(resolve_function, resolve_call): Remove call to
find_noncopying_intrinsics.
* trans-array.c (gfc_conv_array_transpose): Remove.
(gfc_walk_subexpr): Make non-static. Move prototype...
* trans-array.h (gfc_walk_subexpr): ... here.
* trans-intrinsic.c (gfc_conv_intrinsic_function): Update transpose
handling.
(walk_inline_intrinsic_transpose, walk_inline_intrinsic_function,
gfc_inline_intrinsic_function_p): New.
(gfc_is_intrinsic_libcall): Return early in inline intrinsic case.
Remove transpose from the libcall list.
(gfc_walk_intrinsic_function): Special case inline intrinsic.
* trans.h (gfc_inline_intrinsic_function_p): New prototype.
2010-09-10 Mikael Morin <mikael@gcc.gnu.org> 2010-09-10 Mikael Morin <mikael@gcc.gnu.org>
* trans-expr.c (expr_is_variable): New function taking non-copying * trans-expr.c (expr_is_variable): New function taking non-copying
......
...@@ -627,11 +627,15 @@ gfc_check_argument_var_dependency (gfc_expr *var, sym_intent intent, ...@@ -627,11 +627,15 @@ gfc_check_argument_var_dependency (gfc_expr *var, sym_intent intent,
return gfc_check_dependency (var, expr, 1); return gfc_check_dependency (var, expr, 1);
case EXPR_FUNCTION: case EXPR_FUNCTION:
if (intent != INTENT_IN && expr->inline_noncopying_intrinsic if (intent != INTENT_IN)
&& (arg = gfc_get_noncopying_intrinsic_argument (expr)) {
&& gfc_check_argument_var_dependency (var, intent, arg, elemental)) arg = gfc_get_noncopying_intrinsic_argument (expr);
return 1; if (arg != NULL)
if (elemental) return gfc_check_argument_var_dependency (var, intent, arg,
NOT_ELEMENTAL);
}
if (elemental != NOT_ELEMENTAL)
{ {
if ((expr->value.function.esym if ((expr->value.function.esym
&& expr->value.function.esym->attr.elemental) && expr->value.function.esym->attr.elemental)
...@@ -683,12 +687,11 @@ gfc_check_argument_dependency (gfc_expr *other, sym_intent intent, ...@@ -683,12 +687,11 @@ gfc_check_argument_dependency (gfc_expr *other, sym_intent intent,
return gfc_check_argument_var_dependency (other, intent, expr, elemental); return gfc_check_argument_var_dependency (other, intent, expr, elemental);
case EXPR_FUNCTION: case EXPR_FUNCTION:
if (other->inline_noncopying_intrinsic) other = gfc_get_noncopying_intrinsic_argument (other);
{ if (other != NULL)
other = gfc_get_noncopying_intrinsic_argument (other); return gfc_check_argument_dependency (other, INTENT_IN, expr,
return gfc_check_argument_dependency (other, INTENT_IN, expr, NOT_ELEMENTAL);
elemental);
}
return 0; return 0;
default: default:
...@@ -962,8 +965,9 @@ gfc_check_dependency (gfc_expr *expr1, gfc_expr *expr2, bool identical) ...@@ -962,8 +965,9 @@ gfc_check_dependency (gfc_expr *expr1, gfc_expr *expr2, bool identical)
return 1; return 1;
case EXPR_FUNCTION: case EXPR_FUNCTION:
if (expr2->inline_noncopying_intrinsic) if (gfc_get_noncopying_intrinsic_argument (expr2) != NULL)
identical = 1; identical = 1;
/* Remember possible differences between elemental and /* Remember possible differences between elemental and
transformational functions. All functions inside a FORALL transformational functions. All functions inside a FORALL
will be pure. */ will be pure. */
......
...@@ -1695,11 +1695,9 @@ typedef struct gfc_expr ...@@ -1695,11 +1695,9 @@ typedef struct gfc_expr
locus where; locus where;
/* True if the expression is a call to a function that returns an array, /* is_boz is true if the integer is regarded as BOZ bitpatten and is_snan
and if we have decided not to allocate temporary data for that array.
is_boz is true if the integer is regarded as BOZ bitpatten and is_snan
denotes a signalling not-a-number. */ denotes a signalling not-a-number. */
unsigned int inline_noncopying_intrinsic : 1, is_boz : 1, is_snan : 1; unsigned int is_boz : 1, is_snan : 1;
/* Sometimes, when an error has been emitted, it is necessary to prevent /* Sometimes, when an error has been emitted, it is necessary to prevent
it from recurring. */ it from recurring. */
......
...@@ -1916,25 +1916,6 @@ resolve_elemental_actual (gfc_expr *expr, gfc_code *c) ...@@ -1916,25 +1916,6 @@ resolve_elemental_actual (gfc_expr *expr, gfc_code *c)
} }
/* Go through each actual argument in ACTUAL and see if it can be
implemented as an inlined, non-copying intrinsic. FNSYM is the
function being called, or NULL if not known. */
static void
find_noncopying_intrinsics (gfc_symbol *fnsym, gfc_actual_arglist *actual)
{
gfc_actual_arglist *ap;
gfc_expr *expr;
for (ap = actual; ap; ap = ap->next)
if (ap->expr
&& (expr = gfc_get_noncopying_intrinsic_argument (ap->expr))
&& !gfc_check_fncall_dependency (expr, INTENT_IN, fnsym, actual,
NOT_ELEMENTAL))
ap->expr->inline_noncopying_intrinsic = 1;
}
/* This function does the checking of references to global procedures /* This function does the checking of references to global procedures
as defined in sections 18.1 and 14.1, respectively, of the Fortran as defined in sections 18.1 and 14.1, respectively, of the Fortran
77 and 95 standards. It checks for a gsymbol for the name, making 77 and 95 standards. It checks for a gsymbol for the name, making
...@@ -3115,15 +3096,6 @@ resolve_function (gfc_expr *expr) ...@@ -3115,15 +3096,6 @@ resolve_function (gfc_expr *expr)
gfc_expr_set_symbols_referenced (expr->ts.u.cl->length); gfc_expr_set_symbols_referenced (expr->ts.u.cl->length);
} }
if (t == SUCCESS
&& !((expr->value.function.esym
&& expr->value.function.esym->attr.elemental)
||
(expr->value.function.isym
&& expr->value.function.isym->elemental)))
find_noncopying_intrinsics (expr->value.function.esym,
expr->value.function.actual);
/* Make sure that the expression has a typespec that works. */ /* Make sure that the expression has a typespec that works. */
if (expr->ts.type == BT_UNKNOWN) if (expr->ts.type == BT_UNKNOWN)
{ {
...@@ -3602,8 +3574,6 @@ resolve_call (gfc_code *c) ...@@ -3602,8 +3574,6 @@ resolve_call (gfc_code *c)
if (resolve_elemental_actual (NULL, c) == FAILURE) if (resolve_elemental_actual (NULL, c) == FAILURE)
return FAILURE; return FAILURE;
if (t == SUCCESS && !(c->resolved_sym && c->resolved_sym->attr.elemental))
find_noncopying_intrinsics (c->resolved_sym, c->ext.actual);
return t; return t;
} }
......
...@@ -91,7 +91,6 @@ along with GCC; see the file COPYING3. If not see ...@@ -91,7 +91,6 @@ along with GCC; see the file COPYING3. If not see
#include "trans-const.h" #include "trans-const.h"
#include "dependency.h" #include "dependency.h"
static gfc_ss *gfc_walk_subexpr (gfc_ss *, gfc_expr *);
static bool gfc_get_array_constructor_size (mpz_t *, gfc_constructor_base); static bool gfc_get_array_constructor_size (mpz_t *, gfc_constructor_base);
/* The contents of this structure aren't actually used, just the address. */ /* The contents of this structure aren't actually used, just the address. */
...@@ -917,96 +916,6 @@ gfc_trans_create_temp_array (stmtblock_t * pre, stmtblock_t * post, ...@@ -917,96 +916,6 @@ gfc_trans_create_temp_array (stmtblock_t * pre, stmtblock_t * post,
} }
/* Generate code to transpose array EXPR by creating a new descriptor
in which the dimension specifications have been reversed. */
void
gfc_conv_array_transpose (gfc_se * se, gfc_expr * expr)
{
tree dest, src, dest_index, src_index;
gfc_loopinfo *loop;
gfc_ss_info *dest_info;
gfc_ss *dest_ss, *src_ss;
gfc_se src_se;
int n;
loop = se->loop;
src_ss = gfc_walk_expr (expr);
dest_ss = se->ss;
dest_info = &dest_ss->data.info;
gcc_assert (dest_info->dimen == 2);
/* Get a descriptor for EXPR. */
gfc_init_se (&src_se, NULL);
gfc_conv_expr_descriptor (&src_se, expr, src_ss);
gfc_add_block_to_block (&se->pre, &src_se.pre);
gfc_add_block_to_block (&se->post, &src_se.post);
src = src_se.expr;
/* Allocate a new descriptor for the return value. */
dest = gfc_create_var (TREE_TYPE (src), "transp");
dest_info->descriptor = dest;
se->expr = dest;
/* Copy across the dtype field. */
gfc_add_modify (&se->pre,
gfc_conv_descriptor_dtype (dest),
gfc_conv_descriptor_dtype (src));
/* Copy the dimension information, renumbering dimension 1 to 0 and
0 to 1. */
for (n = 0; n < 2; n++)
{
dest_info->delta[n] = gfc_index_zero_node;
dest_info->start[n] = gfc_index_zero_node;
dest_info->end[n] = gfc_index_zero_node;
dest_info->stride[n] = gfc_index_one_node;
dest_info->dim[n] = n;
dest_index = gfc_rank_cst[n];
src_index = gfc_rank_cst[1 - n];
gfc_conv_descriptor_stride_set (&se->pre, dest, dest_index,
gfc_conv_descriptor_stride_get (src, src_index));
gfc_conv_descriptor_lbound_set (&se->pre, dest, dest_index,
gfc_conv_descriptor_lbound_get (src, src_index));
gfc_conv_descriptor_ubound_set (&se->pre, dest, dest_index,
gfc_conv_descriptor_ubound_get (src, src_index));
if (!loop->to[n])
{
gcc_assert (integer_zerop (loop->from[n]));
loop->to[n] =
fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
gfc_conv_descriptor_ubound_get (dest, dest_index),
gfc_conv_descriptor_lbound_get (dest, dest_index));
}
}
/* Copy the data pointer. */
dest_info->data = gfc_conv_descriptor_data_get (src);
gfc_conv_descriptor_data_set (&se->pre, dest, dest_info->data);
/* Copy the offset. This is not changed by transposition; the top-left
element is still at the same offset as before, except where the loop
starts at zero. */
if (!integer_zerop (loop->from[0]))
dest_info->offset = gfc_conv_descriptor_offset_get (src);
else
dest_info->offset = gfc_index_zero_node;
gfc_conv_descriptor_offset_set (&se->pre, dest,
dest_info->offset);
if (dest_info->dimen > loop->temp_dim)
loop->temp_dim = dest_info->dimen;
}
/* Return the number of iterations in a loop that starts at START, /* Return the number of iterations in a loop that starts at START,
ends at END, and has step STEP. */ ends at END, and has step STEP. */
...@@ -6989,7 +6898,7 @@ gfc_walk_array_constructor (gfc_ss * ss, gfc_expr * expr) ...@@ -6989,7 +6898,7 @@ gfc_walk_array_constructor (gfc_ss * ss, gfc_expr * expr)
/* Walk an expression. Add walked expressions to the head of the SS chain. /* Walk an expression. Add walked expressions to the head of the SS chain.
A wholly scalar expression will not be added. */ A wholly scalar expression will not be added. */
static gfc_ss * gfc_ss *
gfc_walk_subexpr (gfc_ss * ss, gfc_expr * expr) gfc_walk_subexpr (gfc_ss * ss, gfc_expr * expr)
{ {
gfc_ss *head; gfc_ss *head;
......
...@@ -64,6 +64,8 @@ void gfc_trans_static_array_pointer (gfc_symbol *); ...@@ -64,6 +64,8 @@ void gfc_trans_static_array_pointer (gfc_symbol *);
/* Generate scalarization information for an expression. */ /* Generate scalarization information for an expression. */
gfc_ss *gfc_walk_expr (gfc_expr *); gfc_ss *gfc_walk_expr (gfc_expr *);
/* Workhorse for gfc_walk_expr. */
gfc_ss *gfc_walk_subexpr (gfc_ss *, gfc_expr *);
/* Walk the arguments of an elemental function. */ /* Walk the arguments of an elemental function. */
gfc_ss *gfc_walk_elemental_function_args (gfc_ss *, gfc_actual_arglist *, gfc_ss *gfc_walk_elemental_function_args (gfc_ss *, gfc_actual_arglist *,
gfc_ss_type); gfc_ss_type);
......
...@@ -5583,7 +5583,7 @@ gfc_conv_intrinsic_function (gfc_se * se, gfc_expr * expr) ...@@ -5583,7 +5583,7 @@ gfc_conv_intrinsic_function (gfc_se * se, gfc_expr * expr)
name = &expr->value.function.name[2]; name = &expr->value.function.name[2];
if (expr->rank > 0 && !expr->inline_noncopying_intrinsic) if (expr->rank > 0)
{ {
lib = gfc_is_intrinsic_libcall (expr); lib = gfc_is_intrinsic_libcall (expr);
if (lib != 0) if (lib != 0)
...@@ -5957,13 +5957,9 @@ gfc_conv_intrinsic_function (gfc_se * se, gfc_expr * expr) ...@@ -5957,13 +5957,9 @@ gfc_conv_intrinsic_function (gfc_se * se, gfc_expr * expr)
break; break;
case GFC_ISYM_TRANSPOSE: case GFC_ISYM_TRANSPOSE:
if (se->ss && se->ss->useflags) /* The scalarizer has already been set up for reversed dimension access
{ order ; now we just get the argument value normally. */
gfc_conv_tmp_array_ref (se); gfc_conv_expr (se, expr->value.function.actual->expr);
gfc_advance_se_ss_chain (se);
}
else
gfc_conv_array_transpose (se, expr->value.function.actual->expr);
break; break;
case GFC_ISYM_LEN: case GFC_ISYM_LEN:
...@@ -6188,6 +6184,64 @@ gfc_conv_intrinsic_function (gfc_se * se, gfc_expr * expr) ...@@ -6188,6 +6184,64 @@ gfc_conv_intrinsic_function (gfc_se * se, gfc_expr * expr)
} }
static gfc_ss *
walk_inline_intrinsic_transpose (gfc_ss *ss, gfc_expr *expr)
{
gfc_ss *arg_ss, *tmp_ss;
gfc_actual_arglist *arg;
arg = expr->value.function.actual;
gcc_assert (arg->expr);
arg_ss = gfc_walk_subexpr (gfc_ss_terminator, arg->expr);
gcc_assert (arg_ss != gfc_ss_terminator);
for (tmp_ss = arg_ss; ; tmp_ss = tmp_ss->next)
{
if (tmp_ss->type != GFC_SS_SCALAR
&& tmp_ss->type != GFC_SS_REFERENCE)
{
int tmp_dim;
gfc_ss_info *info;
info = &tmp_ss->data.info;
gcc_assert (info->dimen == 2);
/* We just invert dimensions. */
tmp_dim = info->dim[0];
info->dim[0] = info->dim[1];
info->dim[1] = tmp_dim;
}
/* Stop when tmp_ss points to the last valid element of the chain... */
if (tmp_ss->next == gfc_ss_terminator)
break;
}
/* ... so that we can attach the rest of the chain to it. */
tmp_ss->next = ss;
return arg_ss;
}
static gfc_ss *
walk_inline_intrinsic_function (gfc_ss * ss, gfc_expr * expr)
{
switch (expr->value.function.isym->id)
{
case GFC_ISYM_TRANSPOSE:
return walk_inline_intrinsic_transpose (ss, expr);
default:
gcc_unreachable ();
}
gcc_unreachable ();
}
/* This generates code to execute before entering the scalarization loop. /* This generates code to execute before entering the scalarization loop.
Currently does nothing. */ Currently does nothing. */
...@@ -6250,6 +6304,26 @@ gfc_walk_intrinsic_libfunc (gfc_ss * ss, gfc_expr * expr) ...@@ -6250,6 +6304,26 @@ gfc_walk_intrinsic_libfunc (gfc_ss * ss, gfc_expr * expr)
} }
/* Return whether the function call expression EXPR will be expanded
inline by gfc_conv_intrinsic_function. */
bool
gfc_inline_intrinsic_function_p (gfc_expr *expr)
{
if (!expr->value.function.isym)
return false;
switch (expr->value.function.isym->id)
{
case GFC_ISYM_TRANSPOSE:
return true;
default:
return false;
}
}
/* Returns nonzero if the specified intrinsic function call maps directly to /* Returns nonzero if the specified intrinsic function call maps directly to
an external library call. Should only be used for functions that return an external library call. Should only be used for functions that return
arrays. */ arrays. */
...@@ -6260,6 +6334,9 @@ gfc_is_intrinsic_libcall (gfc_expr * expr) ...@@ -6260,6 +6334,9 @@ gfc_is_intrinsic_libcall (gfc_expr * expr)
gcc_assert (expr->expr_type == EXPR_FUNCTION && expr->value.function.isym); gcc_assert (expr->expr_type == EXPR_FUNCTION && expr->value.function.isym);
gcc_assert (expr->rank > 0); gcc_assert (expr->rank > 0);
if (gfc_inline_intrinsic_function_p (expr))
return 0;
switch (expr->value.function.isym->id) switch (expr->value.function.isym->id)
{ {
case GFC_ISYM_ALL: case GFC_ISYM_ALL:
...@@ -6280,7 +6357,6 @@ gfc_is_intrinsic_libcall (gfc_expr * expr) ...@@ -6280,7 +6357,6 @@ gfc_is_intrinsic_libcall (gfc_expr * expr)
case GFC_ISYM_SUM: case GFC_ISYM_SUM:
case GFC_ISYM_SHAPE: case GFC_ISYM_SHAPE:
case GFC_ISYM_SPREAD: case GFC_ISYM_SPREAD:
case GFC_ISYM_TRANSPOSE:
case GFC_ISYM_YN2: case GFC_ISYM_YN2:
/* Ignore absent optional parameters. */ /* Ignore absent optional parameters. */
return 1; return 1;
...@@ -6306,11 +6382,15 @@ gfc_walk_intrinsic_function (gfc_ss * ss, gfc_expr * expr, ...@@ -6306,11 +6382,15 @@ gfc_walk_intrinsic_function (gfc_ss * ss, gfc_expr * expr,
gcc_assert (isym); gcc_assert (isym);
if (isym->elemental) if (isym->elemental)
return gfc_walk_elemental_function_args (ss, expr->value.function.actual, GFC_SS_SCALAR); return gfc_walk_elemental_function_args (ss, expr->value.function.actual,
GFC_SS_SCALAR);
if (expr->rank == 0) if (expr->rank == 0)
return ss; return ss;
if (gfc_inline_intrinsic_function_p (expr))
return walk_inline_intrinsic_function (ss, expr);
if (gfc_is_intrinsic_libcall (expr)) if (gfc_is_intrinsic_libcall (expr))
return gfc_walk_intrinsic_libfunc (ss, expr); return gfc_walk_intrinsic_libfunc (ss, expr);
......
...@@ -345,7 +345,12 @@ tree gfc_builtin_decl_for_float_kind (enum built_in_function, int); ...@@ -345,7 +345,12 @@ tree gfc_builtin_decl_for_float_kind (enum built_in_function, int);
/* Intrinsic function handling. */ /* Intrinsic function handling. */
void gfc_conv_intrinsic_function (gfc_se *, gfc_expr *); void gfc_conv_intrinsic_function (gfc_se *, gfc_expr *);
/* Does an intrinsic map directly to an external library call. */ /* Is the intrinsic expanded inline. */
bool gfc_inline_intrinsic_function_p (gfc_expr *);
/* Does an intrinsic map directly to an external library call
This is true for array-returning intrinsics, unless
gfc_inline_intrinsic_function_p returns true. */
int gfc_is_intrinsic_libcall (gfc_expr *); int gfc_is_intrinsic_libcall (gfc_expr *);
tree gfc_conv_intrinsic_move_alloc (gfc_code *); tree gfc_conv_intrinsic_move_alloc (gfc_code *);
......
2010-09-11 Mikael Morin <mikael@gcc.gnu.org>
* gfortran.dg/inline_transpose_1.f90: Update temporary's locations
and counts. Check that transpose is not called.
* gfortran.dg/transpose_2.f90: Update error message.
2010-09-10 Rodrigo Rivas Costa <rodrigorivascosta@gmail.com> 2010-09-10 Rodrigo Rivas Costa <rodrigorivascosta@gmail.com>
PR c++/43824 PR c++/43824
......
! { dg-do run } ! { dg-do run }
! { dg-options "-fdump-tree-original -Warray-temporaries" } ! { dg-options "-fdump-tree-original -fdump-tree-optimized -Warray-temporaries -fbounds-check" }
implicit none implicit none
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
c = transpose(a) c = transpose(a)
if (any(c /= q)) call abort if (any(c /= q)) call abort
write(u,*) transpose(a) ! Unnecessary { dg-warning "Creating array temporary" } write(u,*) transpose(a)
write(v,*) q write(v,*) q
if (u /= v) call abort if (u /= v) call abort
...@@ -37,10 +37,10 @@ ...@@ -37,10 +37,10 @@
e = r e = r
f = s f = s
g = transpose(e+f) ! Unnecessary { dg-warning "Creating array temporary" } g = transpose(e+f)
if (any(g /= r + s)) call abort if (any(g /= r + s)) call abort
write(u,*) transpose(e+f) ! 2 Unnecessary temps { dg-warning "Creating array temporary" } write(u,*) transpose(e+f)
write(v,*) r + s write(v,*) r + s
if (u /= v) call abort if (u /= v) call abort
...@@ -48,7 +48,7 @@ ...@@ -48,7 +48,7 @@
e = transpose(e) ! { dg-warning "Creating array temporary" } e = transpose(e) ! { dg-warning "Creating array temporary" }
if (any(e /= s)) call abort if (any(e /= s)) call abort
write(u,*) transpose(transpose(e)) ! Unnecessary { dg-warning "Creating array temporary" } write(u,*) transpose(transpose(e))
write(v,*) s write(v,*) s
if (u /= v) call abort if (u /= v) call abort
...@@ -56,15 +56,15 @@ ...@@ -56,15 +56,15 @@
e = transpose(e+f) ! { dg-warning "Creating array temporary" } e = transpose(e+f) ! { dg-warning "Creating array temporary" }
if (any(e /= 2*r)) call abort if (any(e /= 2*r)) call abort
write(u,*) transpose(transpose(e+f))-f ! 2 Unnecessary temps { dg-warning "Creating array temporary" } write(u,*) transpose(transpose(e+f))-f
write(v,*) 2*r write(v,*) 2*r
if (u /= v) call abort if (u /= v) call abort
a = foo(transpose(c)) a = foo(transpose(c)) ! Unnecessary { dg-warning "Creating array temporary" }
if (any(a /= p+1)) call abort if (any(a /= p+1)) call abort
write(u,*) foo(transpose(c)) ! { dg-warning "Creating array temporary" } write(u,*) foo(transpose(c)) ! 2 temps, should be 1 { dg-warning "Creating array temporary" }
write(v,*) p+1 write(v,*) p+1
if (u /= v) call abort if (u /= v) call abort
...@@ -72,15 +72,15 @@ ...@@ -72,15 +72,15 @@
c = transpose(foo(a)) ! Unnecessary { dg-warning "Creating array temporary" } c = transpose(foo(a)) ! Unnecessary { dg-warning "Creating array temporary" }
if (any(c /= q+2)) call abort if (any(c /= q+2)) call abort
write(u,*) transpose(foo(a)) ! 2 temps, should be 1 { dg-warning "Creating array temporary" } write(u,*) transpose(foo(a)) ! { dg-warning "Creating array temporary" }
write(v,*) q+2 write(v,*) q+2
if (u /= v) call abort if (u /= v) call abort
e = foo(transpose(e)) ! { dg-warning "Creating array temporary" } e = foo(transpose(e)) ! 2 temps, should be 1 { dg-warning "Creating array temporary" }
if (any(e /= 2*s+1)) call abort if (any(e /= 2*s+1)) call abort
write(u,*) transpose(foo(transpose(e))-1) ! 3 temps, should be 1 { dg-warning "Creating array temporary" } write(u,*) transpose(foo(transpose(e))-1) ! 2 temps, should be 1 { dg-warning "Creating array temporary" }
write(v,*) 2*s+1 write(v,*) 2*s+1
if (u /= v) call abort if (u /= v) call abort
...@@ -88,23 +88,23 @@ ...@@ -88,23 +88,23 @@
e = transpose(foo(e)) ! { dg-warning "Creating array temporary" } e = transpose(foo(e)) ! { dg-warning "Creating array temporary" }
if (any(e /= 2*r+2)) call abort if (any(e /= 2*r+2)) call abort
write(u,*) transpose(foo(transpose(e)-1)) ! 4 temps, should be 2 { dg-warning "Creating array temporary" } write(u,*) transpose(foo(transpose(e)-1)) ! 2 temps { dg-warning "Creating array temporary" }
write(v,*) 2*r+2 write(v,*) 2*r+2
if (u /= v) call abort if (u /= v) call abort
a = bar(transpose(c)) ! Unnecessary { dg-warning "Creating array temporary" } a = bar(transpose(c))
if (any(a /= p+4)) call abort if (any(a /= p+4)) call abort
write(u,*) bar(transpose(c)) ! Unnecessary { dg-warning "Creating array temporary" } write(u,*) bar(transpose(c))
write(v,*) p+4 write(v,*) p+4
if (u /= v) call abort if (u /= v) call abort
c = transpose(bar(a)) ! Unnecessary { dg-warning "Creating array temporary" } c = transpose(bar(a))
if (any(c /= q+6)) call abort if (any(c /= q+6)) call abort
write(u,*) transpose(bar(a)) ! 2 Unnecessary temps { dg-warning "Creating array temporary" } write(u,*) transpose(bar(a))
write(v,*) q+6 write(v,*) q+6
if (u /= v) call abort if (u /= v) call abort
...@@ -112,7 +112,7 @@ ...@@ -112,7 +112,7 @@
e = bar(transpose(e)) ! { dg-warning "Creating array temporary" } e = bar(transpose(e)) ! { dg-warning "Creating array temporary" }
if (any(e /= 2*s+4)) call abort if (any(e /= 2*s+4)) call abort
write(u,*) transpose(bar(transpose(e)))-2 ! 3 Unnecessary temps { dg-warning "Creating array temporary" } write(u,*) transpose(bar(transpose(e)))-2
write(v,*) 2*s+4 write(v,*) 2*s+4
if (u /= v) call abort if (u /= v) call abort
...@@ -120,44 +120,44 @@ ...@@ -120,44 +120,44 @@
e = transpose(bar(e)) ! { dg-warning "Creating array temporary" } e = transpose(bar(e)) ! { dg-warning "Creating array temporary" }
if (any(e /= 2*r+6)) call abort if (any(e /= 2*r+6)) call abort
write(u,*) transpose(transpose(bar(e))-2) ! 4 Unnecessary temps { dg-warning "Creating array temporary" } write(u,*) transpose(transpose(bar(e))-2)
write(v,*) 2*r+6 write(v,*) 2*r+6
if (u /= v) call abort if (u /= v) call abort
if (any(a /= transpose(transpose(a)))) call abort ! Unnecessary { dg-warning "Creating array temporary" } if (any(a /= transpose(transpose(a)))) call abort ! optimized away
write(u,*) a write(u,*) a
write(v,*) transpose(transpose(a)) ! Unnecessary { dg-warning "Creating array temporary" } write(v,*) transpose(transpose(a))
if (u /= v) call abort if (u /= v) call abort
b = a * a b = a * a
if (any(transpose(a+b) /= transpose(a)+transpose(b))) call abort ! 4 unnecessary temps { dg-warning "Creating array temporary" } if (any(transpose(a+b) /= transpose(a)+transpose(b))) call abort ! optimized away
write(u,*) transpose(a+b) ! 2 unnecessary temps { dg-warning "Creating array temporary" } write(u,*) transpose(a+b)
write(v,*) transpose(a) + transpose(b) ! 2 unnecessary temps { dg-warning "Creating array temporary" } write(v,*) transpose(a) + transpose(b)
if (u /= v) call abort if (u /= v) call abort
if (any(transpose(matmul(a,c)) /= matmul(transpose(c), transpose(a)))) call abort ! 3 temps, should be 2 { dg-warning "Creating array temporary" } if (any(transpose(matmul(a,c)) /= matmul(transpose(c), transpose(a)))) call abort ! 4 temps, should be 2 { dg-warning "Creating array temporary" }
write(u,*) transpose(matmul(a,c)) ! 2 temps, should be 1 { dg-warning "Creating array temporary" } write(u,*) transpose(matmul(a,c)) ! { dg-warning "Creating array temporary" }
write(v,*) matmul(transpose(c), transpose(a)) ! { dg-warning "Creating array temporary" } write(v,*) matmul(transpose(c), transpose(a)) ! 3 temps, should be 1 { dg-warning "Creating array temporary" }
if (u /= v) call abort if (u /= v) call abort
if (any(transpose(matmul(e,a)) /= matmul(transpose(a), transpose(e)))) call abort ! 3 temps, should be 2 { dg-warning "Creating array temporary" } if (any(transpose(matmul(e,a)) /= matmul(transpose(a), transpose(e)))) call abort ! 4 temps, should be 2 { dg-warning "Creating array temporary" }
write(u,*) transpose(matmul(e,a)) ! 2 temps, should be 1 { dg-warning "Creating array temporary" } write(u,*) transpose(matmul(e,a)) ! { dg-warning "Creating array temporary" }
write(v,*) matmul(transpose(a), transpose(e)) ! { dg-warning "Creating array temporary" } write(v,*) matmul(transpose(a), transpose(e)) ! 3 temps, should be 1 { dg-warning "Creating array temporary" }
if (u /= v) call abort if (u /= v) call abort
call baz (transpose(a)) call baz (transpose(a)) ! Unnecessary { dg-warning "Creating array temporary" }
call toto (f, transpose (e)) ! Unnecessary { dg-warning "Creating array temporary" } call toto (f, transpose (e))
if (any (f /= 4 * s + 12)) call abort if (any (f /= 4 * s + 12)) call abort
call toto (f, transpose (f)) ! { dg-warning "Creating array temporary" } call toto (f, transpose (f)) ! { dg-warning "Creating array temporary" }
...@@ -189,5 +189,16 @@ ...@@ -189,5 +189,16 @@
end subroutine toto end subroutine toto
end end
! { dg-final { scan-tree-dump-times "struct\[^\\n\]*atmp" 60 "original" } } ! No call to transpose
! { dg-final { cleanup-tree-dump "original" } } ! { dg-final { scan-tree-dump-times "_gfortran_transpose" 0 "original" } }
!
! 34 temporaries
! { dg-final { scan-tree-dump-times "struct\[^\\n\]*atmp" 34 "original" } }
!
! 2 tests optimized out
! { dg-final { scan-tree-dump-times "_gfortran_abort" 34 "original" } }
! { # Commented out as failing at -O0: dg-final { scan-tree-dump-times "_gfortran_abort" 32 "optimized" } }
!
! cleanup
! { #dg-final { cleanup-tree-dump "original" } }
! { dg-final { cleanup-tree-dump "optimized" } }
...@@ -15,4 +15,5 @@ program main ...@@ -15,4 +15,5 @@ program main
b = 2.1 b = 2.1
b = transpose(a) b = transpose(a)
end program main end program main
! { dg-output "Fortran runtime error: Incorrect extent in return value of TRANSPOSE intrinsic in dimension 1: is 2, should be 3" } ! { dg-output "Fortran runtime error: Array bound mismatch for dimension 1 of
! array 'b' (3/2)" }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment