Skip to content

Commit

Permalink
[SveEmitter] Add SVE tuple types and builtins for svundef.
Browse files Browse the repository at this point in the history
This patch adds new SVE types to Clang that describe tuples of SVE
vectors. For example `svint32x2_t` which maps to the twice-as-wide
vector `<vscale x 8 x i32>`. Similarly, `svint32x3_t` will map to
`<vscale x 12 x i32>`.

It also adds builtins to return an `undef` vector for a given
SVE type.

Reviewers: c-rhodes, david-arm, ctetreau, efriedma, rengolin

Reviewed By: c-rhodes

Tags: #clang

Differential Revision: https://reviews.llvm.org/D81459
  • Loading branch information
sdesmalen-arm committed Jun 15, 2020
1 parent ca2dcbd commit 91a4a59
Show file tree
Hide file tree
Showing 10 changed files with 499 additions and 39 deletions.
51 changes: 51 additions & 0 deletions clang/include/clang/Basic/AArch64SVEACLETypes.def
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,57 @@ 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)

//
// x2
//
SVE_VECTOR_TYPE("__SVInt8x2_t", SveInt8x2, SveInt8x2Ty, 32, 8, true, false)
SVE_VECTOR_TYPE("__SVInt16x2_t", SveInt16x2, SveInt16x2Ty, 16, 16, true, false)
SVE_VECTOR_TYPE("__SVInt32x2_t", SveInt32x2, SveInt32x2Ty, 8, 32, true, false)
SVE_VECTOR_TYPE("__SVInt64x2_t", SveInt64x2, SveInt64x2Ty, 4, 64, true, false)

SVE_VECTOR_TYPE("__SVUint8x2_t", SveUint8x2, SveUint8x2Ty, 32, 8, false, false)
SVE_VECTOR_TYPE("__SVUint16x2_t", SveUint16x2, SveUint16x2Ty, 16, 16, false, false)
SVE_VECTOR_TYPE("__SVUint32x2_t", SveUint32x2, SveUint32x2Ty, 8, 32, false, false)
SVE_VECTOR_TYPE("__SVUint64x2_t", SveUint64x2, SveUint64x2Ty, 4, 64, false, false)

SVE_VECTOR_TYPE("__SVFloat16x2_t", SveFloat16x2, SveFloat16x2Ty, 16, 16, true, true)
SVE_VECTOR_TYPE("__SVFloat32x2_t", SveFloat32x2, SveFloat32x2Ty, 8, 32, true, true)
SVE_VECTOR_TYPE("__SVFloat64x2_t", SveFloat64x2, SveFloat64x2Ty, 4, 64, true, true)

//
// x3
//
SVE_VECTOR_TYPE("__SVInt8x3_t", SveInt8x3, SveInt8x3Ty, 48, 8, true, false)
SVE_VECTOR_TYPE("__SVInt16x3_t", SveInt16x3, SveInt16x3Ty, 24, 16, true, false)
SVE_VECTOR_TYPE("__SVInt32x3_t", SveInt32x3, SveInt32x3Ty, 12, 32, true, false)
SVE_VECTOR_TYPE("__SVInt64x3_t", SveInt64x3, SveInt64x3Ty, 6, 64, true, false)

SVE_VECTOR_TYPE("__SVUint8x3_t", SveUint8x3, SveUint8x3Ty, 48, 8, false, false)
SVE_VECTOR_TYPE("__SVUint16x3_t", SveUint16x3, SveUint16x3Ty, 24, 16, false, false)
SVE_VECTOR_TYPE("__SVUint32x3_t", SveUint32x3, SveUint32x3Ty, 12, 32, false, false)
SVE_VECTOR_TYPE("__SVUint64x3_t", SveUint64x3, SveUint64x3Ty, 6, 64, false, false)

SVE_VECTOR_TYPE("__SVFloat16x3_t", SveFloat16x3, SveFloat16x3Ty, 24, 16, true, true)
SVE_VECTOR_TYPE("__SVFloat32x3_t", SveFloat32x3, SveFloat32x3Ty, 12, 32, true, true)
SVE_VECTOR_TYPE("__SVFloat64x3_t", SveFloat64x3, SveFloat64x3Ty, 6, 64, true, true)

//
// x4
//
SVE_VECTOR_TYPE("__SVInt8x4_t", SveInt8x4, SveInt8x4Ty, 64, 8, true, false)
SVE_VECTOR_TYPE("__SVInt16x4_t", SveInt16x4, SveInt16x4Ty, 32, 16, true, false)
SVE_VECTOR_TYPE("__SVInt32x4_t", SveInt32x4, SveInt32x4Ty, 16, 32, true, false)
SVE_VECTOR_TYPE("__SVInt64x4_t", SveInt64x4, SveInt64x4Ty, 8, 64, true, false)

