1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \ 3; RUN: | FileCheck -check-prefix=RV32I-FPELIM %s 4; RUN: llc -mtriple=riscv32 -mattr=+f -target-abi ilp32f \ 5; RUN: -verify-machineinstrs < %s \ 6; RUN: | FileCheck -check-prefix=RV32I-FPELIM %s 7; RUN: llc -mtriple=riscv32 -verify-machineinstrs -frame-pointer=all < %s \ 8; RUN: | FileCheck -check-prefix=RV32I-WITHFP %s 9; RUN: llc -mtriple=riscv32 -verify-machineinstrs -frame-pointer=all \ 10; RUN: -mattr=+f -target-abi ilp32f < %s \ 11; RUN: | FileCheck -check-prefix=RV32I-WITHFP %s 12 13; This file contains tests that should have identical output for the ilp32, 14; and ilp32f. As well as calling convention details, we check that 15; ra and fp are consistently stored to fp-4 and fp-8. 16 17; Check that on RV32 ilp32[f], double is passed in a pair of registers. Unlike 18; the convention for varargs, this need not be an aligned pair. 19 20define i32 @callee_double_in_regs(i32 %a, double %b) nounwind { 21; RV32I-FPELIM-LABEL: callee_double_in_regs: 22; RV32I-FPELIM: # %bb.0: 23; RV32I-FPELIM-NEXT: addi sp, sp, -16 24; RV32I-FPELIM-NEXT: sw ra, 12(sp) # 4-byte Folded Spill 25; RV32I-FPELIM-NEXT: sw s0, 8(sp) # 4-byte Folded Spill 26; RV32I-FPELIM-NEXT: mv s0, a0 27; RV32I-FPELIM-NEXT: mv a0, a1 28; RV32I-FPELIM-NEXT: mv a1, a2 29; RV32I-FPELIM-NEXT: call __fixdfsi 30; RV32I-FPELIM-NEXT: add a0, s0, a0 31; RV32I-FPELIM-NEXT: lw ra, 12(sp) # 4-byte Folded Reload 32; RV32I-FPELIM-NEXT: lw s0, 8(sp) # 4-byte Folded Reload 33; RV32I-FPELIM-NEXT: addi sp, sp, 16 34; RV32I-FPELIM-NEXT: ret 35; 36; RV32I-WITHFP-LABEL: callee_double_in_regs: 37; RV32I-WITHFP: # %bb.0: 38; RV32I-WITHFP-NEXT: addi sp, sp, -16 39; RV32I-WITHFP-NEXT: sw ra, 12(sp) # 4-byte Folded Spill 40; RV32I-WITHFP-NEXT: sw s0, 8(sp) # 4-byte Folded Spill 41; RV32I-WITHFP-NEXT: sw s1, 4(sp) # 4-byte Folded Spill 42; RV32I-WITHFP-NEXT: addi s0, sp, 16 43; RV32I-WITHFP-NEXT: mv s1, a0 44; RV32I-WITHFP-NEXT: mv a0, a1 45; RV32I-WITHFP-NEXT: mv a1, a2 46; RV32I-WITHFP-NEXT: call __fixdfsi 47; RV32I-WITHFP-NEXT: add a0, s1, a0 48; RV32I-WITHFP-NEXT: lw ra, 12(sp) # 4-byte Folded Reload 49; RV32I-WITHFP-NEXT: lw s0, 8(sp) # 4-byte Folded Reload 50; RV32I-WITHFP-NEXT: lw s1, 4(sp) # 4-byte Folded Reload 51; RV32I-WITHFP-NEXT: addi sp, sp, 16 52; RV32I-WITHFP-NEXT: ret 53 %b_fptosi = fptosi double %b to i32 54 %1 = add i32 %a, %b_fptosi 55 ret i32 %1 56} 57 58define i32 @caller_double_in_regs() nounwind { 59; RV32I-FPELIM-LABEL: caller_double_in_regs: 60; RV32I-FPELIM: # %bb.0: 61; RV32I-FPELIM-NEXT: addi sp, sp, -16 62; RV32I-FPELIM-NEXT: sw ra, 12(sp) # 4-byte Folded Spill 63; RV32I-FPELIM-NEXT: li a0, 1 64; RV32I-FPELIM-NEXT: lui a2, 262144 65; RV32I-FPELIM-NEXT: li a1, 0 66; RV32I-FPELIM-NEXT: call callee_double_in_regs 67; RV32I-FPELIM-NEXT: lw ra, 12(sp) # 4-byte Folded Reload 68; RV32I-FPELIM-NEXT: addi sp, sp, 16 69; RV32I-FPELIM-NEXT: ret 70; 71; RV32I-WITHFP-LABEL: caller_double_in_regs: 72; RV32I-WITHFP: # %bb.0: 73; RV32I-WITHFP-NEXT: addi sp, sp, -16 74; RV32I-WITHFP-NEXT: sw ra, 12(sp) # 4-byte Folded Spill 75; RV32I-WITHFP-NEXT: sw s0, 8(sp) # 4-byte Folded Spill 76; RV32I-WITHFP-NEXT: addi s0, sp, 16 77; RV32I-WITHFP-NEXT: li a0, 1 78; RV32I-WITHFP-NEXT: lui a2, 262144 79; RV32I-WITHFP-NEXT: li a1, 0 80; RV32I-WITHFP-NEXT: call callee_double_in_regs 81; RV32I-WITHFP-NEXT: lw ra, 12(sp) # 4-byte Folded Reload 82; RV32I-WITHFP-NEXT: lw s0, 8(sp) # 4-byte Folded Reload 83; RV32I-WITHFP-NEXT: addi sp, sp, 16 84; RV32I-WITHFP-NEXT: ret 85 %1 = call i32 @callee_double_in_regs(i32 1, double 2.0) 86 ret i32 %1 87} 88 89; Check 2x*xlen values are aligned appropriately when passed on the stack 90; Must keep define on a single line due to an update_llc_test_checks.py limitation 91define i32 @callee_aligned_stack(i32 %a, i32 %b, fp128 %c, i32 %d, i32 %e, i64 %f, i32 %g, i32 %h, double %i, i32 %j, [2 x i32] %k) nounwind { 92; The double should be 8-byte aligned on the stack, but the two-element array 93; should only be 4-byte aligned 94; RV32I-FPELIM-LABEL: callee_aligned_stack: 95; RV32I-FPELIM: # %bb.0: 96; RV32I-FPELIM-NEXT: lw a0, 0(a2) 97; RV32I-FPELIM-NEXT: lw a1, 8(sp) 98; RV32I-FPELIM-NEXT: lw a2, 0(sp) 99; RV32I-FPELIM-NEXT: lw a3, 20(sp) 100; RV32I-FPELIM-NEXT: lw a4, 16(sp) 101; RV32I-FPELIM-NEXT: add a0, a0, a7 102; RV32I-FPELIM-NEXT: add a1, a2, a1 103; RV32I-FPELIM-NEXT: add a0, a0, a1 104; RV32I-FPELIM-NEXT: add a3, a4, a3 105; RV32I-FPELIM-NEXT: add a0, a0, a3 106; RV32I-FPELIM-NEXT: ret 107; 108; RV32I-WITHFP-LABEL: callee_aligned_stack: 109; RV32I-WITHFP: # %bb.0: 110; RV32I-WITHFP-NEXT: addi sp, sp, -16 111; RV32I-WITHFP-NEXT: sw ra, 12(sp) # 4-byte Folded Spill 112; RV32I-WITHFP-NEXT: sw s0, 8(sp) # 4-byte Folded Spill 113; RV32I-WITHFP-NEXT: addi s0, sp, 16 114; RV32I-WITHFP-NEXT: lw a0, 0(a2) 115; RV32I-WITHFP-NEXT: lw a1, 8(s0) 116; RV32I-WITHFP-NEXT: lw a2, 0(s0) 117; RV32I-WITHFP-NEXT: lw a3, 20(s0) 118; RV32I-WITHFP-NEXT: lw a4, 16(s0) 119; RV32I-WITHFP-NEXT: add a0, a0, a7 120; RV32I-WITHFP-NEXT: add a1, a2, a1 121; RV32I-WITHFP-NEXT: add a0, a0, a1 122; RV32I-WITHFP-NEXT: add a3, a4, a3 123; RV32I-WITHFP-NEXT: add a0, a0, a3 124; RV32I-WITHFP-NEXT: lw ra, 12(sp) # 4-byte Folded Reload 125; RV32I-WITHFP-NEXT: lw s0, 8(sp) # 4-byte Folded Reload 126; RV32I-WITHFP-NEXT: addi sp, sp, 16 127; RV32I-WITHFP-NEXT: ret 128 %1 = bitcast fp128 %c to i128 129 %2 = trunc i128 %1 to i32 130 %3 = add i32 %2, %g 131 %4 = add i32 %3, %h 132 %5 = bitcast double %i to i64 133 %6 = trunc i64 %5 to i32 134 %7 = add i32 %4, %6 135 %8 = add i32 %7, %j 136 %9 = extractvalue [2 x i32] %k, 0 137 %10 = add i32 %8, %9 138 ret i32 %10 139} 140 141define void @caller_aligned_stack() nounwind { 142; The double should be 8-byte aligned on the stack, but the two-element array 143; should only be 4-byte aligned 144; RV32I-FPELIM-LABEL: caller_aligned_stack: 145; RV32I-FPELIM: # %bb.0: 146; RV32I-FPELIM-NEXT: addi sp, sp, -64 147; RV32I-FPELIM-NEXT: sw ra, 60(sp) # 4-byte Folded Spill 148; RV32I-FPELIM-NEXT: sw s0, 56(sp) # 4-byte Folded Spill 149; RV32I-FPELIM-NEXT: li a5, 18 150; RV32I-FPELIM-NEXT: li a6, 17 151; RV32I-FPELIM-NEXT: li a7, 16 152; RV32I-FPELIM-NEXT: lui t0, 262236 153; RV32I-FPELIM-NEXT: lui t1, 377487 154; RV32I-FPELIM-NEXT: li t2, 15 155; RV32I-FPELIM-NEXT: lui t3, 262153 156; RV32I-FPELIM-NEXT: lui t4, 545260 157; RV32I-FPELIM-NEXT: lui t5, 964690 158; RV32I-FPELIM-NEXT: lui t6, 335544 159; RV32I-FPELIM-NEXT: lui s0, 688509 160; RV32I-FPELIM-NEXT: li a0, 1 161; RV32I-FPELIM-NEXT: li a1, 11 162; RV32I-FPELIM-NEXT: addi a2, sp, 32 163; RV32I-FPELIM-NEXT: li a3, 12 164; RV32I-FPELIM-NEXT: li a4, 13 165; RV32I-FPELIM-NEXT: sw a6, 20(sp) 166; RV32I-FPELIM-NEXT: sw a5, 24(sp) 167; RV32I-FPELIM-NEXT: li a6, 4 168; RV32I-FPELIM-NEXT: addi a5, t0, 655 169; RV32I-FPELIM-NEXT: addi t0, t1, 1475 170; RV32I-FPELIM-NEXT: sw t2, 0(sp) 171; RV32I-FPELIM-NEXT: sw t0, 8(sp) 172; RV32I-FPELIM-NEXT: sw a5, 12(sp) 173; RV32I-FPELIM-NEXT: sw a7, 16(sp) 174; RV32I-FPELIM-NEXT: li a7, 14 175; RV32I-FPELIM-NEXT: addi t0, t3, 491 176; RV32I-FPELIM-NEXT: addi t1, t4, -1967 177; RV32I-FPELIM-NEXT: addi t2, t5, -328 178; RV32I-FPELIM-NEXT: addi t3, t6, 1311 179; RV32I-FPELIM-NEXT: addi a5, s0, -2048 180; RV32I-FPELIM-NEXT: sw t3, 32(sp) 181; RV32I-FPELIM-NEXT: sw t2, 36(sp) 182; RV32I-FPELIM-NEXT: sw t1, 40(sp) 183; RV32I-FPELIM-NEXT: sw t0, 44(sp) 184; RV32I-FPELIM-NEXT: call callee_aligned_stack 185; RV32I-FPELIM-NEXT: lw ra, 60(sp) # 4-byte Folded Reload 186; RV32I-FPELIM-NEXT: lw s0, 56(sp) # 4-byte Folded Reload 187; RV32I-FPELIM-NEXT: addi sp, sp, 64 188; RV32I-FPELIM-NEXT: ret 189; 190; RV32I-WITHFP-LABEL: caller_aligned_stack: 191; RV32I-WITHFP: # %bb.0: 192; RV32I-WITHFP-NEXT: addi sp, sp, -64 193; RV32I-WITHFP-NEXT: sw ra, 60(sp) # 4-byte Folded Spill 194; RV32I-WITHFP-NEXT: sw s0, 56(sp) # 4-byte Folded Spill 195; RV32I-WITHFP-NEXT: sw s1, 52(sp) # 4-byte Folded Spill 196; RV32I-WITHFP-NEXT: addi s0, sp, 64 197; RV32I-WITHFP-NEXT: li a5, 18 198; RV32I-WITHFP-NEXT: li a6, 17 199; RV32I-WITHFP-NEXT: li a7, 16 200; RV32I-WITHFP-NEXT: lui t0, 262236 201; RV32I-WITHFP-NEXT: lui t1, 377487 202; RV32I-WITHFP-NEXT: li t2, 15 203; RV32I-WITHFP-NEXT: lui t3, 262153 204; RV32I-WITHFP-NEXT: lui t4, 545260 205; RV32I-WITHFP-NEXT: lui t5, 964690 206; RV32I-WITHFP-NEXT: lui t6, 335544 207; RV32I-WITHFP-NEXT: lui s1, 688509 208; RV32I-WITHFP-NEXT: li a0, 1 209; RV32I-WITHFP-NEXT: li a1, 11 210; RV32I-WITHFP-NEXT: addi a2, s0, -32 211; RV32I-WITHFP-NEXT: li a3, 12 212; RV32I-WITHFP-NEXT: li a4, 13 213; RV32I-WITHFP-NEXT: sw a6, 20(sp) 214; RV32I-WITHFP-NEXT: sw a5, 24(sp) 215; RV32I-WITHFP-NEXT: li a6, 4 216; RV32I-WITHFP-NEXT: addi a5, t0, 655 217; RV32I-WITHFP-NEXT: addi t0, t1, 1475 218; RV32I-WITHFP-NEXT: sw t2, 0(sp) 219; RV32I-WITHFP-NEXT: sw t0, 8(sp) 220; RV32I-WITHFP-NEXT: sw a5, 12(sp) 221; RV32I-WITHFP-NEXT: sw a7, 16(sp) 222; RV32I-WITHFP-NEXT: li a7, 14 223; RV32I-WITHFP-NEXT: addi t0, t3, 491 224; RV32I-WITHFP-NEXT: addi t1, t4, -1967 225; RV32I-WITHFP-NEXT: addi t2, t5, -328 226; RV32I-WITHFP-NEXT: addi t3, t6, 1311 227; RV32I-WITHFP-NEXT: addi a5, s1, -2048 228; RV32I-WITHFP-NEXT: sw t3, -32(s0) 229; RV32I-WITHFP-NEXT: sw t2, -28(s0) 230; RV32I-WITHFP-NEXT: sw t1, -24(s0) 231; RV32I-WITHFP-NEXT: sw t0, -20(s0) 232; RV32I-WITHFP-NEXT: call callee_aligned_stack 233; RV32I-WITHFP-NEXT: lw ra, 60(sp) # 4-byte Folded Reload 234; RV32I-WITHFP-NEXT: lw s0, 56(sp) # 4-byte Folded Reload 235; RV32I-WITHFP-NEXT: lw s1, 52(sp) # 4-byte Folded Reload 236; RV32I-WITHFP-NEXT: addi sp, sp, 64 237; RV32I-WITHFP-NEXT: ret 238 %1 = call i32 @callee_aligned_stack(i32 1, i32 11, 239 fp128 0xLEB851EB851EB851F400091EB851EB851, i32 12, i32 13, 240 i64 20000000000, i32 14, i32 15, double 2.720000e+00, i32 16, 241 [2 x i32] [i32 17, i32 18]) 242 ret void 243} 244 245define double @callee_small_scalar_ret() nounwind { 246; RV32I-FPELIM-LABEL: callee_small_scalar_ret: 247; RV32I-FPELIM: # %bb.0: 248; RV32I-FPELIM-NEXT: lui a1, 261888 249; RV32I-FPELIM-NEXT: li a0, 0 250; RV32I-FPELIM-NEXT: ret 251; 252; RV32I-WITHFP-LABEL: callee_small_scalar_ret: 253; RV32I-WITHFP: # %bb.0: 254; RV32I-WITHFP-NEXT: addi sp, sp, -16 255; RV32I-WITHFP-NEXT: sw ra, 12(sp) # 4-byte Folded Spill 256; RV32I-WITHFP-NEXT: sw s0, 8(sp) # 4-byte Folded Spill 257; RV32I-WITHFP-NEXT: addi s0, sp, 16 258; RV32I-WITHFP-NEXT: lui a1, 261888 259; RV32I-WITHFP-NEXT: li a0, 0 260; RV32I-WITHFP-NEXT: lw ra, 12(sp) # 4-byte Folded Reload 261; RV32I-WITHFP-NEXT: lw s0, 8(sp) # 4-byte Folded Reload 262; RV32I-WITHFP-NEXT: addi sp, sp, 16 263; RV32I-WITHFP-NEXT: ret 264 ret double 1.0 265} 266 267define i64 @caller_small_scalar_ret() nounwind { 268; RV32I-FPELIM-LABEL: caller_small_scalar_ret: 269; RV32I-FPELIM: # %bb.0: 270; RV32I-FPELIM-NEXT: addi sp, sp, -16 271; RV32I-FPELIM-NEXT: sw ra, 12(sp) # 4-byte Folded Spill 272; RV32I-FPELIM-NEXT: call callee_small_scalar_ret 273; RV32I-FPELIM-NEXT: lw ra, 12(sp) # 4-byte Folded Reload 274; RV32I-FPELIM-NEXT: addi sp, sp, 16 275; RV32I-FPELIM-NEXT: ret 276; 277; RV32I-WITHFP-LABEL: caller_small_scalar_ret: 278; RV32I-WITHFP: # %bb.0: 279; RV32I-WITHFP-NEXT: addi sp, sp, -16 280; RV32I-WITHFP-NEXT: sw ra, 12(sp) # 4-byte Folded Spill 281; RV32I-WITHFP-NEXT: sw s0, 8(sp) # 4-byte Folded Spill 282; RV32I-WITHFP-NEXT: addi s0, sp, 16 283; RV32I-WITHFP-NEXT: call callee_small_scalar_ret 284; RV32I-WITHFP-NEXT: lw ra, 12(sp) # 4-byte Folded Reload 285; RV32I-WITHFP-NEXT: lw s0, 8(sp) # 4-byte Folded Reload 286; RV32I-WITHFP-NEXT: addi sp, sp, 16 287; RV32I-WITHFP-NEXT: ret 288 %1 = call double @callee_small_scalar_ret() 289 %2 = bitcast double %1 to i64 290 ret i64 %2 291} 292