From 9473c1945f9f1dfa143e172622f16e4264e2628b Mon Sep 17 00:00:00 2001 From: Chad Rosier Date: Mon, 11 Nov 2013 18:04:22 +0000 Subject: [PATCH] [AArch64] Add support for NEON scalar floating-point convert to fixed-point instructions. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@194395 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/arm_neon.td | 11 +++---- lib/CodeGen/CGBuiltin.cpp | 14 +++++++++ test/CodeGen/aarch64-neon-intrinsics.c | 40 ++++++++++++++++++++------ utils/TableGen/NeonEmitter.cpp | 8 ++++-- 4 files changed, 58 insertions(+), 15 deletions(-) diff --git a/include/clang/Basic/arm_neon.td b/include/clang/Basic/arm_neon.td index fa97e82766..32bca46726 100644 --- a/include/clang/Basic/arm_neon.td +++ b/include/clang/Basic/arm_neon.td @@ -179,6 +179,7 @@ class NoTestOpInst : Inst {} // r: scalar of double width element type, signed // a: scalar of element type (splat to vector type) // b: scalar of unsigned integer/long type (int/float args) +// $: scalar of signed integer/long type (int/float args) // y: scalar of float // o: scalar of double // k: default elt width, double num elts @@ -870,7 +871,6 @@ def SCALAR_SQRSHRN_N: SInst<"vqrshrn_n", "zsi", "SsSiSlSUsSUiSUl">; def SCALAR_SQSHRUN_N: SInst<"vqshrun_n", "zsi", "SsSiSl">; // Signed Saturating Rounded Shift Right Unsigned Narrow (Immediate) def SCALAR_SQRSHRUN_N: SInst<"vqrshrun_n", "zsi", "SsSiSl">; -} //////////////////////////////////////////////////////////////////////////////// // Scalar Signed/Unsigned Fixed-point Convert To Floating-Point (Immediate) @@ -879,10 +879,11 @@ def SCALAR_SCVTF_N_F64: SInst<"vcvt_n_f64", "osi", "SlSUl">; //////////////////////////////////////////////////////////////////////////////// // Scalar Floating-point Convert To Signed/Unsigned Fixed-point (Immediate) -def SCALAR_FCVTZS_N_S32 : SInst<"vcvt_n_s32", "xsi", "Sf">; -def SCALAR_FCVTZU_N_U32 : SInst<"vcvt_n_u32", "usi", "Sf">; -def SCALAR_FCVTZS_N_S64 : SInst<"vcvt_n_s64", "xsi", "Sd">; -def SCALAR_FCVTZU_N_U64 : SInst<"vcvt_n_u64", "usi", "Sd">; +def SCALAR_FCVTZS_N_S32 : SInst<"vcvt_n_s32", "$si", "Sf">; +def SCALAR_FCVTZU_N_U32 : SInst<"vcvt_n_u32", "bsi", "Sf">; +def SCALAR_FCVTZS_N_S64 : SInst<"vcvt_n_s64", "$si", "Sd">; +def SCALAR_FCVTZU_N_U64 : SInst<"vcvt_n_u64", "bsi", "Sd">; +} //////////////////////////////////////////////////////////////////////////////// // Scalar Reduce Pairwise Addition (Scalar and Floating Point) diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index f892d12372..5ced54360f 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -2384,6 +2384,20 @@ static Value *EmitAArch64ScalarBuiltinExpr(CodeGenFunction &CGF, case AArch64::BI__builtin_neon_vcvtd_n_f64_u64: Int = Intrinsic::aarch64_neon_vcvtf64_n_u64; s = "vcvtf"; OverloadInt = false; break; + // Scalar Floating-point Convert To Signed Fixed-point (Immediate) + case AArch64::BI__builtin_neon_vcvts_n_s32_f32: + Int = Intrinsic::aarch64_neon_vcvts_n_s32_f32; + s = "fcvtzs"; OverloadInt = false; break; + case AArch64::BI__builtin_neon_vcvtd_n_s64_f64: + Int = Intrinsic::aarch64_neon_vcvtd_n_s64_f64; + s = "fcvtzs"; OverloadInt = false; break; + // Scalar Floating-point Convert To Unsigned Fixed-point (Immediate) + case AArch64::BI__builtin_neon_vcvts_n_u32_f32: + Int = Intrinsic::aarch64_neon_vcvts_n_u32_f32; + s = "fcvtzu"; OverloadInt = false; break; + case AArch64::BI__builtin_neon_vcvtd_n_u64_f64: + Int = Intrinsic::aarch64_neon_vcvtd_n_u64_f64; + s = "fcvtzu"; OverloadInt = false; break; } if (!Int) diff --git a/test/CodeGen/aarch64-neon-intrinsics.c b/test/CodeGen/aarch64-neon-intrinsics.c index 6cc6a69ad1..c59b6ec94f 100644 --- a/test/CodeGen/aarch64-neon-intrinsics.c +++ b/test/CodeGen/aarch64-neon-intrinsics.c @@ -7750,24 +7750,48 @@ int32_t test_vqrshrund_n_s64(int64_t a) { float32_t test_vcvts_n_f32_s32(int32_t a) { // CHECK: test_vcvts_n_f32_s32 -// CHECK: scvtf {{s[0-9]+}}, {{s[0-9]+}}, #0 - return (float32_t)vcvts_n_f32_s32(a, 0); +// CHECK: scvtf {{s[0-9]+}}, {{s[0-9]+}}, #1 + return (float32_t)vcvts_n_f32_s32(a, 1); } float64_t test_vcvtd_n_f64_s64(int64_t a) { // CHECK: test_vcvtd_n_f64_s64 -// CHECK: scvtf {{d[0-9]+}}, {{d[0-9]+}}, #0 - return (float64_t)vcvtd_n_f64_s64(a, 0); +// CHECK: scvtf {{d[0-9]+}}, {{d[0-9]+}}, #1 + return (float64_t)vcvtd_n_f64_s64(a, 1); } float32_t test_vcvts_n_f32_u32(uint32_t a) { // CHECK: test_vcvts_n_f32_u32 -// CHECK: ucvtf {{s[0-9]+}}, {{s[0-9]+}}, #0 - return (float32_t)vcvts_n_f32_u32(a, 0); +// CHECK: ucvtf {{s[0-9]+}}, {{s[0-9]+}}, #32 + return (float32_t)vcvts_n_f32_u32(a, 32); } float64_t test_vcvtd_n_f64_u64(uint64_t a) { // CHECK: test_vcvtd_n_f64_u64 -// CHECK: ucvtf {{d[0-9]+}}, {{d[0-9]+}}, #0 - return (float64_t)vcvtd_n_f64_u64(a, 0); +// CHECK: ucvtf {{d[0-9]+}}, {{d[0-9]+}}, #64 + return (float64_t)vcvtd_n_f64_u64(a, 64); +} + +int32_t test_vcvts_n_s32_f32(float32_t a) { +// CHECK: test_vcvts_n_s32_f32 +// CHECK: fcvtzs {{s[0-9]+}}, {{s[0-9]+}}, #1 + return (int32_t)vcvts_n_s32_f32(a, 1); +} + +int64_t test_vcvtd_n_s64_f64(float64_t a) { +// CHECK: test_vcvtd_n_s64_f64 +// CHECK: fcvtzs {{d[0-9]+}}, {{d[0-9]+}}, #1 + return (int64_t)vcvtd_n_s64_f64(a, 1); +} + +uint32_t test_vcvts_n_u32_f32(float32_t a) { +// CHECK: test_vcvts_n_u32_f32 +// CHECK: fcvtzu {{s[0-9]+}}, {{s[0-9]+}}, #32 + return (uint32_t)vcvts_n_u32_f32(a, 32); +} + +uint64_t test_vcvtd_n_u64_f64(float64_t a) { +// CHECK: test_vcvtd_n_u64_f64 +// CHECK: fcvtzu {{d[0-9]+}}, {{d[0-9]+}}, #64 + return (uint64_t)vcvtd_n_u64_f64(a, 64); } diff --git a/utils/TableGen/NeonEmitter.cpp b/utils/TableGen/NeonEmitter.cpp index 95daa39cce..4fd94a982c 100644 --- a/utils/TableGen/NeonEmitter.cpp +++ b/utils/TableGen/NeonEmitter.cpp @@ -468,6 +468,8 @@ static char ModType(const char mod, char type, bool &quad, bool &poly, if (type == 'd') type = 'l'; break; + case '$': + scal = true; case 'x': usgn = false; poly = false; @@ -2547,8 +2549,10 @@ NeonEmitter::genIntrinsicRangeCheckCode(raw_ostream &OS, "Fixed point convert name should contains \"32\" or \"64\""); } else if (R->getValueAsBit("isScalarShift")) { - // Right shifts have an 'r' in the name, left shifts do not. - if (name.find('r') != std::string::npos) + // Right shifts have an 'r' in the name, left shifts do not. Convert + // instructions have the same bounds and right shifts. + if (name.find('r') != std::string::npos || + name.find("cvt") != std::string::npos) rangestr = "l = 1; "; rangestr += "u = " + -- 2.40.0