Skip to content

Commit 249fef0

Browse files
kamleshbhaluitstellar
authored andcommitted
[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 (cherry picked from commit 7622ea5)
1 parent 71c14cd commit 249fef0

File tree

2 files changed

+156
-2
lines changed

2 files changed

+156
-2
lines changed

llvm/lib/Target/RISCV/RISCVISelLowering.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,14 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
197197
setTruncStoreAction(MVT::f64, MVT::f16, Expand);
198198
}
199199

200+
if (Subtarget.is64Bit() &&
201+
!(Subtarget.hasStdExtD() || Subtarget.hasStdExtF())) {
202+
setOperationAction(ISD::FP_TO_UINT, MVT::i32, Custom);
203+
setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom);
204+
setOperationAction(ISD::STRICT_FP_TO_UINT, MVT::i32, Custom);
205+
setOperationAction(ISD::STRICT_FP_TO_SINT, MVT::i32, Custom);
206+
}
207+
200208
setOperationAction(ISD::GlobalAddress, XLenVT, Custom);
201209
setOperationAction(ISD::BlockAddress, XLenVT, Custom);
202210
setOperationAction(ISD::ConstantPool, XLenVT, Custom);
@@ -876,6 +884,32 @@ void RISCVTargetLowering::ReplaceNodeResults(SDNode *N,
876884
switch (N->getOpcode()) {
877885
default:
878886
llvm_unreachable("Don't know how to custom type legalize this operation!");
887+
case ISD::STRICT_FP_TO_SINT:
888+
case ISD::STRICT_FP_TO_UINT:
889+
case ISD::FP_TO_SINT:
890+
case ISD::FP_TO_UINT: {
891+
bool IsStrict = N->isStrictFPOpcode();
892+
assert(N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
893+
"Unexpected custom legalisation");
894+
SDValue Op0 = IsStrict ? N->getOperand(1) : N->getOperand(0);
895+
RTLIB::Libcall LC;
896+
if (N->getOpcode() == ISD::FP_TO_SINT ||
897+
N->getOpcode() == ISD::STRICT_FP_TO_SINT)
898+
LC = RTLIB::getFPTOSINT(Op0.getValueType(), N->getValueType(0));
899+
else
900+
LC = RTLIB::getFPTOUINT(Op0.getValueType(), N->getValueType(0));
901+
MakeLibCallOptions CallOptions;
902+
EVT OpVT = Op0.getValueType();
903+
CallOptions.setTypeListBeforeSoften(OpVT, N->getValueType(0), true);
904+
SDValue Chain = IsStrict ? N->getOperand(0) : SDValue();
905+
SDValue Result;
906+
std::tie(Result, Chain) =
907+
makeLibCall(DAG, LC, N->getValueType(0), Op0, CallOptions, DL, Chain);
908+
Results.push_back(Result);
909+
if (IsStrict)
910+
Results.push_back(Chain);
911+
break;
912+
}
879913
case ISD::READCYCLECOUNTER: {
880914
assert(!Subtarget.is64Bit() &&
881915
"READCYCLECOUNTER only has custom type legalization on riscv32");

llvm/test/CodeGen/RISCV/rv64i-single-softfloat.ll

Lines changed: 122 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ define i32 @fcvt_w_s(float %a) nounwind {
174174
; RV64I: # %bb.0:
175175
; RV64I-NEXT: addi sp, sp, -16
176176
; RV64I-NEXT: sd ra, 8(sp)
177-
; RV64I-NEXT: call __fixsfdi
177+
; RV64I-NEXT: call __fixsfsi
178178
; RV64I-NEXT: ld ra, 8(sp)
179179
; RV64I-NEXT: addi sp, sp, 16
180180
; RV64I-NEXT: ret
@@ -187,7 +187,7 @@ define i32 @fcvt_wu_s(float %a) nounwind {
187187
; RV64I: # %bb.0:
188188
; RV64I-NEXT: addi sp, sp, -16
189189
; RV64I-NEXT: sd ra, 8(sp)
190-
; RV64I-NEXT: call __fixunssfdi
190+
; RV64I-NEXT: call __fixunssfsi
191191
; RV64I-NEXT: ld ra, 8(sp)
192192
; RV64I-NEXT: addi sp, sp, 16
193193
; RV64I-NEXT: ret
@@ -710,3 +710,123 @@ define float @fp_trunc(double %a) nounwind {
710710
%conv = fptrunc double %a to float
711711
ret float %conv
712712
}
713+
714+
define i32 @fp32_to_ui32(float %a) nounwind {
715+
; RV64I-LABEL: fp32_to_ui32:
716+
; RV64I: # %bb.0: # %entry
717+
; RV64I-NEXT: addi sp, sp, -16
718+
; RV64I-NEXT: sd ra, 8(sp)
719+
; RV64I-NEXT: call __fixunssfsi
720+
; RV64I-NEXT: ld ra, 8(sp)
721+
; RV64I-NEXT: addi sp, sp, 16
722+
; RV64I-NEXT: ret
723+
entry:
724+
%conv = fptoui float %a to i32
725+
ret i32 %conv
726+
}
727+
728+
define i32 @fp32_to_si32(float %a) nounwind {
729+
; RV64I-LABEL: fp32_to_si32:
730+
; RV64I: # %bb.0: # %entry
731+
; RV64I-NEXT: addi sp, sp, -16
732+
; RV64I-NEXT: sd ra, 8(sp)
733+
; RV64I-NEXT: call __fixsfsi
734+
; RV64I-NEXT: ld ra, 8(sp)
735+
; RV64I-NEXT: addi sp, sp, 16
736+
; RV64I-NEXT: ret
737+
entry:
738+
%conv = fptosi float %a to i32
739+
ret i32 %conv
740+
}
741+
742+
define i32 @fp64_to_ui32(double %a) nounwind {
743+
; RV64I-LABEL: fp64_to_ui32:
744+
; RV64I: # %bb.0: # %entry
745+
; RV64I-NEXT: addi sp, sp, -16
746+
; RV64I-NEXT: sd ra, 8(sp)
747+
; RV64I-NEXT: call __fixunsdfsi
748+
; RV64I-NEXT: ld ra, 8(sp)
749+
; RV64I-NEXT: addi sp, sp, 16
750+
; RV64I-NEXT: ret
751+
entry:
752+
%conv = fptoui double %a to i32
753+
ret i32 %conv
754+
}
755+
756+
define i32 @fp64_to_si32(double %a) nounwind {
757+
; RV64I-LABEL: fp64_to_si32:
758+
; RV64I: # %bb.0: # %entry
759+
; RV64I-NEXT: addi sp, sp, -16
760+
; RV64I-NEXT: sd ra, 8(sp)
761+
; RV64I-NEXT: call __fixdfsi
762+
; RV64I-NEXT: ld ra, 8(sp)
763+
; RV64I-NEXT: addi sp, sp, 16
764+
; RV64I-NEXT: ret
765+
entry:
766+
%conv = fptosi double %a to i32
767+
ret i32 %conv
768+
}
769+
770+
771+
772+
declare i32 @llvm.experimental.constrained.fptoui.i32.f32(float, metadata)
773+
declare i32 @llvm.experimental.constrained.fptosi.i32.f32(float, metadata)
774+
declare i32 @llvm.experimental.constrained.fptosi.i32.f64(double, metadata)
775+
declare i32 @llvm.experimental.constrained.fptoui.i32.f64(double, metadata)
776+
777+
define i32 @strict_fp32_to_ui32(float %a) nounwind strictfp {
778+
; RV64I-LABEL: strict_fp32_to_ui32:
779+
; RV64I: # %bb.0: # %entry
780+
; RV64I-NEXT: addi sp, sp, -16
781+
; RV64I-NEXT: sd ra, 8(sp)
782+
; RV64I-NEXT: call __fixunssfsi
783+
; RV64I-NEXT: ld ra, 8(sp)
784+
; RV64I-NEXT: addi sp, sp, 16
785+
; RV64I-NEXT: ret
786+
entry:
787+
%conv = tail call i32 @llvm.experimental.constrained.fptoui.i32.f32(float %a, metadata !"fpexcept.strict")
788+
ret i32 %conv
789+
}
790+
791+
define i32 @strict_fp32_to_si32(float %a) nounwind strictfp {
792+
; RV64I-LABEL: strict_fp32_to_si32:
793+
; RV64I: # %bb.0: # %entry
794+
; RV64I-NEXT: addi sp, sp, -16
795+
; RV64I-NEXT: sd ra, 8(sp)
796+
; RV64I-NEXT: call __fixsfsi
797+
; RV64I-NEXT: ld ra, 8(sp)
798+
; RV64I-NEXT: addi sp, sp, 16
799+
; RV64I-NEXT: ret
800+
entry:
801+
%conv = tail call i32 @llvm.experimental.constrained.fptosi.i32.f32(float %a, metadata !"fpexcept.strict")
802+
ret i32 %conv
803+
}
804+
805+
define i32 @strict_fp64_to_ui32(double %a) nounwind strictfp {
806+
; RV64I-LABEL: strict_fp64_to_ui32:
807+
; RV64I: # %bb.0: # %entry
808+
; RV64I-NEXT: addi sp, sp, -16
809+
; RV64I-NEXT: sd ra, 8(sp)
810+
; RV64I-NEXT: call __fixunsdfsi
811+
; RV64I-NEXT: ld ra, 8(sp)
812+
; RV64I-NEXT: addi sp, sp, 16
813+
; RV64I-NEXT: ret
814+
entry:
815+
%conv = tail call i32 @llvm.experimental.constrained.fptoui.i32.f64(double %a, metadata !"fpexcept.strict")
816+
ret i32 %conv
817+
}
818+
819+
define i32 @struct_fp64_to_si32(double %a) nounwind strictfp {
820+
; RV64I-LABEL: struct_fp64_to_si32:
821+
; RV64I: # %bb.0: # %entry
822+
; RV64I-NEXT: addi sp, sp, -16
823+
; RV64I-NEXT: sd ra, 8(sp)
824+
; RV64I-NEXT: call __fixdfsi
825+
; RV64I-NEXT: ld ra, 8(sp)
826+
; RV64I-NEXT: addi sp, sp, 16
827+
; RV64I-NEXT: ret
828+
entry:
829+
%conv = tail call i32 @llvm.experimental.constrained.fptosi.i32.f64(double %a, metadata !"fpexcept.strict")
830+
ret i32 %conv
831+
}
832+

0 commit comments

Comments
 (0)