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 %s
4; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \
5; RUN:   | FileCheck -check-prefix=RV64I %s
6
7; When passing a function argument with a size that isn't a multiple of XLEN,
8; and the argument is split and passed indirectly, we must ensure that the stack
9; slot size appropriately reflects the total size of the parts the argument is
10; split into. Otherwise, stack writes can clobber neighboring values.
11
12declare void @callee129(i129)
13declare void @callee160(i160)
14declare void @callee161(i161)
15
16; FIXME: Stack write clobbers the spilled value (on RV64).
17define i32 @caller129() nounwind {
18; RV32I-LABEL: caller129:
19; RV32I:       # %bb.0:
20; RV32I-NEXT:    addi sp, sp, -32
21; RV32I-NEXT:    sw ra, 28(sp) # 4-byte Folded Spill
22; RV32I-NEXT:    addi a0, zero, 42
23; RV32I-NEXT:    sw a0, 24(sp)
24; RV32I-NEXT:    sw zero, 16(sp)
25; RV32I-NEXT:    sw zero, 12(sp)
26; RV32I-NEXT:    sw zero, 8(sp)
27; RV32I-NEXT:    sw zero, 4(sp)
28; RV32I-NEXT:    mv a0, sp
29; RV32I-NEXT:    sw zero, 0(sp)
30; RV32I-NEXT:    call callee129@plt
31; RV32I-NEXT:    lw a0, 24(sp)
32; RV32I-NEXT:    lw ra, 28(sp) # 4-byte Folded Reload
33; RV32I-NEXT:    addi sp, sp, 32
34; RV32I-NEXT:    ret
35;
36; RV64I-LABEL: caller129:
37; RV64I:       # %bb.0:
38; RV64I-NEXT:    addi sp, sp, -32
39; RV64I-NEXT:    sd ra, 24(sp) # 8-byte Folded Spill
40; RV64I-NEXT:    addi a0, zero, 42
41; RV64I-NEXT:    sw a0, 20(sp)
42; RV64I-NEXT:    sd zero, 16(sp)
43; RV64I-NEXT:    sd zero, 8(sp)
44; RV64I-NEXT:    mv a0, sp
45; RV64I-NEXT:    sd zero, 0(sp)
46; RV64I-NEXT:    call callee129@plt
47; RV64I-NEXT:    lw a0, 20(sp)
48; RV64I-NEXT:    ld ra, 24(sp) # 8-byte Folded Reload
49; RV64I-NEXT:    addi sp, sp, 32
50; RV64I-NEXT:    ret
51  %1 = alloca i32
52  store i32 42, i32* %1
53  call void @callee129(i129 0)
54  %2 = load i32, i32* %1
55  ret i32 %2
56}
57
58; FIXME: Stack write clobbers the spilled value (on RV64).
59define i32 @caller160() nounwind {
60; RV32I-LABEL: caller160:
61; RV32I:       # %bb.0:
62; RV32I-NEXT:    addi sp, sp, -32
63; RV32I-NEXT:    sw ra, 28(sp) # 4-byte Folded Spill
64; RV32I-NEXT:    addi a0, zero, 42
65; RV32I-NEXT:    sw a0, 24(sp)
66; RV32I-NEXT:    sw zero, 16(sp)
67; RV32I-NEXT:    sw zero, 12(sp)
68; RV32I-NEXT:    sw zero, 8(sp)
69; RV32I-NEXT:    sw zero, 4(sp)
70; RV32I-NEXT:    mv a0, sp
71; RV32I-NEXT:    sw zero, 0(sp)
72; RV32I-NEXT:    call callee160@plt
73; RV32I-NEXT:    lw a0, 24(sp)
74; RV32I-NEXT:    lw ra, 28(sp) # 4-byte Folded Reload
75; RV32I-NEXT:    addi sp, sp, 32
76; RV32I-NEXT:    ret
77;
78; RV64I-LABEL: caller160:
79; RV64I:       # %bb.0:
80; RV64I-NEXT:    addi sp, sp, -32
81; RV64I-NEXT:    sd ra, 24(sp) # 8-byte Folded Spill
82; RV64I-NEXT:    addi a0, zero, 42
83; RV64I-NEXT:    sw a0, 20(sp)
84; RV64I-NEXT:    sd zero, 16(sp)
85; RV64I-NEXT:    sd zero, 8(sp)
86; RV64I-NEXT:    mv a0, sp
87; RV64I-NEXT:    sd zero, 0(sp)
88; RV64I-NEXT:    call callee160@plt
89; RV64I-NEXT:    lw a0, 20(sp)
90; RV64I-NEXT:    ld ra, 24(sp) # 8-byte Folded Reload
91; RV64I-NEXT:    addi sp, sp, 32
92; RV64I-NEXT:    ret
93  %1 = alloca i32
94  store i32 42, i32* %1
95  call void @callee160(i160 0)
96  %2 = load i32, i32* %1
97  ret i32 %2
98}
99
100define i32 @caller161() nounwind {
101; RV32I-LABEL: caller161:
102; RV32I:       # %bb.0:
103; RV32I-NEXT:    addi sp, sp, -32
104; RV32I-NEXT:    sw ra, 28(sp) # 4-byte Folded Spill
105; RV32I-NEXT:    addi a0, zero, 42
106; RV32I-NEXT:    sw a0, 24(sp)
107; RV32I-NEXT:    sw zero, 20(sp)
108; RV32I-NEXT:    sw zero, 16(sp)
109; RV32I-NEXT:    sw zero, 12(sp)
110; RV32I-NEXT:    sw zero, 8(sp)
111; RV32I-NEXT:    sw zero, 4(sp)
112; RV32I-NEXT:    mv a0, sp
113; RV32I-NEXT:    sw zero, 0(sp)
114; RV32I-NEXT:    call callee161@plt
115; RV32I-NEXT:    lw a0, 24(sp)
116; RV32I-NEXT:    lw ra, 28(sp) # 4-byte Folded Reload
117; RV32I-NEXT:    addi sp, sp, 32
118; RV32I-NEXT:    ret
119;
120; RV64I-LABEL: caller161:
121; RV64I:       # %bb.0:
122; RV64I-NEXT:    addi sp, sp, -48
123; RV64I-NEXT:    sd ra, 40(sp) # 8-byte Folded Spill
124; RV64I-NEXT:    addi a0, zero, 42
125; RV64I-NEXT:    sw a0, 36(sp)
126; RV64I-NEXT:    sd zero, 16(sp)
127; RV64I-NEXT:    sd zero, 8(sp)
128; RV64I-NEXT:    mv a0, sp
129; RV64I-NEXT:    sd zero, 0(sp)
130; RV64I-NEXT:    call callee161@plt
131; RV64I-NEXT:    lw a0, 36(sp)
132; RV64I-NEXT:    ld ra, 40(sp) # 8-byte Folded Reload
133; RV64I-NEXT:    addi sp, sp, 48
134; RV64I-NEXT:    ret
135  %1 = alloca i32
136  store i32 42, i32* %1
137  call void @callee161(i161 0)
138  %2 = load i32, i32* %1
139  ret i32 %2
140}
141