https://gcc.gnu.org/g:bd6d591799385b326b3589071b8cfa0bb61a9d19
commit r16-5512-gbd6d591799385b326b3589071b8cfa0bb61a9d19 Author: Sandra Loosemore <[email protected]> Date: Thu Nov 20 21:45:11 2025 +0000 OpenMP: C/C++ common testcases for "omp begin declare variant" 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]> Diff: --- .../c-c++-common/gomp/delim-declare-variant-1.c | 55 +++++++++++++++++ .../c-c++-common/gomp/delim-declare-variant-2.c | 66 ++++++++++++++++++++ .../c-c++-common/gomp/delim-declare-variant-3.c | 49 +++++++++++++++ .../c-c++-common/gomp/delim-declare-variant-4.c | 31 ++++++++++ .../c-c++-common/gomp/delim-declare-variant-5.c | 26 ++++++++ .../c-c++-common/gomp/delim-declare-variant-6.c | 70 ++++++++++++++++++++++ .../c-c++-common/gomp/delim-declare-variant-7.c | 27 +++++++++ .../c-c++-common/gomp/delim-declare-variant-8.c | 54 +++++++++++++++++ .../c-c++-common/gomp/delim-declare-variant-9.c | 47 +++++++++++++++ .../libgomp.c-c++-common/delim-declare-variant-1.c | 45 ++++++++++++++ .../libgomp.c-c++-common/delim-declare-variant-2.c | 47 +++++++++++++++ 11 files changed, 517 insertions(+) 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 000000000000..28cac0d65503 --- /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 000000000000..03bfe2746268 --- /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 000000000000..6b9d819c765f --- /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 000000000000..f6726abefd60 --- /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 000000000000..4e1645bbca89 --- /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 000000000000..0f87118d0176 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/delim-declare-variant-6.c @@ -0,0 +1,70 @@ +/* { 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 OpenMP 6.0 spec 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 000000000000..49a1d530cca3 --- /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 000000000000..33f601d40088 --- /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 000000000000..6bf783e7a624 --- /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 000000000000..916f8a6510f7 --- /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 000000000000..152b9f34f315 --- /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; +}
