As noted in PR middle-end/121630, GCC seems to think that the "simd" construct selector on "declare variant" implies that the variant function accepts vectorized arguments, although this is not anywhere in the OpenMP specification. Additionally, it does not actually vectorize the calls when doing variant replacement, causing incorrect code to be generated. This is making it through the front ends because all of C, C++, and Fortran suppress the normal consistency checking between the variant and base function when "simd" is specified.
This patch removes the special case that bypasses the error checking in the front ends, and fixes the test cases to either check that this is now diagnosed with an error, or to have correct type signatures when the point of the test is to detect some other problem instead. gcc/c/ PR middle-end/121630 * c-parser.cc (c_finish_omp_declare_variant): Remove special case bypassing error checking when the "simd" construct selector is present. gcc/cp/ PR middle-end/121630 * decl.cc (omp_declare_variant_finalize_one): Remove special case bypassing error checking when the "simd" construct selector is present. gcc/fortran/ PR middle-end/121630 * trans-openmp.cc (gfc_trans_omp_declare_variant): Remove special case bypassing error checking when the "simd" construct selector is present. gcc/testsuite/ PR middle-end/121630 * c-c++-common/gomp/declare-variant-5.c: Expect this test to produce errors. * c-c++-common/gomp/declare-variant-7.c: Correct type of variants and adjust expected output. * gcc.dg/gomp/pr95315-2.c: Correct type of variants. * gcc.dg/gomp/pr95315.c: Likewise, inserting code inline instead of including test case that now does something different. * gfortran.dg/gomp/declare-variant-5.f90: Expect this test to produce errors. * gfortran.dg/gomp/declare-variant-7.f90: Correct type of variants. --- gcc/c/c-parser.cc | 258 +++++++++--------- gcc/cp/decl.cc | 10 +- gcc/fortran/trans-openmp.cc | 5 +- .../c-c++-common/gomp/declare-variant-5.c | 18 +- .../c-c++-common/gomp/declare-variant-7.c | 30 +- gcc/testsuite/gcc.dg/gomp/pr95315-2.c | 10 +- gcc/testsuite/gcc.dg/gomp/pr95315.c | 32 ++- .../gfortran.dg/gomp/declare-variant-5.f90 | 6 +- .../gfortran.dg/gomp/declare-variant-7.f90 | 19 +- 9 files changed, 210 insertions(+), 178 deletions(-) diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc index db669242d58..53b7c2749a6 100644 --- a/gcc/c/c-parser.cc +++ b/gcc/c/c-parser.cc @@ -27561,144 +27561,140 @@ c_finish_omp_declare_variant (c_parser *parser, tree fndecl, tree parms) return; } - if (!omp_get_context_selector (ctx, OMP_TRAIT_SET_CONSTRUCT, - OMP_TRAIT_CONSTRUCT_SIMD)) /* Check that the base and variant have compatible types. */ - { - tree base_type = TREE_TYPE (fndecl); - tree variant_type = TREE_TYPE (variant); - bool unprototyped_variant - = (TYPE_ARG_TYPES (variant_type) == NULL_TREE - && !TYPE_NO_NAMED_ARGS_STDARG_P (variant_type)); + tree base_type = TREE_TYPE (fndecl); + tree variant_type = TREE_TYPE (variant); + bool unprototyped_variant + = (TYPE_ARG_TYPES (variant_type) == NULL_TREE + && !TYPE_NO_NAMED_ARGS_STDARG_P (variant_type)); - if (append_args_tree - && TYPE_ARG_TYPES (base_type) == NULL_TREE - && !TYPE_NO_NAMED_ARGS_STDARG_P (base_type)) + if (append_args_tree + && TYPE_ARG_TYPES (base_type) == NULL_TREE + && !TYPE_NO_NAMED_ARGS_STDARG_P (base_type)) + { + /* The base function is a pre-C23 unprototyped function. Without + a prototype, we don't know the offset where the append_args go. + That offset needs to be stored with the append_args in the + variant function attributes, so we cannot presently handle + this case. */ + sorry_at (append_args_loc, + "%<append_args%> with unprototyped base function " + "is not supported yet"); + inform (DECL_SOURCE_LOCATION (fndecl), + "base function %qD declared here", fndecl); + return; + } + else if (append_args_tree) + { + /* Find nbase_args, the number of fixed arguments in the base + function. */ + int nappend_args = 0; + int nbase_args = 0; + for (tree t = TYPE_ARG_TYPES (base_type); + t && TREE_VALUE (t) != void_type_node; t = TREE_CHAIN (t)) + nbase_args++; + for (tree t = append_args_tree; t; t = TREE_CHAIN (t)) + nappend_args++; + + /* Store as purpose = arg number after which to append + and value = list of interop items. */ + append_args_tree = build_tree_list (build_int_cst (integer_type_node, + nbase_args), + append_args_tree); + + /* Give a specific diagnostic if the append_args parameters + of the variant are of the wrong type, or missing. The + compatible types test below could fail to detect this if + the variant is a varargs function. */ + if (!unprototyped_variant) { - /* The base function is a pre-C23 unprototyped function. Without - a prototype, we don't know the offset where the append_args go. - That offset needs to be stored with the append_args in the - variant function attributes, so we cannot presently handle - this case. */ - sorry_at (append_args_loc, - "%<append_args%> with unprototyped base function " - "is not supported yet"); - inform (DECL_SOURCE_LOCATION (fndecl), - "base function %qD declared here", fndecl); + tree args = TYPE_ARG_TYPES (variant_type); + for (int i = 0; args && i < nbase_args; + i++, args = TREE_CHAIN (args)) + ; + for (int i = 0; i < nappend_args; i++, args = TREE_CHAIN (args)) + if (!args || !c_omp_interop_t_p (TREE_VALUE (args))) + { + error_at (DECL_SOURCE_LOCATION (variant), + "argument %d of %qD must be of " + "%<omp_interop_t%>", + nbase_args + i + 1, variant); + inform (append_args_loc, + "%<append_args%> specified here"); + return; + } + } + + /* Perform the "implementation defined transformation" on the type + of the base function to add the append_args before checking it + for compatibility with the function variant's type. */ + tree args = TYPE_ARG_TYPES (base_type); + tree newargs = NULL_TREE; + tree lastarg = NULL_TREE; + for (int j = 0; j < nbase_args; j++, args = TREE_CHAIN (args)) + { + tree t = tree_cons (TREE_PURPOSE (args), + TREE_VALUE (args), NULL_TREE); + if (lastarg) + TREE_CHAIN (lastarg) = t; + else + newargs = t; + lastarg = t; + } + tree type = lookup_name (get_identifier ("omp_interop_t")); + type = type ? TREE_TYPE (type) : pointer_sized_int_node; + for (int j = 0; j < nappend_args; j++) + { + tree t = tree_cons (NULL_TREE, type, NULL_TREE); + if (lastarg) + TREE_CHAIN (lastarg) = t; + else + newargs = t; + lastarg = t; + } + TREE_CHAIN (lastarg) = args; + + /* Temporarily stuff newargs into the original base_type. */ + tree saveargs = TYPE_ARG_TYPES (base_type); + TYPE_ARG_TYPES (base_type) = newargs; + bool fail = !comptypes (base_type, variant_type); + TYPE_ARG_TYPES (base_type) = saveargs; + + if (fail) + { + error_at (token->location, + "variant %qD and base %qD have incompatible types " + "after %<append_args%> adjustment", + variant, fndecl); + inform (DECL_SOURCE_LOCATION (variant), + "%<declare variant%> candidate %qD declared here", + variant); return; } - else if (append_args_tree) + else if (unprototyped_variant) + /* If we've got an unprototyped variant, copy the transformed + base arg types to the variant. This is needed later by + modify_call_for_omp_dispatch. */ + TYPE_ARG_TYPES (variant_type) = newargs; + } + else /* No append_args present. */ + { + if (!comptypes (base_type, variant_type)) { - /* Find nbase_args, the number of fixed arguments in the base - function. */ - int nappend_args = 0; - int nbase_args = 0; - for (tree t = TYPE_ARG_TYPES (base_type); - t && TREE_VALUE (t) != void_type_node; t = TREE_CHAIN (t)) - nbase_args++; - for (tree t = append_args_tree; t; t = TREE_CHAIN (t)) - nappend_args++; - - /* Store as purpose = arg number after which to append - and value = list of interop items. */ - append_args_tree = build_tree_list (build_int_cst (integer_type_node, - nbase_args), - append_args_tree); - - /* Give a specific diagnostic if the append_args parameters - of the variant are of the wrong type, or missing. The - compatible types test below could fail to detect this if - the variant is a varargs function. */ - if (!unprototyped_variant) - { - tree args = TYPE_ARG_TYPES (variant_type); - for (int i = 0; args && i < nbase_args; - i++, args = TREE_CHAIN (args)) - ; - for (int i = 0; i < nappend_args; i++, args = TREE_CHAIN (args)) - if (!args || !c_omp_interop_t_p (TREE_VALUE (args))) - { - error_at (DECL_SOURCE_LOCATION (variant), - "argument %d of %qD must be of " - "%<omp_interop_t%>", - nbase_args + i + 1, variant); - inform (append_args_loc, - "%<append_args%> specified here"); - return; - } - } - - /* Perform the "implementation defined transformation" on the type - of the base function to add the append_args before checking it - for compatibility with the function variant's type. */ - tree args = TYPE_ARG_TYPES (base_type); - tree newargs = NULL_TREE; - tree lastarg = NULL_TREE; - for (int j = 0; j < nbase_args; j++, args = TREE_CHAIN (args)) - { - tree t = tree_cons (TREE_PURPOSE (args), - TREE_VALUE (args), NULL_TREE); - if (lastarg) - TREE_CHAIN (lastarg) = t; - else - newargs = t; - lastarg = t; - } - tree type = lookup_name (get_identifier ("omp_interop_t")); - type = type ? TREE_TYPE (type) : pointer_sized_int_node; - for (int j = 0; j < nappend_args; j++) - { - tree t = tree_cons (NULL_TREE, type, NULL_TREE); - if (lastarg) - TREE_CHAIN (lastarg) = t; - else - newargs = t; - lastarg = t; - } - TREE_CHAIN (lastarg) = args; - - /* Temporarily stuff newargs into the original base_type. */ - tree saveargs = TYPE_ARG_TYPES (base_type); - TYPE_ARG_TYPES (base_type) = newargs; - bool fail = !comptypes (base_type, variant_type); - TYPE_ARG_TYPES (base_type) = saveargs; - - if (fail) - { - error_at (token->location, - "variant %qD and base %qD have incompatible types " - "after %<append_args%> adjustment", - variant, fndecl); - inform (DECL_SOURCE_LOCATION (variant), - "%<declare variant%> candidate %qD declared here", - variant); - return; - } - else if (unprototyped_variant) - /* If we've got an unprototyped variant, copy the transformed - base arg types to the variant. This is needed later by - modify_call_for_omp_dispatch. */ - TYPE_ARG_TYPES (variant_type) = newargs; - } - else /* No append_args present. */ - { - if (!comptypes (base_type, variant_type)) - { - error_at (token->location, - "variant %qD and base %qD have incompatible types", - variant, fndecl); - inform (DECL_SOURCE_LOCATION (variant), - "%<declare variant%> candidate %qD declared here", - variant); - return; - } - else if (TYPE_ARG_TYPES (variant_type) == NULL_TREE - && !TYPE_NO_NAMED_ARGS_STDARG_P (variant_type) - && TYPE_ARG_TYPES (base_type) != NULL_TREE) - /* If we've got an unprototyped variant but the base has - a prototype, copy the base arg types to the variant. */ - TYPE_ARG_TYPES (variant_type) = TYPE_ARG_TYPES (base_type); + error_at (token->location, + "variant %qD and base %qD have incompatible types", + variant, fndecl); + inform (DECL_SOURCE_LOCATION (variant), + "%<declare variant%> candidate %qD declared here", + variant); + return; } + else if (TYPE_ARG_TYPES (variant_type) == NULL_TREE + && !TYPE_NO_NAMED_ARGS_STDARG_P (variant_type) + && TYPE_ARG_TYPES (base_type) != NULL_TREE) + /* If we've got an unprototyped variant but the base has + a prototype, copy the base arg types to the variant. */ + TYPE_ARG_TYPES (variant_type) = TYPE_ARG_TYPES (base_type); } /* If we made it here, store the parsed information. */ diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc index 140cc9b4699..fe22e062861 100644 --- a/gcc/cp/decl.cc +++ b/gcc/cp/decl.cc @@ -8493,13 +8493,9 @@ omp_declare_variant_finalize_one (tree decl, tree attr) tree simd = omp_get_context_selector (ctx, OMP_TRAIT_SET_CONSTRUCT, OMP_TRAIT_CONSTRUCT_SIMD); if (simd) - { - TREE_VALUE (simd) - = c_omp_declare_simd_clauses_to_numbers (DECL_ARGUMENTS (decl), - OMP_TS_PROPERTIES (simd)); - /* FIXME, adjusting simd args unimplemented. */ - return true; - } + TREE_VALUE (simd) + = c_omp_declare_simd_clauses_to_numbers (DECL_ARGUMENTS (decl), + OMP_TS_PROPERTIES (simd)); tree chain = TREE_CHAIN (TREE_VALUE (attr)); location_t varid_loc diff --git a/gcc/fortran/trans-openmp.cc b/gcc/fortran/trans-openmp.cc index 278e91c2c49..98b725b0312 100644 --- a/gcc/fortran/trans-openmp.cc +++ b/gcc/fortran/trans-openmp.cc @@ -9735,10 +9735,7 @@ gfc_trans_omp_declare_variant (gfc_namespace *ns, gfc_namespace *parent_ns) variant_proc_name, &odv->where); variant_proc_sym = NULL; } - else if (omp_get_context_selector (set_selectors, - OMP_TRAIT_SET_CONSTRUCT, - OMP_TRAIT_CONSTRUCT_SIMD) - == NULL_TREE) + else { char err[256]; gfc_formal_arglist *last_arg = NULL, *extra_arg = NULL; diff --git a/gcc/testsuite/c-c++-common/gomp/declare-variant-5.c b/gcc/testsuite/c-c++-common/gomp/declare-variant-5.c index 6ebf09457c0..0592cde2895 100644 --- a/gcc/testsuite/c-c++-common/gomp/declare-variant-5.c +++ b/gcc/testsuite/c-c++-common/gomp/declare-variant-5.c @@ -1,19 +1,31 @@ /* { dg-do compile { target i?86-*-* x86_64-*-* } } */ /* { dg-additional-options "-mavx2" } */ +/* This test used to compile without error in the expectation that the + "simd" construct specifier would be sufficient to vectorize calls to + the variant function, but in fact that behavior is not in the OpenMP + spec and has never worked in GCC, only resulting in wrong code being + emitted. */ + typedef float __v4sf __attribute__((vector_size (16))); typedef int __v4si __attribute__((vector_size (16))); typedef float __v8sf __attribute__((vector_size (32))); typedef int __v8si __attribute__((vector_size (32))); -__v4si f1 (__v4sf, __v4sf, float *); -__v8si f2 (__v8sf, __v8sf, float *); -__v4si f3 (__v4si, int, __v4si); +__v4si f1 (__v4sf, __v4sf, float *); /* { dg-note "initializing argument 1" "" { target c++} */ +__v8si f2 (__v8sf, __v8sf, float *); /* { dg-note "initializing argument 1" "" { target c++} */ +__v4si f3 (__v4si, int, __v4si); /* { dg-note "initializing argument 1" "" { target c++} */ #pragma omp declare variant (f1) match (construct={parallel,for,simd(simdlen(4),notinbranch,uniform(z),aligned(z:4 * sizeof (*z)))}) +/* { dg-error "variant 'f1' and base 'f4' have incompatible types" "" { target c } .-1 } */ +/* { dg-error "cannot convert 'float' to '__v4sf'" "" { target c++ } .-2 } */ #pragma omp declare variant (f2) match (construct={for,simd(uniform(z),simdlen(8),notinbranch)}) +/* { dg-error "variant 'f2' and base 'f4' have incompatible types" "" { target c } .-1 } */ +/* { dg-error "cannot convert 'float' to '__v8sf'" "" { target c++ } .-2 } */ int f4 (float x, float y, float *z); #pragma omp declare variant (f3) match (construct={simd(simdlen(4),inbranch,linear(y:1))}) +/* { dg-error "variant .* and base .* have incompatible types" "" { target c } .-1 } */ +/* { dg-error "cannot convert 'int' to '__v4si'" "" { target c++ } .-2 } */ int f5 (int x, int y); void diff --git a/gcc/testsuite/c-c++-common/gomp/declare-variant-7.c b/gcc/testsuite/c-c++-common/gomp/declare-variant-7.c index 4eebcbcd1d2..72532455bd0 100644 --- a/gcc/testsuite/c-c++-common/gomp/declare-variant-7.c +++ b/gcc/testsuite/c-c++-common/gomp/declare-variant-7.c @@ -1,35 +1,41 @@ /* { dg-do compile { target i?86-*-* x86_64-*-* } } */ /* { dg-additional-options "-mavx2" } */ -typedef float __v4sf __attribute__((vector_size (16))); -typedef int __v4si __attribute__((vector_size (16))); -typedef float __v8sf __attribute__((vector_size (32))); -typedef int __v8si __attribute__((vector_size (32))); -__v4si f1 (__v4sf, __v4sf, float *); -__v8si f2 (__v8sf, __v8sf, float *); -__v4si f3 (__v4si, int, __v4si); +int f1 (float, float, float *); +int f2 (float, float, float *); +int f3 (int, int); #pragma omp declare variant (f1) match (construct={parallel,for,simd(simdlen(4),notinbranch,uniform(z),aligned(z:4 * sizeof (*z)))}) 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 'construct' 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 } .-1 } */ +/* { dg-error "'int f1\\\(\[^\\n\]*\\\)' used as a variant with incompatible 'construct' selector sets" "" { target c++ } .-2 } */ 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 'construct' 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 } .-1 } */ +/* { dg-error "'int f1\\\(\[^\\n\]*\\\)' used as a variant with incompatible 'construct' selector sets" "" { target c++ } .-2 } */ 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 'construct' 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 } .-1 } */ +/* { dg-error "'int f1\\\(\[^\\n\]*\\\)' used as a variant with incompatible 'construct' selector sets" "" { target c++ } .-2 } */ 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 'construct' 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 } .-1 } */ +/* { dg-error "'int f2\\\(\[^\\n\]*\\\)' used as a variant with incompatible 'construct' selector sets" "" { target c++} .-2 } */ 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 'construct' 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 } .-1 } */ +/* { dg-error "'int f3\\\(\[^\\n\]*\\\)' used as a variant with incompatible 'construct' selector sets" "" { target c++} .-2 } */ 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); diff --git a/gcc/testsuite/gcc.dg/gomp/pr95315-2.c b/gcc/testsuite/gcc.dg/gomp/pr95315-2.c index 3a5018a1eee..9295e900081 100644 --- a/gcc/testsuite/gcc.dg/gomp/pr95315-2.c +++ b/gcc/testsuite/gcc.dg/gomp/pr95315-2.c @@ -2,13 +2,9 @@ /* { dg-do compile } */ /* { dg-options "-O2 -fopenmp --param ggc-min-heapsize=0" } */ -typedef float __v4sf __attribute__((vector_size (16))); -typedef int __v4si __attribute__((vector_size (16))); -typedef float __v8sf __attribute__((vector_size (32))); -typedef int __v8si __attribute__((vector_size (32))); -__v4si f1 (__v4sf, __v4sf, float *); -__v8si f2 (__v8sf, __v8sf, float *); -__v4si f3 (__v4si, int, __v4si); +int f1 (float, float, float *); +int f2 (float, float, float *); +int f3 (int, int); #pragma omp declare variant (f1) match (construct={parallel,for,simd(simdlen(4),notinbranch,uniform(z),aligned(z:4 * sizeof (*z)))}) #pragma omp declare variant (f2) match (construct={for,simd(uniform(z),simdlen(8),notinbranch)}) diff --git a/gcc/testsuite/gcc.dg/gomp/pr95315.c b/gcc/testsuite/gcc.dg/gomp/pr95315.c index 4981e0b8949..0e4407102dc 100644 --- a/gcc/testsuite/gcc.dg/gomp/pr95315.c +++ b/gcc/testsuite/gcc.dg/gomp/pr95315.c @@ -2,4 +2,34 @@ /* { dg-do compile } */ /* { dg-options "-O2 -fopenmp --param ggc-min-heapsize=0" } */ -#include "../../c-c++-common/gomp/declare-variant-5.c" +int f1 (float, float, float *); +int f2 (float, float, float *); +int f3 (int, int); + +#pragma omp declare variant (f1) match (construct={parallel,for,simd(simdlen(4),notinbranch,uniform(z),aligned(z:4 * sizeof (*z)))}) +#pragma omp declare variant (f2) match (construct={for,simd(uniform(z),simdlen(8),notinbranch)}) +int f4 (float x, float y, float *z); + +#pragma omp declare variant (f3) match (construct={simd(simdlen(4),inbranch,linear(y:1))}) +int f5 (int x, int y); + +void +test (int *x, float *y, float *z, float *w) +{ + #pragma omp parallel + #pragma omp for simd aligned (w:4 * sizeof (float)) + for (int i = 0; i < 1024; i++) + x[i] = f4 (y[i], z[i], w); + #pragma omp parallel for simd aligned (w:4 * sizeof (float)) simdlen(4) + for (int i = 1024; i < 2048; i++) + x[i] = f4 (y[i], z[i], w); + #pragma omp simd aligned (w:4 * sizeof (float)) + for (int i = 2048; i < 4096; i++) + x[i] = f4 (y[i], z[i], w); + #pragma omp simd + for (int i = 4096; i < 8192; i++) + if (x[i] > 10) + x[i] = f5 (x[i], i); +} + + diff --git a/gcc/testsuite/gfortran.dg/gomp/declare-variant-5.f90 b/gcc/testsuite/gfortran.dg/gomp/declare-variant-5.f90 index ad7acb9842d..de46278ee6d 100644 --- a/gcc/testsuite/gfortran.dg/gomp/declare-variant-5.f90 +++ b/gcc/testsuite/gfortran.dg/gomp/declare-variant-5.f90 @@ -31,13 +31,13 @@ contains integer function f4 (x, y, z) real, intent(in) :: x, y real, intent(out) :: z - !$omp declare variant (f1) match (construct={parallel,do,simd(simdlen(4),notinbranch,uniform(z),aligned(z:16))}) - !$omp declare variant (f2) match (construct={do,simd(uniform(z),simdlen(8),notinbranch)}) + !$omp declare variant (f1) match (construct={parallel,do,simd(simdlen(4),notinbranch,uniform(z),aligned(z:16))}) ! { dg-error "incompatible types: Rank mismatch in function result" } + !$omp declare variant (f2) match (construct={do,simd(uniform(z),simdlen(8),notinbranch)}) ! { dg-error "incompatible types: Rank mismatch in function result" } end function integer function f5 (x, y) integer, intent(in) :: x, y - !$omp declare variant (f3) match (construct={simd(simdlen(4),inbranch,linear(y:1))}) + !$omp declare variant (f3) match (construct={simd(simdlen(4),inbranch,linear(y:1))}) ! { dg-error "incompatible types: Rank mismatch in function result" } end function subroutine test (x, y, z, w) diff --git a/gcc/testsuite/gfortran.dg/gomp/declare-variant-7.f90 b/gcc/testsuite/gfortran.dg/gomp/declare-variant-7.f90 index 1590a2a26f0..67d8b10067d 100644 --- a/gcc/testsuite/gfortran.dg/gomp/declare-variant-7.f90 +++ b/gcc/testsuite/gfortran.dg/gomp/declare-variant-7.f90 @@ -5,25 +5,24 @@ module main implicit none contains function f1 (x, y, z) - integer, dimension(4) :: f1 - real, dimension(4), intent(in) :: x, y - real, intent(out) :: z + integer :: f1 + real, intent(in) :: x, y + real, pointer, intent(out) :: z f1 = x end function function f2 (x, y, z) - integer, dimension(8) :: f2 - real, dimension(8), intent(in) :: x, y - real, intent(out) :: z + integer :: f2 + real, intent(in) :: x, y + real, pointer, intent(out) :: z f2 = x end function - function f3 (x, y, z) - integer, dimension(4) :: f3 - real, dimension(4), intent(in) :: x, z - integer, intent(in) :: y + function f3 (x, z) + integer :: f3 + integer, intent(in) :: x, z f3 = x end function -- 2.39.5