Add Neon VCVT instructions for f32 <-> f16 conversions.
authorBob Wilson <bob.wilson@apple.com>
Wed, 15 Dec 2010 22:14:12 +0000 (22:14 +0000)
committerBob Wilson <bob.wilson@apple.com>
Wed, 15 Dec 2010 22:14:12 +0000 (22:14 +0000)
Clang is now providing intrinsics for these and so we need to support them
in the backend.  Radar 8068427.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@121902 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/IntrinsicsARM.td
lib/Target/ARM/ARM.td
lib/Target/ARM/ARMInstrInfo.td
lib/Target/ARM/ARMInstrNEON.td
test/CodeGen/ARM/vcvt.ll
test/MC/ARM/neon-convert-encoding.s
test/MC/ARM/neont2-convert-encoding.s

index 6c047718e6f67fedbe9522ef06271f4072b40a7c..546538a57abdb3eeb77dc897b78b27d9d7fc0ad2 100644 (file)
@@ -286,6 +286,12 @@ def int_arm_neon_vcvtfp2fxu : Neon_CvtFPToFx_Intrinsic;
 def int_arm_neon_vcvtfxs2fp : Neon_CvtFxToFP_Intrinsic;
 def int_arm_neon_vcvtfxu2fp : Neon_CvtFxToFP_Intrinsic;
 
+// Vector Conversions Between Half-Precision and Single-Precision.
+def int_arm_neon_vcvtfp2hf
+    : Intrinsic<[llvm_v4i16_ty], [llvm_v4f32_ty], [IntrNoMem]>;
+def int_arm_neon_vcvthf2fp
+    : Intrinsic<[llvm_v4f32_ty], [llvm_v4i16_ty], [IntrNoMem]>;
+
 // Narrowing Saturating Vector Moves.
 def int_arm_neon_vqmovns : Neon_1Arg_Narrow_Intrinsic;
 def int_arm_neon_vqmovnu : Neon_1Arg_Narrow_Intrinsic;
index 5b4371611dd82499a8416de49cf742e4f7376092..bf4315fc6c3e93ba606eb3f9081f4b8de4c12fb5 100644 (file)
@@ -103,7 +103,8 @@ def ProcA8      : SubtargetFeature<"a8", "ARMProcFamily", "CortexA8",
                                     FeatureHasSlowFPVMLx, FeatureT2XtPk]>;
 def ProcA9      : SubtargetFeature<"a9", "ARMProcFamily", "CortexA9",
                                    "Cortex-A9 ARM processors",
-                                   [FeatureHasSlowFPVMLx, FeatureT2XtPk]>;
+                                   [FeatureHasSlowFPVMLx, FeatureT2XtPk,
+                                    FeatureFP16]>;
 
 class ProcNoItin<string Name, list<SubtargetFeature> Features>
  : Processor<Name, GenericItineraries, Features>;
index 71948e1b641cefce64bafbb709c1c0c6b3f5791c..1686b80792dea974137fa40dad45cb993b396dab 100644 (file)
@@ -156,6 +156,7 @@ def NoVFP            : Predicate<"!Subtarget->hasVFP2()">;
 def HasVFP2          : Predicate<"Subtarget->hasVFP2()">, AssemblerPredicate;
 def HasVFP3          : Predicate<"Subtarget->hasVFP3()">, AssemblerPredicate;
 def HasNEON          : Predicate<"Subtarget->hasNEON()">, AssemblerPredicate;
+def HasFP16          : Predicate<"Subtarget->hasFP16()">, AssemblerPredicate;
 def HasDivide        : Predicate<"Subtarget->hasDivide()">, AssemblerPredicate;
 def HasT2ExtractPack : Predicate<"Subtarget->hasT2ExtractPack()">,
                                  AssemblerPredicate;
index b95e02fbf9f415168fcc9964f9b8d8b91d70b35a..e27a4a8911618d5dfc20142eabedd609c3d36a87 100644 (file)
@@ -1724,6 +1724,15 @@ class N2VL<bits<2> op24_23, bits<2> op21_20, bits<2> op19_18,
         (ins DPR:$Vm), itin, OpcodeStr, Dt, "$Vd, $Vm", "",
         [(set QPR:$Vd, (TyQ (OpNode (TyD DPR:$Vm))))]>;
 
+// Long 2-register intrinsics.
+class N2VLInt<bits<2> op24_23, bits<2> op21_20, bits<2> op19_18,
+              bits<2> op17_16, bits<5> op11_7, bit op6, bit op4,
+              InstrItinClass itin, string OpcodeStr, string Dt,
+              ValueType TyQ, ValueType TyD, Intrinsic IntOp>
+  : N2V<op24_23, op21_20, op19_18, op17_16, op11_7, op6, op4, (outs QPR:$Vd),
+        (ins DPR:$Vm), itin, OpcodeStr, Dt, "$Vd, $Vm", "",
+        [(set QPR:$Vd, (TyQ (IntOp (TyD DPR:$Vm))))]>;
+
 // 2-register shuffles (VTRN/VZIP/VUZP), both double- and quad-register.
 class N2VDShuffle<bits<2> op19_18, bits<5> op11_7, string OpcodeStr, string Dt>
   : N2V<0b11, 0b11, op19_18, 0b10, op11_7, 0, 0, (outs DPR:$Vd, DPR:$Vm),
@@ -4447,6 +4456,16 @@ def VCVTxs2fq : N2VCvtQ<0, 1, 0b1110, 0, 1, "vcvt", "f32.s32",
 def VCVTxu2fq : N2VCvtQ<1, 1, 0b1110, 0, 1, "vcvt", "f32.u32",
                         v4f32, v4i32, int_arm_neon_vcvtfxu2fp>;
 
