diff --git a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h index b681a0708db4b..5d7e03bbaeb7d 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h @@ -778,6 +778,11 @@ class LegalizeRuleSet { LegalizeRuleSet &libcallFor(std::initializer_list Types) { return actionFor(LegalizeAction::Libcall, Types); } + LegalizeRuleSet &libcallFor(bool Pred, std::initializer_list Types) { + if (!Pred) + return *this; + return actionFor(LegalizeAction::Libcall, Types); + } LegalizeRuleSet & libcallFor(std::initializer_list> Types) { return actionFor(LegalizeAction::Libcall, Types); diff --git a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp index 456ca9894e6a7..3fc436cceadb4 100644 --- a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp +++ b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp @@ -491,21 +491,24 @@ RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST) // FP Operations + // FIXME: Support s128 for rv32 when libcall handling is able to use sret. getActionDefinitionsBuilder( {G_FADD, G_FSUB, G_FMUL, G_FDIV, G_FMA, G_FSQRT, G_FMAXNUM, G_FMINNUM}) .legalFor(ST.hasStdExtF(), {s32}) .legalFor(ST.hasStdExtD(), {s64}) .legalFor(ST.hasStdExtZfh(), {s16}) - .libcallFor({s32, s64}); + .libcallFor({s32, s64}) + .libcallFor(ST.is64Bit(), {s128}); getActionDefinitionsBuilder({G_FNEG, G_FABS}) .legalFor(ST.hasStdExtF(), {s32}) .legalFor(ST.hasStdExtD(), {s64}) .legalFor(ST.hasStdExtZfh(), {s16}) - .lowerFor({s32, s64}); + .lowerFor({s32, s64, s128}); getActionDefinitionsBuilder(G_FREM) .libcallFor({s32, s64}) + .libcallFor(ST.is64Bit(), {s128}) .minScalar(0, s32) .scalarize(0); @@ -521,19 +524,22 @@ RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST) .legalFor(ST.hasStdExtD(), {{s32, s64}}) .legalFor(ST.hasStdExtZfh(), {{s16, s32}}) .legalFor(ST.hasStdExtZfh() && ST.hasStdExtD(), {{s16, s64}}) - .libcallFor({{s32, s64}}); + .libcallFor({{s32, s64}}) + .libcallFor(ST.is64Bit(), {{s32, s128}, {s64, s128}}); getActionDefinitionsBuilder(G_FPEXT) .legalFor(ST.hasStdExtD(), {{s64, s32}}) .legalFor(ST.hasStdExtZfh(), {{s32, s16}}) .legalFor(ST.hasStdExtZfh() && ST.hasStdExtD(), {{s64, s16}}) - .libcallFor({{s64, s32}}); + .libcallFor({{s64, s32}}) + .libcallFor(ST.is64Bit(), {{s128, s32}, {s128, s64}}); getActionDefinitionsBuilder(G_FCMP) .legalFor(ST.hasStdExtF(), {{sXLen, s32}}) .legalFor(ST.hasStdExtD(), {{sXLen, s64}}) .legalFor(ST.hasStdExtZfh(), {{sXLen, s16}}) .clampScalar(0, sXLen, sXLen) - .libcallFor({{sXLen, s32}, {sXLen, s64}}); + .libcallFor({{sXLen, s32}, {sXLen, s64}}) + .libcallFor(ST.is64Bit(), {{sXLen, s128}}); // TODO: Support vector version of G_IS_FPCLASS. getActionDefinitionsBuilder(G_IS_FPCLASS) @@ -546,7 +552,7 @@ RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST) .legalFor(ST.hasStdExtF(), {s32}) .legalFor(ST.hasStdExtD(), {s64}) .legalFor(ST.hasStdExtZfh(), {s16}) - .lowerFor({s32, s64}); + .lowerFor({s32, s64, s128}); getActionDefinitionsBuilder({G_FPTOSI, G_FPTOUI}) .legalFor(ST.hasStdExtF(), {{sXLen, s32}}) @@ -558,7 +564,8 @@ RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST) .widenScalarToNextPow2(0) .minScalar(0, s32) .libcallFor({{s32, s32}, {s64, s32}, {s32, s64}, {s64, s64}}) - .libcallFor(ST.is64Bit(), {{s128, s32}, {s128, s64}}); + .libcallFor(ST.is64Bit(), {{s32, s128}, {s64, s128}}) // FIXME RV32. + .libcallFor(ST.is64Bit(), {{s128, s32}, {s128, s64}, {s128, s128}}); getActionDefinitionsBuilder({G_SITOFP, G_UITOFP}) .legalFor(ST.hasStdExtF(), {{s32, sXLen}}) @@ -579,7 +586,8 @@ RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST) // Otherwise only promote to s32 since we have si libcalls. .minScalar(1, s32) .libcallFor({{s32, s32}, {s64, s32}, {s32, s64}, {s64, s64}}) - .libcallFor(ST.is64Bit(), {{s32, s128}, {s64, s128}}); + .libcallFor(ST.is64Bit(), {{s128, s32}, {s128, s64}}) // FIXME RV32. + .libcallFor(ST.is64Bit(), {{s32, s128}, {s64, s128}, {s128, s128}}); // FIXME: We can do custom inline expansion like SelectionDAG. // FIXME: Legal with Zfa. diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/fp128.ll b/llvm/test/CodeGen/RISCV/GlobalISel/fp128.ll new file mode 100644 index 0000000000000..9f5c013c9ccd4 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/GlobalISel/fp128.ll @@ -0,0 +1,538 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=riscv64 -global-isel < %s \ +; RUN: | FileCheck -check-prefixes=CHECK,RV64I %s +; RUN: llc -mtriple=riscv64 -global-isel -mattr=+d < %s \ +; RUN: | FileCheck -check-prefixes=CHECK,RV64D %s + +; FIXME: Support RV32. + +define fp128 @fadd(fp128 %x, fp128 %y) nounwind { +; CHECK-LABEL: fadd: +; CHECK: # %bb.0: +; CHECK-NEXT: addi sp, sp, -16 +; CHECK-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; CHECK-NEXT: call __addtf3 +; CHECK-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; CHECK-NEXT: addi sp, sp, 16 +; CHECK-NEXT: ret + %a = fadd fp128 %x, %y + ret fp128 %a +} + +define fp128 @fsub(fp128 %x, fp128 %y) nounwind { +; CHECK-LABEL: fsub: +; CHECK: # %bb.0: +; CHECK-NEXT: addi sp, sp, -16 +; CHECK-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; CHECK-NEXT: call __subtf3 +; CHECK-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; CHECK-NEXT: addi sp, sp, 16 +; CHECK-NEXT: ret + %a = fsub fp128 %x, %y + ret fp128 %a +} + +define fp128 @fmul(fp128 %x, fp128 %y) nounwind { +; CHECK-LABEL: fmul: +; CHECK: # %bb.0: +; CHECK-NEXT: addi sp, sp, -16 +; CHECK-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; CHECK-NEXT: call __multf3 +; CHECK-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; CHECK-NEXT: addi sp, sp, 16 +; CHECK-NEXT: ret + %a = fmul fp128 %x, %y + ret fp128 %a +} + +define fp128 @fdiv(fp128 %x, fp128 %y) nounwind { +; CHECK-LABEL: fdiv: +; CHECK: # %bb.0: +; CHECK-NEXT: addi sp, sp, -16 +; CHECK-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; CHECK-NEXT: call __divtf3 +; CHECK-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; CHECK-NEXT: addi sp, sp, 16 +; CHECK-NEXT: ret + %a = fdiv fp128 %x, %y + ret fp128 %a +} + +define fp128 @frem(fp128 %x, fp128 %y) nounwind { +; CHECK-LABEL: frem: +; CHECK: # %bb.0: +; CHECK-NEXT: addi sp, sp, -16 +; CHECK-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; CHECK-NEXT: call fmodl +; CHECK-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; CHECK-NEXT: addi sp, sp, 16 +; CHECK-NEXT: ret + %a = frem fp128 %x, %y + ret fp128 %a +} + +define fp128 @fma(fp128 %x, fp128 %y, fp128 %z) nounwind { +; CHECK-LABEL: fma: +; CHECK: # %bb.0: +; CHECK-NEXT: addi sp, sp, -16 +; CHECK-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; CHECK-NEXT: call fmal +; CHECK-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; CHECK-NEXT: addi sp, sp, 16 +; CHECK-NEXT: ret + %a = call fp128 @llvm.fma.f128(fp128 %x, fp128 %y, fp128 %z) + ret fp128 %a +} + +define fp128 @fneg(fp128 %x) { +; CHECK-LABEL: fneg: +; CHECK: # %bb.0: +; CHECK-NEXT: li a2, -1 +; CHECK-NEXT: slli a2, a2, 63 +; CHECK-NEXT: xor a1, a1, a2 +; CHECK-NEXT: ret + %a = fneg fp128 %x + ret fp128 %a +} + +define fp128 @fabs(fp128 %x) { +; CHECK-LABEL: fabs: +; CHECK: # %bb.0: +; CHECK-NEXT: li a2, -1 +; CHECK-NEXT: srli a2, a2, 1 +; CHECK-NEXT: and a1, a1, a2 +; CHECK-NEXT: ret + %a = call fp128 @llvm.fabs.f128(fp128 %x) + ret fp128 %a +} + +define fp128 @fcopysign(fp128 %x, fp128 %y) { +; CHECK-LABEL: fcopysign: +; CHECK: # %bb.0: +; CHECK-NEXT: li a2, -1 +; CHECK-NEXT: slli a4, a2, 63 +; CHECK-NEXT: srli a2, a2, 1 +; CHECK-NEXT: and a1, a1, a2 +; CHECK-NEXT: and a3, a3, a4 +; CHECK-NEXT: or a1, a1, a3 +; CHECK-NEXT: ret + %a = call fp128 @llvm.copysign.f128(fp128 %x, fp128 %y) + ret fp128 %a +} + +define i1 @fcmp(fp128 %x, fp128 %y) nounwind { +; CHECK-LABEL: fcmp: +; CHECK: # %bb.0: +; CHECK-NEXT: addi sp, sp, -16 +; CHECK-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; CHECK-NEXT: call __eqtf2 +; CHECK-NEXT: slli a0, a0, 32 +; CHECK-NEXT: srli a0, a0, 32 +; CHECK-NEXT: seqz a0, a0 +; CHECK-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; CHECK-NEXT: addi sp, sp, 16 +; CHECK-NEXT: ret + %a = fcmp oeq fp128 %x, %y + ret i1 %a +} + +define fp128 @constant(fp128 %x) nounwind { +; CHECK-LABEL: constant: +; CHECK: # %bb.0: +; CHECK-NEXT: addi sp, sp, -16 +; CHECK-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; CHECK-NEXT: lui a2, %hi(.LCPI10_0) +; CHECK-NEXT: addi a3, a2, %lo(.LCPI10_0) +; CHECK-NEXT: ld a2, 0(a3) +; CHECK-NEXT: ld a3, 8(a3) +; CHECK-NEXT: call __addtf3 +; CHECK-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; CHECK-NEXT: addi sp, sp, 16 +; CHECK-NEXT: ret + %a = fadd fp128 %x, 0xL00000000000000007FFF000000000000 + ret fp128 %a +} + +define fp128 @fpext_f32(float %x, float %y) nounwind { +; RV64I-LABEL: fpext_f32: +; RV64I: # %bb.0: +; RV64I-NEXT: addi sp, sp, -16 +; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; RV64I-NEXT: call __addsf3 +; RV64I-NEXT: call __extendsftf2 +; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: ret +; +; RV64D-LABEL: fpext_f32: +; RV64D: # %bb.0: +; RV64D-NEXT: addi sp, sp, -16 +; RV64D-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; RV64D-NEXT: fadd.s fa0, fa0, fa1 +; RV64D-NEXT: call __extendsftf2 +; RV64D-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; RV64D-NEXT: addi sp, sp, 16 +; RV64D-NEXT: ret + %a = fadd float %x, %y + %b = fpext float %a to fp128 + ret fp128 %b +} + +define fp128 @fpext_f64(double %x, double %y) nounwind { +; RV64I-LABEL: fpext_f64: +; RV64I: # %bb.0: +; RV64I-NEXT: addi sp, sp, -16 +; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; RV64I-NEXT: call __adddf3 +; RV64I-NEXT: call __extenddftf2 +; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: ret +; +; RV64D-LABEL: fpext_f64: +; RV64D: # %bb.0: +; RV64D-NEXT: addi sp, sp, -16 +; RV64D-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; RV64D-NEXT: fadd.d fa0, fa0, fa1 +; RV64D-NEXT: call __extenddftf2 +; RV64D-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; RV64D-NEXT: addi sp, sp, 16 +; RV64D-NEXT: ret + %a = fadd double %x, %y + %b = fpext double %a to fp128 + ret fp128 %b +} + +define float @fptrunc_f32(fp128 %x, float %y) nounwind { +; RV64I-LABEL: fptrunc_f32: +; RV64I: # %bb.0: +; RV64I-NEXT: addi sp, sp, -16 +; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; RV64I-NEXT: sd s0, 0(sp) # 8-byte Folded Spill +; RV64I-NEXT: mv s0, a2 +; RV64I-NEXT: call __trunctfsf2 +; RV64I-NEXT: mv a1, s0 +; RV64I-NEXT: call __addsf3 +; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; RV64I-NEXT: ld s0, 0(sp) # 8-byte Folded Reload +; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: ret +; +; RV64D-LABEL: fptrunc_f32: +; RV64D: # %bb.0: +; RV64D-NEXT: addi sp, sp, -16 +; RV64D-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; RV64D-NEXT: fsd fs0, 0(sp) # 8-byte Folded Spill +; RV64D-NEXT: fmv.s fs0, fa0 +; RV64D-NEXT: call __trunctfsf2 +; RV64D-NEXT: fadd.s fa0, fa0, fs0 +; RV64D-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; RV64D-NEXT: fld fs0, 0(sp) # 8-byte Folded Reload +; RV64D-NEXT: addi sp, sp, 16 +; RV64D-NEXT: ret + %a = fptrunc fp128 %x to float + %b = fadd float %a, %y + ret float %b +} + +define double @fptrunc_f64(fp128 %x, double %y) nounwind { +; RV64I-LABEL: fptrunc_f64: +; RV64I: # %bb.0: +; RV64I-NEXT: addi sp, sp, -16 +; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; RV64I-NEXT: sd s0, 0(sp) # 8-byte Folded Spill +; RV64I-NEXT: mv s0, a2 +; RV64I-NEXT: call __trunctfdf2 +; RV64I-NEXT: mv a1, s0 +; RV64I-NEXT: call __adddf3 +; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; RV64I-NEXT: ld s0, 0(sp) # 8-byte Folded Reload +; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: ret +; +; RV64D-LABEL: fptrunc_f64: +; RV64D: # %bb.0: +; RV64D-NEXT: addi sp, sp, -16 +; RV64D-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; RV64D-NEXT: fsd fs0, 0(sp) # 8-byte Folded Spill +; RV64D-NEXT: fmv.d fs0, fa0 +; RV64D-NEXT: call __trunctfdf2 +; RV64D-NEXT: fadd.d fa0, fa0, fs0 +; RV64D-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; RV64D-NEXT: fld fs0, 0(sp) # 8-byte Folded Reload +; RV64D-NEXT: addi sp, sp, 16 +; RV64D-NEXT: ret + %a = fptrunc fp128 %x to double + %b = fadd double %a, %y + ret double %b +} + +define i8 @fptosi_i8(fp128 %x) nounwind { +; CHECK-LABEL: fptosi_i8: +; CHECK: # %bb.0: +; CHECK-NEXT: addi sp, sp, -16 +; CHECK-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; CHECK-NEXT: call __fixtfsi +; CHECK-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; CHECK-NEXT: addi sp, sp, 16 +; CHECK-NEXT: ret + %a = fptosi fp128 %x to i8 + ret i8 %a +} + +define i16 @fptosi_i16(fp128 %x) nounwind { +; CHECK-LABEL: fptosi_i16: +; CHECK: # %bb.0: +; CHECK-NEXT: addi sp, sp, -16 +; CHECK-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; CHECK-NEXT: call __fixtfsi +; CHECK-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; CHECK-NEXT: addi sp, sp, 16 +; CHECK-NEXT: ret + %a = fptosi fp128 %x to i16 + ret i16 %a +} + +define i32 @fptosi_i32(fp128 %x) nounwind { +; CHECK-LABEL: fptosi_i32: +; CHECK: # %bb.0: +; CHECK-NEXT: addi sp, sp, -16 +; CHECK-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; CHECK-NEXT: call __fixtfsi +; CHECK-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; CHECK-NEXT: addi sp, sp, 16 +; CHECK-NEXT: ret + %a = fptosi fp128 %x to i32 + ret i32 %a +} + +define i64 @fptosi_i64(fp128 %x) nounwind { +; CHECK-LABEL: fptosi_i64: +; CHECK: # %bb.0: +; CHECK-NEXT: addi sp, sp, -16 +; CHECK-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; CHECK-NEXT: call __fixtfdi +; CHECK-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; CHECK-NEXT: addi sp, sp, 16 +; CHECK-NEXT: ret + %a = fptosi fp128 %x to i64 + ret i64 %a +} + +define i128 @fptosi_i128(fp128 %x) nounwind { +; CHECK-LABEL: fptosi_i128: +; CHECK: # %bb.0: +; CHECK-NEXT: addi sp, sp, -16 +; CHECK-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; CHECK-NEXT: call __fixtfti +; CHECK-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; CHECK-NEXT: addi sp, sp, 16 +; CHECK-NEXT: ret + %a = fptosi fp128 %x to i128 + ret i128 %a +} + +define i8 @fptoui_i8(fp128 %x) nounwind { +; CHECK-LABEL: fptoui_i8: +; CHECK: # %bb.0: +; CHECK-NEXT: addi sp, sp, -16 +; CHECK-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; CHECK-NEXT: call __fixunstfsi +; CHECK-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; CHECK-NEXT: addi sp, sp, 16 +; CHECK-NEXT: ret + %a = fptoui fp128 %x to i8 + ret i8 %a +} + +define i16 @fptoui_i16(fp128 %x) nounwind { +; CHECK-LABEL: fptoui_i16: +; CHECK: # %bb.0: +; CHECK-NEXT: addi sp, sp, -16 +; CHECK-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; CHECK-NEXT: call __fixunstfsi +; CHECK-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; CHECK-NEXT: addi sp, sp, 16 +; CHECK-NEXT: ret + %a = fptoui fp128 %x to i16 + ret i16 %a +} + +define i32 @fptoui_i32(fp128 %x) nounwind { +; CHECK-LABEL: fptoui_i32: +; CHECK: # %bb.0: +; CHECK-NEXT: addi sp, sp, -16 +; CHECK-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; CHECK-NEXT: call __fixunstfsi +; CHECK-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; CHECK-NEXT: addi sp, sp, 16 +; CHECK-NEXT: ret + %a = fptoui fp128 %x to i32 + ret i32 %a +} + +define i64 @fptoui_i64(fp128 %x) nounwind { +; CHECK-LABEL: fptoui_i64: +; CHECK: # %bb.0: +; CHECK-NEXT: addi sp, sp, -16 +; CHECK-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; CHECK-NEXT: call __fixunstfdi +; CHECK-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; CHECK-NEXT: addi sp, sp, 16 +; CHECK-NEXT: ret + %a = fptoui fp128 %x to i64 + ret i64 %a +} + +define i128 @fptoui_i128(fp128 %x) nounwind { +; CHECK-LABEL: fptoui_i128: +; CHECK: # %bb.0: +; CHECK-NEXT: addi sp, sp, -16 +; CHECK-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; CHECK-NEXT: call __fixunstfti +; CHECK-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; CHECK-NEXT: addi sp, sp, 16 +; CHECK-NEXT: ret + %a = fptoui fp128 %x to i128 + ret i128 %a +} + +define fp128 @sitofp_i8(i8 %x) nounwind { +; CHECK-LABEL: sitofp_i8: +; CHECK: # %bb.0: +; CHECK-NEXT: addi sp, sp, -16 +; CHECK-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; CHECK-NEXT: slli a0, a0, 56 +; CHECK-NEXT: srai a0, a0, 56 +; CHECK-NEXT: call __floatsitf +; CHECK-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; CHECK-NEXT: addi sp, sp, 16 +; CHECK-NEXT: ret + %a = sitofp i8 %x to fp128 + ret fp128 %a +} + +define fp128 @sitofp_i16(i16 %x) nounwind { +; CHECK-LABEL: sitofp_i16: +; CHECK: # %bb.0: +; CHECK-NEXT: addi sp, sp, -16 +; CHECK-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; CHECK-NEXT: slli a0, a0, 48 +; CHECK-NEXT: srai a0, a0, 48 +; CHECK-NEXT: call __floatsitf +; CHECK-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; CHECK-NEXT: addi sp, sp, 16 +; CHECK-NEXT: ret + %a = sitofp i16 %x to fp128 + ret fp128 %a +} + +define fp128 @sitofp_i32(i32 %x) nounwind { +; CHECK-LABEL: sitofp_i32: +; CHECK: # %bb.0: +; CHECK-NEXT: addi sp, sp, -16 +; CHECK-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; CHECK-NEXT: sext.w a0, a0 +; CHECK-NEXT: call __floatsitf +; CHECK-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; CHECK-NEXT: addi sp, sp, 16 +; CHECK-NEXT: ret + %a = sitofp i32 %x to fp128 + ret fp128 %a +} + +define fp128 @sitofp_i64(i64 %x) nounwind { +; CHECK-LABEL: sitofp_i64: +; CHECK: # %bb.0: +; CHECK-NEXT: addi sp, sp, -16 +; CHECK-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; CHECK-NEXT: call __floatditf +; CHECK-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; CHECK-NEXT: addi sp, sp, 16 +; CHECK-NEXT: ret + %a = sitofp i64 %x to fp128 + ret fp128 %a +} + +define fp128 @sitofp_i128(i128 %x) nounwind { +; CHECK-LABEL: sitofp_i128: +; CHECK: # %bb.0: +; CHECK-NEXT: addi sp, sp, -16 +; CHECK-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; CHECK-NEXT: call __floattitf +; CHECK-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; CHECK-NEXT: addi sp, sp, 16 +; CHECK-NEXT: ret + %a = sitofp i128 %x to fp128 + ret fp128 %a +} + +define fp128 @uitofp_i8(i8 %x) nounwind { +; CHECK-LABEL: uitofp_i8: +; CHECK: # %bb.0: +; CHECK-NEXT: addi sp, sp, -16 +; CHECK-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; CHECK-NEXT: andi a0, a0, 255 +; CHECK-NEXT: call __floatunsitf +; CHECK-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; CHECK-NEXT: addi sp, sp, 16 +; CHECK-NEXT: ret + %a = uitofp i8 %x to fp128 + ret fp128 %a +} + +define fp128 @uitofp_i16(i16 %x) nounwind { +; CHECK-LABEL: uitofp_i16: +; CHECK: # %bb.0: +; CHECK-NEXT: addi sp, sp, -16 +; CHECK-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; CHECK-NEXT: lui a1, 16 +; CHECK-NEXT: addiw a1, a1, -1 +; CHECK-NEXT: and a0, a0, a1 +; CHECK-NEXT: call __floatunsitf +; CHECK-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; CHECK-NEXT: addi sp, sp, 16 +; CHECK-NEXT: ret + %a = uitofp i16 %x to fp128 + ret fp128 %a +} + +define fp128 @uitofp_i32(i32 %x) nounwind { +; CHECK-LABEL: uitofp_i32: +; CHECK: # %bb.0: +; CHECK-NEXT: addi sp, sp, -16 +; CHECK-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; CHECK-NEXT: sext.w a0, a0 +; CHECK-NEXT: call __floatunsitf +; CHECK-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; CHECK-NEXT: addi sp, sp, 16 +; CHECK-NEXT: ret + %a = uitofp i32 %x to fp128 + ret fp128 %a +} + +define fp128 @uitofp_i64(i64 %x) nounwind { +; CHECK-LABEL: uitofp_i64: +; CHECK: # %bb.0: +; CHECK-NEXT: addi sp, sp, -16 +; CHECK-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; CHECK-NEXT: call __floatunditf +; CHECK-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; CHECK-NEXT: addi sp, sp, 16 +; CHECK-NEXT: ret + %a = uitofp i64 %x to fp128 + ret fp128 %a +} + +define fp128 @uitofp_i128(i128 %x) nounwind { +; CHECK-LABEL: uitofp_i128: +; CHECK: # %bb.0: +; CHECK-NEXT: addi sp, sp, -16 +; CHECK-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; CHECK-NEXT: call __floatuntitf +; CHECK-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; CHECK-NEXT: addi sp, sp, 16 +; CHECK-NEXT: ret + %a = uitofp i128 %x to fp128 + ret fp128 %a +}