aboutsummaryrefslogtreecommitdiff
path: root/gcc/c-family
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/c-family')
-rw-r--r--gcc/c-family/ChangeLog17
-rw-r--r--gcc/c-family/c-common.h4
-rw-r--r--gcc/c-family/c-cppbuiltin.c2
-rw-r--r--gcc/c-family/c-omp.c111
-rw-r--r--gcc/c-family/c-pragma.c1
-rw-r--r--gcc/c-family/c-pragma.h5
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;