diff options
author | Ian Lance Taylor <iant@golang.org> | 2021-09-13 10:37:49 -0700 |
---|---|---|
committer | Ian Lance Taylor <iant@golang.org> | 2021-09-13 10:37:49 -0700 |
commit | e252b51ccde010cbd2a146485d8045103cd99533 (patch) | |
tree | e060f101cdc32bf5e520de8e5275db9d4236b74c /gcc/c-family/c-omp.c | |
parent | f10c7c4596dda99d2ee872c995ae4aeda65adbdf (diff) | |
parent | 104c05c5284b7822d770ee51a7d91946c7e56d50 (diff) | |
download | gcc-e252b51ccde010cbd2a146485d8045103cd99533.zip gcc-e252b51ccde010cbd2a146485d8045103cd99533.tar.gz gcc-e252b51ccde010cbd2a146485d8045103cd99533.tar.bz2 |
Merge from trunk revision 104c05c5284b7822d770ee51a7d91946c7e56d50.
Diffstat (limited to 'gcc/c-family/c-omp.c')
-rw-r--r-- | gcc/c-family/c-omp.c | 425 |
1 files changed, 407 insertions, 18 deletions
diff --git a/gcc/c-family/c-omp.c b/gcc/c-family/c-omp.c index fb1a0d6..75184a3 100644 --- a/gcc/c-family/c-omp.c +++ b/gcc/c-family/c-omp.c @@ -36,6 +36,7 @@ along with GCC; see the file COPYING3. If not see #include "gimplify.h" #include "langhooks.h" #include "bitmap.h" +#include "gimple-fold.h" /* Complete a #pragma oacc wait construct. LOC is the location of @@ -86,6 +87,20 @@ c_finish_omp_master (location_t loc, tree stmt) return t; } +/* Complete a #pragma omp masked construct. BODY is the structured-block + that follows the pragma. LOC is the location of the #pragma. */ + +tree +c_finish_omp_masked (location_t loc, tree body, tree clauses) +{ + tree stmt = make_node (OMP_MASKED); + TREE_TYPE (stmt) = void_type_node; + OMP_MASKED_BODY (stmt) = body; + OMP_MASKED_CLAUSES (stmt) = clauses; + SET_EXPR_LOCATION (stmt, loc); + return add_stmt (stmt); +} + /* Complete a #pragma omp taskgroup construct. BODY is the structured-block that follows the pragma. LOC is the location of the #pragma. */ @@ -201,15 +216,17 @@ c_finish_omp_taskyield (location_t loc) tree 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, bool swapped, - enum omp_memory_order memory_order, bool test) + tree v, tree lhs1, tree rhs1, tree r, bool swapped, + enum omp_memory_order memory_order, bool weak, + bool test) { - tree x, type, addr, pre = NULL_TREE; + tree x, type, addr, pre = NULL_TREE, rtmp = NULL_TREE, vtmp = NULL_TREE; HOST_WIDE_INT bitpos = 0, bitsize = 0; + enum tree_code orig_opcode = opcode; if (lhs == error_mark_node || rhs == error_mark_node || v == error_mark_node || lhs1 == error_mark_node - || rhs1 == error_mark_node) + || rhs1 == error_mark_node || r == error_mark_node) return error_mark_node; /* ??? According to one reading of the OpenMP spec, complex type are @@ -229,6 +246,12 @@ c_finish_omp_atomic (location_t loc, enum tree_code code, error_at (loc, "%<_Atomic%> expression in %<#pragma omp atomic%>"); return error_mark_node; } + if (r && r != void_list_node && !INTEGRAL_TYPE_P (TREE_TYPE (r))) + { + error_at (loc, "%<#pragma omp atomic compare capture%> with non-integral " + "comparison result"); + return error_mark_node; + } if (opcode == RDIV_EXPR) opcode = TRUNC_DIV_EXPR; @@ -285,6 +308,7 @@ c_finish_omp_atomic (location_t loc, enum tree_code code, x = build1 (OMP_ATOMIC_READ, type, addr); SET_EXPR_LOCATION (x, loc); OMP_ATOMIC_MEMORY_ORDER (x) = memory_order; + gcc_assert (!weak); if (blhs) x = build3_loc (loc, BIT_FIELD_REF, TREE_TYPE (blhs), x, bitsize_int (bitsize), bitsize_int (bitpos)); @@ -299,12 +323,29 @@ c_finish_omp_atomic (location_t loc, enum tree_code code, { lhs = build3_loc (loc, BIT_FIELD_REF, TREE_TYPE (blhs), lhs, bitsize_int (bitsize), bitsize_int (bitpos)); - if (swapped) + if (opcode == COND_EXPR) + { + bool save = in_late_binary_op; + in_late_binary_op = true; + std::swap (rhs, rhs1); + rhs1 = build_binary_op (loc, EQ_EXPR, lhs, rhs1, true); + in_late_binary_op = save; + } + else if (swapped) rhs = build_binary_op (loc, opcode, rhs, lhs, true); else if (opcode != NOP_EXPR) rhs = build_binary_op (loc, opcode, lhs, rhs, true); opcode = NOP_EXPR; } + else if (opcode == COND_EXPR) + { + bool save = in_late_binary_op; + in_late_binary_op = true; + std::swap (rhs, rhs1); + rhs1 = build_binary_op (loc, EQ_EXPR, lhs, rhs1, true); + in_late_binary_op = save; + opcode = NOP_EXPR; + } else if (swapped) { rhs = build_binary_op (loc, opcode, rhs, lhs, true); @@ -329,6 +370,100 @@ c_finish_omp_atomic (location_t loc, enum tree_code code, if (blhs) rhs = build3_loc (loc, BIT_INSERT_EXPR, type, new_lhs, rhs, bitsize_int (bitpos)); + if (orig_opcode == COND_EXPR) + { + if (error_operand_p (rhs1)) + return error_mark_node; + gcc_assert (TREE_CODE (rhs1) == EQ_EXPR); + tree cmptype = TREE_TYPE (TREE_OPERAND (rhs1, 0)); + if (SCALAR_FLOAT_TYPE_P (cmptype)) + { + bool clear_padding = false; + if (BITS_PER_UNIT == 8 && CHAR_BIT == 8) + { + HOST_WIDE_INT sz = int_size_in_bytes (cmptype), i; + gcc_assert (sz > 0); + unsigned char *buf = XALLOCAVEC (unsigned char, sz); + memset (buf, ~0, sz); + clear_type_padding_in_mask (cmptype, buf); + for (i = 0; i < sz; i++) + if (buf[i] != (unsigned char) ~0) + { + clear_padding = true; + break; + } + } + tree inttype = NULL_TREE; + if (!clear_padding && tree_fits_uhwi_p (TYPE_SIZE (cmptype))) + { + HOST_WIDE_INT prec = tree_to_uhwi (TYPE_SIZE (cmptype)); + inttype = c_common_type_for_size (prec, 1); + if (inttype + && (!tree_int_cst_equal (TYPE_SIZE (cmptype), + TYPE_SIZE (inttype)) + || TYPE_PRECISION (inttype) != prec)) + inttype = NULL_TREE; + } + if (inttype) + { + TREE_OPERAND (rhs1, 0) + = build1_loc (loc, VIEW_CONVERT_EXPR, inttype, + TREE_OPERAND (rhs1, 0)); + TREE_OPERAND (rhs1, 1) + = build1_loc (loc, VIEW_CONVERT_EXPR, inttype, + TREE_OPERAND (rhs1, 1)); + } + else + { + tree pcmptype = build_pointer_type (cmptype); + tree tmp1 = create_tmp_var_raw (cmptype); + TREE_ADDRESSABLE (tmp1) = 1; + DECL_CONTEXT (tmp1) = current_function_decl; + tmp1 = build4 (TARGET_EXPR, cmptype, tmp1, + TREE_OPERAND (rhs1, 0), NULL, NULL); + tmp1 = build1 (ADDR_EXPR, pcmptype, tmp1); + tree tmp2 = create_tmp_var_raw (cmptype); + TREE_ADDRESSABLE (tmp2) = 1; + DECL_CONTEXT (tmp2) = current_function_decl; + tmp2 = build4 (TARGET_EXPR, cmptype, tmp2, + TREE_OPERAND (rhs1, 1), NULL, NULL); + tmp2 = build1 (ADDR_EXPR, pcmptype, tmp2); + tree fndecl = builtin_decl_explicit (BUILT_IN_MEMCMP); + rhs1 = build_call_expr_loc (loc, fndecl, 3, tmp1, tmp2, + TYPE_SIZE_UNIT (cmptype)); + rhs1 = build2 (EQ_EXPR, boolean_type_node, rhs1, + integer_zero_node); + if (clear_padding) + { + fndecl = builtin_decl_explicit (BUILT_IN_CLEAR_PADDING); + tree cp1 = build_call_expr_loc (loc, fndecl, 1, tmp1); + tree cp2 = build_call_expr_loc (loc, fndecl, 1, tmp2); + rhs1 = omit_two_operands_loc (loc, boolean_type_node, + rhs1, cp2, cp1); + } + } + } + if (r) + { + tree var = create_tmp_var (boolean_type_node); + DECL_CONTEXT (var) = current_function_decl; + rtmp = build4 (TARGET_EXPR, boolean_type_node, var, + NULL, NULL, NULL); + save = in_late_binary_op; + in_late_binary_op = true; + x = build_modify_expr (loc, var, NULL_TREE, NOP_EXPR, + loc, rhs1, NULL_TREE); + in_late_binary_op = save; + if (x == error_mark_node) + return error_mark_node; + gcc_assert (TREE_CODE (x) == MODIFY_EXPR + && TREE_OPERAND (x, 0) == var); + TREE_OPERAND (x, 0) = rtmp; + rhs1 = omit_one_operand_loc (loc, boolean_type_node, x, rtmp); + } + rhs = build3_loc (loc, COND_EXPR, type, rhs1, rhs, new_lhs); + rhs1 = NULL_TREE; + } /* Punt the actual generation of atomic operations to common code. */ if (code == OMP_ATOMIC) @@ -336,6 +471,7 @@ c_finish_omp_atomic (location_t loc, enum tree_code code, x = build2 (code, type, addr, rhs); SET_EXPR_LOCATION (x, loc); OMP_ATOMIC_MEMORY_ORDER (x) = memory_order; + OMP_ATOMIC_WEAK (x) = weak; /* Generally it is hard to prove lhs1 and lhs are the same memory location, just diagnose different variables. */ @@ -398,8 +534,25 @@ c_finish_omp_atomic (location_t loc, enum tree_code code, bitsize_int (bitsize), bitsize_int (bitpos)); type = TREE_TYPE (blhs); } - x = build_modify_expr (loc, v, NULL_TREE, NOP_EXPR, + if (r) + { + vtmp = create_tmp_var (TREE_TYPE (x)); + DECL_CONTEXT (vtmp) = current_function_decl; + } + else + vtmp = v; + x = build_modify_expr (loc, vtmp, NULL_TREE, NOP_EXPR, loc, x, NULL_TREE); + if (x == error_mark_node) + return error_mark_node; + if (r) + { + vtmp = build4 (TARGET_EXPR, boolean_type_node, vtmp, + NULL, NULL, NULL); + gcc_assert (TREE_CODE (x) == MODIFY_EXPR + && TREE_OPERAND (x, 0) == TARGET_EXPR_SLOT (vtmp)); + TREE_OPERAND (x, 0) = vtmp; + } if (rhs1 && rhs1 != orig_lhs) { tree rhs1addr = build_unary_op (loc, ADDR_EXPR, rhs1, false); @@ -432,6 +585,28 @@ c_finish_omp_atomic (location_t loc, enum tree_code code, if (pre) x = omit_one_operand_loc (loc, type, x, pre); + if (r && r != void_list_node) + { + in_late_binary_op = true; + tree x2 = build_modify_expr (loc, r, NULL_TREE, NOP_EXPR, + loc, rtmp, NULL_TREE); + in_late_binary_op = save; + if (x2 == error_mark_node) + return error_mark_node; + x = omit_one_operand_loc (loc, TREE_TYPE (x2), x2, x); + } + if (v && vtmp != v) + { + in_late_binary_op = true; + tree x2 = build_modify_expr (loc, v, NULL_TREE, NOP_EXPR, + loc, vtmp, NULL_TREE); + in_late_binary_op = save; + if (x2 == error_mark_node) + return error_mark_node; + x2 = build3_loc (loc, COND_EXPR, void_type_node, rtmp, + void_node, x2); + x = omit_one_operand_loc (loc, TREE_TYPE (x2), x2, x); + } return x; } @@ -592,7 +767,7 @@ c_finish_omp_flush (location_t loc, int mo) { tree x; - if (mo == MEMMODEL_LAST) + if (mo == MEMMODEL_LAST || mo == MEMMODEL_SEQ_CST) { x = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE); x = build_call_expr_loc (loc, x, 0); @@ -1542,11 +1717,16 @@ c_oacc_split_loop_clauses (tree clauses, tree *not_loop_clauses, #pragma omp distribute parallel for simd #pragma omp distribute simd #pragma omp for simd + #pragma omp masked taskloop + #pragma omp masked taskloop simd #pragma omp master taskloop #pragma omp master taskloop simd #pragma omp parallel for #pragma omp parallel for simd #pragma omp parallel loop + #pragma omp parallel masked + #pragma omp parallel masked taskloop + #pragma omp parallel masked taskloop simd #pragma omp parallel master #pragma omp parallel master taskloop #pragma omp parallel master taskloop simd @@ -1651,6 +1831,9 @@ c_omp_split_clauses (location_t loc, enum tree_code code, case OMP_CLAUSE_BIND: s = C_OMP_CLAUSE_SPLIT_LOOP; break; + case OMP_CLAUSE_FILTER: + s = C_OMP_CLAUSE_SPLIT_MASKED; + break; /* Duplicate this to all of taskloop, distribute, for, simd and loop. */ case OMP_CLAUSE_COLLAPSE: @@ -1700,10 +1883,10 @@ c_omp_split_clauses (location_t loc, enum tree_code code, else s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE; break; - /* Private clause is supported on all constructs but master, - it is enough to put it on the innermost one other than master. For - #pragma omp {for,sections} put it on parallel though, - as that's what we did for OpenMP 3.1. */ + /* Private clause is supported on all constructs but master/masked, + it is enough to put it on the innermost one other than + master/masked. For #pragma omp {for,sections} put it on parallel + though, as that's what we did for OpenMP 3.1. */ case OMP_CLAUSE_PRIVATE: switch (code) { @@ -1713,14 +1896,15 @@ c_omp_split_clauses (location_t loc, enum tree_code code, case OMP_DISTRIBUTE: s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE; break; case OMP_TEAMS: s = C_OMP_CLAUSE_SPLIT_TEAMS; break; case OMP_MASTER: s = C_OMP_CLAUSE_SPLIT_PARALLEL; break; + case OMP_MASKED: s = C_OMP_CLAUSE_SPLIT_PARALLEL; break; case OMP_TASKLOOP: s = C_OMP_CLAUSE_SPLIT_TASKLOOP; break; case OMP_LOOP: s = C_OMP_CLAUSE_SPLIT_LOOP; break; default: gcc_unreachable (); } break; /* Firstprivate clause is supported on all constructs but - simd, master and loop. Put it on the outermost of those and - duplicate on teams and parallel. */ + simd, master, masked and loop. Put it on the outermost of those + and duplicate on teams and parallel. */ case OMP_CLAUSE_FIRSTPRIVATE: if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)) != 0) @@ -1733,10 +1917,21 @@ c_omp_split_clauses (location_t loc, enum tree_code code, { /* This must be #pragma omp target simd. */ s = C_OMP_CLAUSE_SPLIT_TARGET; + OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (clauses) = 1; + OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT_TARGET (clauses) = 1; break; } c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses), OMP_CLAUSE_FIRSTPRIVATE); + /* firstprivate should not be applied to target if it is + also lastprivate or on the combined/composite construct, + or if it is mentioned in map clause. OMP_CLAUSE_DECLs + may need to go through FE handling though (instantiation, + C++ non-static data members, array section lowering), so + add the clause with OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT and + let *finish_omp_clauses and the gimplifier handle it + right. */ + OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c) = 1; OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses); OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TARGET]; cclauses[C_OMP_CLAUSE_SPLIT_TARGET] = c; @@ -1762,7 +1957,7 @@ c_omp_split_clauses (location_t loc, enum tree_code code, else if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP)) != 0) /* This must be - #pragma omp parallel master taskloop{, simd}. */ + #pragma omp parallel mas{ked,ter} taskloop{, simd}. */ s = C_OMP_CLAUSE_SPLIT_TASKLOOP; else /* This must be @@ -1794,9 +1989,10 @@ c_omp_split_clauses (location_t loc, enum tree_code code, else if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP)) != 0) { - /* This must be #pragma omp {,{,parallel }master }taskloop simd + /* This must be + #pragma omp {,{,parallel }mas{ked,ter} }taskloop simd or - #pragma omp {,parallel }master taskloop. */ + #pragma omp {,parallel }mas{ked,ter} taskloop. */ gcc_assert (code == OMP_SIMD || code == OMP_TASKLOOP); s = C_OMP_CLAUSE_SPLIT_TASKLOOP; } @@ -1978,6 +2174,16 @@ c_omp_split_clauses (location_t loc, enum tree_code code, "%<parallel for%>, %<parallel for simd%>"); OMP_CLAUSE_REDUCTION_INSCAN (clauses) = 0; } + if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)) != 0) + { + c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses), + OMP_CLAUSE_MAP); + OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses); + OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_TOFROM); + OMP_CLAUSE_MAP_IMPLICIT (c) = 1; + OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TARGET]; + cclauses[C_OMP_CLAUSE_SPLIT_TARGET] = c; + } if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0) { if (code == OMP_SIMD) @@ -2023,7 +2229,8 @@ c_omp_split_clauses (location_t loc, enum tree_code code, } else if (code == OMP_SECTIONS || code == OMP_PARALLEL - || code == OMP_MASTER) + || code == OMP_MASTER + || code == OMP_MASKED) s = C_OMP_CLAUSE_SPLIT_PARALLEL; else if (code == OMP_TASKLOOP) s = C_OMP_CLAUSE_SPLIT_TASKLOOP; @@ -2048,12 +2255,42 @@ c_omp_split_clauses (location_t loc, enum tree_code code, OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP]; cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP] = c; } + else if ((mask & (OMP_CLAUSE_MASK_1 + << PRAGMA_OMP_CLAUSE_NUM_TEAMS)) != 0) + { + c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses), + OMP_CLAUSE_REDUCTION); + OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses); + OMP_CLAUSE_REDUCTION_CODE (c) + = OMP_CLAUSE_REDUCTION_CODE (clauses); + OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) + = OMP_CLAUSE_REDUCTION_PLACEHOLDER (clauses); + OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c) + = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clauses); + OMP_CLAUSE_REDUCTION_INSCAN (c) + = OMP_CLAUSE_REDUCTION_INSCAN (clauses); + OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS]; + cclauses[C_OMP_CLAUSE_SPLIT_TEAMS] = c; + } s = C_OMP_CLAUSE_SPLIT_SIMD; } else s = C_OMP_CLAUSE_SPLIT_TEAMS; break; case OMP_CLAUSE_IN_REDUCTION: + if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)) != 0) + { + /* When on target, map(always, tofrom: item) is added as + well. For non-combined target it is added in the FEs. */ + c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses), + OMP_CLAUSE_MAP); + OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses); + OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_ALWAYS_TOFROM); + OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TARGET]; + cclauses[C_OMP_CLAUSE_SPLIT_TARGET] = c; + s = C_OMP_CLAUSE_SPLIT_TARGET; + break; + } /* in_reduction on taskloop simd becomes reduction on the simd and keeps being in_reduction on taskloop. */ if (code == OMP_SIMD) @@ -2404,7 +2641,8 @@ c_omp_split_clauses (location_t loc, enum tree_code code, gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_TARGET] == NULL_TREE); if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS)) == 0) gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_TEAMS] == NULL_TREE); - if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) == 0) + if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) == 0 + && (mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FILTER)) == 0) gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE] == NULL_TREE); if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS)) == 0) gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL] == NULL_TREE); @@ -2861,3 +3099,154 @@ c_omp_adjust_map_clauses (tree clauses, bool is_target) } } } + +static const struct c_omp_directive omp_directives[] = { + /* Keep this alphabetically sorted by the first word. Non-null second/third + if any should precede null ones. */ + { "allocate", nullptr, nullptr, PRAGMA_OMP_ALLOCATE, + C_OMP_DIR_DECLARATIVE, false }, + /* { "assume", nullptr, nullptr, PRAGMA_OMP_ASSUME, + C_OMP_DIR_INFORMATIONAL, false }, */ + /* { "assumes", nullptr, nullptr, PRAGMA_OMP_ASSUMES, + C_OMP_DIR_INFORMATIONAL, false }, */ + { "atomic", nullptr, nullptr, PRAGMA_OMP_ATOMIC, + C_OMP_DIR_CONSTRUCT, false }, + { "barrier", nullptr, nullptr, PRAGMA_OMP_BARRIER, + C_OMP_DIR_STANDALONE, false }, + /* { "begin", "assumes", nullptr, PRAGMA_OMP_BEGIN, + C_OMP_DIR_INFORMATIONAL, false }, */ + /* { "begin", "declare", "target", PRAGMA_OMP_BEGIN, + C_OMP_DIR_DECLARATIVE, false }, */ + /* { "begin", "declare", "variant", PRAGMA_OMP_BEGIN, + C_OMP_DIR_DECLARATIVE, false }, */ + /* { "begin", "metadirective", nullptr, PRAGMA_OMP_BEGIN, + C_OMP_DIR_???, ??? }, */ + { "cancel", nullptr, nullptr, PRAGMA_OMP_CANCEL, + C_OMP_DIR_STANDALONE, false }, + { "cancellation", "point", nullptr, PRAGMA_OMP_CANCELLATION_POINT, + C_OMP_DIR_STANDALONE, false }, + { "critical", nullptr, nullptr, PRAGMA_OMP_CRITICAL, + C_OMP_DIR_CONSTRUCT, false }, + /* { "declare", "mapper", nullptr, PRAGMA_OMP_DECLARE, + C_OMP_DIR_DECLARATIVE, false }, */ + { "declare", "reduction", nullptr, PRAGMA_OMP_DECLARE, + C_OMP_DIR_DECLARATIVE, true }, + { "declare", "simd", nullptr, PRAGMA_OMP_DECLARE, + C_OMP_DIR_DECLARATIVE, true }, + { "declare", "target", nullptr, PRAGMA_OMP_DECLARE, + C_OMP_DIR_DECLARATIVE, false }, + { "declare", "variant", nullptr, PRAGMA_OMP_DECLARE, + C_OMP_DIR_DECLARATIVE, false }, + { "depobj", nullptr, nullptr, PRAGMA_OMP_DEPOBJ, + C_OMP_DIR_STANDALONE, false }, + /* { "dispatch", nullptr, nullptr, PRAGMA_OMP_DISPATCH, + C_OMP_DIR_CONSTRUCT, false }, */ + { "distribute", nullptr, nullptr, PRAGMA_OMP_DISTRIBUTE, + C_OMP_DIR_CONSTRUCT, true }, + /* { "end", "assumes", nullptr, PRAGMA_OMP_END, + C_OMP_DIR_INFORMATIONAL, false }, */ + { "end", "declare", "target", PRAGMA_OMP_END_DECLARE_TARGET, + C_OMP_DIR_DECLARATIVE, false }, + /* { "end", "declare", "variant", PRAGMA_OMP_END, + C_OMP_DIR_DECLARATIVE, false }, */ + /* { "end", "metadirective", nullptr, PRAGMA_OMP_END, + C_OMP_DIR_???, ??? }, */ + /* error with at(execution) is C_OMP_DIR_STANDALONE. */ + { "error", nullptr, nullptr, PRAGMA_OMP_ERROR, + C_OMP_DIR_UTILITY, false }, + { "flush", nullptr, nullptr, PRAGMA_OMP_FLUSH, + C_OMP_DIR_STANDALONE, false }, + { "for", nullptr, nullptr, PRAGMA_OMP_FOR, + C_OMP_DIR_CONSTRUCT, true }, + /* { "interop", nullptr, nullptr, PRAGMA_OMP_INTEROP, + C_OMP_DIR_STANDALONE, false }, */ + { "loop", nullptr, nullptr, PRAGMA_OMP_LOOP, + C_OMP_DIR_CONSTRUCT, true }, + { "masked", nullptr, nullptr, PRAGMA_OMP_MASKED, + C_OMP_DIR_CONSTRUCT, true }, + { "master", nullptr, nullptr, PRAGMA_OMP_MASTER, + C_OMP_DIR_CONSTRUCT, true }, + /* { "metadirective", nullptr, nullptr, PRAGMA_OMP_METADIRECTIVE, + C_OMP_DIR_???, ??? }, */ + { "nothing", nullptr, nullptr, PRAGMA_OMP_NOTHING, + C_OMP_DIR_UTILITY, false }, + /* ordered with depend clause is C_OMP_DIR_STANDALONE. */ + { "ordered", nullptr, nullptr, PRAGMA_OMP_ORDERED, + C_OMP_DIR_CONSTRUCT, true }, + { "parallel", nullptr, nullptr, PRAGMA_OMP_PARALLEL, + C_OMP_DIR_CONSTRUCT, true }, + { "requires", nullptr, nullptr, PRAGMA_OMP_REQUIRES, + C_OMP_DIR_INFORMATIONAL, false }, + { "scan", nullptr, nullptr, PRAGMA_OMP_SCAN, + C_OMP_DIR_CONSTRUCT, true }, + { "scope", nullptr, nullptr, PRAGMA_OMP_SCOPE, + C_OMP_DIR_CONSTRUCT, false }, + { "section", nullptr, nullptr, PRAGMA_OMP_SECTION, + C_OMP_DIR_CONSTRUCT, false }, + { "sections", nullptr, nullptr, PRAGMA_OMP_SECTIONS, + C_OMP_DIR_CONSTRUCT, false }, + { "simd", nullptr, nullptr, PRAGMA_OMP_SIMD, + C_OMP_DIR_CONSTRUCT, true }, + { "single", nullptr, nullptr, PRAGMA_OMP_SINGLE, + C_OMP_DIR_CONSTRUCT, false }, + { "target", "data", nullptr, PRAGMA_OMP_TARGET, + C_OMP_DIR_CONSTRUCT, false }, + { "target", "enter", "data", PRAGMA_OMP_TARGET, + C_OMP_DIR_STANDALONE, false }, + { "target", "exit", "data", PRAGMA_OMP_TARGET, + C_OMP_DIR_STANDALONE, false }, + { "target", "update", nullptr, PRAGMA_OMP_TARGET, + C_OMP_DIR_STANDALONE, false }, + { "target", nullptr, nullptr, PRAGMA_OMP_TARGET, + C_OMP_DIR_CONSTRUCT, true }, + { "task", nullptr, nullptr, PRAGMA_OMP_TASK, + C_OMP_DIR_CONSTRUCT, false }, + { "taskgroup", nullptr, nullptr, PRAGMA_OMP_TASKGROUP, + C_OMP_DIR_CONSTRUCT, false }, + { "taskloop", nullptr, nullptr, PRAGMA_OMP_TASKLOOP, + C_OMP_DIR_CONSTRUCT, true }, + { "taskwait", nullptr, nullptr, PRAGMA_OMP_TASKWAIT, + C_OMP_DIR_STANDALONE, false }, + { "taskyield", nullptr, nullptr, PRAGMA_OMP_TASKYIELD, + C_OMP_DIR_STANDALONE, false }, + /* { "tile", nullptr, nullptr, PRAGMA_OMP_TILE, + C_OMP_DIR_CONSTRUCT, false }, */ + { "teams", nullptr, nullptr, PRAGMA_OMP_TEAMS, + C_OMP_DIR_CONSTRUCT, true }, + { "threadprivate", nullptr, nullptr, PRAGMA_OMP_THREADPRIVATE, + C_OMP_DIR_DECLARATIVE, false } + /* { "unroll", nullptr, nullptr, PRAGMA_OMP_UNROLL, + C_OMP_DIR_CONSTRUCT, false }, */ +}; + +/* Find (non-combined/composite) OpenMP directive (if any) which starts + with FIRST keyword and for multi-word directives has SECOND and + THIRD keyword after it. */ + +const struct c_omp_directive * +c_omp_categorize_directive (const char *first, const char *second, + const char *third) +{ + const size_t n_omp_directives = ARRAY_SIZE (omp_directives); + for (size_t i = 0; i < n_omp_directives; i++) + { + if ((unsigned char) omp_directives[i].first[0] + < (unsigned char) first[0]) + continue; + if ((unsigned char) omp_directives[i].first[0] + > (unsigned char) first[0]) + break; + if (strcmp (omp_directives[i].first, first)) + continue; + if (!omp_directives[i].second) + return &omp_directives[i]; + if (!second || strcmp (omp_directives[i].second, second)) + continue; + if (!omp_directives[i].third) + return &omp_directives[i]; + if (!third || strcmp (omp_directives[i].third, third)) + continue; + return &omp_directives[i]; + } + return NULL; +} |