[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
diff --git a/include/clang/Basic/arm_neon.td b/include/clang/Basic/arm_neon.td
index fa97e82..32bca46 100644
--- a/include/clang/Basic/arm_neon.td
+++ b/include/clang/Basic/arm_neon.td
@@ -179,6 +179,7 @@
 // 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_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 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 // 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 f892d12..5ced543 100644
--- a/lib/CodeGen/CGBuiltin.cpp
+++ b/lib/CodeGen/CGBuiltin.cpp
@@ -2384,6 +2384,20 @@
   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 6cc6a69..c59b6ec 100644
--- a/test/CodeGen/aarch64-neon-intrinsics.c
+++ b/test/CodeGen/aarch64-neon-intrinsics.c
@@ -7750,24 +7750,48 @@
 
 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 95daa39..4fd94a9 100644
--- a/utils/TableGen/NeonEmitter.cpp
+++ b/utils/TableGen/NeonEmitter.cpp
@@ -468,6 +468,8 @@
       if (type == 'd')
         type = 'l';
       break;
+    case '$':
+      scal = true;
     case 'x':
       usgn = false;
       poly = false;
@@ -2547,8 +2549,10 @@
               "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 = " +