omp-general.h (omp_context_selector_set_compare): Declare.
authorJakub Jelinek <jakub@redhat.com>
Fri, 1 Nov 2019 23:30:55 +0000 (00:30 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Fri, 1 Nov 2019 23:30:55 +0000 (00:30 +0100)
* omp-general.h (omp_context_selector_set_compare): Declare.
* omp-general.c (omp_construct_simd_compare,
omp_context_selector_props_compare, omp_context_selector_set_compare,
omp_context_selector_compare): New functions.
(omp_resolve_declare_variant): Prune variants that are strict subset
of another variant.
c-family/
* c-omp.c (c_omp_mark_declare_variant): Use
omp_context_selector_set_compare.
testsuite/
* c-c++-common/gomp/declare-variant-6.c: Expect construct rather than
constructor in diagnostic messages.
* c-c++-common/gomp/declare-variant-7.c: Likewise.
* c-c++-common/gomp/declare-variant-11.c: New test.

From-SVN: r277734

gcc/ChangeLog
gcc/c-family/ChangeLog
gcc/c-family/c-omp.c
gcc/omp-general.c
gcc/omp-general.h
gcc/testsuite/ChangeLog
gcc/testsuite/c-c++-common/gomp/declare-variant-11.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/gomp/declare-variant-6.c
gcc/testsuite/c-c++-common/gomp/declare-variant-7.c

index 796f5e9ec9110c5ceb6347a60e2d1f8917080d51..17beb66d25655ba414fef78368e3649fb89ed381 100644 (file)
@@ -1,3 +1,12 @@
+2019-11-02  Jakub Jelinek  <jakub@redhat.com>
+
+       * omp-general.h (omp_context_selector_set_compare): Declare.
+       * omp-general.c (omp_construct_simd_compare,
+       omp_context_selector_props_compare, omp_context_selector_set_compare,
+       omp_context_selector_compare): New functions.
+       (omp_resolve_declare_variant): Prune variants that are strict subset
+       of another variant.
+
 2019-11-01  Martin Sebor  <msebor@redhat.com>
 
        PR middle-end/91679
index 9bc219049a383cb785cc8f8ae2b9fdaa2b027240..dfc78a4617379fd6c4cb68518c36a70a80c12039 100644 (file)
@@ -1,5 +1,8 @@
 2019-11-02  Jakub Jelinek  <jakub@redhat.com>
 
+       * c-omp.c (c_omp_mark_declare_variant): Use
+       omp_context_selector_set_compare.
+
        PR c++/88335 - Implement P1073R3: Immediate functions
        * c-common.h (enum rid): Add RID_CONSTEVAL.
        * c-common.c (c_common_reswords): Add consteval.
index 4f5a6ed175adefe8694a9514a1ab76d4105e0fbe..fdf778f93abccdc952606200576f6f4d37a5d9ad 100644 (file)
@@ -2275,113 +2275,10 @@ c_omp_mark_declare_variant (location_t loc, tree variant, tree construct)
       DECL_ATTRIBUTES (variant) = attr;
       return;
     }
