| ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py |
| ; RUN: llc -mtriple=riscv32 -mattr=+d -verify-machineinstrs < %s \ |
| ; RUN: | FileCheck -check-prefix=RV32IFD %s |
| |
| ; Sanity checks for calling convention lowering for RV32D. This can be |
| ; somewhat error-prone for soft-float RV32D due to the fact that f64 is legal |
| ; but i64 is not, and there is no instruction to move values directly between |
| ; the GPRs and 64-bit FPRs. |
| |
| define double @callee_double_inreg(double %a, double %b) nounwind { |
| ; RV32IFD-LABEL: callee_double_inreg: |
| ; RV32IFD: # %bb.0: |
| ; RV32IFD-NEXT: addi sp, sp, -16 |
| ; RV32IFD-NEXT: sw a2, 8(sp) |
| ; RV32IFD-NEXT: sw a3, 12(sp) |
| ; RV32IFD-NEXT: fld ft0, 8(sp) |
| ; RV32IFD-NEXT: sw a0, 8(sp) |
| ; RV32IFD-NEXT: sw a1, 12(sp) |
| ; RV32IFD-NEXT: fld ft1, 8(sp) |
| ; RV32IFD-NEXT: fadd.d ft0, ft1, ft0 |
| ; RV32IFD-NEXT: fsd ft0, 8(sp) |
| ; RV32IFD-NEXT: lw a0, 8(sp) |
| ; RV32IFD-NEXT: lw a1, 12(sp) |
| ; RV32IFD-NEXT: addi sp, sp, 16 |
| ; RV32IFD-NEXT: ret |
| %1 = fadd double %a, %b |
| ret double %1 |
| } |
| |
| ; TODO: code quality for loading and then passing f64 constants is poor. |
| |
| define double @caller_double_inreg() nounwind { |
| ; RV32IFD-LABEL: caller_double_inreg: |
| ; RV32IFD: # %bb.0: |
| ; RV32IFD-NEXT: addi sp, sp, -16 |
| ; RV32IFD-NEXT: sw ra, 12(sp) |
| ; RV32IFD-NEXT: lui a0, %hi(.LCPI1_0) |
| ; RV32IFD-NEXT: addi a0, a0, %lo(.LCPI1_0) |
| ; RV32IFD-NEXT: fld ft0, 0(a0) |
| ; RV32IFD-NEXT: lui a0, %hi(.LCPI1_1) |
| ; RV32IFD-NEXT: addi a0, a0, %lo(.LCPI1_1) |
| ; RV32IFD-NEXT: fld ft1, 0(a0) |
| ; RV32IFD-NEXT: fsd ft1, 0(sp) |
| ; RV32IFD-NEXT: lw a0, 0(sp) |
| ; RV32IFD-NEXT: lw a1, 4(sp) |
| ; RV32IFD-NEXT: fsd ft0, 0(sp) |
| ; RV32IFD-NEXT: lw a2, 0(sp) |
| ; RV32IFD-NEXT: lw a3, 4(sp) |
| ; RV32IFD-NEXT: call callee_double_inreg |
| ; RV32IFD-NEXT: lw ra, 12(sp) |
| ; RV32IFD-NEXT: addi sp, sp, 16 |
| ; RV32IFD-NEXT: ret |
| %1 = call double @callee_double_inreg(double 2.720000e+00, double 3.720000e+00) |
| ret double %1 |
| } |
| |
| define double @callee_double_split_reg_stack(i32 %a, i64 %b, i64 %c, double %d, double %e) nounwind { |
| ; RV32IFD-LABEL: callee_double_split_reg_stack: |
| ; RV32IFD: # %bb.0: |
| ; RV32IFD-NEXT: addi sp, sp, -16 |
| ; RV32IFD-NEXT: lw a0, 16(sp) |
| ; RV32IFD-NEXT: sw a7, 8(sp) |
| ; RV32IFD-NEXT: sw a0, 12(sp) |
| ; RV32IFD-NEXT: fld ft0, 8(sp) |
| ; RV32IFD-NEXT: sw a5, 8(sp) |
| ; RV32IFD-NEXT: sw a6, 12(sp) |
| ; RV32IFD-NEXT: fld ft1, 8(sp) |
| ; RV32IFD-NEXT: fadd.d ft0, ft1, ft0 |
| ; RV32IFD-NEXT: fsd ft0, 8(sp) |
| ; RV32IFD-NEXT: lw a0, 8(sp) |
| ; RV32IFD-NEXT: lw a1, 12(sp) |
| ; RV32IFD-NEXT: addi sp, sp, 16 |
| ; RV32IFD-NEXT: ret |
| %1 = fadd double %d, %e |
| ret double %1 |
| } |
| |
| define double @caller_double_split_reg_stack() nounwind { |
| ; RV32IFD-LABEL: caller_double_split_reg_stack: |
| ; RV32IFD: # %bb.0: |
| ; RV32IFD-NEXT: addi sp, sp, -32 |
| ; RV32IFD-NEXT: sw ra, 28(sp) |
| ; RV32IFD-NEXT: lui a0, %hi(.LCPI3_0) |
| ; RV32IFD-NEXT: addi a0, a0, %lo(.LCPI3_0) |
| ; RV32IFD-NEXT: fld ft0, 0(a0) |
| ; RV32IFD-NEXT: fsd ft0, 16(sp) |
| ; RV32IFD-NEXT: lw a7, 16(sp) |
| ; RV32IFD-NEXT: lw a0, 20(sp) |
| ; RV32IFD-NEXT: sw a0, 0(sp) |
| ; RV32IFD-NEXT: lui a0, %hi(.LCPI3_1) |
| ; RV32IFD-NEXT: addi a0, a0, %lo(.LCPI3_1) |
| ; RV32IFD-NEXT: fld ft0, 0(a0) |
| ; RV32IFD-NEXT: fsd ft0, 16(sp) |
| ; RV32IFD-NEXT: lw a5, 16(sp) |
| ; RV32IFD-NEXT: lw a6, 20(sp) |
| ; RV32IFD-NEXT: addi a0, zero, 1 |
| ; RV32IFD-NEXT: addi a1, zero, 2 |
| ; RV32IFD-NEXT: addi a3, zero, 3 |
| ; RV32IFD-NEXT: mv a2, zero |
| ; RV32IFD-NEXT: mv a4, zero |
| ; RV32IFD-NEXT: call callee_double_split_reg_stack |
| ; RV32IFD-NEXT: lw ra, 28(sp) |
| ; RV32IFD-NEXT: addi sp, sp, 32 |
| ; RV32IFD-NEXT: ret |
| %1 = call double @callee_double_split_reg_stack(i32 1, i64 2, i64 3, double 4.72, double 5.72) |
| ret double %1 |
| } |
| |
| define double @callee_double_stack(i64 %a, i64 %b, i64 %c, i64 %d, double %e, double %f) nounwind { |
| ; RV32IFD-LABEL: callee_double_stack: |
| ; RV32IFD: # %bb.0: |
| ; RV32IFD-NEXT: addi sp, sp, -16 |
| ; RV32IFD-NEXT: fld ft0, 24(sp) |
| ; RV32IFD-NEXT: fld ft1, 16(sp) |
| ; RV32IFD-NEXT: fadd.d ft0, ft1, ft0 |
| ; RV32IFD-NEXT: fsd ft0, 8(sp) |
| ; RV32IFD-NEXT: lw a0, 8(sp) |
| ; RV32IFD-NEXT: lw a1, 12(sp) |
| ; RV32IFD-NEXT: addi sp, sp, 16 |
| ; RV32IFD-NEXT: ret |
| %1 = fadd double %e, %f |
| ret double %1 |
| } |
| |
| define double @caller_double_stack() nounwind { |
| ; RV32IFD-LABEL: caller_double_stack: |
| ; RV32IFD: # %bb.0: |
| ; RV32IFD-NEXT: addi sp, sp, -32 |
| ; RV32IFD-NEXT: sw ra, 28(sp) |
| ; RV32IFD-NEXT: lui a0, 262510 |
| ; RV32IFD-NEXT: addi a0, a0, 327 |
| ; RV32IFD-NEXT: sw a0, 4(sp) |
| ; RV32IFD-NEXT: lui a0, 262574 |
| ; RV32IFD-NEXT: addi a0, a0, 327 |
| ; RV32IFD-NEXT: sw a0, 12(sp) |
| ; RV32IFD-NEXT: lui a0, 713032 |
| ; RV32IFD-NEXT: addi a0, a0, -1311 |
| ; RV32IFD-NEXT: sw a0, 0(sp) |
| ; RV32IFD-NEXT: sw a0, 8(sp) |
| ; RV32IFD-NEXT: addi a0, zero, 1 |
| ; RV32IFD-NEXT: addi a2, zero, 2 |
| ; RV32IFD-NEXT: addi a4, zero, 3 |
| ; RV32IFD-NEXT: addi a6, zero, 4 |
| ; RV32IFD-NEXT: mv a1, zero |
| ; RV32IFD-NEXT: mv a3, zero |
| ; RV32IFD-NEXT: mv a5, zero |
| ; RV32IFD-NEXT: mv a7, zero |
| ; RV32IFD-NEXT: call callee_double_stack |
| ; RV32IFD-NEXT: lw ra, 28(sp) |
| ; RV32IFD-NEXT: addi sp, sp, 32 |
| ; RV32IFD-NEXT: ret |
| %1 = call double @callee_double_stack(i64 1, i64 2, i64 3, i64 4, double 5.72, double 6.72) |
| ret double %1 |
| } |