gcc/testsuite/ChangeLog
        * c-c++-common/gomp/delim-declare-variant-1.c: New.
        * c-c++-common/gomp/delim-declare-variant-2.c: New.
        * c-c++-common/gomp/delim-declare-variant-3.c: New.
        * c-c++-common/gomp/delim-declare-variant-4.c: New.
        * c-c++-common/gomp/delim-declare-variant-5.c: New.
        * c-c++-common/gomp/delim-declare-variant-6.c: New.
        * c-c++-common/gomp/delim-declare-variant-7.c: New.

libgomp/ChangeLog
        * testsuite/libgomp.c-c++-common/delim-declare-variant-1.c: New.
---
 .../gomp/delim-declare-variant-1.c            | 55 ++++++++++++++
 .../gomp/delim-declare-variant-2.c            | 66 +++++++++++++++++
 .../gomp/delim-declare-variant-3.c            | 50 +++++++++++++
 .../gomp/delim-declare-variant-4.c            | 31 ++++++++
 .../gomp/delim-declare-variant-5.c            | 26 +++++++
 .../gomp/delim-declare-variant-6.c            | 71 +++++++++++++++++++
 .../gomp/delim-declare-variant-7.c            | 27 +++++++
 .../delim-declare-variant-1.c                 | 45 ++++++++++++
 8 files changed, 371 insertions(+)
 create mode 100644 gcc/testsuite/c-c++-common/gomp/delim-declare-variant-1.c
 create mode 100644 gcc/testsuite/c-c++-common/gomp/delim-declare-variant-2.c
 create mode 100644 gcc/testsuite/c-c++-common/gomp/delim-declare-variant-3.c
 create mode 100644 gcc/testsuite/c-c++-common/gomp/delim-declare-variant-4.c
 create mode 100644 gcc/testsuite/c-c++-common/gomp/delim-declare-variant-5.c
 create mode 100644 gcc/testsuite/c-c++-common/gomp/delim-declare-variant-6.c
 create mode 100644 gcc/testsuite/c-c++-common/gomp/delim-declare-variant-7.c
 create mode 100644 
libgomp/testsuite/libgomp.c-c++-common/delim-declare-variant-1.c

