]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - test/CodeGen/RISCV/interrupt-attr-nocall.ll
Vendor import of llvm trunk r338150:
[FreeBSD/FreeBSD.git] / test / CodeGen / RISCV / interrupt-attr-nocall.ll
1 ; 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
25 define 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
54 define 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
88 define 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 ;
118 define 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
154 define 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 ;
184 define 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
216 attributes #0 = { "interrupt"="machine" }
217 attributes #1 = { "interrupt"="machine" "no-frame-pointer-elim"="true" }