1 ; RUN: llc -mtriple=thumbv4t-none--eabi < %s | FileCheck %s --check-prefix=CHECK-V4T
2 ; RUN: llc -mtriple=thumbv5t-none--eabi < %s | FileCheck %s --check-prefix=CHECK-V5T
4 ; CHECK-V4T-LABEL: clobberframe
5 ; CHECK-V5T-LABEL: clobberframe
6 define <4 x i32> @clobberframe(<6 x i32>* %p) #0 {
10 ; CHECK-V4T: push {[[SAVED:(r[4567](, )?)+]], lr}
12 ; CHECK-V5T: push {[[SAVED:(r[4567](, )?)+]], lr}
14 %b = alloca <6 x i32>, align 16
15 %a = alloca <4 x i32>, align 16
16 %stuff = load <6 x i32>, <6 x i32>* %p, align 16
17 store <6 x i32> %stuff, <6 x i32>* %b, align 16
18 store <4 x i32> <i32 0, i32 1, i32 2, i32 3>, <4 x i32>* %a, align 16
19 %0 = load <4 x i32>, <4 x i32>* %a, align 16
25 ; CHECK-V4T-NEXT: pop {[[SAVED]]}
26 ; The ISA for v4 does not support pop pc, so make sure we do not emit
27 ; one even when we do not need to update SP.
28 ; CHECK-V4T-NOT: pop {pc}
29 ; We may only use lo register to pop, but in that case, all the scratch
31 ; r12 is the only register we are allowed to clobber for AAPCS.
32 ; Use it to save a lo register.
33 ; CHECK-V4T-NEXT: mov [[TEMP_REG:r12]], [[POP_REG:r[0-7]]]
34 ; Pop the value of LR.
35 ; CHECK-V4T-NEXT: pop {[[POP_REG]]}
36 ; Copy the value of LR in the right register.
37 ; CHECK-V4T-NEXT: mov lr, [[POP_REG]]
38 ; Restore the value that was in the register we used to pop the value of LR.
39 ; CHECK-V4T-NEXT: mov [[POP_REG]], [[TEMP_REG]]
41 ; CHECK-V4T-NEXT: bx lr
42 ; CHECK-V5T: pop {[[SAVED]], pc}
45 ; CHECK-V4T-LABEL: clobbervariadicframe
46 ; CHECK-V5T-LABEL: clobbervariadicframe
47 define <4 x i32> @clobbervariadicframe(i32 %i, ...) #0 {
52 ; CHECK-V4T: push {[[SAVED:(r[4567](, )?)+]], lr}
54 ; CHECK-V5T: push {[[SAVED:(r[4567](, )?)+]], lr}
56 %b = alloca <4 x i32>, align 16
57 %a = alloca <4 x i32>, align 16
58 store <4 x i32> <i32 42, i32 42, i32 42, i32 42>, <4 x i32>* %b, align 16
59 store <4 x i32> <i32 0, i32 1, i32 2, i32 3>, <4 x i32>* %a, align 16
60 %0 = load <4 x i32>, <4 x i32>* %a, align 16
61 call void @llvm.va_start(i8* null)
66 ; CHECK-V4T: pop {[[SAVED]]}
67 ; CHECK-V4T-NEXT: mov r12, [[POP_REG:r[0-7]]]
68 ; CHECK-V4T-NEXT: pop {[[POP_REG]]}
69 ; CHECK-V4T-NEXT: add sp,
70 ; CHECK-V4T-NEXT: mov lr, [[POP_REG]]
71 ; CHECK-V4T-NEXT: mov [[POP_REG]], r12
74 ; CHECK-V5T-NEXT: pop {[[SAVED]]}
75 ; CHECK-V5T-NEXT: mov r12, [[POP_REG:r[0-7]]]
76 ; CHECK-V5T-NEXT: pop {[[POP_REG]]}
77 ; CHECK-V5T-NEXT: add sp,
78 ; CHECK-V5T-NEXT: mov lr, [[POP_REG]]
79 ; CHECK-V5T-NEXT: mov [[POP_REG]], r12
80 ; CHECK-V5T-NEXT: bx lr
83 ; CHECK-V4T-LABEL: simpleframe
84 ; CHECK-V5T-LABEL: simpleframe
85 define i32 @simpleframe(<6 x i32>* %p) #0 {
89 ; CHECK-V4T: push {[[SAVED:(r[4567](, )?)+]], lr}
90 ; CHECK-V5T: push {[[SAVED:(r[4567](, )?)+]], lr}
92 %0 = load <6 x i32>, <6 x i32>* %p, align 16
93 %1 = extractelement <6 x i32> %0, i32 0
94 %2 = extractelement <6 x i32> %0, i32 1
95 %3 = extractelement <6 x i32> %0, i32 2
96 %4 = extractelement <6 x i32> %0, i32 3
97 %5 = extractelement <6 x i32> %0, i32 4
98 %6 = extractelement <6 x i32> %0, i32 5
99 %add1 = add nsw i32 %1, %2
100 %add2 = add nsw i32 %add1, %3
101 %add3 = add nsw i32 %add2, %4
102 %add4 = add nsw i32 %add3, %5
103 %add5 = add nsw i32 %add4, %6
108 ; CHECK-V4T: pop {[[SAVED]]}
109 ; The ISA for v4 does not support pop pc, so make sure we do not emit
110 ; one even when we do not need to update SP.
111 ; CHECK-V4T-NOT: pop {pc}
112 ; Pop the value of LR into a scratch lo register other than r0 (it is
113 ; used for the return value).
114 ; CHECK-V4T-NEXT: pop {[[POP_REG:r[1-3]]]}
115 ; CHECK-V4T-NEXT: bx [[POP_REG]]
116 ; CHECK-V5T: pop {[[SAVED]], pc}
119 ; CHECK-V4T-LABEL: simplevariadicframe
120 ; CHECK-V5T-LABEL: simplevariadicframe
121 define i32 @simplevariadicframe(i32 %i, ...) #0 {
126 ; CHECK-V4T: push {[[SAVED:(r[4567](, )?)+]], lr}
129 ; CHECK-V5T: push {[[SAVED:(r[4567](, )?)+]], lr}
132 %a = alloca i32, align 4
133 %b = alloca i32, align 4
134 %c = alloca i32, align 4
135 %d = alloca i32, align 4
136 store i32 1, i32* %a, align 4
137 store i32 2, i32* %b, align 4
138 store i32 3, i32* %c, align 4
139 store i32 4, i32* %d, align 4
140 %0 = load i32, i32* %a, align 4
141 %inc = add nsw i32 %0, 1
142 store i32 %inc, i32* %a, align 4
143 %1 = load i32, i32* %b, align 4
144 %inc1 = add nsw i32 %1, 1
145 store i32 %inc1, i32* %b, align 4
146 %2 = load i32, i32* %c, align 4
147 %inc2 = add nsw i32 %2, 1
148 store i32 %inc2, i32* %c, align 4
149 %3 = load i32, i32* %d, align 4
150 %inc3 = add nsw i32 %3, 1
151 store i32 %inc3, i32* %d, align 4
152 %4 = load i32, i32* %a, align 4
153 %5 = load i32, i32* %b, align 4
154 %add = add nsw i32 %4, %5
155 %6 = load i32, i32* %c, align 4
156 %add4 = add nsw i32 %add, %6
157 %7 = load i32, i32* %d, align 4
158 %add5 = add nsw i32 %add4, %7
159 %add6 = add nsw i32 %add5, %i
160 call void @llvm.va_start(i8* null)
166 ; CHECK-V4T-NEXT: pop {[[SAVED]]}
167 ; Only r1 to r3 are available to pop LR.
168 ; r0 is used for the return value.
169 ; CHECK-V4T-NEXT: pop {[[POP_REG:r[1-3]]]}
170 ; CHECK-V4T-NEXT: add sp,
171 ; CHECK-V4T-NEXT: bx [[POP_REG]]
173 ; CHECK-V5T-NEXT: pop {[[SAVED]]}
174 ; Only r1 to r3 are available to pop LR.
175 ; r0 is used for the return value.
176 ; CHECK-V5T-NEXT: pop {[[POP_REG:r[1-3]]]}
177 ; CHECK-V5T-NEXT: add sp,
178 ; CHECK-V5T-NEXT: bx [[POP_REG]]
181 ; CHECK-V4T-LABEL: noframe
182 ; CHECK-V5T-LABEL: noframe
183 define i32 @noframe() #0 {
187 ; CHECK-V4T-NOT: push
188 ; CHECK-V5T-NOT: push
198 ; CHECK-V4T-LABEL: novariadicframe
199 ; CHECK-V5T-LABEL: novariadicframe
200 define i32 @novariadicframe(i32 %i, ...) #0 {
205 ; CHECK-V4T: push {[[SAVED:(r[4567](, )?)+]], lr}
207 ; CHECK-V5T: push {[[SAVED:(r[4567](, )?)+]], lr}
209 call void @llvm.va_start(i8* null)
213 ; CHECK-V4T: pop {[[SAVED]]}
214 ; Only r1 to r3 are available to pop LR.
215 ; r0 is used for the return value.
216 ; CHECK-V4T-NEXT: pop {[[POP_REG:r[1-3]]]}
217 ; CHECK-V4T-NEXT: add sp,
218 ; CHECK-V4T-NEXT: bx [[POP_REG]]
219 ; CHECK-V5T: pop {[[SAVED]]}
220 ; Only r1 to r3 are available to pop LR.
221 ; r0 is used for the return value.
222 ; CHECK-V5T-NEXT: pop {[[POP_REG:r[1-3]]]}
223 ; CHECK-V5T-NEXT: add sp,
224 ; CHECK-V5T-NEXT: bx [[POP_REG]]
227 declare void @llvm.va_start(i8*) nounwind