aboutsummaryrefslogtreecommitdiff
path: root/gcc/gimplify.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2021-09-10 20:41:33 +0200
committerJakub Jelinek <jakub@redhat.com>2021-09-10 20:41:33 +0200
commit8122fbff770bcff183a9c3c72e8092c0ca32150b (patch)
treece01fc417dc7920da04a312ab2abcd350adec6c0 /gcc/gimplify.c
parentb7f84702b364d49824ca97d4a2fc01567301d784 (diff)
downloadgcc-8122fbff770bcff183a9c3c72e8092c0ca32150b.zip
gcc-8122fbff770bcff183a9c3c72e8092c0ca32150b.tar.gz
gcc-8122fbff770bcff183a9c3c72e8092c0ca32150b.tar.bz2
openmp: Implement OpenMP 5.1 atomics, so far for C only
This patch implements OpenMP 5.1 atomics (with clarifications from upcoming 5.2). The most important changes are that it is now possible to write (for C/C++, for Fortran it was possible before already) min/max atomics and more importantly compare and exchange in various forms. Also, acq_rel is now allowed on read/write and acq_rel/acquire are allowed on update, and there are new compare, weak and fail clauses. 2021-09-10 Jakub Jelinek <jakub@redhat.com> gcc/ * tree-core.h (enum omp_memory_order): Add OMP_MEMORY_ORDER_MASK, OMP_FAIL_MEMORY_ORDER_UNSPECIFIED, OMP_FAIL_MEMORY_ORDER_RELAXED, OMP_FAIL_MEMORY_ORDER_ACQUIRE, OMP_FAIL_MEMORY_ORDER_RELEASE, OMP_FAIL_MEMORY_ORDER_ACQ_REL, OMP_FAIL_MEMORY_ORDER_SEQ_CST and OMP_FAIL_MEMORY_ORDER_MASK enumerators. (OMP_FAIL_MEMORY_ORDER_SHIFT): Define. * gimple-pretty-print.c (dump_gimple_omp_atomic_load, dump_gimple_omp_atomic_store): Print [weak] for weak atomic load/store. * gimple.h (enum gf_mask): Change GF_OMP_ATOMIC_MEMORY_ORDER to 6-bit mask, adjust GF_OMP_ATOMIC_NEED_VALUE value and add GF_OMP_ATOMIC_WEAK. (gimple_omp_atomic_weak_p, gimple_omp_atomic_set_weak): New inline functions. * tree.h (OMP_ATOMIC_WEAK): Define. * tree-pretty-print.c (dump_omp_atomic_memory_order): Adjust for fail memory order being encoded in the same enum and also print fail clause if present. (dump_generic_node): Print weak clause if OMP_ATOMIC_WEAK. * gimplify.c (goa_stabilize_expr): Add target_expr and rhs arguments, handle pre_p == NULL case as a test mode that only returns value but doesn't change gimplify nor change anything otherwise, adjust recursive calls, add MODIFY_EXPR, ADDR_EXPR, COND_EXPR, TARGET_EXPR and CALL_EXPR handling, adjust COMPOUND_EXPR handling for __builtin_clear_padding calls, for !rhs gimplify as lvalue rather than rvalue. (gimplify_omp_atomic): Adjust goa_stabilize_expr caller. Handle COND_EXPR rhs. Set weak flag on gimple load/store for OMP_ATOMIC_WEAK. * omp-expand.c (omp_memory_order_to_fail_memmodel): New function. (omp_memory_order_to_memmodel): Adjust for fail clause encoded in the same enum. (expand_omp_atomic_cas): New function. (expand_omp_atomic_pipeline): Use omp_memory_order_to_fail_memmodel function. (expand_omp_atomic): Attempt to optimize atomic compare and exchange using expand_omp_atomic_cas. gcc/c-family/ * c-common.h (c_finish_omp_atomic): Add r and weak arguments. * c-omp.c: Include gimple-fold.h. (c_finish_omp_atomic): Add r and weak arguments. Add support for OpenMP 5.1 atomics. gcc/c/ * c-parser.c (c_parser_conditional_expression): If omp_atomic_lhs and cond.value is >, < or == with omp_atomic_lhs as one of the operands, don't call build_conditional_expr, instead build a COND_EXPR directly. (c_parser_binary_expression): Avoid calling parser_build_binary_op if omp_atomic_lhs even in more cases for >, < or ==. (c_parser_omp_atomic): Update function comment for OpenMP 5.1 atomics, parse OpenMP 5.1 atomics and fail, compare and weak clauses, allow acq_rel on atomic read/write and acq_rel/acquire clauses on update. * c-typeck.c (build_binary_op): For flag_openmp only handle MIN_EXPR/MAX_EXPR. gcc/cp/ * parser.c (cp_parser_omp_atomic): Allow acq_rel on atomic read/write and acq_rel/acquire clauses on update. * semantics.c (finish_omp_atomic): Adjust c_finish_omp_atomic caller. gcc/testsuite/ * c-c++-common/gomp/atomic-17.c (foo): Add tests for atomic read, write or update with acq_rel clause and atomic update with acquire clause. * c-c++-common/gomp/atomic-18.c (foo): Adjust expected diagnostics wording, remove tests moved to atomic-17.c. * c-c++-common/gomp/atomic-21.c: Expect only 2 omp atomic release and 2 omp atomic acq_rel directives instead of 4 omp atomic release. * c-c++-common/gomp/atomic-25.c: New test. * c-c++-common/gomp/atomic-26.c: New test. * c-c++-common/gomp/atomic-27.c: New test. * c-c++-common/gomp/atomic-28.c: New test. * c-c++-common/gomp/atomic-29.c: New test. * c-c++-common/gomp/atomic-30.c: New test. * c-c++-common/goacc-gomp/atomic.c: Expect 1 omp atomic release and 1 omp atomic_acq_rel instead of 2 omp atomic release directives. * gcc.dg/gomp/atomic-5.c: Adjust expected error diagnostic wording. * g++.dg/gomp/atomic-18.C:Expect 4 omp atomic release and 1 omp atomic_acq_rel instead of 5 omp atomic release directives. libgomp/ * testsuite/libgomp.c-c++-common/atomic-19.c: New test. * testsuite/libgomp.c-c++-common/atomic-20.c: New test. * testsuite/libgomp.c-c++-common/atomic-21.c: New test.
Diffstat (limited to 'gcc/gimplify.c')
-rw-r--r--gcc/gimplify.c161
1 files changed, 138 insertions, 23 deletions
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 8820f87..66dfd25 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -13859,14 +13859,15 @@ goa_lhs_expr_p (tree expr, tree addr)
static int
goa_stabilize_expr (tree *expr_p, gimple_seq *pre_p, tree lhs_addr,
- tree lhs_var)
+ tree lhs_var, tree &target_expr, bool rhs)
{
tree expr = *expr_p;
int saw_lhs;
if (goa_lhs_expr_p (expr, lhs_addr))
{
- *expr_p = lhs_var;
+ if (pre_p)
+ *expr_p = lhs_var;
return 1;
}
if (is_gimple_val (expr))
@@ -13878,11 +13879,11 @@ goa_stabilize_expr (tree *expr_p, gimple_seq *pre_p, tree lhs_addr,
case tcc_binary:
case tcc_comparison:
saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1), pre_p, lhs_addr,
- lhs_var);
+ lhs_var, target_expr, true);
/* FALLTHRU */
case tcc_unary:
saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p, lhs_addr,
- lhs_var);
+ lhs_var, target_expr, true);
break;
case tcc_expression:
switch (TREE_CODE (expr))
@@ -13894,36 +13895,131 @@ goa_stabilize_expr (tree *expr_p, gimple_seq *pre_p, tree lhs_addr,
case TRUTH_XOR_EXPR:
case BIT_INSERT_EXPR:
saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1), pre_p,
- lhs_addr, lhs_var);
+ lhs_addr, lhs_var, target_expr, true);
/* FALLTHRU */
case TRUTH_NOT_EXPR:
saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p,
- lhs_addr, lhs_var);
+ lhs_addr, lhs_var, target_expr, true);
+ break;
+ case MODIFY_EXPR:
+ saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1), pre_p,
+ lhs_addr, lhs_var, target_expr, true);
+ /* FALLTHRU */
+ case ADDR_EXPR:
+ saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p,
+ lhs_addr, lhs_var, target_expr, false);
break;
case COMPOUND_EXPR:
+ /* Special-case __builtin_clear_padding call before
+ __builtin_memcmp. */
+ if (TREE_CODE (TREE_OPERAND (expr, 0)) == CALL_EXPR)
+ {
+ tree fndecl = get_callee_fndecl (TREE_OPERAND (expr, 0));
+ if (fndecl
+ && fndecl_built_in_p (fndecl, BUILT_IN_CLEAR_PADDING)
+ && VOID_TYPE_P (TREE_TYPE (TREE_OPERAND (expr, 0))))
+ {
+ saw_lhs = goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p,
+ lhs_addr, lhs_var,
+ target_expr, true);
+ if (!saw_lhs)
+ {
+ expr = TREE_OPERAND (expr, 1);
+ if (!pre_p)
+ return goa_stabilize_expr (&expr, pre_p, lhs_addr,
+ lhs_var, target_expr, true);
+ *expr_p = expr;
+ return goa_stabilize_expr (expr_p, pre_p, lhs_addr,
+ lhs_var, target_expr, true);
+ }
+ else
+ {
+ saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1),
+ pre_p, lhs_addr, lhs_var,
+ target_expr, rhs);
+ break;
+ }
+ }
+ }
/* Break out any preevaluations from cp_build_modify_expr. */
for (; TREE_CODE (expr) == COMPOUND_EXPR;
expr = TREE_OPERAND (expr, 1))
- gimplify_stmt (&TREE_OPERAND (expr, 0), pre_p);
+ if (pre_p)
+ gimplify_stmt (&TREE_OPERAND (expr, 0), pre_p);
+ if (!pre_p)
+ return goa_stabilize_expr (&expr, pre_p, lhs_addr, lhs_var,
+ target_expr, rhs);
*expr_p = expr;
- return goa_stabilize_expr (expr_p, pre_p, lhs_addr, lhs_var);
+ return goa_stabilize_expr (expr_p, pre_p, lhs_addr, lhs_var,
+ target_expr, rhs);
+ case COND_EXPR:
+ if (!goa_stabilize_expr (&TREE_OPERAND (expr, 0), NULL, lhs_addr,
+ lhs_var, target_expr, true))
+ break;
+ saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p,
+ lhs_addr, lhs_var, target_expr, true);
+ saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1), pre_p,
+ lhs_addr, lhs_var, target_expr, true);
+ saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 2), pre_p,
+ lhs_addr, lhs_var, target_expr, true);
+ break;
+ case TARGET_EXPR:
+ if (TARGET_EXPR_INITIAL (expr))
+ {
+ if (expr == target_expr)
+ saw_lhs = 1;
+ else
+ {
+ saw_lhs = goa_stabilize_expr (&TARGET_EXPR_INITIAL (expr),
+ pre_p, lhs_addr, lhs_var,
+ target_expr, true);
+ if (saw_lhs && target_expr == NULL_TREE && pre_p)
+ target_expr = expr;
+ }
+ }
+ break;
default:
break;
}
break;
case tcc_reference:
- if (TREE_CODE (expr) == BIT_FIELD_REF)
+ if (TREE_CODE (expr) == BIT_FIELD_REF
+ || TREE_CODE (expr) == VIEW_CONVERT_EXPR)
saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p,
- lhs_addr, lhs_var);
+ lhs_addr, lhs_var, target_expr, true);
+ break;
+ case tcc_vl_exp:
+ if (TREE_CODE (expr) == CALL_EXPR)
+ {
+ if (tree fndecl = get_callee_fndecl (expr))
+ if (fndecl_built_in_p (fndecl, BUILT_IN_CLEAR_PADDING)
+ || fndecl_built_in_p (fndecl, BUILT_IN_MEMCMP))
+ {
+ int nargs = call_expr_nargs (expr);
+ for (int i = 0; i < nargs; i++)
+ saw_lhs |= goa_stabilize_expr (&CALL_EXPR_ARG (expr, i),
+ pre_p, lhs_addr, lhs_var,
+ target_expr, true);
+ }
+ if (saw_lhs == 0 && VOID_TYPE_P (TREE_TYPE (expr)))
+ {
+ if (pre_p)
+ gimplify_stmt (&expr, pre_p);
+ return 0;
+ }
+ }
break;
default:
break;
}
- if (saw_lhs == 0)
+ if (saw_lhs == 0 && pre_p)
{
enum gimplify_status gs;
- gs = gimplify_expr (expr_p, pre_p, NULL, is_gimple_val, fb_rvalue);
+ if (rhs)
+ gs = gimplify_expr (expr_p, pre_p, NULL, is_gimple_val, fb_rvalue);
+ else
+ gs = gimplify_expr (expr_p, pre_p, NULL, is_gimple_lvalue, fb_lvalue);
if (gs != GS_ALL_DONE)
saw_lhs = -1;
}
@@ -13943,9 +14039,12 @@ gimplify_omp_atomic (tree *expr_p, gimple_seq *pre_p)
tree tmp_load;
gomp_atomic_load *loadstmt;
gomp_atomic_store *storestmt;
+ tree target_expr = NULL_TREE;
tmp_load = create_tmp_reg (type);
- if (rhs && goa_stabilize_expr (&rhs, pre_p, addr, tmp_load) < 0)
+ if (rhs
+ && goa_stabilize_expr (&rhs, pre_p, addr, tmp_load, target_expr,
+ true) < 0)
return GS_ERROR;
if (gimplify_expr (&addr, pre_p, NULL, is_gimple_val, fb_rvalue)
@@ -13959,11 +14058,14 @@ gimplify_omp_atomic (tree *expr_p, gimple_seq *pre_p)
{
/* BIT_INSERT_EXPR is not valid for non-integral bitfield
representatives. Use BIT_FIELD_REF on the lhs instead. */
- if (TREE_CODE (rhs) == BIT_INSERT_EXPR
+ tree rhsarg = rhs;
+ if (TREE_CODE (rhs) == COND_EXPR)
+ rhsarg = TREE_OPERAND (rhs, 1);
+ if (TREE_CODE (rhsarg) == BIT_INSERT_EXPR
&& !INTEGRAL_TYPE_P (TREE_TYPE (tmp_load)))
{
- tree bitpos = TREE_OPERAND (rhs, 2);
- tree op1 = TREE_OPERAND (rhs, 1);
+ tree bitpos = TREE_OPERAND (rhsarg, 2);
+ tree op1 = TREE_OPERAND (rhsarg, 1);
tree bitsize;
tree tmp_store = tmp_load;
if (TREE_CODE (*expr_p) == OMP_ATOMIC_CAPTURE_OLD)
@@ -13972,17 +14074,25 @@ gimplify_omp_atomic (tree *expr_p, gimple_seq *pre_p)
bitsize = bitsize_int (TYPE_PRECISION (TREE_TYPE (op1)));
else
bitsize = TYPE_SIZE (TREE_TYPE (op1));
- gcc_assert (TREE_OPERAND (rhs, 0) == tmp_load);
- tree t = build2_loc (EXPR_LOCATION (rhs),
+ gcc_assert (TREE_OPERAND (rhsarg, 0) == tmp_load);
+ tree t = build2_loc (EXPR_LOCATION (rhsarg),
MODIFY_EXPR, void_type_node,
- build3_loc (EXPR_LOCATION (rhs), BIT_FIELD_REF,
- TREE_TYPE (op1), tmp_store, bitsize,
- bitpos), op1);
+ build3_loc (EXPR_LOCATION (rhsarg),
+ BIT_FIELD_REF, TREE_TYPE (op1),
+ tmp_store, bitsize, bitpos), op1);
+ if (TREE_CODE (rhs) == COND_EXPR)
+ t = build3_loc (EXPR_LOCATION (rhs), COND_EXPR, void_type_node,
+ TREE_OPERAND (rhs, 0), t, void_node);
gimplify_and_add (t, pre_p);
rhs = tmp_store;
}
- if (gimplify_expr (&rhs, pre_p, NULL, is_gimple_val, fb_rvalue)
- != GS_ALL_DONE)
+ bool save_allow_rhs_cond_expr = gimplify_ctxp->allow_rhs_cond_expr;
+ if (TREE_CODE (rhs) == COND_EXPR)
+ gimplify_ctxp->allow_rhs_cond_expr = true;
+ enum gimplify_status gs = gimplify_expr (&rhs, pre_p, NULL,
+ is_gimple_val, fb_rvalue);
+ gimplify_ctxp->allow_rhs_cond_expr = save_allow_rhs_cond_expr;
+ if (gs != GS_ALL_DONE)
return GS_ERROR;
}
@@ -13990,6 +14100,11 @@ gimplify_omp_atomic (tree *expr_p, gimple_seq *pre_p)
rhs = tmp_load;
storestmt
= gimple_build_omp_atomic_store (rhs, OMP_ATOMIC_MEMORY_ORDER (*expr_p));
+ if (TREE_CODE (*expr_p) != OMP_ATOMIC_READ && OMP_ATOMIC_WEAK (*expr_p))
+ {
+ gimple_omp_atomic_set_weak (loadstmt);
+ gimple_omp_atomic_set_weak (storestmt);
+ }
gimplify_seq_add_stmt (pre_p, storestmt);
switch (TREE_CODE (*expr_p))
{