diff options
Diffstat (limited to 'gcc/c-family')
-rw-r--r-- | gcc/c-family/ChangeLog | 17 | ||||
-rw-r--r-- | gcc/c-family/c-common.h | 4 | ||||
-rw-r--r-- | gcc/c-family/c-cppbuiltin.c | 2 | ||||
-rw-r--r-- | gcc/c-family/c-omp.c | 111 | ||||
-rw-r--r-- | gcc/c-family/c-pragma.c | 1 | ||||
-rw-r--r-- | gcc/c-family/c-pragma.h | 5 |
6 files changed, 127 insertions, 13 deletions
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 42df0a9..91ed861 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,20 @@ +2011-08-02 Jakub Jelinek <jakub@redhat.com> + + * 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. + 2011-07-25 Dodji Seketeli <dodji@redhat.com> * c-common.h (set_underlying_type): Remove parm name from diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index 4ac7c4a..3a49779 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -1029,9 +1029,11 @@ extern tree c_finish_omp_master (location_t, tree); extern tree c_finish_omp_critical (location_t, tree, tree); extern tree c_finish_omp_ordered (location_t, tree); extern void c_finish_omp_barrier (location_t); -extern tree c_finish_omp_atomic (location_t, enum tree_code, tree, tree); +extern tree c_finish_omp_atomic (location_t, enum tree_code, enum tree_code, + tree, tree, tree, tree, tree); extern void c_finish_omp_flush (location_t); extern void c_finish_omp_taskwait (location_t); +extern void c_finish_omp_taskyield (location_t); extern tree c_finish_omp_for (location_t, tree, tree, tree, tree, tree, tree); extern void c_split_parallel_clauses (location_t, tree, tree *, tree *); extern enum omp_clause_default_kind c_omp_predetermined_sharing (tree); diff --git a/gcc/c-family/c-cppbuiltin.c b/gcc/c-family/c-cppbuiltin.c index 9f0918d..a960cbe 100644 --- a/gcc/c-family/c-cppbuiltin.c +++ b/gcc/c-family/c-cppbuiltin.c @@ -807,7 +807,7 @@ c_cpp_builtins (cpp_reader *pfile) cpp_define (pfile, "__SSP__=1"); if (flag_openmp) - cpp_define (pfile, "_OPENMP=200805"); + cpp_define (pfile, "_OPENMP=201107"); if (int128_integer_type_node != NULL_TREE) builtin_define_type_sizeof ("__SIZEOF_INT128__", diff --git a/gcc/c-family/c-omp.c b/gcc/c-family/c-omp.c index 340656f..4a5b0ca 100644 --- a/gcc/c-family/c-omp.c +++ b/gcc/c-family/c-omp.c @@ -1,7 +1,8 @@ /* This file contains routines to construct GNU OpenMP constructs, called from parsing in the C and C++ front ends. - Copyright (C) 2005, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2005, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. Contributed by Richard Henderson <rth@redhat.com>, Diego Novillo <dnovillo@redhat.com>. @@ -96,18 +97,39 @@ c_finish_omp_taskwait (location_t loc) } -/* Complete a #pragma omp atomic construct. The expression to be - implemented atomically is LHS code= RHS. LOC is the location of - the atomic statement. The value returned is either error_mark_node - (if the construct was erroneous) or an OMP_ATOMIC node which should - be added to the current statement tree with add_stmt.*/ +/* Complete a #pragma omp taskyield construct. LOC is the location of the + pragma. */ + +void +c_finish_omp_taskyield (location_t loc) +{ + tree x; + + x = built_in_decls[BUILT_IN_GOMP_TASKYIELD]; + x = build_call_expr_loc (loc, x, 0); + add_stmt (x); +} + + +/* Complete a #pragma omp atomic construct. For CODE OMP_ATOMIC + the expression to be implemented atomically is LHS opcode= RHS. + For OMP_ATOMIC_READ V = LHS, for OMP_ATOMIC_CAPTURE_{NEW,OLD} LHS + opcode= RHS with the new or old content of LHS returned. + LOC is the location of the atomic statement. The value returned + is either error_mark_node (if the construct was erroneous) or an + OMP_ATOMIC* node which should be added to the current statement + tree with add_stmt. */ tree -c_finish_omp_atomic (location_t loc, enum tree_code code, tree lhs, tree rhs) +c_finish_omp_atomic (location_t loc, enum tree_code code, + enum tree_code opcode, tree lhs, tree rhs, + tree v, tree lhs1, tree rhs1) { tree x, type, addr; - if (lhs == error_mark_node || rhs == error_mark_node) + if (lhs == error_mark_node || rhs == error_mark_node + || v == error_mark_node || lhs1 == error_mark_node + || rhs1 == error_mark_node) return error_mark_node; /* ??? According to one reading of the OpenMP spec, complex type are @@ -143,10 +165,19 @@ c_finish_omp_atomic (location_t loc, enum tree_code code, tree lhs, tree rhs) } lhs = build_indirect_ref (loc, addr, RO_NULL); + if (code == OMP_ATOMIC_READ) + { + x = build1 (OMP_ATOMIC_READ, type, addr); + SET_EXPR_LOCATION (x, loc); + return build_modify_expr (loc, v, NULL_TREE, NOP_EXPR, + loc, x, NULL_TREE); + return x; + } + /* There are lots of warnings, errors, and conversions that need to happen in the course of interpreting a statement. Use the normal mechanisms to do this, and then take it apart again. */ - x = build_modify_expr (input_location, lhs, NULL_TREE, code, + x = build_modify_expr (input_location, lhs, NULL_TREE, opcode, input_location, rhs, NULL_TREE); if (x == error_mark_node) return error_mark_node; @@ -154,8 +185,68 @@ c_finish_omp_atomic (location_t loc, enum tree_code code, tree lhs, tree rhs) rhs = TREE_OPERAND (x, 1); /* Punt the actual generation of atomic operations to common code. */ - x = build2 (OMP_ATOMIC, void_type_node, addr, rhs); + if (code == OMP_ATOMIC) + type = void_type_node; + x = build2 (code, type, addr, rhs); SET_EXPR_LOCATION (x, loc); + + /* Generally it is hard to prove lhs1 and lhs are the same memory + location, just diagnose different variables. */ + if (rhs1 + && TREE_CODE (rhs1) == VAR_DECL + && TREE_CODE (lhs) == VAR_DECL + && rhs1 != lhs) + { + if (code == OMP_ATOMIC) + error_at (loc, "%<#pragma omp atomic update%> uses two different variables for memory"); + else + error_at (loc, "%<#pragma omp atomic capture%> uses two different variables for memory"); + return error_mark_node; + } + + if (code != OMP_ATOMIC) + { + /* Generally it is hard to prove lhs1 and lhs are the same memory + location, just diagnose different variables. */ + if (lhs1 && TREE_CODE (lhs1) == VAR_DECL && TREE_CODE (lhs) == VAR_DECL) + { + if (lhs1 != lhs) + { + error_at (loc, "%<#pragma omp atomic capture%> uses two different variables for memory"); + return error_mark_node; + } + } + x = build_modify_expr (loc, v, NULL_TREE, NOP_EXPR, + loc, x, NULL_TREE); + if (rhs1 && rhs1 != lhs) + { + tree rhs1addr = build_unary_op (loc, ADDR_EXPR, rhs1, 0); + if (rhs1addr == error_mark_node) + return error_mark_node; + x = omit_one_operand_loc (loc, type, x, rhs1addr); + } + if (lhs1 && lhs1 != lhs) + { + tree lhs1addr = build_unary_op (loc, ADDR_EXPR, lhs1, 0); + if (lhs1addr == error_mark_node) + return error_mark_node; + if (code == OMP_ATOMIC_CAPTURE_OLD) + x = omit_one_operand_loc (loc, type, x, lhs1addr); + else + { + x = save_expr (x); + x = omit_two_operands_loc (loc, type, x, x, lhs1addr); + } + } + } + else if (rhs1 && rhs1 != lhs) + { + tree rhs1addr = build_unary_op (loc, ADDR_EXPR, rhs1, 0); + if (rhs1addr == error_mark_node) + return error_mark_node; + x = omit_one_operand_loc (loc, type, x, rhs1addr); + } + return x; } diff --git a/gcc/c-family/c-pragma.c b/gcc/c-family/c-pragma.c index 5c8bc1f..7622f0b 100644 --- a/gcc/c-family/c-pragma.c +++ b/gcc/c-family/c-pragma.c @@ -1196,6 +1196,7 @@ static const struct omp_pragma_def omp_pragmas[] = { { "single", PRAGMA_OMP_SINGLE }, { "task", PRAGMA_OMP_TASK }, { "taskwait", PRAGMA_OMP_TASKWAIT }, + { "taskyield", PRAGMA_OMP_TASKYIELD }, { "threadprivate", PRAGMA_OMP_THREADPRIVATE } }; diff --git a/gcc/c-family/c-pragma.h b/gcc/c-family/c-pragma.h index d231c25..04af94f 100644 --- a/gcc/c-family/c-pragma.h +++ b/gcc/c-family/c-pragma.h @@ -43,6 +43,7 @@ typedef enum pragma_kind { PRAGMA_OMP_SINGLE, PRAGMA_OMP_TASK, PRAGMA_OMP_TASKWAIT, + PRAGMA_OMP_TASKYIELD, PRAGMA_OMP_THREADPRIVATE, PRAGMA_GCC_PCH_PREPROCESS, @@ -70,7 +71,9 @@ typedef enum pragma_omp_clause { PRAGMA_OMP_CLAUSE_REDUCTION, PRAGMA_OMP_CLAUSE_SCHEDULE, PRAGMA_OMP_CLAUSE_SHARED, - PRAGMA_OMP_CLAUSE_UNTIED + PRAGMA_OMP_CLAUSE_UNTIED, + PRAGMA_OMP_CLAUSE_FINAL, + PRAGMA_OMP_CLAUSE_MERGEABLE } pragma_omp_clause; extern struct cpp_reader* parse_in; |