[clang] f225898 - [Clang][AArch64][SME] Add intrinsics for ZA array load/store (LDR/STR)
Bryan Chan via cfe-commits
cfe-commits at lists.llvm.org
Thu Jul 20 02:57:44 PDT 2023
Author: Bryan Chan
Date: 2023-07-20T06:06:35-04:00
New Revision: f225898a7c6105aa34e64f9c7dbfed7ce3443331
URL: https://github.com/llvm/llvm-project/commit/f225898a7c6105aa34e64f9c7dbfed7ce3443331
DIFF: https://github.com/llvm/llvm-project/commit/f225898a7c6105aa34e64f9c7dbfed7ce3443331.diff
LOG: [Clang][AArch64][SME] Add intrinsics for ZA array load/store (LDR/STR)
This patch adds support for the following SME ACLE intrinsics (as defined
in https://arm-software.github.io/acle/main/acle.html):
- svldr_vnum_za
- svstr_vnum_za
Co-authored-by: Sagar Kulkarni <sagar.kulkarni1 at huawei.com>
Reviewed By: sdesmalen
Differential Revision: https://reviews.llvm.org/D134678
Added:
clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_ldr.c
clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_str.c
Modified:
clang/include/clang/Basic/arm_sme.td
clang/lib/CodeGen/CGBuiltin.cpp
clang/lib/CodeGen/CodeGenFunction.h
clang/test/Sema/aarch64-sme-intrinsics/acle_sme_imm.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/Basic/arm_sme.td b/clang/include/clang/Basic/arm_sme.td
index 7c1daf46adfb13..945f212963d6c9 100644
--- a/clang/include/clang/Basic/arm_sme.td
+++ b/clang/include/clang/Basic/arm_sme.td
@@ -44,6 +44,11 @@ defm SVLD1_ZA32 : ZALoad<"za32", "i", "aarch64_sme_ld1w", [ImmCheck<0, ImmCheck0
defm SVLD1_ZA64 : ZALoad<"za64", "l", "aarch64_sme_ld1d", [ImmCheck<0, ImmCheck0_7>, ImmCheck<2, ImmCheck0_1>]>;
defm SVLD1_ZA128 : ZALoad<"za128", "q", "aarch64_sme_ld1q", [ImmCheck<0, ImmCheck0_15>, ImmCheck<2, ImmCheck0_0>]>;
+def SVLDR_VNUM_ZA : MInst<"svldr_vnum_za", "vmiQ", "",
+ [IsOverloadNone, IsStreamingCompatible, IsSharedZA],
+ MemEltTyDefault, "aarch64_sme_ldr",
+ [ImmCheck<1, ImmCheck0_15>]>;
+
////////////////////////////////////////////////////////////////////////////////
// Stores
@@ -73,6 +78,11 @@ defm SVST1_ZA32 : ZAStore<"za32", "i", "aarch64_sme_st1w", [ImmCheck<0, ImmCheck
defm SVST1_ZA64 : ZAStore<"za64", "l", "aarch64_sme_st1d", [ImmCheck<0, ImmCheck0_7>, ImmCheck<2, ImmCheck0_1>]>;
defm SVST1_ZA128 : ZAStore<"za128", "q", "aarch64_sme_st1q", [ImmCheck<0, ImmCheck0_15>, ImmCheck<2, ImmCheck0_0>]>;
+def SVSTR_VNUM_ZA : MInst<"svstr_vnum_za", "vmi%", "",
+ [IsOverloadNone, IsStreamingCompatible, IsSharedZA, IsPreservesZA],
+ MemEltTyDefault, "aarch64_sme_str",
+ [ImmCheck<1, ImmCheck0_15>]>;
+
////////////////////////////////////////////////////////////////////////////////
// Read horizontal/vertical ZA slices
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 599539e1fa4343..416c220351267a 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -9505,6 +9505,22 @@ Value *CodeGenFunction::EmitSMEZero(SVETypeFlags TypeFlags,
return Builder.CreateCall(F, Ops);
}
+Value *CodeGenFunction::EmitSMELdrStr(SVETypeFlags TypeFlags,
+ SmallVectorImpl<Value *> &Ops,
+ unsigned IntID) {
+ Function *Vscale = CGM.getIntrinsic(Intrinsic::vscale, Int64Ty);
+ llvm::Value *VscaleCall = Builder.CreateCall(Vscale, {}, "vscale");
+ llvm::Value *MulVL = Builder.CreateMul(
+ VscaleCall,
+ Builder.getInt64(16 * cast<llvm::ConstantInt>(Ops[1])->getZExtValue()),
+ "mulvl");
+ Ops[2] = Builder.CreateGEP(Int8Ty, Ops[2], MulVL);
+ Ops[0] = EmitTileslice(Ops[1], Ops[0]);
+ Ops.erase(&Ops[1]);
+ 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) {
@@ -9968,6 +9984,9 @@ Value *CodeGenFunction::EmitAArch64SMEBuiltinExpr(unsigned BuiltinID,
else if (BuiltinID == SME::BI__builtin_sme_svzero_mask_za ||
BuiltinID == SME::BI__builtin_sme_svzero_za)
return EmitSMEZero(TypeFlags, Ops, Builtin->LLVMIntrinsic);
+ else if (BuiltinID == SME::BI__builtin_sme_svldr_vnum_za ||
+ BuiltinID == SME::BI__builtin_sme_svstr_vnum_za)
+ return EmitSMELdrStr(TypeFlags, Ops, Builtin->LLVMIntrinsic);
/// Should not happen
return nullptr;
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 8292163ab3365c..409f48a04906e2 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -4286,6 +4286,9 @@ class CodeGenFunction : public CodeGenTypeCache {
llvm::Value *EmitSMEZero(SVETypeFlags TypeFlags,
llvm::SmallVectorImpl<llvm::Value *> &Ops,
unsigned IntID);
+ llvm::Value *EmitSMELdrStr(SVETypeFlags TypeFlags,
+ llvm::SmallVectorImpl<llvm::Value *> &Ops,
+ unsigned IntID);
llvm::Value *EmitAArch64SMEBuiltinExpr(unsigned BuiltinID, const CallExpr *E);
llvm::Value *EmitAArch64BuiltinExpr(unsigned BuiltinID, const CallExpr *E,
diff --git a/clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_ldr.c b/clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_ldr.c
new file mode 100644
index 00000000000000..c96df003da6efc
--- /dev/null
+++ b/clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_ldr.c
@@ -0,0 +1,30 @@
+// 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 <arm_sme_draft_spec_subject_to_change.h>
+
+// CHECK-C-LABEL: @test_svldr_vnum_za(
+// CHECK-CXX-LABEL: @_Z18test_svldr_vnum_zajPKv(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: tail call void @llvm.aarch64.sme.ldr(i32 [[SLICE_BASE:%.*]], ptr [[PTR:%.*]])
+// CHECK-NEXT: ret void
+//
+void test_svldr_vnum_za(uint32_t slice_base, const void *ptr) {
+ svldr_vnum_za(slice_base, 0, ptr);
+}
+
+// CHECK-C-LABEL: @test_svldr_vnum_za_1(
+// CHECK-CXX-LABEL: @_Z20test_svldr_vnum_za_1jPKv(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[VSCALE:%.*]] = tail call i64 @llvm.vscale.i64()
+// CHECK-NEXT: [[MULVL:%.*]] = mul nuw nsw i64 [[VSCALE]], 240
+// CHECK-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[PTR:%.*]], i64 [[MULVL]]
+// CHECK-NEXT: [[TILESLICE:%.*]] = add i32 [[SLICE_BASE:%.*]], 15
+// CHECK-NEXT: tail call void @llvm.aarch64.sme.ldr(i32 [[TILESLICE]], ptr [[TMP0]])
+// CHECK-NEXT: ret void
+//
+void test_svldr_vnum_za_1(uint32_t slice_base, const void *ptr) {
+ svldr_vnum_za(slice_base, 15, ptr);
+}
diff --git a/clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_str.c b/clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_str.c
new file mode 100644
index 00000000000000..d4b1b9fa908acb
--- /dev/null
+++ b/clang/test/CodeGen/aarch64-sme-intrinsics/acle_sme_str.c
@@ -0,0 +1,30 @@
+// 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 <arm_sme_draft_spec_subject_to_change.h>
+
+// CHECK-C-LABEL: @test_svstr_vnum_za(
+// CHECK-CXX-LABEL: @_Z18test_svstr_vnum_zajPv(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: tail call void @llvm.aarch64.sme.str(i32 [[SLICE_BASE:%.*]], ptr [[PTR:%.*]])
+// CHECK-NEXT: ret void
+//
+void test_svstr_vnum_za(uint32_t slice_base, void *ptr) {
+ svstr_vnum_za(slice_base, 0, ptr);
+}
+
+// CHECK-C-LABEL: @test_svstr_vnum_za_1(
+// CHECK-CXX-LABEL: @_Z20test_svstr_vnum_za_1jPv(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[VSCALE:%.*]] = tail call i64 @llvm.vscale.i64()
+// CHECK-NEXT: [[MULVL:%.*]] = mul nuw nsw i64 [[VSCALE]], 240
+// CHECK-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[PTR:%.*]], i64 [[MULVL]]
+// CHECK-NEXT: [[TILESLICE:%.*]] = add i32 [[SLICE_BASE:%.*]], 15
+// CHECK-NEXT: tail call void @llvm.aarch64.sme.str(i32 [[TILESLICE]], ptr [[TMP0]])
+// CHECK-NEXT: ret void
+//
+void test_svstr_vnum_za_1(uint32_t slice_base, void *ptr) {
+ svstr_vnum_za(slice_base, 15, ptr);
+}
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 5c1b8fd3e3905a..ec2e39ae670e27 100644
--- a/clang/test/Sema/aarch64-sme-intrinsics/acle_sme_imm.cpp
+++ b/clang/test/Sema/aarch64-sme-intrinsics/acle_sme_imm.cpp
@@ -174,6 +174,11 @@ void test_range_0_15(svbool_t pg, void *ptr) {
// expected-error at +1 {{argument value 16 is outside the valid range [0, 15]}}
SVE_ACLE_FUNC(svst1_ver_vnum_za8,,,)(0, -1, 16, pg, ptr, 1);
+ // expected-error at +1 {{argument value 16 is outside the valid range [0, 15]}}
+ SVE_ACLE_FUNC(svldr_vnum_za,,,)(-1, 16, ptr);
+ // expected-error at +1 {{argument value 18446744073709551615 is outside the valid range [0, 15]}}
+ SVE_ACLE_FUNC(svstr_vnum_za,,,)(-1, -1, ptr);
+
// expected-error at +1 {{argument value 18446744073709551615 is outside the valid range [0, 15]}}
SVE_ACLE_FUNC(svread_hor_za128, _s8, _m,)(svundef_s8(), pg, -1, -1, 0);
// expected-error at +1 {{argument value 16 is outside the valid range [0, 15]}}
@@ -209,6 +214,9 @@ void test_constant(uint64_t u64, svbool_t pg, void *ptr) {
SVE_ACLE_FUNC(svst1_hor_vnum_za32,,,)(u64, u64, 0, pg, ptr, u64); // expected-error {{argument to 'svst1_hor_vnum_za32' must be a constant integer}}
SVE_ACLE_FUNC(svst1_ver_vnum_za64,,,)(0, u64, u64, pg, ptr, u64); // expected-error {{argument to 'svst1_ver_vnum_za64' must be a constant integer}}
+ SVE_ACLE_FUNC(svldr_vnum_za,,,)(u64, u64, ptr); // expected-error {{argument to 'svldr_vnum_za' must be a constant integer}}
+ SVE_ACLE_FUNC(svstr_vnum_za,,,)(u64, u64, ptr); // expected-error {{argument to 'svstr_vnum_za' must be a constant integer}}
+
SVE_ACLE_FUNC(svread_hor_za8, _s8, _m,)(svundef_s8(), pg, 0, u64, u64); // expected-error-re {{argument to 'svread_hor_za8{{.*}}_m' must be a constant integer}}
SVE_ACLE_FUNC(svread_ver_za16, _s16, _m,)(svundef_s16(), pg, u64, u64, 0); // expected-error-re {{argument to 'svread_ver_za16{{.*}}_m' must be a constant integer}}
SVE_ACLE_FUNC(svwrite_hor_za32, _s32, _m,)(0, u64, u64, pg, svundef_s32()); // expected-error-re {{argument to 'svwrite_hor_za32{{.*}}_m' must be a constant integer}}
More information about the cfe-commits
mailing list