-  tree t1 = TREE_VALUE (attr);
-  tree t2 = construct;
-  tree simd = get_identifier ("simd");
-  while (t1 && t2)
-    {
-      if (TREE_PURPOSE (t1) != TREE_PURPOSE (t2))
-       break;
-      if (TREE_PURPOSE (t1) == simd)
-       {
-         if ((TREE_VALUE (t1) == NULL_TREE)
-             != (TREE_VALUE (t2) == NULL_TREE))
-           break;
-         if (TREE_VALUE (t1))
-           {
-             struct declare_variant_simd_data {
-               bool inbranch, notinbranch;
-               tree simdlen;
-               auto_vec<tree,16> data_sharing;
-               auto_vec<tree,16> aligned;
-               declare_variant_simd_data ()
-                 : inbranch(false), notinbranch(false), simdlen(NULL_TREE) {}
-             } data[2];
-             unsigned int i;
-             for (i = 0; i < 2; i++)
-               for (tree c = TREE_VALUE (i ? t2 : t1);
-                    c; c = OMP_CLAUSE_CHAIN (c))
-                 {
-                   vec<tree> *v;
-                   switch (OMP_CLAUSE_CODE (c))
-                     {
-                     case OMP_CLAUSE_INBRANCH:
-                       data[i].inbranch = true;
-                       continue;
-                     case OMP_CLAUSE_NOTINBRANCH:
-                       data[i].notinbranch = true;
-                       continue;
-                     case OMP_CLAUSE_SIMDLEN:
-                       data[i].simdlen = OMP_CLAUSE_SIMDLEN_EXPR (c);
-                       continue;
-                     case OMP_CLAUSE_UNIFORM:
-                     case OMP_CLAUSE_LINEAR:
-                       v = &data[i].data_sharing;
-                       break;
-                     case OMP_CLAUSE_ALIGNED:
-                       v = &data[i].aligned;
-                       break;
-                     default:
-                       gcc_unreachable ();
-                     }
-                   unsigned HOST_WIDE_INT argno
-                     = tree_to_uhwi (OMP_CLAUSE_DECL (c));
-                   if (argno >= v->length ())
-                     v->safe_grow_cleared (argno + 1);
-                   (*v)[argno] = c;
-                 }
-             if (data[0].inbranch != data[1].inbranch
-                 || data[0].notinbranch != data[1].notinbranch
-                 || !simple_cst_equal (data[0].simdlen,
-                                       data[1].simdlen)
-                 || (data[0].data_sharing.length ()
-                     != data[1].data_sharing.length ())
-                 || (data[0].aligned.length ()
-                     != data[1].aligned.length ()))
-               break;
-             tree c1, c2;
-             FOR_EACH_VEC_ELT (data[0].data_sharing, i, c1)
-               {
-                 c2 = data[1].data_sharing[i];
-                 if ((c1 == NULL_TREE) != (c2 == NULL_TREE))
-                   break;
-                 if (c1 == NULL_TREE)
-                   continue;
-                 if (OMP_CLAUSE_CODE (c1) != OMP_CLAUSE_CODE (c2))
-                   break;
-                 if (OMP_CLAUSE_CODE (c1) != OMP_CLAUSE_LINEAR)
-                   continue;
-                 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (c1)
-                     != OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (c2))
-                   break;
-                 if (OMP_CLAUSE_LINEAR_KIND (c1)
-                     != OMP_CLAUSE_LINEAR_KIND (c2))
-                   break;
-                 if (!simple_cst_equal (OMP_CLAUSE_LINEAR_STEP (c1),
-                                        OMP_CLAUSE_LINEAR_STEP (c2)))
-                   break;
-               }
-             if (i < data[0].data_sharing.length ())
-               break;
-             FOR_EACH_VEC_ELT (data[0].aligned, i, c1)
-               {
-                 c2 = data[1].aligned[i];
-                 if ((c1 == NULL_TREE) != (c2 == NULL_TREE))
-                   break;
-                 if (c1 == NULL_TREE)
-                   continue;
-                 if (!simple_cst_equal (OMP_CLAUSE_ALIGNED_ALIGNMENT (c1),
-                                        OMP_CLAUSE_ALIGNED_ALIGNMENT (c2)))
-                   break;
-               }
-             if (i < data[0].aligned.length ())
-               break;
-           }
-       }
-      t1 = TREE_CHAIN (t1);
-      t2 = TREE_CHAIN (t2);
-    }
-  if (t1 || t2)
-    error_at (loc, "%qD used as a variant with incompatible %<constructor%> "
+  if ((TREE_VALUE (attr) != NULL_TREE) != (construct != NULL_TREE)
+      || (construct != NULL_TREE
+         && omp_context_selector_set_compare ("construct", TREE_VALUE (attr),
+                                              construct)))
+    error_at (loc, "%qD used as a variant with incompatible %<construct%> "
                   "selector sets", variant);
 }
index 82f474674992ca773b6d669d20d0db9a7be8bfef..6700e7fdb8684585dbbb570c2a9804db22e97813 100644 (file)
@@ -947,6 +947,320 @@ omp_context_selector_matches (tree ctx)
   return ret;
 }
 
