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