SVE_VECTOR_TYPE("__SVUint8x4_t", SveUint8x4, SveUint8x4Ty, 64, 8, false, false)
SVE_VECTOR_TYPE("__SVUint16x4_t", SveUint16x4, SveUint16x4Ty, 32, 16, false, false)
SVE_VECTOR_TYPE("__SVUint32x4_t", SveUint32x4, SveUint32x4Ty, 16, 32, false, false)
SVE_VECTOR_TYPE("__SVUint64x4_t", SveUint64x4, SveUint64x4Ty, 8, 64, false, false)

SVE_VECTOR_TYPE("__SVFloat16x4_t", SveFloat16x4, SveFloat16x4Ty, 32, 16, true, true)
SVE_VECTOR_TYPE("__SVFloat32x4_t", SveFloat32x4, SveFloat32x4Ty, 16, 32, true, true)
SVE_VECTOR_TYPE("__SVFloat64x4_t", SveFloat64x4, SveFloat64x4Ty, 8, 64, true, true)

SVE_PREDICATE_TYPE("__SVBool_t", SveBool, SveBoolTy, 16)

#undef SVE_VECTOR_TYPE
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Basic/TargetBuiltins.h
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ namespace clang {
bool isInsertOp1SVALL() const { return Flags & IsInsertOp1SVALL; }
bool isGatherPrefetch() const { return Flags & IsGatherPrefetch; }
bool isReverseUSDOT() const { return Flags & ReverseUSDOT; }
bool isUndef() const { return Flags & IsUndef; }

uint64_t getBits() const { return Flags; }
bool isFlagSet(uint64_t Flag) const { return Flags & Flag; }
Expand Down
8 changes: 8 additions & 0 deletions clang/include/clang/Basic/arm_sve.td
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
// -------------------
// prototype: return (arg, arg, ...)
//
// 2,3,4: array of default vectors
// v: void
// x: vector of signed integers
// u: vector of unsigned integers
Expand Down Expand Up @@ -198,6 +199,7 @@ def IsPrefetch : FlagType<0x08000000>; // Contiguous prefetches.
def IsGatherPrefetch : FlagType<0x10000000>;
def ReverseCompare : FlagType<0x20000000>; // Compare operands must be swapped.
def ReverseUSDOT : FlagType<0x40000000>; // Unsigned/signed operands must be swapped.
def IsUndef : FlagType<0x80000000>; // Codegen `undef` of given type.

// These must be kept in sync with the flags in include/clang/Basic/TargetBuiltins.h
class ImmCheckType<int val> {
Expand Down Expand Up @@ -1264,6 +1266,12 @@ let ArchGuard = "defined(__ARM_FEATURE_SVE_MATMUL_FP64)" in {
def SVMLLA_F64 : SInst<"svmmla[_f64]", "dddd","d", MergeNone, "aarch64_sve_fmmla">;
}

////////////////////////////////////////////////////////////////////////////////
// Vector creation
def SVUNDEF_1 : SInst<"svundef_{d}", "d", "csilUcUsUiUlhfd", MergeNone, "", [IsUndef]>;
def SVUNDEF_2 : SInst<"svundef2_{d}", "2", "csilUcUsUiUlhfd", MergeNone, "", [IsUndef]>;
def SVUNDEF_3 : SInst<"svundef3_{d}", "3", "csilUcUsUiUlhfd", MergeNone, "", [IsUndef]>;
def SVUNDEF_4 : SInst<"svundef4_{d}", "4", "csilUcUsUiUlhfd", MergeNone, "", [IsUndef]>;

////////////////////////////////////////////////////////////////////////////////
// SVE2 WhileGE/GT
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/CodeGen/CGBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8036,6 +8036,8 @@ Value *CodeGenFunction::EmitAArch64SVEBuiltinExpr(unsigned BuiltinID,
return EmitSVEPrefetchLoad(TypeFlags, Ops, Builtin->LLVMIntrinsic);
else if (TypeFlags.isGatherPrefetch())
return EmitSVEGatherPrefetch(TypeFlags, Ops, Builtin->LLVMIntrinsic);
else if (TypeFlags.isUndef())
return UndefValue::get(Ty);
else if (Builtin->LLVMIntrinsic != 0) {
if (TypeFlags.getMergeType() == SVETypeFlags::MergeZeroExp)
InsertExplicitZeroOperand(Builder, Ty, Ops);
Expand Down
101 changes: 74 additions & 27 deletions clang/lib/CodeGen/CodeGenTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -533,44 +533,91 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) {
case BuiltinType::OCLReserveID:
ResultType = CGM.getOpenCLRuntime().convertOpenCLSpecificType(Ty);
break;
#define GET_SVE_INT_VEC(BITS, ELTS) \
llvm::ScalableVectorType::get( \
llvm::IntegerType::get(getLLVMContext(), BITS), ELTS);
case BuiltinType::SveInt8:
case BuiltinType::SveUint8:
return llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 8),
{16, true});
return GET_SVE_INT_VEC(8, 16);
case BuiltinType::SveInt8x2:
case BuiltinType::SveUint8x2:
return GET_SVE_INT_VEC(8, 32);
case BuiltinType::SveInt8x3:
case BuiltinType::SveUint8x3:
return GET_SVE_INT_VEC(8, 48);
case BuiltinType::SveInt8x4:
case BuiltinType::SveUint8x4:
return GET_SVE_INT_VEC(8, 64);
case BuiltinType::SveInt16:
case BuiltinType::SveUint16:
return llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 16),
{8, true});
return GET_SVE_INT_VEC(16, 8);
case BuiltinType::SveInt16x2:
case BuiltinType::SveUint16x2:
return GET_SVE_INT_VEC(16, 16);
case BuiltinType::SveInt16x3:
case BuiltinType::SveUint16x3:
return GET_SVE_INT_VEC(16, 24);
case BuiltinType::SveInt16x4:
case BuiltinType::SveUint16x4:
return GET_SVE_INT_VEC(16, 32);
case BuiltinType::SveInt32:
case BuiltinType::SveUint32:
return llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 32),
{4, true});
return GET_SVE_INT_VEC(32, 4);
case BuiltinType::SveInt32x2:
case BuiltinType::SveUint32x2:
return GET_SVE_INT_VEC(32, 8);
case BuiltinType::SveInt32x3:
case BuiltinType::SveUint32x3:
return GET_SVE_INT_VEC(32, 12);
case BuiltinType::SveInt32x4:
case BuiltinType::SveUint32x4:
return GET_SVE_INT_VEC(32, 16);
case BuiltinType::SveInt64:
case BuiltinType::SveUint64:
return llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 64),
{2, true});
return GET_SVE_INT_VEC(64, 2);
case BuiltinType::SveInt64x2:
case BuiltinType::SveUint64x2:
return GET_SVE_INT_VEC(64, 4);
case BuiltinType::SveInt64x3:
case BuiltinType::SveUint64x3:
return GET_SVE_INT_VEC(64, 6);
case BuiltinType::SveInt64x4:
case BuiltinType::SveUint64x4:
return GET_SVE_INT_VEC(64, 8);
case BuiltinType::SveBool:
return GET_SVE_INT_VEC(1, 16);
#undef GET_SVE_INT_VEC
#define GET_SVE_FP_VEC(TY, ISFP16, ELTS) \
llvm::ScalableVectorType::get( \
getTypeForFormat(getLLVMContext(), \
Context.getFloatTypeSemantics(Context.TY), \
/* UseNativeHalf = */ ISFP16), \
ELTS);
case BuiltinType::SveFloat16:
return llvm::VectorType::get(
getTypeForFormat(getLLVMContext(),
Context.getFloatTypeSemantics(Context.HalfTy),
/* UseNativeHalf = */ true),
{8, true});
return GET_SVE_FP_VEC(HalfTy, true, 8);
case BuiltinType::SveFloat16x2:
return GET_SVE_FP_VEC(HalfTy, true, 16);
case BuiltinType::SveFloat16x3:
return GET_SVE_FP_VEC(HalfTy, true, 24);
case BuiltinType::SveFloat16x4:
return GET_SVE_FP_VEC(HalfTy, true, 32);
case BuiltinType::SveFloat32:
return llvm::VectorType::get(
getTypeForFormat(getLLVMContext(),
Context.getFloatTypeSemantics(Context.FloatTy),
/* UseNativeHalf = */ false),
{4, true});
return GET_SVE_FP_VEC(FloatTy, false, 4);
case BuiltinType::SveFloat32x2:
return GET_SVE_FP_VEC(FloatTy, false, 8);
case BuiltinType::SveFloat32x3:
return GET_SVE_FP_VEC(FloatTy, false, 12);
case BuiltinType::SveFloat32x4:
return GET_SVE_FP_VEC(FloatTy, false, 16);
case BuiltinType::SveFloat64:
return llvm::VectorType::get(
getTypeForFormat(getLLVMContext(),
Context.getFloatTypeSemantics(Context.DoubleTy),
/* UseNativeHalf = */ false),
{2, true});
case BuiltinType::SveBool:
return llvm::VectorType::get(llvm::IntegerType::get(getLLVMContext(), 1),
{16, true});
break;
return GET_SVE_FP_VEC(DoubleTy, false, 2);
case BuiltinType::SveFloat64x2:
return GET_SVE_FP_VEC(DoubleTy, false, 4);
case BuiltinType::SveFloat64x3:
return GET_SVE_FP_VEC(DoubleTy, false, 6);
case BuiltinType::SveFloat64x4:
return GET_SVE_FP_VEC(DoubleTy, false, 8);
#undef GET_SVE_FP_VEC
case BuiltinType::Dependent:
#define BUILTIN_TYPE(Id, SingletonId)
#define PLACEHOLDER_TYPE(Id, SingletonId) \
Expand Down
80 changes: 80 additions & 0 deletions clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_undef.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// 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