+/* Compare construct={simd} CLAUSES1 with CLAUSES2, return 0/-1/1/2 as
+   in omp_context_selector_set_compare.  */
+
+static int
+omp_construct_simd_compare (tree clauses1, tree clauses2)
+{
+  if (clauses1 == NULL_TREE)
+    return clauses2 == NULL_TREE ? 0 : -1;
+  if (clauses2 == NULL_TREE)
+    return 1;
+
+  int r = 0;
+  struct declare_variant_simd_data {
+    bool inbranch, notinbranch;
+    tree simdlen;
+    auto_vec<tree,16> data_sharing;
+    auto_vec<tree,16> aligned;
+    declare_variant_simd_data ()
+      : inbranch(false), notinbranch(false), simdlen(NULL_TREE) {}
+  } data[2];
+  unsigned int i;
+  for (i = 0; i < 2; i++)
+    for (tree c = i ? clauses2 : clauses1; c; c = OMP_CLAUSE_CHAIN (c))
+      {
+       vec<tree> *v;
+       switch (OMP_CLAUSE_CODE (c))
+         {
+         case OMP_CLAUSE_INBRANCH:
+           data[i].inbranch = true;
+           continue;
+         case OMP_CLAUSE_NOTINBRANCH:
+           data[i].notinbranch = true;
+           continue;
+         case OMP_CLAUSE_SIMDLEN:
+           data[i].simdlen = OMP_CLAUSE_SIMDLEN_EXPR (c);
+           continue;
+         case OMP_CLAUSE_UNIFORM:
+         case OMP_CLAUSE_LINEAR:
+           v = &data[i].data_sharing;
+           break;
+         case OMP_CLAUSE_ALIGNED:
+           v = &data[i].aligned;
+           break;
+         default:
+           gcc_unreachable ();
+         }
+       unsigned HOST_WIDE_INT argno = tree_to_uhwi (OMP_CLAUSE_DECL (c));
+       if (argno >= v->length ())
+         v->safe_grow_cleared (argno + 1);
+       (*v)[argno] = c;
+      }
+  /* Here, r is used as a bitmask, 2 is set if CLAUSES1 has something
+     CLAUSES2 doesn't, 1 is set if CLAUSES2 has something CLAUSES1
+     doesn't.  Thus, r == 3 implies return value 2, r == 1 implies
+     -1, r == 2 implies 1 and r == 0 implies 0.  */
+  if (data[0].inbranch != data[1].inbranch)
+    r |= data[0].inbranch ? 2 : 1;
+  if (data[0].notinbranch != data[1].notinbranch)
+    r |= data[0].notinbranch ? 2 : 1;
+  if (!simple_cst_equal (data[0].simdlen, data[1].simdlen))
+    {
+      if (data[0].simdlen && data[1].simdlen)
+       return 2;
+      r |= data[0].simdlen ? 2 : 1;
+    }
+  if (data[0].data_sharing.length () < data[1].data_sharing.length ()
+      || data[0].aligned.length () < data[1].aligned.length ())
+    r |= 1;
+  tree c1, c2;
+  FOR_EACH_VEC_ELT (data[0].data_sharing, i, c1)
+    {
+      c2 = (i < data[1].data_sharing.length ()
+           ? data[1].data_sharing[i] : NULL_TREE);
+      if ((c1 == NULL_TREE) != (c2 == NULL_TREE))
+       {
+         r |= c1 != NULL_TREE ? 2 : 1;
+         continue;
+       }
+      if (c1 == NULL_TREE)
+       continue;
+      if (OMP_CLAUSE_CODE (c1) != OMP_CLAUSE_CODE (c2))
+       return 2;
+      if (OMP_CLAUSE_CODE (c1) != OMP_CLAUSE_LINEAR)
+       continue;
+      if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (c1)
+         != OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (c2))
+       return 2;
+      if (OMP_CLAUSE_LINEAR_KIND (c1) != OMP_CLAUSE_LINEAR_KIND (c2))
+       return 2;
+      if (!simple_cst_equal (OMP_CLAUSE_LINEAR_STEP (c1),
+                            OMP_CLAUSE_LINEAR_STEP (c2)))
+       return 2;
+    }
+  FOR_EACH_VEC_ELT (data[0].aligned, i, c1)
+    {
+      c2 = i < data[1].aligned.length () ? data[1].aligned[i] : NULL_TREE;
+      if ((c1 == NULL_TREE) != (c2 == NULL_TREE))
+       {
+         r |= c1 != NULL_TREE ? 2 : 1;
+         continue;
+       }
+      if (c1 == NULL_TREE)
+       continue;
+      if (!simple_cst_equal (OMP_CLAUSE_ALIGNED_ALIGNMENT (c1),
+                            OMP_CLAUSE_ALIGNED_ALIGNMENT (c2)))
+       return 2;
+    }
+  switch (r)
+    {
+    case 0: return 0;
+    case 1: return -1;
+    case 2: return 1;
+    case 3: return 2;
+    default: gcc_unreachable ();
+    }
+}
+
+/* Compare properties of selectors SEL from SET other than construct.
+   Return 0/-1/1/2 as in omp_context_selector_set_compare.
+   Unlike set names or selector names, properties can have duplicates.  */
+
+static int
+omp_context_selector_props_compare (const char *set, const char *sel,
+                                   tree ctx1, tree ctx2)
+{
+  int ret = 0;
+  for (int pass = 0; pass < 2; pass++)
+    for (tree t1 = pass ? ctx2 : ctx1; t1; t1 = TREE_CHAIN (t1))
+      {
+       tree t2;
+       for (t2 = pass ? ctx1 : ctx2; t2; t2 = TREE_CHAIN (t2))
+         if (TREE_PURPOSE (t1) == TREE_PURPOSE (t2))
+           {
+             if (TREE_PURPOSE (t1) == NULL_TREE)
+               {
+                 if (set[0] == 'u' && strcmp (sel, "condition") == 0)
+                   {
+                     if (integer_zerop (TREE_VALUE (t1))
+                         != integer_zerop (TREE_VALUE (t2)))
+                       return 2;
+                     break;
+                   }
+                 if (simple_cst_equal (TREE_VALUE (t1), TREE_VALUE (t2)))
+                   break;
+               }
+             else if (strcmp (IDENTIFIER_POINTER (TREE_PURPOSE (t1)),
+                              " score") == 0)
+               {
+                 if (!simple_cst_equal (TREE_VALUE (t1), TREE_VALUE (t2)))
+                   return 2;
+                 break;
+               }
+             else
+               break;
+           }
+       if (t2 == NULL_TREE)
+         {
+           int r = pass ? -1 : 1;
+           if (ret && ret != r)
+             return 2;
+           else if (pass)
+             return r;
+           else
+             {
+               ret = r;
+               break;
+             }
+         }
+      }
+  return ret;
+}
+
+/* Compare single context selector sets CTX1 and CTX2 with SET name.
+   Return 0 if CTX1 is equal to CTX2,
+   -1 if CTX1 is a strict subset of CTX2,
+   1 if CTX2 is a strict subset of CTX1, or
+   2 if neither context is a subset of another one.  */
+
+int
+omp_context_selector_set_compare (const char *set, tree ctx1, tree ctx2)
+{
+  bool swapped = false;
+  int ret = 0;
+  int len1 = list_length (ctx1);
+  int len2 = list_length (ctx2);
+  int cnt = 0;
+  if (len1 < len2)
+    {
+      swapped = true;
+      std::swap (ctx1, ctx2);
+      std::swap (len1, len2);
+    }
+  if (set[0] == 'c')
+    {
+      tree t1;
+      tree t2 = ctx2;
+      tree simd = get_identifier ("simd");
+      /* Handle construct set specially.  In this case the order
+        of the selector matters too.  */
+      for (t1 = ctx1; t1; t1 = TREE_CHAIN (t1))
+       if (TREE_PURPOSE (t1) == TREE_PURPOSE (t2))
+         {
+           int r = 0;
+           if (TREE_PURPOSE (t1) == simd)
+             r = omp_construct_simd_compare (TREE_VALUE (t1),
+                                             TREE_VALUE (t2));
+           if (r == 2 || (ret && r && (ret < 0) != (r < 0)))
+             return 2;
+           if (ret == 0)
+             ret = r;
+           t2 = TREE_CHAIN (t2);
+           if (t2 == NULL_TREE)
+             {
+               t1 = TREE_CHAIN (t1);
+               break;
+             }
+         }
+       else if (ret < 0)
+         return 2;
+       else
+         ret = 1;
+      if (t2 != NULL_TREE)
+       return 2;
+      if (t1 != NULL_TREE)
+       {
+         if (ret < 0)
+           return 2;
+         ret = 1;
+       }
+      if (ret == 0)
+       return 0;
+      return swapped ? -ret : ret;
+    }
+  for (tree t1 = ctx1; t1; t1 = TREE_CHAIN (t1))
+    {
+      tree t2;
+      for (t2 = ctx2; t2; t2 = TREE_CHAIN (t2))
+       if (TREE_PURPOSE (t1) == TREE_PURPOSE (t2))
+         {
+           const char *sel = IDENTIFIER_POINTER (TREE_PURPOSE (t1));
+           int r = omp_context_selector_props_compare (set, sel,
+                                                       TREE_VALUE (t1),
+                                                       TREE_VALUE (t2));
+           if (r == 2 || (ret && r && (ret < 0) != (r < 0)))
+             return 2;
+           if (ret == 0)
+             ret = r;
+           cnt++;
+           break;
+         }
+      if (t2 == NULL_TREE)
+       {
+         if (ret == -1)
+           return 2;
+         ret = 1;
+       }
+    }
+  if (cnt < len2)
+    return 2;
+  if (ret == 0)
+    return 0;
+  return swapped ? -ret : ret;
+}
+
+/* Compare whole context selector specification CTX1 and CTX2.
+   Return 0 if CTX1 is equal to CTX2,
+   -1 if CTX1 is a strict subset of CTX2,
+   1 if CTX2 is a strict subset of CTX1, or
+   2 if neither context is a subset of another one.  */
+
+static int
+omp_context_selector_compare (tree ctx1, tree ctx2)
+{
+  bool swapped = false;
+  int ret = 0;
+  int len1 = list_length (ctx1);
+  int len2 = list_length (ctx2);
+  int cnt = 0;
+  if (len1 < len2)
+    {
+      swapped = true;
+      std::swap (ctx1, ctx2);
+      std::swap (len1, len2);
+    }
+  for (tree t1 = ctx1; t1; t1 = TREE_CHAIN (t1))
+    {
+      tree t2;
+      for (t2 = ctx2; t2; t2 = TREE_CHAIN (t2))
+       if (TREE_PURPOSE (t1) == TREE_PURPOSE (t2))
+         {
+           const char *set = IDENTIFIER_POINTER (TREE_PURPOSE (t1));
+           int r = omp_context_selector_set_compare (set, TREE_VALUE (t1),
+                                                     TREE_VALUE (t2));
+           if (r == 2 || (ret && r && (ret < 0) != (r < 0)))
+             return 2;
+           if (ret == 0)
+             ret = r;
+           cnt++;
+           break;
+         }
+      if (t2 == NULL_TREE)
+       {
+         if (ret == -1)
+           return 2;
+         ret = 1;
+       }
+    }
+  if (cnt < len2)
+    return 2;
+  if (ret == 0)
+    return 0;
+  return swapped ? -ret : ret;
+}
+
 /* Try to resolve declare variant, return the variant decl if it should
    be used instead of base, or base otherwise.  */
 
