From: Tim Northover Date: Tue, 25 Feb 2014 11:13:42 +0000 (+0000) Subject: ARM NEON: add _f16 support to a couple of vector-shuffling intrinsics. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=fb7e000aa81db25ced208e290b6221f9e56f11c1;p=clang ARM NEON: add _f16 support to a couple of vector-shuffling intrinsics. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@202137 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/arm_neon.td b/include/clang/Basic/arm_neon.td index eab3b50e38..b1ae1db0f6 100644 --- a/include/clang/Basic/arm_neon.td +++ b/include/clang/Basic/arm_neon.td @@ -410,9 +410,11 @@ def VCREATE : NoTestOpInst<"vcreate", "dl", "csihfUcUsUiUlPcPsl", OP_CAST>; // E.3.19 Set all lanes to same value let InstName = "vmov" in { def VDUP_N : WOpInst<"vdup_n", "ds", - "UcUsUicsiPcPsfQUcQUsQUiQcQsQiQPcQPsQflUlQlQUl", OP_DUP>; + "UcUsUicsiPcPshfQUcQUsQUiQcQsQiQPcQPsQhQflUlQlQUl", + OP_DUP>; def VMOV_N : WOpInst<"vmov_n", "ds", - "UcUsUicsiPcPsfQUcQUsQUiQcQsQiQPcQPsQflUlQlQUl", OP_DUP>; + "UcUsUicsiPcPshfQUcQUsQUiQcQsQiQPcQPsQhQflUlQlQUl", + OP_DUP>; } let InstName = "" in def VDUP_LANE: WOpInst<"vdup_lane", "dgi", diff --git a/test/CodeGen/arm_neon_intrinsics.c b/test/CodeGen/arm_neon_intrinsics.c index 1d76e8a575..d7473ed2bc 100644 --- a/test/CodeGen/arm_neon_intrinsics.c +++ b/test/CodeGen/arm_neon_intrinsics.c @@ -1887,6 +1887,12 @@ poly16x4_t test_vdup_n_p16(poly16_t a) { return vdup_n_p16(a); } +// CHECK: test_vdup_n_f16 +// CHECK: vdup.16 +float16x4_t test_vdup_n_f16(float16_t *a) { + return vdup_n_f16(*a); +} + // CHECK: test_vdup_n_f32 // CHECK: vmov float32x2_t test_vdup_n_f32(float32_t a) { @@ -1941,6 +1947,12 @@ poly16x8_t test_vdupq_n_p16(poly16_t a) { return vdupq_n_p16(a); } +// CHECK: test_vdupq_n_f16 +// CHECK: vdup.16 +float16x8_t test_vdupq_n_f16(float16_t *a) { + return vdupq_n_f16(*a); +} + // CHECK: test_vdupq_n_f32 // CHECK: vmov float32x4_t test_vdupq_n_f32(float32_t a) { @@ -4868,6 +4880,12 @@ poly16x4_t test_vmov_n_p16(poly16_t a) { return vmov_n_p16(a); } +// CHECK: test_vmov_n_f16 +// CHECK: vdup.16 +float16x4_t test_vmov_n_f16(float16_t *a) { + return vmov_n_f16(*a); +} + // CHECK: test_vmov_n_f32 // CHECK: vmov float32x2_t test_vmov_n_f32(float32_t a) { @@ -4922,6 +4940,12 @@ poly16x8_t test_vmovq_n_p16(poly16_t a) { return vmovq_n_p16(a); } +// CHECK: test_vmovq_n_f16 +// CHECK: vdup.16 +float16x8_t test_vmovq_n_f16(float16_t *a) { + return vmovq_n_f16(*a); +} + // CHECK: test_vmovq_n_f32 // CHECK: vmov float32x4_t test_vmovq_n_f32(float32_t a) { diff --git a/utils/TableGen/NeonEmitter.cpp b/utils/TableGen/NeonEmitter.cpp index 932af9a8e8..165e749b33 100644 --- a/utils/TableGen/NeonEmitter.cpp +++ b/utils/TableGen/NeonEmitter.cpp @@ -1436,7 +1436,7 @@ static void GenerateChecksForIntrinsic(const std::string &Name, /// UseMacro - Examine the prototype string to determine if the intrinsic /// should be defined as a preprocessor macro instead of an inline function. -static bool UseMacro(const std::string &proto) { +static bool UseMacro(const std::string &proto, StringRef typestr) { // If this builtin takes an immediate argument, we need to #define it rather // than use a standard declaration, so that SemaChecking can range check // the immediate passed by the user. @@ -1449,6 +1449,12 @@ static bool UseMacro(const std::string &proto) { proto.find('c') != std::string::npos) return true; + // It is not permitted to pass or return an __fp16 by value, so intrinsics + // taking a scalar float16_t must be implemented as macros. + if (typestr.find('h') != std::string::npos && + proto.find('s') != std::string::npos) + return true; + return false; } @@ -1463,7 +1469,7 @@ static bool MacroArgUsedDirectly(const std::string &proto, unsigned i) { // Generate the string "(argtype a, argtype b, ...)" static std::string GenArgs(const std::string &proto, StringRef typestr, const std::string &name) { - bool define = UseMacro(proto); + bool define = UseMacro(proto, typestr); char arg = 'a'; std::string s; @@ -1642,7 +1648,7 @@ static std::string GenOpString(const std::string &name, OpKind op, const std::string &proto, StringRef typestr) { bool quad; unsigned nElts = GetNumElements(typestr, quad); - bool define = UseMacro(proto); + bool define = UseMacro(proto, typestr); std::string ts = TypeString(proto[0], typestr); std::string s; @@ -2386,7 +2392,7 @@ static std::string GenBuiltin(const std::string &name, const std::string &proto, // sret-like argument. bool sret = IsMultiVecProto(proto[0]); - bool define = UseMacro(proto); + bool define = UseMacro(proto, typestr); // Check if the prototype has a scalar operand with the type of the vector // elements. If not, bitcasting the args will take care of arg checking. @@ -2531,7 +2537,7 @@ static std::string GenIntrinsic(const std::string &name, StringRef outTypeStr, StringRef inTypeStr, OpKind kind, ClassKind classKind) { assert(!proto.empty() && ""); - bool define = UseMacro(proto) && kind != OpUnavailable; + bool define = UseMacro(proto, outTypeStr) && kind != OpUnavailable; std::string s; // static always inline + return type