[ARM] Refactor the prologue/epilogue emission to be more robust.
[oota-llvm.git] / test / CodeGen / ARM / thumb1_return_sequence.ll
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
3
4 ; CHECK-V4T-LABEL: clobberframe
5 ; CHECK-V5T-LABEL: clobberframe
6 define <4 x i32> @clobberframe(<6 x i32>* %p) #0 {
7 entry:
8 ; Prologue
9 ; --------
10 ; CHECK-V4T:    push {[[SAVED:(r[4567](, )?)+]], lr}
11 ; CHECK-V4T:    sub sp,
12 ; CHECK-V5T:    push {[[SAVED:(r[4567](, )?)+]], lr}
13
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
20   ret <4 x i32> %0
21
22 ; Epilogue
23 ; --------
24 ; CHECK-V4T:         add sp,
25 ; CHECK-V4T-NEXT:    pop {[[SAVED]]}
26 ; We do not have any SP update to insert so we can just optimize
27 ; the pop sequence.
28 ; CHECK-V4T-NEXT:    pop {pc}
29 ; CHECK-V5T:         pop {[[SAVED]], pc}
30 }
31
32 ; CHECK-V4T-LABEL: clobbervariadicframe
33 ; CHECK-V5T-LABEL: clobbervariadicframe
34 define <4 x i32> @clobbervariadicframe(i32 %i, ...) #0 {
35 entry:
36 ; Prologue
37 ; --------
38 ; CHECK-V4T:    sub sp,
39 ; CHECK-V4T:    push {[[SAVED:(r[4567](, )?)+]], lr}
40 ; CHECK-V5T:    sub sp,
41 ; CHECK-V5T:    push {[[SAVED:(r[4567](, )?)+]], lr}
42
43   %b = alloca <4 x i32>, align 16
44   %a = alloca <4 x i32>, align 16
45   store <4 x i32> <i32 42, i32 42, i32 42, i32 42>, <4 x i32>* %b, align 16
46   store <4 x i32> <i32 0, i32 1, i32 2, i32 3>, <4 x i32>* %a, align 16
47   %0 = load <4 x i32>, <4 x i32>* %a, align 16
48   call void @llvm.va_start(i8* null)
49   ret <4 x i32> %0
50
51 ; Epilogue
52 ; --------
53 ; CHECK-V4T:         pop {[[SAVED]]}
54 ; CHECK-V4T-NEXT:    mov r12, [[POP_REG:r[0-7]]]
55 ; CHECK-V4T-NEXT:    pop {[[POP_REG]]}
56 ; CHECK-V4T-NEXT:    add sp,
57 ; CHECK-V4T-NEXT:    mov lr, [[POP_REG]]
58 ; CHECK-V4T-NEXT:    mov [[POP_REG]], r12
59 ; CHECK-V4T:         bx  lr
60 ; CHECK-V5T:         add sp,
61 ; CHECK-V5T-NEXT:    pop {[[SAVED]]}
62 ; CHECK-V5T-NEXT:    mov r12, [[POP_REG:r[0-7]]]
63 ; CHECK-V5T-NEXT:    pop {[[POP_REG]]}
64 ; CHECK-V5T-NEXT:    add sp,
65 ; CHECK-V5T-NEXT:    mov lr, [[POP_REG]]
66 ; CHECK-V5T-NEXT:    mov [[POP_REG]], r12
67 ; CHECK-V5T-NEXT:    bx lr
68 }
69
70 ; CHECK-V4T-LABEL: simpleframe
71 ; CHECK-V5T-LABEL: simpleframe
72 define i32 @simpleframe(<6 x i32>* %p) #0 {
73 entry:
74 ; Prologue
75 ; --------
76 ; CHECK-V4T:    push    {[[SAVED:(r[4567](, )?)+]], lr}
77 ; CHECK-V5T:    push    {[[SAVED:(r[4567](, )?)+]], lr}
78
79   %0 = load <6 x i32>, <6 x i32>* %p, align 16
80   %1 = extractelement <6 x i32> %0, i32 0
81   %2 = extractelement <6 x i32> %0, i32 1
82   %3 = extractelement <6 x i32> %0, i32 2
83   %4 = extractelement <6 x i32> %0, i32 3
84   %5 = extractelement <6 x i32> %0, i32 4
85   %6 = extractelement <6 x i32> %0, i32 5
86   %add1 = add nsw i32 %1, %2
87   %add2 = add nsw i32 %add1, %3
88   %add3 = add nsw i32 %add2, %4
89   %add4 = add nsw i32 %add3, %5
90   %add5 = add nsw i32 %add4, %6
91   ret i32 %add5
92
93 ; Epilogue
94 ; --------
95 ; CHECK-V4T:    pop {[[SAVED]]}
96 ; CHECK-V4T:    pop {pc}
97 ; CHECK-V5T:    pop {[[SAVED]], pc}
98 }
99
100 ; CHECK-V4T-LABEL: simplevariadicframe
101 ; CHECK-V5T-LABEL: simplevariadicframe
102 define i32 @simplevariadicframe(i32 %i, ...) #0 {
103 entry:
104 ; Prologue
105 ; --------
106 ; CHECK-V4T:    sub sp,
107 ; CHECK-V4T:    push {[[SAVED:(r[4567](, )?)+]], lr}
108 ; CHECK-V4T:    sub sp,
109 ; CHECK-V5T:    sub sp,
110 ; CHECK-V5T:    push {[[SAVED:(r[4567](, )?)+]], lr}
111 ; CHECK-V5T:    sub sp,
112
113   %a = alloca i32, align 4
114   %b = alloca i32, align 4
115   %c = alloca i32, align 4
116   %d = alloca i32, align 4
117   store i32 1, i32* %a, align 4
118   store i32 2, i32* %b, align 4
119   store i32 3, i32* %c, align 4
120   store i32 4, i32* %d, align 4
121   %0 = load i32, i32* %a, align 4
122   %inc = add nsw i32 %0, 1
123   store i32 %inc, i32* %a, align 4
124   %1 = load i32, i32* %b, align 4
125   %inc1 = add nsw i32 %1, 1
126   store i32 %inc1, i32* %b, align 4
127   %2 = load i32, i32* %c, align 4
128   %inc2 = add nsw i32 %2, 1
129   store i32 %inc2, i32* %c, align 4
130   %3 = load i32, i32* %d, align 4
131   %inc3 = add nsw i32 %3, 1
132   store i32 %inc3, i32* %d, align 4
133   %4 = load i32, i32* %a, align 4
134   %5 = load i32, i32* %b, align 4
135   %add = add nsw i32 %4, %5
136   %6 = load i32, i32* %c, align 4
137   %add4 = add nsw i32 %add, %6
138   %7 = load i32, i32* %d, align 4
139   %add5 = add nsw i32 %add4, %7
140   %add6 = add nsw i32 %add5, %i
141   call void @llvm.va_start(i8* null)
142   ret i32 %add6
143
144 ; Epilogue
145 ; --------
146 ; CHECK-V4T:         add sp,
147 ; CHECK-V4T-NEXT:    pop {[[SAVED]]}
148 ; Only r1 to r3 are available to pop LR.
149 ; r0 is used for the return value.
150 ; CHECK-V4T-NEXT:    pop {[[POP_REG:r[1-3]]]}
151 ; CHECK-V4T-NEXT:    add sp,
152 ; CHECK-V4T-NEXT:    bx [[POP_REG]]
153 ; CHECK-V5T:         add sp,
154 ; CHECK-V5T-NEXT:    pop {[[SAVED]]}
155 ; Only r1 to r3 are available to pop LR.
156 ; r0 is used for the return value.
157 ; CHECK-V5T-NEXT:    pop {[[POP_REG:r[1-3]]]}
158 ; CHECK-V5T-NEXT:    add sp,
159 ; CHECK-V5T-NEXT:    bx [[POP_REG]]
160 }
161
162 ; CHECK-V4T-LABEL: noframe
163 ; CHECK-V5T-LABEL: noframe
164 define i32 @noframe() #0 {
165 entry:
166 ; Prologue
167 ; --------
168 ; CHECK-V4T-NOT: push
169 ; CHECK-V5T-NOT: push
170     ret i32 0;
171 ; Epilogue
172 ; --------
173 ; CHECK-V4T-NOT: pop
174 ; CHECK-V5T-NOT: pop
175 ; CHECK-V4T:    bx  lr
176 ; CHECK-V5T:    bx  lr
177 }
178
179 ; CHECK-V4T-LABEL: novariadicframe
180 ; CHECK-V5T-LABEL: novariadicframe
181 define i32 @novariadicframe(i32 %i, ...) #0 {
182 entry:
183 ; Prologue
184 ; --------
185 ; CHECK-V4T:    sub sp,
186 ; CHECK-V4T:    push {[[SAVED:(r[4567](, )?)+]], lr}
187 ; CHECK-V5T:    sub sp,
188 ; CHECK-V5T:    push {[[SAVED:(r[4567](, )?)+]], lr}
189
190   call void @llvm.va_start(i8* null)
191   ret i32 %i;
192 ; Epilogue
193 ; --------
194 ; CHECK-V4T:         pop {[[SAVED]]}
195 ; Only r1 to r3 are available to pop LR.
196 ; r0 is used for the return value.
197 ; CHECK-V4T-NEXT:    pop {[[POP_REG:r[1-3]]]}
198 ; CHECK-V4T-NEXT:    add sp,
199 ; CHECK-V4T-NEXT:    bx [[POP_REG]]
200 ; CHECK-V5T:         pop {[[SAVED]]}
201 ; Only r1 to r3 are available to pop LR.
202 ; r0 is used for the return value.
203 ; CHECK-V5T-NEXT:    pop {[[POP_REG:r[1-3]]]}
204 ; CHECK-V5T-NEXT:    add sp,
205 ; CHECK-V5T-NEXT:    bx [[POP_REG]]
206 }
207
208 declare void @llvm.va_start(i8*) nounwind