blob: b8f6100cdd66525fb9462c31c816ec691422a065 [file] [log] [blame]
Ana Pazos2e4106b2018-07-26 17:49:43 +00001; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc -mtriple riscv32-unknown-elf -o - %s \
3; RUN: 2>&1 | FileCheck %s -check-prefix CHECK-RV32
4; RUN: llc -mtriple riscv32-unknown-elf -mattr=+f -o - %s \
5; RUN: 2>&1 | FileCheck %s -check-prefix CHECK-RV32-F
6; RUN: llc -mtriple riscv32-unknown-elf -mattr=+f,+d -o - %s \
7; RUN: 2>&1 | FileCheck %s -check-prefix CHECK-RV32-FD
8;
9; TODO: Add RV64 tests when we can lower global addresses.
10
11; Checking all registers that are used are being saved.
12; This includes Caller (arguments and temps) and
13; Callee saved registers.
14;
15; extern int a, b, c;
16; __attribute__((interrupt)) void foo_no_call(void) {
17; c = a + b;
18; }
19;
20
21@a = external global i32
22@b = external global i32
23@c = external global i32
24
25define void @foo_i32() #0 {
26; CHECK-RV32-LABEL: foo_i32:
27; CHECK-RV32: # %bb.0:
28; CHECK-RV32-NEXT: addi sp, sp, -16
29; CHECK-RV32-NEXT: sw a0, 12(sp)
30; CHECK-RV32-NEXT: sw a1, 8(sp)
31; CHECK-RV32-NEXT: lui a0, %hi(a)
32; CHECK-RV32-NEXT: lw a0, %lo(a)(a0)
33; CHECK-RV32-NEXT: lui a1, %hi(b)
34; CHECK-RV32-NEXT: lw a1, %lo(b)(a1)
35; CHECK-RV32-NEXT: add a0, a1, a0
36; CHECK-RV32-NEXT: lui a1, %hi(c)
37; CHECK-RV32-NEXT: sw a0, %lo(c)(a1)
38; CHECK-RV32-NEXT: lw a1, 8(sp)
39; CHECK-RV32-NEXT: lw a0, 12(sp)
40; CHECK-RV32-NEXT: addi sp, sp, 16
41; CHECK-RV32-NEXT: mret
42;
43 %1 = load i32, i32* @a
44 %2 = load i32, i32* @b
45 %add = add nsw i32 %2, %1
46 store i32 %add, i32* @c
47 ret void
48}
49
50;
51; Additionally check frame pointer and return address are properly saved.
52;
53
54define void @foo_fp_i32() #1 {
55; CHECK-RV32-LABEL: foo_fp_i32:
56; CHECK-RV32: # %bb.0:
57; CHECK-RV32-NEXT: addi sp, sp, -16
58; CHECK-RV32-NEXT: sw ra, 12(sp)
59; CHECK-RV32-NEXT: sw s0, 8(sp)
60; CHECK-RV32-NEXT: sw a0, 4(sp)
61; CHECK-RV32-NEXT: sw a1, 0(sp)
62; CHECK-RV32-NEXT: addi s0, sp, 16
63; CHECK-RV32-NEXT: lui a0, %hi(a)
64; CHECK-RV32-NEXT: lw a0, %lo(a)(a0)
65; CHECK-RV32-NEXT: lui a1, %hi(b)
66; CHECK-RV32-NEXT: lw a1, %lo(b)(a1)
67; CHECK-RV32-NEXT: add a0, a1, a0
68; CHECK-RV32-NEXT: lui a1, %hi(c)
69; CHECK-RV32-NEXT: sw a0, %lo(c)(a1)
70; CHECK-RV32-NEXT: lw a1, 0(sp)
71; CHECK-RV32-NEXT: lw a0, 4(sp)
72; CHECK-RV32-NEXT: lw s0, 8(sp)
73; CHECK-RV32-NEXT: lw ra, 12(sp)
74; CHECK-RV32-NEXT: addi sp, sp, 16
75; CHECK-RV32-NEXT: mret
76;
77 %1 = load i32, i32* @a
78 %2 = load i32, i32* @b
79 %add = add nsw i32 %2, %1
80 store i32 %add, i32* @c
81 ret void
82}
83
84@e = external global float
85@f = external global float
86@d = external global float
87
88define void @foo_float() #0 {
89; CHECK-RV32-F-LABEL: foo_float:
90; CHECK-RV32-F: # %bb.0:
91; CHECK-RV32-F-NEXT: addi sp, sp, -16
92; CHECK-RV32-F-NEXT: sw a0, 12(sp)
93; CHECK-RV32-F-NEXT: fsw ft0, 8(sp)
94; CHECK-RV32-F-NEXT: fsw ft1, 4(sp)
95; CHECK-RV32-F-NEXT: lui a0, %hi(f)
96; CHECK-RV32-F-NEXT: flw ft0, %lo(f)(a0)
97; CHECK-RV32-F-NEXT: lui a0, %hi(e)
98; CHECK-RV32-F-NEXT: flw ft1, %lo(e)(a0)
99; CHECK-RV32-F-NEXT: fadd.s ft0, ft1, ft0
100; CHECK-RV32-F-NEXT: lui a0, %hi(d)
101; CHECK-RV32-F-NEXT: fsw ft0, %lo(d)(a0)
102; CHECK-RV32-F-NEXT: flw ft1, 4(sp)
103; CHECK-RV32-F-NEXT: flw ft0, 8(sp)
104; CHECK-RV32-F-NEXT: lw a0, 12(sp)
105; CHECK-RV32-F-NEXT: addi sp, sp, 16
106; CHECK-RV32-F-NEXT: mret
107;
108 %1 = load float, float* @e
109 %2 = load float, float* @f
110 %add = fadd float %1, %2
111 store float %add, float* @d
112 ret void
113}
114
115;
116; Additionally check frame pointer and return address are properly saved.
117;
118define void @foo_fp_float() #1 {
119; CHECK-RV32-F-LABEL: foo_fp_float:
120; CHECK-RV32-F: # %bb.0:
121; CHECK-RV32-F-NEXT: addi sp, sp, -32
122; CHECK-RV32-F-NEXT: sw ra, 28(sp)
123; CHECK-RV32-F-NEXT: sw s0, 24(sp)
124; CHECK-RV32-F-NEXT: sw a0, 20(sp)
125; CHECK-RV32-F-NEXT: fsw ft0, 16(sp)
126; CHECK-RV32-F-NEXT: fsw ft1, 12(sp)
127; CHECK-RV32-F-NEXT: addi s0, sp, 32
128; CHECK-RV32-F-NEXT: lui a0, %hi(f)
129; CHECK-RV32-F-NEXT: flw ft0, %lo(f)(a0)
130; CHECK-RV32-F-NEXT: lui a0, %hi(e)
131; CHECK-RV32-F-NEXT: flw ft1, %lo(e)(a0)
132; CHECK-RV32-F-NEXT: fadd.s ft0, ft1, ft0
133; CHECK-RV32-F-NEXT: lui a0, %hi(d)
134; CHECK-RV32-F-NEXT: fsw ft0, %lo(d)(a0)
135; CHECK-RV32-F-NEXT: flw ft1, 12(sp)
136; CHECK-RV32-F-NEXT: flw ft0, 16(sp)
137; CHECK-RV32-F-NEXT: lw a0, 20(sp)
138; CHECK-RV32-F-NEXT: lw s0, 24(sp)
139; CHECK-RV32-F-NEXT: lw ra, 28(sp)
140; CHECK-RV32-F-NEXT: addi sp, sp, 32
141; CHECK-RV32-F-NEXT: mret
142;
143 %1 = load float, float* @e
144 %2 = load float, float* @f
145 %add = fadd float %1, %2
146 store float %add, float* @d
147 ret void
148}
149
150@h = external global double
151@i = external global double
152@g = external global double
153
154define void @foo_double() #0 {
155; CHECK-RV32-FD-LABEL: foo_double:
156; CHECK-RV32-FD: # %bb.0:
157; CHECK-RV32-FD-NEXT: addi sp, sp, -32
158; CHECK-RV32-FD-NEXT: sw a0, 28(sp)
159; CHECK-RV32-FD-NEXT: fsd ft0, 16(sp)
160; CHECK-RV32-FD-NEXT: fsd ft1, 8(sp)
161; CHECK-RV32-FD-NEXT: lui a0, %hi(i)
162; CHECK-RV32-FD-NEXT: fld ft0, %lo(i)(a0)
163; CHECK-RV32-FD-NEXT: lui a0, %hi(h)
164; CHECK-RV32-FD-NEXT: fld ft1, %lo(h)(a0)
165; CHECK-RV32-FD-NEXT: fadd.d ft0, ft1, ft0
166; CHECK-RV32-FD-NEXT: lui a0, %hi(g)
167; CHECK-RV32-FD-NEXT: fsd ft0, %lo(g)(a0)
168; CHECK-RV32-FD-NEXT: fld ft1, 8(sp)
169; CHECK-RV32-FD-NEXT: fld ft0, 16(sp)
170; CHECK-RV32-FD-NEXT: lw a0, 28(sp)
171; CHECK-RV32-FD-NEXT: addi sp, sp, 32
172; CHECK-RV32-FD-NEXT: mret
173;
174 %1 = load double, double* @h
175 %2 = load double, double* @i
176 %add = fadd double %1, %2
177 store double %add, double* @g
178 ret void
179}
180
181;
182; Additionally check frame pointer and return address are properly saved.
183;
184define void @foo_fp_double() #1 {
185; CHECK-RV32-FD-LABEL: foo_fp_double:
186; CHECK-RV32-FD: # %bb.0:
187; CHECK-RV32-FD-NEXT: addi sp, sp, -32
188; CHECK-RV32-FD-NEXT: sw ra, 28(sp)
189; CHECK-RV32-FD-NEXT: sw s0, 24(sp)
190; CHECK-RV32-FD-NEXT: sw a0, 20(sp)
191; CHECK-RV32-FD-NEXT: fsd ft0, 8(sp)
192; CHECK-RV32-FD-NEXT: fsd ft1, 0(sp)
193; CHECK-RV32-FD-NEXT: addi s0, sp, 32
194; CHECK-RV32-FD-NEXT: lui a0, %hi(i)
195; CHECK-RV32-FD-NEXT: fld ft0, %lo(i)(a0)
196; CHECK-RV32-FD-NEXT: lui a0, %hi(h)
197; CHECK-RV32-FD-NEXT: fld ft1, %lo(h)(a0)
198; CHECK-RV32-FD-NEXT: fadd.d ft0, ft1, ft0
199; CHECK-RV32-FD-NEXT: lui a0, %hi(g)
200; CHECK-RV32-FD-NEXT: fsd ft0, %lo(g)(a0)
201; CHECK-RV32-FD-NEXT: fld ft1, 0(sp)
202; CHECK-RV32-FD-NEXT: fld ft0, 8(sp)
203; CHECK-RV32-FD-NEXT: lw a0, 20(sp)
204; CHECK-RV32-FD-NEXT: lw s0, 24(sp)
205; CHECK-RV32-FD-NEXT: lw ra, 28(sp)
206; CHECK-RV32-FD-NEXT: addi sp, sp, 32
207; CHECK-RV32-FD-NEXT: mret
208;
209 %1 = load double, double* @h
210 %2 = load double, double* @i
211 %add = fadd double %1, %2
212 store double %add, double* @g
213 ret void
214}
215
216attributes #0 = { "interrupt"="machine" }
217attributes #1 = { "interrupt"="machine" "no-frame-pointer-elim"="true" }