1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2 ; RUN: llc -mtriple=riscv32 -mattr=+d -verify-machineinstrs < %s \ 3 ; RUN: | FileCheck -check-prefix=RV32IFD %s 4 5 ; Sanity checks for calling convention lowering for RV32D. This can be 6 ; somewhat error-prone for soft-float RV32D due to the fact that f64 is legal 7 ; but i64 is not, and there is no instruction to move values directly between 8 ; the GPRs and 64-bit FPRs. 9 10 define double @callee_double_inreg(double %a, double %b) nounwind { 11 ; RV32IFD-LABEL: callee_double_inreg: 12 ; RV32IFD: # %bb.0: 13 ; RV32IFD-NEXT: addi sp, sp, -16 14 ; RV32IFD-NEXT: sw a2, 8(sp) 15 ; RV32IFD-NEXT: sw a3, 12(sp) 16 ; RV32IFD-NEXT: fld ft0, 8(sp) 17 ; RV32IFD-NEXT: sw a0, 8(sp) 18 ; RV32IFD-NEXT: sw a1, 12(sp) 19 ; RV32IFD-NEXT: fld ft1, 8(sp) 20 ; RV32IFD-NEXT: fadd.d ft0, ft1, ft0 21 ; RV32IFD-NEXT: fsd ft0, 8(sp) 22 ; RV32IFD-NEXT: lw a0, 8(sp) 23 ; RV32IFD-NEXT: lw a1, 12(sp) 24 ; RV32IFD-NEXT: addi sp, sp, 16 25 ; RV32IFD-NEXT: ret 26 %1 = fadd double %a, %b 27 ret double %1 28 } 29 30 ; TODO: code quality for loading and then passing f64 constants is poor. 31 32 define double @caller_double_inreg() nounwind { 33 ; RV32IFD-LABEL: caller_double_inreg: 34 ; RV32IFD: # %bb.0: 35 ; RV32IFD-NEXT: addi sp, sp, -16 36 ; RV32IFD-NEXT: sw ra, 12(sp) 37 ; RV32IFD-NEXT: lui a0, %hi(.LCPI1_0) 38 ; RV32IFD-NEXT: addi a0, a0, %lo(.LCPI1_0) 39 ; RV32IFD-NEXT: fld ft0, 0(a0) 40 ; RV32IFD-NEXT: lui a0, %hi(.LCPI1_1) 41 ; RV32IFD-NEXT: addi a0, a0, %lo(.LCPI1_1) 42 ; RV32IFD-NEXT: fld ft1, 0(a0) 43 ; RV32IFD-NEXT: fsd ft1, 0(sp) 44 ; RV32IFD-NEXT: lw a0, 0(sp) 45 ; RV32IFD-NEXT: lw a1, 4(sp) 46 ; RV32IFD-NEXT: fsd ft0, 0(sp) 47 ; RV32IFD-NEXT: lw a2, 0(sp) 48 ; RV32IFD-NEXT: lw a3, 4(sp) 49 ; RV32IFD-NEXT: call callee_double_inreg 50 ; RV32IFD-NEXT: lw ra, 12(sp) 51 ; RV32IFD-NEXT: addi sp, sp, 16 52 ; RV32IFD-NEXT: ret 53 %1 = call double @callee_double_inreg(double 2.720000e+00, double 3.720000e+00) 54 ret double %1 55 } 56 57 define double @callee_double_split_reg_stack(i32 %a, i64 %b, i64 %c, double %d, double %e) nounwind { 58 ; RV32IFD-LABEL: callee_double_split_reg_stack: 59 ; RV32IFD: # %bb.0: 60 ; RV32IFD-NEXT: addi sp, sp, -16 61 ; RV32IFD-NEXT: lw a0, 16(sp) 62 ; RV32IFD-NEXT: sw a7, 8(sp) 63 ; RV32IFD-NEXT: sw a0, 12(sp) 64 ; RV32IFD-NEXT: fld ft0, 8(sp) 65 ; RV32IFD-NEXT: sw a5, 8(sp) 66 ; RV32IFD-NEXT: sw a6, 12(sp) 67 ; RV32IFD-NEXT: fld ft1, 8(sp) 68 ; RV32IFD-NEXT: fadd.d ft0, ft1, ft0 69 ; RV32IFD-NEXT: fsd ft0, 8(sp) 70 ; RV32IFD-NEXT: lw a0, 8(sp) 71 ; RV32IFD-NEXT: lw a1, 12(sp) 72 ; RV32IFD-NEXT: addi sp, sp, 16 73 ; RV32IFD-NEXT: ret 74 %1 = fadd double %d, %e 75 ret double %1 76 } 77 78 define double @caller_double_split_reg_stack() nounwind { 79 ; RV32IFD-LABEL: caller_double_split_reg_stack: 80 ; RV32IFD: # %bb.0: 81 ; RV32IFD-NEXT: addi sp, sp, -32 82 ; RV32IFD-NEXT: sw ra, 28(sp) 83 ; RV32IFD-NEXT: lui a0, %hi(.LCPI3_0) 84 ; RV32IFD-NEXT: addi a0, a0, %lo(.LCPI3_0) 85 ; RV32IFD-NEXT: fld ft0, 0(a0) 86 ; RV32IFD-NEXT: fsd ft0, 16(sp) 87 ; RV32IFD-NEXT: lw a7, 16(sp) 88 ; RV32IFD-NEXT: lw a0, 20(sp) 89 ; RV32IFD-NEXT: sw a0, 0(sp) 90 ; RV32IFD-NEXT: lui a0, %hi(.LCPI3_1) 91 ; RV32IFD-NEXT: addi a0, a0, %lo(.LCPI3_1) 92 ; RV32IFD-NEXT: fld ft0, 0(a0) 93 ; RV32IFD-NEXT: fsd ft0, 16(sp) 94 ; RV32IFD-NEXT: lw a5, 16(sp) 95 ; RV32IFD-NEXT: lw a6, 20(sp) 96 ; RV32IFD-NEXT: addi a0, zero, 1 97 ; RV32IFD-NEXT: addi a1, zero, 2 98 ; RV32IFD-NEXT: addi a3, zero, 3 99 ; RV32IFD-NEXT: mv a2, zero 100 ; RV32IFD-NEXT: mv a4, zero 101 ; RV32IFD-NEXT: call callee_double_split_reg_stack 102 ; RV32IFD-NEXT: lw ra, 28(sp) 103 ; RV32IFD-NEXT: addi sp, sp, 32 104 ; RV32IFD-NEXT: ret 105 %1 = call double @callee_double_split_reg_stack(i32 1, i64 2, i64 3, double 4.72, double 5.72) 106 ret double %1 107 } 108 109 define double @callee_double_stack(i64 %a, i64 %b, i64 %c, i64 %d, double %e, double %f) nounwind { 110 ; RV32IFD-LABEL: callee_double_stack: 111 ; RV32IFD: # %bb.0: 112 ; RV32IFD-NEXT: addi sp, sp, -16 113 ; RV32IFD-NEXT: fld ft0, 24(sp) 114 ; RV32IFD-NEXT: fld ft1, 16(sp) 115 ; RV32IFD-NEXT: fadd.d ft0, ft1, ft0 116 ; RV32IFD-NEXT: fsd ft0, 8(sp) 117 ; RV32IFD-NEXT: lw a0, 8(sp) 118 ; RV32IFD-NEXT: lw a1, 12(sp) 119 ; RV32IFD-NEXT: addi sp, sp, 16 120 ; RV32IFD-NEXT: ret 121 %1 = fadd double %e, %f 122 ret double %1 123 } 124 125 define double @caller_double_stack() nounwind { 126 ; RV32IFD-LABEL: caller_double_stack: 127 ; RV32IFD: # %bb.0: 128 ; RV32IFD-NEXT: addi sp, sp, -32 129 ; RV32IFD-NEXT: sw ra, 28(sp) 130 ; RV32IFD-NEXT: lui a0, 262510 131 ; RV32IFD-NEXT: addi a0, a0, 327 132 ; RV32IFD-NEXT: sw a0, 4(sp) 133 ; RV32IFD-NEXT: lui a0, 262574 134 ; RV32IFD-NEXT: addi a0, a0, 327 135 ; RV32IFD-NEXT: sw a0, 12(sp) 136 ; RV32IFD-NEXT: lui a0, 713032 137 ; RV32IFD-NEXT: addi a0, a0, -1311 138 ; RV32IFD-NEXT: sw a0, 0(sp) 139 ; RV32IFD-NEXT: sw a0, 8(sp) 140 ; RV32IFD-NEXT: addi a0, zero, 1 141 ; RV32IFD-NEXT: addi a2, zero, 2 142 ; RV32IFD-NEXT: addi a4, zero, 3 143 ; RV32IFD-NEXT: addi a6, zero, 4 144 ; RV32IFD-NEXT: mv a1, zero 145 ; RV32IFD-NEXT: mv a3, zero 146 ; RV32IFD-NEXT: mv a5, zero 147 ; RV32IFD-NEXT: mv a7, zero 148 ; RV32IFD-NEXT: call callee_double_stack 149 ; RV32IFD-NEXT: lw ra, 28(sp) 150 ; RV32IFD-NEXT: addi sp, sp, 32 151 ; RV32IFD-NEXT: ret 152 %1 = call double @callee_double_stack(i64 1, i64 2, i64 3, i64 4, double 5.72, double 6.72) 153 ret double %1 154 } 155