#include <arm_sve.h>

svint8_t test_svundef_s8()
{
// CHECK-LABEL: test_svundef_s8
// CHECK: ret <vscale x 16 x i8> undef
return svundef_s8();
}

svint16_t test_svundef_s16()
{
// CHECK-LABEL: test_svundef_s16
// CHECK: ret <vscale x 8 x i16> undef
return svundef_s16();
}

svint32_t test_svundef_s32()
{
// CHECK-LABEL: test_svundef_s32
// CHECK: ret <vscale x 4 x i32> undef
return svundef_s32();
}

svint64_t test_svundef_s64()
{
// CHECK-LABEL: test_svundef_s64
// CHECK: ret <vscale x 2 x i64> undef
return svundef_s64();
}

svuint8_t test_svundef_u8()
{
// CHECK-LABEL: test_svundef_u8
// CHECK: ret <vscale x 16 x i8> undef
return svundef_u8();
}

svuint16_t test_svundef_u16()
{
// CHECK-LABEL: test_svundef_u16
// CHECK: ret <vscale x 8 x i16> undef
return svundef_u16();
}

svuint32_t test_svundef_u32()
{
// CHECK-LABEL: test_svundef_u32
// CHECK: ret <vscale x 4 x i32> undef
return svundef_u32();
}

