summaryrefslogtreecommitdiff
path: root/gcc/fortran
diff options
context:
space:
mode:
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2011-08-02 16:13:29 +0000
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2011-08-02 16:13:29 +0000
commit2169f33bdc9db9199850a22ce70730c68227b2db (patch)
tree2f3013a777c51a67a52b10f839e1bd56903dc5ba /gcc/fortran
parentf233ad1b4674f8b84008e794113d923ea6822dcf (diff)
downloadgcc-2169f33bdc9db9199850a22ce70730c68227b2db.tar.gz
Merge from gomp-3_1-branch branch:
2011-08-02 Jakub Jelinek <jakub@redhat.com> gcc/ * c-parser.c (enum c_parser_prec): New enum, moved from within c_parser_binary_expression. (c_parser_binary_expression): Add PREC argument. Stop parsing if operator has lower or equal precedence than PREC. (c_parser_conditional_expression, c_parser_omp_for_loop): Adjust callers. (c_parser_omp_atomic): Handle parsing OpenMP 3.1 atomics. Adjust c_finish_omp_atomic caller. (c_parser_omp_taskyield): New function. (c_parser_pragma): Handle PRAGMA_OMP_TASKYIELD. (c_parser_omp_clause_name): Handle final and mergeable clauses. (c_parser_omp_clause_final, c_parser_omp_clause_mergeable): New functions. (c_parser_omp_all_clauses): Handle PRAGMA_OMP_CLAUSE_FINAL and PRAGMA_OMP_CLAUSE_MERGEABLE. (OMP_TASK_CLAUSE_MASK): Allow final and mergeable clauses. (c_parser_omp_clause_reduction): Handle min and max. * c-typeck.c (c_finish_omp_clauses): Don't complain about const qualified predetermined vars in firstprivate clause. andle OMP_CLAUSE_FINAL and OMP_CLAUSE_MERGEABLE. Handle MIN_EXPR and MAX_EXPR. * tree-pretty-print.c (dump_omp_clause): Handle OMP_CLAUSE_FINAL and OMP_CLAUSE_MERGEABLE. (dump_generic_node): Handle OMP_ATOMIC_READ, OMP_ATOMIC_CAPTURE_OLD and OMP_ATOMIC_CAPTURE_NEW. * tree.c (omp_clause_num_ops): Add OMP_CLAUSE_FINAL and OMP_CLAUSE_MERGEABLE. (omp_clause_code_name): Likewise. (walk_tree_1): Handle OMP_CLAUSE_FINAL and OMP_CLAUSE_MERGEABLE. * tree.h (enum omp_clause_code): Add OMP_CLAUSE_FINAL and OMP_CLAUSE_MERGEABLE. (OMP_CLAUSE_FINAL_EXPR): Define. * omp-low.c (scan_sharing_clauses): Handle OMP_CLAUSE_FINAL and OMP_CLAUSE_MERGEABLE. (expand_task_call): Likewise. (expand_omp_atomic_load, expand_omp_atomic_store): New functions. (expand_omp_atomic_fetch_op): Handle cases where old or new value is needed afterwards. (expand_omp_atomic): Call expand_omp_atomic_load resp. expand_omp_atomic_store. * gimplify.c (gimplify_omp_atomic, gimplify_expr): Handle OMP_ATOMIC_READ, OMP_ATOMIC_CAPTURE_OLD and OMP_ATOMIC_CAPTURE_NEW. (gimplify_scan_omp_clauses, gimplify_adjust_omp_clauses): Handle OMP_CLAUSE_FINAL and OMP_CLAUSE_MERGEABLE. * tree-nested.c (convert_nonlocal_omp_clauses, convert_local_omp_clauses): Likewise. * tree.def (OMP_ATOMIC_READ, OMP_ATOMIC_CAPTURE_OLD, OMP_ATOMIC_CAPTURE_NEW): New. * gimple.h (GF_OMP_ATOMIC_NEED_VALUE): New. (gimple_omp_atomic_need_value_p, gimple_omp_atomic_set_need_value): New inlines. * omp-builtins.def (BUILT_IN_GOMP_TASKYIELD): New builtin. * doc/generic.texi: Mention OMP_CLAUSE_COLLAPSE, OMP_CLAUSE_UNTIED, OMP_CLAUSE_FINAL and OMP_CLAUSE_MERGEABLE. gcc/c-family/ * c-common.h (c_finish_omp_atomic): Adjust prototype. (c_finish_omp_taskyield): New prototype. * c-omp.c (c_finish_omp_atomic): Add OPCODE, V, LHS1 and RHS1 arguments. Handle OMP_ATOMIC_READ, OMP_ATOMIC_CAPTURE_OLD and OMP_ATOMIC_CAPTURE_NEW in addition to OMP_ATOMIC. If LHS1 or RHS1 have side-effects, evaluate those too in the right spot, if it is a decl and LHS is also a decl, error out if they aren't the same. (c_finish_omp_taskyield): New function. * c-cppbuiltin.c (c_cpp_builtins): Change _OPENMP to 201107. * c-pragma.c (omp_pragmas): Add taskyield. * c-pragma.h (enum pragma_kind): Add PRAGMA_OMP_TASKYIELD. (enum pragma_omp_clause): Add PRAGMA_OMP_CLAUSE_FINAL and PRAGMA_OMP_CLAUSE_MERGEABLE. gcc/cp/ * cp-tree.h (finish_omp_atomic): Adjust prototype. (cxx_omp_const_qual_no_mutable): New prototype. (finish_omp_taskyield): New prototype. * parser.c (cp_parser_omp_atomic): (cp_parser_omp_atomic): Handle parsing OpenMP 3.1 atomics. Adjust finish_omp_atomic caller. (cp_parser_omp_clause_name): Handle final and mergeable clauses. (cp_parser_omp_clause_final, cp_parser_omp_clause_mergeable): New functions. (cp_parser_omp_all_clauses): Handle PRAGMA_OMP_CLAUSE_FINAL and PRAGMA_OMP_CLAUSE_MERGEABLE. (OMP_TASK_CLAUSE_MASK): Allow final and mergeable clauses. (cp_parser_omp_taskyield): New function. (cp_parser_pragma): Handle PRAGMA_OMP_TASKYIELD. (cp_parser_omp_clause_reduction): Handle min and max. * pt.c (tsubst_expr) <case OMP_ATOMIC>: Handle OpenMP 3.1 atomics. (tsubst_omp_clauses): Handle OMP_CLAUSE_FINAL and OMP_CLAUSE_MERGEABLE. * semantics.c (finish_omp_atomic): Add OPCODE, V, LHS1 and RHS1 arguments. Handle OpenMP 3.1 atomics. Adjust c_finish_omp_atomic caller. (finish_omp_clauses): Don't complain about const qualified predetermined vars and static data members in firstprivate clause. Handle OMP_CLAUSE_FINAL and OMP_CLAUSE_MERGEABLE. Handle MIN_EXPR and MAX_EXPR. (finish_omp_taskyield): New function. * cp-gimplify.c (cxx_omp_const_qual_no_mutable): New function. (cxx_omp_predetermined_sharing): Use it. gcc/fortran/ PR fortran/46752 * cpp.c (cpp_define_builtins): Change _OPENMP to 201107. * openmp.c (gfc_free_omp_clauses): Free also final_expr. (OMP_CLAUSE_FINAL, OMP_CLAUSE_MERGEABLE): Define. (gfc_match_omp_clauses): Handle parsing final and mergeable clauses. (OMP_TASK_CLAUSES): Allow final and mergeable clauses. (gfc_match_omp_taskyield): New function. (resolve_omp_clauses): Resolve final clause. Allow POINTERs and Cray pointers in clauses other than REDUCTION. (gfc_match_omp_atomic): Match optional read/write/update/capture keywords after !$omp atomic. (resolve_omp_atomic): Handle all OpenMP 3.1 atomic forms. * dump-parse-tree.c (show_omp_node): Handle EXEC_OMP_TASKYIELD, print final and mergeable clauses. (show_code_node): Handle EXEC_OMP_TASKYIELD. * trans-openmp.c (gfc_trans_omp_clauses): Handle final and mergeable clauses. (gfc_trans_omp_taskyield): New function. (gfc_trans_omp_directive): Handle EXEC_OMP_TASKYIELD. (gfc_trans_omp_atomic): Handle all OpenMP 3.1 atomic forms. (gfc_omp_clause_copy_ctor): Handle non-allocated allocatable. (gfc_omp_predetermined_sharing): Adjust comment. * gfortran.h (gfc_statement): Add ST_OMP_TASKYIELD and ST_OMP_END_ATOMIC. (gfc_omp_clauses): Add final_expr and mergeable fields. (gfc_exec_op): Add EXEC_OMP_TASKYIELD. (gfc_omp_atomic_op): New enum typedef. (struct gfc_code): Add ext.omp_atomic. * trans.c (trans_code): Handle EXEC_OMP_TASKYIELD. * frontend-passes.c (gfc_code_walker): Also walk final_expr. * resolve.c (gfc_resolve_blocks, resolve_code): Handle EXEC_OMP_TASKYIELD. * st.c (gfc_free_statement): Likewise. * match.h (gfc_match_omp_taskyield): New prototype. * parse.c (decode_omp_directive): Handle taskyield directive. Handle !$omp end atomic. (case_executable): Add ST_OMP_TASKYIELD case. (gfc_ascii_statement): Handle ST_OMP_TASKYIELD. (parse_omp_atomic): Return gfc_statement instead of void. For !$omp atomic capture parse two assignments instead of just one and require !$omp end atomic afterwards, for other !$omp atomic forms just allow !$omp end atomic at the end. (parse_omp_structured_block, parse_executable): Adjust parse_omp_atomic callers. 2011-08-02 Tobias Burnus <burnus@net-b.de> * intrinsic.c (OMP_LIB): Updated openmp_version's value to 201107. * gfortran.texi (OpenMP): Update ref to OpenMP 3.1. * intrinsic.texi (OpenMP Modules): Update ref to OpenMP 3.1; remove deleted omp_integer_kind and omp_logical_kind constants. gcc/testsuite/ PR fortran/46752 * gcc.dg/gomp/atomic-5.c: Adjust expected diagnostics. * gcc.dg/gomp/atomic-15.c: New test. * g++.dg/gomp/atomic-5.C: Adjust expected diagnostics. * g++.dg/gomp/atomic-15.C: New test. * g++.dg/gomp/private-1.C: New test. * g++.dg/gomp/sharing-2.C: New test. * gfortran.dg/gomp/crayptr1.f90: Don't expect error about Cray pointer in FIRSTPRIVATE/LASTPRIVATE. * gfortran.dg/gomp/omp_atomic2.f90: New test. libgomp/ PR fortran/42041 PR fortran/46752 * omp.h.in (omp_in_final): New prototype. * omp_lib.f90.in (omp_in_final): New interface. (omp_integer_kind, omp_logical_kind): Remove and replace all its uses in the module with 4. (openmp_version): Change to 201107. * omp_lib.h.in (omp_sched_static, omp_sched_dynamic, omp_sched_guided, omp_sched_auto): Use omp_sched_kind kind for the parameters. (omp_in_final): New external. (openmp_version): Change to 201107. * task.c (omp_in_final): New function. (gomp_init_task): Initialize final_task. (GOMP_task): Remove unused attribute from flags. Handle final tasks. (GOMP_taskyield): New function. (omp_in_final): Return true if if (false) or final (true) task or descendant of final (true). * fortran.c (omp_in_final_): New function. * libgomp.map (OMP_3.1): Export omp_in_final and omp_in_final_. (GOMP_3.0): Export GOMP_taskyield. * env.c (gomp_nthreads_var_list, gomp_nthreads_var_list_len): New variables. (parse_unsigned_long_list): New function. (initialize_env): Use it for OMP_NUM_THREADS. Call parse_boolean with "OMP_PROC_BIND". If OMP_PROC_BIND=true, call gomp_init_affinity even if parse_affinity returned false. * config/linux/affinity.c (gomp_init_affinity): Handle gomp_cpu_affinity_len == 0. * libgomp_g.h (GOMP_taskyield): New prototype. * libgomp.h (struct gomp_task): Add final_task field. (gomp_nthreads_var_list, gomp_nthreads_var_list_len): New externs. * team.c (gomp_team_start): Override new task's nthreads_var icv if list form OMP_NUM_THREADS has been used and it has value for the new nesting level. * testsuite/libgomp.c/atomic-11.c: New test. * testsuite/libgomp.c/atomic-12.c: New test. * testsuite/libgomp.c/atomic-13.c: New test. * testsuite/libgomp.c/atomic-14.c: New test. * testsuite/libgomp.c/reduction-6.c: New test. * testsuite/libgomp.c/task-5.c: New test. * testsuite/libgomp.c++/atomic-2.C: New test. * testsuite/libgomp.c++/atomic-3.C: New test. * testsuite/libgomp.c++/atomic-4.C: New test. * testsuite/libgomp.c++/atomic-5.C: New test. * testsuite/libgomp.c++/atomic-6.C: New test. * testsuite/libgomp.c++/atomic-7.C: New test. * testsuite/libgomp.c++/atomic-8.C: New test. * testsuite/libgomp.c++/atomic-9.C: New test. * testsuite/libgomp.c++/task-8.C: New test. * testsuite/libgomp.c++/reduction-4.C: New test. * testsuite/libgomp.fortran/allocatable7.f90: New test. * testsuite/libgomp.fortran/allocatable8.f90: New test. * testsuite/libgomp.fortran/crayptr3.f90: New test. * testsuite/libgomp.fortran/omp_atomic3.f90: New test. * testsuite/libgomp.fortran/omp_atomic4.f90: New test. * testsuite/libgomp.fortran/pointer1.f90: New test. * testsuite/libgomp.fortran/pointer2.f90: New test. * testsuite/libgomp.fortran/task4.f90: New test. 2011-08-02 Tobias Burnus <burnus@net-b.de> * libgomp.texi: Update OpenMP spec references to 3.1. (omp_in_final,OMP_PROC_BIND): New sections. (OMP_NUM_THREADS): Document that the value can be now a list. (GOMP_STACKSIZE,GOMP_CPU_AFFINITY): Update @ref. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@177194 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/fortran')
-rw-r--r--gcc/fortran/ChangeLog57
-rw-r--r--gcc/fortran/cpp.c4
-rw-r--r--gcc/fortran/dump-parse-tree.c11
-rw-r--r--gcc/fortran/frontend-passes.c1
-rw-r--r--gcc/fortran/gfortran.h26
-rw-r--r--gcc/fortran/gfortran.texi6
-rw-r--r--gcc/fortran/intrinsic.texi10
-rw-r--r--gcc/fortran/match.h1
-rw-r--r--gcc/fortran/openmp.c201
-rw-r--r--gcc/fortran/parse.c47
-rw-r--r--gcc/fortran/resolve.c2
-rw-r--r--gcc/fortran/st.c1
-rw-r--r--gcc/fortran/trans-openmp.c171
-rw-r--r--gcc/fortran/trans.c1
14 files changed, 475 insertions, 64 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index d2e2044eff0..123990f66b0 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,60 @@
+2011-08-02 Jakub Jelinek <jakub@redhat.com>
+
+ PR fortran/46752
+ * cpp.c (cpp_define_builtins): Change _OPENMP to 201107.
+ * openmp.c (gfc_free_omp_clauses): Free also final_expr.
+ (OMP_CLAUSE_FINAL, OMP_CLAUSE_MERGEABLE): Define.
+ (gfc_match_omp_clauses): Handle parsing final and mergeable
+ clauses.
+ (OMP_TASK_CLAUSES): Allow final and mergeable clauses.
+ (gfc_match_omp_taskyield): New function.
+ (resolve_omp_clauses): Resolve final clause. Allow POINTERs and
+ Cray pointers in clauses other than REDUCTION.
+ (gfc_match_omp_atomic): Match optional
+ read/write/update/capture keywords after !$omp atomic.
+ (resolve_omp_atomic): Handle all OpenMP 3.1 atomic forms.
+ * dump-parse-tree.c (show_omp_node): Handle EXEC_OMP_TASKYIELD,
+ print final and mergeable clauses.
+ (show_code_node): Handle EXEC_OMP_TASKYIELD.
+ * trans-openmp.c (gfc_trans_omp_clauses): Handle final and
+ mergeable clauses.
+ (gfc_trans_omp_taskyield): New function.
+ (gfc_trans_omp_directive): Handle EXEC_OMP_TASKYIELD.
+ (gfc_trans_omp_atomic): Handle all OpenMP 3.1 atomic forms.
+ (gfc_omp_clause_copy_ctor): Handle non-allocated allocatable.
+ (gfc_omp_predetermined_sharing): Adjust comment.
+ * gfortran.h (gfc_statement): Add ST_OMP_TASKYIELD and
+ ST_OMP_END_ATOMIC.
+ (gfc_omp_clauses): Add final_expr and mergeable fields.
+ (gfc_exec_op): Add EXEC_OMP_TASKYIELD.
+ (gfc_omp_atomic_op): New enum typedef.
+ (struct gfc_code): Add ext.omp_atomic.
+ * trans.c (trans_code): Handle EXEC_OMP_TASKYIELD.
+ * frontend-passes.c (gfc_code_walker): Also walk final_expr.
+ * resolve.c (gfc_resolve_blocks, resolve_code): Handle
+ EXEC_OMP_TASKYIELD.
+ * st.c (gfc_free_statement): Likewise.
+ * match.h (gfc_match_omp_taskyield): New prototype.
+ * parse.c (decode_omp_directive): Handle taskyield directive.
+ Handle !$omp end atomic.
+ (case_executable): Add ST_OMP_TASKYIELD case.
+ (gfc_ascii_statement): Handle ST_OMP_TASKYIELD.
+ (parse_omp_atomic): Return gfc_statement instead of void.
+ For !$omp atomic capture parse two assignments instead of
+ just one and require !$omp end atomic afterwards, for
+ other !$omp atomic forms just allow !$omp end atomic at the
+ end.
+ (parse_omp_structured_block, parse_executable): Adjust
+ parse_omp_atomic callers.
+
+2011-08-02 Tobias Burnus <burnus@net-b.de>
+
+ * intrinsic.c (OMP_LIB): Updated openmp_version's
+ value to 201107.
+ * gfortran.texi (OpenMP): Update ref to OpenMP 3.1.
+ * intrinsic.texi (OpenMP Modules): Update ref to OpenMP 3.1;
+ remove deleted omp_integer_kind and omp_logical_kind constants.
+
2011-07-31 Janus Weil <janus@gcc.gnu.org>
PR fortran/49112
diff --git a/gcc/fortran/cpp.c b/gcc/fortran/cpp.c
index 0dece6cd536..a40442ee4d7 100644
--- a/gcc/fortran/cpp.c
+++ b/gcc/fortran/cpp.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc.
+/* Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
This file is part of GCC.
@@ -166,7 +166,7 @@ cpp_define_builtins (cpp_reader *pfile)
cpp_define (pfile, "_LANGUAGE_FORTRAN=1");
if (gfc_option.gfc_flag_openmp)
- cpp_define (pfile, "_OPENMP=200805");
+ cpp_define (pfile, "_OPENMP=201107");
/* The defines below are necessary for the TARGET_* macros.
diff --git a/gcc/fortran/dump-parse-tree.c b/gcc/fortran/dump-parse-tree.c
index 87b8b68408f..ad8b5548071 100644
--- a/gcc/fortran/dump-parse-tree.c
+++ b/gcc/fortran/dump-parse-tree.c
@@ -1039,6 +1039,7 @@ show_omp_node (int level, gfc_code *c)
case EXEC_OMP_SINGLE: name = "SINGLE"; break;
case EXEC_OMP_TASK: name = "TASK"; break;
case EXEC_OMP_TASKWAIT: name = "TASKWAIT"; break;
+ case EXEC_OMP_TASKYIELD: name = "TASKYIELD"; break;
case EXEC_OMP_WORKSHARE: name = "WORKSHARE"; break;
default:
gcc_unreachable ();
@@ -1071,6 +1072,7 @@ show_omp_node (int level, gfc_code *c)
return;
case EXEC_OMP_BARRIER:
case EXEC_OMP_TASKWAIT:
+ case EXEC_OMP_TASKYIELD:
return;
default:
break;
@@ -1085,6 +1087,12 @@ show_omp_node (int level, gfc_code *c)
show_expr (omp_clauses->if_expr);
fputc (')', dumpfile);
}
+ if (omp_clauses->final_expr)
+ {
+ fputs (" FINAL(", dumpfile);
+ show_expr (omp_clauses->final_expr);
+ fputc (')', dumpfile);
+ }
if (omp_clauses->num_threads)
{
fputs (" NUM_THREADS(", dumpfile);
@@ -1130,6 +1138,8 @@ show_omp_node (int level, gfc_code *c)
fputs (" ORDERED", dumpfile);
if (omp_clauses->untied)
fputs (" UNTIED", dumpfile);
+ if (omp_clauses->mergeable)
+ fputs (" MERGEABLE", dumpfile);
if (omp_clauses->collapse)
fprintf (dumpfile, " COLLAPSE(%d)", omp_clauses->collapse);
for (list_type = 0; list_type < OMP_LIST_NUM; list_type++)
@@ -2167,6 +2177,7 @@ show_code_node (int level, gfc_code *c)
case EXEC_OMP_SINGLE:
case EXEC_OMP_TASK:
case EXEC_OMP_TASKWAIT:
+ case EXEC_OMP_TASKYIELD:
case EXEC_OMP_WORKSHARE:
show_omp_node (level, c);
break;
diff --git a/gcc/fortran/frontend-passes.c b/gcc/fortran/frontend-passes.c
index 5c3e280df1c..8ab46f6e457 100644
--- a/gcc/fortran/frontend-passes.c
+++ b/gcc/fortran/frontend-passes.c
@@ -1235,6 +1235,7 @@ gfc_code_walker (gfc_code **c, walk_code_fn_t codefn, walk_expr_fn_t exprfn,
if (co->ext.omp_clauses)
{
WALK_SUBEXPR (co->ext.omp_clauses->if_expr);
+ WALK_SUBEXPR (co->ext.omp_clauses->final_expr);
WALK_SUBEXPR (co->ext.omp_clauses->num_threads);
WALK_SUBEXPR (co->ext.omp_clauses->chunk_size);
}
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index acb54004e9d..acfa9d4c555 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -199,16 +199,16 @@ typedef enum
ST_WRITE, ST_ASSIGNMENT, ST_POINTER_ASSIGNMENT, ST_SELECT_CASE, ST_SEQUENCE,
ST_SIMPLE_IF, ST_STATEMENT_FUNCTION, ST_DERIVED_DECL, ST_LABEL_ASSIGNMENT,
ST_ENUM, ST_ENUMERATOR, ST_END_ENUM, ST_SELECT_TYPE, ST_TYPE_IS, ST_CLASS_IS,
- ST_OMP_ATOMIC, ST_OMP_BARRIER, ST_OMP_CRITICAL, ST_OMP_END_CRITICAL,
- ST_OMP_END_DO, ST_OMP_END_MASTER, ST_OMP_END_ORDERED, ST_OMP_END_PARALLEL,
- ST_OMP_END_PARALLEL_DO, ST_OMP_END_PARALLEL_SECTIONS,
+ ST_OMP_ATOMIC, ST_OMP_BARRIER, ST_OMP_CRITICAL, ST_OMP_END_ATOMIC,
+ ST_OMP_END_CRITICAL, ST_OMP_END_DO, ST_OMP_END_MASTER, ST_OMP_END_ORDERED,
+ ST_OMP_END_PARALLEL, ST_OMP_END_PARALLEL_DO, ST_OMP_END_PARALLEL_SECTIONS,
ST_OMP_END_PARALLEL_WORKSHARE, ST_OMP_END_SECTIONS, ST_OMP_END_SINGLE,
ST_OMP_END_WORKSHARE, ST_OMP_DO, ST_OMP_FLUSH, ST_OMP_MASTER, ST_OMP_ORDERED,
ST_OMP_PARALLEL, ST_OMP_PARALLEL_DO, ST_OMP_PARALLEL_SECTIONS,
ST_OMP_PARALLEL_WORKSHARE, ST_OMP_SECTIONS, ST_OMP_SECTION, ST_OMP_SINGLE,
ST_OMP_THREADPRIVATE, ST_OMP_WORKSHARE, ST_OMP_TASK, ST_OMP_END_TASK,
- ST_OMP_TASKWAIT, ST_PROCEDURE, ST_GENERIC, ST_CRITICAL, ST_END_CRITICAL,
- ST_GET_FCN_CHARACTERISTICS, ST_LOCK, ST_UNLOCK, ST_NONE
+ ST_OMP_TASKWAIT, ST_OMP_TASKYIELD, ST_PROCEDURE, ST_GENERIC, ST_CRITICAL,
+ ST_END_CRITICAL, ST_GET_FCN_CHARACTERISTICS, ST_LOCK, ST_UNLOCK, ST_NONE
}
gfc_statement;
@@ -1050,13 +1050,14 @@ enum gfc_omp_default_sharing
typedef struct gfc_omp_clauses
{
struct gfc_expr *if_expr;
+ struct gfc_expr *final_expr;
struct gfc_expr *num_threads;
gfc_namelist *lists[OMP_LIST_NUM];
enum gfc_omp_sched_kind sched_kind;
struct gfc_expr *chunk_size;
enum gfc_omp_default_sharing default_sharing;
int collapse;
- bool nowait, ordered, untied;
+ bool nowait, ordered, untied, mergeable;
}
gfc_omp_clauses;
@@ -2064,10 +2065,20 @@ typedef enum
EXEC_OMP_PARALLEL_SECTIONS, EXEC_OMP_PARALLEL_WORKSHARE,
EXEC_OMP_SECTIONS, EXEC_OMP_SINGLE, EXEC_OMP_WORKSHARE,
EXEC_OMP_ATOMIC, EXEC_OMP_BARRIER, EXEC_OMP_END_NOWAIT,
- EXEC_OMP_END_SINGLE, EXEC_OMP_TASK, EXEC_OMP_TASKWAIT
+ EXEC_OMP_END_SINGLE, EXEC_OMP_TASK, EXEC_OMP_TASKWAIT,
+ EXEC_OMP_TASKYIELD
}
gfc_exec_op;
+typedef enum
+{
+ GFC_OMP_ATOMIC_UPDATE,
+ GFC_OMP_ATOMIC_READ,
+ GFC_OMP_ATOMIC_WRITE,
+ GFC_OMP_ATOMIC_CAPTURE
+}
+gfc_omp_atomic_op;
+
typedef struct gfc_code
{
gfc_exec_op op;
@@ -2118,6 +2129,7 @@ typedef struct gfc_code
const char *omp_name;
gfc_namelist *omp_namelist;
bool omp_bool;
+ gfc_omp_atomic_op omp_atomic;
}
ext; /* Points to additional structures required by statement */
diff --git a/gcc/fortran/gfortran.texi b/gcc/fortran/gfortran.texi
index 4858b2e39e9..389c05bfaab 100644
--- a/gcc/fortran/gfortran.texi
+++ b/gcc/fortran/gfortran.texi
@@ -530,7 +530,7 @@ support is reported in the @ref{Fortran 2003 status} and
@ref{Fortran 2008 status} sections of the documentation.
Additionally, the GNU Fortran compilers supports the OpenMP specification
-(version 3.0, @url{http://openmp.org/@/wp/@/openmp-specifications/}).
+(version 3.1, @url{http://openmp.org/@/wp/@/openmp-specifications/}).
@node Varying Length Character Strings
@subsection Varying Length Character Strings
@@ -1762,8 +1762,8 @@ It consists of a set of compiler directives, library routines,
and environment variables that influence run-time behavior.
GNU Fortran strives to be compatible to the
-@uref{http://www.openmp.org/mp-documents/spec30.pdf,
-OpenMP Application Program Interface v3.0}.
+@uref{http://www.openmp.org/mp-documents/spec31.pdf,
+OpenMP Application Program Interface v3.1}.
To enable the processing of the OpenMP directive @code{!$omp} in
free-form source code; the @code{c$omp}, @code{*$omp} and @code{!$omp}
diff --git a/gcc/fortran/intrinsic.texi b/gcc/fortran/intrinsic.texi
index 57338f14100..9adeeabf60d 100644
--- a/gcc/fortran/intrinsic.texi
+++ b/gcc/fortran/intrinsic.texi
@@ -13072,7 +13072,7 @@ Both are equivalent to the value @code{NULL} in C.
@section OpenMP Modules @code{OMP_LIB} and @code{OMP_LIB_KINDS}
@table @asis
@item @emph{Standard}:
-OpenMP Application Program Interface v3.0
+OpenMP Application Program Interface v3.1
@end table
@@ -13085,15 +13085,13 @@ the named constants defined in the modules are listed
below.
For details refer to the actual
-@uref{http://www.openmp.org/mp-documents/spec30.pdf,
-OpenMP Application Program Interface v3.0}.
+@uref{http://www.openmp.org/mp-documents/spec31.pdf,
+OpenMP Application Program Interface v3.1}.
@code{OMP_LIB_KINDS} provides the following scalar default-integer
named constants:
@table @asis
-@item @code{omp_integer_kind}
-@item @code{omp_logical_kind}
@item @code{omp_lock_kind}
@item @code{omp_nest_lock_kind}
@item @code{omp_sched_kind}
@@ -13102,7 +13100,7 @@ named constants:
@code{OMP_LIB} provides the scalar default-integer
named constant @code{openmp_version} with a value of the form
@var{yyyymm}, where @code{yyyy} is the year and @var{mm} the month
-of the OpenMP version; for OpenMP v3.0 the value is @code{200805}.
+of the OpenMP version; for OpenMP v3.1 the value is @code{201107}.
And the following scalar integer named constants of the
kind @code{omp_sched_kind}:
diff --git a/gcc/fortran/match.h b/gcc/fortran/match.h
index 5a40d7a173a..0d841044b98 100644
--- a/gcc/fortran/match.h
+++ b/gcc/fortran/match.h
@@ -138,6 +138,7 @@ match gfc_match_omp_sections (void);
match gfc_match_omp_single (void);
match gfc_match_omp_task (void);
match gfc_match_omp_taskwait (void);
+match gfc_match_omp_taskyield (void);
match gfc_match_omp_threadprivate (void);
match gfc_match_omp_workshare (void);
match gfc_match_omp_end_nowait (void);
diff --git a/gcc/fortran/openmp.c b/gcc/fortran/openmp.c
index 69a6bca352e..f5a58779c0c 100644
--- a/gcc/fortran/openmp.c
+++ b/gcc/fortran/openmp.c
@@ -1,5 +1,5 @@
/* OpenMP directive matching and resolving.
- Copyright (C) 2005, 2006, 2007, 2008, 2010
+ Copyright (C) 2005, 2006, 2007, 2008, 2010, 2011
Free Software Foundation, Inc.
Contributed by Jakub Jelinek
@@ -66,6 +66,7 @@ gfc_free_omp_clauses (gfc_omp_clauses *c)
return;
gfc_free_expr (c->if_expr);
+ gfc_free_expr (c->final_expr);
gfc_free_expr (c->num_threads);
gfc_free_expr (c->chunk_size);
for (i = 0; i < OMP_LIST_NUM; i++)
@@ -182,6 +183,8 @@ cleanup:
#define OMP_CLAUSE_ORDERED (1 << 11)
#define OMP_CLAUSE_COLLAPSE (1 << 12)
#define OMP_CLAUSE_UNTIED (1 << 13)
+#define OMP_CLAUSE_FINAL (1 << 14)
+#define OMP_CLAUSE_MERGEABLE (1 << 15)
/* Match OpenMP directive clauses. MASK is a bitmask of
clauses that are allowed for a particular directive. */
@@ -205,6 +208,9 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, int mask)
if ((mask & OMP_CLAUSE_IF) && c->if_expr == NULL
&& gfc_match ("if ( %e )", &c->if_expr) == MATCH_YES)
continue;
+ if ((mask & OMP_CLAUSE_FINAL) && c->final_expr == NULL
+ && gfc_match ("final ( %e )", &c->final_expr) == MATCH_YES)
+ continue;
if ((mask & OMP_CLAUSE_NUM_THREADS) && c->num_threads == NULL
&& gfc_match ("num_threads ( %e )", &c->num_threads) == MATCH_YES)
continue;
@@ -383,6 +389,12 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, int mask)
c->untied = needs_space = true;
continue;
}
+ if ((mask & OMP_CLAUSE_MERGEABLE) && !c->mergeable
+ && gfc_match ("mergeable") == MATCH_YES)
+ {
+ c->mergeable = needs_space = true;
+ continue;
+ }
if ((mask & OMP_CLAUSE_COLLAPSE) && !c->collapse)
{
gfc_expr *cexpr = NULL;
@@ -435,7 +447,8 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, int mask)
| OMP_CLAUSE_LASTPRIVATE | OMP_CLAUSE_REDUCTION)
#define OMP_TASK_CLAUSES \
(OMP_CLAUSE_PRIVATE | OMP_CLAUSE_FIRSTPRIVATE | OMP_CLAUSE_SHARED \
- | OMP_CLAUSE_IF | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_UNTIED)
+ | OMP_CLAUSE_IF | OMP_CLAUSE_DEFAULT | OMP_CLAUSE_UNTIED \
+ | OMP_CLAUSE_FINAL | OMP_CLAUSE_MERGEABLE)
match
gfc_match_omp_parallel (void)
@@ -476,6 +489,20 @@ gfc_match_omp_taskwait (void)
match
+gfc_match_omp_taskyield (void)
+{
+ if (gfc_match_omp_eos () != MATCH_YES)
+ {
+ gfc_error ("Unexpected junk after TASKYIELD clause at %C");
+ return MATCH_ERROR;
+ }
+ new_st.op = EXEC_OMP_TASKYIELD;
+ new_st.ext.omp_clauses = NULL;
+ return MATCH_YES;
+}
+
+
+match
gfc_match_omp_critical (void)
{
char n[GFC_MAX_SYMBOL_LEN+1];
@@ -700,13 +727,22 @@ gfc_match_omp_ordered (void)
match
gfc_match_omp_atomic (void)
{
+ gfc_omp_atomic_op op = GFC_OMP_ATOMIC_UPDATE;
+ if (gfc_match ("% update") == MATCH_YES)
+ op = GFC_OMP_ATOMIC_UPDATE;
+ else if (gfc_match ("% read") == MATCH_YES)
+ op = GFC_OMP_ATOMIC_READ;
+ else if (gfc_match ("% write") == MATCH_YES)
+ op = GFC_OMP_ATOMIC_WRITE;
+ else if (gfc_match ("% capture") == MATCH_YES)
+ op = GFC_OMP_ATOMIC_CAPTURE;
if (gfc_match_omp_eos () != MATCH_YES)
{
gfc_error ("Unexpected junk after $OMP ATOMIC statement at %C");
return MATCH_ERROR;
}
new_st.op = EXEC_OMP_ATOMIC;
- new_st.ext.omp_clauses = NULL;
+ new_st.ext.omp_atomic = op;
return MATCH_YES;
}
@@ -783,6 +819,14 @@ resolve_omp_clauses (gfc_code *code)
gfc_error ("IF clause at %L requires a scalar LOGICAL expression",
&expr->where);
}
+ if (omp_clauses->final_expr)
+ {
+ gfc_expr *expr = omp_clauses->final_expr;
+ if (gfc_resolve_expr (expr) == FAILURE
+ || expr->ts.type != BT_LOGICAL || expr->rank != 0)
+ gfc_error ("FINAL clause at %L requires a scalar LOGICAL expression",
+ &expr->where);
+ }
if (omp_clauses->num_threads)
{
gfc_expr *expr = omp_clauses->num_threads;
@@ -940,15 +984,20 @@ resolve_omp_clauses (gfc_code *code)
n->sym->name, name, &code->loc);
if (list != OMP_LIST_PRIVATE)
{
- if (n->sym->attr.pointer)
+ if (n->sym->attr.pointer
+ && list >= OMP_LIST_REDUCTION_FIRST
+ && list <= OMP_LIST_REDUCTION_LAST)
gfc_error ("POINTER object '%s' in %s clause at %L",
n->sym->name, name, &code->loc);
/* Variables in REDUCTION-clauses must be of intrinsic type (flagged below). */
- if ((list < OMP_LIST_REDUCTION_FIRST || list > OMP_LIST_REDUCTION_LAST) &&
- n->sym->ts.type == BT_DERIVED && n->sym->ts.u.derived->attr.alloc_comp)
+ if ((list < OMP_LIST_REDUCTION_FIRST || list > OMP_LIST_REDUCTION_LAST)
+ && n->sym->ts.type == BT_DERIVED
+ && n->sym->ts.u.derived->attr.alloc_comp)
gfc_error ("%s clause object '%s' has ALLOCATABLE components at %L",
name, n->sym->name, &code->loc);
- if (n->sym->attr.cray_pointer)
+ if (n->sym->attr.cray_pointer
+ && list >= OMP_LIST_REDUCTION_FIRST
+ && list <= OMP_LIST_REDUCTION_LAST)
gfc_error ("Cray pointer '%s' in %s clause at %L",
n->sym->name, name, &code->loc);
}
@@ -1095,12 +1144,18 @@ is_conversion (gfc_expr *expr, bool widening)
static void
resolve_omp_atomic (gfc_code *code)
{
+ gfc_code *atomic_code = code;
gfc_symbol *var;
- gfc_expr *expr2;
+ gfc_expr *expr2, *expr2_tmp;
code = code->block->next;
gcc_assert (code->op == EXEC_ASSIGN);
- gcc_assert (code->next == NULL);
+ gcc_assert ((atomic_code->ext.omp_atomic != GFC_OMP_ATOMIC_CAPTURE
+ && code->next == NULL)
+ || (atomic_code->ext.omp_atomic == GFC_OMP_ATOMIC_CAPTURE
+ && code->next != NULL
+ && code->next->op == EXEC_ASSIGN
+ && code->next->next == NULL));
if (code->expr1->expr_type != EXPR_VARIABLE
|| code->expr1->symtree == NULL
@@ -1118,7 +1173,86 @@ resolve_omp_atomic (gfc_code *code)
var = code->expr1->symtree->n.sym;
expr2 = is_conversion (code->expr2, false);
if (expr2 == NULL)
- expr2 = code->expr2;
+ {
+ if (atomic_code->ext.omp_atomic == GFC_OMP_ATOMIC_READ
+ || atomic_code->ext.omp_atomic == GFC_OMP_ATOMIC_WRITE)
+ expr2 = is_conversion (code->expr2, true);
+ if (expr2 == NULL)
+ expr2 = code->expr2;
+ }
+
+ switch (atomic_code->ext.omp_atomic)
+ {
+ case GFC_OMP_ATOMIC_READ:
+ if (expr2->expr_type != EXPR_VARIABLE
+ || expr2->symtree == NULL
+ || expr2->rank != 0
+ || (expr2->ts.type != BT_INTEGER
+ && expr2->ts.type != BT_REAL
+ && expr2->ts.type != BT_COMPLEX
+ && expr2->ts.type != BT_LOGICAL))
+ gfc_error ("!$OMP ATOMIC READ statement must read from a scalar "
+ "variable of intrinsic type at %L", &expr2->where);
+ return;
+ case GFC_OMP_ATOMIC_WRITE:
+ if (expr2->rank != 0 || expr_references_sym (code->expr2, var, NULL))
+ gfc_error ("expr in !$OMP ATOMIC WRITE assignment var = expr "
+ "must be scalar and cannot reference var at %L",
+ &expr2->where);
+ return;
+ case GFC_OMP_ATOMIC_CAPTURE:
+ expr2_tmp = expr2;
+ if (expr2 == code->expr2)
+ {
+ expr2_tmp = is_conversion (code->expr2, true);
+ if (expr2_tmp == NULL)
+ expr2_tmp = expr2;
+ }
+ if (expr2_tmp->expr_type == EXPR_VARIABLE)
+ {
+ if (expr2_tmp->symtree == NULL
+ || expr2_tmp->rank != 0
+ || (expr2_tmp->ts.type != BT_INTEGER
+ && expr2_tmp->ts.type != BT_REAL
+ && expr2_tmp->ts.type != BT_COMPLEX
+ && expr2_tmp->ts.type != BT_LOGICAL)
+ || expr2_tmp->symtree->n.sym == var)
+ {
+ gfc_error ("!$OMP ATOMIC CAPTURE capture statement must read from "
+ "a scalar variable of intrinsic type at %L",
+ &expr2_tmp->where);
+ return;
+ }
+ var = expr2_tmp->symtree->n.sym;
+ code = code->next;
+ if (code->expr1->expr_type != EXPR_VARIABLE
+ || code->expr1->symtree == NULL
+ || code->expr1->rank != 0
+ || (code->expr1->ts.type != BT_INTEGER
+ && code->expr1->ts.type != BT_REAL
+ && code->expr1->ts.type != BT_COMPLEX
+ && code->expr1->ts.type != BT_LOGICAL))
+ {
+ gfc_error ("!$OMP ATOMIC CAPTURE update statement must set "
+ "a scalar variable of intrinsic type at %L",
+ &code->expr1->where);
+ return;
+ }
+ if (code->expr1->symtree->n.sym != var)
+ {
+ gfc_error ("!$OMP ATOMIC CAPTURE capture statement reads from "
+ "different variable than update statement writes "
+ "into at %L", &code->expr1->where);
+ return;
+ }
+ expr2 = is_conversion (code->expr2, false);
+ if (expr2 == NULL)
+ expr2 = code->expr2;
+ }
+ break;
+ default:
+ break;
+ }
if (expr2->expr_type == EXPR_OP)
{
@@ -1320,6 +1454,53 @@ resolve_omp_atomic (gfc_code *code)
else
gfc_error ("!$OMP ATOMIC assignment must have an operator or intrinsic "
"on right hand side at %L", &expr2->where);
+
+ if (atomic_code->ext.omp_atomic == GFC_OMP_ATOMIC_CAPTURE && code->next)
+ {
+ code = code->next;
+ if (code->expr1->expr_type != EXPR_VARIABLE
+ || code->expr1->symtree == NULL
+ || code->expr1->rank != 0
+ || (code->expr1->ts.type != BT_INTEGER
+ && code->expr1->ts.type != BT_REAL
+ && code->expr1->ts.type != BT_COMPLEX
+ && code->expr1->ts.type != BT_LOGICAL))
+ {
+ gfc_error ("!$OMP ATOMIC CAPTURE capture statement must set "
+ "a scalar variable of intrinsic type at %L",
+ &code->expr1->where);
+ return;
+ }
+
+ expr2 = is_conversion (code->expr2, false);
+ if (expr2 == NULL)
+ {
+ expr2 = is_conversion (code->expr2, true);
+ if (expr2 == NULL)
+ expr2 = code->expr2;
+ }
+
+ if (expr2->expr_type != EXPR_VARIABLE
+ || expr2->symtree == NULL
+ || expr2->rank != 0
+ || (expr2->ts.type != BT_INTEGER
+ && expr2->ts.type != BT_REAL
+ && expr2->ts.type != BT_COMPLEX
+ && expr2->ts.type != BT_LOGICAL))
+ {
+ gfc_error ("!$OMP ATOMIC CAPTURE capture statement must read "
+ "from a scalar variable of intrinsic type at %L",
+ &expr2->where);
+ return;
+ }
+ if (expr2->symtree->n.sym != var)
+ {
+ gfc_error ("!$OMP ATOMIC CAPTURE capture statement reads from "
+ "different variable than update statement writes "
+ "into at %L", &expr2->where);
+ return;
+ }
+ }
}
diff --git a/gcc/fortran/parse.c b/gcc/fortran/parse.c
index ba28648ec2c..2910ab51318 100644
--- a/gcc/fortran/parse.c
+++ b/gcc/fortran/parse.c
@@ -526,6 +526,7 @@ decode_omp_directive (void)
match ("do", gfc_match_omp_do, ST_OMP_DO);
break;
case 'e':
+ match ("end atomic", gfc_match_omp_eos, ST_OMP_END_ATOMIC);
match ("end critical", gfc_match_omp_critical, ST_OMP_END_CRITICAL);
match ("end do", gfc_match_omp_end_nowait, ST_OMP_END_DO);
match ("end master", gfc_match_omp_eos, ST_OMP_END_MASTER);
@@ -567,6 +568,7 @@ decode_omp_directive (void)
case 't':
match ("task", gfc_match_omp_task, ST_OMP_TASK);
match ("taskwait", gfc_match_omp_taskwait, ST_OMP_TASKWAIT);
+ match ("taskyield", gfc_match_omp_taskyield, ST_OMP_TASKYIELD);
match ("threadprivate", gfc_match_omp_threadprivate,
ST_OMP_THREADPRIVATE);
case 'w':
@@ -957,9 +959,9 @@ next_statement (void)
case ST_POINTER_ASSIGNMENT: case ST_EXIT: case ST_CYCLE: \
case ST_ASSIGNMENT: case ST_ARITHMETIC_IF: case ST_WHERE: case ST_FORALL: \
case ST_LABEL_ASSIGNMENT: case ST_FLUSH: case ST_OMP_FLUSH: \
- case ST_OMP_BARRIER: case ST_OMP_TASKWAIT: case ST_ERROR_STOP: \
- case ST_SYNC_ALL: case ST_SYNC_IMAGES: case ST_SYNC_MEMORY: \
- case ST_LOCK: case ST_UNLOCK
+ case ST_OMP_BARRIER: case ST_OMP_TASKWAIT: case ST_OMP_TASKYIELD: \
+ case ST_ERROR_STOP: case ST_SYNC_ALL: case ST_SYNC_IMAGES: \
+ case ST_SYNC_MEMORY: case ST_LOCK: case ST_UNLOCK
/* Statements that mark other executable statements. */
@@ -1470,6 +1472,9 @@ gfc_ascii_statement (gfc_statement st)
case ST_OMP_DO:
p = "!$OMP DO";
break;
+ case ST_OMP_END_ATOMIC:
+ p = "!$OMP END ATOMIC";
+ break;
case ST_OMP_END_CRITICAL:
p = "!$OMP END CRITICAL";
break;
@@ -1542,6 +1547,9 @@ gfc_ascii_statement (gfc_statement st)
case ST_OMP_TASKWAIT:
p = "!$OMP TASKWAIT";
break;
+ case ST_OMP_TASKYIELD:
+ p = "!$OMP TASKYIELD";
+ break;
case ST_OMP_THREADPRIVATE:
p = "!$OMP THREADPRIVATE";
break;
@@ -3420,12 +3428,13 @@ parse_omp_do (gfc_statement omp_st)
/* Parse the statements of OpenMP atomic directive. */
-static void
+static gfc_statement
parse_omp_atomic (void)
{
gfc_statement st;
gfc_code *cp, *np;
gfc_state_data s;
+ int count;
accept_statement (ST_OMP_ATOMIC);
@@ -3434,21 +3443,35 @@ parse_omp_atomic (void)
np = new_level (cp);
np->op = cp->op;
np->block = NULL;
+ count = 1 + (cp->ext.omp_atomic == GFC_OMP_ATOMIC_CAPTURE);
- for (;;)
+ while (count)
{
st = next_statement ();
if (st == ST_NONE)
unexpected_eof ();
else if (st == ST_ASSIGNMENT)
- break;
+ {
+ accept_statement (st);
+ count--;
+ }
else
unexpected_statement (st);
}
- accept_statement (st);
-
pop_state ();
+
+ st = next_statement ();
+ if (st == ST_OMP_END_ATOMIC)
+ {
+ gfc_clear_new_st ();
+ gfc_commit_symbols ();
+ gfc_warning_check ();
+ st = next_statement ();
+ }
+ else if (cp->ext.omp_atomic == GFC_OMP_ATOMIC_CAPTURE)
+ gfc_error ("Missing !$OMP END ATOMIC after !$OMP ATOMIC CAPTURE at %C");
+ return st;
}
@@ -3558,8 +3581,8 @@ parse_omp_structured_block (gfc_statement omp_st, bool workshare_stmts_only)
continue;
case ST_OMP_ATOMIC:
- parse_omp_atomic ();
- break;
+ st = parse_omp_atomic ();
+ continue;
default:
cycle = false;
@@ -3739,8 +3762,8 @@ parse_executable (gfc_statement st)
continue;
case ST_OMP_ATOMIC:
- parse_omp_atomic ();
- break;
+ st = parse_omp_atomic ();
+ continue;
default:
return st;
diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c
index b4d66cc968b..b8a8ebb8a34 100644
--- a/gcc/fortran/resolve.c
+++ b/gcc/fortran/resolve.c
@@ -8824,6 +8824,7 @@ gfc_resolve_blocks (gfc_code *b, gfc_namespace *ns)
case EXEC_OMP_SINGLE:
case EXEC_OMP_TASK:
case EXEC_OMP_TASKWAIT:
+ case EXEC_OMP_TASKYIELD:
case EXEC_OMP_WORKSHARE:
break;
@@ -9390,6 +9391,7 @@ resolve_code (gfc_code *code, gfc_namespace *ns)
case EXEC_OMP_SECTIONS:
case EXEC_OMP_SINGLE:
case EXEC_OMP_TASKWAIT:
+ case EXEC_OMP_TASKYIELD:
case EXEC_OMP_WORKSHARE:
gfc_resolve_omp_directive (code, ns);
break;
diff --git a/gcc/fortran/st.c b/gcc/fortran/st.c
index cedb97c7d55..c051d6a0c97 100644
--- a/gcc/fortran/st.c
+++ b/gcc/fortran/st.c
@@ -208,6 +208,7 @@ gfc_free_statement (gfc_code *p)
case EXEC_OMP_ORDERED:
case EXEC_OMP_END_NOWAIT:
case EXEC_OMP_TASKWAIT:
+ case EXEC_OMP_TASKYIELD:
break;
default:
diff --git a/gcc/fortran/trans-openmp.c b/gcc/fortran/trans-openmp.c
index 29e342f13fb..b1f8e09a1b9 100644
--- a/gcc/fortran/trans-openmp.c
+++ b/gcc/fortran/trans-openmp.c
@@ -88,9 +88,7 @@ gfc_omp_predetermined_sharing (tree decl)
if (GFC_DECL_CRAY_POINTEE (decl))
return OMP_CLAUSE_DEFAULT_PRIVATE;
- /* Assumed-size arrays are predetermined to inherit sharing
- attributes of the associated actual argument, which is shared
- for all we care. */
+ /* Assumed-size arrays are predetermined shared. */
if (TREE_CODE (decl) == PARM_DECL
&& GFC_ARRAY_TYPE_P (TREE_TYPE (decl))
&& GFC_TYPE_ARRAY_AKIND (TREE_TYPE (decl)) == GFC_ARRAY_UNKNOWN
@@ -215,7 +213,8 @@ tree
gfc_omp_clause_copy_ctor (tree clause, tree dest, tree src)
{
tree type = TREE_TYPE (dest), ptr, size, esize, rank, call;
- stmtblock_t block;
+ tree cond, then_b, else_b;
+ stmtblock_t block, cond_block;
if (! GFC_DESCRIPTOR_TYPE_P (type)
|| GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE)
@@ -227,7 +226,9 @@ gfc_omp_clause_copy_ctor (tree clause, tree dest, tree src)
and copied from SRC. */
gfc_start_block (&block);
- gfc_add_modify (&block, dest, src);
+ gfc_init_block (&cond_block);
+
+ gfc_add_modify (&cond_block, dest, src);
rank = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (type) - 1];
size = gfc_conv_descriptor_ubound_get (dest, rank);
size = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
@@ -241,18 +242,30 @@ gfc_omp_clause_copy_ctor (tree clause, tree dest, tree src)
TYPE_SIZE_UNIT (gfc_get_element_type (type)));
size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
size, esize);
- size = gfc_evaluate_now (fold_convert (size_type_node, size), &block);
+ size = gfc_evaluate_now (fold_convert (size_type_node, size), &cond_block);
ptr = gfc_create_var (pvoid_type_node, NULL);
- gfc_allocate_using_malloc (&block, ptr, size, NULL_TREE);
- gfc_conv_descriptor_data_set (&block, dest, ptr);
+ gfc_allocate_using_malloc (&cond_block, ptr, size, NULL_TREE);
+ gfc_conv_descriptor_data_set (&cond_block, dest, ptr);
call = build_call_expr_loc (input_location,
built_in_decls[BUILT_IN_MEMCPY], 3, ptr,
fold_convert (pvoid_type_node,
gfc_conv_descriptor_data_get (src)),
size);
- gfc_add_expr_to_block (&block, fold_convert (void_type_node, call));
+ gfc_add_expr_to_block (&cond_block, fold_convert (void_type_node, call));
+ then_b = gfc_finish_block (&cond_block);
+
+ gfc_init_block (&cond_block);
+ gfc_conv_descriptor_data_set (&cond_block, dest, null_pointer_node);
+ else_b = gfc_finish_block (&cond_block);
+
+ cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
+ fold_convert (pvoid_type_node,
+ gfc_conv_descriptor_data_get (src)),
+ null_pointer_node);
+ gfc_add_expr_to_block (&block, build3_loc (input_location, COND_EXPR,
+ void_type_node, cond, then_b, else_b));
return gfc_finish_block (&block);
}
@@ -855,6 +868,21 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
omp_clauses = gfc_trans_add_clause (c, omp_clauses);
}
+ if (clauses->final_expr)
+ {
+ tree final_var;
+
+ gfc_init_se (&se, NULL);
+ gfc_conv_expr (&se, clauses->final_expr);
+ gfc_add_block_to_block (block, &se.pre);
+ final_var = gfc_evaluate_now (se.expr, block);
+ gfc_add_block_to_block (block, &se.post);
+
+ c = build_omp_clause (where.lb->location, OMP_CLAUSE_FINAL);
+ OMP_CLAUSE_FINAL_EXPR (c) = final_var;
+ omp_clauses = gfc_trans_add_clause (c, omp_clauses);
+ }
+
if (clauses->num_threads)
{
tree num_threads;
@@ -948,6 +976,12 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
omp_clauses = gfc_trans_add_clause (c, omp_clauses);
}
+ if (clauses->mergeable)
+ {
+ c = build_omp_clause (where.lb->location, OMP_CLAUSE_MERGEABLE);
+ omp_clauses = gfc_trans_add_clause (c, omp_clauses);
+ }
+
if (clauses->collapse)
{
c = build_omp_clause (where.lb->location, OMP_CLAUSE_COLLAPSE);
@@ -990,35 +1024,85 @@ static tree gfc_trans_omp_workshare (gfc_code *, gfc_omp_clauses *);
static tree
gfc_trans_omp_atomic (gfc_code *code)
{
+ gfc_code *atomic_code = code;
gfc_se lse;
gfc_se rse;
+ gfc_se vse;
gfc_expr *expr2, *e;
gfc_symbol *var;
stmtblock_t block;
tree lhsaddr, type, rhs, x;
enum tree_code op = ERROR_MARK;
+ enum tree_code aop = OMP_ATOMIC;
bool var_on_left = false;
code = code->block->next;
gcc_assert (code->op == EXEC_ASSIGN);
- gcc_assert (code->next == NULL);
var = code->expr1->symtree->n.sym;
gfc_init_se (&lse, NULL);
gfc_init_se (&rse, NULL);
+ gfc_init_se (&vse, NULL);
gfc_start_block (&block);
- gfc_conv_expr (&lse, code->expr1);
- gfc_add_block_to_block (&block, &lse.pre);
- type = TREE_TYPE (lse.expr);
- lhsaddr = gfc_build_addr_expr (NULL, lse.expr);
-
expr2 = code->expr2;
if (expr2->expr_type == EXPR_FUNCTION
&& expr2->value.function.isym->id == GFC_ISYM_CONVERSION)
expr2 = expr2->value.function.actual->expr;
- if (expr2->expr_type == EXPR_OP)
+ switch (atomic_code->ext.omp_atomic)
+ {
+ case GFC_OMP_ATOMIC_READ:
+ gfc_conv_expr (&vse, code->expr1);
+ gfc_add_block_to_block (&block, &vse.pre);
+
+ gfc_conv_expr (&lse, expr2);
+ gfc_add_block_to_block (&block, &lse.pre);
+ type = TREE_TYPE (lse.expr);
+ lhsaddr = gfc_build_addr_expr (NULL, lse.expr);
+
+ x = build1 (OMP_ATOMIC_READ, type, lhsaddr);
+ x = convert (TREE_TYPE (vse.expr), x);
+ gfc_add_modify (&block, vse.expr, x);
+
+ gfc_add_block_to_block (&block, &lse.pre);
+ gfc_add_block_to_block (&block, &rse.pre);
+
+ return gfc_finish_block (&block);
+ case GFC_OMP_ATOMIC_CAPTURE:
+ aop = OMP_ATOMIC_CAPTURE_NEW;
+ if (expr2->expr_type == EXPR_VARIABLE)
+ {
+ aop = OMP_ATOMIC_CAPTURE_OLD;
+ gfc_conv_expr (&vse, code->expr1);
+ gfc_add_block_to_block (&block, &vse.pre);
+
+ gfc_conv_expr (&lse, expr2);
+ gfc_add_block_to_block (&block, &lse.pre);
+ gfc_init_se (&lse, NULL);
+ code = code->next;
+ var = code->expr1->symtree->n.sym;
+ expr2 = code->expr2;
+ if (expr2->expr_type == EXPR_FUNCTION
+ && expr2->value.function.isym->id == GFC_ISYM_CONVERSION)
+ expr2 = expr2->value.function.actual->expr;
+ }
+ break;
+ default:
+ break;
+ }
+
+ gfc_conv_expr (&lse, code->expr1);
+ gfc_add_block_to_block (&block, &lse.pre);
+ type = TREE_TYPE (lse.expr);
+ lhsaddr = gfc_build_addr_expr (NULL, lse.expr);
+
+ if (atomic_code->ext.omp_atomic == GFC_OMP_ATOMIC_WRITE)
+ {
+ gfc_conv_expr (&rse, expr2);
+ gfc_add_block_to_block (&block, &rse.pre);
+ }
+ else if (expr2->expr_type == EXPR_OP)
{
gfc_expr *e;
switch (expr2->value.op.op)
@@ -1134,25 +1218,55 @@ gfc_trans_omp_atomic (gfc_code *code)
lhsaddr = save_expr (lhsaddr);
rhs = gfc_evaluate_now (rse.expr, &block);
- x = convert (TREE_TYPE (rhs), build_fold_indirect_ref_loc (input_location,
- lhsaddr));
- if (var_on_left)
- x = fold_build2_loc (input_location, op, TREE_TYPE (rhs), x, rhs);
+ if (atomic_code->ext.omp_atomic == GFC_OMP_ATOMIC_WRITE)
+ x = rhs;
else
- x = fold_build2_loc (input_location, op, TREE_TYPE (rhs), rhs, x);
+ {
+ x = convert (TREE_TYPE (rhs),
+ build_fold_indirect_ref_loc (input_location, lhsaddr));
+ if (var_on_left)
+ x = fold_build2_loc (input_location, op, TREE_TYPE (rhs), x, rhs);
+ else
+ x = fold_build2_loc (input_location, op, TREE_TYPE (rhs), rhs, x);
+ }
if (TREE_CODE (TREE_TYPE (rhs)) == COMPLEX_TYPE
&& TREE_CODE (type) != COMPLEX_TYPE)
x = fold_build1_loc (input_location, REALPART_EXPR,
TREE_TYPE (TREE_TYPE (rhs)), x);
- x = build2_v (OMP_ATOMIC, lhsaddr, convert (type, x));
- gfc_add_expr_to_block (&block, x);
-
gfc_add_block_to_block (&block, &lse.pre);
gfc_add_block_to_block (&block, &rse.pre);
+ if (aop == OMP_ATOMIC)
+ {
+ x = build2_v (OMP_ATOMIC, lhsaddr, convert (type, x));
+ gfc_add_expr_to_block (&block, x);
+ }
+ else
+ {
+ if (aop == OMP_ATOMIC_CAPTURE_NEW)
+ {
+ code = code->next;
+ expr2 = code->expr2;
+ if (expr2->expr_type == EXPR_FUNCTION
+ && expr2->value.function.isym->id == GFC_ISYM_CONVERSION)
+ expr2 = expr2->value.function.actual->expr;
+
+ gcc_assert (expr2->expr_type == EXPR_VARIABLE);
+ gfc_conv_expr (&vse, code->expr1);
+ gfc_add_block_to_block (&block, &vse.pre);
+
+ gfc_init_se (&lse, NULL);
+ gfc_conv_expr (&lse, expr2);
+ gfc_add_block_to_block (&block, &lse.pre);
+ }
+ x = build2 (aop, type, lhsaddr, convert (type, x));
+ x = convert (TREE_TYPE (vse.expr), x);
+ gfc_add_modify (&block, vse.expr, x);
+ }
+
return gfc_finish_block (&block);
}
@@ -1629,6 +1743,13 @@ gfc_trans_omp_taskwait (void)
}
static tree
+gfc_trans_omp_taskyield (void)
+{
+ tree decl = built_in_decls [BUILT_IN_GOMP_TASKYIELD];
+ return build_call_expr_loc (input_location, decl, 0);
+}
+
+static tree
gfc_trans_omp_workshare (gfc_code *code, gfc_omp_clauses *clauses)
{
tree res, tmp, stmt;
@@ -1821,6 +1942,8 @@ gfc_trans_omp_directive (gfc_code *code)
return gfc_trans_omp_task (code);
case EXEC_OMP_TASKWAIT:
return gfc_trans_omp_taskwait ();
+ case EXEC_OMP_TASKYIELD:
+ return gfc_trans_omp_taskyield ();
case EXEC_OMP_WORKSHARE:
return gfc_trans_omp_workshare (code, code->ext.omp_clauses);
default:
diff --git a/gcc/fortran/trans.c b/gcc/fortran/trans.c
index 2f8c7fdc440..19f215cd54d 100644
--- a/gcc/fortran/trans.c
+++ b/gcc/fortran/trans.c
@@ -1410,6 +1410,7 @@ trans_code (gfc_code * code, tree cond)
case EXEC_OMP_SINGLE:
case EXEC_OMP_TASK:
case EXEC_OMP_TASKWAIT:
+ case EXEC_OMP_TASKYIELD:
case EXEC_OMP_WORKSHARE:
res = gfc_trans_omp_directive (code);
break;