From: Thomas Koenig Date: Thu, 17 Dec 2020 14:58:45 +0000 (+0100) Subject: Use __builtin_atomic_thread_fence and implement SYNC_MEMORY. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d91352b42efcb2a81039ab1911d4fda414143ddb;p=thirdparty%2Fgcc.git Use __builtin_atomic_thread_fence and implement SYNC_MEMORY. gcc/fortran/ChangeLog: * trans.c (gfc_trans_memory_barrier_fence): New function. * trans.h (gfc_trans_memory_barrier_fence): Prototype it. * trans-stmt.c (gfc_trans_sync): For shared coarrays, use memory fence. Don't do anything else for SYNC MEMORY. gcc/testsuite/ChangeLog: * gfortran.dg/caf-shared/sync_all_1.f90: New test. * gfortran.dg/caf-shared/sync_memory_1.f90: New test. --- diff --git a/gcc/fortran/trans-stmt.c b/gcc/fortran/trans-stmt.c index 368165e69f94..8db4333457c7 100644 --- a/gcc/fortran/trans-stmt.c +++ b/gcc/fortran/trans-stmt.c @@ -1307,11 +1307,16 @@ gfc_trans_sync (gfc_code *code, gfc_exec_op type) /* Per F2008, 8.5.1, a SYNC MEMORY is implied by calling the image control statements SYNC IMAGES and SYNC ALL. */ - if (flag_coarray == GFC_FCOARRAY_LIB || flag_coarray == GFC_FCOARRAY_SHARED) + if (flag_coarray == GFC_FCOARRAY_LIB) { tmp = gfc_trans_memory_barrier (); gfc_add_expr_to_block (&se.pre, tmp); } + else if (flag_coarray == GFC_FCOARRAY_SHARED) + { + tmp = gfc_trans_memory_barrier_fence (); + gfc_add_expr_to_block (&se.pre, tmp); + } if (flag_coarray != GFC_FCOARRAY_LIB && flag_coarray != GFC_FCOARRAY_SHARED) { @@ -1332,8 +1337,16 @@ gfc_trans_sync (gfc_code *code, gfc_exec_op type) stat = gfc_build_addr_expr (NULL, stat); if(type == EXEC_SYNC_MEMORY) - tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_memory, - 3, stat, errmsg, errmsglen); + { + /* For shared coarrays, there is no need for a memory + fence here because that is emitted anyway below. */ + if (flag_coarray != GFC_FCOARRAY_SHARED) + tmp = build_call_expr_loc (input_location, + gfor_fndecl_caf_sync_memory, + 3, stat, errmsg, errmsglen); + else + tmp = NULL_TREE; + } else { if (flag_coarray == GFC_FCOARRAY_LIB) @@ -1343,8 +1356,8 @@ gfc_trans_sync (gfc_code *code, gfc_exec_op type) tmp = build_call_expr_loc (input_location, gfor_fndecl_cas_sync_all, 1, stat); } - - gfc_add_expr_to_block (&se.pre, tmp); + if (tmp != NULL_TREE) + gfc_add_expr_to_block (&se.pre, tmp); } else { diff --git a/gcc/fortran/trans.c b/gcc/fortran/trans.c index aa30710d51d3..fa7fd9d88aae 100644 --- a/gcc/fortran/trans.c +++ b/gcc/fortran/trans.c @@ -34,6 +34,7 @@ along with GCC; see the file COPYING3. If not see #include "trans-types.h" #include "trans-const.h" #include "diagnostic-core.h" +#include "memmodel.h" /* For MEMMODEL_ enums. */ /* Naming convention for backend interface code: @@ -49,6 +50,7 @@ const char gfc_msg_fault[] = N_("Array reference out of bounds"); const char gfc_msg_wrong_return[] = N_("Incorrect function return value"); /* Insert a memory barrier into the code. */ + tree gfc_trans_memory_barrier (void) { @@ -63,6 +65,20 @@ gfc_trans_memory_barrier (void) return tmp; } +/* Same as above, but do it by calling + __builtin_atomic_thread_fence. */ + +tree +gfc_trans_memory_barrier_fence (void) +{ + tree call, mode; + call = builtin_decl_explicit (BUILT_IN_ATOMIC_THREAD_FENCE); + mode = build_int_cst (integer_type_node, MEMMODEL_ACQ_REL); + call = build_call_expr_loc (input_location, call, 1, mode); + return call; +} + + /* Return a location_t suitable for 'tree' for a gfortran locus. The way the parser works in gfortran, loc->lb->location contains only the line number and LOCATION_COLUMN is 0; hence, the column has to be added when generating diff --git a/gcc/fortran/trans.h b/gcc/fortran/trans.h index eef90f647a0a..95e4741906c9 100644 --- a/gcc/fortran/trans.h +++ b/gcc/fortran/trans.h @@ -504,6 +504,7 @@ void gfc_conv_expr_type (gfc_se * se, gfc_expr *, tree); /* Insert a memory barrier into the code. */ tree gfc_trans_memory_barrier (void); +tree gfc_trans_memory_barrier_fence (void); /* trans-expr.c */ tree gfc_conv_scalar_to_descriptor (gfc_se *, tree, symbol_attribute); diff --git a/gcc/testsuite/gfortran.dg/caf-shared/sync_all_1.f90 b/gcc/testsuite/gfortran.dg/caf-shared/sync_all_1.f90 new file mode 100644 index 000000000000..95343f548189 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/caf-shared/sync_all_1.f90 @@ -0,0 +1,9 @@ +! { dg-do compile } +! { dg-options "-fdump-tree-original" } +program main + sync all +end program main +! { dg-final { scan-tree-dump-times "__atomic_thread_fence \\(4\\)" 1 "original" } } +! { dg-final { scan-tree-dump-times "_gfortran_cas_coarray_sync_all" 1 "original" } } + + diff --git a/gcc/testsuite/gfortran.dg/caf-shared/sync_memory_1.f90 b/gcc/testsuite/gfortran.dg/caf-shared/sync_memory_1.f90 new file mode 100644 index 000000000000..25a7dcc421e1 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/caf-shared/sync_memory_1.f90 @@ -0,0 +1,6 @@ +! { dg-do compile } +! { dg-options "-fdump-tree-original" } +program main + sync memory +end program main +! { dg-final { scan-tree-dump-times "__atomic_thread_fence \\(4\\)" 1 "original" } }