diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -1275,6 +1275,12 @@ /// Returns a vla type where known sizes are replaced with [*]. QualType getVariableArrayDecayedType(QualType Ty) const; + /// Return the unique reference to a scalable vector type of the specified + /// element type and scalable number of elements. + /// + /// \pre \p EltTy must be a built-in type. + QualType getScalableVectorType(QualType EltTy, unsigned NumElts) const; + /// Return the unique reference to a vector type of the specified /// element type and size. /// diff --git a/clang/include/clang/Basic/AArch64SVEACLETypes.def b/clang/include/clang/Basic/AArch64SVEACLETypes.def --- a/clang/include/clang/Basic/AArch64SVEACLETypes.def +++ b/clang/include/clang/Basic/AArch64SVEACLETypes.def @@ -38,32 +38,32 @@ //===----------------------------------------------------------------------===// #ifndef SVE_VECTOR_TYPE -#define SVE_VECTOR_TYPE(Name, Id, SingletonId, ElKind, ElBits, IsSigned, IsFP)\ +#define SVE_VECTOR_TYPE(Name, Id, SingletonId, NumEls, ElBits, IsSigned, IsFP) \ SVE_TYPE(Name, Id, SingletonId) #endif #ifndef SVE_PREDICATE_TYPE -#define SVE_PREDICATE_TYPE(Name, Id, SingletonId, ElKind)\ +#define SVE_PREDICATE_TYPE(Name, Id, SingletonId, NumEls)\ SVE_TYPE(Name, Id, SingletonId) #endif //===- Vector point types -----------------------------------------------===// -SVE_VECTOR_TYPE("__SVInt8_t", SveInt8, SveInt8Ty, SveElSInt8, 8, true, false) -SVE_VECTOR_TYPE("__SVInt16_t", SveInt16, SveInt16Ty, SveElSInt16, 16, true, false) -SVE_VECTOR_TYPE("__SVInt32_t", SveInt32, SveInt32Ty, SveElSInt32, 32, true, false) -SVE_VECTOR_TYPE("__SVInt64_t", SveInt64, SveInt64Ty, SveElSInt64, 64, true, false) +SVE_VECTOR_TYPE("__SVInt8_t", SveInt8, SveInt8Ty, 16, 8, true, false) +SVE_VECTOR_TYPE("__SVInt16_t", SveInt16, SveInt16Ty, 8, 16, true, false) +SVE_VECTOR_TYPE("__SVInt32_t", SveInt32, SveInt32Ty, 4, 32, true, false) +SVE_VECTOR_TYPE("__SVInt64_t", SveInt64, SveInt64Ty, 2, 64, true, false) -SVE_VECTOR_TYPE("__SVUint8_t", SveUint8, SveUint8Ty, SveElUInt8, 8, false, false) -SVE_VECTOR_TYPE("__SVUint16_t", SveUint16, SveUint16Ty, SveElUInt16, 16, false, false) -SVE_VECTOR_TYPE("__SVUint32_t", SveUint32, SveUint32Ty, SveElUInt32, 32, false, false) -SVE_VECTOR_TYPE("__SVUint64_t", SveUint64, SveUint64Ty, SveElUInt64, 64, false, false) +SVE_VECTOR_TYPE("__SVUint8_t", SveUint8, SveUint8Ty, 16, 8, false, false) +SVE_VECTOR_TYPE("__SVUint16_t", SveUint16, SveUint16Ty, 8, 16, false, false) +SVE_VECTOR_TYPE("__SVUint32_t", SveUint32, SveUint32Ty, 4, 32, false, false) +SVE_VECTOR_TYPE("__SVUint64_t", SveUint64, SveUint64Ty, 2, 64, false, false) -SVE_VECTOR_TYPE("__SVFloat16_t", SveFloat16, SveFloat16Ty, SveElHalf, 16, true, true) -SVE_VECTOR_TYPE("__SVFloat32_t", SveFloat32, SveFloat32Ty, SveElFloat, 32, true, true) -SVE_VECTOR_TYPE("__SVFloat64_t", SveFloat64, SveFloat64Ty, SveElDouble, 64, true, true) +SVE_VECTOR_TYPE("__SVFloat16_t", SveFloat16, SveFloat16Ty, 8, 16, true, true) +SVE_VECTOR_TYPE("__SVFloat32_t", SveFloat32, SveFloat32Ty, 4, 32, true, true) +SVE_VECTOR_TYPE("__SVFloat64_t", SveFloat64, SveFloat64Ty, 2, 64, true, true) -SVE_PREDICATE_TYPE("__SVBool_t", SveBool, SveBoolTy, SveElBool) +SVE_PREDICATE_TYPE("__SVBool_t", SveBool, SveBoolTy, 16) #undef SVE_VECTOR_TYPE #undef SVE_PREDICATE_TYPE diff --git a/clang/include/clang/Basic/Builtins.def b/clang/include/clang/Basic/Builtins.def --- a/clang/include/clang/Basic/Builtins.def +++ b/clang/include/clang/Basic/Builtins.def @@ -36,6 +36,7 @@ // a -> __builtin_va_list // A -> "reference" to __builtin_va_list // V -> Vector, followed by the number of elements and the base type. +// q -> Scalable vector, followed by the number of elements and the base type. // E -> ext_vector, followed by the number of elements and the base type. // X -> _Complex, followed by the base type. // Y -> ptrdiff_t diff --git a/clang/include/clang/Basic/BuiltinsAArch64.def b/clang/include/clang/Basic/BuiltinsAArch64.def --- a/clang/include/clang/Basic/BuiltinsAArch64.def +++ b/clang/include/clang/Basic/BuiltinsAArch64.def @@ -99,6 +99,19 @@ BUILTIN(__builtin_arm_tcancel, "vWUIi", "n") BUILTIN(__builtin_arm_ttest, "WUi", "nc") +// SVE +BUILTIN(__builtin_sve_svld1_s16, "q8sq16bSsC*", "n") +BUILTIN(__builtin_sve_svld1_s32, "q4iq16bSiC*", "n") +BUILTIN(__builtin_sve_svld1_s64, "q2Wiq16bSWiC*", "n") +BUILTIN(__builtin_sve_svld1_s8, "q16Scq16bScC*", "n") +BUILTIN(__builtin_sve_svld1_u16, "q8Usq16bUsC*", "n") +BUILTIN(__builtin_sve_svld1_u32, "q4Uiq16bUiC*", "n") +BUILTIN(__builtin_sve_svld1_u64, "q2UWiq16bUWiC*", "n") +BUILTIN(__builtin_sve_svld1_u8, "q16Ucq16bUcC*", "n") +BUILTIN(__builtin_sve_svld1_f64, "q2dq16bdC*", "n") +BUILTIN(__builtin_sve_svld1_f32, "q4fq16bfC*", "n") +BUILTIN(__builtin_sve_svld1_f16, "q8hq16bhC*", "n") + TARGET_HEADER_BUILTIN(_BitScanForward, "UcUNi*UNi", "nh", "intrin.h", ALL_MS_LANGUAGES, "") TARGET_HEADER_BUILTIN(_BitScanReverse, "UcUNi*UNi", "nh", "intrin.h", ALL_MS_LANGUAGES, "") TARGET_HEADER_BUILTIN(_BitScanForward64, "UcUNi*ULLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "") diff --git a/clang/include/clang/Basic/arm_sve.td b/clang/include/clang/Basic/arm_sve.td new file mode 100644 --- /dev/null +++ b/clang/include/clang/Basic/arm_sve.td @@ -0,0 +1,14 @@ +//===--- arm_sve.td - ARM SVE compiler interface ------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the TableGen definitions from which the ARM SVE header +// file will be generated. See: +// +// https://developer.arm.com/architectures/system-architectures/software-standards/acle +// +//===----------------------------------------------------------------------===// diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -2100,16 +2100,16 @@ // Because the length is only known at runtime, we use a dummy value // of 0 for the static length. The alignment values are those defined // by the Procedure Call Standard for the Arm Architecture. -#define SVE_VECTOR_TYPE(Name, Id, SingletonId, ElKind, ElBits, IsSigned, IsFP)\ - case BuiltinType::Id: \ - Width = 0; \ - Align = 128; \ - break; -#define SVE_PREDICATE_TYPE(Name, Id, SingletonId, ElKind) \ - case BuiltinType::Id: \ - Width = 0; \ - Align = 16; \ - break; +#define SVE_VECTOR_TYPE(Name, Id, SingletonId, NumEls, ElBits, IsSigned, IsFP) \ + case BuiltinType::Id: \ + Width = 0; \ + Align = 128; \ + break; +#define SVE_PREDICATE_TYPE(Name, Id, SingletonId, NumEls) \ + case BuiltinType::Id: \ + Width = 0; \ + Align = 16; \ + break; #include "clang/Basic/AArch64SVEACLETypes.def" } break; @@ -3584,6 +3584,28 @@ return QualType(newType, 0); } +/// getScalableVectorType - Return the unique reference to a scalable vector +/// type of the specified element type and size. VectorType must be a built-in +/// type. +QualType ASTContext::getScalableVectorType(QualType EltTy, + unsigned NumElts) const { + if (Target->hasAArch64SVETypes()) { + uint64_t EltTySize = getTypeSize(EltTy); +#define SVE_VECTOR_TYPE(Name, Id, SingletonId, NumEls, ElBits, IsSigned, IsFP) \ + if (!EltTy->isBooleanType() && \ + ((EltTy->hasIntegerRepresentation() && \ + EltTy->hasSignedIntegerRepresentation() == IsSigned) || \ + (EltTy->hasFloatingRepresentation() && IsFP)) && \ + EltTySize == ElBits && NumElts == NumEls) \ + return SingletonId; +#define SVE_PREDICATE_TYPE(Name, Id, SingletonId, NumEls) \ + if (EltTy->isBooleanType() && NumElts == NumEls) \ + return SingletonId; +#include "clang/Basic/AArch64SVEACLETypes.def" + } + return QualType(); +} + /// getVectorType - Return the unique reference to a vector type of /// the specified element type and size. VectorType must be a built-in type. QualType ASTContext::getVectorType(QualType vecType, unsigned NumElts, @@ -9699,6 +9721,19 @@ else Type = Context.getLValueReferenceType(Type); break; + case 'q': { + char *End; + unsigned NumElements = strtoul(Str, &End, 10); + assert(End != Str && "Missing vector size"); + Str = End; + + QualType ElementType = DecodeTypeFromStr(Str, Context, Error, + RequiresICE, false); + assert(!RequiresICE && "Can't require vector ICE"); + + Type = Context.getScalableVectorType(ElementType, NumElements); + break; + } case 'V': { char *End; unsigned NumElements = strtoul(Str, &End, 10); diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -7384,6 +7384,58 @@ return Op; } +// Reinterpret the input predicate so that it can be used to correctly isolate +// the elements of the specified datatype. +Value *CodeGenFunction::EmitSVEPredicateCast(Value *Pred, + llvm::VectorType *VTy) { + llvm::VectorType *RTy = llvm::VectorType::get( + IntegerType::get(getLLVMContext(), 1), VTy->getElementCount()); + if (Pred->getType() == RTy) + return Pred; + + unsigned IntID; + llvm::Type *IntrinsicTy; + switch (VTy->getNumElements()) { + default: + llvm_unreachable("unsupported element count!"); + case 2: + case 4: + case 8: + IntID = Intrinsic::aarch64_sve_convert_from_svbool; + IntrinsicTy = RTy; + break; + case 16: + IntID = Intrinsic::aarch64_sve_convert_to_svbool; + IntrinsicTy = Pred->getType(); + break; + } + + Function *F = CGM.getIntrinsic(IntID, IntrinsicTy); + Value *C = Builder.CreateCall(F, Pred); + assert(C->getType() == RTy && "Unexpected return type!"); + return C; +} + +Value *CodeGenFunction::EmitSVEMaskedLoad(llvm::Type *ReturnTy, + SmallVectorImpl &Ops) { + llvm::PointerType *PTy = cast(Ops[1]->getType()); + llvm::Type *MemEltTy = PTy->getPointerElementType(); + + // The vector type that is returned may be different from the + // eventual type loaded from memory. + auto VectorTy = cast(ReturnTy); + auto MemoryTy = + llvm::VectorType::get(MemEltTy, VectorTy->getVectorElementCount()); + + Value *Offset = Builder.getInt32(0); + Value *Predicate = EmitSVEPredicateCast(Ops[0], MemoryTy); + Value *BasePtr = Builder.CreateBitCast(Ops[1], MemoryTy->getPointerTo()); + BasePtr = Builder.CreateGEP(MemoryTy, BasePtr, Offset); + + Value *Splat0 = Constant::getNullValue(MemoryTy); + return Builder.CreateMaskedLoad(BasePtr, Align(1), Predicate, Splat0); +} + Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID, const CallExpr *E, llvm::Triple::ArchType Arch) { @@ -7420,6 +7472,27 @@ return Builder.CreateCall(F, llvm::ConstantInt::get(Int32Ty, HintID)); } + switch (BuiltinID) { + case AArch64::BI__builtin_sve_svld1_u8: + case AArch64::BI__builtin_sve_svld1_u16: + case AArch64::BI__builtin_sve_svld1_u32: + case AArch64::BI__builtin_sve_svld1_u64: + case AArch64::BI__builtin_sve_svld1_s8: + case AArch64::BI__builtin_sve_svld1_s16: + case AArch64::BI__builtin_sve_svld1_s32: + case AArch64::BI__builtin_sve_svld1_s64: + case AArch64::BI__builtin_sve_svld1_f16: + case AArch64::BI__builtin_sve_svld1_f32: + case AArch64::BI__builtin_sve_svld1_f64: { + llvm::SmallVector Ops = {EmitScalarExpr(E->getArg(0)), + EmitScalarExpr(E->getArg(1))}; + llvm::Type *Ty = ConvertType(E->getType()); + return EmitSVEMaskedLoad(Ty, Ops); + } + default: + break; + } + if (BuiltinID == AArch64::BI__builtin_arm_prefetch) { Value *Address = EmitScalarExpr(E->getArg(0)); Value *RW = EmitScalarExpr(E->getArg(1)); diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -3900,6 +3900,11 @@ llvm::Value *EmitNeonRShiftImm(llvm::Value *Vec, llvm::Value *Amt, llvm::Type *Ty, bool usgn, const char *name); llvm::Value *vectorWrapScalar16(llvm::Value *Op); + + llvm::Value *EmitSVEPredicateCast(llvm::Value *Pred, llvm::VectorType *VTy); + llvm::Value *EmitSVEMaskedLoad(llvm::Type *ReturnTy, + SmallVectorImpl &Ops); + llvm::Value *EmitAArch64BuiltinExpr(unsigned BuiltinID, const CallExpr *E, llvm::Triple::ArchType Arch); llvm::Value *EmitBPFBuiltinExpr(unsigned BuiltinID, const CallExpr *E); diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -495,13 +495,15 @@ // Scan function arguments for vector width. for (llvm::Argument &A : CurFn->args()) if (auto *VT = dyn_cast(A.getType())) - LargestVectorWidth = std::max((uint64_t)LargestVectorWidth, - VT->getPrimitiveSizeInBits().getFixedSize()); + LargestVectorWidth = + std::max((uint64_t)LargestVectorWidth, + VT->getPrimitiveSizeInBits().getKnownMinSize()); // Update vector width based on return type. if (auto *VT = dyn_cast(CurFn->getReturnType())) - LargestVectorWidth = std::max((uint64_t)LargestVectorWidth, - VT->getPrimitiveSizeInBits().getFixedSize()); + LargestVectorWidth = + std::max((uint64_t)LargestVectorWidth, + VT->getPrimitiveSizeInBits().getKnownMinSize()); // Add the required-vector-width attribute. This contains the max width from: // 1. min-vector-width attribute used in the source program. diff --git a/clang/lib/Headers/CMakeLists.txt b/clang/lib/Headers/CMakeLists.txt --- a/clang/lib/Headers/CMakeLists.txt +++ b/clang/lib/Headers/CMakeLists.txt @@ -184,6 +184,8 @@ clang_generate_header(-gen-arm-neon arm_neon.td arm_neon.h) # Generate arm_fp16.h clang_generate_header(-gen-arm-fp16 arm_fp16.td arm_fp16.h) +# Generate arm_sve.h +clang_generate_header(-gen-arm-sve-header arm_sve.td arm_sve.h) # Generate arm_mve.h clang_generate_header(-gen-arm-mve-header arm_mve.td arm_mve.h) # Generate arm_cde.h diff --git a/clang/lib/Headers/module.modulemap b/clang/lib/Headers/module.modulemap --- a/clang/lib/Headers/module.modulemap +++ b/clang/lib/Headers/module.modulemap @@ -27,6 +27,12 @@ header "arm_fp16.h" export * } + + explicit module sve { + requires sve + header "arm_sve.h" + export * + } } explicit module intel { diff --git a/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ld1.c b/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ld1.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_ld1.c @@ -0,0 +1,83 @@ +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -fallow-half-arguments-and-returns -S -O1 -Werror -emit-llvm -o - %s -D__ARM_FEATURE_SVE | FileCheck %s + +#include +// +// ld1 +// + +svint8_t test_svld1_s8(svbool_t pg, const int8_t *base) +{ + // CHECK-LABEL: test_svld1_s8 + // CHECK: @llvm.masked.load.nxv16i8.p0nxv16i8(* %{{.*}}, i32 1, %{{.*}}, zeroinitializer) + return svld1_s8(pg, base); +} + +svint16_t test_svld1_s16(svbool_t pg, const int16_t *base) +{ + // CHECK-LABEL: test_svld1_s16 + // CHECK: @llvm.masked.load.nxv8i16.p0nxv8i16(* %{{.*}}, i32 1, %{{.*}}, zeroinitializer) + return svld1_s16(pg, base); +} + +svint32_t test_svld1_s32(svbool_t pg, const int32_t *base) +{ + // CHECK-LABEL: test_svld1_s32 + // CHECK: @llvm.masked.load.nxv4i32.p0nxv4i32(* %{{.*}}, i32 1, %{{.*}}, zeroinitializer) + return svld1_s32(pg, base); +} + +svint64_t test_svld1_s64(svbool_t pg, const int64_t *base) +{ + // CHECK-LABEL: test_svld1_s64 + // CHECK: @llvm.masked.load.nxv2i64.p0nxv2i64(* %{{.*}}, i32 1, %{{.*}}, zeroinitializer) + return svld1_s64(pg, base); +} + +svuint8_t test_svld1_u8(svbool_t pg, const uint8_t *base) +{ + // CHECK-LABEL: test_svld1_u8 + // CHECK: @llvm.masked.load.nxv16i8.p0nxv16i8(* %{{.*}}, i32 1, %{{.*}}, zeroinitializer) + return svld1_u8(pg, base); +} + +svuint16_t test_svld1_u16(svbool_t pg, const uint16_t *base) +{ + // CHECK-LABEL: test_svld1_u16 + // CHECK: @llvm.masked.load.nxv8i16.p0nxv8i16(* %{{.*}}, i32 1, %{{.*}}, zeroinitializer) + return svld1_u16(pg, base); +} + +svuint32_t test_svld1_u32(svbool_t pg, const uint32_t *base) +{ + // CHECK-LABEL: test_svld1_u32 + // CHECK: @llvm.masked.load.nxv4i32.p0nxv4i32(* %{{.*}}, i32 1, %{{.*}}, zeroinitializer) + return svld1_u32(pg, base); +} + +svuint64_t test_svld1_u64(svbool_t pg, const uint64_t *base) +{ + // CHECK-LABEL: test_svld1_u64 + // CHECK: @llvm.masked.load.nxv2i64.p0nxv2i64(* %{{.*}}, i32 1, %{{.*}}, zeroinitializer) + return svld1_u64(pg, base); +} + +svfloat16_t test_svld1_f16(svbool_t pg, const float16_t *base) +{ + // CHECK-LABEL: test_svld1_f16 + // CHECK: @llvm.masked.load.nxv8f16.p0nxv8f16(* %{{.*}}, i32 1, %{{.*}}, zeroinitializer) + return svld1_f16(pg, base); +} + +svfloat32_t test_svld1_f32(svbool_t pg, const float32_t *base) +{ + // CHECK-LABEL: test_svld1_f32 + // CHECK: @llvm.masked.load.nxv4f32.p0nxv4f32(* %{{.*}}, i32 1, %{{.*}}, zeroinitializer) + return svld1_f32(pg, base); +} + +svfloat64_t test_svld1_f64(svbool_t pg, const float64_t *base) +{ + // CHECK-LABEL: test_svld1_f64 + // CHECK: @llvm.masked.load.nxv2f64.p0nxv2f64(* %{{.*}}, i32 1, %{{.*}}, zeroinitializer) + return svld1_f64(pg, base); +} diff --git a/clang/utils/TableGen/CMakeLists.txt b/clang/utils/TableGen/CMakeLists.txt --- a/clang/utils/TableGen/CMakeLists.txt +++ b/clang/utils/TableGen/CMakeLists.txt @@ -17,6 +17,7 @@ ClangTypeNodesEmitter.cpp MveEmitter.cpp NeonEmitter.cpp + SveEmitter.cpp TableGen.cpp ) set_target_properties(clang-tblgen PROPERTIES FOLDER "Clang tablegenning") diff --git a/clang/utils/TableGen/SveEmitter.cpp b/clang/utils/TableGen/SveEmitter.cpp new file mode 100644 --- /dev/null +++ b/clang/utils/TableGen/SveEmitter.cpp @@ -0,0 +1,128 @@ +//===- SveEmitter.cpp - Generate arm_sve.h for use with clang -*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This tablegen backend is responsible for emitting arm_sve.h, which includes +// a declaration and definition of each function specified by the ARM C/C++ +// Language Extensions (ACLE). +// +// For details, visit: +// https://developer.arm.com/architectures/system-architectures/software-standards/acle +// +// Each SVE instruction is implemented in terms of 1 or more functions which +// are suffixed with the element type of the input vectors. Functions may be +// implemented in terms of generic vector operations such as +, *, -, etc. or +// by calling a __builtin_-prefixed function which will be handled by clang's +// CodeGen library. +// +// See also the documentation in include/clang/Basic/arm_sve.td. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/TableGen/Record.h" +#include "llvm/TableGen/Error.h" +#include +#include +#include +#include + +using namespace llvm; + +//===----------------------------------------------------------------------===// +// SVEEmitter +//===----------------------------------------------------------------------===// + +namespace { + +class SVEEmitter { +private: + RecordKeeper &Records; + +public: + SVEEmitter(RecordKeeper &R) : Records(R) {} + + // run - Emit arm_sve.h + void run(raw_ostream &o); +}; + +} // end anonymous namespace + + +//===----------------------------------------------------------------------===// +// SVEEmitter implementation +//===----------------------------------------------------------------------===// + +void SVEEmitter::run(raw_ostream &OS) { + OS << "/*===---- arm_sve.h - ARM SVE intrinsics " + "-----------------------------------===\n" + " *\n" + " *\n" + " * Part of the LLVM Project, under the Apache License v2.0 with LLVM " + "Exceptions.\n" + " * See https://llvm.org/LICENSE.txt for license information.\n" + " * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n" + " *\n" + " *===-----------------------------------------------------------------" + "------===\n" + " */\n\n"; + + OS << "#ifndef __ARM_SVE_H\n"; + OS << "#define __ARM_SVE_H\n\n"; + + OS << "#if !defined(__ARM_FEATURE_SVE)\n"; + OS << "#error \"SVE support not enabled\"\n"; + OS << "#else\n\n"; + + OS << "#include \n\n"; + OS << "#ifndef __cplusplus\n"; + OS << "#include \n"; + OS << "#endif\n\n"; + + OS << "typedef __fp16 float16_t;\n"; + OS << "typedef float float32_t;\n"; + OS << "typedef double float64_t;\n"; + OS << "typedef bool bool_t;\n\n"; + + OS << "typedef __SVInt8_t svint8_t;\n"; + OS << "typedef __SVInt16_t svint16_t;\n"; + OS << "typedef __SVInt32_t svint32_t;\n"; + OS << "typedef __SVInt64_t svint64_t;\n"; + OS << "typedef __SVUint8_t svuint8_t;\n"; + OS << "typedef __SVUint16_t svuint16_t;\n"; + OS << "typedef __SVUint32_t svuint32_t;\n"; + OS << "typedef __SVUint64_t svuint64_t;\n"; + OS << "typedef __SVFloat16_t svfloat16_t;\n"; + OS << "typedef __SVFloat32_t svfloat32_t;\n"; + OS << "typedef __SVFloat64_t svfloat64_t;\n"; + OS << "typedef __SVBool_t svbool_t;\n\n"; + + OS << "#define svld1_u8(...) __builtin_sve_svld1_u8(__VA_ARGS__)\n"; + OS << "#define svld1_u16(...) __builtin_sve_svld1_u16(__VA_ARGS__)\n"; + OS << "#define svld1_u32(...) __builtin_sve_svld1_u32(__VA_ARGS__)\n"; + OS << "#define svld1_u64(...) __builtin_sve_svld1_u64(__VA_ARGS__)\n"; + OS << "#define svld1_s8(...) __builtin_sve_svld1_s8(__VA_ARGS__)\n"; + OS << "#define svld1_s16(...) __builtin_sve_svld1_s16(__VA_ARGS__)\n"; + OS << "#define svld1_s32(...) __builtin_sve_svld1_s32(__VA_ARGS__)\n"; + OS << "#define svld1_s64(...) __builtin_sve_svld1_s64(__VA_ARGS__)\n"; + OS << "#define svld1_f16(...) __builtin_sve_svld1_f16(__VA_ARGS__)\n"; + OS << "#define svld1_f32(...) __builtin_sve_svld1_f32(__VA_ARGS__)\n"; + OS << "#define svld1_f64(...) __builtin_sve_svld1_f64(__VA_ARGS__)\n"; + + OS << "#endif /*__ARM_FEATURE_SVE */\n"; + OS << "#endif /* __ARM_SVE_H */\n"; +} + +namespace clang { +void EmitSveHeader(RecordKeeper &Records, raw_ostream &OS) { + SVEEmitter(Records).run(OS); +} + +} // End namespace clang diff --git a/clang/utils/TableGen/TableGen.cpp b/clang/utils/TableGen/TableGen.cpp --- a/clang/utils/TableGen/TableGen.cpp +++ b/clang/utils/TableGen/TableGen.cpp @@ -70,6 +70,7 @@ GenArmMveBuiltinSema, GenArmMveBuiltinCG, GenArmMveBuiltinAliases, + GenArmSveHeader, GenArmCdeHeader, GenArmCdeBuiltinDef, GenArmCdeBuiltinSema, @@ -185,6 +186,8 @@ "Generate ARM NEON sema support for clang"), clEnumValN(GenArmNeonTest, "gen-arm-neon-test", "Generate ARM NEON tests for clang"), + clEnumValN(GenArmSveHeader, "gen-arm-sve-header", + "Generate arm_sve.h for clang"), clEnumValN(GenArmMveHeader, "gen-arm-mve-header", "Generate arm_mve.h for clang"), clEnumValN(GenArmMveBuiltinDef, "gen-arm-mve-builtin-def", @@ -366,6 +369,9 @@ case GenArmMveBuiltinAliases: EmitMveBuiltinAliases(Records, OS); break; + case GenArmSveHeader: + EmitSveHeader(Records, OS); + break; case GenArmCdeHeader: EmitCdeHeader(Records, OS); break; diff --git a/clang/utils/TableGen/TableGenBackends.h b/clang/utils/TableGen/TableGenBackends.h --- a/clang/utils/TableGen/TableGenBackends.h +++ b/clang/utils/TableGen/TableGenBackends.h @@ -91,6 +91,8 @@ void EmitNeonSema2(llvm::RecordKeeper &Records, llvm::raw_ostream &OS); void EmitNeonTest2(llvm::RecordKeeper &Records, llvm::raw_ostream &OS); +void EmitSveHeader(llvm::RecordKeeper &Records, llvm::raw_ostream &OS); + void EmitMveHeader(llvm::RecordKeeper &Records, llvm::raw_ostream &OS); void EmitMveBuiltinDef(llvm::RecordKeeper &Records, llvm::raw_ostream &OS); void EmitMveBuiltinSema(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);