diff --git a/clang/include/clang/Basic/arm_sme.td b/clang/include/clang/Basic/arm_sme.td index 4f82615bfb9d9..7c1daf46adfb1 100644 --- a/clang/include/clang/Basic/arm_sme.td +++ b/clang/include/clang/Basic/arm_sme.td @@ -114,3 +114,14 @@ defm SVWRITE_ZA16 : ZAWrite<"za16", "sUshb", "aarch64_sme_write", [ImmCheck<0, I defm SVWRITE_ZA32 : ZAWrite<"za32", "iUif", "aarch64_sme_write", [ImmCheck<0, ImmCheck0_3>, ImmCheck<2, ImmCheck0_3>]>; defm SVWRITE_ZA64 : ZAWrite<"za64", "lUld", "aarch64_sme_write", [ImmCheck<0, ImmCheck0_7>, ImmCheck<2, ImmCheck0_1>]>; defm SVWRITE_ZA128 : ZAWrite<"za128", "csilUcUsUiUlhbfd", "aarch64_sme_writeq", [ImmCheck<0, ImmCheck0_15>, ImmCheck<2, ImmCheck0_0>]>; + +//////////////////////////////////////////////////////////////////////////////// +// SME - Zero + +let TargetGuard = "sme" in { + def SVZERO_MASK_ZA : SInst<"svzero_mask_za", "vi", "", MergeNone, "aarch64_sme_zero", + [IsOverloadNone, IsStreamingCompatible, IsSharedZA], + [ImmCheck<0, ImmCheck0_255>]>; + def SVZERO_ZA : SInst<"svzero_za", "v", "", MergeNone, "aarch64_sme_zero", + [IsOverloadNone, IsStreamingCompatible, IsSharedZA]>; +} diff --git a/clang/include/clang/Basic/arm_sve_sme_incl.td b/clang/include/clang/Basic/arm_sve_sme_incl.td index e664b8b3e3f63..74c9b9266771b 100644 --- a/clang/include/clang/Basic/arm_sve_sme_incl.td +++ b/clang/include/clang/Basic/arm_sve_sme_incl.td @@ -245,6 +245,7 @@ def ImmCheck0_2 : ImmCheckType<14>; // 0..2 def ImmCheck0_3 : ImmCheckType<15>; // 0..3 def ImmCheck0_0 : ImmCheckType<16>; // 0..0 def ImmCheck0_15 : ImmCheckType<17>; // 0..15 +def ImmCheck0_255 : ImmCheckType<18>; // 0..255 class ImmCheck { int Arg = arg; diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 9d9ad162c6f5d..599539e1fa434 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -9495,6 +9495,16 @@ Value *CodeGenFunction::EmitSMEReadWrite(SVETypeFlags TypeFlags, return Builder.CreateCall(F, Ops); } +Value *CodeGenFunction::EmitSMEZero(SVETypeFlags TypeFlags, + SmallVectorImpl &Ops, + unsigned IntID) { + // svzero_za() intrinsic zeros the entire za tile and has no paramters. + if (Ops.size() == 0) + Ops.push_back(llvm::ConstantInt::get(Int32Ty, 255)); + Function *F = CGM.getIntrinsic(IntID, {}); + return Builder.CreateCall(F, Ops); +} + // Limit the usage of scalable llvm IR generated by the ACLE by using the // sve dup.x intrinsic instead of IRBuilder::CreateVectorSplat. Value *CodeGenFunction::EmitSVEDupX(Value *Scalar, llvm::Type *Ty) { @@ -9955,6 +9965,9 @@ Value *CodeGenFunction::EmitAArch64SMEBuiltinExpr(unsigned BuiltinID, return EmitSMELd1St1(TypeFlags, Ops, Builtin->LLVMIntrinsic); else if (TypeFlags.isReadZA() || TypeFlags.isWriteZA()) return EmitSMEReadWrite(TypeFlags, Ops, Builtin->LLVMIntrinsic); + else if (BuiltinID == SME::BI__builtin_sme_svzero_mask_za || + BuiltinID == SME::BI__builtin_sme_svzero_za) + return EmitSMEZero(TypeFlags, Ops, Builtin->LLVMIntrinsic); /// Should not happen return nullptr; diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 246050b341d67..8292163ab3365 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -4283,6 +4283,9 @@ class CodeGenFunction : public CodeGenTypeCache { llvm::Value *EmitSMEReadWrite(SVETypeFlags TypeFlags, llvm::SmallVectorImpl &Ops, unsigned IntID); + llvm::Value *EmitSMEZero(SVETypeFlags TypeFlags, + llvm::SmallVectorImpl &Ops, + unsigned IntID); llvm::Value *EmitAArch64SMEBuiltinExpr(unsigned BuiltinID, const CallExpr *E); llvm::Value *EmitAArch64BuiltinExpr(unsigned BuiltinID, const CallExpr *E, diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 077f560d4fe1b..17d9889da85e2 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -3003,6 +3003,10 @@ bool Sema::CheckSVEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { if (SemaBuiltinConstantArgRange(TheCall, ArgNum, 0, 15)) HasError = true; break; + case SVETypeFlags::ImmCheck0_255: + if (SemaBuiltinConstantArgRange(TheCall, ArgNum, 0, 255)) + HasError = true; + break; } } diff --git a/clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_zero.c b/clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_zero.c new file mode 100644 index 0000000000000..3ff9f6346c492 --- /dev/null +++ b/clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_zero.c @@ -0,0 +1,46 @@ +// REQUIRES: aarch64-registered-target +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme -target-feature +sve -S -O1 -Werror -emit-llvm -o - %s | FileCheck %s -check-prefixes=CHECK,CHECK-C +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme -target-feature +sve -S -O1 -Werror -emit-llvm -o - -x c++ %s | FileCheck %s -check-prefixes=CHECK,CHECK-CXX +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme -target-feature +sve -S -O1 -Werror -o /dev/null %s + +#include + +// CHECK-C-LABEL: @test_svzero_mask_za( +// CHECK-CXX-LABEL: @_Z19test_svzero_mask_zav( +// CHECK-NEXT: entry: +// CHECK-NEXT: tail call void @llvm.aarch64.sme.zero(i32 0) +// CHECK-NEXT: ret void +// +void test_svzero_mask_za() { + svzero_mask_za(0); +} + +// CHECK-C-LABEL: @test_svzero_mask_za_1( +// CHECK-CXX-LABEL: @_Z21test_svzero_mask_za_1v( +// CHECK-NEXT: entry: +// CHECK-NEXT: tail call void @llvm.aarch64.sme.zero(i32 176) +// CHECK-NEXT: ret void +// +void test_svzero_mask_za_1() { + svzero_mask_za(176); +} + +// CHECK-C-LABEL: @test_svzero_mask_za_2( +// CHECK-CXX-LABEL: @_Z21test_svzero_mask_za_2v( +// CHECK-NEXT: entry: +// CHECK-NEXT: tail call void @llvm.aarch64.sme.zero(i32 255) +// CHECK-NEXT: ret void +// +void test_svzero_mask_za_2() { + svzero_mask_za(255); +} + +// CHECK-C-LABEL: @test_svzero_za( +// CHECK-CXX-LABEL: @_Z14test_svzero_zav( +// CHECK-NEXT: entry: +// CHECK-NEXT: tail call void @llvm.aarch64.sme.zero(i32 255) +// CHECK-NEXT: ret void +// +void test_svzero_za() { + svzero_za(); +} diff --git a/clang/test/Sema/aarch64-sme-intrinsics/acle_sme_imm.cpp b/clang/test/Sema/aarch64-sme-intrinsics/acle_sme_imm.cpp index 2142dbe4c3a52..5c1b8fd3e3905 100644 --- a/clang/test/Sema/aarch64-sme-intrinsics/acle_sme_imm.cpp +++ b/clang/test/Sema/aarch64-sme-intrinsics/acle_sme_imm.cpp @@ -192,6 +192,13 @@ void test_range_0_15(svbool_t pg, void *ptr) { SVE_ACLE_FUNC(svwrite_ver_za8, _s8, _m,)(0, -1, 16, pg, svundef_s8()); } +void test_range_0_255(svbool_t pg, void *ptr) { + // expected-error@+1 {{argument value 256 is outside the valid range [0, 255]}} + SVE_ACLE_FUNC(svzero_mask_za,,,)(256); + // expected-error@+1 {{argument value 18446744073709551615 is outside the valid range [0, 255]}} + SVE_ACLE_FUNC(svzero_mask_za,,,)(-1); +} + void test_constant(uint64_t u64, svbool_t pg, void *ptr) { SVE_ACLE_FUNC(svld1_hor_za8,,,)(u64, u64, 0, pg, ptr); // expected-error {{argument to 'svld1_hor_za8' must be a constant integer}} SVE_ACLE_FUNC(svld1_ver_za16,,,)(0, u64, u64, pg, ptr); // expected-error {{argument to 'svld1_ver_za16' must be a constant integer}}