@@ -954,11 +1268,14 @@ tree
 omp_resolve_declare_variant (tree base)
 {
   tree variant = NULL_TREE;
+  auto_vec <tree, 16> variants;
   for (tree attr = DECL_ATTRIBUTES (base); attr; attr = TREE_CHAIN (attr))
     {
       attr = lookup_attribute ("omp declare variant base", attr);
       if (attr == NULL_TREE)
        break;
+      if (TREE_CODE (TREE_PURPOSE (TREE_VALUE (attr))) != FUNCTION_DECL)
+       continue;
       switch (omp_context_selector_matches (TREE_VALUE (TREE_VALUE (attr))))
        {
        case 0:
@@ -968,16 +1285,49 @@ omp_resolve_declare_variant (tree base)
          /* 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;
+         variants.safe_push (attr);
        }
     }
+  if (variants.length () == 0)
+    return base;
+  if (variants.length () == 1)
+    return TREE_PURPOSE (TREE_VALUE (variants[0]));
+
+  /* A context selector that is a strict subset of another context selector has a score
+     of zero.  */
+  tree attr1, attr2;
+  unsigned int i, j;
+  FOR_EACH_VEC_ELT (variants, i, attr1)
+    if (attr1)
+      {
+       tree ctx1 = TREE_VALUE (TREE_VALUE (attr1));
+       FOR_EACH_VEC_ELT_FROM (variants, j, attr2, i + 1)
+         if (attr2)
+           {
+             tree ctx2 = TREE_VALUE (TREE_VALUE (attr2));
+             int r = omp_context_selector_compare (ctx1, ctx2);
+             if (r == -1)
+               {
+                 /* ctx1 is a strict subset of ctx2, remove
+                    attr1 from the vector.  */
+                 variants[i] = NULL_TREE;
+                 break;
+               }
+             else if (r == 1)
+               /* ctx2 is a strict subset of ctx1, remove attr2
+                  from the vector.  */
+               variants[j] = NULL_TREE;
+           }
+      }
+  /* FIXME: Scoring not implemented yet, so just resolve it
+     if there is a single variant left.  */
+  FOR_EACH_VEC_ELT (variants, i, attr1)
+    if (attr1)
+      {
+       if (variant)
+         return base;
+       variant = TREE_PURPOSE (TREE_VALUE (attr1));
+      }
   return variant ? variant : base;
 }
 
index c0c294d29f483f7a7e2f979698b318e7a053c00e..c6f95eb776f66f9b815d0ba27bd6be30c19eaea9 100644 (file)
@@ -86,6 +86,7 @@ extern poly_uint64 omp_max_vf (void);
 extern int omp_max_simt_vf (void);
 extern int omp_constructor_traits_to_codes (tree, enum tree_code *);
 extern int omp_context_selector_matches (tree);
+extern int omp_context_selector_set_compare (const char *, tree, tree);
 extern tree omp_resolve_declare_variant (tree);
 extern tree oacc_launch_pack (unsigned code, tree device, unsigned op);
 extern tree oacc_replace_fn_attrib_attr (tree attribs, tree dims);
index 5473b252e731a7ab9136fed99ae039512563f848..e8a3856afebd588a1855caf03b0330fc21d21e32 100644 (file)
@@ -1,5 +1,10 @@
 2019-11-02  Jakub Jelinek  <jakub@redhat.com>
 
+       * c-c++-common/gomp/declare-variant-6.c: Expect construct rather than
+       constructor in diagnostic messages.
+       * c-c++-common/gomp/declare-variant-7.c: Likewise.
+       * c-c++-common/gomp/declare-variant-11.c: New test.
+
        PR c++/88335 - Implement P1073R3: Immediate functions
        * g++.dg/cpp2a/consteval1.C: New test.
        * g++.dg/cpp2a/consteval2.C: New test.
diff --git a/gcc/testsuite/c-c++-common/gomp/declare-variant-11.c b/gcc/testsuite/c-c++-common/gomp/declare-variant-11.c
new file mode 100644 (file)
index 0000000..9879a9b
--- /dev/null
@@ -0,0 +1,83 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-foffload=disable -fdump-tree-gimple" } */
+/* { dg-additional-options "-mavx512bw -mavx512vl" { target { i?86-*-* x86_64-*-* } } } */
+
+void f01 (void);
+void f02 (void);
+#pragma omp declare variant (f01) match (device={isa(avx512f,avx512vl)})
+#pragma omp declare variant (f02) match (device={isa(avx512bw,avx512vl,avx512f)})
+void f03 (void);
+void f04 (void);
+void f05 (void);
+#pragma omp declare variant (f04) match (device={isa(avx512f,avx512vl)})
+#pragma omp declare variant (f05) match (device={isa(avx512bw,avx512vl,avx512f)})
+void f06 (void);
+void f07 (void);
+void f08 (void);
+#pragma omp declare variant (f07) match (device={isa(sse4,sse3,avx)})
+#pragma omp declare variant (f08) match (device={isa(avx,sse3)})
+void f09 (void);
+void f10 (void);
+void f11 (void);
+void f12 (void);
+#pragma omp declare variant (f10) match (device={isa(avx512f)})
+#pragma omp declare variant (f11) match (user={condition(1)},device={isa(avx512f)},implementation={vendor(gnu)})
+#pragma omp declare variant (f12) match (user={condition(2 + 1)},device={isa(avx512f)})
+void f13 (void);
+void f14 (void);
+void f15 (void);
+void f16 (void);
+void f17 (void);
+#pragma omp declare variant (f14) match (construct={teams,for})
+#pragma omp declare variant (f15) match (construct={teams,parallel,for})
+#pragma omp declare variant (f16) match (construct={for})
+#pragma omp declare variant (f17) match (construct={parallel,for})
+void f18 (void);
+void f19 (void);
+void f20 (void);
+void f21 (void);
+void f22 (void);
+#pragma omp declare variant (f19) match (construct={teams,for})
+#pragma omp declare variant (f20) match (construct={teams,parallel,for})
+#pragma omp declare variant (f21) match (construct={for})
+#pragma omp declare variant (f22) match (construct={parallel,for})
+void f23 (void);
+void f24 (void);
+void f25 (void);
+void f26 (void);
+#pragma omp declare variant (f24) match (device={kind(cpu)})
+#pragma omp declare variant (f25) match (device={kind(cpu),isa(avx512f),arch(x86_64)})
+#pragma omp declare variant (f26) match (device={arch(x86_64),kind(cpu)})
+void f27 (void);
+
+void
+test1 (void)
+{
+  int i;
+  f03 ();      /* { dg-final { scan-tree-dump-times "f02 \\\(\\\);" 1 "gimple" { target i?86-*-* x86_64-*-* } } } */
+               /* { dg-final { scan-tree-dump-times "f03 \\\(\\\);" 1 "gimple" { target { ! { i?86-*-* x86_64-*-* } } } } } */
+  f09 ();      /* { dg-final { scan-tree-dump-times "f07 \\\(\\\);" 1 "gimple" { target i?86-*-* x86_64-*-* } } } */
+               /* { dg-final { scan-tree-dump-times "f09 \\\(\\\);" 1 "gimple" { target { ! { i?86-*-* x86_64-*-* } } } } } */
+  f13 ();      /* { dg-final { scan-tree-dump-times "f11 \\\(\\\);" 1 "gimple" { target i?86-*-* x86_64-*-* } } } */
+               /* { dg-final { scan-tree-dump-times "f13 \\\(\\\);" 1 "gimple" { target { ! { i?86-*-* x86_64-*-* } } } } } */
+  #pragma omp teams distribute parallel for
+  for (i = 0; i < 1; i++)
+    f18 ();    /* { dg-final { scan-tree-dump-times "f15 \\\(\\\);" 1 "gimple" } } */
+  #pragma omp parallel for
+  for (i = 0; i < 1; i++)
+    f23 ();    /* { dg-final { scan-tree-dump-times "f22 \\\(\\\);" 1 "gimple" } } */
+  f27 ();      /* { dg-final { scan-tree-dump-times "f25 \\\(\\\);" 1 "gimple" { target { { i?86-*-* x86_64-*-* } && lp64 } } } } */
+               /* { dg-final { scan-tree-dump-times "f24 \\\(\\\);" 1 "gimple" { target { { i?86-*-* x86_64-*-* } && { ! lp64 } } } } } */
+               /* { dg-final { scan-tree-dump-times "f24 \\\(\\\);" 1 "gimple" { target { ! { nvptx*-*-* amdgcn*-*-* i?86-*-* x86_64-*-* } } } } } */
+               /* { dg-final { scan-tree-dump-times "f27 \\\(\\\);" 1 "gimple" { target { nvptx*-*-* amdgcn*-*-* } } } } */
+}
+
+#if defined(__i386__) || defined(__x86_64__)
+__attribute__((target ("no-avx512bw,avx512f,avx512vl")))
+#endif
+void
+test2 (void)
+{
+  f06 ();      /* { dg-final { scan-tree-dump-times "f04 \\\(\\\);" 1 "gimple" { target i?86-*-* x86_64-*-* } } } */
+               /* { dg-final { scan-tree-dump-times "f06 \\\(\\\);" 1 "gimple" { target { ! { i?86-*-* x86_64-*-* } } } } } */
+}
index 9ccfd0f39acf6f61454a232135240e32d9ee2069..159da07d4cb520ddc050475735dc955e33c5137d 100644 (file)
@@ -7,29 +7,29 @@ double f4 (int, long, float);
 double f5 (int, long, float);
 #pragma omp declare variant (f5) match (user={condition(0)})
 double f6 (int, long, float);
-#pragma omp declare variant (f5) match (construct={parallel},user={condition(score(1):1)})     /* { dg-error "'\[^'\n\r]*f5\[^'\n\r]*' used as a variant with incompatible 'constructor' selector sets" } */
+#pragma omp declare variant (f5) match (construct={parallel},user={condition(score(1):1)})     /* { dg-error "'\[^'\n\r]*f5\[^'\n\r]*' used as a variant with incompatible 'construct' selector sets" } */
 double f7 (int, long, float);
 double f8 (int, long, float);
 #pragma omp declare variant (f8) match (user={condition(0)},construct={for})
 double f9 (int, long, float);
-#pragma omp declare variant (f8) match (user={condition(1)})                                   /* { dg-error "'\[^'\n\r]*f8\[^'\n\r]*' used as a variant with incompatible 'constructor' selector sets" } */
+#pragma omp declare variant (f8) match (user={condition(1)})                                   /* { dg-error "'\[^'\n\r]*f8\[^'\n\r]*' used as a variant with incompatible 'construct' selector sets" } */
 double f10 (int, long, float);
 double f11 (int, long, float);
 #pragma omp declare variant (f11) match (construct={target,teams,parallel,for})
 double f12 (int, long, float);
 #pragma omp declare variant (f11) match (user={condition(score(1):1)},construct={target,teams,parallel,for})
 double f13 (int, long, float);
-#pragma omp declare variant (f11) match (implementation={vendor(gnu)},construct={target,teams,parallel})       /* { dg-error "'\[^'\n\r]*f11\[^'\n\r]*' used as a variant with incompatible 'constructor' selector sets" } */
+#pragma omp declare variant (f11) match (implementation={vendor(gnu)},construct={target,teams,parallel})       /* { dg-error "'\[^'\n\r]*f11\[^'\n\r]*' used as a variant with incompatible 'construct' selector sets" } */
 double f14 (int, long, float);
-#pragma omp declare variant (f11) match (device={kind(any)},construct={teams,parallel})                /* { dg-error "'\[^'\n\r]*f11\[^'\n\r]*' used as a variant with incompatible 'constructor' selector sets" } */
+#pragma omp declare variant (f11) match (device={kind(any)},construct={teams,parallel})                /* { dg-error "'\[^'\n\r]*f11\[^'\n\r]*' used as a variant with incompatible 'construct' selector sets" } */
 double f15 (int, long, float);
 double f16 (int, long, float);
 #pragma omp declare variant (f16) match (construct={teams,parallel})
 double f17 (int, long, float);
-#pragma omp declare variant (f16) match(construct={teams,parallel,for})                                /* { dg-error "'\[^'\n\r]*f16\[^'\n\r]*' used as a variant with incompatible 'constructor' selector sets" } */
+#pragma omp declare variant (f16) match(construct={teams,parallel,for})                                /* { dg-error "'\[^'\n\r]*f16\[^'\n\r]*' used as a variant with incompatible 'construct' selector sets" } */
 double f18 (int, long, float);
 double f19 (int, long, float);
 #pragma omp declare variant (f19) match (construct={parallel})
 double f20 (int, long, float);
-#pragma omp declare variant (f19) match (construct={for},implementation={vendor(gnu,llvm)})    /* { dg-error "'\[^'\n\r]*f19\[^'\n\r]*' used as a variant with incompatible 'constructor' selector sets" } */
+#pragma omp declare variant (f19) match (construct={for},implementation={vendor(gnu,llvm)})    /* { dg-error "'\[^'\n\r]*f19\[^'\n\r]*' used as a variant with incompatible 'construct' selector sets" } */
 double f21 (int, long, float);
index 1df63384dffea88d596794baf99beb40b0a19644..4eebcbcd1d20e718a8b180dd39203bfde03cd781 100644 (file)
@@ -13,23 +13,23 @@ __v4si f3 (__v4si, int, __v4si);
 int f4 (float x, float y, float *z);
 #pragma omp declare variant (f1) match (construct={parallel,for,simd(uniform(w),simdlen(8*2-12),aligned(w:4*sizeof (float)),notinbranch)})
 int f5 (float u, float v, float *w);
-#pragma omp declare variant (f1) match (construct={parallel,for,simd(linear(w),notinbranch,simdlen(4),aligned(w:4*sizeof (float)))})   /* { dg-error "'f1' used as a variant with incompatible 'constructor' selector sets" "" { target c } } */
+#pragma omp declare variant (f1) match (construct={parallel,for,simd(linear(w),notinbranch,simdlen(4),aligned(w:4*sizeof (float)))})   /* { dg-error "'f1' used as a variant with incompatible 'construct' selector sets" "" { target c } } */
 int f6 (float u, float v, float *w);
-#pragma omp declare variant (f1) match (construct={parallel,for,simd(uniform(w),notinbranch,simdlen(4),aligned(w:2*sizeof (float)))})  /* { dg-error "'f1' used as a variant with incompatible 'constructor' selector sets" "" { target c } } */
+#pragma omp declare variant (f1) match (construct={parallel,for,simd(uniform(w),notinbranch,simdlen(4),aligned(w:2*sizeof (float)))})  /* { dg-error "'f1' used as a variant with incompatible 'construct' selector sets" "" { target c } } */
 int f7 (float u, float v, float *w);
-#pragma omp declare variant (f1) match (construct={parallel,for,simd(uniform(w),notinbranch,simdlen(4),aligned(w))})                   /* { dg-error "'f1' used as a variant with incompatible 'constructor' selector sets" "" { target c } } */
+#pragma omp declare variant (f1) match (construct={parallel,for,simd(uniform(w),notinbranch,simdlen(4),aligned(w))})                   /* { dg-error "'f1' used as a variant with incompatible 'construct' selector sets" "" { target c } } */
 int f8 (float u, float v, float *w);
 #pragma omp declare variant (f2) match (construct={for,simd(uniform(z),simdlen(8),notinbranch)})
 int f9 (float x, float y, float *z);
 #pragma omp declare variant (f2) match (construct={for,simd(notinbranch,simdlen(2+2+4),uniform (q))})
 int f10 (float x, float y, float *q);
-#pragma omp declare variant (f2) match (construct={for,simd(linear(z:2),simdlen(8),notinbranch)})      /* { dg-error "'f2' used as a variant with incompatible 'constructor' selector sets" "" { target c } } */
+#pragma omp declare variant (f2) match (construct={for,simd(linear(z:2),simdlen(8),notinbranch)})      /* { dg-error "'f2' used as a variant with incompatible 'construct' selector sets" "" { target c } } */
 int f11 (float x, float y, float *z);
 #pragma omp declare variant (f3) match (construct={simd(simdlen(4),inbranch,linear(y:1))})
 int f12 (int x, int y);
 #pragma omp declare variant (f3) match (construct={simd(inbranch, simdlen (5-1), linear (q:4-3))})
 int f13 (int x, int q);
-#pragma omp declare variant (f3) match (construct={simd(inbranch,simdlen(4),linear(q:2))})             /* { dg-error "'f3' used as a variant with incompatible 'constructor' selector sets" "" { target c } } */
+#pragma omp declare variant (f3) match (construct={simd(inbranch,simdlen(4),linear(q:2))})             /* { dg-error "'f3' used as a variant with incompatible 'construct' selector sets" "" { target c } } */
 int f14 (int x, int q);
 #pragma omp declare variant (f3) match (construct={simd(inbranch simdlen (4) linear (q:1))})           /* { dg-error "clauses in 'simd' trait should be separated by ','" } */
 int f15 (int x, int q);