svuint64_t test_svundef_u64()
{
// CHECK-LABEL: test_svundef_u64
// CHECK: ret <vscale x 2 x i64> undef
return svundef_u64();
}

svfloat16_t test_svundef_f16()
{
// CHECK-LABEL: test_svundef_f16
// CHECK: ret <vscale x 8 x half> undef
return svundef_f16();
}

svfloat32_t test_svundef_f32()
{
// CHECK-LABEL: test_svundef_f32
// CHECK: ret <vscale x 4 x float> undef
return svundef_f32();
}

svfloat64_t test_svundef_f64()
{
// CHECK-LABEL: test_svundef_f64
// CHECK: ret <vscale x 2 x double> undef
return svundef_f64();
}
80 changes: 80 additions & 0 deletions clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_undef2.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -triple aarch64-none-linux-gnu -target-feature +sve -fallow-half-arguments-and-returns -S -O2 -Werror -Wall -emit-llvm -o - %s | FileCheck %s

#include <arm_sve.h>

svint8x2_t test_svundef2_s8()
{
// CHECK-LABEL: test_svundef2_s8
// CHECK: ret <vscale x 32 x i8> undef
return svundef2_s8();
}

svint16x2_t test_svundef2_s16()
{
// CHECK-LABEL: test_svundef2_s16
// CHECK: ret <vscale x 16 x i16> undef
return svundef2_s16();
}

svint32x2_t test_svundef2_s32()
{
// CHECK-LABEL: test_svundef2_s32
// CHECK: ret <vscale x 8 x i32> undef
return svundef2_s32();
}

svint64x2_t test_svundef2_s64()
{
// CHECK-LABEL: test_svundef2_s64
// CHECK: ret <vscale x 4 x i64> undef
return svundef2_s64();
}

svuint8x2_t test_svundef2_u8()
{
// CHECK-LABEL: test_svundef2_u8
// CHECK: ret <vscale x 32 x i8> undef
return svundef2_u8();
}

svuint16x2_t test_svundef2_u16()
{
// CHECK-LABEL: test_svundef2_u16
// CHECK: ret <vscale x 16 x i16> undef
return svundef2_u16();
}

svuint32x2_t test_svundef2_u32()
{
// CHECK-LABEL: test_svundef2_u32
// CHECK: ret <vscale x 8 x i32> undef
return svundef2_u32();
}

svuint64x2_t test_svundef2_u64()
{
// CHECK-LABEL: test_svundef2_u64
// CHECK: ret <vscale x 4 x i64> undef
return svundef2_u64();
}

svfloat16x2_t test_svundef2_f16()
{
// CHECK-LABEL: test_svundef2_f16
// CHECK: ret <vscale x 16 x half> undef
return svundef2_f16();
}

svfloat32x2_t test_svundef2_f32()
{
// CHECK-LABEL: test_svundef2_f32
// CHECK: ret <vscale x 8 x float> undef
return svundef2_f32();
}

svfloat64x2_t test_svundef2_f64()
{
// CHECK-LABEL: test_svundef2_f64
// CHECK: ret <vscale x 4 x double> undef
return svundef2_f64();
}
Loading

0 comments on commit 91a4a59

Please sign in to comment.