This revision was automatically updated to reflect the committed changes. Closed by commit rG515020c091e7: [SveEmitter] Add more immediate operand checks. (authored by sdesmalen).
Changed prior to commit: https://reviews.llvm.org/D76679?vs=252246&id=258724#toc Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D76679/new/ https://reviews.llvm.org/D76679 Files: clang/include/clang/Basic/arm_sve.td clang/lib/CodeGen/CGBuiltin.cpp clang/lib/Sema/SemaChecking.cpp clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_asrd.c clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ext.c clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_tmad.c clang/test/CodeGen/aarch64-sve-intrinsics/negative/acle_sve_asrd.c clang/test/CodeGen/aarch64-sve-intrinsics/negative/acle_sve_ext.c clang/test/CodeGen/aarch64-sve-intrinsics/negative/acle_sve_tmad.c clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qshlu.c clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_shrnb.c clang/test/CodeGen/aarch64-sve2-intrinsics/negative/acle_sve2_qshlu.c clang/test/CodeGen/aarch64-sve2-intrinsics/negative/acle_sve2_shrnb.c clang/utils/TableGen/SveEmitter.cpp
Index: clang/utils/TableGen/SveEmitter.cpp =================================================================== --- clang/utils/TableGen/SveEmitter.cpp +++ clang/utils/TableGen/SveEmitter.cpp @@ -456,6 +456,9 @@ Bitwidth = ElementBitwidth; NumVectors = 0; break; + case 'h': + ElementBitwidth /= 2; + break; case 'P': Signed = true; Float = false; @@ -463,6 +466,11 @@ Bitwidth = 16; ElementBitwidth = 1; break; + case 'u': + Predicate = false; + Signed = false; + Float = false; + break; case 'i': Predicate = false; Float = false; Index: clang/test/CodeGen/aarch64-sve2-intrinsics/negative/acle_sve2_shrnb.c =================================================================== --- /dev/null +++ clang/test/CodeGen/aarch64-sve2-intrinsics/negative/acle_sve2_shrnb.c @@ -0,0 +1,47 @@ +// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -D__ARM_FEATURE_SVE2 -triple aarch64-none-linux-gnu -target-feature +sve2 -fallow-half-arguments-and-returns -fsyntax-only -verify %s +// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -D__ARM_FEATURE_SVE2 -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve2 -fallow-half-arguments-and-returns -fsyntax-only -verify %s + +#ifdef SVE_OVERLOADED_FORMS +// A simple used,unused... macro, long enough to represent any SVE builtin. +#define SVE_ACLE_FUNC(A1,A2_UNUSED,A3,A4_UNUSED) A1##A3 +#else +#define SVE_ACLE_FUNC(A1,A2,A3,A4) A1##A2##A3##A4 +#endif + +#include <arm_sve.h> + +svint8_t test_svshrnb_n_s16(svint16_t op1) +{ + // expected-error-re@+1 {{argument value {{[0-9]+}} is outside the valid range [1, 8]}} + return SVE_ACLE_FUNC(svshrnb,_n_s16,,)(op1, 0); +} + +svint16_t test_svshrnb_n_s32(svint32_t op1) +{ + // expected-error-re@+1 {{argument value {{[0-9]+}} is outside the valid range [1, 16]}} + return SVE_ACLE_FUNC(svshrnb,_n_s32,,)(op1, 0); +} + +svint32_t test_svshrnb_n_s64(svint64_t op1) +{ + // expected-error-re@+1 {{argument value {{[0-9]+}} is outside the valid range [1, 32]}} + return SVE_ACLE_FUNC(svshrnb,_n_s64,,)(op1, 0); +} + +svuint8_t test_svshrnb_n_u16(svuint16_t op1) +{ + // expected-error-re@+1 {{argument value {{[0-9]+}} is outside the valid range [1, 8]}} + return SVE_ACLE_FUNC(svshrnb,_n_u16,,)(op1, 0); +} + +svuint16_t test_svshrnb_n_u32(svuint32_t op1) +{ + // expected-error-re@+1 {{argument value {{[0-9]+}} is outside the valid range [1, 16]}} + return SVE_ACLE_FUNC(svshrnb,_n_u32,,)(op1, 0); +} + +svuint32_t test_svshrnb_n_u64(svuint64_t op1) +{ + // expected-error-re@+1 {{argument value {{[0-9]+}} is outside the valid range [1, 32]}} + return SVE_ACLE_FUNC(svshrnb,_n_u64,,)(op1, 0); +} Index: clang/test/CodeGen/aarch64-sve2-intrinsics/negative/acle_sve2_qshlu.c =================================================================== --- /dev/null +++ clang/test/CodeGen/aarch64-sve2-intrinsics/negative/acle_sve2_qshlu.c @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -D__ARM_FEATURE_SVE2 -triple aarch64-none-linux-gnu -target-feature +sve2 -fallow-half-arguments-and-returns -fsyntax-only -verify %s +// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -D__ARM_FEATURE_SVE2 -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve2 -fallow-half-arguments-and-returns -fsyntax-only -verify %s + +#ifdef SVE_OVERLOADED_FORMS +// A simple used,unused... macro, long enough to represent any SVE builtin. +#define SVE_ACLE_FUNC(A1,A2_UNUSED,A3,A4_UNUSED) A1##A3 +#else +#define SVE_ACLE_FUNC(A1,A2,A3,A4) A1##A2##A3##A4 +#endif + +#include <arm_sve.h> + +svuint8_t test_svqshlu_n_s8_m(svbool_t pg, svint8_t op1) +{ + // expected-error-re@+1 {{argument value {{[0-9]+}} is outside the valid range [0, 7]}} + return SVE_ACLE_FUNC(svqshlu,_n_s8,_m,)(pg, op1, -1); +} + +svuint16_t test_svqshlu_n_s16_m(svbool_t pg, svint16_t op1) +{ + // expected-error-re@+1 {{argument value {{[0-9]+}} is outside the valid range [0, 15]}} + return SVE_ACLE_FUNC(svqshlu,_n_s16,_m,)(pg, op1, -1); +} + +svuint32_t test_svqshlu_n_s32_m(svbool_t pg, svint32_t op1) +{ + // expected-error-re@+1 {{argument value {{[0-9]+}} is outside the valid range [0, 31]}} + return SVE_ACLE_FUNC(svqshlu,_n_s32,_m,)(pg, op1, -1); +} + +svuint64_t test_svqshlu_n_s64_m(svbool_t pg, svint64_t op1) +{ + // expected-error-re@+1 {{argument value {{[0-9]+}} is outside the valid range [0, 63]}} + return SVE_ACLE_FUNC(svqshlu,_n_s64,_m,)(pg, op1, -1); +} Index: clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_shrnb.c =================================================================== --- /dev/null +++ clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_shrnb.c @@ -0,0 +1,133 @@ +// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -D__ARM_FEATURE_SVE2 -triple aarch64-none-linux-gnu -target-feature +sve2 -fallow-half-arguments-and-returns -S -O1 -Werror -Wall -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -D__ARM_FEATURE_SVE2 -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve2 -fallow-half-arguments-and-returns -S -O1 -Werror -Wall -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -triple aarch64-none-linux-gnu -target-feature +sve -fallow-half-arguments-and-returns -fsyntax-only -verify -verify-ignore-unexpected=error %s +// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve -fallow-half-arguments-and-returns -fsyntax-only -verify=overload -verify-ignore-unexpected=error %s + +#include <arm_sve.h> + +#ifdef SVE_OVERLOADED_FORMS +// A simple used,unused... macro, long enough to represent any SVE builtin. +#define SVE_ACLE_FUNC(A1,A2_UNUSED,A3,A4_UNUSED) A1##A3 +#else +#define SVE_ACLE_FUNC(A1,A2,A3,A4) A1##A2##A3##A4 +#endif + +svint8_t test_svshrnb_n_s16(svint16_t op1) +{ + // CHECK-LABEL: test_svshrnb_n_s16 + // CHECK: %[[INTRINSIC:.*]] = call <vscale x 16 x i8> @llvm.aarch64.sve.shrnb.nxv8i16(<vscale x 8 x i16> %op1, i32 1) + // CHECK: ret <vscale x 16 x i8> %[[INTRINSIC]] + // overload-warning@+2 {{implicit declaration of function 'svshrnb'}} + // expected-warning@+1 {{implicit declaration of function 'svshrnb_n_s16'}} + return SVE_ACLE_FUNC(svshrnb,_n_s16,,)(op1, 1); +} + +svint8_t test_svshrnb_n_s16_1(svint16_t op1) +{ + // CHECK-LABEL: test_svshrnb_n_s16_1 + // CHECK: %[[INTRINSIC:.*]] = call <vscale x 16 x i8> @llvm.aarch64.sve.shrnb.nxv8i16(<vscale x 8 x i16> %op1, i32 8) + // CHECK: ret <vscale x 16 x i8> %[[INTRINSIC]] + // overload-warning@+2 {{implicit declaration of function 'svshrnb'}} + // expected-warning@+1 {{implicit declaration of function 'svshrnb_n_s16'}} + return SVE_ACLE_FUNC(svshrnb,_n_s16,,)(op1, 8); +} + +svint16_t test_svshrnb_n_s32(svint32_t op1) +{ + // CHECK-LABEL: test_svshrnb_n_s32 + // CHECK: %[[INTRINSIC:.*]] = call <vscale x 8 x i16> @llvm.aarch64.sve.shrnb.nxv4i32(<vscale x 4 x i32> %op1, i32 1) + // CHECK: ret <vscale x 8 x i16> %[[INTRINSIC]] + // overload-warning@+2 {{implicit declaration of function 'svshrnb'}} + // expected-warning@+1 {{implicit declaration of function 'svshrnb_n_s32'}} + return SVE_ACLE_FUNC(svshrnb,_n_s32,,)(op1, 1); +} + +svint16_t test_svshrnb_n_s32_1(svint32_t op1) +{ + // CHECK-LABEL: test_svshrnb_n_s32_1 + // CHECK: %[[INTRINSIC:.*]] = call <vscale x 8 x i16> @llvm.aarch64.sve.shrnb.nxv4i32(<vscale x 4 x i32> %op1, i32 16) + // CHECK: ret <vscale x 8 x i16> %[[INTRINSIC]] + // overload-warning@+2 {{implicit declaration of function 'svshrnb'}} + // expected-warning@+1 {{implicit declaration of function 'svshrnb_n_s32'}} + return SVE_ACLE_FUNC(svshrnb,_n_s32,,)(op1, 16); +} + +svint32_t test_svshrnb_n_s64(svint64_t op1) +{ + // CHECK-LABEL: test_svshrnb_n_s64 + // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x i32> @llvm.aarch64.sve.shrnb.nxv2i64(<vscale x 2 x i64> %op1, i32 1) + // CHECK: ret <vscale x 4 x i32> %[[INTRINSIC]] + // overload-warning@+2 {{implicit declaration of function 'svshrnb'}} + // expected-warning@+1 {{implicit declaration of function 'svshrnb_n_s64'}} + return SVE_ACLE_FUNC(svshrnb,_n_s64,,)(op1, 1); +} + +svint32_t test_svshrnb_n_s64_1(svint64_t op1) +{ + // CHECK-LABEL: test_svshrnb_n_s64_1 + // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x i32> @llvm.aarch64.sve.shrnb.nxv2i64(<vscale x 2 x i64> %op1, i32 32) + // CHECK: ret <vscale x 4 x i32> %[[INTRINSIC]] + // overload-warning@+2 {{implicit declaration of function 'svshrnb'}} + // expected-warning@+1 {{implicit declaration of function 'svshrnb_n_s64'}} + return SVE_ACLE_FUNC(svshrnb,_n_s64,,)(op1, 32); +} + +svuint8_t test_svshrnb_n_u16(svuint16_t op1) +{ + // CHECK-LABEL: test_svshrnb_n_u16 + // CHECK: %[[INTRINSIC:.*]] = call <vscale x 16 x i8> @llvm.aarch64.sve.shrnb.nxv8i16(<vscale x 8 x i16> %op1, i32 1) + // CHECK: ret <vscale x 16 x i8> %[[INTRINSIC]] + // overload-warning@+2 {{implicit declaration of function 'svshrnb'}} + // expected-warning@+1 {{implicit declaration of function 'svshrnb_n_u16'}} + return SVE_ACLE_FUNC(svshrnb,_n_u16,,)(op1, 1); +} + +svuint8_t test_svshrnb_n_u16_1(svuint16_t op1) +{ + // CHECK-LABEL: test_svshrnb_n_u16_1 + // CHECK: %[[INTRINSIC:.*]] = call <vscale x 16 x i8> @llvm.aarch64.sve.shrnb.nxv8i16(<vscale x 8 x i16> %op1, i32 8) + // CHECK: ret <vscale x 16 x i8> %[[INTRINSIC]] + // overload-warning@+2 {{implicit declaration of function 'svshrnb'}} + // expected-warning@+1 {{implicit declaration of function 'svshrnb_n_u16'}} + return SVE_ACLE_FUNC(svshrnb,_n_u16,,)(op1, 8); +} + +svuint16_t test_svshrnb_n_u32(svuint32_t op1) +{ + // CHECK-LABEL: test_svshrnb_n_u32 + // CHECK: %[[INTRINSIC:.*]] = call <vscale x 8 x i16> @llvm.aarch64.sve.shrnb.nxv4i32(<vscale x 4 x i32> %op1, i32 1) + // CHECK: ret <vscale x 8 x i16> %[[INTRINSIC]] + // overload-warning@+2 {{implicit declaration of function 'svshrnb'}} + // expected-warning@+1 {{implicit declaration of function 'svshrnb_n_u32'}} + return SVE_ACLE_FUNC(svshrnb,_n_u32,,)(op1, 1); +} + +svuint16_t test_svshrnb_n_u32_1(svuint32_t op1) +{ + // CHECK-LABEL: test_svshrnb_n_u32_1 + // CHECK: %[[INTRINSIC:.*]] = call <vscale x 8 x i16> @llvm.aarch64.sve.shrnb.nxv4i32(<vscale x 4 x i32> %op1, i32 16) + // CHECK: ret <vscale x 8 x i16> %[[INTRINSIC]] + // overload-warning@+2 {{implicit declaration of function 'svshrnb'}} + // expected-warning@+1 {{implicit declaration of function 'svshrnb_n_u32'}} + return SVE_ACLE_FUNC(svshrnb,_n_u32,,)(op1, 16); +} + +svuint32_t test_svshrnb_n_u64(svuint64_t op1) +{ + // CHECK-LABEL: test_svshrnb_n_u64 + // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x i32> @llvm.aarch64.sve.shrnb.nxv2i64(<vscale x 2 x i64> %op1, i32 1) + // CHECK: ret <vscale x 4 x i32> %[[INTRINSIC]] + // overload-warning@+2 {{implicit declaration of function 'svshrnb'}} + // expected-warning@+1 {{implicit declaration of function 'svshrnb_n_u64'}} + return SVE_ACLE_FUNC(svshrnb,_n_u64,,)(op1, 1); +} + +svuint32_t test_svshrnb_n_u64_1(svuint64_t op1) +{ + // CHECK-LABEL: test_svshrnb_n_u64_1 + // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x i32> @llvm.aarch64.sve.shrnb.nxv2i64(<vscale x 2 x i64> %op1, i32 32) + // CHECK: ret <vscale x 4 x i32> %[[INTRINSIC]] + // overload-warning@+2 {{implicit declaration of function 'svshrnb'}} + // expected-warning@+1 {{implicit declaration of function 'svshrnb_n_u64'}} + return SVE_ACLE_FUNC(svshrnb,_n_u64,,)(op1, 32); +} Index: clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qshlu.c =================================================================== --- /dev/null +++ clang/test/CodeGen/aarch64-sve2-intrinsics/acle_sve2_qshlu.c @@ -0,0 +1,99 @@ +// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -D__ARM_FEATURE_SVE2 -triple aarch64-none-linux-gnu -target-feature +sve2 -fallow-half-arguments-and-returns -S -O1 -Werror -Wall -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -D__ARM_FEATURE_SVE2 -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve2 -fallow-half-arguments-and-returns -S -O1 -Werror -Wall -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -triple aarch64-none-linux-gnu -target-feature +sve -fallow-half-arguments-and-returns -fsyntax-only -verify -verify-ignore-unexpected=error %s +// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve -fallow-half-arguments-and-returns -fsyntax-only -verify=overload -verify-ignore-unexpected=error %s + +#include <arm_sve.h> + +#ifdef SVE_OVERLOADED_FORMS +// A simple used,unused... macro, long enough to represent any SVE builtin. +#define SVE_ACLE_FUNC(A1,A2_UNUSED,A3,A4_UNUSED) A1##A3 +#else +#define SVE_ACLE_FUNC(A1,A2,A3,A4) A1##A2##A3##A4 +#endif + +svuint8_t test_svqshlu_n_s8_m(svbool_t pg, svint8_t op1) +{ + // CHECK-LABEL: test_svqshlu_n_s8_m + // CHECK: %[[INTRINSIC:.*]] = call <vscale x 16 x i8> @llvm.aarch64.sve.sqshlu.nxv16i8(<vscale x 16 x i1> %pg, <vscale x 16 x i8> %op1, i32 0) + // CHECK: ret <vscale x 16 x i8> %[[INTRINSIC]] + // overload-warning@+2 {{implicit declaration of function 'svqshlu_m'}} + // expected-warning@+1 {{implicit declaration of function 'svqshlu_n_s8_m'}} + return SVE_ACLE_FUNC(svqshlu,_n_s8,_m,)(pg, op1, 0); +} + +svuint8_t test_svqshlu_n_s8_m_1(svbool_t pg, svint8_t op1) +{ + // CHECK-LABEL: test_svqshlu_n_s8_m_1 + // CHECK: %[[INTRINSIC:.*]] = call <vscale x 16 x i8> @llvm.aarch64.sve.sqshlu.nxv16i8(<vscale x 16 x i1> %pg, <vscale x 16 x i8> %op1, i32 7) + // CHECK: ret <vscale x 16 x i8> %[[INTRINSIC]] + // overload-warning@+2 {{implicit declaration of function 'svqshlu_m'}} + // expected-warning@+1 {{implicit declaration of function 'svqshlu_n_s8_m'}} + return SVE_ACLE_FUNC(svqshlu,_n_s8,_m,)(pg, op1, 7); +} + +svuint16_t test_svqshlu_n_s16_m(svbool_t pg, svint16_t op1) +{ + // CHECK-LABEL: test_svqshlu_n_s16_m + // CHECK: %[[PG:.*]] = call <vscale x 8 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv8i1(<vscale x 16 x i1> %pg) + // CHECK: %[[INTRINSIC:.*]] = call <vscale x 8 x i16> @llvm.aarch64.sve.sqshlu.nxv8i16(<vscale x 8 x i1> %[[PG]], <vscale x 8 x i16> %op1, i32 0) + // CHECK: ret <vscale x 8 x i16> %[[INTRINSIC]] + // overload-warning@+2 {{implicit declaration of function 'svqshlu_m'}} + // expected-warning@+1 {{implicit declaration of function 'svqshlu_n_s16_m'}} + return SVE_ACLE_FUNC(svqshlu,_n_s16,_m,)(pg, op1, 0); +} + +svuint16_t test_svqshlu_n_s16_m_1(svbool_t pg, svint16_t op1) +{ + // CHECK-LABEL: test_svqshlu_n_s16_m_1 + // CHECK: %[[PG:.*]] = call <vscale x 8 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv8i1(<vscale x 16 x i1> %pg) + // CHECK: %[[INTRINSIC:.*]] = call <vscale x 8 x i16> @llvm.aarch64.sve.sqshlu.nxv8i16(<vscale x 8 x i1> %[[PG]], <vscale x 8 x i16> %op1, i32 15) + // CHECK: ret <vscale x 8 x i16> %[[INTRINSIC]] + // overload-warning@+2 {{implicit declaration of function 'svqshlu_m'}} + // expected-warning@+1 {{implicit declaration of function 'svqshlu_n_s16_m'}} + return SVE_ACLE_FUNC(svqshlu,_n_s16,_m,)(pg, op1, 15); +} + +svuint32_t test_svqshlu_n_s32_m(svbool_t pg, svint32_t op1) +{ + // CHECK-LABEL: test_svqshlu_n_s32_m + // CHECK: %[[PG:.*]] = call <vscale x 4 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv4i1(<vscale x 16 x i1> %pg) + // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x i32> @llvm.aarch64.sve.sqshlu.nxv4i32(<vscale x 4 x i1> %[[PG]], <vscale x 4 x i32> %op1, i32 0) + // CHECK: ret <vscale x 4 x i32> %[[INTRINSIC]] + // overload-warning@+2 {{implicit declaration of function 'svqshlu_m'}} + // expected-warning@+1 {{implicit declaration of function 'svqshlu_n_s32_m'}} + return SVE_ACLE_FUNC(svqshlu,_n_s32,_m,)(pg, op1, 0); +} + +svuint32_t test_svqshlu_n_s32_m_1(svbool_t pg, svint32_t op1) +{ + // CHECK-LABEL: test_svqshlu_n_s32_m_1 + // CHECK: %[[PG:.*]] = call <vscale x 4 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv4i1(<vscale x 16 x i1> %pg) + // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x i32> @llvm.aarch64.sve.sqshlu.nxv4i32(<vscale x 4 x i1> %[[PG]], <vscale x 4 x i32> %op1, i32 31) + // CHECK: ret <vscale x 4 x i32> %[[INTRINSIC]] + // overload-warning@+2 {{implicit declaration of function 'svqshlu_m'}} + // expected-warning@+1 {{implicit declaration of function 'svqshlu_n_s32_m'}} + return SVE_ACLE_FUNC(svqshlu,_n_s32,_m,)(pg, op1, 31); +} + +svuint64_t test_svqshlu_n_s64_m(svbool_t pg, svint64_t op1) +{ + // CHECK-LABEL: test_svqshlu_n_s64_m + // CHECK: %[[PG:.*]] = call <vscale x 2 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv2i1(<vscale x 16 x i1> %pg) + // CHECK: %[[INTRINSIC:.*]] = call <vscale x 2 x i64> @llvm.aarch64.sve.sqshlu.nxv2i64(<vscale x 2 x i1> %[[PG]], <vscale x 2 x i64> %op1, i32 0) + // CHECK: ret <vscale x 2 x i64> %[[INTRINSIC]] + // overload-warning@+2 {{implicit declaration of function 'svqshlu_m'}} + // expected-warning@+1 {{implicit declaration of function 'svqshlu_n_s64_m'}} + return SVE_ACLE_FUNC(svqshlu,_n_s64,_m,)(pg, op1, 0); +} + +svuint64_t test_svqshlu_n_s64_m_1(svbool_t pg, svint64_t op1) +{ + // CHECK-LABEL: test_svqshlu_n_s64_m_1 + // CHECK: %[[PG:.*]] = call <vscale x 2 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv2i1(<vscale x 16 x i1> %pg) + // CHECK: %[[INTRINSIC:.*]] = call <vscale x 2 x i64> @llvm.aarch64.sve.sqshlu.nxv2i64(<vscale x 2 x i1> %[[PG]], <vscale x 2 x i64> %op1, i32 63) + // CHECK: ret <vscale x 2 x i64> %[[INTRINSIC]] + // overload-warning@+2 {{implicit declaration of function 'svqshlu_m'}} + // expected-warning@+1 {{implicit declaration of function 'svqshlu_n_s64_m'}} + return SVE_ACLE_FUNC(svqshlu,_n_s64,_m,)(pg, op1, 63); +} Index: clang/test/CodeGen/aarch64-sve-intrinsics/negative/acle_sve_tmad.c =================================================================== --- /dev/null +++ clang/test/CodeGen/aarch64-sve-intrinsics/negative/acle_sve_tmad.c @@ -0,0 +1,47 @@ +// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -triple aarch64-none-linux-gnu -target-feature +sve -fallow-half-arguments-and-returns -fsyntax-only -verify %s +// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve -fallow-half-arguments-and-returns -fsyntax-only -verify %s + +#ifdef SVE_OVERLOADED_FORMS +// A simple used,unused... macro, long enough to represent any SVE builtin. +#define SVE_ACLE_FUNC(A1,A2_UNUSED,A3,A4_UNUSED) A1##A3 +#else +#define SVE_ACLE_FUNC(A1,A2,A3,A4) A1##A2##A3##A4 +#endif + +#include <arm_sve.h> + +svfloat16_t test_svtmad_f16(svfloat16_t op1, svfloat16_t op2) +{ + // expected-error-re@+1 {{argument value {{[0-9]+}} is outside the valid range [0, 7]}} + return SVE_ACLE_FUNC(svtmad,_f16,,)(op1, op2, -1); +} + +svfloat16_t test_svtmad_f16_1(svfloat16_t op1, svfloat16_t op2) +{ + // expected-error-re@+1 {{argument value {{[0-9]+}} is outside the valid range [0, 7]}} + return SVE_ACLE_FUNC(svtmad,_f16,,)(op1, op2, 8); +} + +svfloat32_t test_svtmad_f32(svfloat32_t op1, svfloat32_t op2) +{ + // expected-error-re@+1 {{argument value {{[0-9]+}} is outside the valid range [0, 7]}} + return SVE_ACLE_FUNC(svtmad,_f32,,)(op1, op2, -1); +} + +svfloat32_t test_svtmad_f32_1(svfloat32_t op1, svfloat32_t op2) +{ + // expected-error-re@+1 {{argument value {{[0-9]+}} is outside the valid range [0, 7]}} + return SVE_ACLE_FUNC(svtmad,_f32,,)(op1, op2, 8); +} + +svfloat64_t test_svtmad_f64(svfloat64_t op1, svfloat64_t op2) +{ + // expected-error-re@+1 {{argument value {{[0-9]+}} is outside the valid range [0, 7]}} + return SVE_ACLE_FUNC(svtmad,_f64,,)(op1, op2, -1); +} + +svfloat64_t test_svtmad_f64_1(svfloat64_t op1, svfloat64_t op2) +{ + // expected-error-re@+1 {{argument value {{[0-9]+}} is outside the valid range [0, 7]}} + return SVE_ACLE_FUNC(svtmad,_f64,,)(op1, op2, 8); +} Index: clang/test/CodeGen/aarch64-sve-intrinsics/negative/acle_sve_ext.c =================================================================== --- /dev/null +++ clang/test/CodeGen/aarch64-sve-intrinsics/negative/acle_sve_ext.c @@ -0,0 +1,101 @@ +// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -triple aarch64-none-linux-gnu -target-feature +sve -fallow-half-arguments-and-returns -fsyntax-only -verify %s +// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve -fallow-half-arguments-and-returns -fsyntax-only -verify %s + +#ifdef SVE_OVERLOADED_FORMS +// A simple used,unused... macro, long enough to represent any SVE builtin. +#define SVE_ACLE_FUNC(A1,A2_UNUSED,A3,A4_UNUSED) A1##A3 +#else +#define SVE_ACLE_FUNC(A1,A2,A3,A4) A1##A2##A3##A4 +#endif + +#include <arm_sve.h> + +svint8_t test_svext_s8(svint8_t op1, svint8_t op2) +{ + // expected-error-re@+1 {{argument value {{[0-9]+}} is outside the valid range [0, 255]}} + return SVE_ACLE_FUNC(svext,_s8,,)(op1, op2, -1); +} + +svint8_t test_svext_s8_1(svint8_t op1, svint8_t op2) +{ + // expected-error-re@+1 {{argument value {{[0-9]+}} is outside the valid range [0, 255]}} + return SVE_ACLE_FUNC(svext,_s8,,)(op1, op2, 256); +} + +svint16_t test_svext_s16(svint16_t op1, svint16_t op2) +{ + // expected-error-re@+1 {{argument value {{[0-9]+}} is outside the valid range [0, 127]}} + return SVE_ACLE_FUNC(svext,_s16,,)(op1, op2, -1); +} + +svint16_t test_svext_s16_1(svint16_t op1, svint16_t op2) +{ + // expected-error-re@+1 {{argument value {{[0-9]+}} is outside the valid range [0, 127]}} + return SVE_ACLE_FUNC(svext,_s16,,)(op1, op2, 128); +} + +svint32_t test_svext_s32(svint32_t op1, svint32_t op2) +{ + // expected-error-re@+1 {{argument value {{[0-9]+}} is outside the valid range [0, 63]}} + return SVE_ACLE_FUNC(svext,_s32,,)(op1, op2, -1); +} + +svint32_t test_svext_s32_1(svint32_t op1, svint32_t op2) +{ + // expected-error-re@+1 {{argument value {{[0-9]+}} is outside the valid range [0, 63]}} + return SVE_ACLE_FUNC(svext,_s32,,)(op1, op2, 64); +} + +svint64_t test_svext_s64(svint64_t op1, svint64_t op2) +{ + // expected-error-re@+1 {{argument value {{[0-9]+}} is outside the valid range [0, 31]}} + return SVE_ACLE_FUNC(svext,_s64,,)(op1, op2, -1); +} + +svint64_t test_svext_s64_1(svint64_t op1, svint64_t op2) +{ + // expected-error-re@+1 {{argument value {{[0-9]+}} is outside the valid range [0, 31]}} + return SVE_ACLE_FUNC(svext,_s64,,)(op1, op2, 32); +} + +svuint8_t test_svext_u8(svuint8_t op1, svuint8_t op2) +{ + // expected-error-re@+1 {{argument value {{[0-9]+}} is outside the valid range [0, 255]}} + return SVE_ACLE_FUNC(svext,_u8,,)(op1, op2, -1); +} + +svuint16_t test_svext_u16(svuint16_t op1, svuint16_t op2) +{ + // expected-error-re@+1 {{argument value {{[0-9]+}} is outside the valid range [0, 127]}} + return SVE_ACLE_FUNC(svext,_u16,,)(op1, op2, 128); +} + +svuint32_t test_svext_u32(svuint32_t op1, svuint32_t op2) +{ + // expected-error-re@+1 {{argument value {{[0-9]+}} is outside the valid range [0, 63]}} + return SVE_ACLE_FUNC(svext,_u32,,)(op1, op2, -1); +} + +svuint64_t test_svext_u64(svuint64_t op1, svuint64_t op2) +{ + // expected-error-re@+1 {{argument value {{[0-9]+}} is outside the valid range [0, 31]}} + return SVE_ACLE_FUNC(svext,_u64,,)(op1, op2, 32); +} + +svfloat16_t test_svext_f16(svfloat16_t op1, svfloat16_t op2) +{ + // expected-error-re@+1 {{argument value {{[0-9]+}} is outside the valid range [0, 127]}} + return SVE_ACLE_FUNC(svext,_f16,,)(op1, op2, -1); +} + +svfloat32_t test_svext_f32(svfloat32_t op1, svfloat32_t op2) +{ + // expected-error-re@+1 {{argument value {{[0-9]+}} is outside the valid range [0, 63]}} + return SVE_ACLE_FUNC(svext,_f32,,)(op1, op2, 64); +} + +svfloat64_t test_svext_f64(svfloat64_t op1, svfloat64_t op2) +{ + // expected-error-re@+1 {{argument value {{[0-9]+}} is outside the valid range [0, 31]}} + return SVE_ACLE_FUNC(svext,_f64,,)(op1, op2, -1); +} Index: clang/test/CodeGen/aarch64-sve-intrinsics/negative/acle_sve_asrd.c =================================================================== --- /dev/null +++ clang/test/CodeGen/aarch64-sve-intrinsics/negative/acle_sve_asrd.c @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -triple aarch64-none-linux-gnu -target-feature +sve -fallow-half-arguments-and-returns -fsyntax-only -verify %s +// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve -fallow-half-arguments-and-returns -fsyntax-only -verify %s + +#ifdef SVE_OVERLOADED_FORMS +// A simple used,unused... macro, long enough to represent any SVE builtin. +#define SVE_ACLE_FUNC(A1,A2_UNUSED,A3,A4_UNUSED) A1##A3 +#else +#define SVE_ACLE_FUNC(A1,A2,A3,A4) A1##A2##A3##A4 +#endif + +#include <arm_sve.h> + +svint8_t test_svasrd_n_s8_m(svbool_t pg, svint8_t op1) +{ + // expected-error-re@+1 {{argument value {{[0-9]+}} is outside the valid range [1, 8]}} + return SVE_ACLE_FUNC(svasrd,_n_s8,_m,)(pg, op1, 0); +} + +svint16_t test_svasrd_n_s16_m(svbool_t pg, svint16_t op1) +{ + // expected-error-re@+1 {{argument value {{[0-9]+}} is outside the valid range [1, 16]}} + return SVE_ACLE_FUNC(svasrd,_n_s16,_m,)(pg, op1, 17); +} + +svint32_t test_svasrd_n_s32_m(svbool_t pg, svint32_t op1) +{ + // expected-error-re@+1 {{argument value {{[0-9]+}} is outside the valid range [1, 32]}} + return SVE_ACLE_FUNC(svasrd,_n_s32,_m,)(pg, op1, 0); +} + +svint64_t test_svasrd_n_s64_m(svbool_t pg, svint64_t op1) +{ + // expected-error-re@+1 {{argument value {{[0-9]+}} is outside the valid range [1, 64]}} + return SVE_ACLE_FUNC(svasrd,_n_s64,_m,)(pg, op1, 65); +} Index: clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_tmad.c =================================================================== --- /dev/null +++ clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_tmad.c @@ -0,0 +1,43 @@ +// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -triple aarch64-none-linux-gnu -target-feature +sve -fallow-half-arguments-and-returns -S -O1 -Werror -Wall -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve -fallow-half-arguments-and-returns -S -O1 -Werror -Wall -emit-llvm -o - %s | FileCheck %s + +#include <arm_sve.h> + +#ifdef SVE_OVERLOADED_FORMS +// A simple used,unused... macro, long enough to represent any SVE builtin. +#define SVE_ACLE_FUNC(A1,A2_UNUSED,A3,A4_UNUSED) A1##A3 +#else +#define SVE_ACLE_FUNC(A1,A2,A3,A4) A1##A2##A3##A4 +#endif + +svfloat16_t test_svtmad_f16(svfloat16_t op1, svfloat16_t op2) +{ + // CHECK-LABEL: test_svtmad_f16 + // CHECK: %[[INTRINSIC:.*]] = call <vscale x 8 x half> @llvm.aarch64.sve.ftmad.x.nxv8f16(<vscale x 8 x half> %op1, <vscale x 8 x half> %op2, i32 0) + // CHECK: ret <vscale x 8 x half> %[[INTRINSIC]] + return SVE_ACLE_FUNC(svtmad,_f16,,)(op1, op2, 0); +} + +svfloat16_t test_svtmad_f16_1(svfloat16_t op1, svfloat16_t op2) +{ + // CHECK-LABEL: test_svtmad_f16_1 + // CHECK: %[[INTRINSIC:.*]] = call <vscale x 8 x half> @llvm.aarch64.sve.ftmad.x.nxv8f16(<vscale x 8 x half> %op1, <vscale x 8 x half> %op2, i32 7) + // CHECK: ret <vscale x 8 x half> %[[INTRINSIC]] + return SVE_ACLE_FUNC(svtmad,_f16,,)(op1, op2, 7); +} + +svfloat32_t test_svtmad_f32(svfloat32_t op1, svfloat32_t op2) +{ + // CHECK-LABEL: test_svtmad_f32 + // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x float> @llvm.aarch64.sve.ftmad.x.nxv4f32(<vscale x 4 x float> %op1, <vscale x 4 x float> %op2, i32 0) + // CHECK: ret <vscale x 4 x float> %[[INTRINSIC]] + return SVE_ACLE_FUNC(svtmad,_f32,,)(op1, op2, 0); +} + +svfloat64_t test_svtmad_f64(svfloat64_t op1, svfloat64_t op2) +{ + // CHECK-LABEL: test_svtmad_f64 + // CHECK: %[[INTRINSIC:.*]] = call <vscale x 2 x double> @llvm.aarch64.sve.ftmad.x.nxv2f64(<vscale x 2 x double> %op1, <vscale x 2 x double> %op2, i32 0) + // CHECK: ret <vscale x 2 x double> %[[INTRINSIC]] + return SVE_ACLE_FUNC(svtmad,_f64,,)(op1, op2, 0); +} Index: clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ext.c =================================================================== --- /dev/null +++ clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ext.c @@ -0,0 +1,131 @@ +// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -triple aarch64-none-linux-gnu -target-feature +sve -fallow-half-arguments-and-returns -S -O1 -Werror -Wall -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve -fallow-half-arguments-and-returns -S -O1 -Werror -Wall -emit-llvm -o - %s | FileCheck %s + +#include <arm_sve.h> + +#ifdef SVE_OVERLOADED_FORMS +// A simple used,unused... macro, long enough to represent any SVE builtin. +#define SVE_ACLE_FUNC(A1,A2_UNUSED,A3,A4_UNUSED) A1##A3 +#else +#define SVE_ACLE_FUNC(A1,A2,A3,A4) A1##A2##A3##A4 +#endif + +svint8_t test_svext_s8(svint8_t op1, svint8_t op2) +{ + // CHECK-LABEL: test_svext_s8 + // CHECK: %[[INTRINSIC:.*]] = call <vscale x 16 x i8> @llvm.aarch64.sve.ext.nxv16i8(<vscale x 16 x i8> %op1, <vscale x 16 x i8> %op2, i32 0) + // CHECK: ret <vscale x 16 x i8> %[[INTRINSIC]] + return SVE_ACLE_FUNC(svext,_s8,,)(op1, op2, 0); +} + +svint8_t test_svext_s8_1(svint8_t op1, svint8_t op2) +{ + // CHECK-LABEL: test_svext_s8_1 + // CHECK: %[[INTRINSIC:.*]] = call <vscale x 16 x i8> @llvm.aarch64.sve.ext.nxv16i8(<vscale x 16 x i8> %op1, <vscale x 16 x i8> %op2, i32 255) + // CHECK: ret <vscale x 16 x i8> %[[INTRINSIC]] + return SVE_ACLE_FUNC(svext,_s8,,)(op1, op2, 255); +} + +svint16_t test_svext_s16(svint16_t op1, svint16_t op2) +{ + // CHECK-LABEL: test_svext_s16 + // CHECK: %[[INTRINSIC:.*]] = call <vscale x 8 x i16> @llvm.aarch64.sve.ext.nxv8i16(<vscale x 8 x i16> %op1, <vscale x 8 x i16> %op2, i32 0) + // CHECK: ret <vscale x 8 x i16> %[[INTRINSIC]] + return SVE_ACLE_FUNC(svext,_s16,,)(op1, op2, 0); +} + +svint16_t test_svext_s16_1(svint16_t op1, svint16_t op2) +{ + // CHECK-LABEL: test_svext_s16_1 + // CHECK: %[[INTRINSIC:.*]] = call <vscale x 8 x i16> @llvm.aarch64.sve.ext.nxv8i16(<vscale x 8 x i16> %op1, <vscale x 8 x i16> %op2, i32 127) + // CHECK: ret <vscale x 8 x i16> %[[INTRINSIC]] + return SVE_ACLE_FUNC(svext,_s16,,)(op1, op2, 127); +} + +svint32_t test_svext_s32(svint32_t op1, svint32_t op2) +{ + // CHECK-LABEL: test_svext_s32 + // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x i32> @llvm.aarch64.sve.ext.nxv4i32(<vscale x 4 x i32> %op1, <vscale x 4 x i32> %op2, i32 0) + // CHECK: ret <vscale x 4 x i32> %[[INTRINSIC]] + return SVE_ACLE_FUNC(svext,_s32,,)(op1, op2, 0); +} + +svint32_t test_svext_s32_1(svint32_t op1, svint32_t op2) +{ + // CHECK-LABEL: test_svext_s32_1 + // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x i32> @llvm.aarch64.sve.ext.nxv4i32(<vscale x 4 x i32> %op1, <vscale x 4 x i32> %op2, i32 63) + // CHECK: ret <vscale x 4 x i32> %[[INTRINSIC]] + return SVE_ACLE_FUNC(svext,_s32,,)(op1, op2, 63); +} + +svint64_t test_svext_s64(svint64_t op1, svint64_t op2) +{ + // CHECK-LABEL: test_svext_s64 + // CHECK: %[[INTRINSIC:.*]] = call <vscale x 2 x i64> @llvm.aarch64.sve.ext.nxv2i64(<vscale x 2 x i64> %op1, <vscale x 2 x i64> %op2, i32 0) + // CHECK: ret <vscale x 2 x i64> %[[INTRINSIC]] + return SVE_ACLE_FUNC(svext,_s64,,)(op1, op2, 0); +} + +svint64_t test_svext_s64_1(svint64_t op1, svint64_t op2) +{ + // CHECK-LABEL: test_svext_s64_1 + // CHECK: %[[INTRINSIC:.*]] = call <vscale x 2 x i64> @llvm.aarch64.sve.ext.nxv2i64(<vscale x 2 x i64> %op1, <vscale x 2 x i64> %op2, i32 31) + // CHECK: ret <vscale x 2 x i64> %[[INTRINSIC]] + return SVE_ACLE_FUNC(svext,_s64,,)(op1, op2, 31); +} + +svuint8_t test_svext_u8(svuint8_t op1, svuint8_t op2) +{ + // CHECK-LABEL: test_svext_u8 + // CHECK: %[[INTRINSIC:.*]] = call <vscale x 16 x i8> @llvm.aarch64.sve.ext.nxv16i8(<vscale x 16 x i8> %op1, <vscale x 16 x i8> %op2, i32 255) + // CHECK: ret <vscale x 16 x i8> %[[INTRINSIC]] + return SVE_ACLE_FUNC(svext,_u8,,)(op1, op2, 255); +} + +svuint16_t test_svext_u16(svuint16_t op1, svuint16_t op2) +{ + // CHECK-LABEL: test_svext_u16 + // CHECK: %[[INTRINSIC:.*]] = call <vscale x 8 x i16> @llvm.aarch64.sve.ext.nxv8i16(<vscale x 8 x i16> %op1, <vscale x 8 x i16> %op2, i32 127) + // CHECK: ret <vscale x 8 x i16> %[[INTRINSIC]] + return SVE_ACLE_FUNC(svext,_u16,,)(op1, op2, 127); +} + +svuint32_t test_svext_u32(svuint32_t op1, svuint32_t op2) +{ + // CHECK-LABEL: test_svext_u32 + // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x i32> @llvm.aarch64.sve.ext.nxv4i32(<vscale x 4 x i32> %op1, <vscale x 4 x i32> %op2, i32 63) + // CHECK: ret <vscale x 4 x i32> %[[INTRINSIC]] + return SVE_ACLE_FUNC(svext,_u32,,)(op1, op2, 63); +} + +svuint64_t test_svext_u64(svuint64_t op1, svuint64_t op2) +{ + // CHECK-LABEL: test_svext_u64 + // CHECK: %[[INTRINSIC:.*]] = call <vscale x 2 x i64> @llvm.aarch64.sve.ext.nxv2i64(<vscale x 2 x i64> %op1, <vscale x 2 x i64> %op2, i32 31) + // CHECK: ret <vscale x 2 x i64> %[[INTRINSIC]] + return SVE_ACLE_FUNC(svext,_u64,,)(op1, op2, 31); +} + +svfloat16_t test_svext_f16(svfloat16_t op1, svfloat16_t op2) +{ + // CHECK-LABEL: test_svext_f16 + // CHECK: %[[INTRINSIC:.*]] = call <vscale x 8 x half> @llvm.aarch64.sve.ext.nxv8f16(<vscale x 8 x half> %op1, <vscale x 8 x half> %op2, i32 127) + // CHECK: ret <vscale x 8 x half> %[[INTRINSIC]] + return SVE_ACLE_FUNC(svext,_f16,,)(op1, op2, 127); +} + +svfloat32_t test_svext_f32(svfloat32_t op1, svfloat32_t op2) +{ + // CHECK-LABEL: test_svext_f32 + // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x float> @llvm.aarch64.sve.ext.nxv4f32(<vscale x 4 x float> %op1, <vscale x 4 x float> %op2, i32 63) + // CHECK: ret <vscale x 4 x float> %[[INTRINSIC]] + return SVE_ACLE_FUNC(svext,_f32,,)(op1, op2, 63); +} + +svfloat64_t test_svext_f64(svfloat64_t op1, svfloat64_t op2) +{ + // CHECK-LABEL: test_svext_f64 + // CHECK: %[[INTRINSIC:.*]] = call <vscale x 2 x double> @llvm.aarch64.sve.ext.nxv2f64(<vscale x 2 x double> %op1, <vscale x 2 x double> %op2, i32 31) + // CHECK: ret <vscale x 2 x double> %[[INTRINSIC]] + return SVE_ACLE_FUNC(svext,_f64,,)(op1, op2, 31); +} Index: clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_asrd.c =================================================================== --- /dev/null +++ clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_asrd.c @@ -0,0 +1,81 @@ +// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -triple aarch64-none-linux-gnu -target-feature +sve -fallow-half-arguments-and-returns -S -O1 -Werror -Wall -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve -fallow-half-arguments-and-returns -S -O1 -Werror -Wall -emit-llvm -o - %s | FileCheck %s + +#include <arm_sve.h> + +#ifdef SVE_OVERLOADED_FORMS +// A simple used,unused... macro, long enough to represent any SVE builtin. +#define SVE_ACLE_FUNC(A1,A2_UNUSED,A3,A4_UNUSED) A1##A3 +#else +#define SVE_ACLE_FUNC(A1,A2,A3,A4) A1##A2##A3##A4 +#endif + +svint8_t test_svasrd_n_s8_m(svbool_t pg, svint8_t op1) +{ + // CHECK-LABEL: test_svasrd_n_s8_m + // CHECK: %[[INTRINSIC:.*]] = call <vscale x 16 x i8> @llvm.aarch64.sve.asrd.nxv16i8(<vscale x 16 x i1> %pg, <vscale x 16 x i8> %op1, i32 1) + // CHECK: ret <vscale x 16 x i8> %[[INTRINSIC]] + return SVE_ACLE_FUNC(svasrd,_n_s8,_m,)(pg, op1, 1); +} + +svint16_t test_svasrd_n_s16_m(svbool_t pg, svint16_t op1) +{ + // CHECK-LABEL: test_svasrd_n_s16_m + // CHECK: %[[P0:.*]] = call <vscale x 8 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv8i1(<vscale x 16 x i1> %pg) + // CHECK: %[[INTRINSIC:.*]] = call <vscale x 8 x i16> @llvm.aarch64.sve.asrd.nxv8i16(<vscale x 8 x i1> %[[P0]], <vscale x 8 x i16> %op1, i32 1) + // CHECK: ret <vscale x 8 x i16> %[[INTRINSIC]] + return SVE_ACLE_FUNC(svasrd,_n_s16,_m,)(pg, op1, 1); +} + +svint32_t test_svasrd_n_s32_m(svbool_t pg, svint32_t op1) +{ + // CHECK-LABEL: test_svasrd_n_s32_m + // CHECK: %[[P0:.*]] = call <vscale x 4 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv4i1(<vscale x 16 x i1> %pg) + // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x i32> @llvm.aarch64.sve.asrd.nxv4i32(<vscale x 4 x i1> %[[P0]], <vscale x 4 x i32> %op1, i32 1) + // CHECK: ret <vscale x 4 x i32> %[[INTRINSIC]] + return SVE_ACLE_FUNC(svasrd,_n_s32,_m,)(pg, op1, 1); +} + +svint64_t test_svasrd_n_s64_m(svbool_t pg, svint64_t op1) +{ + // CHECK-LABEL: test_svasrd_n_s64_m + // CHECK: %[[P0:.*]] = call <vscale x 2 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv2i1(<vscale x 16 x i1> %pg) + // CHECK: %[[INTRINSIC:.*]] = call <vscale x 2 x i64> @llvm.aarch64.sve.asrd.nxv2i64(<vscale x 2 x i1> %[[P0]], <vscale x 2 x i64> %op1, i32 1) + // CHECK: ret <vscale x 2 x i64> %[[INTRINSIC]] + return SVE_ACLE_FUNC(svasrd,_n_s64,_m,)(pg, op1, 1); +} + +svint8_t test_svasrd_n_s8_max_m(svbool_t pg, svint8_t op1) +{ + // CHECK-LABEL: test_svasrd_n_s8_max_m + // CHECK: %[[INTRINSIC:.*]] = call <vscale x 16 x i8> @llvm.aarch64.sve.asrd.nxv16i8(<vscale x 16 x i1> %pg, <vscale x 16 x i8> %op1, i32 8) + // CHECK: ret <vscale x 16 x i8> %[[INTRINSIC]] + return SVE_ACLE_FUNC(svasrd,_n_s8,_m,)(pg, op1, 8); +} + +svint16_t test_svasrd_n_s16_max_m(svbool_t pg, svint16_t op1) +{ + // CHECK-LABEL: test_svasrd_n_s16_max_m + // CHECK: %[[P0:.*]] = call <vscale x 8 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv8i1(<vscale x 16 x i1> %pg) + // CHECK: %[[INTRINSIC:.*]] = call <vscale x 8 x i16> @llvm.aarch64.sve.asrd.nxv8i16(<vscale x 8 x i1> %[[P0]], <vscale x 8 x i16> %op1, i32 16) + // CHECK: ret <vscale x 8 x i16> %[[INTRINSIC]] + return SVE_ACLE_FUNC(svasrd,_n_s16,_m,)(pg, op1, 16); +} + +svint32_t test_svasrd_n_s32_max_m(svbool_t pg, svint32_t op1) +{ + // CHECK-LABEL: test_svasrd_n_s32_max_m + // CHECK: %[[P0:.*]] = call <vscale x 4 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv4i1(<vscale x 16 x i1> %pg) + // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x i32> @llvm.aarch64.sve.asrd.nxv4i32(<vscale x 4 x i1> %[[P0]], <vscale x 4 x i32> %op1, i32 32) + // CHECK: ret <vscale x 4 x i32> %[[INTRINSIC]] + return SVE_ACLE_FUNC(svasrd,_n_s32,_m,)(pg, op1, 32); +} + +svint64_t test_svasrd_n_s64_max_m(svbool_t pg, svint64_t op1) +{ + // CHECK-LABEL: test_svasrd_n_s64_max_m + // CHECK: %[[P0:.*]] = call <vscale x 2 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv2i1(<vscale x 16 x i1> %pg) + // CHECK: %[[INTRINSIC:.*]] = call <vscale x 2 x i64> @llvm.aarch64.sve.asrd.nxv2i64(<vscale x 2 x i1> %[[P0]], <vscale x 2 x i64> %op1, i32 64) + // CHECK: ret <vscale x 2 x i64> %[[INTRINSIC]] + return SVE_ACLE_FUNC(svasrd,_n_s64,_m,)(pg, op1, 64); +} Index: clang/lib/Sema/SemaChecking.cpp =================================================================== --- clang/lib/Sema/SemaChecking.cpp +++ clang/lib/Sema/SemaChecking.cpp @@ -2025,6 +2025,29 @@ if (SemaBuiltinConstantArgRange(TheCall, ArgNum, 1, 16)) HasError = true; break; + case SVETypeFlags::ImmCheck0_7: + if (SemaBuiltinConstantArgRange(TheCall, ArgNum, 0, 7)) + HasError = true; + break; + case SVETypeFlags::ImmCheckExtract: + if (SemaBuiltinConstantArgRange(TheCall, ArgNum, 0, + (2048 / ElementSizeInBits) - 1)) + HasError = true; + break; + case SVETypeFlags::ImmCheckShiftRight: + if (SemaBuiltinConstantArgRange(TheCall, ArgNum, 1, ElementSizeInBits)) + HasError = true; + break; + case SVETypeFlags::ImmCheckShiftRightNarrow: + if (SemaBuiltinConstantArgRange(TheCall, ArgNum, 1, + ElementSizeInBits / 2)) + HasError = true; + break; + case SVETypeFlags::ImmCheckShiftLeft: + if (SemaBuiltinConstantArgRange(TheCall, ArgNum, 0, + ElementSizeInBits - 1)) + HasError = true; + break; } } Index: clang/lib/CodeGen/CGBuiltin.cpp =================================================================== --- clang/lib/CodeGen/CGBuiltin.cpp +++ clang/lib/CodeGen/CGBuiltin.cpp @@ -7630,6 +7630,15 @@ else if (Builtin->LLVMIntrinsic != 0) { llvm::Type* OverloadedTy = getSVEType(TypeFlags); + // Predicates must match the main datatype. + for (unsigned i = 0, e = Ops.size(); i != e; ++i) { + if (auto PredTy = dyn_cast<llvm::VectorType>(Ops[i]->getType())) + if (PredTy->getScalarType()->isIntegerTy(1)) { + auto NewPredTy = cast<llvm::VectorType>(OverloadedTy); + Ops[i] = EmitSVEPredicateCast(Ops[i], NewPredTy); + } + } + Function *F = CGM.getIntrinsic(Builtin->LLVMIntrinsic, OverloadedTy); Value *Call = Builder.CreateCall(F, Ops); return Call; Index: clang/include/clang/Basic/arm_sve.td =================================================================== --- clang/include/clang/Basic/arm_sve.td +++ clang/include/clang/Basic/arm_sve.td @@ -58,9 +58,11 @@ // ------------------- // prototype: return (arg, arg, ...) // +// u: vector of unsigned integers // d: default // c: const pointer type // P: predicate type +// h: 1/2 width elements, 2x element count // // i: constant uint64_t // @@ -157,14 +159,18 @@ } def ImmCheck0_31 : ImmCheckType<0>; // 0..31 (used for e.g. predicate patterns) def ImmCheck1_16 : ImmCheckType<1>; // 1..16 +def ImmCheckExtract : ImmCheckType<2>; // 0..(2048/sizeinbits(elt) - 1) +def ImmCheckShiftRight : ImmCheckType<3>; // 1..sizeinbits(elt) +def ImmCheckShiftRightNarrow : ImmCheckType<4>; // 1..sizeinbits(elt)/2 +def ImmCheckShiftLeft : ImmCheckType<5>; // 0..(sizeinbits(elt) - 1) +def ImmCheck0_7 : ImmCheckType<6>; // 0..7 class ImmCheck<int arg, ImmCheckType kind, int eltSizeArg = -1> { int Arg = arg; - int EltSizeArg = eltSizeArg; + int EltSizeArg = eltSizeArg; ImmCheckType Kind = kind; } -// Every intrinsic subclasses Inst. class Inst<string n, string p, string t, MergeType mt, string i, list<FlagType> ft, list<ImmCheck> ch, MemEltType met> { string Name = n; @@ -283,6 +289,30 @@ def SVSTNT1_VNUM : MInst<"svstnt1_vnum[_{d}]", "vPpld", "csilUcUsUiUlhfd", [IsStore], MemEltTyDefault, "aarch64_sve_stnt1">; //////////////////////////////////////////////////////////////////////////////// +// Permutations and selection +def SVEXT : SInst<"svext[_{d}]", "dddi", "csilUcUsUiUlhfd", MergeNone, "aarch64_sve_ext", [], [ImmCheck<2, ImmCheckExtract, 1>]>; + +//////////////////////////////////////////////////////////////////////////////// +// Shifts +def SVASRD_M : SInst<"svasrd[_n_{d}]", "dPdi", "csil", MergeOp1, "aarch64_sve_asrd", [], [ImmCheck<2, ImmCheckShiftRight, 1>]>; + +//////////////////////////////////////////////////////////////////////////////// +// SVE2 - Narrowing DSP operations +let ArchGuard = "defined(__ARM_FEATURE_SVE2)" in { +def SVSHRNB : SInst<"svshrnb[_n_{d}]", "hdi", "silUsUiUl", MergeNone, "aarch64_sve_shrnb", [], [ImmCheck<1, ImmCheckShiftRightNarrow, 0>]>; +} + +//////////////////////////////////////////////////////////////////////////////// +// SVE2 - Uniform DSP operations +let ArchGuard = "defined(__ARM_FEATURE_SVE2)" in { +def SVQSHLU_M : SInst<"svqshlu[_n_{d}]", "uPdi", "csil", MergeOp1, "aarch64_sve_sqshlu", [], [ImmCheck<2, ImmCheckShiftLeft, 1>]>; +} + +//////////////////////////////////////////////////////////////////////////////// +// Floating-point arithmetic +def SVTMAD : SInst<"svtmad[_{d}]", "dddi", "hfd", MergeNone, "aarch64_sve_ftmad_x", [], [ImmCheck<2, ImmCheck0_7>]>; + +//////////////////////////////////////////////////////////////////////////////// // Saturating scalar arithmetic def SVQDECH_S : SInst<"svqdech_pat[_{d}]", "ddIi", "s", MergeNone, "aarch64_sve_sqdech", [], [ImmCheck<2, ImmCheck1_16>]>; def SVQDECH_U : SInst<"svqdech_pat[_{d}]", "ddIi", "Us", MergeNone, "aarch64_sve_uqdech", [], [ImmCheck<2, ImmCheck1_16>]>;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits