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 -mattr=+d -target-abi ilp32d \ 8; RUN: -verify-machineinstrs < %s \ 9; RUN: | FileCheck -check-prefix=RV32I-FPELIM %s 10; RUN: llc -mtriple=riscv32 -verify-machineinstrs -frame-pointer=all < %s \ 11; RUN: | FileCheck -check-prefix=RV32I-WITHFP %s 12; RUN: llc -mtriple=riscv32 -verify-machineinstrs -frame-pointer=all \ 13; RUN: -mattr=+f -target-abi ilp32f < %s \ 14; RUN: | FileCheck -check-prefix=RV32I-WITHFP %s 15; RUN: llc -mtriple=riscv32 -verify-machineinstrs -frame-pointer=all \ 16; RUN: -mattr=+d -target-abi ilp32d < %s \ 17; RUN: | FileCheck -check-prefix=RV32I-WITHFP %s 18 19; This file contains tests that should have identical output for the ilp32, 20; ilp32f, and ilp32d ABIs. i.e. where no arguments are passed according to 21; the floating point ABI. As well as calling convention details, we check that 22; ra and fp are consistently stored to fp-4 and fp-8. 23 24; Check that on RV32, i64 is passed in a pair of registers. Unlike 25; the convention for varargs, this need not be an aligned pair. 26 27define i32 @callee_i64_in_regs(i32 %a, i64 %b) nounwind { 28; RV32I-FPELIM-LABEL: callee_i64_in_regs: 29; RV32I-FPELIM: # %bb.0: 30; RV32I-FPELIM-NEXT: add a0, a0, a1 31; RV32I-FPELIM-NEXT: ret 32; 33; RV32I-WITHFP-LABEL: callee_i64_in_regs: 34; RV32I-WITHFP: # %bb.0: 35; RV32I-WITHFP-NEXT: addi sp, sp, -16 36; RV32I-WITHFP-NEXT: sw ra, 12(sp) 37; RV32I-WITHFP-NEXT: sw s0, 8(sp) 38; RV32I-WITHFP-NEXT: addi s0, sp, 16 39; RV32I-WITHFP-NEXT: add a0, a0, a1 40; RV32I-WITHFP-NEXT: lw s0, 8(sp) 41; RV32I-WITHFP-NEXT: lw ra, 12(sp) 42; RV32I-WITHFP-NEXT: addi sp, sp, 16 43; RV32I-WITHFP-NEXT: ret 44 %b_trunc = trunc i64 %b to i32 45 %1 = add i32 %a, %b_trunc 46 ret i32 %1 47} 48 49define i32 @caller_i64_in_regs() nounwind { 50; RV32I-FPELIM-LABEL: caller_i64_in_regs: 51; RV32I-FPELIM: # %bb.0: 52; RV32I-FPELIM-NEXT: addi sp, sp, -16 53; RV32I-FPELIM-NEXT: sw ra, 12(sp) 54; RV32I-FPELIM-NEXT: addi a0, zero, 1 55; RV32I-FPELIM-NEXT: addi a1, zero, 2 56; RV32I-FPELIM-NEXT: mv a2, zero 57; RV32I-FPELIM-NEXT: call callee_i64_in_regs 58; RV32I-FPELIM-NEXT: lw ra, 12(sp) 59; RV32I-FPELIM-NEXT: addi sp, sp, 16 60; RV32I-FPELIM-NEXT: ret 61; 62; RV32I-WITHFP-LABEL: caller_i64_in_regs: 63; RV32I-WITHFP: # %bb.0: 64; RV32I-WITHFP-NEXT: addi sp, sp, -16 65; RV32I-WITHFP-NEXT: sw ra, 12(sp) 66; RV32I-WITHFP-NEXT: sw s0, 8(sp) 67; RV32I-WITHFP-NEXT: addi s0, sp, 16 68; RV32I-WITHFP-NEXT: addi a0, zero, 1 69; RV32I-WITHFP-NEXT: addi a1, zero, 2 70; RV32I-WITHFP-NEXT: mv a2, zero 71; RV32I-WITHFP-NEXT: call callee_i64_in_regs 72; RV32I-WITHFP-NEXT: lw s0, 8(sp) 73; RV32I-WITHFP-NEXT: lw ra, 12(sp) 74; RV32I-WITHFP-NEXT: addi sp, sp, 16 75; RV32I-WITHFP-NEXT: ret 76 %1 = call i32 @callee_i64_in_regs(i32 1, i64 2) 77 ret i32 %1 78} 79 80; Check that the stack is used once the GPRs are exhausted 81 82define i32 @callee_many_scalars(i8 %a, i16 %b, i32 %c, i64 %d, i32 %e, i32 %f, i64 %g, i32 %h) nounwind { 83; RV32I-FPELIM-LABEL: callee_many_scalars: 84; RV32I-FPELIM: # %bb.0: 85; RV32I-FPELIM-NEXT: lw t0, 4(sp) 86; RV32I-FPELIM-NEXT: lw t1, 0(sp) 87; RV32I-FPELIM-NEXT: andi t2, a0, 255 88; RV32I-FPELIM-NEXT: lui a0, 16 89; RV32I-FPELIM-NEXT: addi a0, a0, -1 90; RV32I-FPELIM-NEXT: and a0, a1, a0 91; RV32I-FPELIM-NEXT: add a0, t2, a0 92; RV32I-FPELIM-NEXT: add a0, a0, a2 93; RV32I-FPELIM-NEXT: xor a1, a4, t1 94; RV32I-FPELIM-NEXT: xor a2, a3, a7 95; RV32I-FPELIM-NEXT: or a1, a2, a1 96; RV32I-FPELIM-NEXT: seqz a1, a1 97; RV32I-FPELIM-NEXT: add a0, a1, a0 98; RV32I-FPELIM-NEXT: add a0, a0, a5 99; RV32I-FPELIM-NEXT: add a0, a0, a6 100; RV32I-FPELIM-NEXT: add a0, a0, t0 101; RV32I-FPELIM-NEXT: ret 102; 103; RV32I-WITHFP-LABEL: callee_many_scalars: 104; RV32I-WITHFP: # %bb.0: 105; RV32I-WITHFP-NEXT: addi sp, sp, -16 106; RV32I-WITHFP-NEXT: sw ra, 12(sp) 107; RV32I-WITHFP-NEXT: sw s0, 8(sp) 108; RV32I-WITHFP-NEXT: addi s0, sp, 16 109; RV32I-WITHFP-NEXT: lw t0, 4(s0) 110; RV32I-WITHFP-NEXT: lw t1, 0(s0) 111; RV32I-WITHFP-NEXT: andi t2, a0, 255 112; RV32I-WITHFP-NEXT: lui a0, 16 113; RV32I-WITHFP-NEXT: addi a0, a0, -1 114; RV32I-WITHFP-NEXT: and a0, a1, a0 115; RV32I-WITHFP-NEXT: add a0, t2, a0 116; RV32I-WITHFP-NEXT: add a0, a0, a2 117; RV32I-WITHFP-NEXT: xor a1, a4, t1 118; RV32I-WITHFP-NEXT: xor a2, a3, a7 119; RV32I-WITHFP-NEXT: or a1, a2, a1 120; RV32I-WITHFP-NEXT: seqz a1, a1 121; RV32I-WITHFP-NEXT: add a0, a1, a0 122; RV32I-WITHFP-NEXT: add a0, a0, a5 123; RV32I-WITHFP-NEXT: add a0, a0, a6 124; RV32I-WITHFP-NEXT: add a0, a0, t0 125; RV32I-WITHFP-NEXT: lw s0, 8(sp) 126; RV32I-WITHFP-NEXT: lw ra, 12(sp) 127; RV32I-WITHFP-NEXT: addi sp, sp, 16 128; RV32I-WITHFP-NEXT: ret 129 %a_ext = zext i8 %a to i32 130 %b_ext = zext i16 %b to i32 131 %1 = add i32 %a_ext, %b_ext 132 %2 = add i32 %1, %c 133 %3 = icmp eq i64 %d, %g 134 %4 = zext i1 %3 to i32 135 %5 = add i32 %4, %2 136 %6 = add i32 %5, %e 137 %7 = add i32 %6, %f 138 %8 = add i32 %7, %h 139 ret i32 %8 140} 141 142define i32 @caller_many_scalars() nounwind { 143; RV32I-FPELIM-LABEL: caller_many_scalars: 144; RV32I-FPELIM: # %bb.0: 145; RV32I-FPELIM-NEXT: addi sp, sp, -16 146; RV32I-FPELIM-NEXT: sw ra, 12(sp) 147; RV32I-FPELIM-NEXT: addi a0, zero, 8 148; RV32I-FPELIM-NEXT: sw a0, 4(sp) 149; RV32I-FPELIM-NEXT: addi a0, zero, 1 150; RV32I-FPELIM-NEXT: addi a1, zero, 2 151; RV32I-FPELIM-NEXT: addi a2, zero, 3 152; RV32I-FPELIM-NEXT: addi a3, zero, 4 153; RV32I-FPELIM-NEXT: addi a5, zero, 5 154; RV32I-FPELIM-NEXT: addi a6, zero, 6 155; RV32I-FPELIM-NEXT: addi a7, zero, 7 156; RV32I-FPELIM-NEXT: sw zero, 0(sp) 157; RV32I-FPELIM-NEXT: mv a4, zero 158; RV32I-FPELIM-NEXT: call callee_many_scalars 159; RV32I-FPELIM-NEXT: lw ra, 12(sp) 160; RV32I-FPELIM-NEXT: addi sp, sp, 16 161; RV32I-FPELIM-NEXT: ret 162; 163; RV32I-WITHFP-LABEL: caller_many_scalars: 164; RV32I-WITHFP: # %bb.0: 165; RV32I-WITHFP-NEXT: addi sp, sp, -16 166; RV32I-WITHFP-NEXT: sw ra, 12(sp) 167; RV32I-WITHFP-NEXT: sw s0, 8(sp) 168; RV32I-WITHFP-NEXT: addi s0, sp, 16 169; RV32I-WITHFP-NEXT: addi a0, zero, 8 170; RV32I-WITHFP-NEXT: sw a0, 4(sp) 171; RV32I-WITHFP-NEXT: addi a0, zero, 1 172; RV32I-WITHFP-NEXT: addi a1, zero, 2 173; RV32I-WITHFP-NEXT: addi a2, zero, 3 174; RV32I-WITHFP-NEXT: addi a3, zero, 4 175; RV32I-WITHFP-NEXT: addi a5, zero, 5 176; RV32I-WITHFP-NEXT: addi a6, zero, 6 177; RV32I-WITHFP-NEXT: addi a7, zero, 7 178; RV32I-WITHFP-NEXT: sw zero, 0(sp) 179; RV32I-WITHFP-NEXT: mv a4, zero 180; RV32I-WITHFP-NEXT: call callee_many_scalars 181; RV32I-WITHFP-NEXT: lw s0, 8(sp) 182; RV32I-WITHFP-NEXT: lw ra, 12(sp) 183; RV32I-WITHFP-NEXT: addi sp, sp, 16 184; RV32I-WITHFP-NEXT: ret 185 %1 = call i32 @callee_many_scalars(i8 1, i16 2, i32 3, i64 4, i32 5, i32 6, i64 7, i32 8) 186 ret i32 %1 187} 188 189 190; Check that i128 and fp128 are passed indirectly 191 192define i32 @callee_large_scalars(i128 %a, fp128 %b) nounwind { 193; RV32I-FPELIM-LABEL: callee_large_scalars: 194; RV32I-FPELIM: # %bb.0: 195; RV32I-FPELIM-NEXT: lw a6, 0(a1) 196; RV32I-FPELIM-NEXT: lw a7, 0(a0) 197; RV32I-FPELIM-NEXT: lw a4, 4(a1) 198; RV32I-FPELIM-NEXT: lw a5, 12(a1) 199; RV32I-FPELIM-NEXT: lw a2, 12(a0) 200; RV32I-FPELIM-NEXT: lw a3, 4(a0) 201; RV32I-FPELIM-NEXT: lw a1, 8(a1) 202; RV32I-FPELIM-NEXT: lw a0, 8(a0) 203; RV32I-FPELIM-NEXT: xor a2, a2, a5 204; RV32I-FPELIM-NEXT: xor a3, a3, a4 205; RV32I-FPELIM-NEXT: or a2, a3, a2 206; RV32I-FPELIM-NEXT: xor a0, a0, a1 207; RV32I-FPELIM-NEXT: xor a1, a7, a6 208; RV32I-FPELIM-NEXT: or a0, a1, a0 209; RV32I-FPELIM-NEXT: or a0, a0, a2 210; RV32I-FPELIM-NEXT: seqz a0, a0 211; RV32I-FPELIM-NEXT: ret 212; 213; RV32I-WITHFP-LABEL: callee_large_scalars: 214; RV32I-WITHFP: # %bb.0: 215; RV32I-WITHFP-NEXT: addi sp, sp, -16 216; RV32I-WITHFP-NEXT: sw ra, 12(sp) 217; RV32I-WITHFP-NEXT: sw s0, 8(sp) 218; RV32I-WITHFP-NEXT: addi s0, sp, 16 219; RV32I-WITHFP-NEXT: lw a6, 0(a1) 220; RV32I-WITHFP-NEXT: lw a7, 0(a0) 221; RV32I-WITHFP-NEXT: lw a4, 4(a1) 222; RV32I-WITHFP-NEXT: lw a5, 12(a1) 223; RV32I-WITHFP-NEXT: lw a2, 12(a0) 224; RV32I-WITHFP-NEXT: lw a3, 4(a0) 225; RV32I-WITHFP-NEXT: lw a1, 8(a1) 226; RV32I-WITHFP-NEXT: lw a0, 8(a0) 227; RV32I-WITHFP-NEXT: xor a2, a2, a5 228; RV32I-WITHFP-NEXT: xor a3, a3, a4 229; RV32I-WITHFP-NEXT: or a2, a3, a2 230; RV32I-WITHFP-NEXT: xor a0, a0, a1 231; RV32I-WITHFP-NEXT: xor a1, a7, a6 232; RV32I-WITHFP-NEXT: or a0, a1, a0 233; RV32I-WITHFP-NEXT: or a0, a0, a2 234; RV32I-WITHFP-NEXT: seqz a0, a0 235; RV32I-WITHFP-NEXT: lw s0, 8(sp) 236; RV32I-WITHFP-NEXT: lw ra, 12(sp) 237; RV32I-WITHFP-NEXT: addi sp, sp, 16 238; RV32I-WITHFP-NEXT: ret 239 %b_bitcast = bitcast fp128 %b to i128 240 %1 = icmp eq i128 %a, %b_bitcast 241 %2 = zext i1 %1 to i32 242 ret i32 %2 243} 244 245define i32 @caller_large_scalars() nounwind { 246; RV32I-FPELIM-LABEL: caller_large_scalars: 247; RV32I-FPELIM: # %bb.0: 248; RV32I-FPELIM-NEXT: addi sp, sp, -48 249; RV32I-FPELIM-NEXT: sw ra, 44(sp) 250; RV32I-FPELIM-NEXT: lui a0, 524272 251; RV32I-FPELIM-NEXT: sw a0, 12(sp) 252; RV32I-FPELIM-NEXT: sw zero, 8(sp) 253; RV32I-FPELIM-NEXT: sw zero, 4(sp) 254; RV32I-FPELIM-NEXT: sw zero, 0(sp) 255; RV32I-FPELIM-NEXT: sw zero, 36(sp) 256; RV32I-FPELIM-NEXT: sw zero, 32(sp) 257; RV32I-FPELIM-NEXT: sw zero, 28(sp) 258; RV32I-FPELIM-NEXT: addi a2, zero, 1 259; RV32I-FPELIM-NEXT: addi a0, sp, 24 260; RV32I-FPELIM-NEXT: mv a1, sp 261; RV32I-FPELIM-NEXT: sw a2, 24(sp) 262; RV32I-FPELIM-NEXT: call callee_large_scalars 263; RV32I-FPELIM-NEXT: lw ra, 44(sp) 264; RV32I-FPELIM-NEXT: addi sp, sp, 48 265; RV32I-FPELIM-NEXT: ret 266; 267; RV32I-WITHFP-LABEL: caller_large_scalars: 268; RV32I-WITHFP: # %bb.0: 269; RV32I-WITHFP-NEXT: addi sp, sp, -48 270; RV32I-WITHFP-NEXT: sw ra, 44(sp) 271; RV32I-WITHFP-NEXT: sw s0, 40(sp) 272; RV32I-WITHFP-NEXT: addi s0, sp, 48 273; RV32I-WITHFP-NEXT: lui a0, 524272 274; RV32I-WITHFP-NEXT: sw a0, -36(s0) 275; RV32I-WITHFP-NEXT: sw zero, -40(s0) 276; RV32I-WITHFP-NEXT: sw zero, -44(s0) 277; RV32I-WITHFP-NEXT: sw zero, -48(s0) 278; RV32I-WITHFP-NEXT: sw zero, -12(s0) 279; RV32I-WITHFP-NEXT: sw zero, -16(s0) 280; RV32I-WITHFP-NEXT: sw zero, -20(s0) 281; RV32I-WITHFP-NEXT: addi a2, zero, 1 282; RV32I-WITHFP-NEXT: addi a0, s0, -24 283; RV32I-WITHFP-NEXT: addi a1, s0, -48 284; RV32I-WITHFP-NEXT: sw a2, -24(s0) 285; RV32I-WITHFP-NEXT: call callee_large_scalars 286; RV32I-WITHFP-NEXT: lw s0, 40(sp) 287; RV32I-WITHFP-NEXT: lw ra, 44(sp) 288; RV32I-WITHFP-NEXT: addi sp, sp, 48 289; RV32I-WITHFP-NEXT: ret 290 %1 = call i32 @callee_large_scalars(i128 1, fp128 0xL00000000000000007FFF000000000000) 291 ret i32 %1 292} 293 294; Check that arguments larger than 2*xlen are handled correctly when their 295; address is passed on the stack rather than in memory 296 297; Must keep define on a single line due to an update_llc_test_checks.py limitation 298define i32 @callee_large_scalars_exhausted_regs(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i128 %h, i32 %i, fp128 %j) nounwind { 299; RV32I-FPELIM-LABEL: callee_large_scalars_exhausted_regs: 300; RV32I-FPELIM: # %bb.0: 301; RV32I-FPELIM-NEXT: lw a0, 4(sp) 302; RV32I-FPELIM-NEXT: lw a6, 0(a0) 303; RV32I-FPELIM-NEXT: lw t0, 0(a7) 304; RV32I-FPELIM-NEXT: lw a3, 4(a0) 305; RV32I-FPELIM-NEXT: lw a4, 12(a0) 306; RV32I-FPELIM-NEXT: lw a5, 12(a7) 307; RV32I-FPELIM-NEXT: lw a1, 4(a7) 308; RV32I-FPELIM-NEXT: lw a0, 8(a0) 309; RV32I-FPELIM-NEXT: lw a2, 8(a7) 310; RV32I-FPELIM-NEXT: xor a4, a5, a4 311; RV32I-FPELIM-NEXT: xor a1, a1, a3 312; RV32I-FPELIM-NEXT: or a1, a1, a4 313; RV32I-FPELIM-NEXT: xor a0, a2, a0 314; RV32I-FPELIM-NEXT: xor a2, t0, a6 315; RV32I-FPELIM-NEXT: or a0, a2, a0 316; RV32I-FPELIM-NEXT: or a0, a0, a1 317; RV32I-FPELIM-NEXT: seqz a0, a0 318; RV32I-FPELIM-NEXT: ret 319; 320; RV32I-WITHFP-LABEL: callee_large_scalars_exhausted_regs: 321; RV32I-WITHFP: # %bb.0: 322; RV32I-WITHFP-NEXT: addi sp, sp, -16 323; RV32I-WITHFP-NEXT: sw ra, 12(sp) 324; RV32I-WITHFP-NEXT: sw s0, 8(sp) 325; RV32I-WITHFP-NEXT: addi s0, sp, 16 326; RV32I-WITHFP-NEXT: lw a0, 4(s0) 327; RV32I-WITHFP-NEXT: lw a6, 0(a0) 328; RV32I-WITHFP-NEXT: lw t0, 0(a7) 329; RV32I-WITHFP-NEXT: lw a3, 4(a0) 330; RV32I-WITHFP-NEXT: lw a4, 12(a0) 331; RV32I-WITHFP-NEXT: lw a5, 12(a7) 332; RV32I-WITHFP-NEXT: lw a1, 4(a7) 333; RV32I-WITHFP-NEXT: lw a0, 8(a0) 334; RV32I-WITHFP-NEXT: lw a2, 8(a7) 335; RV32I-WITHFP-NEXT: xor a4, a5, a4 336; RV32I-WITHFP-NEXT: xor a1, a1, a3 337; RV32I-WITHFP-NEXT: or a1, a1, a4 338; RV32I-WITHFP-NEXT: xor a0, a2, a0 339; RV32I-WITHFP-NEXT: xor a2, t0, a6 340; RV32I-WITHFP-NEXT: or a0, a2, a0 341; RV32I-WITHFP-NEXT: or a0, a0, a1 342; RV32I-WITHFP-NEXT: seqz a0, a0 343; RV32I-WITHFP-NEXT: lw s0, 8(sp) 344; RV32I-WITHFP-NEXT: lw ra, 12(sp) 345; RV32I-WITHFP-NEXT: addi sp, sp, 16 346; RV32I-WITHFP-NEXT: ret 347 %j_bitcast = bitcast fp128 %j to i128 348 %1 = icmp eq i128 %h, %j_bitcast 349 %2 = zext i1 %1 to i32 350 ret i32 %2 351} 352 353define i32 @caller_large_scalars_exhausted_regs() nounwind { 354; RV32I-FPELIM-LABEL: caller_large_scalars_exhausted_regs: 355; RV32I-FPELIM: # %bb.0: 356; RV32I-FPELIM-NEXT: addi sp, sp, -64 357; RV32I-FPELIM-NEXT: sw ra, 60(sp) 358; RV32I-FPELIM-NEXT: addi a0, sp, 16 359; RV32I-FPELIM-NEXT: sw a0, 4(sp) 360; RV32I-FPELIM-NEXT: addi a0, zero, 9 361; RV32I-FPELIM-NEXT: sw a0, 0(sp) 362; RV32I-FPELIM-NEXT: lui a0, 524272 363; RV32I-FPELIM-NEXT: sw a0, 28(sp) 364; RV32I-FPELIM-NEXT: sw zero, 24(sp) 365; RV32I-FPELIM-NEXT: sw zero, 20(sp) 366; RV32I-FPELIM-NEXT: sw zero, 16(sp) 367; RV32I-FPELIM-NEXT: sw zero, 52(sp) 368; RV32I-FPELIM-NEXT: sw zero, 48(sp) 369; RV32I-FPELIM-NEXT: sw zero, 44(sp) 370; RV32I-FPELIM-NEXT: addi t0, zero, 8 371; RV32I-FPELIM-NEXT: addi a0, zero, 1 372; RV32I-FPELIM-NEXT: addi a1, zero, 2 373; RV32I-FPELIM-NEXT: addi a2, zero, 3 374; RV32I-FPELIM-NEXT: addi a3, zero, 4 375; RV32I-FPELIM-NEXT: addi a4, zero, 5 376; RV32I-FPELIM-NEXT: addi a5, zero, 6 377; RV32I-FPELIM-NEXT: addi a6, zero, 7 378; RV32I-FPELIM-NEXT: addi a7, sp, 40 379; RV32I-FPELIM-NEXT: sw t0, 40(sp) 380; RV32I-FPELIM-NEXT: call callee_large_scalars_exhausted_regs 381; RV32I-FPELIM-NEXT: lw ra, 60(sp) 382; RV32I-FPELIM-NEXT: addi sp, sp, 64 383; RV32I-FPELIM-NEXT: ret 384; 385; RV32I-WITHFP-LABEL: caller_large_scalars_exhausted_regs: 386; RV32I-WITHFP: # %bb.0: 387; RV32I-WITHFP-NEXT: addi sp, sp, -64 388; RV32I-WITHFP-NEXT: sw ra, 60(sp) 389; RV32I-WITHFP-NEXT: sw s0, 56(sp) 390; RV32I-WITHFP-NEXT: addi s0, sp, 64 391; RV32I-WITHFP-NEXT: addi a0, s0, -48 392; RV32I-WITHFP-NEXT: sw a0, 4(sp) 393; RV32I-WITHFP-NEXT: addi a0, zero, 9 394; RV32I-WITHFP-NEXT: sw a0, 0(sp) 395; RV32I-WITHFP-NEXT: lui a0, 524272 396; RV32I-WITHFP-NEXT: sw a0, -36(s0) 397; RV32I-WITHFP-NEXT: sw zero, -40(s0) 398; RV32I-WITHFP-NEXT: sw zero, -44(s0) 399; RV32I-WITHFP-NEXT: sw zero, -48(s0) 400; RV32I-WITHFP-NEXT: sw zero, -12(s0) 401; RV32I-WITHFP-NEXT: sw zero, -16(s0) 402; RV32I-WITHFP-NEXT: sw zero, -20(s0) 403; RV32I-WITHFP-NEXT: addi t0, zero, 8 404; RV32I-WITHFP-NEXT: addi a0, zero, 1 405; RV32I-WITHFP-NEXT: addi a1, zero, 2 406; RV32I-WITHFP-NEXT: addi a2, zero, 3 407; RV32I-WITHFP-NEXT: addi a3, zero, 4 408; RV32I-WITHFP-NEXT: addi a4, zero, 5 409; RV32I-WITHFP-NEXT: addi a5, zero, 6 410; RV32I-WITHFP-NEXT: addi a6, zero, 7 411; RV32I-WITHFP-NEXT: addi a7, s0, -24 412; RV32I-WITHFP-NEXT: sw t0, -24(s0) 413; RV32I-WITHFP-NEXT: call callee_large_scalars_exhausted_regs 414; RV32I-WITHFP-NEXT: lw s0, 56(sp) 415; RV32I-WITHFP-NEXT: lw ra, 60(sp) 416; RV32I-WITHFP-NEXT: addi sp, sp, 64 417; RV32I-WITHFP-NEXT: ret 418 %1 = call i32 @callee_large_scalars_exhausted_regs( 419 i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i128 8, i32 9, 420 fp128 0xL00000000000000007FFF000000000000) 421 ret i32 %1 422} 423 424; Ensure that libcalls generated in the middle-end obey the calling convention 425 426define i32 @caller_mixed_scalar_libcalls(i64 %a) nounwind { 427; RV32I-FPELIM-LABEL: caller_mixed_scalar_libcalls: 428; RV32I-FPELIM: # %bb.0: 429; RV32I-FPELIM-NEXT: addi sp, sp, -32 430; RV32I-FPELIM-NEXT: sw ra, 28(sp) 431; RV32I-FPELIM-NEXT: mv a2, a1 432; RV32I-FPELIM-NEXT: mv a1, a0 433; RV32I-FPELIM-NEXT: addi a0, sp, 8 434; RV32I-FPELIM-NEXT: call __floatditf 435; RV32I-FPELIM-NEXT: lw a0, 8(sp) 436; RV32I-FPELIM-NEXT: lw ra, 28(sp) 437; RV32I-FPELIM-NEXT: addi sp, sp, 32 438; RV32I-FPELIM-NEXT: ret 439; 440; RV32I-WITHFP-LABEL: caller_mixed_scalar_libcalls: 441; RV32I-WITHFP: # %bb.0: 442; RV32I-WITHFP-NEXT: addi sp, sp, -32 443; RV32I-WITHFP-NEXT: sw ra, 28(sp) 444; RV32I-WITHFP-NEXT: sw s0, 24(sp) 445; RV32I-WITHFP-NEXT: addi s0, sp, 32 446; RV32I-WITHFP-NEXT: mv a2, a1 447; RV32I-WITHFP-NEXT: mv a1, a0 448; RV32I-WITHFP-NEXT: addi a0, s0, -24 449; RV32I-WITHFP-NEXT: call __floatditf 450; RV32I-WITHFP-NEXT: lw a0, -24(s0) 451; RV32I-WITHFP-NEXT: lw s0, 24(sp) 452; RV32I-WITHFP-NEXT: lw ra, 28(sp) 453; RV32I-WITHFP-NEXT: addi sp, sp, 32 454; RV32I-WITHFP-NEXT: ret 455 %1 = sitofp i64 %a to fp128 456 %2 = bitcast fp128 %1 to i128 457 %3 = trunc i128 %2 to i32 458 ret i32 %3 459} 460 461; Check passing of coerced integer arrays 462 463%struct.small = type { i32, i32* } 464 465define i32 @callee_small_coerced_struct([2 x i32] %a.coerce) nounwind { 466; RV32I-FPELIM-LABEL: callee_small_coerced_struct: 467; RV32I-FPELIM: # %bb.0: 468; RV32I-FPELIM-NEXT: xor a0, a0, a1 469; RV32I-FPELIM-NEXT: seqz a0, a0 470; RV32I-FPELIM-NEXT: ret 471; 472; RV32I-WITHFP-LABEL: callee_small_coerced_struct: 473; RV32I-WITHFP: # %bb.0: 474; RV32I-WITHFP-NEXT: addi sp, sp, -16 475; RV32I-WITHFP-NEXT: sw ra, 12(sp) 476; RV32I-WITHFP-NEXT: sw s0, 8(sp) 477; RV32I-WITHFP-NEXT: addi s0, sp, 16 478; RV32I-WITHFP-NEXT: xor a0, a0, a1 479; RV32I-WITHFP-NEXT: seqz a0, a0 480; RV32I-WITHFP-NEXT: lw s0, 8(sp) 481; RV32I-WITHFP-NEXT: lw ra, 12(sp) 482; RV32I-WITHFP-NEXT: addi sp, sp, 16 483; RV32I-WITHFP-NEXT: ret 484 %1 = extractvalue [2 x i32] %a.coerce, 0 485 %2 = extractvalue [2 x i32] %a.coerce, 1 486 %3 = icmp eq i32 %1, %2 487 %4 = zext i1 %3 to i32 488 ret i32 %4 489} 490 491define i32 @caller_small_coerced_struct() nounwind { 492; RV32I-FPELIM-LABEL: caller_small_coerced_struct: 493; RV32I-FPELIM: # %bb.0: 494; RV32I-FPELIM-NEXT: addi sp, sp, -16 495; RV32I-FPELIM-NEXT: sw ra, 12(sp) 496; RV32I-FPELIM-NEXT: addi a0, zero, 1 497; RV32I-FPELIM-NEXT: addi a1, zero, 2 498; RV32I-FPELIM-NEXT: call callee_small_coerced_struct 499; RV32I-FPELIM-NEXT: lw ra, 12(sp) 500; RV32I-FPELIM-NEXT: addi sp, sp, 16 501; RV32I-FPELIM-NEXT: ret 502; 503; RV32I-WITHFP-LABEL: caller_small_coerced_struct: 504; RV32I-WITHFP: # %bb.0: 505; RV32I-WITHFP-NEXT: addi sp, sp, -16 506; RV32I-WITHFP-NEXT: sw ra, 12(sp) 507; RV32I-WITHFP-NEXT: sw s0, 8(sp) 508; RV32I-WITHFP-NEXT: addi s0, sp, 16 509; RV32I-WITHFP-NEXT: addi a0, zero, 1 510; RV32I-WITHFP-NEXT: addi a1, zero, 2 511; RV32I-WITHFP-NEXT: call callee_small_coerced_struct 512; RV32I-WITHFP-NEXT: lw s0, 8(sp) 513; RV32I-WITHFP-NEXT: lw ra, 12(sp) 514; RV32I-WITHFP-NEXT: addi sp, sp, 16 515; RV32I-WITHFP-NEXT: ret 516 %1 = call i32 @callee_small_coerced_struct([2 x i32] [i32 1, i32 2]) 517 ret i32 %1 518} 519 520; Check large struct arguments, which are passed byval 521 522%struct.large = type { i32, i32, i32, i32 } 523 524define i32 @callee_large_struct(%struct.large* byval(%struct.large) align 4 %a) nounwind { 525; RV32I-FPELIM-LABEL: callee_large_struct: 526; RV32I-FPELIM: # %bb.0: 527; RV32I-FPELIM-NEXT: lw a1, 0(a0) 528; RV32I-FPELIM-NEXT: lw a0, 12(a0) 529; RV32I-FPELIM-NEXT: add a0, a1, a0 530; RV32I-FPELIM-NEXT: ret 531; 532; RV32I-WITHFP-LABEL: callee_large_struct: 533; RV32I-WITHFP: # %bb.0: 534; RV32I-WITHFP-NEXT: addi sp, sp, -16 535; RV32I-WITHFP-NEXT: sw ra, 12(sp) 536; RV32I-WITHFP-NEXT: sw s0, 8(sp) 537; RV32I-WITHFP-NEXT: addi s0, sp, 16 538; RV32I-WITHFP-NEXT: lw a1, 0(a0) 539; RV32I-WITHFP-NEXT: lw a0, 12(a0) 540; RV32I-WITHFP-NEXT: add a0, a1, a0 541; RV32I-WITHFP-NEXT: lw s0, 8(sp) 542; RV32I-WITHFP-NEXT: lw ra, 12(sp) 543; RV32I-WITHFP-NEXT: addi sp, sp, 16 544; RV32I-WITHFP-NEXT: ret 545 %1 = getelementptr inbounds %struct.large, %struct.large* %a, i32 0, i32 0 546 %2 = getelementptr inbounds %struct.large, %struct.large* %a, i32 0, i32 3 547 %3 = load i32, i32* %1 548 %4 = load i32, i32* %2 549 %5 = add i32 %3, %4 550 ret i32 %5 551} 552 553define i32 @caller_large_struct() nounwind { 554; RV32I-FPELIM-LABEL: caller_large_struct: 555; RV32I-FPELIM: # %bb.0: 556; RV32I-FPELIM-NEXT: addi sp, sp, -48 557; RV32I-FPELIM-NEXT: sw ra, 44(sp) 558; RV32I-FPELIM-NEXT: addi a0, zero, 1 559; RV32I-FPELIM-NEXT: sw a0, 24(sp) 560; RV32I-FPELIM-NEXT: addi a1, zero, 2 561; RV32I-FPELIM-NEXT: sw a1, 28(sp) 562; RV32I-FPELIM-NEXT: addi a2, zero, 3 563; RV32I-FPELIM-NEXT: sw a2, 32(sp) 564; RV32I-FPELIM-NEXT: addi a3, zero, 4 565; RV32I-FPELIM-NEXT: sw a3, 36(sp) 566; RV32I-FPELIM-NEXT: sw a0, 8(sp) 567; RV32I-FPELIM-NEXT: sw a1, 12(sp) 568; RV32I-FPELIM-NEXT: sw a2, 16(sp) 569; RV32I-FPELIM-NEXT: sw a3, 20(sp) 570; RV32I-FPELIM-NEXT: addi a0, sp, 8 571; RV32I-FPELIM-NEXT: call callee_large_struct 572; RV32I-FPELIM-NEXT: lw ra, 44(sp) 573; RV32I-FPELIM-NEXT: addi sp, sp, 48 574; RV32I-FPELIM-NEXT: ret 575; 576; RV32I-WITHFP-LABEL: caller_large_struct: 577; RV32I-WITHFP: # %bb.0: 578; RV32I-WITHFP-NEXT: addi sp, sp, -48 579; RV32I-WITHFP-NEXT: sw ra, 44(sp) 580; RV32I-WITHFP-NEXT: sw s0, 40(sp) 581; RV32I-WITHFP-NEXT: addi s0, sp, 48 582; RV32I-WITHFP-NEXT: addi a0, zero, 1 583; RV32I-WITHFP-NEXT: sw a0, -24(s0) 584; RV32I-WITHFP-NEXT: addi a1, zero, 2 585; RV32I-WITHFP-NEXT: sw a1, -20(s0) 586; RV32I-WITHFP-NEXT: addi a2, zero, 3 587; RV32I-WITHFP-NEXT: sw a2, -16(s0) 588; RV32I-WITHFP-NEXT: addi a3, zero, 4 589; RV32I-WITHFP-NEXT: sw a3, -12(s0) 590; RV32I-WITHFP-NEXT: sw a0, -40(s0) 591; RV32I-WITHFP-NEXT: sw a1, -36(s0) 592; RV32I-WITHFP-NEXT: sw a2, -32(s0) 593; RV32I-WITHFP-NEXT: sw a3, -28(s0) 594; RV32I-WITHFP-NEXT: addi a0, s0, -40 595; RV32I-WITHFP-NEXT: call callee_large_struct 596; RV32I-WITHFP-NEXT: lw s0, 40(sp) 597; RV32I-WITHFP-NEXT: lw ra, 44(sp) 598; RV32I-WITHFP-NEXT: addi sp, sp, 48 599; RV32I-WITHFP-NEXT: ret 600 %ls = alloca %struct.large, align 4 601 %1 = bitcast %struct.large* %ls to i8* 602 %a = getelementptr inbounds %struct.large, %struct.large* %ls, i32 0, i32 0 603 store i32 1, i32* %a 604 %b = getelementptr inbounds %struct.large, %struct.large* %ls, i32 0, i32 1 605 store i32 2, i32* %b 606 %c = getelementptr inbounds %struct.large, %struct.large* %ls, i32 0, i32 2 607 store i32 3, i32* %c 608 %d = getelementptr inbounds %struct.large, %struct.large* %ls, i32 0, i32 3 609 store i32 4, i32* %d 610 %2 = call i32 @callee_large_struct(%struct.large* byval(%struct.large) align 4 %ls) 611 ret i32 %2 612} 613 614; Check 2x*xlen values are aligned appropriately when passed on the stack 615; Must keep define on a single line due to an update_llc_test_checks.py limitation 616define i32 @callee_aligned_stack(i32 %a, i32 %b, fp128 %c, i32 %d, i32 %e, i64 %f, i32 %g, i32 %h, i64 %i, i32 %j, [2 x i32] %k) nounwind { 617; The i64 should be 8-byte aligned on the stack, but the two-element array 618; should only be 4-byte aligned 619; RV32I-FPELIM-LABEL: callee_aligned_stack: 620; RV32I-FPELIM: # %bb.0: 621; RV32I-FPELIM-NEXT: lw a0, 0(a2) 622; RV32I-FPELIM-NEXT: lw a1, 20(sp) 623; RV32I-FPELIM-NEXT: lw a2, 0(sp) 624; RV32I-FPELIM-NEXT: lw a3, 8(sp) 625; RV32I-FPELIM-NEXT: lw a4, 16(sp) 626; RV32I-FPELIM-NEXT: add a0, a0, a7 627; RV32I-FPELIM-NEXT: add a0, a0, a2 628; RV32I-FPELIM-NEXT: add a0, a0, a3 629; RV32I-FPELIM-NEXT: add a0, a0, a4 630; RV32I-FPELIM-NEXT: add a0, a0, a1 631; RV32I-FPELIM-NEXT: ret 632; 633; RV32I-WITHFP-LABEL: callee_aligned_stack: 634; RV32I-WITHFP: # %bb.0: 635; RV32I-WITHFP-NEXT: addi sp, sp, -16 636; RV32I-WITHFP-NEXT: sw ra, 12(sp) 637; RV32I-WITHFP-NEXT: sw s0, 8(sp) 638; RV32I-WITHFP-NEXT: addi s0, sp, 16 639; RV32I-WITHFP-NEXT: lw a0, 0(a2) 640; RV32I-WITHFP-NEXT: lw a1, 20(s0) 641; RV32I-WITHFP-NEXT: lw a2, 0(s0) 642; RV32I-WITHFP-NEXT: lw a3, 8(s0) 643; RV32I-WITHFP-NEXT: lw a4, 16(s0) 644; RV32I-WITHFP-NEXT: add a0, a0, a7 645; RV32I-WITHFP-NEXT: add a0, a0, a2 646; RV32I-WITHFP-NEXT: add a0, a0, a3 647; RV32I-WITHFP-NEXT: add a0, a0, a4 648; RV32I-WITHFP-NEXT: add a0, a0, a1 649; RV32I-WITHFP-NEXT: lw s0, 8(sp) 650; RV32I-WITHFP-NEXT: lw ra, 12(sp) 651; RV32I-WITHFP-NEXT: addi sp, sp, 16 652; RV32I-WITHFP-NEXT: ret 653 %1 = bitcast fp128 %c to i128 654 %2 = trunc i128 %1 to i32 655 %3 = add i32 %2, %g 656 %4 = add i32 %3, %h 657 %5 = trunc i64 %i to i32 658 %6 = add i32 %4, %5 659 %7 = add i32 %6, %j 660 %8 = extractvalue [2 x i32] %k, 0 661 %9 = add i32 %7, %8 662 ret i32 %9 663} 664 665define void @caller_aligned_stack() nounwind { 666; The i64 should be 8-byte aligned on the stack, but the two-element array 667; should only be 4-byte aligned 668; RV32I-FPELIM-LABEL: caller_aligned_stack: 669; RV32I-FPELIM: # %bb.0: 670; RV32I-FPELIM-NEXT: addi sp, sp, -64 671; RV32I-FPELIM-NEXT: sw ra, 60(sp) 672; RV32I-FPELIM-NEXT: addi a0, zero, 19 673; RV32I-FPELIM-NEXT: sw a0, 24(sp) 674; RV32I-FPELIM-NEXT: addi a0, zero, 18 675; RV32I-FPELIM-NEXT: sw a0, 20(sp) 676; RV32I-FPELIM-NEXT: addi a0, zero, 17 677; RV32I-FPELIM-NEXT: sw a0, 16(sp) 678; RV32I-FPELIM-NEXT: sw zero, 12(sp) 679; RV32I-FPELIM-NEXT: addi a0, zero, 16 680; RV32I-FPELIM-NEXT: sw a0, 8(sp) 681; RV32I-FPELIM-NEXT: addi a0, zero, 15 682; RV32I-FPELIM-NEXT: sw a0, 0(sp) 683; RV32I-FPELIM-NEXT: lui a0, 262153 684; RV32I-FPELIM-NEXT: addi a0, a0, 491 685; RV32I-FPELIM-NEXT: sw a0, 44(sp) 686; RV32I-FPELIM-NEXT: lui a0, 545260 687; RV32I-FPELIM-NEXT: addi a0, a0, -1967 688; RV32I-FPELIM-NEXT: sw a0, 40(sp) 689; RV32I-FPELIM-NEXT: lui a0, 964690 690; RV32I-FPELIM-NEXT: addi a0, a0, -328 691; RV32I-FPELIM-NEXT: sw a0, 36(sp) 692; RV32I-FPELIM-NEXT: lui a0, 335544 693; RV32I-FPELIM-NEXT: addi t0, a0, 1311 694; RV32I-FPELIM-NEXT: lui a0, 688509 695; RV32I-FPELIM-NEXT: addi a5, a0, -2048 696; RV32I-FPELIM-NEXT: addi a0, zero, 1 697; RV32I-FPELIM-NEXT: addi a1, zero, 11 698; RV32I-FPELIM-NEXT: addi a2, sp, 32 699; RV32I-FPELIM-NEXT: addi a3, zero, 12 700; RV32I-FPELIM-NEXT: addi a4, zero, 13 701; RV32I-FPELIM-NEXT: addi a6, zero, 4 702; RV32I-FPELIM-NEXT: addi a7, zero, 14 703; RV32I-FPELIM-NEXT: sw t0, 32(sp) 704; RV32I-FPELIM-NEXT: call callee_aligned_stack 705; RV32I-FPELIM-NEXT: lw ra, 60(sp) 706; RV32I-FPELIM-NEXT: addi sp, sp, 64 707; RV32I-FPELIM-NEXT: ret 708; 709; RV32I-WITHFP-LABEL: caller_aligned_stack: 710; RV32I-WITHFP: # %bb.0: 711; RV32I-WITHFP-NEXT: addi sp, sp, -64 712; RV32I-WITHFP-NEXT: sw ra, 60(sp) 713; RV32I-WITHFP-NEXT: sw s0, 56(sp) 714; RV32I-WITHFP-NEXT: addi s0, sp, 64 715; RV32I-WITHFP-NEXT: addi a0, zero, 19 716; RV32I-WITHFP-NEXT: sw a0, 24(sp) 717; RV32I-WITHFP-NEXT: addi a0, zero, 18 718; RV32I-WITHFP-NEXT: sw a0, 20(sp) 719; RV32I-WITHFP-NEXT: addi a0, zero, 17 720; RV32I-WITHFP-NEXT: sw a0, 16(sp) 721; RV32I-WITHFP-NEXT: sw zero, 12(sp) 722; RV32I-WITHFP-NEXT: addi a0, zero, 16 723; RV32I-WITHFP-NEXT: sw a0, 8(sp) 724; RV32I-WITHFP-NEXT: addi a0, zero, 15 725; RV32I-WITHFP-NEXT: sw a0, 0(sp) 726; RV32I-WITHFP-NEXT: lui a0, 262153 727; RV32I-WITHFP-NEXT: addi a0, a0, 491 728; RV32I-WITHFP-NEXT: sw a0, -20(s0) 729; RV32I-WITHFP-NEXT: lui a0, 545260 730; RV32I-WITHFP-NEXT: addi a0, a0, -1967 731; RV32I-WITHFP-NEXT: sw a0, -24(s0) 732; RV32I-WITHFP-NEXT: lui a0, 964690 733; RV32I-WITHFP-NEXT: addi a0, a0, -328 734; RV32I-WITHFP-NEXT: sw a0, -28(s0) 735; RV32I-WITHFP-NEXT: lui a0, 335544 736; RV32I-WITHFP-NEXT: addi t0, a0, 1311 737; RV32I-WITHFP-NEXT: lui a0, 688509 738; RV32I-WITHFP-NEXT: addi a5, a0, -2048 739; RV32I-WITHFP-NEXT: addi a0, zero, 1 740; RV32I-WITHFP-NEXT: addi a1, zero, 11 741; RV32I-WITHFP-NEXT: addi a2, s0, -32 742; RV32I-WITHFP-NEXT: addi a3, zero, 12 743; RV32I-WITHFP-NEXT: addi a4, zero, 13 744; RV32I-WITHFP-NEXT: addi a6, zero, 4 745; RV32I-WITHFP-NEXT: addi a7, zero, 14 746; RV32I-WITHFP-NEXT: sw t0, -32(s0) 747; RV32I-WITHFP-NEXT: call callee_aligned_stack 748; RV32I-WITHFP-NEXT: lw s0, 56(sp) 749; RV32I-WITHFP-NEXT: lw ra, 60(sp) 750; RV32I-WITHFP-NEXT: addi sp, sp, 64 751; RV32I-WITHFP-NEXT: ret 752 %1 = call i32 @callee_aligned_stack(i32 1, i32 11, 753 fp128 0xLEB851EB851EB851F400091EB851EB851, i32 12, i32 13, 754 i64 20000000000, i32 14, i32 15, i64 16, i32 17, 755 [2 x i32] [i32 18, i32 19]) 756 ret void 757} 758 759; Check return of 2x xlen scalars 760 761define i64 @callee_small_scalar_ret() nounwind { 762; RV32I-FPELIM-LABEL: callee_small_scalar_ret: 763; RV32I-FPELIM: # %bb.0: 764; RV32I-FPELIM-NEXT: lui a0, 466866 765; RV32I-FPELIM-NEXT: addi a0, a0, 1677 766; RV32I-FPELIM-NEXT: addi a1, zero, 287 767; RV32I-FPELIM-NEXT: ret 768; 769; RV32I-WITHFP-LABEL: callee_small_scalar_ret: 770; RV32I-WITHFP: # %bb.0: 771; RV32I-WITHFP-NEXT: addi sp, sp, -16 772; RV32I-WITHFP-NEXT: sw ra, 12(sp) 773; RV32I-WITHFP-NEXT: sw s0, 8(sp) 774; RV32I-WITHFP-NEXT: addi s0, sp, 16 775; RV32I-WITHFP-NEXT: lui a0, 466866 776; RV32I-WITHFP-NEXT: addi a0, a0, 1677 777; RV32I-WITHFP-NEXT: addi a1, zero, 287 778; RV32I-WITHFP-NEXT: lw s0, 8(sp) 779; RV32I-WITHFP-NEXT: lw ra, 12(sp) 780; RV32I-WITHFP-NEXT: addi sp, sp, 16 781; RV32I-WITHFP-NEXT: ret 782 ret i64 1234567898765 783} 784 785define i32 @caller_small_scalar_ret() nounwind { 786; RV32I-FPELIM-LABEL: caller_small_scalar_ret: 787; RV32I-FPELIM: # %bb.0: 788; RV32I-FPELIM-NEXT: addi sp, sp, -16 789; RV32I-FPELIM-NEXT: sw ra, 12(sp) 790; RV32I-FPELIM-NEXT: call callee_small_scalar_ret 791; RV32I-FPELIM-NEXT: lui a2, 56 792; RV32I-FPELIM-NEXT: addi a2, a2, 580 793; RV32I-FPELIM-NEXT: xor a1, a1, a2 794; RV32I-FPELIM-NEXT: lui a2, 200614 795; RV32I-FPELIM-NEXT: addi a2, a2, 647 796; RV32I-FPELIM-NEXT: xor a0, a0, a2 797; RV32I-FPELIM-NEXT: or a0, a0, a1 798; RV32I-FPELIM-NEXT: seqz a0, a0 799; RV32I-FPELIM-NEXT: lw ra, 12(sp) 800; RV32I-FPELIM-NEXT: addi sp, sp, 16 801; RV32I-FPELIM-NEXT: ret 802; 803; RV32I-WITHFP-LABEL: caller_small_scalar_ret: 804; RV32I-WITHFP: # %bb.0: 805; RV32I-WITHFP-NEXT: addi sp, sp, -16 806; RV32I-WITHFP-NEXT: sw ra, 12(sp) 807; RV32I-WITHFP-NEXT: sw s0, 8(sp) 808; RV32I-WITHFP-NEXT: addi s0, sp, 16 809; RV32I-WITHFP-NEXT: call callee_small_scalar_ret 810; RV32I-WITHFP-NEXT: lui a2, 56 811; RV32I-WITHFP-NEXT: addi a2, a2, 580 812; RV32I-WITHFP-NEXT: xor a1, a1, a2 813; RV32I-WITHFP-NEXT: lui a2, 200614 814; RV32I-WITHFP-NEXT: addi a2, a2, 647 815; RV32I-WITHFP-NEXT: xor a0, a0, a2 816; RV32I-WITHFP-NEXT: or a0, a0, a1 817; RV32I-WITHFP-NEXT: seqz a0, a0 818; RV32I-WITHFP-NEXT: lw s0, 8(sp) 819; RV32I-WITHFP-NEXT: lw ra, 12(sp) 820; RV32I-WITHFP-NEXT: addi sp, sp, 16 821; RV32I-WITHFP-NEXT: ret 822 %1 = call i64 @callee_small_scalar_ret() 823 %2 = icmp eq i64 987654321234567, %1 824 %3 = zext i1 %2 to i32 825 ret i32 %3 826} 827 828; Check return of 2x xlen structs 829 830define %struct.small @callee_small_struct_ret() nounwind { 831; RV32I-FPELIM-LABEL: callee_small_struct_ret: 832; RV32I-FPELIM: # %bb.0: 833; RV32I-FPELIM-NEXT: addi a0, zero, 1 834; RV32I-FPELIM-NEXT: mv a1, zero 835; RV32I-FPELIM-NEXT: ret 836; 837; RV32I-WITHFP-LABEL: callee_small_struct_ret: 838; RV32I-WITHFP: # %bb.0: 839; RV32I-WITHFP-NEXT: addi sp, sp, -16 840; RV32I-WITHFP-NEXT: sw ra, 12(sp) 841; RV32I-WITHFP-NEXT: sw s0, 8(sp) 842; RV32I-WITHFP-NEXT: addi s0, sp, 16 843; RV32I-WITHFP-NEXT: addi a0, zero, 1 844; RV32I-WITHFP-NEXT: mv a1, zero 845; RV32I-WITHFP-NEXT: lw s0, 8(sp) 846; RV32I-WITHFP-NEXT: lw ra, 12(sp) 847; RV32I-WITHFP-NEXT: addi sp, sp, 16 848; RV32I-WITHFP-NEXT: ret 849 ret %struct.small { i32 1, i32* null } 850} 851 852define i32 @caller_small_struct_ret() nounwind { 853; RV32I-FPELIM-LABEL: caller_small_struct_ret: 854; RV32I-FPELIM: # %bb.0: 855; RV32I-FPELIM-NEXT: addi sp, sp, -16 856; RV32I-FPELIM-NEXT: sw ra, 12(sp) 857; RV32I-FPELIM-NEXT: call callee_small_struct_ret 858; RV32I-FPELIM-NEXT: add a0, a0, a1 859; RV32I-FPELIM-NEXT: lw ra, 12(sp) 860; RV32I-FPELIM-NEXT: addi sp, sp, 16 861; RV32I-FPELIM-NEXT: ret 862; 863; RV32I-WITHFP-LABEL: caller_small_struct_ret: 864; RV32I-WITHFP: # %bb.0: 865; RV32I-WITHFP-NEXT: addi sp, sp, -16 866; RV32I-WITHFP-NEXT: sw ra, 12(sp) 867; RV32I-WITHFP-NEXT: sw s0, 8(sp) 868; RV32I-WITHFP-NEXT: addi s0, sp, 16 869; RV32I-WITHFP-NEXT: call callee_small_struct_ret 870; RV32I-WITHFP-NEXT: add a0, a0, a1 871; RV32I-WITHFP-NEXT: lw s0, 8(sp) 872; RV32I-WITHFP-NEXT: lw ra, 12(sp) 873; RV32I-WITHFP-NEXT: addi sp, sp, 16 874; RV32I-WITHFP-NEXT: ret 875 %1 = call %struct.small @callee_small_struct_ret() 876 %2 = extractvalue %struct.small %1, 0 877 %3 = extractvalue %struct.small %1, 1 878 %4 = ptrtoint i32* %3 to i32 879 %5 = add i32 %2, %4 880 ret i32 %5 881} 882 883; Check return of >2x xlen scalars 884 885define fp128 @callee_large_scalar_ret() nounwind { 886; RV32I-FPELIM-LABEL: callee_large_scalar_ret: 887; RV32I-FPELIM: # %bb.0: 888; RV32I-FPELIM-NEXT: lui a1, 524272 889; RV32I-FPELIM-NEXT: sw a1, 12(a0) 890; RV32I-FPELIM-NEXT: sw zero, 8(a0) 891; RV32I-FPELIM-NEXT: sw zero, 4(a0) 892; RV32I-FPELIM-NEXT: sw zero, 0(a0) 893; RV32I-FPELIM-NEXT: ret 894; 895; RV32I-WITHFP-LABEL: callee_large_scalar_ret: 896; RV32I-WITHFP: # %bb.0: 897; RV32I-WITHFP-NEXT: addi sp, sp, -16 898; RV32I-WITHFP-NEXT: sw ra, 12(sp) 899; RV32I-WITHFP-NEXT: sw s0, 8(sp) 900; RV32I-WITHFP-NEXT: addi s0, sp, 16 901; RV32I-WITHFP-NEXT: lui a1, 524272 902; RV32I-WITHFP-NEXT: sw a1, 12(a0) 903; RV32I-WITHFP-NEXT: sw zero, 8(a0) 904; RV32I-WITHFP-NEXT: sw zero, 4(a0) 905; RV32I-WITHFP-NEXT: sw zero, 0(a0) 906; RV32I-WITHFP-NEXT: lw s0, 8(sp) 907; RV32I-WITHFP-NEXT: lw ra, 12(sp) 908; RV32I-WITHFP-NEXT: addi sp, sp, 16 909; RV32I-WITHFP-NEXT: ret 910 ret fp128 0xL00000000000000007FFF000000000000 911} 912 913define void @caller_large_scalar_ret() nounwind { 914; RV32I-FPELIM-LABEL: caller_large_scalar_ret: 915; RV32I-FPELIM: # %bb.0: 916; RV32I-FPELIM-NEXT: addi sp, sp, -32 917; RV32I-FPELIM-NEXT: sw ra, 28(sp) 918; RV32I-FPELIM-NEXT: mv a0, sp 919; RV32I-FPELIM-NEXT: call callee_large_scalar_ret 920; RV32I-FPELIM-NEXT: lw ra, 28(sp) 921; RV32I-FPELIM-NEXT: addi sp, sp, 32 922; RV32I-FPELIM-NEXT: ret 923; 924; RV32I-WITHFP-LABEL: caller_large_scalar_ret: 925; RV32I-WITHFP: # %bb.0: 926; RV32I-WITHFP-NEXT: addi sp, sp, -32 927; RV32I-WITHFP-NEXT: sw ra, 28(sp) 928; RV32I-WITHFP-NEXT: sw s0, 24(sp) 929; RV32I-WITHFP-NEXT: addi s0, sp, 32 930; RV32I-WITHFP-NEXT: addi a0, s0, -32 931; RV32I-WITHFP-NEXT: call callee_large_scalar_ret 932; RV32I-WITHFP-NEXT: lw s0, 24(sp) 933; RV32I-WITHFP-NEXT: lw ra, 28(sp) 934; RV32I-WITHFP-NEXT: addi sp, sp, 32 935; RV32I-WITHFP-NEXT: ret 936 %1 = call fp128 @callee_large_scalar_ret() 937 ret void 938} 939 940; Check return of >2x xlen structs 941 942define void @callee_large_struct_ret(%struct.large* noalias sret(%struct.large) %agg.result) nounwind { 943; RV32I-FPELIM-LABEL: callee_large_struct_ret: 944; RV32I-FPELIM: # %bb.0: 945; RV32I-FPELIM-NEXT: addi a1, zero, 1 946; RV32I-FPELIM-NEXT: sw a1, 0(a0) 947; RV32I-FPELIM-NEXT: addi a1, zero, 2 948; RV32I-FPELIM-NEXT: sw a1, 4(a0) 949; RV32I-FPELIM-NEXT: addi a1, zero, 3 950; RV32I-FPELIM-NEXT: sw a1, 8(a0) 951; RV32I-FPELIM-NEXT: addi a1, zero, 4 952; RV32I-FPELIM-NEXT: sw a1, 12(a0) 953; RV32I-FPELIM-NEXT: ret 954; 955; RV32I-WITHFP-LABEL: callee_large_struct_ret: 956; RV32I-WITHFP: # %bb.0: 957; RV32I-WITHFP-NEXT: addi sp, sp, -16 958; RV32I-WITHFP-NEXT: sw ra, 12(sp) 959; RV32I-WITHFP-NEXT: sw s0, 8(sp) 960; RV32I-WITHFP-NEXT: addi s0, sp, 16 961; RV32I-WITHFP-NEXT: addi a1, zero, 1 962; RV32I-WITHFP-NEXT: sw a1, 0(a0) 963; RV32I-WITHFP-NEXT: addi a1, zero, 2 964; RV32I-WITHFP-NEXT: sw a1, 4(a0) 965; RV32I-WITHFP-NEXT: addi a1, zero, 3 966; RV32I-WITHFP-NEXT: sw a1, 8(a0) 967; RV32I-WITHFP-NEXT: addi a1, zero, 4 968; RV32I-WITHFP-NEXT: sw a1, 12(a0) 969; RV32I-WITHFP-NEXT: lw s0, 8(sp) 970; RV32I-WITHFP-NEXT: lw ra, 12(sp) 971; RV32I-WITHFP-NEXT: addi sp, sp, 16 972; RV32I-WITHFP-NEXT: ret 973 %a = getelementptr inbounds %struct.large, %struct.large* %agg.result, i32 0, i32 0 974 store i32 1, i32* %a, align 4 975 %b = getelementptr inbounds %struct.large, %struct.large* %agg.result, i32 0, i32 1 976 store i32 2, i32* %b, align 4 977 %c = getelementptr inbounds %struct.large, %struct.large* %agg.result, i32 0, i32 2 978 store i32 3, i32* %c, align 4 979 %d = getelementptr inbounds %struct.large, %struct.large* %agg.result, i32 0, i32 3 980 store i32 4, i32* %d, align 4 981 ret void 982} 983 984define i32 @caller_large_struct_ret() nounwind { 985; RV32I-FPELIM-LABEL: caller_large_struct_ret: 986; RV32I-FPELIM: # %bb.0: 987; RV32I-FPELIM-NEXT: addi sp, sp, -32 988; RV32I-FPELIM-NEXT: sw ra, 28(sp) 989; RV32I-FPELIM-NEXT: addi a0, sp, 8 990; RV32I-FPELIM-NEXT: call callee_large_struct_ret 991; RV32I-FPELIM-NEXT: lw a0, 8(sp) 992; RV32I-FPELIM-NEXT: lw a1, 20(sp) 993; RV32I-FPELIM-NEXT: add a0, a0, a1 994; RV32I-FPELIM-NEXT: lw ra, 28(sp) 995; RV32I-FPELIM-NEXT: addi sp, sp, 32 996; RV32I-FPELIM-NEXT: ret 997; 998; RV32I-WITHFP-LABEL: caller_large_struct_ret: 999; RV32I-WITHFP: # %bb.0: 1000; RV32I-WITHFP-NEXT: addi sp, sp, -32 1001; RV32I-WITHFP-NEXT: sw ra, 28(sp) 1002; RV32I-WITHFP-NEXT: sw s0, 24(sp) 1003; RV32I-WITHFP-NEXT: addi s0, sp, 32 1004; RV32I-WITHFP-NEXT: addi a0, s0, -24 1005; RV32I-WITHFP-NEXT: call callee_large_struct_ret 1006; RV32I-WITHFP-NEXT: lw a0, -24(s0) 1007; RV32I-WITHFP-NEXT: lw a1, -12(s0) 1008; RV32I-WITHFP-NEXT: add a0, a0, a1 1009; RV32I-WITHFP-NEXT: lw s0, 24(sp) 1010; RV32I-WITHFP-NEXT: lw ra, 28(sp) 1011; RV32I-WITHFP-NEXT: addi sp, sp, 32 1012; RV32I-WITHFP-NEXT: ret 1013 %1 = alloca %struct.large 1014 call void @callee_large_struct_ret(%struct.large* sret(%struct.large) %1) 1015 %2 = getelementptr inbounds %struct.large, %struct.large* %1, i32 0, i32 0 1016 %3 = load i32, i32* %2 1017 %4 = getelementptr inbounds %struct.large, %struct.large* %1, i32 0, i32 3 1018 %5 = load i32, i32* %4 1019 %6 = add i32 %3, %5 1020 ret i32 %6 1021} 1022