diff --git a/lib/Target/RISCV/RISCVISelLowering.cpp b/lib/Target/RISCV/RISCVISelLowering.cpp index d29a80e22a6..9cfd747ffc0 100644 --- a/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/lib/Target/RISCV/RISCVISelLowering.cpp @@ -834,10 +834,14 @@ static bool CC_RISCV(const DataLayout &DL, unsigned ValNo, MVT ValVT, MVT LocVT, if (Reg) { State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); - } else { - State.addLoc( - CCValAssign::getMem(ValNo, ValVT, StackOffset, LocVT, LocInfo)); + return false; } + + if (ValVT == MVT::f32) { + LocVT = MVT::f32; + LocInfo = CCValAssign::Full; + } + State.addLoc(CCValAssign::getMem(ValNo, ValVT, StackOffset, LocVT, LocInfo)); return false; } @@ -1046,7 +1050,6 @@ SDValue RISCVTargetLowering::LowerFormalArguments( for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { CCValAssign &VA = ArgLocs[i]; - assert(VA.getLocVT() == XLenVT && "Unhandled argument type"); SDValue ArgValue; // Passing f64 on RV32D with a soft float ABI must be handled as a special // case. diff --git a/test/CodeGen/RISCV/calling-conv-rv32f-ilp32.ll b/test/CodeGen/RISCV/calling-conv-rv32f-ilp32.ll new file mode 100644 index 00000000000..849e18a81bb --- /dev/null +++ b/test/CodeGen/RISCV/calling-conv-rv32f-ilp32.ll @@ -0,0 +1,81 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=riscv32 -mattr=+f -verify-machineinstrs < %s \ +; RUN: | FileCheck %s -check-prefix=RV32IF + +; Exercises the ILP32 calling convention code in the case that f32 is a legal +; type. As well as testing that lowering is correct, these tests also aim to +; check that floating point load/store or integer load/store is chosen +; optimally when floats are passed on the stack. + +define float @onstack_f32_noop(i64 %a, i64 %b, i64 %c, i64 %d, float %e, float %f) nounwind { +; RV32IF-LABEL: onstack_f32_noop: +; RV32IF: # %bb.0: +; RV32IF-NEXT: lw a0, 4(sp) +; RV32IF-NEXT: ret + ret float %f +} + +define float @onstack_f32_fadd(i64 %a, i64 %b, i64 %c, i64 %d, float %e, float %f) nounwind { +; RV32IF-LABEL: onstack_f32_fadd: +; RV32IF: # %bb.0: +; RV32IF-NEXT: flw ft0, 4(sp) +; RV32IF-NEXT: flw ft1, 0(sp) +; RV32IF-NEXT: fadd.s ft0, ft1, ft0 +; RV32IF-NEXT: fmv.x.w a0, ft0 +; RV32IF-NEXT: ret + %1 = fadd float %e, %f + ret float %1 +} + +define float @caller_onstack_f32_noop(float %a) nounwind { +; RV32IF-LABEL: caller_onstack_f32_noop: +; RV32IF: # %bb.0: +; RV32IF-NEXT: addi sp, sp, -16 +; RV32IF-NEXT: sw ra, 12(sp) +; RV32IF-NEXT: sw a0, 4(sp) +; RV32IF-NEXT: lui a0, 264704 +; RV32IF-NEXT: sw a0, 0(sp) +; RV32IF-NEXT: addi a0, zero, 1 +; RV32IF-NEXT: addi a2, zero, 2 +; RV32IF-NEXT: addi a4, zero, 3 +; RV32IF-NEXT: addi a6, zero, 4 +; RV32IF-NEXT: mv a1, zero +; RV32IF-NEXT: mv a3, zero +; RV32IF-NEXT: mv a5, zero +; RV32IF-NEXT: mv a7, zero +; RV32IF-NEXT: call onstack_f32_noop +; RV32IF-NEXT: lw ra, 12(sp) +; RV32IF-NEXT: addi sp, sp, 16 +; RV32IF-NEXT: ret + %1 = call float @onstack_f32_noop(i64 1, i64 2, i64 3, i64 4, float 5.0, float %a) + ret float %1 +} + +define float @caller_onstack_f32_fadd(float %a, float %b) nounwind { +; RV32IF-LABEL: caller_onstack_f32_fadd: +; RV32IF: # %bb.0: +; RV32IF-NEXT: addi sp, sp, -16 +; RV32IF-NEXT: sw ra, 12(sp) +; RV32IF-NEXT: fmv.w.x ft0, a0 +; RV32IF-NEXT: fmv.w.x ft1, a1 +; RV32IF-NEXT: fsub.s ft2, ft1, ft0 +; RV32IF-NEXT: fsw ft2, 4(sp) +; RV32IF-NEXT: fadd.s ft0, ft0, ft1 +; RV32IF-NEXT: fsw ft0, 0(sp) +; RV32IF-NEXT: addi a0, zero, 1 +; RV32IF-NEXT: addi a2, zero, 2 +; RV32IF-NEXT: addi a4, zero, 3 +; RV32IF-NEXT: addi a6, zero, 4 +; RV32IF-NEXT: mv a1, zero +; RV32IF-NEXT: mv a3, zero +; RV32IF-NEXT: mv a5, zero +; RV32IF-NEXT: mv a7, zero +; RV32IF-NEXT: call onstack_f32_noop +; RV32IF-NEXT: lw ra, 12(sp) +; RV32IF-NEXT: addi sp, sp, 16 +; RV32IF-NEXT: ret + %1 = fadd float %a, %b + %2 = fsub float %b, %a + %3 = call float @onstack_f32_noop(i64 1, i64 2, i64 3, i64 4, float %1, float %2) + ret float %3 +}