[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