diff --git a/gcc/testsuite/c-c++-common/gomp/delim-declare-variant-1.c 
b/gcc/testsuite/c-c++-common/gomp/delim-declare-variant-1.c
new file mode 100644
index 00000000000..28cac0d6550
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/delim-declare-variant-1.c
@@ -0,0 +1,55 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-fdump-tree-gimple" } */
+
+/* Check basic functionality for the delimited form of "declare variant"
+   - no error re duplicate definitions
+   - variants are registered and correctly resolved at call site.  */
+
+int foo (int a)
+{
+  return a;
+}
+
+int bar (int x)
+{
+  return x;
+}
+
+#pragma omp begin declare variant match (construct={target})
+int foo (int a)
+{
+  return a + 1;
+}
+
+int bar (int x)
+{
+  return x * 2;
+}
+#pragma omp end declare variant
+
+/* Because of the high score value, this variant for "bar" should always be
+   selected even when the one above also matches.  */
+#pragma omp begin declare variant match 
(implementation={vendor(score(10000):"gnu")})
+int bar (int x)
+{
+  return x * 4;
+}
+#pragma omp end declare variant
+
+int main (void)
+{
+  if (foo (42) != 42) __builtin_abort ();
+  if (bar (3) != 12) __builtin_abort ();
+#pragma omp target
+  {
+    if (foo (42) != 43) __builtin_abort ();
+    if (bar (3) != 12) __builtin_abort ();
+  }
+}
+
+/* { dg-final { scan-tree-dump-times "omp declare variant base 
\\(foo.ompvariant." 1 "gimple" } } */
+/* { dg-final { scan-tree-dump-times "omp declare variant base 
\\(bar.ompvariant." 2 "gimple" } } */
+/* { dg-final { scan-tree-dump-times "foo \\(42\\)" 1 "gimple" } } */
+/* { dg-final { scan-tree-dump-times "foo\\.ompvariant. \\(42\\)" 1 "gimple" } 
} */
+/* { dg-final { scan-tree-dump-times "bar \\(3\\)" 0 "gimple" } } */
+/* { dg-final { scan-tree-dump-times "bar\\.ompvariant. \\(3\\)" 2 "gimple" } 
} */
diff --git a/gcc/testsuite/c-c++-common/gomp/delim-declare-variant-2.c 
b/gcc/testsuite/c-c++-common/gomp/delim-declare-variant-2.c
new file mode 100644
index 00000000000..03bfe274626
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/delim-declare-variant-2.c
@@ -0,0 +1,66 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-foffload=disable -fdump-tree-original" } */
+
+/* Check for elision of preprocessed code in a begin/end declare variant
+   construct when it can be determined at parse time that the selector
+   can never match.  */
+
+int foobar (int x, int y)
+{
+  return x * y;
+}
+
+int baz (int x)
+{
+  return x;
+}
+
+#pragma omp begin declare variant match (implementation={vendor("acme")}) /* { 
dg-warning "unknown property" } */
+int foobar (int x, int y)
+{
+  random junk that would ordinarily cause a parse error;
+  return x + y;
+}
+#pragma omp end declare variant
+
+#pragma omp begin declare variant match (device={kind(fpga)})
+int foobar (int x, int y)
+{
+  random junk that would ordinarily cause a parse error;
+  return x + y;
+}
+#pragma omp end declare variant
+
+/* Per the OpenMP specification, elision only happens when the implementation
+   or device selectors cannot match; the user/condition selector doesn't
+   matter for this.  */
+#pragma omp begin declare variant match (user={condition (0)})
+int foobar (int x, int y)
+{
+  return x + y;
+}
+#pragma omp end declare variant
+
+/* Check that we're finding the right "omp end declare variant" when
+   constructs are nested.  */
+#pragma omp begin declare variant match (implementation={vendor("acme")})  /* 
{ dg-warning "unknown property" } */
+  #pragma omp begin declare variant match (device={kind(fpga)})
+  int baz (int x)
+  {
+    random junk that would ordinarily cause a parse error;
+    return x + 1;
+  }
+  #pragma omp end declare variant
+  #pragma omp begin declare variant match (device={kind(host)})
+  int baz (int x)
+  {
+    random junk that would ordinarily cause a parse error;
+    return x + 2;
+  }
+  #pragma omp end declare variant
+#pragma omp end declare variant
+
+/* { dg-final { scan-tree-dump-times "foobar.ompvariant" 1 "original" } } */
+/* { dg-final { scan-tree-dump-not "baz.ompvariant" "original" } } */
+
+
diff --git a/gcc/testsuite/c-c++-common/gomp/delim-declare-variant-3.c 
b/gcc/testsuite/c-c++-common/gomp/delim-declare-variant-3.c
new file mode 100644
index 00000000000..63d10d72ea9
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/delim-declare-variant-3.c
@@ -0,0 +1,50 @@
+/* { dg-do compile } */
+
+/* Check that an error is diagnosed when a function defined in a
+   "begin declare variant" construct doesn't have a visible declaration
+   at that point.  
+
+   The spec is not completely clear on this; it says the base function must be
+   "declared elsewhere without an associated declare variant directive",
+   without defining what "elsewhere" means.  Particularly in C++ it would be
+   incorrect to inject such a declaration at the point of the variant
+   definition (think of a variant for a class method that is defined with a
+   qualified name outside of the class declaration, for instance).  The C++
+   front end could differentiate between cases where base declaration injection
+   is allowed vs not, but for now it seems simplest just to require that a
+   definition always be visible.  */
+
+/* This declaration of baz is incompatible with the variant below.  */
+extern double baz (double, double);
+
+/* This is not a function at all.  */
+extern int quux;
+
+#pragma omp begin declare variant match (construct={target})
+int foo (int a)  /* { dg-error "no previous declaration of base function" } */
+{
+  return a + 1;
+}
+
+int bar (int x)  /* { dg-error "no previous declaration of base function" } */
+{
+  return x * 2;
+}
+
+int baz (int x)  /* { dg-error "variant function definition does not match 
previous declaration of .baz." } */
+{
+  return x * 2;
+}
+
+int quux (int x, int y)  /* { dg-error "variant function definition does not 
match previous declaration of .quux." } */
+{
+  return x + y;
+}
+#pragma omp end declare variant
+
+/* This later definition of foo doesn't count for resolving the variant
+   above.  */
+int foo (int a)
+{
+  return a;
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/delim-declare-variant-4.c 
b/gcc/testsuite/c-c++-common/gomp/delim-declare-variant-4.c
new file mode 100644
index 00000000000..f6726abefd6
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/delim-declare-variant-4.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+
+/* Check that a proper error is diagnosed if an "omp begin declare variant"
+   construct has an invalid selector, and that this causes the whole variant
+   to be skipped over rather than a duplicate definition error.  */
+
+int foo (int a)
+{
+  return a;
+}
+
+#pragma omp begin declare variant match (construct=target)  /* { dg-error 
"expected '\{' before 'target'" } */
+int foo (int a)
+{
+  return a + 1;
+}
+
+#pragma omp end declare variant
+
+int bar (int x)
+{
+  return x;
+}
+
+#pragma omp begin declare variant match (gibberish = {blah(1)})  /* { dg-error 
"expected context selector set name" } */
+int bar (int x)
+{
+  return x + 2;
+}
+
+#pragma omp end declare variant
diff --git a/gcc/testsuite/c-c++-common/gomp/delim-declare-variant-5.c 
b/gcc/testsuite/c-c++-common/gomp/delim-declare-variant-5.c
new file mode 100644
index 00000000000..4e1645bbca8
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/delim-declare-variant-5.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+
+/* Check that the simd trait is rejected in the match clause for
+   "begin declare variant".  */
+
+int foo (int a)
+{
+  return a;
+}
+
+int bar (int x)
+{
+  return x;
+}
+
+#pragma omp begin declare variant match (construct={target, simd})  /* { 
dg-error "the 'simd' selector is not permitted" } */
+int foo (int a)
+{
+  return a + 1;
+}
+
+int bar (int x)
+{
+  return x * 2;
+}
+#pragma omp end declare variant
diff --git a/gcc/testsuite/c-c++-common/gomp/delim-declare-variant-6.c 
b/gcc/testsuite/c-c++-common/gomp/delim-declare-variant-6.c
new file mode 100644
index 00000000000..9b03b00fde9
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/delim-declare-variant-6.c
@@ -0,0 +1,71 @@
+/* { dg-do compile { target x86_64-*-* } } */
+/* { dg-additional-options "-fdump-tree-gimple -foffload=disable" } */
+
+/* Test merging of context selectors for nested "begin declare variant"
+   directives.
+
+   The spec (TR12) says: "the effective context selectors of the outer
+   directive are appended do the context selector of the inner directive to
+   form the effective context selector of the inner directive.  If a
+   trait-set-selector is present on both directives, the trait-selector list of
+   the outer directive is appended to the trait-selector list of the inner
+   directive after equivalent trait-selectors have been removed from the outer
+   list."  */
+
+int f1 (int x) { return x; }
+int f2 (int x) { return x; }
+int f3 (int x) { return x; }
+int f4 (int x) { return x; }
+int f5 (int x) { return x; }
+
+/* Check that duplicate traits can be detected, even when the properties
+   use different forms.  (If these were considered different, it would
+   trigger an error instead.)  */
+#pragma omp begin declare variant match (implementation={vendor(gnu)})
+#pragma omp begin declare variant match (implementation={vendor("gnu")})
+int f1 (int x) { return -x; }
+#pragma omp end declare variant
+#pragma omp end declare variant
+
+#pragma omp begin declare variant match (implementation={vendor("gnu")})
+#pragma omp begin declare variant match (implementation={vendor(gnu)})
+int f2 (int x) { return -x; }
+#pragma omp end declare variant
+#pragma omp end declare variant
+
+/* Check that non-duplicate traits are collected from both inner and outer.  */
+
+#pragma omp begin declare variant match (device={kind("host")})
+#pragma omp begin declare variant match (device={arch("x86_64")})
+int f3 (int x) { return -x; }
+#pragma omp end declare variant
+#pragma omp end declare variant
+/* { dg-final { scan-tree-dump "f3\\.ompvariant.*kind \\(.host.\\)" "gimple" } 
} */
+/* { dg-final { scan-tree-dump "f3\\.ompvariant.*arch \\(.x86_64.\\)" "gimple" 
} } */
+
+/* Check that traits for construct selectors merge as expected.  */
+
+#pragma omp begin declare variant match (construct={parallel, for})
+#pragma omp begin declare variant match (construct={teams})
+int f4 (int x) { return -x; }
+#pragma omp end declare variant
+#pragma omp end declare variant
+/* { dg-final { scan-tree-dump "f4\\.ompvariant.*teams, parallel, for" 
"gimple" }  } */
+
+/* Check that multiple trait sets are collected.  */
+
+extern int flag;
+
+#pragma omp begin declare variant match (construct={parallel, for})
+#pragma omp begin declare variant match (construct={teams})
+#pragma omp begin declare variant match (user={condition(flag)})
+#pragma omp begin declare variant match (device={kind("host")})
+int f5 (int x) { return -x; }
+#pragma omp end declare variant
+#pragma omp end declare variant
+#pragma omp end declare variant
+#pragma omp end declare variant
+/* { dg-final { scan-tree-dump "f5\\.ompvariant.*teams, parallel, for" 
"gimple" }  } */
+/* { dg-final { scan-tree-dump "f5\\.ompvariant.*flag" "gimple" }  } */
+/* { dg-final { scan-tree-dump "f5\\.ompvariant.*kind \\(.host.\\)" "gimple" } 
} */
+
diff --git a/gcc/testsuite/c-c++-common/gomp/delim-declare-variant-7.c 
b/gcc/testsuite/c-c++-common/gomp/delim-declare-variant-7.c
new file mode 100644
index 00000000000..49a1d530cca
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/delim-declare-variant-7.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-fdump-tree-gimple" } */
+
+/* Test that merging of context selectors from an enclosing "begin declare
+   variant" directive applies to nested regular "declare variant" directives
+   (not just nested "begin declare variant", which is tested elsewhere).  */
+
+extern int foo1 (int);
+extern int foo2 (int);
+
+#pragma omp begin declare variant match (implementation={vendor(gnu)})
+
+#pragma omp declare variant (foo1) \
+  match (construct={parallel,for})
+#pragma omp declare variant (foo2) \
+  match (device={kind(any)})
+extern int foo (int);
+
+#pragma omp end declare variant
+
+int foo (int x)
+{
+  return x + 42;
+}
+
+/* { dg-final { scan-tree-dump-times "omp declare variant base" 2 "gimple" } } 
*/
+/* { dg-final { scan-tree-dump-times "vendor \\(.gnu.\\)" 2 "gimple" } } */
diff --git a/libgomp/testsuite/libgomp.c-c++-common/delim-declare-variant-1.c 
b/libgomp/testsuite/libgomp.c-c++-common/delim-declare-variant-1.c
new file mode 100644
index 00000000000..916f8a6510f
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/delim-declare-variant-1.c
@@ -0,0 +1,45 @@
+/* Check basic functionality for the delimited form of "declare variant"
+   - no error re duplicate definitions
+   - variants are registered and correctly resolved at call site.  */
+
+int foo (int a)
+{
+  return a;
+}
+
+int bar (int x)
+{
+  return x;
+}
+
+#pragma omp begin declare variant match (construct={target})
+int foo (int a)
+{
+  return a + 1;
+}
+
+int bar (int x)
+{
+  return x * 2;
+}
+#pragma omp end declare variant
+
+/* Because of the high score value, this variant for "bar" should always be
+   selected even when the one above also matches.  */
+#pragma omp begin declare variant match 
(implementation={vendor(score(10000):"gnu")})
+int bar (int x)
+{
+  return x * 4;
+}
+#pragma omp end declare variant
+
+int main (void)
+{
+  if (foo (42) != 42) __builtin_abort ();
+  if (bar (3) != 12) __builtin_abort ();
+#pragma omp target
+  {
+    if (foo (42) != 43) __builtin_abort ();
+    if (bar (3) != 12) __builtin_abort ();
+  }
+}
-- 
2.34.1

Reply via email to