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 10define 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 32define 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 57define 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 78define 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 109define 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 125define 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