forked from OSchip/llvm-project
[RISCV64] Emit correct lib call for fp(float/double) to ui/si
Since i32 is not legal in riscv64, it always promoted to i64 before emitting lib call and for conversions like float/double to int and float/double to unsigned int wrong lib call was emitted. This commit fix it using custom lowering. Differential Revision: https://reviews.llvm.org/D80526
This commit is contained in:
parent
b2f2adee00
commit
7622ea5835
|
@ -197,6 +197,14 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
|
||||||
setTruncStoreAction(MVT::f64, MVT::f16, Expand);
|
setTruncStoreAction(MVT::f64, MVT::f16, Expand);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Subtarget.is64Bit() &&
|
||||||
|
!(Subtarget.hasStdExtD() || Subtarget.hasStdExtF())) {
|
||||||
|
setOperationAction(ISD::FP_TO_UINT, MVT::i32, Custom);
|
||||||
|
setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom);
|
||||||
|
setOperationAction(ISD::STRICT_FP_TO_UINT, MVT::i32, Custom);
|
||||||
|
setOperationAction(ISD::STRICT_FP_TO_SINT, MVT::i32, Custom);
|
||||||
|
}
|
||||||
|
|
||||||
setOperationAction(ISD::GlobalAddress, XLenVT, Custom);
|
setOperationAction(ISD::GlobalAddress, XLenVT, Custom);
|
||||||
setOperationAction(ISD::BlockAddress, XLenVT, Custom);
|
setOperationAction(ISD::BlockAddress, XLenVT, Custom);
|
||||||
setOperationAction(ISD::ConstantPool, XLenVT, Custom);
|
setOperationAction(ISD::ConstantPool, XLenVT, Custom);
|
||||||
|
@ -904,6 +912,32 @@ void RISCVTargetLowering::ReplaceNodeResults(SDNode *N,
|
||||||
switch (N->getOpcode()) {
|
switch (N->getOpcode()) {
|
||||||
default:
|
default:
|
||||||
llvm_unreachable("Don't know how to custom type legalize this operation!");
|
llvm_unreachable("Don't know how to custom type legalize this operation!");
|
||||||
|
case ISD::STRICT_FP_TO_SINT:
|
||||||
|
case ISD::STRICT_FP_TO_UINT:
|
||||||
|
case ISD::FP_TO_SINT:
|
||||||
|
case ISD::FP_TO_UINT: {
|
||||||
|
bool IsStrict = N->isStrictFPOpcode();
|
||||||
|
assert(N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
|
||||||
|
"Unexpected custom legalisation");
|
||||||
|
SDValue Op0 = IsStrict ? N->getOperand(1) : N->getOperand(0);
|
||||||
|
RTLIB::Libcall LC;
|
||||||
|
if (N->getOpcode() == ISD::FP_TO_SINT ||
|
||||||
|
N->getOpcode() == ISD::STRICT_FP_TO_SINT)
|
||||||
|
LC = RTLIB::getFPTOSINT(Op0.getValueType(), N->getValueType(0));
|
||||||
|
else
|
||||||
|
LC = RTLIB::getFPTOUINT(Op0.getValueType(), N->getValueType(0));
|
||||||
|
MakeLibCallOptions CallOptions;
|
||||||
|
EVT OpVT = Op0.getValueType();
|
||||||
|
CallOptions.setTypeListBeforeSoften(OpVT, N->getValueType(0), true);
|
||||||
|
SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
|
||||||
|
SDValue Result;
|
||||||
|
std::tie(Result, Chain) =
|
||||||
|
makeLibCall(DAG, LC, N->getValueType(0), Op0, CallOptions, DL, Chain);
|
||||||
|
Results.push_back(Result);
|
||||||
|
if (IsStrict)
|
||||||
|
Results.push_back(Chain);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case ISD::READCYCLECOUNTER: {
|
case ISD::READCYCLECOUNTER: {
|
||||||
assert(!Subtarget.is64Bit() &&
|
assert(!Subtarget.is64Bit() &&
|
||||||
"READCYCLECOUNTER only has custom type legalization on riscv32");
|
"READCYCLECOUNTER only has custom type legalization on riscv32");
|
||||||
|
|
|
@ -174,7 +174,7 @@ define i32 @fcvt_w_s(float %a) nounwind {
|
||||||
; RV64I: # %bb.0:
|
; RV64I: # %bb.0:
|
||||||
; RV64I-NEXT: addi sp, sp, -16
|
; RV64I-NEXT: addi sp, sp, -16
|
||||||
; RV64I-NEXT: sd ra, 8(sp)
|
; RV64I-NEXT: sd ra, 8(sp)
|
||||||
; RV64I-NEXT: call __fixsfdi
|
; RV64I-NEXT: call __fixsfsi
|
||||||
; RV64I-NEXT: ld ra, 8(sp)
|
; RV64I-NEXT: ld ra, 8(sp)
|
||||||
; RV64I-NEXT: addi sp, sp, 16
|
; RV64I-NEXT: addi sp, sp, 16
|
||||||
; RV64I-NEXT: ret
|
; RV64I-NEXT: ret
|
||||||
|
@ -187,7 +187,7 @@ define i32 @fcvt_wu_s(float %a) nounwind {
|
||||||
; RV64I: # %bb.0:
|
; RV64I: # %bb.0:
|
||||||
; RV64I-NEXT: addi sp, sp, -16
|
; RV64I-NEXT: addi sp, sp, -16
|
||||||
; RV64I-NEXT: sd ra, 8(sp)
|
; RV64I-NEXT: sd ra, 8(sp)
|
||||||
; RV64I-NEXT: call __fixunssfdi
|
; RV64I-NEXT: call __fixunssfsi
|
||||||
; RV64I-NEXT: ld ra, 8(sp)
|
; RV64I-NEXT: ld ra, 8(sp)
|
||||||
; RV64I-NEXT: addi sp, sp, 16
|
; RV64I-NEXT: addi sp, sp, 16
|
||||||
; RV64I-NEXT: ret
|
; RV64I-NEXT: ret
|
||||||
|
@ -710,3 +710,123 @@ define float @fp_trunc(double %a) nounwind {
|
||||||
%conv = fptrunc double %a to float
|
%conv = fptrunc double %a to float
|
||||||
ret float %conv
|
ret float %conv
|
||||||
}
|
}
|
||||||
|
|
||||||
|
define i32 @fp32_to_ui32(float %a) nounwind {
|
||||||
|
; RV64I-LABEL: fp32_to_ui32:
|
||||||
|
; RV64I: # %bb.0: # %entry
|
||||||
|
; RV64I-NEXT: addi sp, sp, -16
|
||||||
|
; RV64I-NEXT: sd ra, 8(sp)
|
||||||
|
; RV64I-NEXT: call __fixunssfsi
|
||||||
|
; RV64I-NEXT: ld ra, 8(sp)
|
||||||
|
; RV64I-NEXT: addi sp, sp, 16
|
||||||
|
; RV64I-NEXT: ret
|
||||||
|
entry:
|
||||||
|
%conv = fptoui float %a to i32
|
||||||
|
ret i32 %conv
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @fp32_to_si32(float %a) nounwind {
|
||||||
|
; RV64I-LABEL: fp32_to_si32:
|
||||||
|
; RV64I: # %bb.0: # %entry
|
||||||
|
; RV64I-NEXT: addi sp, sp, -16
|
||||||
|
; RV64I-NEXT: sd ra, 8(sp)
|
||||||
|
; RV64I-NEXT: call __fixsfsi
|
||||||
|
; RV64I-NEXT: ld ra, 8(sp)
|
||||||
|
; RV64I-NEXT: addi sp, sp, 16
|
||||||
|
; RV64I-NEXT: ret
|
||||||
|
entry:
|
||||||
|
%conv = fptosi float %a to i32
|
||||||
|
ret i32 %conv
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @fp64_to_ui32(double %a) nounwind {
|
||||||
|
; RV64I-LABEL: fp64_to_ui32:
|
||||||
|
; RV64I: # %bb.0: # %entry
|
||||||
|
; RV64I-NEXT: addi sp, sp, -16
|
||||||
|
; RV64I-NEXT: sd ra, 8(sp)
|
||||||
|
; RV64I-NEXT: call __fixunsdfsi
|
||||||
|
; RV64I-NEXT: ld ra, 8(sp)
|
||||||
|
; RV64I-NEXT: addi sp, sp, 16
|
||||||
|
; RV64I-NEXT: ret
|
||||||
|
entry:
|
||||||
|
%conv = fptoui double %a to i32
|
||||||
|
ret i32 %conv
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @fp64_to_si32(double %a) nounwind {
|
||||||
|
; RV64I-LABEL: fp64_to_si32:
|
||||||
|
; RV64I: # %bb.0: # %entry
|
||||||
|
; RV64I-NEXT: addi sp, sp, -16
|
||||||
|
; RV64I-NEXT: sd ra, 8(sp)
|
||||||
|
; RV64I-NEXT: call __fixdfsi
|
||||||
|
; RV64I-NEXT: ld ra, 8(sp)
|
||||||
|
; RV64I-NEXT: addi sp, sp, 16
|
||||||
|
; RV64I-NEXT: ret
|
||||||
|
entry:
|
||||||
|
%conv = fptosi double %a to i32
|
||||||
|
ret i32 %conv
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
declare i32 @llvm.experimental.constrained.fptoui.i32.f32(float, metadata)
|
||||||
|
declare i32 @llvm.experimental.constrained.fptosi.i32.f32(float, metadata)
|
||||||
|
declare i32 @llvm.experimental.constrained.fptosi.i32.f64(double, metadata)
|
||||||
|
declare i32 @llvm.experimental.constrained.fptoui.i32.f64(double, metadata)
|
||||||
|
|
||||||
|
define i32 @strict_fp32_to_ui32(float %a) nounwind strictfp {
|
||||||
|
; RV64I-LABEL: strict_fp32_to_ui32:
|
||||||
|
; RV64I: # %bb.0: # %entry
|
||||||
|
; RV64I-NEXT: addi sp, sp, -16
|
||||||
|
; RV64I-NEXT: sd ra, 8(sp)
|
||||||
|
; RV64I-NEXT: call __fixunssfsi
|
||||||
|
; RV64I-NEXT: ld ra, 8(sp)
|
||||||
|
; RV64I-NEXT: addi sp, sp, 16
|
||||||
|
; RV64I-NEXT: ret
|
||||||
|
entry:
|
||||||
|
%conv = tail call i32 @llvm.experimental.constrained.fptoui.i32.f32(float %a, metadata !"fpexcept.strict")
|
||||||
|
ret i32 %conv
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @strict_fp32_to_si32(float %a) nounwind strictfp {
|
||||||
|
; RV64I-LABEL: strict_fp32_to_si32:
|
||||||
|
; RV64I: # %bb.0: # %entry
|
||||||
|
; RV64I-NEXT: addi sp, sp, -16
|
||||||
|
; RV64I-NEXT: sd ra, 8(sp)
|
||||||
|
; RV64I-NEXT: call __fixsfsi
|
||||||
|
; RV64I-NEXT: ld ra, 8(sp)
|
||||||
|
; RV64I-NEXT: addi sp, sp, 16
|
||||||
|
; RV64I-NEXT: ret
|
||||||
|
entry:
|
||||||
|
%conv = tail call i32 @llvm.experimental.constrained.fptosi.i32.f32(float %a, metadata !"fpexcept.strict")
|
||||||
|
ret i32 %conv
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @strict_fp64_to_ui32(double %a) nounwind strictfp {
|
||||||
|
; RV64I-LABEL: strict_fp64_to_ui32:
|
||||||
|
; RV64I: # %bb.0: # %entry
|
||||||
|
; RV64I-NEXT: addi sp, sp, -16
|
||||||
|
; RV64I-NEXT: sd ra, 8(sp)
|
||||||
|
; RV64I-NEXT: call __fixunsdfsi
|
||||||
|
; RV64I-NEXT: ld ra, 8(sp)
|
||||||
|
; RV64I-NEXT: addi sp, sp, 16
|
||||||
|
; RV64I-NEXT: ret
|
||||||
|
entry:
|
||||||
|
%conv = tail call i32 @llvm.experimental.constrained.fptoui.i32.f64(double %a, metadata !"fpexcept.strict")
|
||||||
|
ret i32 %conv
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @struct_fp64_to_si32(double %a) nounwind strictfp {
|
||||||
|
; RV64I-LABEL: struct_fp64_to_si32:
|
||||||
|
; RV64I: # %bb.0: # %entry
|
||||||
|
; RV64I-NEXT: addi sp, sp, -16
|
||||||
|
; RV64I-NEXT: sd ra, 8(sp)
|
||||||
|
; RV64I-NEXT: call __fixdfsi
|
||||||
|
; RV64I-NEXT: ld ra, 8(sp)
|
||||||
|
; RV64I-NEXT: addi sp, sp, 16
|
||||||
|
; RV64I-NEXT: ret
|
||||||
|
entry:
|
||||||
|
%conv = tail call i32 @llvm.experimental.constrained.fptosi.i32.f64(double %a, metadata !"fpexcept.strict")
|
||||||
|
ret i32 %conv
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue