tree
c_finish_omp_critical (location_t loc, tree body, tree name, tree clauses)
{
+ gcc_assert (!clauses || OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_HINT);
+ if (name == NULL_TREE
+ && clauses != NULL_TREE
+ && integer_nonzerop (OMP_CLAUSE_HINT_EXPR (clauses)))
+ {
+ error_at (OMP_CLAUSE_LOCATION (clauses),
+ "%<#pragma omp critical%> with %<hint%> clause requires "
+ "a name, except when %<omp_sync_hint_none%> is used");
+ return error_mark_node;
+ }
+
tree stmt = make_node (OMP_CRITICAL);
TREE_TYPE (stmt) = void_type_node;
OMP_CRITICAL_BODY (stmt) = body;
expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
tree c, t = expr.value;
t = c_fully_fold (t, false, NULL);
-
- parens.skip_until_found_close (parser);
-
if (!INTEGRAL_TYPE_P (TREE_TYPE (t))
- || TREE_CODE (t) != INTEGER_CST)
+ || TREE_CODE (t) != INTEGER_CST
+ || tree_int_cst_sgn (t) == -1)
{
- c_parser_error (parser, "expected constant integer expression");
+ c_parser_error (parser, "expected constant integer expression "
+ "with valid sync-hint value");
return list;
}
-
+ parens.skip_until_found_close (parser);
check_no_duplicate_clause (list, OMP_CLAUSE_HINT, "hint");
c = build_omp_clause (hint_loc, OMP_CLAUSE_HINT);
if (c_parser_next_token_is (parser, CPP_COMMA)
&& c_parser_peek_2nd_token (parser)->type == CPP_NAME)
c_parser_consume_token (parser);
-
- clauses = c_parser_omp_all_clauses (parser,
- OMP_CRITICAL_CLAUSE_MASK,
- "#pragma omp critical");
}
- else
- {
- if (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
- c_parser_error (parser, "expected %<(%> or end of line");
- c_parser_skip_to_pragma_eol (parser);
- }
-
+ clauses = c_parser_omp_all_clauses (parser, OMP_CRITICAL_CLAUSE_MASK,
+ "#pragma omp critical");
stmt = c_parser_omp_structured_block (parser, if_p);
return c_finish_omp_critical (loc, stmt, name, clauses);
}
gcc_unreachable ();
}
- if (stmt)
+ if (stmt && stmt != error_mark_node)
gcc_assert (EXPR_LOCATION (stmt) != UNKNOWN_LOCATION);
}
t = cp_parser_assignment_expression (parser);
+ if (t != error_mark_node)
+ {
+ t = fold_non_dependent_expr (t);
+ if (!value_dependent_expression_p (t)
+ && (!INTEGRAL_TYPE_P (TREE_TYPE (t))
+ || !tree_fits_shwi_p (t)
+ || tree_int_cst_sgn (t) == -1))
+ error_at (location, "expected constant integer expression with "
+ "valid sync-hint value");
+ }
if (t == error_mark_node
|| !parens.require_close (parser))
cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
/*or_comma=*/false,
/*consume_paren=*/true);
-
check_no_duplicate_clause (list, OMP_CLAUSE_HINT, "hint", location);
c = build_omp_clause (location, OMP_CLAUSE_HINT);
if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA)
&& cp_lexer_nth_token_is (parser->lexer, 2, CPP_NAME))
cp_lexer_consume_token (parser->lexer);
-
- clauses = cp_parser_omp_all_clauses (parser,
- OMP_CRITICAL_CLAUSE_MASK,
- "#pragma omp critical", pragma_tok);
}
- else
- cp_parser_require_pragma_eol (parser, pragma_tok);
+
+ clauses = cp_parser_omp_all_clauses (parser, OMP_CRITICAL_CLAUSE_MASK,
+ "#pragma omp critical", pragma_tok);
stmt = cp_parser_omp_structured_block (parser, if_p);
return c_finish_omp_critical (input_location, stmt, name, clauses);
stmt = pop_stmt_list (stmt);
}
+ if (TREE_CODE (t) == OMP_CRITICAL
+ && tmp != NULL_TREE
+ && integer_nonzerop (OMP_CLAUSE_HINT_EXPR (tmp)))
+ {
+ error_at (OMP_CLAUSE_LOCATION (tmp),
+ "%<#pragma omp critical%> with %<hint%> clause requires "
+ "a name, except when %<omp_sync_hint_none%> is used");
+ RETURN (error_mark_node);
+ }
t = copy_node (t);
OMP_BODY (t) = stmt;
OMP_CLAUSES (t) = tmp;
gfc_omp_clauses *c = NULL;
if (gfc_match (" ( %n )", n) != MATCH_YES)
- {
- n[0] = '\0';
- if (gfc_match_omp_eos () != MATCH_YES)
- {
- gfc_error ("Unexpected junk after $OMP CRITICAL statement at %C");
- return MATCH_ERROR;
- }
- }
- else if (gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_HINT)) != MATCH_YES)
+ n[0] = '\0';
+
+ if (gfc_match_omp_clauses (&c, omp_mask (OMP_CLAUSE_HINT),
+ /* first = */ n[0] == '\0') != MATCH_YES)
return MATCH_ERROR;
new_st.op = EXEC_OMP_CRITICAL;
if (omp_clauses->device)
resolve_nonnegative_int_expr (omp_clauses->device, "DEVICE");
if (omp_clauses->hint)
- resolve_scalar_int_expr (omp_clauses->hint, "HINT");
+ {
+ resolve_scalar_int_expr (omp_clauses->hint, "HINT");
+ if (omp_clauses->hint->ts.type != BT_INTEGER
+ || omp_clauses->hint->expr_type != EXPR_CONSTANT
+ || mpz_sgn (omp_clauses->hint->value.integer) < 0)
+ gfc_error ("Value of HINT clause at %L shall be a valid "
+ "constant hint expression", &omp_clauses->hint->where);
+ }
if (omp_clauses->priority)
resolve_nonnegative_int_expr (omp_clauses->priority, "PRIORITY");
if (omp_clauses->dist_chunk_size)
case EXEC_OMP_ATOMIC:
resolve_omp_atomic (code);
break;
+ case EXEC_OMP_CRITICAL:
+ if (code->ext.omp_clauses)
+ resolve_omp_clauses (code, code->ext.omp_clauses, NULL);
+ if (!code->ext.omp_clauses->critical_name
+ && code->ext.omp_clauses->hint
+ && code->ext.omp_clauses->hint->ts.type == BT_INTEGER
+ && code->ext.omp_clauses->hint->expr_type == EXPR_CONSTANT
+ && mpz_sgn (code->ext.omp_clauses->hint->value.integer) != 0)
+ gfc_error ("OMP CRITICAL at %L with HINT clause requires a NAME, "
+ "except when omp_sync_hint_none is used", &code->loc);
+ break;
default:
break;
}
cp->ext.omp_clauses->nowait |= new_st.ext.omp_bool;
break;
case EXEC_OMP_END_CRITICAL:
- if (((cp->ext.omp_clauses == NULL) ^ (new_st.ext.omp_name == NULL))
+ if (((cp->ext.omp_clauses->critical_name == NULL)
+ ^ (new_st.ext.omp_name == NULL))
|| (new_st.ext.omp_name != NULL
&& strcmp (cp->ext.omp_clauses->critical_name,
new_st.ext.omp_name) != 0))
static tree
gfc_trans_omp_critical (gfc_code *code)
{
- tree name = NULL_TREE, stmt;
- if (code->ext.omp_clauses != NULL)
+ stmtblock_t block;
+ tree stmt, name = NULL_TREE;
+ if (code->ext.omp_clauses->critical_name != NULL)
name = get_identifier (code->ext.omp_clauses->critical_name);
- stmt = gfc_trans_code (code->block->next);
- return build3_loc (input_location, OMP_CRITICAL, void_type_node, stmt,
- NULL_TREE, name);
+ gfc_start_block (&block);
+ stmt = make_node (OMP_CRITICAL);
+ TREE_TYPE (stmt) = void_type_node;
+ OMP_CRITICAL_BODY (stmt) = gfc_trans_code (code->block->next);
+ OMP_CRITICAL_NAME (stmt) = name;
+ OMP_CRITICAL_CLAUSES (stmt) = gfc_trans_omp_clauses (&block,
+ code->ext.omp_clauses,
+ code->loc);
+ gfc_add_expr_to_block (&block, stmt);
+ return gfc_finish_block (&block);
}
typedef struct dovar_init_d {
--- /dev/null
+#include <omp.h>
+
+void
+example_criticial ()
+{
+ int a, b;
+ #pragma omp parallel for
+ for (int i = 0; i < 10; ++i)
+ {
+ #pragma omp critical hint(omp_sync_hint_none) /* OK */
+ a += i;
+ #pragma omp critical (HASH) hint(omp_sync_hint_none) /* OK */
+ a += i;
+ #pragma omp critical (HASH2) hint(omp_sync_hint_uncontended) /* OK */
+ a += i;
+ #pragma omp critical (HASH3) hint(omp_sync_hint_contended) /* OK */
+ a += i;
+ #pragma omp critical (HASH4) hint(omp_sync_hint_speculative) /* OK */
+ a += i;
+ #pragma omp critical (HASH5) hint(omp_sync_hint_nonspeculative) /* OK */
+ a += i;
+ #pragma omp critical (HASH6) hint(omp_sync_hint_contended + omp_sync_hint_speculative) /* OK */
+ a += i;
+ #pragma omp critical (HASH6) hint(omp_sync_hint_contended | omp_sync_hint_speculative) /* OK */
+ a += i;
+
+ /* Accepted but invalid: different hint for same name. */
+ #pragma omp critical (HASH6) hint(omp_sync_hint_uncontended + omp_sync_hint_speculative)
+ a += i;
+ /* Accepted but invalid: Some random integer expr. */
+ #pragma omp critical (HASH) hint(omp_sync_hint_speculative + 1 + 2)
+ a += i;
+
+ #pragma omp critical (HASH) hint(-3) /* { dg-error "expected constant integer expression" } */
+ a += i;
+ #pragma omp critical (HASH2) hint(b) /* { dg-error "constant integer expression" } */
+ a += i;
+/*
+ Fails with gcc as 'expected identifier' and
+ with g++ as "clause requires a name, except when 'omp_sync_hint_none'"
+ #pragma omp critical () hint(omp_sync_hint_speculative)
+ a += i;
+*/
+ #pragma omp critical hint(omp_sync_hint_speculative) /* { dg-error "with 'hint' clause requires a name, except when 'omp_sync_hint_none' is used" } */
+ a += i;
+ }
+}
--- /dev/null
+/* { dg-additional-options "-fdump-tree-original" } */
+#include <omp.h>
+
+void
+example_criticial ()
+{
+ int a, b;
+ #pragma omp parallel for
+ for (int i = 0; i < 10; ++i)
+ {
+ #pragma omp critical hint(omp_sync_hint_none)
+ a += i;
+ #pragma omp critical (HASH1) hint(omp_sync_hint_none)
+ a += i;
+ #pragma omp critical (HASH2) hint(omp_sync_hint_uncontended)
+ a += i;
+ #pragma omp critical (HASH3) hint(omp_sync_hint_contended)
+ a += i;
+ #pragma omp critical (HASH4) hint(omp_sync_hint_speculative)
+ a += i;
+ #pragma omp critical (HASH5) hint(omp_sync_hint_nonspeculative)
+ a += i;
+ #pragma omp critical (HASH6) hint(omp_sync_hint_contended + omp_sync_hint_speculative)
+ a += i;
+ #pragma omp critical (HASH7) hint(omp_sync_hint_contended | omp_sync_hint_speculative)
+ a += i;
+ }
+}
+
+/* { dg-final { scan-tree-dump-times "omp critical \\(HASH1\\) hint\\(0\\)" 1 "original" } } */
+/* { dg-final { scan-tree-dump-times "omp critical \\(HASH2\\) hint\\(1\\)" 1 "original" } } */
+/* { dg-final { scan-tree-dump-times "omp critical \\(HASH3\\) hint\\(2\\)" 1 "original" } } */
+/* { dg-final { scan-tree-dump-times "omp critical \\(HASH4\\) hint\\(8\\)" 1 "original" } } */
+/* { dg-final { scan-tree-dump-times "omp critical \\(HASH5\\) hint\\(4\\)" 1 "original" } } */
+/* { dg-final { scan-tree-dump-times "omp critical \\(HASH6\\) hint\\(10\\)" 1 "original" } } */
+/* { dg-final { scan-tree-dump-times "omp critical \\(HASH7\\) hint\\(10\\)" 1 "original" } } */
template <int N>
void
-foo (void)
+foo0 (void)
+{
+ #pragma omp critical (foo), hint (N + 1) // { dg-error "critical' with 'hint' clause requires a name, except when 'omp_sync_hint_none' is used" }
+ i++;
+}
+
+template <int N>
+void
+foo_1 (void)
{
#pragma omp critical (foo), hint (N + 1)
i++;
}
+template <int N>
+void
+foobar0 (void)
+{
+ #pragma omp critical hint (N + 0)
+ i++;
+}
+
+template <int N>
+void
+foobar1 (void)
+{
+ #pragma omp critical hint (N + 0) // { dg-error "critical' with 'hint' clause requires a name, except when 'omp_sync_hint_none' is used" }
+ i++;
+}
+
template <int N>
void
bar (void)
void
test ()
{
- foo <0> ();
+ foo0 <0> (); // Error
+ foo_1 <-1> (); // OK
+ foobar0 <0> (); // OK
+ foobar1 <1> (); // Error
bar <0> ();
baz (0.0);
}
--- /dev/null
+subroutine example_criticial ()
+ use omp_lib
+ implicit none
+ integer, parameter :: my_omp_hint = omp_sync_hint_contended
+ integer i, a, b
+
+ !$omp parallel do
+ do i = 1, 10
+ !$omp critical (HASH0) hint(my_omp_hint) ! OK
+ a = a + i;
+ !$omp end critical (HASH0)
+ end do
+ !$omp parallel do
+ do i = 1, 10
+ !$omp critical (HASH1) hint(omp_sync_hint_none) ! OK
+ a = a + i;
+ !$omp end critical (HASH1)
+ end do
+ !$omp parallel do
+ do i = 1, 10
+ !$omp critical (HASH2) hint(omp_sync_hint_uncontended) ! OK
+ a = a + i;
+ !$omp end critical (HASH2)
+ end do
+ !$omp parallel do
+ do i = 1, 10
+ !$omp critical (HASH3) hint(omp_sync_hint_contended) ! OK
+ a = a + i;
+ !$omp end critical (HASH3)
+ end do
+ !$omp parallel do
+ do i = 1, 10
+ !$omp critical (HASH4) hint(omp_sync_hint_speculative) ! OK
+ a = a + i;
+ !$omp end critical (HASH4)
+ end do
+ !$omp parallel do
+ do i = 1, 10
+ !$omp critical (HASH5) hint(omp_sync_hint_nonspeculative) ! OK
+ a = a + i;
+ !$omp end critical (HASH5)
+ end do
+ !$omp parallel do
+ do i = 1, 10
+ !$omp critical (HASH6) hint(omp_sync_hint_contended + omp_sync_hint_speculative) ! OK
+ a = a + i;
+ !$omp end critical (HASH6)
+ end do
+
+ !$omp parallel do
+ do i = 1, 10
+ ! Accepted but invalid: different hint for same name.
+ !$omp critical (HASH6) hint(omp_sync_hint_contended + omp_sync_hint_speculative) ! OK
+ a = a + i;
+ !$omp end critical (HASH6)
+ end do
+ !$omp parallel do
+ do i = 1, 10
+ ! Accepted but invalid: Some random integer expr.
+ !$omp critical (HASH) hint(1 + 2)
+ a = a + i;
+ !$omp end critical (HASH)
+ end do
+ !$omp parallel do
+ do i = 1, 10
+ !$omp critical (HASH) hint(-3) ! { dg-error "shall be a valid constant hint expression" }
+ a = a + i;
+ !$omp end critical (HASH)
+ end do
+ !$omp parallel do
+ do i = 1, 10
+ !$omp critical (HASH2) hint(b) ! { dg-error "shall be a valid constant hint expression" }
+ a = a + i;
+ !$omp end critical (HASH2)
+ end do
+ !$omp parallel do
+ do i = 1, 10
+ !$omp critical () hint(omp_hint_speculative) ! { dg-error "Invalid character in name" }
+ a = a + i;
+! !$omp end critical
+ end do
+ !$omp parallel do
+ do i = 1, 10
+ !$omp critical hint(omp_sync_hint_none) ! OK
+ a = a + i;
+ !$omp end critical
+ end do
+ !$omp parallel do
+ do i = 1, 10
+ !$omp critical hint(omp_sync_hint_contended) ! { dg-error "CRITICAL at .1. with HINT clause requires a NAME, except when omp_sync_hint_none is used" }
+ a = a + i;
+ !$omp end critical
+ end do
+end
--- /dev/null
+! { dg-additional-options "-fdump-tree-original" }
+subroutine example_criticial ()
+ use omp_lib
+ implicit none
+ integer, parameter :: my_omp_hint = omp_sync_hint_contended
+ integer i, a, b
+
+ !$omp parallel do
+ do i = 1, 10
+ !$omp critical (HASH0) hint(my_omp_hint)
+ a = a + i;
+ !$omp end critical (HASH0)
+ end do
+ !$omp parallel do
+ do i = 1, 10
+ !$omp critical (HASH1), hint(omp_sync_hint_none)
+ a = a + i;
+ !$omp end critical (HASH1)
+ end do
+ !$omp parallel do
+ do i = 1, 10
+ !$omp critical (HASH2) hint(omp_sync_hint_uncontended)
+ a = a + i;
+ !$omp end critical (HASH2)
+ end do
+ !$omp parallel do
+ do i = 1, 10
+ !$omp critical (HASH3) hint(omp_sync_hint_contended)
+ a = a + i;
+ !$omp end critical (HASH3)
+ end do
+ !$omp parallel do
+ do i = 1, 10
+ !$omp critical (HASH4) hint(omp_sync_hint_speculative)
+ a = a + i;
+ !$omp end critical (HASH4)
+ end do
+ !$omp parallel do
+ do i = 1, 10
+ !$omp critical (HASH5) hint(omp_sync_hint_nonspeculative)
+ a = a + i;
+ !$omp end critical (HASH5)
+ end do
+ !$omp parallel do
+ do i = 1, 10
+ !$omp critical (HASH6), hint(omp_sync_hint_contended + omp_sync_hint_speculative)
+ a = a + i;
+ !$omp end critical (HASH6)
+ end do
+ !$omp parallel do
+ do i = 1, 10
+ !$omp critical hint(omp_sync_hint_none + omp_sync_hint_none)
+ a = a + i;
+ !$omp end critical
+ end do
+end
+
+! { dg-final { scan-tree-dump-times "omp critical \\(hash0\\) hint\\(2\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "omp critical \\(hash1\\) hint\\(0\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "omp critical \\(hash2\\) hint\\(1\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "omp critical \\(hash3\\) hint\\(2\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "omp critical \\(hash4\\) hint\\(8\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "omp critical \\(hash5\\) hint\\(4\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "omp critical \\(hash6\\) hint\\(10\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "omp critical hint\\(0\\)" 1 "original" } }
integer, parameter :: omp_nest_lock_kind = @OMP_NEST_LOCK_KIND@
integer, parameter :: omp_sched_kind = 4
integer, parameter :: omp_proc_bind_kind = 4
- integer, parameter :: omp_lock_hint_kind = 4
+ integer, parameter :: omp_sync_hint_kind = 4
+ integer, parameter :: omp_lock_hint_kind = omp_sync_hint_kind
integer, parameter :: omp_pause_resource_kind = 4
integer, parameter :: omp_allocator_handle_kind = c_intptr_t
integer, parameter :: omp_alloctrait_key_kind = c_int
integer (omp_proc_bind_kind), &
parameter :: omp_proc_bind_spread = 4
integer (omp_lock_hint_kind), &
- parameter :: omp_lock_hint_none = 0
+ parameter :: omp_sync_hint_none = 0
integer (omp_lock_hint_kind), &
- parameter :: omp_lock_hint_uncontended = 1
+ parameter :: omp_lock_hint_none = omp_sync_hint_none
integer (omp_lock_hint_kind), &
- parameter :: omp_lock_hint_contended = 2
+ parameter :: omp_sync_hint_uncontended = 1
integer (omp_lock_hint_kind), &
- parameter :: omp_lock_hint_nonspeculative = 4
+ parameter :: omp_lock_hint_uncontended &
+ = omp_sync_hint_uncontended
integer (omp_lock_hint_kind), &
- parameter :: omp_lock_hint_speculative = 8
+ parameter :: omp_sync_hint_contended = 2
+ integer (omp_lock_hint_kind), &
+ parameter :: omp_lock_hint_contended &
+ = omp_sync_hint_contended
+ integer (omp_lock_hint_kind), &
+ parameter :: omp_sync_hint_nonspeculative = 4
+ integer (omp_lock_hint_kind), &
+ parameter :: omp_lock_hint_nonspeculative &
+ = omp_sync_hint_nonspeculative
+ integer (omp_lock_hint_kind), &
+ parameter :: omp_sync_hint_speculative = 8
+ integer (omp_lock_hint_kind), &
+ parameter :: omp_lock_hint_speculative &
+ = omp_sync_hint_speculative
integer (kind=omp_pause_resource_kind), &
parameter :: omp_pause_soft = 1
integer (kind=omp_pause_resource_kind), &
parameter (omp_proc_bind_master = 2)
parameter (omp_proc_bind_close = 3)
parameter (omp_proc_bind_spread = 4)
+ integer omp_sync_hint_kind
integer omp_lock_hint_kind
- parameter (omp_lock_hint_kind = 4)
+ parameter (omp_sync_hint_kind = 4)
+ parameter (omp_lock_hint_kind = omp_sync_hint_kind)
+ integer (omp_sync_hint_kind) omp_sync_hint_none
integer (omp_lock_hint_kind) omp_lock_hint_none
+ integer (omp_sync_hint_kind) omp_sync_hint_uncontended
integer (omp_lock_hint_kind) omp_lock_hint_uncontended
- integer (omp_lock_hint_kind) omp_lock_hint_contended
+ integer (omp_sync_hint_kind) omp_sync_hint_contended
+ integer (omp_sync_hint_kind) omp_lock_hint_contended
+ integer (omp_lock_hint_kind) omp_sync_hint_nonspeculative
integer (omp_lock_hint_kind) omp_lock_hint_nonspeculative
+ integer (omp_sync_hint_kind) omp_sync_hint_speculative
integer (omp_lock_hint_kind) omp_lock_hint_speculative
+ parameter (omp_sync_hint_none = 0)
parameter (omp_lock_hint_none = 0)
+ parameter (omp_sync_hint_uncontended = 1)
parameter (omp_lock_hint_uncontended = 1)
+ parameter (omp_sync_hint_contended = 2)
parameter (omp_lock_hint_contended = 2)
+ parameter (omp_sync_hint_nonspeculative = 4)
parameter (omp_lock_hint_nonspeculative = 4)
+ parameter (omp_sync_hint_speculative = 8)
parameter (omp_lock_hint_speculative = 8)
parameter (openmp_version = 201511)
integer omp_pause_resource_kind