[ARM] Adjust how NEON shifts are lowered
[llvm-core.git] / test / CodeGen / ARM / addsubo-legalization.ll
blobc899e5f73ead3df5c722f5085396c4e783559247
1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc < %s -mtriple=thumbv7k-linux-gnu | FileCheck %s
4 declare {<2 x i64>, <2 x i1>} @llvm.uadd.with.overflow.v2i64(<2 x i64>, <2 x i64>)
5 declare {<2 x i64>, <2 x i1>} @llvm.usub.with.overflow.v2i64(<2 x i64>, <2 x i64>)
6 declare {<2 x i64>, <2 x i1>} @llvm.sadd.with.overflow.v2i64(<2 x i64>, <2 x i64>)
7 declare {<2 x i64>, <2 x i1>} @llvm.ssub.with.overflow.v2i64(<2 x i64>, <2 x i64>)
9 define <2 x i1> @uaddo(<2 x i64> *%ptr, <2 x i64> *%ptr2) {
10 ; CHECK-LABEL: uaddo:
11 ; CHECK:       @ %bb.0:
12 ; CHECK-NEXT:    push {r4, r5, r6, r7, lr}
13 ; CHECK-NEXT:    vld1.64 {d18, d19}, [r0]
14 ; CHECK-NEXT:    vld1.64 {d16, d17}, [r1]
15 ; CHECK-NEXT:    movs r1, #0
16 ; CHECK-NEXT:    vadd.i64 q8, q9, q8
17 ; CHECK-NEXT:    vmov.32 r3, d18[0]
18 ; CHECK-NEXT:    vmov.32 r2, d18[1]
19 ; CHECK-NEXT:    vmov.32 r12, d16[0]
20 ; CHECK-NEXT:    vmov.32 lr, d16[1]
21 ; CHECK-NEXT:    vmov.32 r4, d17[0]
22 ; CHECK-NEXT:    vmov.32 r5, d19[0]
23 ; CHECK-NEXT:    vmov.32 r6, d17[1]
24 ; CHECK-NEXT:    vmov.32 r7, d19[1]
25 ; CHECK-NEXT:    subs.w r3, r12, r3
26 ; CHECK-NEXT:    sbcs.w r2, lr, r2
27 ; CHECK-NEXT:    mov.w r2, #0
28 ; CHECK-NEXT:    it lo
29 ; CHECK-NEXT:    movlo r2, #1
30 ; CHECK-NEXT:    cmp r2, #0
31 ; CHECK-NEXT:    it ne
32 ; CHECK-NEXT:    movne.w r2, #-1
33 ; CHECK-NEXT:    subs r3, r4, r5
34 ; CHECK-NEXT:    sbcs.w r3, r6, r7
35 ; CHECK-NEXT:    it lo
36 ; CHECK-NEXT:    movlo r1, #1
37 ; CHECK-NEXT:    cmp r1, #0
38 ; CHECK-NEXT:    it ne
39 ; CHECK-NEXT:    movne.w r1, #-1
40 ; CHECK-NEXT:    vst1.64 {d16, d17}, [r0]
41 ; CHECK-NEXT:    mov r0, r2
42 ; CHECK-NEXT:    pop {r4, r5, r6, r7, pc}
43   %x = load <2 x i64>, <2 x i64>* %ptr, align 8
44   %y = load <2 x i64>, <2 x i64>* %ptr2, align 8
45   %s = call {<2 x i64>, <2 x i1>} @llvm.uadd.with.overflow.v2i64(<2 x i64> %x, <2 x i64> %y)
46   %m = extractvalue {<2 x i64>, <2 x i1>} %s, 0
47   %o = extractvalue {<2 x i64>, <2 x i1>} %s, 1
48   store <2 x i64> %m, <2 x i64>* %ptr
49   ret <2 x i1> %o
52 define <2 x i1> @usubo(<2 x i64> *%ptr, <2 x i64> *%ptr2) {
53 ; CHECK-LABEL: usubo:
54 ; CHECK:       @ %bb.0:
55 ; CHECK-NEXT:    push {r4, r5, r6, r7, lr}
56 ; CHECK-NEXT:    vld1.64 {d16, d17}, [r1]
57 ; CHECK-NEXT:    movs r1, #0
58 ; CHECK-NEXT:    vld1.64 {d18, d19}, [r0]
59 ; CHECK-NEXT:    vsub.i64 q8, q9, q8
60 ; CHECK-NEXT:    vmov.32 r12, d18[0]
61 ; CHECK-NEXT:    vmov.32 lr, d18[1]
62 ; CHECK-NEXT:    vmov.32 r3, d16[0]
63 ; CHECK-NEXT:    vmov.32 r2, d16[1]
64 ; CHECK-NEXT:    vmov.32 r4, d19[0]
65 ; CHECK-NEXT:    vmov.32 r5, d17[0]
66 ; CHECK-NEXT:    vmov.32 r6, d19[1]
67 ; CHECK-NEXT:    vmov.32 r7, d17[1]
68 ; CHECK-NEXT:    subs.w r3, r12, r3
69 ; CHECK-NEXT:    sbcs.w r2, lr, r2
70 ; CHECK-NEXT:    mov.w r2, #0
71 ; CHECK-NEXT:    it lo
72 ; CHECK-NEXT:    movlo r2, #1
73 ; CHECK-NEXT:    cmp r2, #0
74 ; CHECK-NEXT:    it ne
75 ; CHECK-NEXT:    movne.w r2, #-1
76 ; CHECK-NEXT:    subs r3, r4, r5
77 ; CHECK-NEXT:    sbcs.w r3, r6, r7
78 ; CHECK-NEXT:    it lo
79 ; CHECK-NEXT:    movlo r1, #1
80 ; CHECK-NEXT:    cmp r1, #0
81 ; CHECK-NEXT:    it ne
82 ; CHECK-NEXT:    movne.w r1, #-1
83 ; CHECK-NEXT:    vst1.64 {d16, d17}, [r0]
84 ; CHECK-NEXT:    mov r0, r2
85 ; CHECK-NEXT:    pop {r4, r5, r6, r7, pc}
86   %x = load <2 x i64>, <2 x i64>* %ptr, align 8
87   %y = load <2 x i64>, <2 x i64>* %ptr2, align 8
88   %s = call {<2 x i64>, <2 x i1>} @llvm.usub.with.overflow.v2i64(<2 x i64> %x, <2 x i64> %y)
89   %m = extractvalue {<2 x i64>, <2 x i1>} %s, 0
90   %o = extractvalue {<2 x i64>, <2 x i1>} %s, 1
91   store <2 x i64> %m, <2 x i64>* %ptr
92   ret <2 x i1> %o
95 define <2 x i1> @saddo(<2 x i64> *%ptr, <2 x i64> *%ptr2) {
96 ; CHECK-LABEL: saddo:
97 ; CHECK:       @ %bb.0:
98 ; CHECK-NEXT:    push {r4, r5, r6, r7, lr}
99 ; CHECK-NEXT:    vld1.64 {d16, d17}, [r1]
100 ; CHECK-NEXT:    movs r5, #0
101 ; CHECK-NEXT:    movs r6, #0
102 ; CHECK-NEXT:    movs r3, #0
103 ; CHECK-NEXT:    vmov.32 r1, d16[1]
104 ; CHECK-NEXT:    vld1.64 {d18, d19}, [r0]
105 ; CHECK-NEXT:    vmov.32 r2, d17[1]
106 ; CHECK-NEXT:    vadd.i64 q8, q9, q8
107 ; CHECK-NEXT:    vmov.32 r12, d18[1]
108 ; CHECK-NEXT:    vmov.32 r4, d19[1]
109 ; CHECK-NEXT:    vmov.32 lr, d16[1]
110 ; CHECK-NEXT:    vmov.32 r7, d17[1]
111 ; CHECK-NEXT:    cmp.w r1, #-1
112 ; CHECK-NEXT:    mov.w r1, #0
113 ; CHECK-NEXT:    it gt
114 ; CHECK-NEXT:    movgt r1, #1
115 ; CHECK-NEXT:    cmp r1, #0
116 ; CHECK-NEXT:    it ne
117 ; CHECK-NEXT:    movne.w r1, #-1
118 ; CHECK-NEXT:    cmp.w r2, #-1
119 ; CHECK-NEXT:    mov.w r2, #0
120 ; CHECK-NEXT:    it gt
121 ; CHECK-NEXT:    movgt r2, #1
122 ; CHECK-NEXT:    cmp.w r12, #-1
123 ; CHECK-NEXT:    it gt
124 ; CHECK-NEXT:    movgt r5, #1
125 ; CHECK-NEXT:    cmp r5, #0
126 ; CHECK-NEXT:    it ne
127 ; CHECK-NEXT:    movne.w r5, #-1
128 ; CHECK-NEXT:    cmp.w r4, #-1
129 ; CHECK-NEXT:    mov.w r4, #0
130 ; CHECK-NEXT:    it gt
131 ; CHECK-NEXT:    movgt r4, #1
132 ; CHECK-NEXT:    cmp.w lr, #-1
133 ; CHECK-NEXT:    it gt
134 ; CHECK-NEXT:    movgt r6, #1
135 ; CHECK-NEXT:    cmp r6, #0
136 ; CHECK-NEXT:    it ne
137 ; CHECK-NEXT:    movne.w r6, #-1
138 ; CHECK-NEXT:    cmp.w r7, #-1
139 ; CHECK-NEXT:    it gt
140 ; CHECK-NEXT:    movgt r3, #1
141 ; CHECK-NEXT:    cmp r3, #0
142 ; CHECK-NEXT:    it ne
143 ; CHECK-NEXT:    movne.w r3, #-1
144 ; CHECK-NEXT:    cmp r4, #0
145 ; CHECK-NEXT:    vdup.32 d19, r3
146 ; CHECK-NEXT:    it ne
147 ; CHECK-NEXT:    movne.w r4, #-1
148 ; CHECK-NEXT:    cmp r2, #0
149 ; CHECK-NEXT:    it ne
150 ; CHECK-NEXT:    movne.w r2, #-1
151 ; CHECK-NEXT:    vdup.32 d23, r2
152 ; CHECK-NEXT:    vdup.32 d21, r4
153 ; CHECK-NEXT:    vdup.32 d18, r6
154 ; CHECK-NEXT:    vdup.32 d22, r1
155 ; CHECK-NEXT:    vdup.32 d20, r5
156 ; CHECK-NEXT:    vceq.i32 q9, q10, q9
157 ; CHECK-NEXT:    vst1.64 {d16, d17}, [r0]
158 ; CHECK-NEXT:    vceq.i32 q10, q10, q11
159 ; CHECK-NEXT:    vrev64.32 q11, q9
160 ; CHECK-NEXT:    vrev64.32 q12, q10
161 ; CHECK-NEXT:    vand q9, q9, q11
162 ; CHECK-NEXT:    vand q10, q10, q12
163 ; CHECK-NEXT:    vbic q9, q10, q9
164 ; CHECK-NEXT:    vmovn.i64 d18, q9
165 ; CHECK-NEXT:    vmov r2, r1, d18
166 ; CHECK-NEXT:    mov r0, r2
167 ; CHECK-NEXT:    pop {r4, r5, r6, r7, pc}
168   %x = load <2 x i64>, <2 x i64>* %ptr, align 8
169   %y = load <2 x i64>, <2 x i64>* %ptr2, align 8
170   %s = call {<2 x i64>, <2 x i1>} @llvm.sadd.with.overflow.v2i64(<2 x i64> %x, <2 x i64> %y)
171   %m = extractvalue {<2 x i64>, <2 x i1>} %s, 0
172   %o = extractvalue {<2 x i64>, <2 x i1>} %s, 1
173   store <2 x i64> %m, <2 x i64>* %ptr
174   ret <2 x i1> %o
177 define <2 x i1> @ssubo(<2 x i64> *%ptr, <2 x i64> *%ptr2) {
178 ; CHECK-LABEL: ssubo:
179 ; CHECK:       @ %bb.0:
180 ; CHECK-NEXT:    push {r4, r5, r6, r7, lr}
181 ; CHECK-NEXT:    vld1.64 {d18, d19}, [r1]
182 ; CHECK-NEXT:    movs r5, #0
183 ; CHECK-NEXT:    movs r6, #0
184 ; CHECK-NEXT:    movs r3, #0
185 ; CHECK-NEXT:    vld1.64 {d20, d21}, [r0]
186 ; CHECK-NEXT:    vsub.i64 q8, q10, q9
187 ; CHECK-NEXT:    vmov.32 r12, d20[1]
188 ; CHECK-NEXT:    vmov.32 lr, d21[1]
189 ; CHECK-NEXT:    vmov.32 r1, d16[1]
190 ; CHECK-NEXT:    vmov.32 r2, d17[1]
191 ; CHECK-NEXT:    vmov.32 r4, d18[1]
192 ; CHECK-NEXT:    vmov.32 r7, d19[1]
193 ; CHECK-NEXT:    cmp.w r1, #-1
194 ; CHECK-NEXT:    mov.w r1, #0
195 ; CHECK-NEXT:    it gt
196 ; CHECK-NEXT:    movgt r1, #1
197 ; CHECK-NEXT:    cmp r1, #0
198 ; CHECK-NEXT:    it ne
199 ; CHECK-NEXT:    movne.w r1, #-1
200 ; CHECK-NEXT:    cmp.w r2, #-1
201 ; CHECK-NEXT:    mov.w r2, #0
202 ; CHECK-NEXT:    it gt
203 ; CHECK-NEXT:    movgt r2, #1
204 ; CHECK-NEXT:    cmp.w r12, #-1
205 ; CHECK-NEXT:    it gt
206 ; CHECK-NEXT:    movgt r5, #1
207 ; CHECK-NEXT:    cmp r5, #0
208 ; CHECK-NEXT:    it ne
209 ; CHECK-NEXT:    movne.w r5, #-1
210 ; CHECK-NEXT:    cmp.w lr, #-1
211 ; CHECK-NEXT:    it gt
212 ; CHECK-NEXT:    movgt r6, #1
213 ; CHECK-NEXT:    cmp.w r4, #-1
214 ; CHECK-NEXT:    mov.w r4, #0
215 ; CHECK-NEXT:    it gt
216 ; CHECK-NEXT:    movgt r4, #1
217 ; CHECK-NEXT:    cmp r4, #0
218 ; CHECK-NEXT:    it ne
219 ; CHECK-NEXT:    movne.w r4, #-1
220 ; CHECK-NEXT:    cmp.w r7, #-1
221 ; CHECK-NEXT:    it gt
222 ; CHECK-NEXT:    movgt r3, #1
223 ; CHECK-NEXT:    cmp r3, #0
224 ; CHECK-NEXT:    it ne
225 ; CHECK-NEXT:    movne.w r3, #-1
226 ; CHECK-NEXT:    vdup.32 d19, r3
227 ; CHECK-NEXT:    cmp r6, #0
228 ; CHECK-NEXT:    it ne
229 ; CHECK-NEXT:    movne.w r6, #-1
230 ; CHECK-NEXT:    vdup.32 d21, r6
231 ; CHECK-NEXT:    cmp r2, #0
232 ; CHECK-NEXT:    vdup.32 d18, r4
233 ; CHECK-NEXT:    it ne
234 ; CHECK-NEXT:    movne.w r2, #-1
235 ; CHECK-NEXT:    vdup.32 d23, r2
236 ; CHECK-NEXT:    vdup.32 d20, r5
237 ; CHECK-NEXT:    vdup.32 d22, r1
238 ; CHECK-NEXT:    vceq.i32 q9, q10, q9
239 ; CHECK-NEXT:    vst1.64 {d16, d17}, [r0]
240 ; CHECK-NEXT:    vceq.i32 q10, q10, q11
241 ; CHECK-NEXT:    vrev64.32 q11, q9
242 ; CHECK-NEXT:    vrev64.32 q12, q10
243 ; CHECK-NEXT:    vand q9, q9, q11
244 ; CHECK-NEXT:    vand q10, q10, q12
245 ; CHECK-NEXT:    vmvn q9, q9
246 ; CHECK-NEXT:    vbic q9, q9, q10
247 ; CHECK-NEXT:    vmovn.i64 d18, q9
248 ; CHECK-NEXT:    vmov r2, r1, d18
249 ; CHECK-NEXT:    mov r0, r2
250 ; CHECK-NEXT:    pop {r4, r5, r6, r7, pc}
251   %x = load <2 x i64>, <2 x i64>* %ptr, align 8
252   %y = load <2 x i64>, <2 x i64>* %ptr2, align 8
253   %s = call {<2 x i64>, <2 x i1>} @llvm.ssub.with.overflow.v2i64(<2 x i64> %x, <2 x i64> %y)
254   %m = extractvalue {<2 x i64>, <2 x i1>} %s, 0
255   %o = extractvalue {<2 x i64>, <2 x i1>} %s, 1
256   store <2 x i64> %m, <2 x i64>* %ptr
257   ret <2 x i1> %o