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 ; Stack is realigned because of the <6 x i32> type
13 ; CHECK-V4T: mov sp, r4
14 ; CHECK-V5T: push {[[SAVED:(r[4567](, )?)+]], lr}
16 %b = alloca <6 x i32>, align 16
17 %a = alloca <4 x i32>, align 16
18 %stuff = load <6 x i32>, <6 x i32>* %p, align 16
19 store <6 x i32> %stuff, <6 x i32>* %b, align 16
20 store <4 x i32> <i32 0, i32 1, i32 2, i32 3>, <4 x i32>* %a, align 16
21 %0 = load <4 x i32>, <4 x i32>* %a, align 16
26 ; Stack realignment means sp is restored from frame pointer
28 ; CHECK-V4T-NEXT: ldr [[POP:r[4567]]], [sp, #16]
29 ; CHECK-V4T-NEXT: mov lr, [[POP]]
30 ; CHECK-V4T-NEXT: pop {[[SAVED]]}
31 ; CHECK-V4T-NEXT add sp, sp, #4
32 ; The ISA for v4 does not support pop pc, so make sure we do not emit
33 ; one even when we do not need to update SP.
34 ; CHECK-V4T-NOT: pop {pc}
36 ; CHECK-V5T: pop {[[SAVED]], pc}
39 ; CHECK-V4T-LABEL: clobbervariadicframe
40 ; CHECK-V5T-LABEL: clobbervariadicframe
41 define <4 x i32> @clobbervariadicframe(i32 %i, ...) #0 {
46 ; CHECK-V4T: push {[[SAVED:(r[4567](, )?)+]], lr}
48 ; CHECK-V5T: push {[[SAVED:(r[4567](, )?)+]], lr}
50 %b = alloca <4 x i32>, align 16
51 %a = alloca <4 x i32>, align 16
52 store <4 x i32> <i32 42, i32 42, i32 42, i32 42>, <4 x i32>* %b, align 16
53 store <4 x i32> <i32 0, i32 1, i32 2, i32 3>, <4 x i32>* %a, align 16
54 %0 = load <4 x i32>, <4 x i32>* %a, align 16
55 call void @llvm.va_start(i8* null)
60 ; CHECK-V4T: ldr [[POP:r[4567]]], [sp, #16]
61 ; CHECK-V4T-NEXT: mov lr, [[POP]]
62 ; CHECK-V4T-NEXT: pop {[[SAVED]]}
63 ; CHECK-V4T-NEXT: add sp, #16
64 ; CHECK-V4T-NEXT: bx lr
66 ; CHECK-V5T-NEXT: mov sp, r4
67 ; CHECK-V5T: ldr [[POP:r[4567]]], [sp, #16]
68 ; CHECK-V5T-NEXT: mov lr, [[POP]]
69 ; CHECK-V5T-NEXT: pop {[[SAVED]]}
70 ; CHECK-V5T-NEXT: add sp, #16
71 ; CHECK-V5T-NEXT: bx lr
74 ; CHECK-V4T-LABEL: simpleframe
75 ; CHECK-V5T-LABEL: simpleframe
76 define i32 @simpleframe(<6 x i32>* %p) #0 {
80 ; CHECK-V4T: push {[[SAVED:(r[4567](, )?)+]], lr}
81 ; CHECK-V5T: push {[[SAVED:(r[4567](, )?)+]], lr}
83 %0 = load <6 x i32>, <6 x i32>* %p, align 16
84 %1 = extractelement <6 x i32> %0, i32 0
85 %2 = extractelement <6 x i32> %0, i32 1
86 %3 = extractelement <6 x i32> %0, i32 2
87 %4 = extractelement <6 x i32> %0, i32 3
88 %5 = extractelement <6 x i32> %0, i32 4
89 %6 = extractelement <6 x i32> %0, i32 5
90 %add1 = add nsw i32 %1, %2
91 %add2 = add nsw i32 %add1, %3
92 %add3 = add nsw i32 %add2, %4
93 %add4 = add nsw i32 %add3, %5
94 %add5 = add nsw i32 %add4, %6
99 ; CHECK-V4T: pop {[[SAVED]]}
100 ; The ISA for v4 does not support pop pc, so make sure we do not emit
101 ; one even when we do not need to update SP.
102 ; CHECK-V4T-NOT: pop {pc}
103 ; Pop the value of LR into a scratch lo register other than r0 (it is
104 ; used for the return value).
105 ; CHECK-V4T-NEXT: pop {[[POP_REG:r[1-3]]]}
106 ; CHECK-V4T-NEXT: bx [[POP_REG]]
107 ; CHECK-V5T: pop {[[SAVED]], pc}
110 ; CHECK-V4T-LABEL: simplevariadicframe
111 ; CHECK-V5T-LABEL: simplevariadicframe
112 define i32 @simplevariadicframe(i32 %i, ...) #0 {
117 ; CHECK-V4T: push {[[SAVED:(r[4567](, )?)+]], lr}
120 ; CHECK-V5T: push {[[SAVED:(r[4567](, )?)+]], lr}
123 %a = alloca i32, align 4
124 %b = alloca i32, align 4
125 %c = alloca i32, align 4
126 %d = alloca i32, align 4
127 store i32 1, i32* %a, align 4
128 store i32 2, i32* %b, align 4
129 store i32 3, i32* %c, align 4
130 store i32 4, i32* %d, align 4
131 %0 = load i32, i32* %a, align 4
132 %inc = add nsw i32 %0, 1
133 store i32 %inc, i32* %a, align 4
134 %1 = load i32, i32* %b, align 4
135 %inc1 = add nsw i32 %1, 1
136 store i32 %inc1, i32* %b, align 4
137 %2 = load i32, i32* %c, align 4
138 %inc2 = add nsw i32 %2, 1
139 store i32 %inc2, i32* %c, align 4
140 %3 = load i32, i32* %d, align 4
141 %inc3 = add nsw i32 %3, 1
142 store i32 %inc3, i32* %d, align 4
143 %4 = load i32, i32* %a, align 4
144 %5 = load i32, i32* %b, align 4
145 %add = add nsw i32 %4, %5
146 %6 = load i32, i32* %c, align 4
147 %add4 = add nsw i32 %add, %6
148 %7 = load i32, i32* %d, align 4
149 %add5 = add nsw i32 %add4, %7
150 %add6 = add nsw i32 %add5, %i
151 call void @llvm.va_start(i8* null)
157 ; CHECK-V4T-NEXT: pop {[[SAVED]]}
158 ; Only r1 to r3 are available to pop LR.
159 ; r0 is used for the return value.
160 ; CHECK-V4T-NEXT: pop {[[POP_REG:r[1-3]]]}
161 ; CHECK-V4T-NEXT: add sp,
162 ; CHECK-V4T-NEXT: bx [[POP_REG]]
164 ; CHECK-V5T-NEXT: pop {[[SAVED]]}
165 ; Only r1 to r3 are available to pop LR.
166 ; r0 is used for the return value.
167 ; CHECK-V5T-NEXT: pop {[[POP_REG:r[1-3]]]}
168 ; CHECK-V5T-NEXT: add sp,
169 ; CHECK-V5T-NEXT: bx [[POP_REG]]
172 ; CHECK-V4T-LABEL: noframe
173 ; CHECK-V5T-LABEL: noframe
174 define i32 @noframe() #0 {
178 ; CHECK-V4T-NOT: push
179 ; CHECK-V5T-NOT: push
189 ; CHECK-V4T-LABEL: novariadicframe
190 ; CHECK-V5T-LABEL: novariadicframe
191 define i32 @novariadicframe(i32 %i, ...) #0 {
196 ; CHECK-V4T: push {[[SAVED:(r[4567](, )?)+]], lr}
198 ; CHECK-V5T: push {[[SAVED:(r[4567](, )?)+]], lr}
200 call void @llvm.va_start(i8* null)
204 ; CHECK-V4T: pop {[[SAVED]]}
205 ; Only r1 to r3 are available to pop LR.
206 ; r0 is used for the return value.
207 ; CHECK-V4T-NEXT: pop {[[POP_REG:r[1-3]]]}
208 ; CHECK-V4T-NEXT: add sp,
209 ; CHECK-V4T-NEXT: bx [[POP_REG]]
210 ; CHECK-V5T: pop {[[SAVED]]}
211 ; Only r1 to r3 are available to pop LR.
212 ; r0 is used for the return value.
213 ; CHECK-V5T-NEXT: pop {[[POP_REG:r[1-3]]]}
214 ; CHECK-V5T-NEXT: add sp,
215 ; CHECK-V5T-NEXT: bx [[POP_REG]]
218 declare void @llvm.va_start(i8*) nounwind