Add Neon VCVT instructions for f32 <-> f16 conversions.

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
This commit is contained in:
Bob Wilson 2010-12-15 22:14:12 +00:00
parent 8d1b7e57e5
commit 0406356cd4
7 changed files with 57 additions and 4 deletions

View 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;

View 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>;

View 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;

View 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

View 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

View 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

View 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