llvm.org GIT mirror llvm / e72ff88
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 Tim Northover 6 years ago
2 changed file(s) with 64 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
316316 setTruncStoreAction(MVT::f128, MVT::f64, Expand);
317317 setTruncStoreAction(MVT::f128, MVT::f32, Expand);
318318 setTruncStoreAction(MVT::f128, MVT::f16, Expand);
319
320 setOperationAction(ISD::BITCAST, MVT::i16, Custom);
321 setOperationAction(ISD::BITCAST, MVT::f16, Custom);
322
319323 // Indexed loads and stores are supported.
320324 for (unsigned im = (unsigned)ISD::PRE_INC;
321325 im != (unsigned)ISD::LAST_INDEXED_MODE; ++im) {
15091513 return CallResult.first;
15101514 }
15111515
1516 static SDValue LowerBITCAST(SDValue Op, SelectionDAG &DAG) {
1517 if (Op.getValueType() != MVT::f16)
1518 return SDValue();
1519
1520 assert(Op.getOperand(0).getValueType() == MVT::i16);
1521 SDLoc DL(Op);
1522
1523 Op = DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i32, Op.getOperand(0));
1524 Op = DAG.getNode(ISD::BITCAST, DL, MVT::f32, Op);
1525 return SDValue(
1526 DAG.getMachineNode(TargetOpcode::EXTRACT_SUBREG, DL, MVT::f16, Op,
1527 DAG.getTargetConstant(AArch64::hsub, MVT::i32)),
1528 0);
1529 }
1530
1531
15121532 SDValue AArch64TargetLowering::LowerOperation(SDValue Op,
15131533 SelectionDAG &DAG) const {
15141534 switch (Op.getOpcode()) {
15151535 default:
15161536 llvm_unreachable("unimplemented operand");
15171537 return SDValue();
1538 case ISD::BITCAST:
1539 return LowerBITCAST(Op, DAG);
15181540 case ISD::GlobalAddress:
15191541 return LowerGlobalAddress(Op, DAG);
15201542 case ISD::GlobalTLSAddress:
79417963 return true;
79427964 }
79437965
7966 static void ReplaceBITCASTResults(SDNode *N, SmallVectorImpl &Results,
7967 SelectionDAG &DAG) {
7968 if (N->getValueType(0) != MVT::i16)
7969 return;
7970
7971 SDLoc DL(N);
7972 SDValue Op = N->getOperand(0);
7973 assert(Op.getValueType() == MVT::f16 &&
7974 "Inconsistent bitcast? Only 16-bit types should be i16 or f16");
7975 Op = SDValue(
7976 DAG.getMachineNode(TargetOpcode::INSERT_SUBREG, DL, MVT::f32,
7977 DAG.getUNDEF(MVT::i32), Op,
7978 DAG.getTargetConstant(AArch64::hsub, MVT::i32)),
7979 0);
7980 Op = DAG.getNode(ISD::BITCAST, DL, MVT::i32, Op);
7981 Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, MVT::i16, Op));
7982 }
7983
79447984 void AArch64TargetLowering::ReplaceNodeResults(
79457985 SDNode *N, SmallVectorImpl &Results, SelectionDAG &DAG) const {
79467986 switch (N->getOpcode()) {
79477987 default:
79487988 llvm_unreachable("Don't know how to custom expand this");
7989 case ISD::BITCAST:
7990 ReplaceBITCASTResults(N, Results, DAG);
7991 return;
79497992 case ISD::FP_TO_UINT:
79507993 case ISD::FP_TO_SINT:
79517994 assert(N->getValueType(0) == MVT::i128 && "unexpected illegal conversion");
1616 ret i16 %val_int
1717 }
1818
19 define i16 @test_reg_bitcast_from_half(half %in) {
20 ; CHECK-LABEL: test_reg_bitcast_from_half:
21 ; CHECK-NOT: str
22 ; CHECK-NOT: ldr
23 ; CHECK-DAG: fmov w0, s0
24 ; CHECK: ret
25 %val = bitcast half %in to i16
26 ret i16 %val
27 }
28
1929 define void @test_bitcast_to_half(half* %addr, i16 %in) {
2030 ; CHECK-LABEL: test_bitcast_to_half:
2131 ; CHECK: strh w1, [x0]
2232 %val_fp = bitcast i16 %in to half
2333 store half %val_fp, half* %addr
2434 ret void
35 }
36
37 define half @test_reg_bitcast_to_half(i16 %in) {
38 ; CHECK-LABEL: test_reg_bitcast_to_half:
39 ; CHECK-NOT: str
40 ; CHECK-NOT: ldr
41 ; CHECK-DAG: fmov s0, w0
42 ; CHECK: ret
43
44 %val = bitcast i16 %in to half
45 ret half %val
2546 }
2647
2748 define float @test_extend32(half* %addr) {