From ba1cc6956b956eb5b92c45af79a8b1fe426ec4d3 Mon Sep 17 00:00:00 2001 From: Marcel Vollweiler Date: Tue, 7 Sep 2021 03:46:28 -0700 Subject: [PATCH] C, C++, Fortran, OpenMP: Add support for 'flush seq_cst' construct. This patch adds support for the 'seq_cst' memory order clause on the 'flush' directive which was introduced in OpenMP 5.1. gcc/c-family/ChangeLog: * c-omp.c (c_finish_omp_flush): Handle MEMMODEL_SEQ_CST. gcc/c/ChangeLog: * c-parser.c (c_parser_omp_flush): Parse 'seq_cst' clause on 'flush' directive. gcc/cp/ChangeLog: * parser.c (cp_parser_omp_flush): Parse 'seq_cst' clause on 'flush' directive. * semantics.c (finish_omp_flush): Handle MEMMODEL_SEQ_CST. gcc/fortran/ChangeLog: * openmp.c (gfc_match_omp_flush): Parse 'seq_cst' clause on 'flush' directive. * trans-openmp.c (gfc_trans_omp_flush): Handle OMP_MEMORDER_SEQ_CST. gcc/testsuite/ChangeLog: * c-c++-common/gomp/flush-1.c: Add test case for 'seq_cst'. * c-c++-common/gomp/flush-2.c: Add test case for 'seq_cst'. * g++.dg/gomp/attrs-1.C: Adapt test to handle all flush clauses. * g++.dg/gomp/attrs-2.C: Adapt test to handle all flush clauses. * gfortran.dg/gomp/flush-1.f90: Add test case for 'seq_cst'. * gfortran.dg/gomp/flush-2.f90: Add test case for 'seq_cst'. --- gcc/c-family/c-omp.c | 2 +- gcc/c/c-parser.c | 7 +++++-- gcc/cp/parser.c | 7 +++++-- gcc/cp/semantics.c | 2 +- gcc/fortran/openmp.c | 6 ++++-- gcc/fortran/trans-openmp.c | 3 ++- gcc/testsuite/c-c++-common/gomp/flush-1.c | 9 +++++++++ gcc/testsuite/c-c++-common/gomp/flush-2.c | 7 ++++--- gcc/testsuite/g++.dg/gomp/attrs-1.C | 6 ++++++ gcc/testsuite/g++.dg/gomp/attrs-2.C | 6 ++++++ gcc/testsuite/gfortran.dg/gomp/flush-1.f90 | 8 ++++++++ gcc/testsuite/gfortran.dg/gomp/flush-2.f90 | 9 +++++---- 12 files changed, 56 insertions(+), 16 deletions(-) diff --git a/gcc/c-family/c-omp.c b/gcc/c-family/c-omp.c index 18de7e4..4b95fc1 100644 --- a/gcc/c-family/c-omp.c +++ b/gcc/c-family/c-omp.c @@ -606,7 +606,7 @@ c_finish_omp_flush (location_t loc, int mo) { tree x; - if (mo == MEMMODEL_LAST) + if (mo == MEMMODEL_LAST || mo == MEMMODEL_SEQ_CST) { x = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE); x = build_call_expr_loc (loc, x, 0); diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index 3b1d10f..4d074ec 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -18339,7 +18339,9 @@ c_parser_omp_flush (c_parser *parser) const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); - if (!strcmp (p, "acq_rel")) + if (!strcmp (p, "seq_cst")) + mo = MEMMODEL_SEQ_CST; + else if (!strcmp (p, "acq_rel")) mo = MEMMODEL_ACQ_REL; else if (!strcmp (p, "release")) mo = MEMMODEL_RELEASE; @@ -18347,7 +18349,8 @@ c_parser_omp_flush (c_parser *parser) mo = MEMMODEL_ACQUIRE; else error_at (c_parser_peek_token (parser)->location, - "expected %, % or %"); + "expected %, %, % or " + "%"); c_parser_consume_token (parser); } if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index ea71f9c..f9c2c8a 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -40742,7 +40742,9 @@ cp_parser_omp_flush (cp_parser *parser, cp_token *pragma_tok) { tree id = cp_lexer_peek_token (parser->lexer)->u.value; const char *p = IDENTIFIER_POINTER (id); - if (!strcmp (p, "acq_rel")) + if (!strcmp (p, "seq_cst")) + mo = MEMMODEL_SEQ_CST; + else if (!strcmp (p, "acq_rel")) mo = MEMMODEL_ACQ_REL; else if (!strcmp (p, "release")) mo = MEMMODEL_RELEASE; @@ -40750,7 +40752,8 @@ cp_parser_omp_flush (cp_parser *parser, cp_token *pragma_tok) mo = MEMMODEL_ACQUIRE; else error_at (cp_lexer_peek_token (parser->lexer)->location, - "expected %, % or %"); + "expected %, %, % or " + "%"); cp_lexer_consume_token (parser->lexer); } if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN)) diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index f4b042f..8b78e89 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -10039,7 +10039,7 @@ finish_omp_flush (int mo) { tree fn = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE); releasing_vec vec; - if (mo != MEMMODEL_LAST) + if (mo != MEMMODEL_LAST && mo != MEMMODEL_SEQ_CST) { fn = builtin_decl_explicit (BUILT_IN_ATOMIC_THREAD_FENCE); vec->quick_push (build_int_cst (integer_type_node, mo)); diff --git a/gcc/fortran/openmp.c b/gcc/fortran/openmp.c index 64ecd54..a64b7f5 100644 --- a/gcc/fortran/openmp.c +++ b/gcc/fortran/openmp.c @@ -3782,7 +3782,9 @@ gfc_match_omp_flush (void) enum gfc_omp_memorder mo = OMP_MEMORDER_UNSET; if (gfc_match_omp_eos () == MATCH_NO && gfc_peek_ascii_char () != '(') { - if (gfc_match ("acq_rel") == MATCH_YES) + if (gfc_match ("seq_cst") == MATCH_YES) + mo = OMP_MEMORDER_SEQ_CST; + else if (gfc_match ("acq_rel") == MATCH_YES) mo = OMP_MEMORDER_ACQ_REL; else if (gfc_match ("release") == MATCH_YES) mo = OMP_MEMORDER_RELEASE; @@ -3790,7 +3792,7 @@ gfc_match_omp_flush (void) mo = OMP_MEMORDER_ACQUIRE; else { - gfc_error ("Expected AQC_REL, RELEASE, or ACQUIRE at %C"); + gfc_error ("Expected SEQ_CST, AQC_REL, RELEASE, or ACQUIRE at %C"); return MATCH_ERROR; } c = gfc_get_omp_clauses (); diff --git a/gcc/fortran/trans-openmp.c b/gcc/fortran/trans-openmp.c index 6f9b0e3..e55e0c8 100644 --- a/gcc/fortran/trans-openmp.c +++ b/gcc/fortran/trans-openmp.c @@ -5413,7 +5413,8 @@ gfc_trans_omp_flush (gfc_code *code) { tree call; if (!code->ext.omp_clauses - || code->ext.omp_clauses->memorder == OMP_MEMORDER_UNSET) + || code->ext.omp_clauses->memorder == OMP_MEMORDER_UNSET + || code->ext.omp_clauses->memorder == OMP_MEMORDER_SEQ_CST) { call = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE); call = build_call_expr_loc (input_location, call, 0); diff --git a/gcc/testsuite/c-c++-common/gomp/flush-1.c b/gcc/testsuite/c-c++-common/gomp/flush-1.c index 7c3e529..717b951 100644 --- a/gcc/testsuite/c-c++-common/gomp/flush-1.c +++ b/gcc/testsuite/c-c++-common/gomp/flush-1.c @@ -1,4 +1,5 @@ /* { dg-additional-options "-fdump-tree-gimple" } */ +/* { dg-final { scan-tree-dump "foo \\(6\\);\[\n\r]* __sync_synchronize \\(\\);\[\n\r]* foo \\(6\\);" "gimple" } } */ /* { dg-final { scan-tree-dump "foo \\(4\\);\[\n\r]* __atomic_thread_fence \\(4\\);\[\n\r]* foo \\(4\\);" "gimple" } } */ /* { dg-final { scan-tree-dump "foo \\(3\\);\[\n\r]* __atomic_thread_fence \\(3\\);\[\n\r]* foo \\(3\\);" "gimple" } } */ /* { dg-final { scan-tree-dump "foo \\(2\\);\[\n\r]* __atomic_thread_fence \\(2\\);\[\n\r]* foo \\(2\\);" "gimple" } } */ @@ -37,3 +38,11 @@ f4 (void) #pragma omp flush foo (5); } + +void +f5 (void) +{ + foo (6); + #pragma omp flush seq_cst + foo (6); +} diff --git a/gcc/testsuite/c-c++-common/gomp/flush-2.c b/gcc/testsuite/c-c++-common/gomp/flush-2.c index 00baa8a..30ef598 100644 --- a/gcc/testsuite/c-c++-common/gomp/flush-2.c +++ b/gcc/testsuite/c-c++-common/gomp/flush-2.c @@ -8,10 +8,11 @@ foo (void) #pragma omp flush acquire #pragma omp flush release #pragma omp flush acq_rel - #pragma omp flush relaxed /* { dg-error "expected 'acq_rel', 'release' or 'acquire'" } */ - #pragma omp flush seq_cst /* { dg-error "expected 'acq_rel', 'release' or 'acquire'" } */ - #pragma omp flush foobar /* { dg-error "expected 'acq_rel', 'release' or 'acquire'" } */ + #pragma omp flush seq_cst + #pragma omp flush relaxed /* { dg-error "expected 'seq_cst', 'acq_rel', 'release' or 'acquire'" } */ + #pragma omp flush foobar /* { dg-error "expected 'seq_cst', 'acq_rel', 'release' or 'acquire'" } */ #pragma omp flush acquire (a, b) /* { dg-error "'flush' list specified together with memory order clause" } */ #pragma omp flush release (a, b) /* { dg-error "'flush' list specified together with memory order clause" } */ #pragma omp flush acq_rel (a, b) /* { dg-error "'flush' list specified together with memory order clause" } */ + #pragma omp flush seq_cst (a, b) /* { dg-error "'flush' list specified together with memory order clause" } */ } diff --git a/gcc/testsuite/g++.dg/gomp/attrs-1.C b/gcc/testsuite/g++.dg/gomp/attrs-1.C index cd20845..c871c51 100644 --- a/gcc/testsuite/g++.dg/gomp/attrs-1.C +++ b/gcc/testsuite/g++.dg/gomp/attrs-1.C @@ -528,6 +528,12 @@ bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int s, ; [[omp::directive (flush acq_rel)]] ; + [[omp::directive (flush acquire)]] + ; + [[omp::directive (flush release)]] + ; + [[omp::directive (flush seq_cst)]] + ; [[omp::directive (flush (p, f))]] ; [[omp::directive (simd diff --git a/gcc/testsuite/g++.dg/gomp/attrs-2.C b/gcc/testsuite/g++.dg/gomp/attrs-2.C index 5c54905..5ec19b3 100644 --- a/gcc/testsuite/g++.dg/gomp/attrs-2.C +++ b/gcc/testsuite/g++.dg/gomp/attrs-2.C @@ -528,6 +528,12 @@ bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int s, ; [[omp::directive (flush, acq_rel)]] ; + [[omp::directive (flush, acquire)]] + ; + [[omp::directive (flush, release)]] + ; + [[omp::directive (flush, seq_cst)]] + ; [[omp::directive (flush (p, f))]] ; [[omp::directive (simd, diff --git a/gcc/testsuite/gfortran.dg/gomp/flush-1.f90 b/gcc/testsuite/gfortran.dg/gomp/flush-1.f90 index d0b7f9e..904bb1d 100644 --- a/gcc/testsuite/gfortran.dg/gomp/flush-1.f90 +++ b/gcc/testsuite/gfortran.dg/gomp/flush-1.f90 @@ -1,4 +1,5 @@ ! { dg-additional-options "-fdump-tree-gimple" } +! { dg-final { scan-tree-dump "foo \\(6\\);\[\n\r]* __sync_synchronize \\(\\);\[\n\r]* foo \\(6\\);" "gimple" } } ! { dg-final { scan-tree-dump "foo \\(4\\);\[\n\r]* __atomic_thread_fence \\(4\\);\[\n\r]* foo \\(4\\);" "gimple" } } ! { dg-final { scan-tree-dump "foo \\(3\\);\[\n\r]* __atomic_thread_fence \\(3\\);\[\n\r]* foo \\(3\\);" "gimple" } } ! { dg-final { scan-tree-dump "foo \\(2\\);\[\n\r]* __atomic_thread_fence \\(2\\);\[\n\r]* foo \\(2\\);" "gimple" } } @@ -39,3 +40,10 @@ subroutine f4 !$omp flush call foo (5) end + +subroutine f5 + use m + call foo (6) + !$omp flush seq_cst + call foo (6) +end diff --git a/gcc/testsuite/gfortran.dg/gomp/flush-2.f90 b/gcc/testsuite/gfortran.dg/gomp/flush-2.f90 index 6857371..ba23444 100644 --- a/gcc/testsuite/gfortran.dg/gomp/flush-2.f90 +++ b/gcc/testsuite/gfortran.dg/gomp/flush-2.f90 @@ -9,10 +9,11 @@ subroutine foo (void) !$omp flush acquire !$omp flush release !$omp flush acq_rel - !$omp flush relaxed ! { dg-error "Expected AQC_REL, RELEASE, or ACQUIRE" } - !$omp flush seq_cst ! { dg-error "Expected AQC_REL, RELEASE, or ACQUIRE" } - !$omp flush foobar ! { dg-error "Expected AQC_REL, RELEASE, or ACQUIRE" } + !$omp flush seq_cst + !$omp flush relaxed ! { dg-error "Expected SEQ_CST, AQC_REL, RELEASE, or ACQUIRE" } + !$omp flush foobar ! { dg-error "Expected SEQ_CST, AQC_REL, RELEASE, or ACQUIRE" } !$omp flush acquire (a, b) ! { dg-error "List specified together with memory order clause in FLUSH directive" } !$omp flush release (a, b) ! { dg-error "List specified together with memory order clause in FLUSH directive" } !$omp flush acq_rel (a, b) ! { dg-error "List specified together with memory order clause in FLUSH directive" } -end + !$omp flush seq_cst (a, b) ! { dg-error "List specified together with memory order clause in FLUSH directive" } + end -- 2.7.4