aboutsummaryrefslogtreecommitdiff
path: root/gcc/omp-general.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2019-10-25 00:29:09 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2019-10-25 00:29:09 +0200
commit135df52cc3f1ef90092ab02a01c4dabc7fd0ed18 (patch)
tree788a3c845a393f73563f1c4dba757939c85265ff /gcc/omp-general.c
parentf8cb8bcde13df2f2b1a996567c849ec512eec210 (diff)
downloadgcc-135df52cc3f1ef90092ab02a01c4dabc7fd0ed18.zip
gcc-135df52cc3f1ef90092ab02a01c4dabc7fd0ed18.tar.gz
gcc-135df52cc3f1ef90092ab02a01c4dabc7fd0ed18.tar.bz2
gimplify.h (omp_construct_selector_matches): Declare.
* gimplify.h (omp_construct_selector_matches): Declare. * gimplify.c (struct gimplify_omp_ctx): Add code member. (gimplify_call_expr): Call omp_resolve_declare_variant and remap called function if needed for flag_openmp. (gimplify_scan_omp_clauses): Set ctx->code. (omp_construct_selector_matches): New function. * omp-general.h (omp_constructor_traits_to_codes, omp_context_selector_matches, omp_resolve_declare_variant): Declare. * omp-general.c (omp_constructor_traits_to_codes, omp_context_selector_matches, omp_resolve_declare_variant): New functions. c-family/ * c-common.h (c_omp_context_selector_matches): Remove. * c-omp.c (c_omp_context_selector_matches): Remove. * c-attribs.c (c_common_attribute_table): Add "omp declare target {host,nohost,block}" attributes. c/ * c-parser.c (c_finish_omp_declare_variant): Use omp_context_selector_matches instead of c_omp_context_selector_matches. * c-decl.c (c_decl_attributes): Add "omp declare target block" attribute in between declare target and end declare target pragmas. cp/ * decl2.c (cplus_decl_attributes): Add "omp declare target block" attribute in between declare target and end declare target pragmas. testsuite/ * c-c++-common/gomp/declare-variant-8.c: New test. From-SVN: r277427
Diffstat (limited to 'gcc/omp-general.c')
-rw-r--r--gcc/omp-general.c298
1 files changed, 298 insertions, 0 deletions
diff --git a/gcc/omp-general.c b/gcc/omp-general.c
index 1a78a70..9397b19 100644
--- a/gcc/omp-general.c
+++ b/gcc/omp-general.c
@@ -35,6 +35,11 @@ along with GCC; see the file COPYING3. If not see
#include "omp-general.h"
#include "stringpool.h"
#include "attribs.h"
+#include "gimplify.h"
+#include "cgraph.h"
+#include "symbol-summary.h"
+#include "hsa-common.h"
+#include "tree-pass.h"
enum omp_requires omp_requires_mask;
@@ -538,6 +543,299 @@ omp_max_simt_vf (void)
return 0;
}
+/* Store the construct selectors as tree codes from last to first,
+ return their number. */
+
+int
+omp_constructor_traits_to_codes (tree ctx, enum tree_code *constructs)
+{
+ int nconstructs = list_length (ctx);
+ int i = nconstructs - 1;
+ for (tree t2 = ctx; t2; t2 = TREE_CHAIN (t2), i--)
+ {
+ const char *sel = IDENTIFIER_POINTER (TREE_PURPOSE (t2));
+ if (!strcmp (sel, "target"))
+ constructs[i] = OMP_TARGET;
+ else if (!strcmp (sel, "teams"))
+ constructs[i] = OMP_TEAMS;
+ else if (!strcmp (sel, "parallel"))
+ constructs[i] = OMP_PARALLEL;
+ else if (!strcmp (sel, "for") || !strcmp (sel, "do"))
+ constructs[i] = OMP_FOR;
+ else if (!strcmp (sel, "simd"))
+ constructs[i] = OMP_SIMD;
+ else
+ gcc_unreachable ();
+ }
+ gcc_assert (i == -1);
+ return nconstructs;
+}
+
+/* Return 1 if context selector matches the current OpenMP context, 0
+ if it does not and -1 if it is unknown and need to be determined later.
+ Some properties can be checked right away during parsing (this routine),
+ others need to wait until the whole TU is parsed, others need to wait until
+ IPA, others until vectorization. */
+
+int
+omp_context_selector_matches (tree ctx)
+{
+ int ret = 1;
+ for (tree t1 = ctx; t1; t1 = TREE_CHAIN (t1))
+ {
+ char set = IDENTIFIER_POINTER (TREE_PURPOSE (t1))[0];
+ if (set == 'c')
+ {
+ /* For now, ignore the construct set. While something can be
+ determined already during parsing, we don't know until end of TU
+ whether additional constructs aren't added through declare variant
+ unless "omp declare variant variant" attribute exists already
+ (so in most of the cases), and we'd need to maintain set of
+ surrounding OpenMP constructs, which is better handled during
+ gimplification. */
+ if (symtab->state == PARSING
+ || (cfun->curr_properties & PROP_gimple_any) != 0)
+ {
+ ret = -1;
+ continue;
+ }
+
+ enum tree_code constructs[5];
+ int nconstructs
+ = omp_constructor_traits_to_codes (TREE_VALUE (t1), constructs);
+ HOST_WIDE_INT r
+ = omp_construct_selector_matches (constructs, nconstructs);
+ if (r == 0)
+ return 0;
+ if (r == -1)
+ ret = -1;
+ continue;
+ }
+ for (tree t2 = TREE_VALUE (t1); t2; t2 = TREE_CHAIN (t2))
+ {
+ const char *sel = IDENTIFIER_POINTER (TREE_PURPOSE (t2));
+ switch (*sel)
+ {
+ case 'v':
+ if (set == 'i' && !strcmp (sel, "vendor"))
+ for (tree t3 = TREE_VALUE (t2); t3; t3 = TREE_CHAIN (t3))
+ {
+ const char *prop = IDENTIFIER_POINTER (TREE_PURPOSE (t3));
+ if (!strcmp (prop, " score") || !strcmp (prop, "gnu"))
+ continue;
+ return 0;
+ }
+ break;
+ case 'e':
+ if (set == 'i' && !strcmp (sel, "extension"))
+ /* We don't support any extensions right now. */
+ return 0;
+ break;
+ case 'a':
+ if (set == 'i' && !strcmp (sel, "atomic_default_mem_order"))
+ {
+ enum omp_memory_order omo
+ = ((enum omp_memory_order)
+ (omp_requires_mask
+ & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER));
+ if (omo == OMP_MEMORY_ORDER_UNSPECIFIED)
+ {
+ /* We don't know yet, until end of TU. */
+ if (symtab->state == PARSING)
+ {
+ ret = -1;
+ break;
+ }
+ else
+ omo = OMP_MEMORY_ORDER_RELAXED;
+ }
+ tree t3 = TREE_VALUE (t2);
+ const char *prop = IDENTIFIER_POINTER (TREE_PURPOSE (t3));
+ if (!strcmp (prop, " score"))
+ {
+ t3 = TREE_CHAIN (t3);
+ prop = IDENTIFIER_POINTER (TREE_PURPOSE (t3));
+ }
+ if (!strcmp (prop, "relaxed")
+ && omo != OMP_MEMORY_ORDER_RELAXED)
+ return 0;
+ else if (!strcmp (prop, "seq_cst")
+ && omo != OMP_MEMORY_ORDER_SEQ_CST)
+ return 0;
+ else if (!strcmp (prop, "acq_rel")
+ && omo != OMP_MEMORY_ORDER_ACQ_REL)
+ return 0;
+ }
+ if (set == 'd' && !strcmp (sel, "arch"))
+ /* For now, need a target hook. */
+ ret = -1;
+ break;
+ case 'u':
+ if (set == 'i' && !strcmp (sel, "unified_address"))
+ {
+ if ((omp_requires_mask & OMP_REQUIRES_UNIFIED_ADDRESS) == 0)
+ {
+ if (symtab->state == PARSING)
+ ret = -1;
+ else
+ return 0;
+ }
+ break;
+ }
+ if (set == 'i' && !strcmp (sel, "unified_shared_memory"))
+ {
+ if ((omp_requires_mask
+ & OMP_REQUIRES_UNIFIED_SHARED_MEMORY) == 0)
+ {
+ if (symtab->state == PARSING)
+ ret = -1;
+ else
+ return 0;
+ }
+ break;
+ }
+ break;
+ case 'd':
+ if (set == 'i' && !strcmp (sel, "dynamic_allocators"))
+ {
+ if ((omp_requires_mask
+ & OMP_REQUIRES_DYNAMIC_ALLOCATORS) == 0)
+ {
+ if (symtab->state == PARSING)
+ ret = -1;
+ else
+ return 0;
+ }
+ break;
+ }
+ break;
+ case 'r':
+ if (set == 'i' && !strcmp (sel, "reverse_offload"))
+ {
+ if ((omp_requires_mask & OMP_REQUIRES_REVERSE_OFFLOAD) == 0)
+ {
+ if (symtab->state == PARSING)
+ ret = -1;
+ else
+ return 0;
+ }
+ break;
+ }
+ break;
+ case 'k':
+ if (set == 'd' && !strcmp (sel, "kind"))
+ for (tree t3 = TREE_VALUE (t2); t3; t3 = TREE_CHAIN (t3))
+ {
+ const char *prop = IDENTIFIER_POINTER (TREE_PURPOSE (t3));
+ if (!strcmp (prop, "any"))
+ continue;
+ if (!strcmp (prop, "fpga"))
+ return 0; /* Right now GCC doesn't support any fpgas. */
+ if (!strcmp (prop, "host"))
+ {
+ if (ENABLE_OFFLOADING || hsa_gen_requested_p ())
+ ret = -1;
+ continue;
+ }
+ if (!strcmp (prop, "nohost"))
+ {
+ if (ENABLE_OFFLOADING || hsa_gen_requested_p ())
+ ret = -1;
+ else
+ return 0;
+ continue;
+ }
+ if (!strcmp (prop, "cpu") || !strcmp (prop, "gpu"))
+ {
+ bool maybe_gpu = false;
+ if (hsa_gen_requested_p ())
+ maybe_gpu = true;
+ else if (ENABLE_OFFLOADING)
+ for (const char *c = getenv ("OFFLOAD_TARGET_NAMES");
+ c; )
+ {
+ if (!strncmp (c, "nvptx", strlen ("nvptx"))
+ || !strncmp (c, "amdgcn", strlen ("amdgcn")))
+ {
+ maybe_gpu = true;
+ break;
+ }
+ else if ((c = strchr (c, ',')))
+ c++;
+ }
+ if (!maybe_gpu)
+ {
+ if (prop[0] == 'g')
+ return 0;
+ }
+ else
+ ret = -1;
+ continue;
+ }
+ /* Any other kind doesn't match. */
+ return 0;
+ }
+ break;
+ case 'i':
+ if (set == 'd' && !strcmp (sel, "isa"))
+ /* For now, need a target hook. */
+ ret = -1;
+ break;
+ case 'c':
+ if (set == 'u' && !strcmp (sel, "condition"))
+ for (tree t3 = TREE_VALUE (t2); t3; t3 = TREE_CHAIN (t3))
+ if (TREE_PURPOSE (t3) == NULL_TREE)
+ {
+ if (integer_zerop (TREE_VALUE (t3)))
+ return 0;
+ if (integer_nonzerop (TREE_VALUE (t3)))
+ break;
+ ret = -1;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ return ret;
+}
+
+/* Try to resolve declare variant, return the variant decl if it should
+ be used instead of base, or base otherwise. */
+
+tree
+omp_resolve_declare_variant (tree base)
+{
+ tree variant = NULL_TREE;
+ for (tree attr = DECL_ATTRIBUTES (base); attr; attr = TREE_CHAIN (attr))
+ {
+ attr = lookup_attribute ("omp declare variant base", attr);
+ if (attr == NULL_TREE)
+ break;
+ switch (omp_context_selector_matches (TREE_VALUE (TREE_VALUE (attr))))
+ {
+ case 0:
+ /* No match, ignore. */
+ break;
+ case -1:
+ /* Needs to be deferred. */
+ return base;
+ default:
+ /* FIXME: Scoring not implemented yet, so just resolve it
+ if there is a single variant only. */
+ if (variant)
+ return base;
+ if (TREE_CODE (TREE_PURPOSE (TREE_VALUE (attr))) == FUNCTION_DECL)
+ variant = TREE_PURPOSE (TREE_VALUE (attr));
+ else
+ return base;
+ }
+ }
+ return variant ? variant : base;
+}
+
+
/* Encode an oacc launch argument. This matches the GOMP_LAUNCH_PACK
macro on gomp-constants.h. We do not check for overflow. */