mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-11-02 07:11:49 +00:00
AArch64: implement efficient f16 bitcasts
Because i16 is illegal, there's no native DAG method to represent a bitcast to or from an f16 type. This meant LLVM was inserting a stack store/load pair which is really not ideal. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@213378 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
b41b1d4bac
commit
e72ff8829e
@ -317,6 +317,10 @@ AArch64TargetLowering::AArch64TargetLowering(TargetMachine &TM)
|
|||||||
setTruncStoreAction(MVT::f128, MVT::f64, Expand);
|
setTruncStoreAction(MVT::f128, MVT::f64, Expand);
|
||||||
setTruncStoreAction(MVT::f128, MVT::f32, Expand);
|
setTruncStoreAction(MVT::f128, MVT::f32, Expand);
|
||||||
setTruncStoreAction(MVT::f128, MVT::f16, Expand);
|
setTruncStoreAction(MVT::f128, MVT::f16, Expand);
|
||||||
|
|
||||||
|
setOperationAction(ISD::BITCAST, MVT::i16, Custom);
|
||||||
|
setOperationAction(ISD::BITCAST, MVT::f16, Custom);
|
||||||
|
|
||||||
// Indexed loads and stores are supported.
|
// Indexed loads and stores are supported.
|
||||||
for (unsigned im = (unsigned)ISD::PRE_INC;
|
for (unsigned im = (unsigned)ISD::PRE_INC;
|
||||||
im != (unsigned)ISD::LAST_INDEXED_MODE; ++im) {
|
im != (unsigned)ISD::LAST_INDEXED_MODE; ++im) {
|
||||||
@ -1510,12 +1514,30 @@ SDValue AArch64TargetLowering::LowerFSINCOS(SDValue Op,
|
|||||||
return CallResult.first;
|
return CallResult.first;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static SDValue LowerBITCAST(SDValue Op, SelectionDAG &DAG) {
|
||||||
|
if (Op.getValueType() != MVT::f16)
|
||||||
|
return SDValue();
|
||||||
|
|
||||||
|
assert(Op.getOperand(0).getValueType() == MVT::i16);
|
||||||
|
SDLoc DL(Op);
|
||||||
|
|
||||||
|
Op = DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i32, Op.getOperand(0));
|
||||||
|
Op = DAG.getNode(ISD::BITCAST, DL, MVT::f32, Op);
|
||||||
|
return SDValue(
|
||||||
|
DAG.getMachineNode(TargetOpcode::EXTRACT_SUBREG, DL, MVT::f16, Op,
|
||||||
|
DAG.getTargetConstant(AArch64::hsub, MVT::i32)),
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
SDValue AArch64TargetLowering::LowerOperation(SDValue Op,
|
SDValue AArch64TargetLowering::LowerOperation(SDValue Op,
|
||||||
SelectionDAG &DAG) const {
|
SelectionDAG &DAG) const {
|
||||||
switch (Op.getOpcode()) {
|
switch (Op.getOpcode()) {
|
||||||
default:
|
default:
|
||||||
llvm_unreachable("unimplemented operand");
|
llvm_unreachable("unimplemented operand");
|
||||||
return SDValue();
|
return SDValue();
|
||||||
|
case ISD::BITCAST:
|
||||||
|
return LowerBITCAST(Op, DAG);
|
||||||
case ISD::GlobalAddress:
|
case ISD::GlobalAddress:
|
||||||
return LowerGlobalAddress(Op, DAG);
|
return LowerGlobalAddress(Op, DAG);
|
||||||
case ISD::GlobalTLSAddress:
|
case ISD::GlobalTLSAddress:
|
||||||
@ -7942,11 +7964,32 @@ bool AArch64TargetLowering::getPostIndexedAddressParts(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ReplaceBITCASTResults(SDNode *N, SmallVectorImpl<SDValue> &Results,
|
||||||
|
SelectionDAG &DAG) {
|
||||||
|
if (N->getValueType(0) != MVT::i16)
|
||||||
|
return;
|
||||||
|
|
||||||
|
SDLoc DL(N);
|
||||||
|
SDValue Op = N->getOperand(0);
|
||||||
|
assert(Op.getValueType() == MVT::f16 &&
|
||||||
|
"Inconsistent bitcast? Only 16-bit types should be i16 or f16");
|
||||||
|
Op = SDValue(
|
||||||
|
DAG.getMachineNode(TargetOpcode::INSERT_SUBREG, DL, MVT::f32,
|
||||||
|
DAG.getUNDEF(MVT::i32), Op,
|
||||||
|
DAG.getTargetConstant(AArch64::hsub, MVT::i32)),
|
||||||
|
0);
|
||||||
|
Op = DAG.getNode(ISD::BITCAST, DL, MVT::i32, Op);
|
||||||
|
Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, MVT::i16, Op));
|
||||||
|
}
|
||||||
|
|
||||||
void AArch64TargetLowering::ReplaceNodeResults(
|
void AArch64TargetLowering::ReplaceNodeResults(
|
||||||
SDNode *N, SmallVectorImpl<SDValue> &Results, SelectionDAG &DAG) const {
|
SDNode *N, SmallVectorImpl<SDValue> &Results, SelectionDAG &DAG) const {
|
||||||
switch (N->getOpcode()) {
|
switch (N->getOpcode()) {
|
||||||
default:
|
default:
|
||||||
llvm_unreachable("Don't know how to custom expand this");
|
llvm_unreachable("Don't know how to custom expand this");
|
||||||
|
case ISD::BITCAST:
|
||||||
|
ReplaceBITCASTResults(N, Results, DAG);
|
||||||
|
return;
|
||||||
case ISD::FP_TO_UINT:
|
case ISD::FP_TO_UINT:
|
||||||
case ISD::FP_TO_SINT:
|
case ISD::FP_TO_SINT:
|
||||||
assert(N->getValueType(0) == MVT::i128 && "unexpected illegal conversion");
|
assert(N->getValueType(0) == MVT::i128 && "unexpected illegal conversion");
|
||||||
|
@ -17,6 +17,16 @@ define i16 @test_bitcast_from_half(half* %addr) {
|
|||||||
ret i16 %val_int
|
ret i16 %val_int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
define i16 @test_reg_bitcast_from_half(half %in) {
|
||||||
|
; CHECK-LABEL: test_reg_bitcast_from_half:
|
||||||
|
; CHECK-NOT: str
|
||||||
|
; CHECK-NOT: ldr
|
||||||
|
; CHECK-DAG: fmov w0, s0
|
||||||
|
; CHECK: ret
|
||||||
|
%val = bitcast half %in to i16
|
||||||
|
ret i16 %val
|
||||||
|
}
|
||||||
|
|
||||||
define void @test_bitcast_to_half(half* %addr, i16 %in) {
|
define void @test_bitcast_to_half(half* %addr, i16 %in) {
|
||||||
; CHECK-LABEL: test_bitcast_to_half:
|
; CHECK-LABEL: test_bitcast_to_half:
|
||||||
; CHECK: strh w1, [x0]
|
; CHECK: strh w1, [x0]
|
||||||
@ -25,6 +35,17 @@ define void @test_bitcast_to_half(half* %addr, i16 %in) {
|
|||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
define half @test_reg_bitcast_to_half(i16 %in) {
|
||||||
|
; CHECK-LABEL: test_reg_bitcast_to_half:
|
||||||
|
; CHECK-NOT: str
|
||||||
|
; CHECK-NOT: ldr
|
||||||
|
; CHECK-DAG: fmov s0, w0
|
||||||
|
; CHECK: ret
|
||||||
|
|
||||||
|
%val = bitcast i16 %in to half
|
||||||
|
ret half %val
|
||||||
|
}
|
||||||
|
|
||||||
define float @test_extend32(half* %addr) {
|
define float @test_extend32(half* %addr) {
|
||||||
; CHECK-LABEL: test_extend32:
|
; CHECK-LABEL: test_extend32:
|
||||||
; CHECK: fcvt {{s[0-9]+}}, {{h[0-9]+}}
|
; CHECK: fcvt {{s[0-9]+}}, {{h[0-9]+}}
|
||||||
|
Loading…
Reference in New Issue
Block a user