| ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py | |
| ; RUN: llc -mtriple=riscv32 -mattr=+d -target-abi=ilp32 -verify-machineinstrs < %s \ | |
| ; RUN: | FileCheck -check-prefix=RV32IFD %s | |
| ; RUN: llc -mtriple=riscv32 -mattr=+zdinx -target-abi=ilp32 -verify-machineinstrs < %s \ | |
| ; RUN: | FileCheck -check-prefix=RV32IZFINXZDINX %s | |
| ; Basic correctness 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 fa5, 8(sp) | |
| ; RV32IFD-NEXT: sw a0, 8(sp) | |
| ; RV32IFD-NEXT: sw a1, 12(sp) | |
| ; RV32IFD-NEXT: fld fa4, 8(sp) | |
| ; RV32IFD-NEXT: fadd.d fa5, fa4, fa5 | |
| ; RV32IFD-NEXT: fsd fa5, 8(sp) | |
| ; RV32IFD-NEXT: lw a0, 8(sp) | |
| ; RV32IFD-NEXT: lw a1, 12(sp) | |
| ; RV32IFD-NEXT: addi sp, sp, 16 | |
| ; RV32IFD-NEXT: ret | |
| ; | |
| ; RV32IZFINXZDINX-LABEL: callee_double_inreg: | |
| ; RV32IZFINXZDINX: # %bb.0: | |
| ; RV32IZFINXZDINX-NEXT: fadd.d a0, a0, a2 | |
| ; RV32IZFINXZDINX-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) # 4-byte Folded Spill | |
| ; RV32IFD-NEXT: lui a0, 262236 | |
| ; RV32IFD-NEXT: lui a2, 377487 | |
| ; RV32IFD-NEXT: lui a3, 262364 | |
| ; RV32IFD-NEXT: addi a1, a0, 655 | |
| ; RV32IFD-NEXT: addi a0, a2, 1475 | |
| ; RV32IFD-NEXT: addi a3, a3, 655 | |
| ; RV32IFD-NEXT: mv a2, a0 | |
| ; RV32IFD-NEXT: call callee_double_inreg | |
| ; RV32IFD-NEXT: lw ra, 12(sp) # 4-byte Folded Reload | |
| ; RV32IFD-NEXT: addi sp, sp, 16 | |
| ; RV32IFD-NEXT: ret | |
| ; | |
| ; RV32IZFINXZDINX-LABEL: caller_double_inreg: | |
| ; RV32IZFINXZDINX: # %bb.0: | |
| ; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 | |
| ; RV32IZFINXZDINX-NEXT: sw ra, 12(sp) # 4-byte Folded Spill | |
| ; RV32IZFINXZDINX-NEXT: lui a0, 262236 | |
| ; RV32IZFINXZDINX-NEXT: lui a2, 377487 | |
| ; RV32IZFINXZDINX-NEXT: lui a3, 262364 | |
| ; RV32IZFINXZDINX-NEXT: addi a1, a0, 655 | |
| ; RV32IZFINXZDINX-NEXT: addi a0, a2, 1475 | |
| ; RV32IZFINXZDINX-NEXT: addi a3, a3, 655 | |
| ; RV32IZFINXZDINX-NEXT: mv a2, a0 | |
| ; RV32IZFINXZDINX-NEXT: call callee_double_inreg | |
| ; RV32IZFINXZDINX-NEXT: lw ra, 12(sp) # 4-byte Folded Reload | |
| ; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 | |
| ; RV32IZFINXZDINX-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 fa5, 8(sp) | |
| ; RV32IFD-NEXT: sw a5, 8(sp) | |
| ; RV32IFD-NEXT: sw a6, 12(sp) | |
| ; RV32IFD-NEXT: fld fa4, 8(sp) | |
| ; RV32IFD-NEXT: fadd.d fa5, fa4, fa5 | |
| ; RV32IFD-NEXT: fsd fa5, 8(sp) | |
| ; RV32IFD-NEXT: lw a0, 8(sp) | |
| ; RV32IFD-NEXT: lw a1, 12(sp) | |
| ; RV32IFD-NEXT: addi sp, sp, 16 | |
| ; RV32IFD-NEXT: ret | |
| ; | |
| ; RV32IZFINXZDINX-LABEL: callee_double_split_reg_stack: | |
| ; RV32IZFINXZDINX: # %bb.0: | |
| ; RV32IZFINXZDINX-NEXT: mv a0, a7 | |
| ; RV32IZFINXZDINX-NEXT: lw a1, 0(sp) | |
| ; RV32IZFINXZDINX-NEXT: mv a3, a6 | |
| ; RV32IZFINXZDINX-NEXT: mv a2, a5 | |
| ; RV32IZFINXZDINX-NEXT: fadd.d a0, a2, a0 | |
| ; RV32IZFINXZDINX-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, -16 | |
| ; RV32IFD-NEXT: sw ra, 12(sp) # 4-byte Folded Spill | |
| ; RV32IFD-NEXT: lui a0, 262510 | |
| ; RV32IFD-NEXT: lui a1, 262446 | |
| ; RV32IFD-NEXT: lui a2, 713032 | |
| ; RV32IFD-NEXT: addi t0, a0, 327 | |
| ; RV32IFD-NEXT: addi a6, a1, 327 | |
| ; RV32IFD-NEXT: addi a5, a2, -1311 | |
| ; RV32IFD-NEXT: li a0, 1 | |
| ; RV32IFD-NEXT: li a1, 2 | |
| ; RV32IFD-NEXT: li a3, 3 | |
| ; RV32IFD-NEXT: li a2, 0 | |
| ; RV32IFD-NEXT: li a4, 0 | |
| ; RV32IFD-NEXT: mv a7, a5 | |
| ; RV32IFD-NEXT: sw t0, 0(sp) | |
| ; RV32IFD-NEXT: call callee_double_split_reg_stack | |
| ; RV32IFD-NEXT: lw ra, 12(sp) # 4-byte Folded Reload | |
| ; RV32IFD-NEXT: addi sp, sp, 16 | |
| ; RV32IFD-NEXT: ret | |
| ; | |
| ; RV32IZFINXZDINX-LABEL: caller_double_split_reg_stack: | |
| ; RV32IZFINXZDINX: # %bb.0: | |
| ; RV32IZFINXZDINX-NEXT: addi sp, sp, -16 | |
| ; RV32IZFINXZDINX-NEXT: sw ra, 12(sp) # 4-byte Folded Spill | |
| ; RV32IZFINXZDINX-NEXT: lui a0, 262510 | |
| ; RV32IZFINXZDINX-NEXT: lui a1, 262446 | |
| ; RV32IZFINXZDINX-NEXT: lui a2, 713032 | |
| ; RV32IZFINXZDINX-NEXT: addi t0, a0, 327 | |
| ; RV32IZFINXZDINX-NEXT: addi a6, a1, 327 | |
| ; RV32IZFINXZDINX-NEXT: addi a5, a2, -1311 | |
| ; RV32IZFINXZDINX-NEXT: li a0, 1 | |
| ; RV32IZFINXZDINX-NEXT: li a1, 2 | |
| ; RV32IZFINXZDINX-NEXT: li a3, 3 | |
| ; RV32IZFINXZDINX-NEXT: li a2, 0 | |
| ; RV32IZFINXZDINX-NEXT: li a4, 0 | |
| ; RV32IZFINXZDINX-NEXT: mv a7, a5 | |
| ; RV32IZFINXZDINX-NEXT: sw t0, 0(sp) | |
| ; RV32IZFINXZDINX-NEXT: call callee_double_split_reg_stack | |
| ; RV32IZFINXZDINX-NEXT: lw ra, 12(sp) # 4-byte Folded Reload | |
| ; RV32IZFINXZDINX-NEXT: addi sp, sp, 16 | |
| ; RV32IZFINXZDINX-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 fa5, 24(sp) | |
| ; RV32IFD-NEXT: fld fa4, 16(sp) | |
| ; RV32IFD-NEXT: fadd.d fa5, fa4, fa5 | |
| ; RV32IFD-NEXT: fsd fa5, 8(sp) | |
| ; RV32IFD-NEXT: lw a0, 8(sp) | |
| ; RV32IFD-NEXT: lw a1, 12(sp) | |
| ; RV32IFD-NEXT: addi sp, sp, 16 | |
| ; RV32IFD-NEXT: ret | |
| ; | |
| ; RV32IZFINXZDINX-LABEL: callee_double_stack: | |
| ; RV32IZFINXZDINX: # %bb.0: | |
| ; RV32IZFINXZDINX-NEXT: lw a1, 12(sp) | |
| ; RV32IZFINXZDINX-NEXT: lw a3, 4(sp) | |
| ; RV32IZFINXZDINX-NEXT: lw a0, 8(sp) | |
| ; RV32IZFINXZDINX-NEXT: lw a2, 0(sp) | |
| ; RV32IZFINXZDINX-NEXT: fadd.d a0, a2, a0 | |
| ; RV32IZFINXZDINX-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) # 4-byte Folded Spill | |
| ; RV32IFD-NEXT: li a1, 0 | |
| ; RV32IFD-NEXT: li a3, 0 | |
| ; RV32IFD-NEXT: li a5, 0 | |
| ; RV32IFD-NEXT: li a7, 0 | |
| ; RV32IFD-NEXT: lui a0, 262510 | |
| ; RV32IFD-NEXT: addi t0, a0, 327 | |
| ; RV32IFD-NEXT: lui a0, 713032 | |
| ; RV32IFD-NEXT: lui a2, 262574 | |
| ; RV32IFD-NEXT: addi t1, a0, -1311 | |
| ; RV32IFD-NEXT: addi t2, a2, 327 | |
| ; RV32IFD-NEXT: li a0, 1 | |
| ; RV32IFD-NEXT: li a2, 2 | |
| ; RV32IFD-NEXT: li a4, 3 | |
| ; RV32IFD-NEXT: li a6, 4 | |
| ; RV32IFD-NEXT: sw t1, 0(sp) | |
| ; RV32IFD-NEXT: sw t0, 4(sp) | |
| ; RV32IFD-NEXT: sw t1, 8(sp) | |
| ; RV32IFD-NEXT: sw t2, 12(sp) | |
| ; RV32IFD-NEXT: call callee_double_stack | |
| ; RV32IFD-NEXT: lw ra, 28(sp) # 4-byte Folded Reload | |
| ; RV32IFD-NEXT: addi sp, sp, 32 | |
| ; RV32IFD-NEXT: ret | |
| ; | |
| ; RV32IZFINXZDINX-LABEL: caller_double_stack: | |
| ; RV32IZFINXZDINX: # %bb.0: | |
| ; RV32IZFINXZDINX-NEXT: addi sp, sp, -32 | |
| ; RV32IZFINXZDINX-NEXT: sw ra, 28(sp) # 4-byte Folded Spill | |
| ; RV32IZFINXZDINX-NEXT: li a1, 0 | |
| ; RV32IZFINXZDINX-NEXT: li a3, 0 | |
| ; RV32IZFINXZDINX-NEXT: li a5, 0 | |
| ; RV32IZFINXZDINX-NEXT: li a7, 0 | |
| ; RV32IZFINXZDINX-NEXT: lui a0, 262510 | |
| ; RV32IZFINXZDINX-NEXT: addi t0, a0, 327 | |
| ; RV32IZFINXZDINX-NEXT: lui a0, 713032 | |
| ; RV32IZFINXZDINX-NEXT: lui a2, 262574 | |
| ; RV32IZFINXZDINX-NEXT: addi t1, a0, -1311 | |
| ; RV32IZFINXZDINX-NEXT: addi t2, a2, 327 | |
| ; RV32IZFINXZDINX-NEXT: li a0, 1 | |
| ; RV32IZFINXZDINX-NEXT: li a2, 2 | |
| ; RV32IZFINXZDINX-NEXT: li a4, 3 | |
| ; RV32IZFINXZDINX-NEXT: li a6, 4 | |
| ; RV32IZFINXZDINX-NEXT: sw t1, 0(sp) | |
| ; RV32IZFINXZDINX-NEXT: sw t0, 4(sp) | |
| ; RV32IZFINXZDINX-NEXT: sw t1, 8(sp) | |
| ; RV32IZFINXZDINX-NEXT: sw t2, 12(sp) | |
| ; RV32IZFINXZDINX-NEXT: call callee_double_stack | |
| ; RV32IZFINXZDINX-NEXT: lw ra, 28(sp) # 4-byte Folded Reload | |
| ; RV32IZFINXZDINX-NEXT: addi sp, sp, 32 | |
| ; RV32IZFINXZDINX-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 | |
| } | |
| define double @func_return_double_undef() nounwind { | |
| ; RV32IFD-LABEL: func_return_double_undef: | |
| ; RV32IFD: # %bb.0: | |
| ; RV32IFD-NEXT: ret | |
| ; | |
| ; RV32IZFINXZDINX-LABEL: func_return_double_undef: | |
| ; RV32IZFINXZDINX: # %bb.0: | |
| ; RV32IZFINXZDINX-NEXT: ret | |
| ret double poison | |
| } |