ARM NEON: add _f16 support to a couple of vector-shuffling intrinsics.

llvm-svn: 202137
This commit is contained in:
Tim Northover 2014-02-25 11:13:42 +00:00
parent 5117553301
commit 87da936164
3 changed files with 39 additions and 7 deletions

View File

@ -410,9 +410,11 @@ def VCREATE : NoTestOpInst<"vcreate", "dl", "csihfUcUsUiUlPcPsl", OP_CAST>;
// E.3.19 Set all lanes to same value // E.3.19 Set all lanes to same value
let InstName = "vmov" in { let InstName = "vmov" in {
def VDUP_N : WOpInst<"vdup_n", "ds", def VDUP_N : WOpInst<"vdup_n", "ds",
"UcUsUicsiPcPsfQUcQUsQUiQcQsQiQPcQPsQflUlQlQUl", OP_DUP>; "UcUsUicsiPcPshfQUcQUsQUiQcQsQiQPcQPsQhQflUlQlQUl",
OP_DUP>;
def VMOV_N : WOpInst<"vmov_n", "ds", def VMOV_N : WOpInst<"vmov_n", "ds",
"UcUsUicsiPcPsfQUcQUsQUiQcQsQiQPcQPsQflUlQlQUl", OP_DUP>; "UcUsUicsiPcPshfQUcQUsQUiQcQsQiQPcQPsQhQflUlQlQUl",
OP_DUP>;
} }
let InstName = "" in let InstName = "" in
def VDUP_LANE: WOpInst<"vdup_lane", "dgi", def VDUP_LANE: WOpInst<"vdup_lane", "dgi",

View File

@ -1887,6 +1887,12 @@ poly16x4_t test_vdup_n_p16(poly16_t a) {
return vdup_n_p16(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: test_vdup_n_f32
// CHECK: vmov // CHECK: vmov
float32x2_t test_vdup_n_f32(float32_t a) { 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); 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: test_vdupq_n_f32
// CHECK: vmov // CHECK: vmov
float32x4_t test_vdupq_n_f32(float32_t a) { 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); 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: test_vmov_n_f32
// CHECK: vmov // CHECK: vmov
float32x2_t test_vmov_n_f32(float32_t a) { 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); 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: test_vmovq_n_f32
// CHECK: vmov // CHECK: vmov
float32x4_t test_vmovq_n_f32(float32_t a) { float32x4_t test_vmovq_n_f32(float32_t a) {

View File

@ -1436,7 +1436,7 @@ static void GenerateChecksForIntrinsic(const std::string &Name,
/// UseMacro - Examine the prototype string to determine if the intrinsic /// UseMacro - Examine the prototype string to determine if the intrinsic
/// should be defined as a preprocessor macro instead of an inline function. /// 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 // If this builtin takes an immediate argument, we need to #define it rather
// than use a standard declaration, so that SemaChecking can range check // than use a standard declaration, so that SemaChecking can range check
// the immediate passed by the user. // the immediate passed by the user.
@ -1449,6 +1449,12 @@ static bool UseMacro(const std::string &proto) {
proto.find('c') != std::string::npos) proto.find('c') != std::string::npos)
return true; 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; return false;
} }
@ -1463,7 +1469,7 @@ static bool MacroArgUsedDirectly(const std::string &proto, unsigned i) {
// Generate the string "(argtype a, argtype b, ...)" // Generate the string "(argtype a, argtype b, ...)"
static std::string GenArgs(const std::string &proto, StringRef typestr, static std::string GenArgs(const std::string &proto, StringRef typestr,
const std::string &name) { const std::string &name) {
bool define = UseMacro(proto); bool define = UseMacro(proto, typestr);
char arg = 'a'; char arg = 'a';
std::string s; std::string s;
@ -1642,7 +1648,7 @@ static std::string GenOpString(const std::string &name, OpKind op,
const std::string &proto, StringRef typestr) { const std::string &proto, StringRef typestr) {
bool quad; bool quad;
unsigned nElts = GetNumElements(typestr, quad); unsigned nElts = GetNumElements(typestr, quad);
bool define = UseMacro(proto); bool define = UseMacro(proto, typestr);
std::string ts = TypeString(proto[0], typestr); std::string ts = TypeString(proto[0], typestr);
std::string s; std::string s;
@ -2386,7 +2392,7 @@ static std::string GenBuiltin(const std::string &name, const std::string &proto,
// sret-like argument. // sret-like argument.
bool sret = IsMultiVecProto(proto[0]); 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 // 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. // 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, StringRef outTypeStr, StringRef inTypeStr,
OpKind kind, ClassKind classKind) { OpKind kind, ClassKind classKind) {
assert(!proto.empty() && ""); assert(!proto.empty() && "");
bool define = UseMacro(proto) && kind != OpUnavailable; bool define = UseMacro(proto, outTypeStr) && kind != OpUnavailable;
std::string s; std::string s;
// static always inline + return type // static always inline + return type