2015-03-09 Alessandro Fanfarillo fanfarillo.gcc@gmail.com trans-decl.c: Add function declaration caf_sync_memory trans.h: Ditto trans-stmt.c: Add caf_sync_memory invocation coarray_38.f90: Test case single.c: caf_sync_memory implementation libcaf.h: caf_sync_memory prototype diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c index 3664824..a66c25c 100644 --- a/gcc/fortran/trans-decl.c +++ b/gcc/fortran/trans-decl.c @@ -153,6 +153,7 @@ tree gfor_fndecl_caf_get; tree gfor_fndecl_caf_send; tree gfor_fndecl_caf_sendget; tree gfor_fndecl_caf_sync_all; +tree gfor_fndecl_caf_sync_memory; tree gfor_fndecl_caf_sync_images; tree gfor_fndecl_caf_error_stop; tree gfor_fndecl_caf_error_stop_str; @@ -3451,6 +3452,10 @@ gfc_build_builtin_function_decls (void) get_identifier (PREFIX("caf_sync_all")), ".WW", void_type_node, 3, pint_type, pchar_type_node, integer_type_node); + gfor_fndecl_caf_sync_memory = gfc_build_library_function_decl_with_spec ( + get_identifier (PREFIX("caf_sync_memory")), ".WW", void_type_node, + 3, pint_type, pchar_type_node, integer_type_node); + gfor_fndecl_caf_sync_images = gfc_build_library_function_decl_with_spec ( get_identifier (PREFIX("caf_sync_images")), ".RRWW", void_type_node, 5, integer_type_node, pint_type, pint_type, diff --git a/gcc/fortran/trans-stmt.c b/gcc/fortran/trans-stmt.c index 505f905..dce0e87 100644 --- a/gcc/fortran/trans-stmt.c +++ b/gcc/fortran/trans-stmt.c @@ -768,8 +768,7 @@ gfc_trans_sync (gfc_code *code, gfc_exec_op type) else stat = null_pointer_node; - if (code->expr3 && flag_coarray == GFC_FCOARRAY_LIB - && type != EXEC_SYNC_MEMORY) + if (code->expr3 && flag_coarray == GFC_FCOARRAY_LIB) { gcc_assert (code->expr3->expr_type == EXPR_VARIABLE); gfc_init_se (&argse, NULL); @@ -778,7 +777,7 @@ gfc_trans_sync (gfc_code *code, gfc_exec_op type) errmsg = gfc_build_addr_expr (NULL, argse.expr); errmsglen = argse.string_length; } - else if (flag_coarray == GFC_FCOARRAY_LIB && type != EXEC_SYNC_MEMORY) + else if (flag_coarray == GFC_FCOARRAY_LIB) { errmsg = null_pointer_node; errmsglen = build_int_cst (integer_type_node, 0); @@ -822,13 +821,13 @@ gfc_trans_sync (gfc_code *code, gfc_exec_op type) gfc_add_expr_to_block (&se.pre, tmp); } - if (flag_coarray != GFC_FCOARRAY_LIB || type == EXEC_SYNC_MEMORY) + if (flag_coarray != GFC_FCOARRAY_LIB) { /* Set STAT to zero. */ if (code->expr2) gfc_add_modify (&se.pre, stat, build_int_cst (TREE_TYPE (stat), 0)); } - else if (type == EXEC_SYNC_ALL) + else if (type == EXEC_SYNC_ALL || type == EXEC_SYNC_MEMORY) { /* SYNC ALL => stat == null_pointer_node SYNC ALL(stat=s) => stat has an integer type @@ -840,8 +839,13 @@ gfc_trans_sync (gfc_code *code, gfc_exec_op type) if (TREE_TYPE (stat) == integer_type_node) stat = gfc_build_addr_expr (NULL, stat); - tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_all, - 3, stat, errmsg, errmsglen); + if(type == EXEC_SYNC_MEMORY) + tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_memory, + 3, stat, errmsg, errmsglen); + else + tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_all, + 3, stat, errmsg, errmsglen); + gfc_add_expr_to_block (&se.pre, tmp); } else diff --git a/gcc/fortran/trans.h b/gcc/fortran/trans.h index bd1520a..3ba2f88 100644 --- a/gcc/fortran/trans.h +++ b/gcc/fortran/trans.h @@ -731,6 +731,7 @@ extern GTY(()) tree gfor_fndecl_caf_get; extern GTY(()) tree gfor_fndecl_caf_send; extern GTY(()) tree gfor_fndecl_caf_sendget; extern GTY(()) tree gfor_fndecl_caf_sync_all; +extern GTY(()) tree gfor_fndecl_caf_sync_memory; extern GTY(()) tree gfor_fndecl_caf_sync_images; extern GTY(()) tree gfor_fndecl_caf_error_stop; extern GTY(()) tree gfor_fndecl_caf_error_stop_str; diff --git a/gcc/testsuite/gfortran.dg/coarray_38.f90 b/gcc/testsuite/gfortran.dg/coarray_38.f90 new file mode 100644 index 0000000..01b5b31 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/coarray_38.f90 @@ -0,0 +1,11 @@ +! { dg-do compile } +! { dg-options "-fcoarray=lib -fdump-tree-original" } +! +! Coarray sync memory managed by external library +! +implicit none +integer :: n +sync memory +end +! { dg-final { scan-tree-dump-times "_gfortran_caf_sync_memory \\(0B, 0B, 0\\);" 1 "original" } } +! { dg-final { cleanup-tree-dump "original" } } diff --git a/libgfortran/caf/libcaf.h b/libgfortran/caf/libcaf.h index bd5c9c6..27e0d62 100644 --- a/libgfortran/caf/libcaf.h +++ b/libgfortran/caf/libcaf.h @@ -99,6 +99,7 @@ void *_gfortran_caf_register (size_t, caf_register_t, caf_token_t *, int *, char *, int); void _gfortran_caf_deregister (caf_token_t *, int *, char *, int); +void _gfortran_caf_sync_memory(int *, char *, int); void _gfortran_caf_sync_all (int *, char *, int); void _gfortran_caf_sync_images (int, int[], int *, char *, int); diff --git a/libgfortran/caf/single.c b/libgfortran/caf/single.c index 7405c91..8eb61c3 100644 --- a/libgfortran/caf/single.c +++ b/libgfortran/caf/single.c @@ -156,6 +156,17 @@ _gfortran_caf_deregister (caf_token_t *token, int *stat, *stat = 0; } +void +_gfortran_caf_sync_memory(int *stat, + char *errmsg __attribute__ ((unused)), + int errmsg_len __attribute__ ((unused))) +{ + if (stat) + *stat = 0; + + asm volatile("" ::: "memory"); +} + void _gfortran_caf_sync_all (int *stat,