forked from OSchip/llvm-project
Teach the AArch64 backend to handle f16
This allows the AArch64 backend to handle fadd, fsub, fmul and fdiv operations on f16 (half-precision) types by promoting to f32. llvm-svn: 215891
This commit is contained in:
parent
12993dd916
commit
f5469bec97
|
@ -4264,6 +4264,9 @@ void SelectionDAGLegalize::PromoteNode(SDNode *Node) {
|
|||
Tmp1, Tmp2, Node->getOperand(2)));
|
||||
break;
|
||||
}
|
||||
case ISD::FADD:
|
||||
case ISD::FSUB:
|
||||
case ISD::FMUL:
|
||||
case ISD::FDIV:
|
||||
case ISD::FREM:
|
||||
case ISD::FPOW: {
|
||||
|
|
|
@ -278,6 +278,15 @@ AArch64TargetLowering::AArch64TargetLowering(TargetMachine &TM)
|
|||
setOperationAction(ISD::FCOPYSIGN, MVT::f64, Custom);
|
||||
setOperationAction(ISD::FCOPYSIGN, MVT::f32, Custom);
|
||||
|
||||
// f16 is storage-only, so we promote operations to f32 if we know this is
|
||||
// valid, and ignore them otherwise. The operations not mentioned here will
|
||||
// fail to select, but this is not a major problem as no source language
|
||||
// should be emitting native f16 operations yet.
|
||||
setOperationAction(ISD::FADD, MVT::f16, Promote);
|
||||
setOperationAction(ISD::FDIV, MVT::f16, Promote);
|
||||
setOperationAction(ISD::FMUL, MVT::f16, Promote);
|
||||
setOperationAction(ISD::FSUB, MVT::f16, Promote);
|
||||
|
||||
// AArch64 has implementations of a lot of rounding-like FP operations.
|
||||
static MVT RoundingTypes[] = { MVT::f32, MVT::f64};
|
||||
for (unsigned I = 0; I < array_lengthof(RoundingTypes); ++I) {
|
||||
|
|
|
@ -0,0 +1,109 @@
|
|||
; RUN: llc < %s -mtriple=aarch64-none-eabi | FileCheck %s
|
||||
|
||||
define half @add_h(half %a, half %b) {
|
||||
entry:
|
||||
; CHECK-LABEL: add_h:
|
||||
; CHECK: fcvt
|
||||
; CHECK: fcvt
|
||||
; CHECK: fadd
|
||||
; CHECK: fcvt
|
||||
%0 = fadd half %a, %b
|
||||
ret half %0
|
||||
}
|
||||
|
||||
|
||||
define half @sub_h(half %a, half %b) {
|
||||
entry:
|
||||
; CHECK-LABEL: sub_h:
|
||||
; CHECK: fcvt
|
||||
; CHECK: fcvt
|
||||
; CHECK: fsub
|
||||
; CHECK: fcvt
|
||||
%0 = fsub half %a, %b
|
||||
ret half %0
|
||||
}
|
||||
|
||||
|
||||
define half @mul_h(half %a, half %b) {
|
||||
entry:
|
||||
; CHECK-LABEL: mul_h:
|
||||
; CHECK: fcvt
|
||||
; CHECK: fcvt
|
||||
; CHECK: fmul
|
||||
; CHECK: fcvt
|
||||
%0 = fmul half %a, %b
|
||||
ret half %0
|
||||
}
|
||||
|
||||
|
||||
define half @div_h(half %a, half %b) {
|
||||
entry:
|
||||
; CHECK-LABEL: div_h:
|
||||
; CHECK: fcvt
|
||||
; CHECK: fcvt
|
||||
; CHECK: fdiv
|
||||
; CHECK: fcvt
|
||||
%0 = fdiv half %a, %b
|
||||
ret half %0
|
||||
}
|
||||
|
||||
|
||||
define half @load_h(half* %a) {
|
||||
entry:
|
||||
; CHECK-LABEL: load_h:
|
||||
; CHECK: ldr h
|
||||
%0 = load half* %a, align 4
|
||||
ret half %0
|
||||
}
|
||||
|
||||
|
||||
define void @store_h(half* %a, half %b) {
|
||||
entry:
|
||||
; CHECK-LABEL: store_h:
|
||||
; CHECK: str h
|
||||
store half %b, half* %a, align 4
|
||||
ret void
|
||||
}
|
||||
|
||||
define half @s_to_h(float %a) {
|
||||
; CHECK-LABEL: s_to_h:
|
||||
; CHECK: fcvt
|
||||
%1 = fptrunc float %a to half
|
||||
ret half %1
|
||||
}
|
||||
|
||||
define half @d_to_h(double %a) {
|
||||
; CHECK-LABEL: d_to_h:
|
||||
; CHECK: fcvt
|
||||
%1 = fptrunc double %a to half
|
||||
ret half %1
|
||||
}
|
||||
|
||||
define float @h_to_s(half %a) {
|
||||
; CHECK-LABEL: h_to_s:
|
||||
; CHECK: fcvt
|
||||
%1 = fpext half %a to float
|
||||
ret float %1
|
||||
}
|
||||
|
||||
define double @h_to_d(half %a) {
|
||||
; CHECK-LABEL: h_to_d:
|
||||
; CHECK: fcvt
|
||||
%1 = fpext half %a to double
|
||||
ret double %1
|
||||
}
|
||||
|
||||
define half @bitcast_i_to_h(i16 %a) {
|
||||
; CHECK-LABEL: bitcast_i_to_h:
|
||||
; CHECK: fmov
|
||||
%1 = bitcast i16 %a to half
|
||||
ret half %1
|
||||
}
|
||||
|
||||
|
||||
define i16 @bitcast_h_to_i(half %a) {
|
||||
; CHECK-LABEL: bitcast_h_to_i:
|
||||
; CHECK: fmov
|
||||
%1 = bitcast half %a to i16
|
||||
ret i16 %1
|
||||
}
|
Loading…
Reference in New Issue