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.
* c-c++-common/gomp/delim-declare-variant-8.c: New.
* c-c++-common/gomp/delim-declare-variant-9.c: New.
libgomp/ChangeLog
* testsuite/libgomp.c-c++-common/delim-declare-variant-1.c: New.
* testsuite/libgomp.c-c++-common/delim-declare-variant-2.c: New.
Co-Authored-By: Tobias Burnus <[email protected]>
---
.../gomp/delim-declare-variant-1.c | 55 ++++++++++++++
.../gomp/delim-declare-variant-2.c | 66 +++++++++++++++++
.../gomp/delim-declare-variant-3.c | 49 +++++++++++++
.../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 +++++++
.../gomp/delim-declare-variant-8.c | 54 ++++++++++++++
.../gomp/delim-declare-variant-9.c | 47 ++++++++++++
.../delim-declare-variant-1.c | 45 ++++++++++++
.../delim-declare-variant-2.c | 47 ++++++++++++
11 files changed, 518 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 gcc/testsuite/c-c++-common/gomp/delim-declare-variant-8.c
create mode 100644 gcc/testsuite/c-c++-common/gomp/delim-declare-variant-9.c
create mode 100644
libgomp/testsuite/libgomp.c-c++-common/delim-declare-variant-1.c
create mode 100644
libgomp/testsuite/libgomp.c-c++-common/delim-declare-variant-2.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..6b9d819c765
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/delim-declare-variant-3.c
@@ -0,0 +1,49 @@
+/* { 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)
+{
+ return a + 1;
+}
+
+int bar (int x) /* { dg-error "no declaration of base function" } */
+{
+ return x * 2;
+}
+
+int baz (int x) /* { dg-error "variant function definition does not match
declaration of .baz." } */
+{
+ return x * 2;
+}
+
+int quux (int x, int y) /* { dg-error "variant function definition does not
match declaration of .quux." } */
+{
+ return x + y;
+}
+#pragma omp end declare variant
+
+/* It's supposedly allowed to define the base function after the variant. */
+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/gcc/testsuite/c-c++-common/gomp/delim-declare-variant-8.c
b/gcc/testsuite/c-c++-common/gomp/delim-declare-variant-8.c
new file mode 100644
index 00000000000..33f601d4008
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/delim-declare-variant-8.c
@@ -0,0 +1,54 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-fdump-tree-gimple" } */
+
+/* This is the same as delim-declare-variant-1.c, but using attribute
+ syntax. */
+
+int foo (int a)
+{
+ return a;
+}
+
+int bar (int x)
+{
+ return x;
+}
+
+[[omp::directive (begin declare variant, match (construct={target}))]];
+int foo (int a)
+{
+ return a + 1;
+}
+
+int bar (int x)
+{
+ return x * 2;
+}
+[[omp::directive (end declare variant)]];
+
+/* Because of the high score value, this variant for "bar" should always be
+ selected even when the one above also matches. */
+[[omp::directive (begin declare variant match
(implementation={vendor(score(10000):"gnu")}))]];
+int bar (int x)
+{
+ return x * 4;
+}
+[[omp::directive (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-9.c
b/gcc/testsuite/c-c++-common/gomp/delim-declare-variant-9.c
new file mode 100644
index 00000000000..6bf783e7a62
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/delim-declare-variant-9.c
@@ -0,0 +1,47 @@
+/* { dg-do compile } */
+
+/* Check diagnostics for mismatched pragma/attribute forms of delimited
+ declare variant. */
+
+int foo (int a)
+{
+ return a;
+}
+
+int bar (int x)
+{
+ return x;
+}
+
+[[omp::directive (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 /* { dg-error "'begin declare variant' in
attribute syntax terminated with 'end declare variant' in pragma syntax" } */
+
+/* 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;
+}
+[[omp::directive (end declare variant)]]; /* { dg-error "'begin declare
variant' in pragma syntax terminated with 'end declare variant' in attribute
syntax" } */
+
+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 ();
+ }
+}
+
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 ();
+ }
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/delim-declare-variant-2.c
b/libgomp/testsuite/libgomp.c-c++-common/delim-declare-variant-2.c
new file mode 100644
index 00000000000..152b9f34f31
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/delim-declare-variant-2.c
@@ -0,0 +1,47 @@
+/* Check that the correct function is used;
+ assumes that vendor(gnu) is always true. */
+
+int inner() { return 1; }
+
+int outer(int is_novar) {
+ int k;
+ if (!is_novar) __builtin_abort();
+
+ k = inner();
+ if (k != 22) __builtin_abort();
+
+ #pragma omp dispatch novariants(1)
+ k = inner();
+ if (k != 1) __builtin_abort();
+ return 3;
+}
+
+#pragma omp begin declare variant match(implementation={vendor(gnu)})
+int outer(int is_novar) {
+ int k;
+ if (is_novar) __builtin_abort();
+
+ k = inner();
+ if (k != 22) __builtin_abort();
+
+ #pragma omp dispatch novariants(1)
+ k = inner();
+ if (k != 1) __builtin_abort();
+ return 44;
+}
+
+int inner() { return 22; }
+#pragma omp end declare variant
+
+int
+main()
+{
+ int j;
+ j = outer(0);
+ if (j != 44) __builtin_abort();
+
+ #pragma omp dispatch novariants(1)
+ j = outer(1);
+ if (j != 3) __builtin_abort();
+ return 0;
+}
--
2.39.5