+//   VCVT     : Vector Convert Between Half-Precision and Single-Precision.
+def  VCVTf2h  : N2VNInt<0b11, 0b11, 0b01, 0b10, 0b01100, 0, 0,
+                        IIC_VUNAQ, "vcvt", "f16.f32",
+                        v4i16, v4f32, int_arm_neon_vcvtfp2hf>,
+                Requires<[HasNEON, HasFP16]>;
+def  VCVTh2f  : N2VLInt<0b11, 0b11, 0b01, 0b10, 0b01110, 0, 0,
+                        IIC_VUNAQ, "vcvt", "f32.f16",
+                        v4f32, v4i16, int_arm_neon_vcvthf2fp>,
+                Requires<[HasNEON, HasFP16]>;
+
 // Vector Reverse.
 
 //   VREV64   : Vector Reverse elements within 64-bit doublewords
index f4cc5368d9aaa5766378bec554db2ab9ac29fbf7..c078f493094bea3bbb08e804b0fd2f2b32f9932e 100644 (file)
@@ -1,4 +1,4 @@
-; RUN: llc < %s -march=arm -mattr=+neon | FileCheck %s
+; RUN: llc < %s -march=arm -mattr=+neon,+fp16 | FileCheck %s
 
 define <2 x i32> @vcvt_f32tos32(<2 x float>* %A) nounwind {
 ;CHECK: vcvt_f32tos32:
@@ -138,3 +138,21 @@ declare <4 x i32> @llvm.arm.neon.vcvtfp2fxu.v4i32.v4f32(<4 x float>, i32) nounwi
 declare <4 x float> @llvm.arm.neon.vcvtfxs2fp.v4f32.v4i32(<4 x i32>, i32) nounwind readnone
 declare <4 x float> @llvm.arm.neon.vcvtfxu2fp.v4f32.v4i32(<4 x i32>, i32) nounwind readnone
 
+define <4 x float> @vcvt_f16tof32(<4 x i16>* %A) nounwind {
+;CHECK: vcvt_f16tof32:
+;CHECK: vcvt.f32.f16
+       %tmp1 = load <4 x i16>* %A
+       %tmp2 = call <4 x float> @llvm.arm.neon.vcvthf2fp(<4 x i16> %tmp1)
+       ret <4 x float> %tmp2
+}
+
+define <4 x i16> @vcvt_f32tof16(<4 x float>* %A) nounwind {
+;CHECK: vcvt_f32tof16:
+;CHECK: vcvt.f16.f32
+       %tmp1 = load <4 x float>* %A
+       %tmp2 = call <4 x i16> @llvm.arm.neon.vcvtfp2hf(<4 x float> %tmp1)
+       ret <4 x i16> %tmp2
+}
+
+declare <4 x float> @llvm.arm.neon.vcvthf2fp(<4 x i16>) nounwind readnone
+declare <4 x i16> @llvm.arm.neon.vcvtfp2hf(<4 x float>) nounwind readnone
index fdd1d033f3206744f5cafeccf7f7729273d7b59f..1733c5222bee5711889848ae5579d6fe994ff6d7 100644 (file)
@@ -1,4 +1,4 @@
-@ RUN: llvm-mc -mcpu=cortex-a8 -triple arm-unknown-unknown -show-encoding < %s | FileCheck %s
+@ RUN: llvm-mc -mcpu=cortex-a9 -triple arm-unknown-unknown -show-encoding < %s | FileCheck %s
 
 @ CHECK: vcvt.s32.f32  d16, d16        @ encoding: [0x20,0x07,0xfb,0xf3]
        vcvt.s32.f32    d16, d16
@@ -32,3 +32,7 @@
        vcvt.f32.s32    q8, q8, #1
 @ CHECK: vcvt.f32.u32  q8, q8, #1      @ encoding: [0x70,0x0e,0xff,0xf3]
        vcvt.f32.u32    q8, q8, #1
+@ CHECK: vcvt.f32.f16  q8, d16         @ encoding: [0x20,0x07,0xf6,0xf3]
+       vcvt.f32.f16    q8, d16
+@ CHECK: vcvt.f16.f32  d16, q8         @ encoding: [0x20,0x06,0xf6,0xf3]
+       vcvt.f16.f32    d16, q8
index 1dbd42a3946c45fb43ebccc02f8bf3b4e828eeae..1df3b43f305fc30a75f97de528a22a7ae55bbbf9 100644 (file)
@@ -1,4 +1,4 @@
-@ RUN: llvm-mc -mcpu=cortex-a8 -triple thumb-unknown-unknown -show-encoding < %s | FileCheck %s
+@ RUN: llvm-mc -mcpu=cortex-a9 -triple thumb-unknown-unknown -show-encoding < %s | FileCheck %s
 
 .code 16
 
@@ -34,3 +34,7 @@
        vcvt.f32.s32    q8, q8, #1
 @ CHECK: vcvt.f32.u32  q8, q8, #1      @ encoding: [0xff,0xff,0x70,0x0e]
        vcvt.f32.u32    q8, q8, #1
+@ CHECK: vcvt.f32.f16  q8, d16         @ encoding: [0xf6,0xff,0x20,0x07]
+       vcvt.f32.f16    q8, d16
+@ CHECK: vcvt.f16.f32  d16, q8         @ encoding: [0xf6,0xff,0x20,0x06]
+       vcvt.f16.f32    d16, q8