diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp --- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -11150,7 +11150,7 @@ /// as defined by `LS(P)` in 3.2.1 of the AAVFABI. /// TODO: Add support for references, section 3.2.1, item 1. static unsigned getAArch64LS(QualType QT, ParamKindTy Kind, ASTContext &C) { - if (getAArch64MTV(QT, Kind) && QT.getCanonicalType()->isPointerType()) { + if (!getAArch64MTV(QT, Kind) && QT.getCanonicalType()->isPointerType()) { QualType PTy = QT.getCanonicalType()->getPointeeType(); if (getAArch64PBV(PTy, C)) return C.getTypeSize(PTy); diff --git a/clang/test/OpenMP/aarch64_vfabi_NarrowestDataSize.c b/clang/test/OpenMP/aarch64_vfabi_NarrowestDataSize.c new file mode 100644 --- /dev/null +++ b/clang/test/OpenMP/aarch64_vfabi_NarrowestDataSize.c @@ -0,0 +1,82 @@ +// RUN: %clang_cc1 -triple aarch64-linux-gnu -target-feature +neon -fopenmp -x c -emit-llvm %s -o - -femit-all-decls | FileCheck %s +// RUN: %clang_cc1 -triple aarch64-linux-gnu -target-feature +neon -fopenmp-simd -x c -emit-llvm %s -o - -femit-all-decls | FileCheck %s + +// REQUIRES: aarch64-registered-target +// Note: -fopemp and -fopenmp-simd behavior are expected to be the same. + +// This test checks the values of Narrowest Data Size (NDS), as defined in +// https://github.com/ARM-software/abi-aa/tree/master/vfabia64 +// +// NDS is used to compute the token in the name of AdvSIMD +// vector functions when no `simdlen` is specified, with the rule: +// +// if NDS(f) = 1, then VLEN = 16, 8; +// if NDS(f) = 2, then VLEN = 8, 4; +// if NDS(f) = 4, then VLEN = 4, 2; +// if NDS(f) = 8 or NDS(f) = 16, then VLEN = 2. + +// NDS(NDS_is_sizeof_char) = 1 +#pragma omp declare simd notinbranch +char NDS_is_sizeof_char(short in); +// CHECK-DAG: _ZGVnN16v_NDS_is_sizeof_char +// CHECK-DAG: _ZGVnN8v_NDS_is_sizeof_char +// CHECK-NOT: _ZGV{{.*}}_NDS_is_sizeof_char + +// NDS(NDS_is_sizeof_short) = 2 +#pragma omp declare simd notinbranch +int NDS_is_sizeof_short(short in); +// CHECK-DAG: _ZGVnN8v_NDS_is_sizeof_short +// CHECK-DAG: _ZGVnN4v_NDS_is_sizeof_short +// CHECK-NOT: _ZGV{{.*}}_NDS_is_sizeof_short + +// NDS(NDS_is_sizeof_float_with_linear) = 4, and not 2, because the pointers are +// marked as `linear` and therefore the size of the pointee realizes +// the NDS. +#pragma omp declare simd linear(sin) notinbranch +void NDS_is_sizeof_float_with_linear(double in, float *sin); +// Neon accepts only power of 2 values as . +// CHECK-DAG: _ZGVnN4vl4_NDS_is_sizeof_float_with_linear +// CHECK-DAG: _ZGVnN2vl4_NDS_is_sizeof_float_with_linear +// CHECK-NOT: _ZGV{{.*}}_NDS_is_sizeof_float_with_linear + +// NDS(NDS_is_size_of_float) = 4 +#pragma omp declare simd notinbranch +double NDS_is_size_of_float(float in); +// CHECK-DAG: _ZGVnN4v_NDS_is_size_of_float +// CHECK-DAG: _ZGVnN2v_NDS_is_size_of_float +// CHECK-NOT: _ZGV{{.*}}_NDS_is_size_of_float + +// NDS(NDS_is_sizeof_double) = 8 +#pragma omp declare simd linear(sin) notinbranch +void NDS_is_sizeof_double(double in, double *sin); +// CHECK-DAG: _ZGVnN2vl8_NDS_is_sizeof_double +// CHECK-NOT: _ZGV{{.*}}_NDS_is_sizeof_double + +// NDS(double_complex) = 16 +#pragma omp declare simd notinbranch +double _Complex double_complex(double _Complex); +// CHECK-DAG: _ZGVnN2v_double_complex +// CHECK-NOT: _ZGV{{.*}}_double_complex + +// NDS(double_complex_linear_char) = 1, becasue `x` is marked linear. +#pragma omp declare simd linear(x) notinbranch +double _Complex double_complex_linear_char(double _Complex y, char *x); +// CHECK-DAG: _ZGVnN8vl_double_complex_linear_char +// CHECK-DAG: _ZGVnN16vl_double_complex_linear_char +// CHECK-NOT: _ZGV{{.*}}_double_complex_linear_char + +static float *F; +static double *D; +static short S; +static int I; +static char C; +static double _Complex DC; +void do_something() { + C = NDS_is_sizeof_char(S); + I = NDS_is_sizeof_short(S); + NDS_is_sizeof_float_with_linear(*D, F); + *D = NDS_is_size_of_float(*F); + NDS_is_sizeof_double(*D, D); + DC = double_complex(DC); + DC = double_complex_linear_char(DC, &C); +} diff --git a/clang/test/OpenMP/aarch64_vfabi_WidestDataSize.c b/clang/test/OpenMP/aarch64_vfabi_WidestDataSize.c new file mode 100644 --- /dev/null +++ b/clang/test/OpenMP/aarch64_vfabi_WidestDataSize.c @@ -0,0 +1,78 @@ +// RUN: %clang_cc1 -triple aarch64-linux-gnu -target-feature +sve -fopenmp -x c -emit-llvm %s -o - -femit-all-decls | FileCheck %s +// RUN: %clang_cc1 -triple aarch64-linux-gnu -target-feature +sve -fopenmp-simd -x c -emit-llvm %s -o - -femit-all-decls | FileCheck %s + +// REQUIRES: aarch64-registered-target +// Note: -fopemp and -fopenmp-simd behavior are expected to be the same. + +// This test checks the values of Widest Data Size (WDS), as defined +// in https://github.com/ARM-software/abi-aa/tree/master/vfabia64 +// +// WDS is used to check the accepted values of `simdlen()` when +// targeting fixed-length SVE vector function names. The values of +// `` that are accepted are such that for X = WDS * * 8, +// 128-bit <= X <= 2048-bit and X is a multiple of 128-bit. + +#pragma omp declare simd simdlen(8) +#pragma omp declare simd simdlen(16) +#pragma omp declare simd simdlen(256) +#pragma omp declare simd simdlen(272) +char WDS_is_sizeof_char(char in); +// WDS = 1, simdlen(8) and simdlen(272) are not generated. +// CHECK-DAG: _ZGVsM16v_WDS_is_sizeof_char +// CHECK-DAG: _ZGVsM256v_WDS_is_sizeof_char +// CHECK-NOT: _ZGV{{.*}}_WDS_is_sizeof_char + +#pragma omp declare simd simdlen(4) +#pragma omp declare simd simdlen(8) +#pragma omp declare simd simdlen(128) +#pragma omp declare simd simdlen(136) +char WDS_is_sizeof_short(short in); +// WDS = 2, simdlen(4) and simdlen(136) are not generated. +// CHECK-DAG: _ZGVsM8v_WDS_is_sizeof_short +// CHECK-DAG: _ZGVsM128v_WDS_is_sizeof_short +// CHECK-NOT: _ZGV{{.*}}_WDS_is_sizeof_short + +#pragma omp declare simd linear(sin) notinbranch simdlen(2) +#pragma omp declare simd linear(sin) notinbranch simdlen(4) +#pragma omp declare simd linear(sin) notinbranch simdlen(64) +#pragma omp declare simd linear(sin) notinbranch simdlen(68) +void WDS_is_sizeof_float_pointee(float in, float *sin); +// WDS = 4, simdlen(2) and simdlen(68) are not generated. +// CHECK-DAG: _ZGVsM4vl4_WDS_is_sizeof_float_pointee +// CHECK-DAG: _ZGVsM64vl4_WDS_is_sizeof_float_pointee +// CHECK-NOT: _ZGV{{.*}}_WDS_is_sizeof_float_pointee + +#pragma omp declare simd linear(sin) notinbranch simdlen(2) +#pragma omp declare simd linear(sin) notinbranch simdlen(4) +#pragma omp declare simd linear(sin) notinbranch simdlen(32) +#pragma omp declare simd linear(sin) notinbranch simdlen(34) +void WDS_is_sizeof_double_pointee(float in, double *sin); +// WDS = 8 because of the linear clause, simdlen(34) is not generated. +// CHECK-DAG: _ZGVsM2vl8_WDS_is_sizeof_double_pointee +// CHECK-DAG: _ZGVsM4vl8_WDS_is_sizeof_double_pointee +// CHECK-DAG: _ZGVsM32vl8_WDS_is_sizeof_double_pointee +// CHECK-NOT: _ZGV{{.*}}_WDS_is_sizeof_double_pointee + +#pragma omp declare simd simdlen(2) +#pragma omp declare simd simdlen(4) +#pragma omp declare simd simdlen(32) +#pragma omp declare simd simdlen(34) +double WDS_is_sizeof_double(double in); +// WDS = 8, simdlen(34) is not generated. +// CHECK-DAG: _ZGVsM2v_WDS_is_sizeof_double +// CHECK-DAG: _ZGVsM4v_WDS_is_sizeof_double +// CHECK-DAG: _ZGVsM32v_WDS_is_sizeof_double +// CHECK-NOT: _ZGV{{.*}}_WDS_is_sizeof_double + +static char C; +static short S; +static float F; +static double D; + +void do_something() { + C = WDS_is_sizeof_char(C); + C = WDS_is_sizeof_short(S); + WDS_is_sizeof_float_pointee(F, &F); + WDS_is_sizeof_double_pointee(F, &D); + D = WDS_is_sizeof_double(D); +}