Skip to content

Commit 9464f9a

Browse files
toppercmemfrob
authored andcommitted
[RISCV] Pass 'half' in the lower 16 bits of an f32 value when F extension is enabled, but Zfh is not.
Without Zfh the half type isn't legal, but it could still be used as an argument/return in IR. Clang will not generate this today. Previously we promoted the half value to float for arguments and returns if the F extension is enabled but Zfh isn't. Then depending on which ABI is enabled we would pass it in either an FPR or a GPR in float format. If the F extension isn't enabled, it would get passed in the lower 16 bits of a GPR in half format. With this patch the value will always in half format and will be in the lower bits of a GPR or FPR. This should be consistent with where the bits are located when Zfh is enabled. I've based this implementation off of how this is done on ARM. I've manually nan-boxed the value to 32 bits using integer ops. It looks like flw, fsw, fmv.s, fmv.w.x, fmf.x.w won't canonicalize nans so should leave the value alone. I think those are the instructions that could get used on this value. Reviewed By: kito-cheng Differential Revision: https://reviews.llvm.org/D98670
1 parent c36c444 commit 9464f9a

File tree

3 files changed

+637
-14
lines changed

3 files changed

+637
-14
lines changed

llvm/lib/Target/RISCV/RISCVISelLowering.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7383,7 +7383,20 @@ bool RISCVTargetLowering::allowsMisalignedMemoryAccesses(
73837383
bool RISCVTargetLowering::splitValueIntoRegisterParts(
73847384
SelectionDAG &DAG, const SDLoc &DL, SDValue Val, SDValue *Parts,
73857385
unsigned NumParts, MVT PartVT, Optional<CallingConv::ID> CC) const {
7386+
bool IsABIRegCopy = CC.hasValue();
73867387
EVT ValueVT = Val.getValueType();
7388+
if (IsABIRegCopy && ValueVT == MVT::f16 && PartVT == MVT::f32) {
7389+
// Cast the f16 to i16, extend to i32, pad with ones to make a float nan,
7390+
// and cast to f32.
7391+
Val = DAG.getNode(ISD::BITCAST, DL, MVT::i16, Val);
7392+
Val = DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i32, Val);
7393+
Val = DAG.getNode(ISD::OR, DL, MVT::i32, Val,
7394+
DAG.getConstant(0xFFFF0000, DL, MVT::i32));
7395+
Val = DAG.getNode(ISD::BITCAST, DL, MVT::f32, Val);
7396+
Parts[0] = Val;
7397+
return true;
7398+
}
7399+
73877400
if (ValueVT.isScalableVector() && PartVT.isScalableVector()) {
73887401
LLVMContext &Context = *DAG.getContext();
73897402
EVT ValueEltVT = ValueVT.getVectorElementType();
@@ -7412,6 +7425,17 @@ bool RISCVTargetLowering::splitValueIntoRegisterParts(
74127425
SDValue RISCVTargetLowering::joinRegisterPartsIntoValue(
74137426
SelectionDAG &DAG, const SDLoc &DL, const SDValue *Parts, unsigned NumParts,
74147427
MVT PartVT, EVT ValueVT, Optional<CallingConv::ID> CC) const {
7428+
bool IsABIRegCopy = CC.hasValue();
7429+
if (IsABIRegCopy && ValueVT == MVT::f16 && PartVT == MVT::f32) {
7430+
SDValue Val = Parts[0];
7431+
7432+
// Cast the f32 to i32, truncate to i16, and cast back to f16.
7433+
Val = DAG.getNode(ISD::BITCAST, DL, MVT::i32, Val);
7434+
Val = DAG.getNode(ISD::TRUNCATE, DL, MVT::i16, Val);
7435+
Val = DAG.getNode(ISD::BITCAST, DL, MVT::f16, Val);
7436+
return Val;
7437+
}
7438+
74157439
if (ValueVT.isScalableVector() && PartVT.isScalableVector()) {
74167440
LLVMContext &Context = *DAG.getContext();
74177441
SDValue Val = Parts[0];

0 commit comments

Comments
 (0)