diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -6886,7 +6886,18 @@ bool RISCVTargetLowering::splitValueIntoRegisterParts( SelectionDAG &DAG, const SDLoc &DL, SDValue Val, SDValue *Parts, unsigned NumParts, MVT PartVT, Optional CC) const { + bool IsABIRegCopy = CC.hasValue(); EVT ValueVT = Val.getValueType(); + if (IsABIRegCopy && ValueVT == MVT::f16 && PartVT == MVT::f32) { + unsigned ValueBits = ValueVT.getSizeInBits(); + unsigned PartBits = PartVT.getSizeInBits(); + Val = DAG.getNode(ISD::BITCAST, DL, MVT::getIntegerVT(ValueBits), Val); + Val = DAG.getNode(ISD::ANY_EXTEND, DL, MVT::getIntegerVT(PartBits), Val); + Val = DAG.getNode(ISD::BITCAST, DL, PartVT, Val); + Parts[0] = Val; + return true; + } + if (ValueVT.isScalableVector() && PartVT.isScalableVector()) { LLVMContext &Context = *DAG.getContext(); EVT ValueEltVT = ValueVT.getVectorElementType(); @@ -6915,6 +6926,17 @@ SDValue RISCVTargetLowering::joinRegisterPartsIntoValue( SelectionDAG &DAG, const SDLoc &DL, const SDValue *Parts, unsigned NumParts, MVT PartVT, EVT ValueVT, Optional CC) const { + bool IsABIRegCopy = CC.hasValue(); + if (IsABIRegCopy && ValueVT == MVT::f16 && PartVT == MVT::f32) { + unsigned ValueBits = ValueVT.getSizeInBits(); + unsigned PartBits = PartVT.getSizeInBits(); + SDValue Val = Parts[0]; + + Val = DAG.getNode(ISD::BITCAST, DL, MVT::getIntegerVT(PartBits), Val); + Val = DAG.getNode(ISD::TRUNCATE, DL, MVT::getIntegerVT(ValueBits), Val); + Val = DAG.getNode(ISD::BITCAST, DL, ValueVT, Val); + return Val; + } if (ValueVT.isScalableVector() && PartVT.isScalableVector()) { LLVMContext &Context = *DAG.getContext(); SDValue Val = Parts[0]; diff --git a/llvm/test/CodeGen/RISCV/copysign-casts.ll b/llvm/test/CodeGen/RISCV/copysign-casts.ll --- a/llvm/test/CodeGen/RISCV/copysign-casts.ll +++ b/llvm/test/CodeGen/RISCV/copysign-casts.ll @@ -124,22 +124,42 @@ ; RV32IF: # %bb.0: ; RV32IF-NEXT: fmv.x.w a2, fa0 ; RV32IF-NEXT: lui a3, 524288 -; RV32IF-NEXT: and a2, a2, a3 ; RV32IF-NEXT: addi a3, a3, -1 ; RV32IF-NEXT: and a1, a1, a3 +; RV32IF-NEXT: lui a3, 8 +; RV32IF-NEXT: and a2, a2, a3 +; RV32IF-NEXT: slli a2, a2, 16 ; RV32IF-NEXT: or a1, a1, a2 ; RV32IF-NEXT: ret ; ; RV32IFD-LABEL: fold_promote_d_h: ; RV32IFD: # %bb.0: -; RV32IFD-NEXT: fcvt.d.s ft0, fa1 -; RV32IFD-NEXT: fsgnj.d fa0, fa0, ft0 +; RV32IFD-NEXT: addi sp, sp, -16 +; RV32IFD-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32IFD-NEXT: fsd fs0, 0(sp) # 8-byte Folded Spill +; RV32IFD-NEXT: fmv.d fs0, fa0 +; RV32IFD-NEXT: fmv.x.w a0, fa1 +; RV32IFD-NEXT: call __gnu_h2f_ieee@plt +; RV32IFD-NEXT: fcvt.d.s ft0, fa0 +; RV32IFD-NEXT: fsgnj.d fa0, fs0, ft0 +; RV32IFD-NEXT: fld fs0, 0(sp) # 8-byte Folded Reload +; RV32IFD-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32IFD-NEXT: addi sp, sp, 16 ; RV32IFD-NEXT: ret ; ; RV64IFD-LABEL: fold_promote_d_h: ; RV64IFD: # %bb.0: -; RV64IFD-NEXT: fcvt.d.s ft0, fa1 -; RV64IFD-NEXT: fsgnj.d fa0, fa0, ft0 +; RV64IFD-NEXT: addi sp, sp, -16 +; RV64IFD-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; RV64IFD-NEXT: fsd fs0, 0(sp) # 8-byte Folded Spill +; RV64IFD-NEXT: fmv.d fs0, fa0 +; RV64IFD-NEXT: fmv.x.w a0, fa1 +; RV64IFD-NEXT: call __gnu_h2f_ieee@plt +; RV64IFD-NEXT: fcvt.d.s ft0, fa0 +; RV64IFD-NEXT: fsgnj.d fa0, fs0, ft0 +; RV64IFD-NEXT: fld fs0, 0(sp) # 8-byte Folded Reload +; RV64IFD-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; RV64IFD-NEXT: addi sp, sp, 16 ; RV64IFD-NEXT: ret ; ; RV32IFZFH-LABEL: fold_promote_d_h: @@ -195,17 +215,44 @@ ; ; RV32IF-LABEL: fold_promote_f_h: ; RV32IF: # %bb.0: -; RV32IF-NEXT: fsgnj.s fa0, fa0, fa1 +; RV32IF-NEXT: addi sp, sp, -16 +; RV32IF-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32IF-NEXT: fsw fs0, 8(sp) # 4-byte Folded Spill +; RV32IF-NEXT: fmv.s fs0, fa0 +; RV32IF-NEXT: fmv.x.w a0, fa1 +; RV32IF-NEXT: call __gnu_h2f_ieee@plt +; RV32IF-NEXT: fsgnj.s fa0, fs0, fa0 +; RV32IF-NEXT: flw fs0, 8(sp) # 4-byte Folded Reload +; RV32IF-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32IF-NEXT: addi sp, sp, 16 ; RV32IF-NEXT: ret ; ; RV32IFD-LABEL: fold_promote_f_h: ; RV32IFD: # %bb.0: -; RV32IFD-NEXT: fsgnj.s fa0, fa0, fa1 +; RV32IFD-NEXT: addi sp, sp, -16 +; RV32IFD-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32IFD-NEXT: fsd fs0, 0(sp) # 8-byte Folded Spill +; RV32IFD-NEXT: fmv.s fs0, fa0 +; RV32IFD-NEXT: fmv.x.w a0, fa1 +; RV32IFD-NEXT: call __gnu_h2f_ieee@plt +; RV32IFD-NEXT: fsgnj.s fa0, fs0, fa0 +; RV32IFD-NEXT: fld fs0, 0(sp) # 8-byte Folded Reload +; RV32IFD-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32IFD-NEXT: addi sp, sp, 16 ; RV32IFD-NEXT: ret ; ; RV64IFD-LABEL: fold_promote_f_h: ; RV64IFD: # %bb.0: -; RV64IFD-NEXT: fsgnj.s fa0, fa0, fa1 +; RV64IFD-NEXT: addi sp, sp, -16 +; RV64IFD-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; RV64IFD-NEXT: fsd fs0, 0(sp) # 8-byte Folded Spill +; RV64IFD-NEXT: fmv.s fs0, fa0 +; RV64IFD-NEXT: fmv.x.w a0, fa1 +; RV64IFD-NEXT: call __gnu_h2f_ieee@plt +; RV64IFD-NEXT: fsgnj.s fa0, fs0, fa0 +; RV64IFD-NEXT: fld fs0, 0(sp) # 8-byte Folded Reload +; RV64IFD-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; RV64IFD-NEXT: addi sp, sp, 16 ; RV64IFD-NEXT: ret ; ; RV32IFZFH-LABEL: fold_promote_f_h: @@ -341,9 +388,11 @@ ; RV32IF-NEXT: sw ra, 12(sp) # 4-byte Folded Spill ; RV32IF-NEXT: fsw fs0, 8(sp) # 4-byte Folded Spill ; RV32IF-NEXT: fmv.s fs0, fa1 -; RV32IF-NEXT: call __gnu_f2h_ieee@plt +; RV32IF-NEXT: fmv.x.w a0, fa0 ; RV32IF-NEXT: call __gnu_h2f_ieee@plt ; RV32IF-NEXT: fsgnj.s fa0, fa0, fs0 +; RV32IF-NEXT: call __gnu_f2h_ieee@plt +; RV32IF-NEXT: fmv.w.x fa0, a0 ; RV32IF-NEXT: flw fs0, 8(sp) # 4-byte Folded Reload ; RV32IF-NEXT: lw ra, 12(sp) # 4-byte Folded Reload ; RV32IF-NEXT: addi sp, sp, 16 @@ -355,9 +404,11 @@ ; RV32IFD-NEXT: sw ra, 12(sp) # 4-byte Folded Spill ; RV32IFD-NEXT: fsd fs0, 0(sp) # 8-byte Folded Spill ; RV32IFD-NEXT: fmv.s fs0, fa1 -; RV32IFD-NEXT: call __gnu_f2h_ieee@plt +; RV32IFD-NEXT: fmv.x.w a0, fa0 ; RV32IFD-NEXT: call __gnu_h2f_ieee@plt ; RV32IFD-NEXT: fsgnj.s fa0, fa0, fs0 +; RV32IFD-NEXT: call __gnu_f2h_ieee@plt +; RV32IFD-NEXT: fmv.w.x fa0, a0 ; RV32IFD-NEXT: fld fs0, 0(sp) # 8-byte Folded Reload ; RV32IFD-NEXT: lw ra, 12(sp) # 4-byte Folded Reload ; RV32IFD-NEXT: addi sp, sp, 16 @@ -369,9 +420,11 @@ ; RV64IFD-NEXT: sd ra, 8(sp) # 8-byte Folded Spill ; RV64IFD-NEXT: fsd fs0, 0(sp) # 8-byte Folded Spill ; RV64IFD-NEXT: fmv.s fs0, fa1 -; RV64IFD-NEXT: call __gnu_f2h_ieee@plt +; RV64IFD-NEXT: fmv.x.w a0, fa0 ; RV64IFD-NEXT: call __gnu_h2f_ieee@plt ; RV64IFD-NEXT: fsgnj.s fa0, fa0, fs0 +; RV64IFD-NEXT: call __gnu_f2h_ieee@plt +; RV64IFD-NEXT: fmv.w.x fa0, a0 ; RV64IFD-NEXT: fld fs0, 0(sp) # 8-byte Folded Reload ; RV64IFD-NEXT: ld ra, 8(sp) # 8-byte Folded Reload ; RV64IFD-NEXT: addi sp, sp, 16 @@ -451,10 +504,12 @@ ; RV32IF-NEXT: sw ra, 12(sp) # 4-byte Folded Spill ; RV32IF-NEXT: sw s0, 8(sp) # 4-byte Folded Spill ; RV32IF-NEXT: mv s0, a1 -; RV32IF-NEXT: call __gnu_f2h_ieee@plt +; RV32IF-NEXT: fmv.x.w a0, fa0 ; RV32IF-NEXT: call __gnu_h2f_ieee@plt ; RV32IF-NEXT: fmv.w.x ft0, s0 ; RV32IF-NEXT: fsgnj.s fa0, fa0, ft0 +; RV32IF-NEXT: call __gnu_f2h_ieee@plt +; RV32IF-NEXT: fmv.w.x fa0, a0 ; RV32IF-NEXT: lw s0, 8(sp) # 4-byte Folded Reload ; RV32IF-NEXT: lw ra, 12(sp) # 4-byte Folded Reload ; RV32IF-NEXT: addi sp, sp, 16 @@ -466,10 +521,12 @@ ; RV32IFD-NEXT: sw ra, 12(sp) # 4-byte Folded Spill ; RV32IFD-NEXT: fsd fs0, 0(sp) # 8-byte Folded Spill ; RV32IFD-NEXT: fmv.d fs0, fa1 -; RV32IFD-NEXT: call __gnu_f2h_ieee@plt +; RV32IFD-NEXT: fmv.x.w a0, fa0 ; RV32IFD-NEXT: call __gnu_h2f_ieee@plt ; RV32IFD-NEXT: fcvt.s.d ft0, fs0 ; RV32IFD-NEXT: fsgnj.s fa0, fa0, ft0 +; RV32IFD-NEXT: call __gnu_f2h_ieee@plt +; RV32IFD-NEXT: fmv.w.x fa0, a0 ; RV32IFD-NEXT: fld fs0, 0(sp) # 8-byte Folded Reload ; RV32IFD-NEXT: lw ra, 12(sp) # 4-byte Folded Reload ; RV32IFD-NEXT: addi sp, sp, 16 @@ -481,10 +538,12 @@ ; RV64IFD-NEXT: sd ra, 8(sp) # 8-byte Folded Spill ; RV64IFD-NEXT: fsd fs0, 0(sp) # 8-byte Folded Spill ; RV64IFD-NEXT: fmv.d fs0, fa1 -; RV64IFD-NEXT: call __gnu_f2h_ieee@plt +; RV64IFD-NEXT: fmv.x.w a0, fa0 ; RV64IFD-NEXT: call __gnu_h2f_ieee@plt ; RV64IFD-NEXT: fcvt.s.d ft0, fs0 ; RV64IFD-NEXT: fsgnj.s fa0, fa0, ft0 +; RV64IFD-NEXT: call __gnu_f2h_ieee@plt +; RV64IFD-NEXT: fmv.w.x fa0, a0 ; RV64IFD-NEXT: fld fs0, 0(sp) # 8-byte Folded Reload ; RV64IFD-NEXT: ld ra, 8(sp) # 8-byte Folded Reload ; RV64IFD-NEXT: addi sp, sp, 16