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) 25; RV32I-FPELIM-NEXT: sw s0, 8(sp) 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 s0, 8(sp) 32; RV32I-FPELIM-NEXT: lw ra, 12(sp) 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) 40; RV32I-WITHFP-NEXT: sw s0, 8(sp) 41; RV32I-WITHFP-NEXT: sw s1, 4(sp) 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 s1, 4(sp) 49; RV32I-WITHFP-NEXT: lw s0, 8(sp) 50; RV32I-WITHFP-NEXT: lw ra, 12(sp) 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) 63; RV32I-FPELIM-NEXT: addi a0, zero, 1 64; RV32I-FPELIM-NEXT: lui a2, 262144 65; RV32I-FPELIM-NEXT: mv a1, zero 66; RV32I-FPELIM-NEXT: call callee_double_in_regs 67; RV32I-FPELIM-NEXT: lw ra, 12(sp) 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) 75; RV32I-WITHFP-NEXT: sw s0, 8(sp) 76; RV32I-WITHFP-NEXT: addi s0, sp, 16 77; RV32I-WITHFP-NEXT: addi a0, zero, 1 78; RV32I-WITHFP-NEXT: lui a2, 262144 79; RV32I-WITHFP-NEXT: mv a1, zero 80; RV32I-WITHFP-NEXT: call callee_double_in_regs 81; RV32I-WITHFP-NEXT: lw s0, 8(sp) 82; RV32I-WITHFP-NEXT: lw ra, 12(sp) 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, 20(sp) 98; RV32I-FPELIM-NEXT: lw a2, 0(sp) 99; RV32I-FPELIM-NEXT: lw a3, 8(sp) 100; RV32I-FPELIM-NEXT: lw a4, 16(sp) 101; RV32I-FPELIM-NEXT: add a0, a0, a7 102; RV32I-FPELIM-NEXT: add a0, a0, a2 103; RV32I-FPELIM-NEXT: add a0, a0, a3 104; RV32I-FPELIM-NEXT: add a0, a0, a4 105; RV32I-FPELIM-NEXT: add a0, a0, a1 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) 112; RV32I-WITHFP-NEXT: sw s0, 8(sp) 113; RV32I-WITHFP-NEXT: addi s0, sp, 16 114; RV32I-WITHFP-NEXT: lw a0, 0(a2) 115; RV32I-WITHFP-NEXT: lw a1, 20(s0) 116; RV32I-WITHFP-NEXT: lw a2, 0(s0) 117; RV32I-WITHFP-NEXT: lw a3, 8(s0) 118; RV32I-WITHFP-NEXT: lw a4, 16(s0) 119; RV32I-WITHFP-NEXT: add a0, a0, a7 120; RV32I-WITHFP-NEXT: add a0, a0, a2 121; RV32I-WITHFP-NEXT: add a0, a0, a3 122; RV32I-WITHFP-NEXT: add a0, a0, a4 123; RV32I-WITHFP-NEXT: add a0, a0, a1 124; RV32I-WITHFP-NEXT: lw s0, 8(sp) 125; RV32I-WITHFP-NEXT: lw ra, 12(sp) 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) 148; RV32I-FPELIM-NEXT: addi a0, zero, 18 149; RV32I-FPELIM-NEXT: sw a0, 24(sp) 150; RV32I-FPELIM-NEXT: addi a0, zero, 17 151; RV32I-FPELIM-NEXT: sw a0, 20(sp) 152; RV32I-FPELIM-NEXT: addi a0, zero, 16 153; RV32I-FPELIM-NEXT: sw a0, 16(sp) 154; RV32I-FPELIM-NEXT: lui a0, 262236 155; RV32I-FPELIM-NEXT: addi a0, a0, 655 156; RV32I-FPELIM-NEXT: sw a0, 12(sp) 157; RV32I-FPELIM-NEXT: lui a0, 377487 158; RV32I-FPELIM-NEXT: addi a0, a0, 1475 159; RV32I-FPELIM-NEXT: sw a0, 8(sp) 160; RV32I-FPELIM-NEXT: addi a0, zero, 15 161; RV32I-FPELIM-NEXT: sw a0, 0(sp) 162; RV32I-FPELIM-NEXT: lui a0, 262153 163; RV32I-FPELIM-NEXT: addi a0, a0, 491 164; RV32I-FPELIM-NEXT: sw a0, 44(sp) 165; RV32I-FPELIM-NEXT: lui a0, 545260 166; RV32I-FPELIM-NEXT: addi a0, a0, -1967 167; RV32I-FPELIM-NEXT: sw a0, 40(sp) 168; RV32I-FPELIM-NEXT: lui a0, 964690 169; RV32I-FPELIM-NEXT: addi a0, a0, -328 170; RV32I-FPELIM-NEXT: sw a0, 36(sp) 171; RV32I-FPELIM-NEXT: lui a0, 335544 172; RV32I-FPELIM-NEXT: addi t0, a0, 1311 173; RV32I-FPELIM-NEXT: lui a0, 688509 174; RV32I-FPELIM-NEXT: addi a5, a0, -2048 175; RV32I-FPELIM-NEXT: addi a0, zero, 1 176; RV32I-FPELIM-NEXT: addi a1, zero, 11 177; RV32I-FPELIM-NEXT: addi a2, sp, 32 178; RV32I-FPELIM-NEXT: addi a3, zero, 12 179; RV32I-FPELIM-NEXT: addi a4, zero, 13 180; RV32I-FPELIM-NEXT: addi a6, zero, 4 181; RV32I-FPELIM-NEXT: addi a7, zero, 14 182; RV32I-FPELIM-NEXT: sw t0, 32(sp) 183; RV32I-FPELIM-NEXT: call callee_aligned_stack 184; RV32I-FPELIM-NEXT: lw ra, 60(sp) 185; RV32I-FPELIM-NEXT: addi sp, sp, 64 186; RV32I-FPELIM-NEXT: ret 187; 188; RV32I-WITHFP-LABEL: caller_aligned_stack: 189; RV32I-WITHFP: # %bb.0: 190; RV32I-WITHFP-NEXT: addi sp, sp, -64 191; RV32I-WITHFP-NEXT: sw ra, 60(sp) 192; RV32I-WITHFP-NEXT: sw s0, 56(sp) 193; RV32I-WITHFP-NEXT: addi s0, sp, 64 194; RV32I-WITHFP-NEXT: addi a0, zero, 18 195; RV32I-WITHFP-NEXT: sw a0, 24(sp) 196; RV32I-WITHFP-NEXT: addi a0, zero, 17 197; RV32I-WITHFP-NEXT: sw a0, 20(sp) 198; RV32I-WITHFP-NEXT: addi a0, zero, 16 199; RV32I-WITHFP-NEXT: sw a0, 16(sp) 200; RV32I-WITHFP-NEXT: lui a0, 262236 201; RV32I-WITHFP-NEXT: addi a0, a0, 655 202; RV32I-WITHFP-NEXT: sw a0, 12(sp) 203; RV32I-WITHFP-NEXT: lui a0, 377487 204; RV32I-WITHFP-NEXT: addi a0, a0, 1475 205; RV32I-WITHFP-NEXT: sw a0, 8(sp) 206; RV32I-WITHFP-NEXT: addi a0, zero, 15 207; RV32I-WITHFP-NEXT: sw a0, 0(sp) 208; RV32I-WITHFP-NEXT: lui a0, 262153 209; RV32I-WITHFP-NEXT: addi a0, a0, 491 210; RV32I-WITHFP-NEXT: sw a0, -20(s0) 211; RV32I-WITHFP-NEXT: lui a0, 545260 212; RV32I-WITHFP-NEXT: addi a0, a0, -1967 213; RV32I-WITHFP-NEXT: sw a0, -24(s0) 214; RV32I-WITHFP-NEXT: lui a0, 964690 215; RV32I-WITHFP-NEXT: addi a0, a0, -328 216; RV32I-WITHFP-NEXT: sw a0, -28(s0) 217; RV32I-WITHFP-NEXT: lui a0, 335544 218; RV32I-WITHFP-NEXT: addi t0, a0, 1311 219; RV32I-WITHFP-NEXT: lui a0, 688509 220; RV32I-WITHFP-NEXT: addi a5, a0, -2048 221; RV32I-WITHFP-NEXT: addi a0, zero, 1 222; RV32I-WITHFP-NEXT: addi a1, zero, 11 223; RV32I-WITHFP-NEXT: addi a2, s0, -32 224; RV32I-WITHFP-NEXT: addi a3, zero, 12 225; RV32I-WITHFP-NEXT: addi a4, zero, 13 226; RV32I-WITHFP-NEXT: addi a6, zero, 4 227; RV32I-WITHFP-NEXT: addi a7, zero, 14 228; RV32I-WITHFP-NEXT: sw t0, -32(s0) 229; RV32I-WITHFP-NEXT: call callee_aligned_stack 230; RV32I-WITHFP-NEXT: lw s0, 56(sp) 231; RV32I-WITHFP-NEXT: lw ra, 60(sp) 232; RV32I-WITHFP-NEXT: addi sp, sp, 64 233; RV32I-WITHFP-NEXT: ret 234 %1 = call i32 @callee_aligned_stack(i32 1, i32 11, 235 fp128 0xLEB851EB851EB851F400091EB851EB851, i32 12, i32 13, 236 i64 20000000000, i32 14, i32 15, double 2.720000e+00, i32 16, 237 [2 x i32] [i32 17, i32 18]) 238 ret void 239} 240 241define double @callee_small_scalar_ret() nounwind { 242; RV32I-FPELIM-LABEL: callee_small_scalar_ret: 243; RV32I-FPELIM: # %bb.0: 244; RV32I-FPELIM-NEXT: lui a1, 261888 245; RV32I-FPELIM-NEXT: mv a0, zero 246; RV32I-FPELIM-NEXT: ret 247; 248; RV32I-WITHFP-LABEL: callee_small_scalar_ret: 249; RV32I-WITHFP: # %bb.0: 250; RV32I-WITHFP-NEXT: addi sp, sp, -16 251; RV32I-WITHFP-NEXT: sw ra, 12(sp) 252; RV32I-WITHFP-NEXT: sw s0, 8(sp) 253; RV32I-WITHFP-NEXT: addi s0, sp, 16 254; RV32I-WITHFP-NEXT: lui a1, 261888 255; RV32I-WITHFP-NEXT: mv a0, zero 256; RV32I-WITHFP-NEXT: lw s0, 8(sp) 257; RV32I-WITHFP-NEXT: lw ra, 12(sp) 258; RV32I-WITHFP-NEXT: addi sp, sp, 16 259; RV32I-WITHFP-NEXT: ret 260 ret double 1.0 261} 262 263define i64 @caller_small_scalar_ret() nounwind { 264; RV32I-FPELIM-LABEL: caller_small_scalar_ret: 265; RV32I-FPELIM: # %bb.0: 266; RV32I-FPELIM-NEXT: addi sp, sp, -16 267; RV32I-FPELIM-NEXT: sw ra, 12(sp) 268; RV32I-FPELIM-NEXT: call callee_small_scalar_ret 269; RV32I-FPELIM-NEXT: lw ra, 12(sp) 270; RV32I-FPELIM-NEXT: addi sp, sp, 16 271; RV32I-FPELIM-NEXT: ret 272; 273; RV32I-WITHFP-LABEL: caller_small_scalar_ret: 274; RV32I-WITHFP: # %bb.0: 275; RV32I-WITHFP-NEXT: addi sp, sp, -16 276; RV32I-WITHFP-NEXT: sw ra, 12(sp) 277; RV32I-WITHFP-NEXT: sw s0, 8(sp) 278; RV32I-WITHFP-NEXT: addi s0, sp, 16 279; RV32I-WITHFP-NEXT: call callee_small_scalar_ret 280; RV32I-WITHFP-NEXT: lw s0, 8(sp) 281; RV32I-WITHFP-NEXT: lw ra, 12(sp) 282; RV32I-WITHFP-NEXT: addi sp, sp, 16 283; RV32I-WITHFP-NEXT: ret 284 %1 = call double @callee_small_scalar_ret() 285 %2 = bitcast double %1 to i64 286 ret i64 %2 287} 288