[clang] 823e2a6 - [SveEmitter] Add builtins for contiguous prefetches
Sander de Smalen via cfe-commits
cfe-commits at lists.llvm.org
Fri Apr 24 03:36:31 PDT 2020
Author: Sander de Smalen
Date: 2020-04-24T11:35:59+01:00
New Revision: 823e2a670a9da8e5cd8beed108355a168ca1a23b
URL: https://github.com/llvm/llvm-project/commit/823e2a670a9da8e5cd8beed108355a168ca1a23b
DIFF: https://github.com/llvm/llvm-project/commit/823e2a670a9da8e5cd8beed108355a168ca1a23b.diff
LOG: [SveEmitter] Add builtins for contiguous prefetches
This patch also adds the enum `sv_prfop` for the prefetch operation specifier
and checks to ensure the passed enum values are valid.
Reviewers: SjoerdMeijer, efriedma, ctetreau
Reviewed By: efriedma
Tags: #clang
Differential Revision: https://reviews.llvm.org/D78674
Added:
clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_prfb.c
clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_prfd.c
clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_prfh.c
clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_prfw.c
clang/test/CodeGen/aarch64-sve-intrinsics/negative/acle_sve_prfb.c
clang/test/CodeGen/aarch64-sve-intrinsics/negative/acle_sve_prfd.c
clang/test/CodeGen/aarch64-sve-intrinsics/negative/acle_sve_prfh.c
clang/test/CodeGen/aarch64-sve-intrinsics/negative/acle_sve_prfw.c
Modified:
clang/include/clang/Basic/TargetBuiltins.h
clang/include/clang/Basic/arm_sve.td
clang/lib/CodeGen/CGBuiltin.cpp
clang/lib/CodeGen/CodeGenFunction.h
clang/lib/Sema/SemaChecking.cpp
clang/utils/TableGen/SveEmitter.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/Basic/TargetBuiltins.h b/clang/include/clang/Basic/TargetBuiltins.h
index 5ef1a58fbb0f..1a9cb4cda1a4 100644
--- a/clang/include/clang/Basic/TargetBuiltins.h
+++ b/clang/include/clang/Basic/TargetBuiltins.h
@@ -238,6 +238,7 @@ namespace clang {
bool isOverloadDefault() const { return !(Flags & OverloadKindMask); }
bool isOverloadWhileRW() const { return Flags & IsOverloadWhileRW; }
bool isOverloadCvt() const { return Flags & IsOverloadCvt; }
+ bool isPrefetch() const { return Flags & IsPrefetch; }
uint64_t getBits() const { return Flags; }
bool isFlagSet(uint64_t Flag) const { return Flags & Flag; }
diff --git a/clang/include/clang/Basic/arm_sve.td b/clang/include/clang/Basic/arm_sve.td
index 4b69cdcb6468..5709dc8b8781 100644
--- a/clang/include/clang/Basic/arm_sve.td
+++ b/clang/include/clang/Basic/arm_sve.td
@@ -58,6 +58,7 @@
// -------------------
// prototype: return (arg, arg, ...)
//
+// v: void
// x: vector of signed integers
// u: vector of unsigned integers
// d: default
@@ -82,6 +83,7 @@
// M: svfloat32_t
// N: svfloat64_t
+// J: Prefetch type (sv_prfop)
// A: pointer to int8_t
// B: pointer to int16_t
// C: pointer to int32_t
@@ -176,6 +178,7 @@ def IsOverloadWhileRW : FlagType<0x00400000>; // Use {pred(default type)
def IsOverloadCvt : FlagType<0x00800000>; // Use {typeof(operand0), typeof(last operand)} as overloaded types.
def OverloadKindMask : FlagType<0x00E00000>; // When the masked values are all '0', the default type is used as overload type.
def IsByteIndexed : FlagType<0x01000000>;
+def IsPrefetch : FlagType<0x08000000>; // Contiguous prefetches.
// These must be kept in sync with the flags in include/clang/Basic/TargetBuiltins.h
class ImmCheckType<int val> {
@@ -193,6 +196,7 @@ def ImmCheckLaneIndexCompRotate : ImmCheckType<8>; // 0..(128/(2*sizeinbits(elt
def ImmCheckLaneIndexDot : ImmCheckType<9>; // 0..(128/(4*sizeinbits(elt)) - 1)
def ImmCheckComplexRot90_270 : ImmCheckType<10>; // [90,270]
def ImmCheckComplexRotAll90 : ImmCheckType<11>; // [0, 90, 180,270]
+def ImmCheck0_13 : ImmCheckType<12>; // 0..13
class ImmCheck<int arg, ImmCheckType kind, int eltSizeArg = -1> {
int Arg = arg;
@@ -543,6 +547,21 @@ def SVSTNT1 : MInst<"svstnt1[_{d}]", "vPpd", "csilUcUsUiUlhfd", [IsStore], MemEl
// Store one vector, with no truncation, non-temporal (scalar base, VL displacement)
def SVSTNT1_VNUM : MInst<"svstnt1_vnum[_{d}]", "vPpld", "csilUcUsUiUlhfd", [IsStore], MemEltTyDefault, "aarch64_sve_stnt1">;
+////////////////////////////////////////////////////////////////////////////////
+// Prefetches
+
+// Prefetch (Scalar base)
+def SVPRFB : MInst<"svprfb", "vPcJ", "c", [IsPrefetch], MemEltTyInt8, "aarch64_sve_prf">;
+def SVPRFH : MInst<"svprfh", "vPcJ", "s", [IsPrefetch], MemEltTyInt16, "aarch64_sve_prf">;
+def SVPRFW : MInst<"svprfw", "vPcJ", "i", [IsPrefetch], MemEltTyInt32, "aarch64_sve_prf">;
+def SVPRFD : MInst<"svprfd", "vPcJ", "l", [IsPrefetch], MemEltTyInt64, "aarch64_sve_prf">;
+
+// Prefetch (Scalar base, VL displacement)
+def SVPRFB_VNUM : MInst<"svprfb_vnum", "vPclJ", "c", [IsPrefetch], MemEltTyInt8, "aarch64_sve_prf">;
+def SVPRFH_VNUM : MInst<"svprfh_vnum", "vPclJ", "s", [IsPrefetch], MemEltTyInt16, "aarch64_sve_prf">;
+def SVPRFW_VNUM : MInst<"svprfw_vnum", "vPclJ", "i", [IsPrefetch], MemEltTyInt32, "aarch64_sve_prf">;
+def SVPRFD_VNUM : MInst<"svprfd_vnum", "vPclJ", "l", [IsPrefetch], MemEltTyInt64, "aarch64_sve_prf">;
+
////////////////////////////////////////////////////////////////////////////////
// Integer arithmetic
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index fb2bbd574306..468bc4eab59d 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -7568,6 +7568,13 @@ llvm::VectorType *CodeGenFunction::getSVEType(const SVETypeFlags &TypeFlags) {
}
}
+constexpr unsigned SVEBitsPerBlock = 128;
+
+static llvm::VectorType* getSVEVectorForElementType(llvm::Type *EltTy) {
+ unsigned NumElts = SVEBitsPerBlock / EltTy->getScalarSizeInBits();
+ return llvm::VectorType::get(EltTy, { NumElts, true });
+}
+
// Reinterpret the input predicate so that it can be used to correctly isolate
// the elements of the specified datatype.
Value *CodeGenFunction::EmitSVEPredicateCast(Value *Pred,
@@ -7707,6 +7714,30 @@ Value *CodeGenFunction::EmitSVEScatterStore(SVETypeFlags TypeFlags,
return Builder.CreateCall(F, Ops);
}
+Value *CodeGenFunction::EmitSVEPrefetchLoad(SVETypeFlags TypeFlags,
+ SmallVectorImpl<Value *> &Ops,
+ unsigned BuiltinID) {
+ auto *MemEltTy = SVEBuiltinMemEltTy(TypeFlags);
+ auto *VectorTy = getSVEVectorForElementType(MemEltTy);
+ auto *MemoryTy = llvm::VectorType::get(MemEltTy, VectorTy->getElementCount());
+
+ Value *Predicate = EmitSVEPredicateCast(Ops[0], MemoryTy);
+ Value *BasePtr = Ops[1];
+
+ // Implement the index operand if not omitted.
+ if (Ops.size() > 3) {
+ BasePtr = Builder.CreateBitCast(BasePtr, MemoryTy->getPointerTo());
+ BasePtr = Builder.CreateGEP(MemoryTy, BasePtr, Ops[2]);
+ }
+
+ // Prefetch intriniscs always expect an i8*
+ BasePtr = Builder.CreateBitCast(BasePtr, llvm::PointerType::getUnqual(Int8Ty));
+ Value *PrfOp = Ops.back();
+
+ Function *F = CGM.getIntrinsic(BuiltinID, Predicate->getType());
+ return Builder.CreateCall(F, {Predicate, BasePtr, PrfOp});
+}
+
Value *CodeGenFunction::EmitSVEMaskedLoad(const CallExpr *E,
llvm::Type *ReturnTy,
SmallVectorImpl<Value *> &Ops,
@@ -7759,13 +7790,6 @@ Value *CodeGenFunction::EmitSVEMaskedStore(const CallExpr *E,
return Builder.CreateCall(F, {Val, Predicate, BasePtr});
}
-constexpr unsigned SVEBitsPerBlock = 128;
-
-static llvm::VectorType* getSVEVectorForElementType(llvm::Type *EltTy) {
- unsigned NumElts = SVEBitsPerBlock / EltTy->getScalarSizeInBits();
- return llvm::VectorType::get(EltTy, { NumElts, true });
-}
-
// 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) {
@@ -7847,6 +7871,8 @@ Value *CodeGenFunction::EmitAArch64SVEBuiltinExpr(unsigned BuiltinID,
return EmitSVEGatherLoad(TypeFlags, Ops, Builtin->LLVMIntrinsic);
else if (TypeFlags.isScatterStore())
return EmitSVEScatterStore(TypeFlags, Ops, Builtin->LLVMIntrinsic);
+ else if (TypeFlags.isPrefetch())
+ return EmitSVEPrefetchLoad(TypeFlags, Ops, Builtin->LLVMIntrinsic);
else if (Builtin->LLVMIntrinsic != 0) {
if (TypeFlags.getMergeType() == SVETypeFlags::MergeZeroExp)
InsertExplicitZeroOperand(Builder, Ty, Ops);
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index a16ad1d178ce..53809b693266 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -3927,6 +3927,9 @@ class CodeGenFunction : public CodeGenTypeCache {
llvm::Value *EmitSVEMaskedStore(const CallExpr *,
SmallVectorImpl<llvm::Value *> &Ops,
unsigned BuiltinID);
+ llvm::Value *EmitSVEPrefetchLoad(SVETypeFlags TypeFlags,
+ SmallVectorImpl<llvm::Value *> &Ops,
+ unsigned BuiltinID);
llvm::Value *EmitAArch64SVEBuiltinExpr(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 126f155b6ad0..a88db3324ef3 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -2042,6 +2042,10 @@ bool Sema::CheckSVEBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
if (SemaBuiltinConstantArgRange(TheCall, ArgNum, 0, 31))
HasError = true;
break;
+ case SVETypeFlags::ImmCheck0_13:
+ if (SemaBuiltinConstantArgRange(TheCall, ArgNum, 0, 13))
+ HasError = true;
+ break;
case SVETypeFlags::ImmCheck1_16:
if (SemaBuiltinConstantArgRange(TheCall, ArgNum, 1, 16))
HasError = true;
diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_prfb.c b/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_prfb.c
new file mode 100644
index 000000000000..f29cb995230c
--- /dev/null
+++ b/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_prfb.c
@@ -0,0 +1,104 @@
+// 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
+
+void test_svprfb(svbool_t pg, const void *base)
+{
+ // CHECK-LABEL: test_svprfb
+ // CHECK: @llvm.aarch64.sve.prf.nxv16i1(<vscale x 16 x i1> %pg, i8* %base, i32 0)
+ return svprfb(pg, base, SV_PLDL1KEEP);
+}
+
+void test_svprfb_1(svbool_t pg, const void *base)
+{
+ // CHECK-LABEL: test_svprfb_1
+ // CHECK: @llvm.aarch64.sve.prf.nxv16i1(<vscale x 16 x i1> %pg, i8* %base, i32 1)
+ return svprfb(pg, base, SV_PLDL1STRM);
+}
+
+void test_svprfb_2(svbool_t pg, const void *base)
+{
+ // CHECK-LABEL: test_svprfb_2
+ // CHECK: @llvm.aarch64.sve.prf.nxv16i1(<vscale x 16 x i1> %pg, i8* %base, i32 2)
+ return svprfb(pg, base, SV_PLDL2KEEP);
+}
+
+void test_svprfb_3(svbool_t pg, const void *base)
+{
+ // CHECK-LABEL: test_svprfb_3
+ // CHECK: @llvm.aarch64.sve.prf.nxv16i1(<vscale x 16 x i1> %pg, i8* %base, i32 3)
+ return svprfb(pg, base, SV_PLDL2STRM);
+}
+
+void test_svprfb_4(svbool_t pg, const void *base)
+{
+ // CHECK-LABEL: test_svprfb_4
+ // CHECK: @llvm.aarch64.sve.prf.nxv16i1(<vscale x 16 x i1> %pg, i8* %base, i32 4)
+ return svprfb(pg, base, SV_PLDL3KEEP);
+}
+
+void test_svprfb_5(svbool_t pg, const void *base)
+{
+ // CHECK-LABEL: test_svprfb_5
+ // CHECK: @llvm.aarch64.sve.prf.nxv16i1(<vscale x 16 x i1> %pg, i8* %base, i32 5)
+ return svprfb(pg, base, SV_PLDL3STRM);
+}
+
+void test_svprfb_6(svbool_t pg, const void *base)
+{
+ // CHECK-LABEL: test_svprfb_6
+ // CHECK: @llvm.aarch64.sve.prf.nxv16i1(<vscale x 16 x i1> %pg, i8* %base, i32 8)
+ return svprfb(pg, base, SV_PSTL1KEEP);
+}
+
+void test_svprfb_7(svbool_t pg, const void *base)
+{
+ // CHECK-LABEL: test_svprfb_7
+ // CHECK: @llvm.aarch64.sve.prf.nxv16i1(<vscale x 16 x i1> %pg, i8* %base, i32 9)
+ return svprfb(pg, base, SV_PSTL1STRM);
+}
+
+void test_svprfb_8(svbool_t pg, const void *base)
+{
+ // CHECK-LABEL: test_svprfb_8
+ // CHECK: @llvm.aarch64.sve.prf.nxv16i1(<vscale x 16 x i1> %pg, i8* %base, i32 10)
+ return svprfb(pg, base, SV_PSTL2KEEP);
+}
+
+void test_svprfb_9(svbool_t pg, const void *base)
+{
+ // CHECK-LABEL: test_svprfb_9
+ // CHECK: @llvm.aarch64.sve.prf.nxv16i1(<vscale x 16 x i1> %pg, i8* %base, i32 11)
+ return svprfb(pg, base, SV_PSTL2STRM);
+}
+
+void test_svprfb_10(svbool_t pg, const void *base)
+{
+ // CHECK-LABEL: test_svprfb_10
+ // CHECK: @llvm.aarch64.sve.prf.nxv16i1(<vscale x 16 x i1> %pg, i8* %base, i32 12)
+ return svprfb(pg, base, SV_PSTL3KEEP);
+}
+
+void test_svprfb_11(svbool_t pg, const void *base)
+{
+ // CHECK-LABEL: test_svprfb_11
+ // CHECK: @llvm.aarch64.sve.prf.nxv16i1(<vscale x 16 x i1> %pg, i8* %base, i32 13)
+ return svprfb(pg, base, SV_PSTL3STRM);
+}
+
+void test_svprfb_vnum(svbool_t pg, const void *base, int64_t vnum)
+{
+ // CHECK-LABEL: test_svprfb_vnum
+ // CHECK: %[[BASE:.*]] = bitcast i8* %base to <vscale x 16 x i8>*
+ // CHECK: %[[GEP:.*]] = getelementptr <vscale x 16 x i8>, <vscale x 16 x i8>* %[[BASE]], i64 %vnum, i64 0
+ // CHECK: @llvm.aarch64.sve.prf.nxv16i1(<vscale x 16 x i1> %pg, i8* %[[GEP]], i32 0)
+ return svprfb_vnum(pg, base, vnum, SV_PLDL1KEEP);
+}
diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_prfd.c b/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_prfd.c
new file mode 100644
index 000000000000..59d3fbfb7e1b
--- /dev/null
+++ b/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_prfd.c
@@ -0,0 +1,118 @@
+// 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
+
+void test_svprfd(svbool_t pg, const void *base)
+{
+ // CHECK-LABEL: test_svprfd
+ // CHECK: %[[PG:.*]] = call <vscale x 2 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv2i1(<vscale x 16 x i1> %pg)
+ // CHECK: @llvm.aarch64.sve.prf.nxv2i1(<vscale x 2 x i1> %[[PG]], i8* %base, i32 0)
+ return svprfd(pg, base, SV_PLDL1KEEP);
+}
+
+void test_svprfd_1(svbool_t pg, const void *base)
+{
+ // CHECK-LABEL: test_svprfd_1
+ // CHECK: %[[PG:.*]] = call <vscale x 2 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv2i1(<vscale x 16 x i1> %pg)
+ // CHECK: @llvm.aarch64.sve.prf.nxv2i1(<vscale x 2 x i1> %[[PG]], i8* %base, i32 1)
+ return svprfd(pg, base, SV_PLDL1STRM);
+}
+
+void test_svprfd_2(svbool_t pg, const void *base)
+{
+ // CHECK-LABEL: test_svprfd_2
+ // CHECK: %[[PG:.*]] = call <vscale x 2 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv2i1(<vscale x 16 x i1> %pg)
+ // CHECK: @llvm.aarch64.sve.prf.nxv2i1(<vscale x 2 x i1> %[[PG]], i8* %base, i32 2)
+ return svprfd(pg, base, SV_PLDL2KEEP);
+}
+
+void test_svprfd_3(svbool_t pg, const void *base)
+{
+ // CHECK-LABEL: test_svprfd_3
+ // CHECK: %[[PG:.*]] = call <vscale x 2 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv2i1(<vscale x 16 x i1> %pg)
+ // CHECK: @llvm.aarch64.sve.prf.nxv2i1(<vscale x 2 x i1> %[[PG]], i8* %base, i32 3)
+ return svprfd(pg, base, SV_PLDL2STRM);
+}
+
+void test_svprfd_4(svbool_t pg, const void *base)
+{
+ // CHECK-LABEL: test_svprfd_4
+ // CHECK: %[[PG:.*]] = call <vscale x 2 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv2i1(<vscale x 16 x i1> %pg)
+ // CHECK: @llvm.aarch64.sve.prf.nxv2i1(<vscale x 2 x i1> %[[PG]], i8* %base, i32 4)
+ return svprfd(pg, base, SV_PLDL3KEEP);
+}
+
+void test_svprfd_5(svbool_t pg, const void *base)
+{
+ // CHECK-LABEL: test_svprfd_5
+ // CHECK: %[[PG:.*]] = call <vscale x 2 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv2i1(<vscale x 16 x i1> %pg)
+ // CHECK: @llvm.aarch64.sve.prf.nxv2i1(<vscale x 2 x i1> %[[PG]], i8* %base, i32 5)
+ return svprfd(pg, base, SV_PLDL3STRM);
+}
+
+void test_svprfd_6(svbool_t pg, const void *base)
+{
+ // CHECK-LABEL: test_svprfd_6
+ // CHECK: %[[PG:.*]] = call <vscale x 2 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv2i1(<vscale x 16 x i1> %pg)
+ // CHECK: @llvm.aarch64.sve.prf.nxv2i1(<vscale x 2 x i1> %[[PG]], i8* %base, i32 8)
+ return svprfd(pg, base, SV_PSTL1KEEP);
+}
+
+void test_svprfd_7(svbool_t pg, const void *base)
+{
+ // CHECK-LABEL: test_svprfd_7
+ // CHECK: %[[PG:.*]] = call <vscale x 2 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv2i1(<vscale x 16 x i1> %pg)
+ // CHECK: @llvm.aarch64.sve.prf.nxv2i1(<vscale x 2 x i1> %[[PG]], i8* %base, i32 9)
+ return svprfd(pg, base, SV_PSTL1STRM);
+}
+
+void test_svprfd_8(svbool_t pg, const void *base)
+{
+ // CHECK-LABEL: test_svprfd_8
+ // CHECK: %[[PG:.*]] = call <vscale x 2 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv2i1(<vscale x 16 x i1> %pg)
+ // CHECK: @llvm.aarch64.sve.prf.nxv2i1(<vscale x 2 x i1> %[[PG]], i8* %base, i32 10)
+ return svprfd(pg, base, SV_PSTL2KEEP);
+}
+
+void test_svprfd_9(svbool_t pg, const void *base)
+{
+ // CHECK-LABEL: test_svprfd_9
+ // CHECK: %[[PG:.*]] = call <vscale x 2 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv2i1(<vscale x 16 x i1> %pg)
+ // CHECK: @llvm.aarch64.sve.prf.nxv2i1(<vscale x 2 x i1> %[[PG]], i8* %base, i32 11)
+ return svprfd(pg, base, SV_PSTL2STRM);
+}
+
+void test_svprfd_10(svbool_t pg, const void *base)
+{
+ // CHECK-LABEL: test_svprfd_10
+ // CHECK: %[[PG:.*]] = call <vscale x 2 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv2i1(<vscale x 16 x i1> %pg)
+ // CHECK: @llvm.aarch64.sve.prf.nxv2i1(<vscale x 2 x i1> %[[PG]], i8* %base, i32 12)
+ return svprfd(pg, base, SV_PSTL3KEEP);
+}
+
+void test_svprfd_11(svbool_t pg, const void *base)
+{
+ // CHECK-LABEL: test_svprfd_11
+ // CHECK: %[[PG:.*]] = call <vscale x 2 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv2i1(<vscale x 16 x i1> %pg)
+ // CHECK: @llvm.aarch64.sve.prf.nxv2i1(<vscale x 2 x i1> %[[PG]], i8* %base, i32 13)
+ return svprfd(pg, base, SV_PSTL3STRM);
+}
+
+void test_svprfd_vnum(svbool_t pg, const void *base, int64_t vnum)
+{
+ // CHECK-LABEL: test_svprfd_vnum
+ // CHECK-DAG: %[[PG:.*]] = call <vscale x 2 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv2i1(<vscale x 16 x i1> %pg)
+ // CHECK-DAG: %[[BASE:.*]] = bitcast i8* %base to <vscale x 2 x i64>*
+ // CHECK-DAG: %[[GEP:.*]] = getelementptr <vscale x 2 x i64>, <vscale x 2 x i64>* %[[BASE]], i64 %vnum
+ // CHECK-DAG: %[[I8_BASE:.*]] = bitcast <vscale x 2 x i64>* %[[GEP]] to i8*
+ // CHECK: @llvm.aarch64.sve.prf.nxv2i1(<vscale x 2 x i1> %[[PG]], i8* %[[I8_BASE]], i32 0)
+ return svprfd_vnum(pg, base, vnum, SV_PLDL1KEEP);
+}
diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_prfh.c b/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_prfh.c
new file mode 100644
index 000000000000..a6290f3f2f0c
--- /dev/null
+++ b/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_prfh.c
@@ -0,0 +1,118 @@
+// 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
+
+void test_svprfh(svbool_t pg, const void *base)
+{
+ // CHECK-LABEL: test_svprfh
+ // CHECK: %[[PG:.*]] = call <vscale x 8 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv8i1(<vscale x 16 x i1> %pg)
+ // CHECK: @llvm.aarch64.sve.prf.nxv8i1(<vscale x 8 x i1> %[[PG]], i8* %base, i32 0)
+ return svprfh(pg, base, SV_PLDL1KEEP);
+}
+
+void test_svprfh_1(svbool_t pg, const void *base)
+{
+ // CHECK-LABEL: test_svprfh_1
+ // CHECK: %[[PG:.*]] = call <vscale x 8 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv8i1(<vscale x 16 x i1> %pg)
+ // CHECK: @llvm.aarch64.sve.prf.nxv8i1(<vscale x 8 x i1> %[[PG]], i8* %base, i32 1)
+ return svprfh(pg, base, SV_PLDL1STRM);
+}
+
+void test_svprfh_2(svbool_t pg, const void *base)
+{
+ // CHECK-LABEL: test_svprfh_2
+ // CHECK: %[[PG:.*]] = call <vscale x 8 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv8i1(<vscale x 16 x i1> %pg)
+ // CHECK: @llvm.aarch64.sve.prf.nxv8i1(<vscale x 8 x i1> %[[PG]], i8* %base, i32 2)
+ return svprfh(pg, base, SV_PLDL2KEEP);
+}
+
+void test_svprfh_3(svbool_t pg, const void *base)
+{
+ // CHECK-LABEL: test_svprfh_3
+ // CHECK: %[[PG:.*]] = call <vscale x 8 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv8i1(<vscale x 16 x i1> %pg)
+ // CHECK: @llvm.aarch64.sve.prf.nxv8i1(<vscale x 8 x i1> %[[PG]], i8* %base, i32 3)
+ return svprfh(pg, base, SV_PLDL2STRM);
+}
+
+void test_svprfh_4(svbool_t pg, const void *base)
+{
+ // CHECK-LABEL: test_svprfh_4
+ // CHECK: %[[PG:.*]] = call <vscale x 8 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv8i1(<vscale x 16 x i1> %pg)
+ // CHECK: @llvm.aarch64.sve.prf.nxv8i1(<vscale x 8 x i1> %[[PG]], i8* %base, i32 4)
+ return svprfh(pg, base, SV_PLDL3KEEP);
+}
+
+void test_svprfh_5(svbool_t pg, const void *base)
+{
+ // CHECK-LABEL: test_svprfh_5
+ // CHECK: %[[PG:.*]] = call <vscale x 8 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv8i1(<vscale x 16 x i1> %pg)
+ // CHECK: @llvm.aarch64.sve.prf.nxv8i1(<vscale x 8 x i1> %[[PG]], i8* %base, i32 5)
+ return svprfh(pg, base, SV_PLDL3STRM);
+}
+
+void test_svprfh_6(svbool_t pg, const void *base)
+{
+ // CHECK-LABEL: test_svprfh_6
+ // CHECK: %[[PG:.*]] = call <vscale x 8 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv8i1(<vscale x 16 x i1> %pg)
+ // CHECK: @llvm.aarch64.sve.prf.nxv8i1(<vscale x 8 x i1> %[[PG]], i8* %base, i32 8)
+ return svprfh(pg, base, SV_PSTL1KEEP);
+}
+
+void test_svprfh_7(svbool_t pg, const void *base)
+{
+ // CHECK-LABEL: test_svprfh_7
+ // CHECK: %[[PG:.*]] = call <vscale x 8 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv8i1(<vscale x 16 x i1> %pg)
+ // CHECK: @llvm.aarch64.sve.prf.nxv8i1(<vscale x 8 x i1> %[[PG]], i8* %base, i32 9)
+ return svprfh(pg, base, SV_PSTL1STRM);
+}
+
+void test_svprfh_8(svbool_t pg, const void *base)
+{
+ // CHECK-LABEL: test_svprfh_8
+ // CHECK: %[[PG:.*]] = call <vscale x 8 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv8i1(<vscale x 16 x i1> %pg)
+ // CHECK: @llvm.aarch64.sve.prf.nxv8i1(<vscale x 8 x i1> %[[PG]], i8* %base, i32 10)
+ return svprfh(pg, base, SV_PSTL2KEEP);
+}
+
+void test_svprfh_9(svbool_t pg, const void *base)
+{
+ // CHECK-LABEL: test_svprfh_9
+ // CHECK: %[[PG:.*]] = call <vscale x 8 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv8i1(<vscale x 16 x i1> %pg)
+ // CHECK: @llvm.aarch64.sve.prf.nxv8i1(<vscale x 8 x i1> %[[PG]], i8* %base, i32 11)
+ return svprfh(pg, base, SV_PSTL2STRM);
+}
+
+void test_svprfh_10(svbool_t pg, const void *base)
+{
+ // CHECK-LABEL: test_svprfh_10
+ // CHECK: %[[PG:.*]] = call <vscale x 8 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv8i1(<vscale x 16 x i1> %pg)
+ // CHECK: @llvm.aarch64.sve.prf.nxv8i1(<vscale x 8 x i1> %[[PG]], i8* %base, i32 12)
+ return svprfh(pg, base, SV_PSTL3KEEP);
+}
+
+void test_svprfh_11(svbool_t pg, const void *base)
+{
+ // CHECK-LABEL: test_svprfh_11
+ // CHECK: %[[PG:.*]] = call <vscale x 8 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv8i1(<vscale x 16 x i1> %pg)
+ // CHECK: @llvm.aarch64.sve.prf.nxv8i1(<vscale x 8 x i1> %[[PG]], i8* %base, i32 13)
+ return svprfh(pg, base, SV_PSTL3STRM);
+}
+
+void test_svprfh_vnum(svbool_t pg, const void *base, int64_t vnum)
+{
+ // CHECK-LABEL: test_svprfh_vnum
+ // CHECK-DAG: %[[PG:.*]] = call <vscale x 8 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv8i1(<vscale x 16 x i1> %pg)
+ // CHECK-DAG: %[[BASE:.*]] = bitcast i8* %base to <vscale x 8 x i16>*
+ // CHECK-DAG: %[[GEP:.*]] = getelementptr <vscale x 8 x i16>, <vscale x 8 x i16>* %[[BASE]], i64 %vnum
+ // CHECK-DAG: %[[I8_BASE:.*]] = bitcast <vscale x 8 x i16>* %[[GEP]] to i8*
+ // CHECK: @llvm.aarch64.sve.prf.nxv8i1(<vscale x 8 x i1> %[[PG]], i8* %[[I8_BASE]], i32 0)
+ return svprfh_vnum(pg, base, vnum, SV_PLDL1KEEP);
+}
diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_prfw.c b/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_prfw.c
new file mode 100644
index 000000000000..e6b1b603e475
--- /dev/null
+++ b/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_prfw.c
@@ -0,0 +1,118 @@
+// 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
+
+void test_svprfw(svbool_t pg, const void *base)
+{
+ // CHECK-LABEL: test_svprfw
+ // CHECK: %[[PG:.*]] = call <vscale x 4 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv4i1(<vscale x 16 x i1> %pg)
+ // CHECK: @llvm.aarch64.sve.prf.nxv4i1(<vscale x 4 x i1> %[[PG]], i8* %base, i32 0)
+ return svprfw(pg, base, SV_PLDL1KEEP);
+}
+
+void test_svprfw_1(svbool_t pg, const void *base)
+{
+ // CHECK-LABEL: test_svprfw_1
+ // CHECK: %[[PG:.*]] = call <vscale x 4 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv4i1(<vscale x 16 x i1> %pg)
+ // CHECK: @llvm.aarch64.sve.prf.nxv4i1(<vscale x 4 x i1> %[[PG]], i8* %base, i32 1)
+ return svprfw(pg, base, SV_PLDL1STRM);
+}
+
+void test_svprfw_2(svbool_t pg, const void *base)
+{
+ // CHECK-LABEL: test_svprfw_2
+ // CHECK: %[[PG:.*]] = call <vscale x 4 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv4i1(<vscale x 16 x i1> %pg)
+ // CHECK: @llvm.aarch64.sve.prf.nxv4i1(<vscale x 4 x i1> %[[PG]], i8* %base, i32 2)
+ return svprfw(pg, base, SV_PLDL2KEEP);
+}
+
+void test_svprfw_3(svbool_t pg, const void *base)
+{
+ // CHECK-LABEL: test_svprfw_3
+ // CHECK: %[[PG:.*]] = call <vscale x 4 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv4i1(<vscale x 16 x i1> %pg)
+ // CHECK: @llvm.aarch64.sve.prf.nxv4i1(<vscale x 4 x i1> %[[PG]], i8* %base, i32 3)
+ return svprfw(pg, base, SV_PLDL2STRM);
+}
+
+void test_svprfw_4(svbool_t pg, const void *base)
+{
+ // CHECK-LABEL: test_svprfw_4
+ // CHECK: %[[PG:.*]] = call <vscale x 4 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv4i1(<vscale x 16 x i1> %pg)
+ // CHECK: @llvm.aarch64.sve.prf.nxv4i1(<vscale x 4 x i1> %[[PG]], i8* %base, i32 4)
+ return svprfw(pg, base, SV_PLDL3KEEP);
+}
+
+void test_svprfw_5(svbool_t pg, const void *base)
+{
+ // CHECK-LABEL: test_svprfw_5
+ // CHECK: %[[PG:.*]] = call <vscale x 4 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv4i1(<vscale x 16 x i1> %pg)
+ // CHECK: @llvm.aarch64.sve.prf.nxv4i1(<vscale x 4 x i1> %[[PG]], i8* %base, i32 5)
+ return svprfw(pg, base, SV_PLDL3STRM);
+}
+
+void test_svprfw_6(svbool_t pg, const void *base)
+{
+ // CHECK-LABEL: test_svprfw_6
+ // CHECK: %[[PG:.*]] = call <vscale x 4 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv4i1(<vscale x 16 x i1> %pg)
+ // CHECK: @llvm.aarch64.sve.prf.nxv4i1(<vscale x 4 x i1> %[[PG]], i8* %base, i32 8)
+ return svprfw(pg, base, SV_PSTL1KEEP);
+}
+
+void test_svprfw_7(svbool_t pg, const void *base)
+{
+ // CHECK-LABEL: test_svprfw_7
+ // CHECK: %[[PG:.*]] = call <vscale x 4 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv4i1(<vscale x 16 x i1> %pg)
+ // CHECK: @llvm.aarch64.sve.prf.nxv4i1(<vscale x 4 x i1> %[[PG]], i8* %base, i32 9)
+ return svprfw(pg, base, SV_PSTL1STRM);
+}
+
+void test_svprfw_8(svbool_t pg, const void *base)
+{
+ // CHECK-LABEL: test_svprfw_8
+ // CHECK: %[[PG:.*]] = call <vscale x 4 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv4i1(<vscale x 16 x i1> %pg)
+ // CHECK: @llvm.aarch64.sve.prf.nxv4i1(<vscale x 4 x i1> %[[PG]], i8* %base, i32 10)
+ return svprfw(pg, base, SV_PSTL2KEEP);
+}
+
+void test_svprfw_9(svbool_t pg, const void *base)
+{
+ // CHECK-LABEL: test_svprfw_9
+ // CHECK: %[[PG:.*]] = call <vscale x 4 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv4i1(<vscale x 16 x i1> %pg)
+ // CHECK: @llvm.aarch64.sve.prf.nxv4i1(<vscale x 4 x i1> %[[PG]], i8* %base, i32 11)
+ return svprfw(pg, base, SV_PSTL2STRM);
+}
+
+void test_svprfw_10(svbool_t pg, const void *base)
+{
+ // CHECK-LABEL: test_svprfw_10
+ // CHECK: %[[PG:.*]] = call <vscale x 4 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv4i1(<vscale x 16 x i1> %pg)
+ // CHECK: @llvm.aarch64.sve.prf.nxv4i1(<vscale x 4 x i1> %[[PG]], i8* %base, i32 12)
+ return svprfw(pg, base, SV_PSTL3KEEP);
+}
+
+void test_svprfw_11(svbool_t pg, const void *base)
+{
+ // CHECK-LABEL: test_svprfw_11
+ // CHECK: %[[PG:.*]] = call <vscale x 4 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv4i1(<vscale x 16 x i1> %pg)
+ // CHECK: @llvm.aarch64.sve.prf.nxv4i1(<vscale x 4 x i1> %[[PG]], i8* %base, i32 13)
+ return svprfw(pg, base, SV_PSTL3STRM);
+}
+
+void test_svprfw_vnum(svbool_t pg, const void *base, int64_t vnum)
+{
+ // CHECK-LABEL: test_svprfw_vnum
+ // CHECK-DAG: %[[PG:.*]] = call <vscale x 4 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv4i1(<vscale x 16 x i1> %pg)
+ // CHECK-DAG: %[[BASE:.*]] = bitcast i8* %base to <vscale x 4 x i32>*
+ // CHECK-DAG: %[[GEP:.*]] = getelementptr <vscale x 4 x i32>, <vscale x 4 x i32>* %[[BASE]], i64 %vnum
+ // CHECK-DAG: %[[I8_BASE:.*]] = bitcast <vscale x 4 x i32>* %[[GEP]] to i8*
+ // CHECK: @llvm.aarch64.sve.prf.nxv4i1(<vscale x 4 x i1> %[[PG]], i8* %[[I8_BASE]], i32 0)
+ return svprfw_vnum(pg, base, vnum, SV_PLDL1KEEP);
+}
diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/negative/acle_sve_prfb.c b/clang/test/CodeGen/aarch64-sve-intrinsics/negative/acle_sve_prfb.c
new file mode 100644
index 000000000000..48fea8c540b7
--- /dev/null
+++ b/clang/test/CodeGen/aarch64-sve-intrinsics/negative/acle_sve_prfb.c
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -triple aarch64-none-linux-gnu -target-feature +sve -fallow-half-arguments-and-returns -fsyntax-only -verify %s
+
+#include <arm_sve.h>
+
+void test_svprfb(svbool_t pg, const void *base)
+{
+ // expected-error at +1 {{argument value 14 is outside the valid range [0, 13]}}
+ return svprfb(pg, base, 14);
+}
+
+void test_svprfb_1(svbool_t pg, const void *base)
+{
+ // expected-error at +1 {{argument value -1 is outside the valid range [0, 13]}}
+ return svprfb(pg, base, -1);
+}
+
+void test_svprfb_vnum(svbool_t pg, const void *base)
+{
+ // expected-error at +1 {{argument value 14 is outside the valid range [0, 13]}}
+ return svprfb_vnum(pg, base, 0, 14);
+}
+
+void test_svprfb_vnum_1(svbool_t pg, const void *base)
+{
+ // expected-error at +1 {{argument value -1 is outside the valid range [0, 13]}}
+ return svprfb_vnum(pg, base, 0, -1);
+}
diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/negative/acle_sve_prfd.c b/clang/test/CodeGen/aarch64-sve-intrinsics/negative/acle_sve_prfd.c
new file mode 100644
index 000000000000..2efa9b6c9e13
--- /dev/null
+++ b/clang/test/CodeGen/aarch64-sve-intrinsics/negative/acle_sve_prfd.c
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -triple aarch64-none-linux-gnu -target-feature +sve -fallow-half-arguments-and-returns -fsyntax-only -verify %s
+
+#include <arm_sve.h>
+
+void test_svprfd(svbool_t pg, const void *base)
+{
+ // expected-error at +1 {{argument value 14 is outside the valid range [0, 13]}}
+ return svprfd(pg, base, 14);
+}
+
+void test_svprfd_1(svbool_t pg, const void *base)
+{
+ // expected-error at +1 {{argument value -1 is outside the valid range [0, 13]}}
+ return svprfd(pg, base, -1);
+}
+
+void test_svprfd_vnum(svbool_t pg, const void *base)
+{
+ // expected-error at +1 {{argument value 14 is outside the valid range [0, 13]}}
+ return svprfd_vnum(pg, base, 0, 14);
+}
+
+void test_svprfd_vnum_1(svbool_t pg, const void *base)
+{
+ // expected-error at +1 {{argument value -1 is outside the valid range [0, 13]}}
+ return svprfd_vnum(pg, base, 0, -1);
+}
diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/negative/acle_sve_prfh.c b/clang/test/CodeGen/aarch64-sve-intrinsics/negative/acle_sve_prfh.c
new file mode 100644
index 000000000000..16b19203cdc5
--- /dev/null
+++ b/clang/test/CodeGen/aarch64-sve-intrinsics/negative/acle_sve_prfh.c
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -triple aarch64-none-linux-gnu -target-feature +sve -fallow-half-arguments-and-returns -fsyntax-only -verify %s
+
+#include <arm_sve.h>
+
+void test_svprfh(svbool_t pg, const void *base)
+{
+ // expected-error at +1 {{argument value 14 is outside the valid range [0, 13]}}
+ return svprfh(pg, base, 14);
+}
+
+void test_svprfh_1(svbool_t pg, const void *base)
+{
+ // expected-error at +1 {{argument value -1 is outside the valid range [0, 13]}}
+ return svprfh(pg, base, -1);
+}
+
+void test_svprfh_vnum(svbool_t pg, const void *base)
+{
+ // expected-error at +1 {{argument value 14 is outside the valid range [0, 13]}}
+ return svprfh_vnum(pg, base, 0, 14);
+}
+
+void test_svprfh_vnum_1(svbool_t pg, const void *base)
+{
+ // expected-error at +1 {{argument value -1 is outside the valid range [0, 13]}}
+ return svprfh_vnum(pg, base, 0, -1);
+}
diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/negative/acle_sve_prfw.c b/clang/test/CodeGen/aarch64-sve-intrinsics/negative/acle_sve_prfw.c
new file mode 100644
index 000000000000..ea1d6e24419b
--- /dev/null
+++ b/clang/test/CodeGen/aarch64-sve-intrinsics/negative/acle_sve_prfw.c
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -triple aarch64-none-linux-gnu -target-feature +sve -fallow-half-arguments-and-returns -fsyntax-only -verify %s
+
+#include <arm_sve.h>
+
+void test_svprfw(svbool_t pg, const void *base)
+{
+ // expected-error at +1 {{argument value 14 is outside the valid range [0, 13]}}
+ return svprfw(pg, base, 14);
+}
+
+void test_svprfw_1(svbool_t pg, const void *base)
+{
+ // expected-error at +1 {{argument value -1 is outside the valid range [0, 13]}}
+ return svprfw(pg, base, -1);
+}
+
+void test_svprfw_vnum(svbool_t pg, const void *base)
+{
+ // expected-error at +1 {{argument value 14 is outside the valid range [0, 13]}}
+ return svprfw_vnum(pg, base, 0, 14);
+}
+
+void test_svprfw_vnum_1(svbool_t pg, const void *base)
+{
+ // expected-error at +1 {{argument value -1 is outside the valid range [0, 13]}}
+ return svprfw_vnum(pg, base, 0, -1);
+}
diff --git a/clang/utils/TableGen/SveEmitter.cpp b/clang/utils/TableGen/SveEmitter.cpp
index 13e1be6ec50f..8c8b415df914 100644
--- a/clang/utils/TableGen/SveEmitter.cpp
+++ b/clang/utils/TableGen/SveEmitter.cpp
@@ -536,6 +536,15 @@ void SVEType::applyModifier(char Mod) {
Immediate = true;
PredicatePattern = true;
break;
+ case 'J':
+ Predicate = false;
+ Float = false;
+ ElementBitwidth = Bitwidth = 32;
+ NumVectors = 0;
+ Signed = true;
+ Immediate = true;
+ PrefetchOp = true;
+ break;
case 'k':
Predicate = false;
Signed = true;
@@ -703,6 +712,9 @@ Intrinsic::Intrinsic(StringRef Name, StringRef Proto, uint64_t MergeTy,
if (T.isPredicatePattern())
ImmChecks.emplace_back(
I - 1, Emitter.getEnumValueForImmCheck("ImmCheck0_31"));
+ else if (T.isPrefetchOp())
+ ImmChecks.emplace_back(
+ I - 1, Emitter.getEnumValueForImmCheck("ImmCheck0_13"));
}
}
@@ -1005,6 +1017,22 @@ void SVEEmitter::createHeader(raw_ostream &OS) {
OS << " SV_ALL = 31\n";
OS << "} sv_pattern;\n\n";
+ OS << "typedef enum\n";
+ OS << "{\n";
+ OS << " SV_PLDL1KEEP = 0,\n";
+ OS << " SV_PLDL1STRM = 1,\n";
+ OS << " SV_PLDL2KEEP = 2,\n";
+ OS << " SV_PLDL2STRM = 3,\n";
+ OS << " SV_PLDL3KEEP = 4,\n";
+ OS << " SV_PLDL3STRM = 5,\n";
+ OS << " SV_PSTL1KEEP = 8,\n";
+ OS << " SV_PSTL1STRM = 9,\n";
+ OS << " SV_PSTL2KEEP = 10,\n";
+ OS << " SV_PSTL2STRM = 11,\n";
+ OS << " SV_PSTL3KEEP = 12,\n";
+ OS << " SV_PSTL3STRM = 13\n";
+ OS << "} sv_prfop;\n\n";
+
OS << "/* Function attributes */\n";
OS << "#define __aio static inline __attribute__((__always_inline__, "
"__nodebug__, __overloadable__))\n\n";
More information about the cfe-commits
mailing list