[CodeGenPrepare] Move extractelement close to store if they can be combined.
[oota-llvm.git] / test / CodeGen / ARM / vector-promotion.ll
1 ; RUN: opt -codegenprepare -mtriple=thumbv7-apple-ios %s -o - -mattr=+neon -S | FileCheck --check-prefix=IR-BOTH --check-prefix=IR-NORMAL %s
2 ; RUN: opt -codegenprepare -mtriple=thumbv7-apple-ios %s -o - -mattr=+neon -S -stress-cgp-store-extract | FileCheck --check-prefix=IR-BOTH --check-prefix=IR-STRESS %s
3 ; RUN: llc -mtriple=thumbv7-apple-ios %s -o - -mattr=+neon | FileCheck --check-prefix=ASM %s
4
5 ; IR-BOTH-LABEL: @simpleOneInstructionPromotion
6 ; IR-BOTH: [[LOAD:%[a-zA-Z_0-9-]+]] = load <2 x i32>* %addr1
7 ; IR-BOTH-NEXT: [[VECTOR_OR:%[a-zA-Z_0-9-]+]] = or <2 x i32> [[LOAD]], <i32 undef, i32 1>
8 ; IR-BOTH-NEXT: [[EXTRACT:%[a-zA-Z_0-9-]+]] = extractelement <2 x i32> [[VECTOR_OR]], i32 1
9 ; IR-BOTH-NEXT: store i32 [[EXTRACT]], i32* %dest
10 ; IR-BOTH-NEXT: ret
11 ;
12 ; Make sure we got rid of any expensive vmov.32 instructions.
13 ; ASM-LABEL: simpleOneInstructionPromotion:
14 ; ASM: vldr [[LOAD:d[0-9]+]], [r0]
15 ; ASM-NEXT: vorr.i32 [[LOAD]], #0x1
16 ; ASM-NEXT: vst1.32 {[[LOAD]][1]}, [r1:32]
17 ; ASM-NEXT: bx
18 define void @simpleOneInstructionPromotion(<2 x i32>* %addr1, i32* %dest) {
19   %in1 = load <2 x i32>* %addr1, align 8
20   %extract = extractelement <2 x i32> %in1, i32 1
21   %out = or i32 %extract, 1
22   store i32 %out, i32* %dest, align 4
23   ret void
24 }
25
26 ; IR-BOTH-LABEL: @unsupportedInstructionForPromotion
27 ; IR-BOTH: [[LOAD:%[a-zA-Z_0-9-]+]] = load <2 x i32>* %addr1
28 ; IR-BOTH-NEXT: [[EXTRACT:%[a-zA-Z_0-9-]+]] = extractelement <2 x i32> [[LOAD]], i32 0
29 ; IR-BOTH-NEXT: [[CMP:%[a-zA-Z_0-9-]+]] = icmp eq i32 [[EXTRACT]], %in2
30 ; IR-BOTH-NEXT: store i1 [[CMP]], i1* %dest
31 ; IR-BOTH-NEXT: ret
32 ;
33 ; ASM-LABEL: unsupportedInstructionForPromotion:
34 ; ASM: vldr [[LOAD:d[0-9]+]], [r0]
35 ; ASM: vmov.32 {{r[0-9]+}}, [[LOAD]]
36 ; ASM: bx
37 define void @unsupportedInstructionForPromotion(<2 x i32>* %addr1, i32 %in2, i1* %dest) {
38   %in1 = load <2 x i32>* %addr1, align 8
39   %extract = extractelement <2 x i32> %in1, i32 0
40   %out = icmp eq i32 %extract, %in2
41   store i1 %out, i1* %dest, align 4
42   ret void
43 }
44
45
46 ; IR-BOTH-LABEL: @unsupportedChainInDifferentBBs
47 ; IR-BOTH: [[LOAD:%[a-zA-Z_0-9-]+]] = load <2 x i32>* %addr1
48 ; IR-BOTH-NEXT: [[EXTRACT:%[a-zA-Z_0-9-]+]] = extractelement <2 x i32> [[LOAD]], i32 0
49 ; IR-BOTH-NEXT: br i1 %bool, label %bb2, label %end
50 ; BB2
51 ; IR-BOTH: [[OR:%[a-zA-Z_0-9-]+]] = or i32 [[EXTRACT]], 1
52 ; IR-BOTH-NEXT: store i32 [[OR]], i32* %dest, align 4
53 ; IR-BOTH: ret
54 ;
55 ; ASM-LABEL: unsupportedChainInDifferentBBs:
56 ; ASM: vldrne [[LOAD:d[0-9]+]], [r0]
57 ; ASM: vmovne.32 {{r[0-9]+}}, [[LOAD]]
58 ; ASM: bx
59 define void @unsupportedChainInDifferentBBs(<2 x i32>* %addr1, i32* %dest, i1 %bool) {
60 bb1:
61   %in1 = load <2 x i32>* %addr1, align 8
62   %extract = extractelement <2 x i32> %in1, i32 0
63   br i1 %bool, label %bb2, label %end
64 bb2: 
65   %out = or i32 %extract, 1
66   store i32 %out, i32* %dest, align 4
67   br label %end
68 end:
69   ret void
70 }
71
72 ; IR-LABEL: @chainOfInstructionsToPromote
73 ; IR-BOTH: [[LOAD:%[a-zA-Z_0-9-]+]] = load <2 x i32>* %addr1
74 ; IR-BOTH-NEXT: [[VECTOR_OR1:%[a-zA-Z_0-9-]+]] = or <2 x i32> [[LOAD]], <i32 1, i32 undef>
75 ; IR-BOTH-NEXT: [[VECTOR_OR2:%[a-zA-Z_0-9-]+]] = or <2 x i32> [[VECTOR_OR1]], <i32 1, i32 undef>
76 ; IR-BOTH-NEXT: [[VECTOR_OR3:%[a-zA-Z_0-9-]+]] = or <2 x i32> [[VECTOR_OR2]], <i32 1, i32 undef>
77 ; IR-BOTH-NEXT: [[VECTOR_OR4:%[a-zA-Z_0-9-]+]] = or <2 x i32> [[VECTOR_OR3]], <i32 1, i32 undef>
78 ; IR-BOTH-NEXT: [[VECTOR_OR5:%[a-zA-Z_0-9-]+]] = or <2 x i32> [[VECTOR_OR4]], <i32 1, i32 undef>
79 ; IR-BOTH-NEXT: [[VECTOR_OR6:%[a-zA-Z_0-9-]+]] = or <2 x i32> [[VECTOR_OR5]], <i32 1, i32 undef>
80 ; IR-BOTH-NEXT: [[VECTOR_OR7:%[a-zA-Z_0-9-]+]] = or <2 x i32> [[VECTOR_OR6]], <i32 1, i32 undef>
81 ; IR-BOTH-NEXT: [[EXTRACT:%[a-zA-Z_0-9-]+]] = extractelement <2 x i32> [[VECTOR_OR7]], i32 0
82 ; IR-BOTH-NEXT: store i32 [[EXTRACT]], i32* %dest
83 ; IR-BOTH-NEXT: ret
84 ;
85 ; ASM-LABEL: chainOfInstructionsToPromote:
86 ; ASM: vldr [[LOAD:d[0-9]+]], [r0]
87 ; ASM-NOT: vmov.32 {{r[0-9]+}}, [[LOAD]]
88 ; ASM: bx
89 define void @chainOfInstructionsToPromote(<2 x i32>* %addr1, i32* %dest) {
90   %in1 = load <2 x i32>* %addr1, align 8
91   %extract = extractelement <2 x i32> %in1, i32 0
92   %out1 = or i32 %extract, 1
93   %out2 = or i32 %out1, 1
94   %out3 = or i32 %out2, 1
95   %out4 = or i32 %out3, 1
96   %out5 = or i32 %out4, 1
97   %out6 = or i32 %out5, 1
98   %out7 = or i32 %out6, 1
99   store i32 %out7, i32* %dest, align 4
100   ret void
101 }
102
103 ; IR-BOTH-LABEL: @unsupportedMultiUses
104 ; IR-BOTH: [[LOAD:%[a-zA-Z_0-9-]+]] = load <2 x i32>* %addr1
105 ; IR-BOTH-NEXT: [[EXTRACT:%[a-zA-Z_0-9-]+]] = extractelement <2 x i32> [[LOAD]], i32 1
106 ; IR-BOTH-NEXT: [[OR:%[a-zA-Z_0-9-]+]] = or i32 [[EXTRACT]], 1
107 ; IR-BOTH-NEXT: store i32 [[OR]], i32* %dest
108 ; IR-BOTH-NEXT: ret i32 [[OR]]
109 ;
110 ; ASM-LABEL: unsupportedMultiUses:
111 ; ASM: vldr [[LOAD:d[0-9]+]], [r0]
112 ; ASM: vmov.32 {{r[0-9]+}}, [[LOAD]]
113 ; ASM: bx
114 define i32 @unsupportedMultiUses(<2 x i32>* %addr1, i32* %dest) {
115   %in1 = load <2 x i32>* %addr1, align 8
116   %extract = extractelement <2 x i32> %in1, i32 1
117   %out = or i32 %extract, 1
118   store i32 %out, i32* %dest, align 4
119   ret i32 %out
120 }
121
122 ; Check that we promote we a splat constant when this is a division.
123 ; The NORMAL mode does not promote anything as divisions are not legal.
124 ; IR-BOTH-LABEL: @udivCase
125 ; IR-BOTH: [[LOAD:%[a-zA-Z_0-9-]+]] = load <2 x i32>* %addr1
126 ; Scalar version:
127 ; IR-NORMAL-NEXT: [[EXTRACT:%[a-zA-Z_0-9-]+]] = extractelement <2 x i32> [[LOAD]], i32 1
128 ; IR-NORMAL-NEXT: [[RES:%[a-zA-Z_0-9-]+]] = udiv i32 [[EXTRACT]], 7
129 ; Vector version:
130 ; IR-STRESS-NEXT: [[DIV:%[a-zA-Z_0-9-]+]] = udiv <2 x i32> [[LOAD]], <i32 7, i32 7>
131 ; IR-STRESS-NEXT: [[RES:%[a-zA-Z_0-9-]+]] = extractelement <2 x i32> [[DIV]], i32 1
132 ;
133 ; IR-BOTH-NEXT: store i32 [[RES]], i32* %dest
134 ; IR-BOTH-NEXT: ret
135 define void @udivCase(<2 x i32>* %addr1, i32* %dest) {
136   %in1 = load <2 x i32>* %addr1, align 8
137   %extract = extractelement <2 x i32> %in1, i32 1
138   %out = udiv i32 %extract, 7
139   store i32 %out, i32* %dest, align 4
140   ret void
141 }
142
143 ; IR-BOTH-LABEL: @uremCase
144 ; IR-BOTH: [[LOAD:%[a-zA-Z_0-9-]+]] = load <2 x i32>* %addr1
145 ; Scalar version:
146 ; IR-NORMAL-NEXT: [[EXTRACT:%[a-zA-Z_0-9-]+]] = extractelement <2 x i32> [[LOAD]], i32 1
147 ; IR-NORMAL-NEXT: [[RES:%[a-zA-Z_0-9-]+]] = urem i32 [[EXTRACT]], 7
148 ; Vector version:
149 ; IR-STRESS-NEXT: [[DIV:%[a-zA-Z_0-9-]+]] = urem <2 x i32> [[LOAD]], <i32 7, i32 7>
150 ; IR-STRESS-NEXT: [[RES:%[a-zA-Z_0-9-]+]] = extractelement <2 x i32> [[DIV]], i32 1
151 ;
152 ; IR-BOTH-NEXT: store i32 [[RES]], i32* %dest
153 ; IR-BOTH-NEXT: ret 
154 define void @uremCase(<2 x i32>* %addr1, i32* %dest) {
155   %in1 = load <2 x i32>* %addr1, align 8
156   %extract = extractelement <2 x i32> %in1, i32 1
157   %out = urem i32 %extract, 7
158   store i32 %out, i32* %dest, align 4
159   ret void
160 }
161
162 ; IR-BOTH-LABEL: @sdivCase
163 ; IR-BOTH: [[LOAD:%[a-zA-Z_0-9-]+]] = load <2 x i32>* %addr1
164 ; Scalar version:
165 ; IR-NORMAL-NEXT: [[EXTRACT:%[a-zA-Z_0-9-]+]] = extractelement <2 x i32> [[LOAD]], i32 1
166 ; IR-NORMAL-NEXT: [[RES:%[a-zA-Z_0-9-]+]] = sdiv i32 [[EXTRACT]], 7
167 ; Vector version:
168 ; IR-STRESS-NEXT: [[DIV:%[a-zA-Z_0-9-]+]] = sdiv <2 x i32> [[LOAD]], <i32 7, i32 7>
169 ; IR-STRESS-NEXT: [[RES:%[a-zA-Z_0-9-]+]] = extractelement <2 x i32> [[DIV]], i32 1
170 ;
171 ; IR-BOTH-NEXT: store i32 [[RES]], i32* %dest
172 ; IR-BOTH-NEXT: ret 
173 define void @sdivCase(<2 x i32>* %addr1, i32* %dest) {
174   %in1 = load <2 x i32>* %addr1, align 8
175   %extract = extractelement <2 x i32> %in1, i32 1
176   %out = sdiv i32 %extract, 7
177   store i32 %out, i32* %dest, align 4
178   ret void
179 }
180
181 ; IR-BOTH-LABEL: @sremCase
182 ; IR-BOTH: [[LOAD:%[a-zA-Z_0-9-]+]] = load <2 x i32>* %addr1
183 ; Scalar version:
184 ; IR-NORMAL-NEXT: [[EXTRACT:%[a-zA-Z_0-9-]+]] = extractelement <2 x i32> [[LOAD]], i32 1
185 ; IR-NORMAL-NEXT: [[RES:%[a-zA-Z_0-9-]+]] = srem i32 [[EXTRACT]], 7
186 ; Vector version:
187 ; IR-STRESS-NEXT: [[DIV:%[a-zA-Z_0-9-]+]] = srem <2 x i32> [[LOAD]], <i32 7, i32 7>
188 ; IR-STRESS-NEXT: [[RES:%[a-zA-Z_0-9-]+]] = extractelement <2 x i32> [[DIV]], i32 1
189 ;
190 ; IR-BOTH-NEXT: store i32 [[RES]], i32* %dest
191 ; IR-BOTH-NEXT: ret 
192 define void @sremCase(<2 x i32>* %addr1, i32* %dest) {
193   %in1 = load <2 x i32>* %addr1, align 8
194   %extract = extractelement <2 x i32> %in1, i32 1
195   %out = srem i32 %extract, 7
196   store i32 %out, i32* %dest, align 4
197   ret void
198 }
199
200 ; IR-BOTH-LABEL: @fdivCase
201 ; IR-BOTH: [[LOAD:%[a-zA-Z_0-9-]+]] = load <2 x float>* %addr1
202 ; Scalar version:  
203 ; IR-NORMAL-NEXT: [[EXTRACT:%[a-zA-Z_0-9-]+]] = extractelement <2 x float> [[LOAD]], i32 1
204 ; IR-NORMAL-NEXT: [[RES:%[a-zA-Z_0-9-]+]] = fdiv float [[EXTRACT]], 7.0
205 ; Vector version:
206 ; IR-STRESS-NEXT: [[DIV:%[a-zA-Z_0-9-]+]] = fdiv <2 x float> [[LOAD]], <float 7.000000e+00, float 7.000000e+00>
207 ; IR-STRESS-NEXT: [[RES:%[a-zA-Z_0-9-]+]] = extractelement <2 x float> [[DIV]], i32 1
208 ;
209 ; IR-BOTH-NEXT: store float [[RES]], float* %dest
210 ; IR-BOTH-NEXT: ret
211 define void @fdivCase(<2 x float>* %addr1, float* %dest) {
212   %in1 = load <2 x float>* %addr1, align 8   
213   %extract = extractelement <2 x float> %in1, i32 1
214   %out = fdiv float %extract, 7.0
215   store float %out, float* %dest, align 4
216   ret void
217 }
218
219 ; IR-BOTH-LABEL: @fremCase
220 ; IR-BOTH: [[LOAD:%[a-zA-Z_0-9-]+]] = load <2 x float>* %addr1
221 ; Scalar version:  
222 ; IR-NORMAL-NEXT: [[EXTRACT:%[a-zA-Z_0-9-]+]] = extractelement <2 x float> [[LOAD]], i32 1
223 ; IR-NORMAL-NEXT: [[RES:%[a-zA-Z_0-9-]+]] = frem float [[EXTRACT]], 7.0
224 ; Vector version:
225 ; IR-STRESS-NEXT: [[DIV:%[a-zA-Z_0-9-]+]] = frem <2 x float> [[LOAD]], <float 7.000000e+00, float 7.000000e+00>
226 ; IR-STRESS-NEXT: [[RES:%[a-zA-Z_0-9-]+]] = extractelement <2 x float> [[DIV]], i32 1
227 ;
228 ; IR-BOTH-NEXT: store float [[RES]], float* %dest
229 ; IR-BOTH-NEXT: ret
230 define void @fremCase(<2 x float>* %addr1, float* %dest) {
231   %in1 = load <2 x float>* %addr1, align 8   
232   %extract = extractelement <2 x float> %in1, i32 1
233   %out = frem float %extract, 7.0
234   store float %out, float* %dest, align 4
235   ret void
236 }
237
238 ; Check that we do not promote when we may introduce undefined behavior
239 ; like division by zero.
240 ; IR-BOTH-LABEL: @undefDivCase
241 ; IR-BOTH: [[LOAD:%[a-zA-Z_0-9-]+]] = load <2 x i32>* %addr1
242 ; IR-BOTH-NEXT: [[EXTRACT:%[a-zA-Z_0-9-]+]] = extractelement <2 x i32> [[LOAD]], i32 1
243 ; IR-BOTH-NEXT: [[RES:%[a-zA-Z_0-9-]+]] = udiv i32 7, [[EXTRACT]]
244 ; IR-BOTH-NEXT: store i32 [[RES]], i32* %dest
245 ; IR-BOTH-NEXT: ret
246 define void @undefDivCase(<2 x i32>* %addr1, i32* %dest) {
247   %in1 = load <2 x i32>* %addr1, align 8
248   %extract = extractelement <2 x i32> %in1, i32 1
249   %out = udiv i32 7, %extract
250   store i32 %out, i32* %dest, align 4
251   ret void
252 }
253
254
255 ; Check that we do not promote when we may introduce undefined behavior
256 ; like division by zero.
257 ; IR-BOTH-LABEL: @undefRemCase
258 ; IR-BOTH: [[LOAD:%[a-zA-Z_0-9-]+]] = load <2 x i32>* %addr1
259 ; IR-BOTH-NEXT: [[EXTRACT:%[a-zA-Z_0-9-]+]] = extractelement <2 x i32> [[LOAD]], i32 1
260 ; IR-BOTH-NEXT: [[RES:%[a-zA-Z_0-9-]+]] = srem i32 7, [[EXTRACT]]
261 ; IR-BOTH-NEXT: store i32 [[RES]], i32* %dest
262 ; IR-BOTH-NEXT: ret
263 define void @undefRemCase(<2 x i32>* %addr1, i32* %dest) {
264   %in1 = load <2 x i32>* %addr1, align 8
265   %extract = extractelement <2 x i32> %in1, i32 1
266   %out = srem i32 7, %extract
267   store i32 %out, i32* %dest, align 4
268   ret void
269 }
270
271 ; Check that we use an undef mask for undefined behavior if the fast-math
272 ; flag is set.
273 ; IR-BOTH-LABEL: @undefConstantFRemCaseWithFastMath
274 ; IR-BOTH: [[LOAD:%[a-zA-Z_0-9-]+]] = load <2 x float>* %addr1
275 ; Scalar version:  
276 ; IR-NORMAL-NEXT: [[EXTRACT:%[a-zA-Z_0-9-]+]] = extractelement <2 x float> [[LOAD]], i32 1
277 ; IR-NORMAL-NEXT: [[RES:%[a-zA-Z_0-9-]+]] = frem nnan float [[EXTRACT]], 7.0
278 ; Vector version:
279 ; IR-STRESS-NEXT: [[DIV:%[a-zA-Z_0-9-]+]] = frem nnan <2 x float> [[LOAD]], <float undef, float 7.000000e+00>
280 ; IR-STRESS-NEXT: [[RES:%[a-zA-Z_0-9-]+]] = extractelement <2 x float> [[DIV]], i32 1
281 ;
282 ; IR-BOTH-NEXT: store float [[RES]], float* %dest
283 ; IR-BOTH-NEXT: ret
284 define void @undefConstantFRemCaseWithFastMath(<2 x float>* %addr1, float* %dest) {
285   %in1 = load <2 x float>* %addr1, align 8   
286   %extract = extractelement <2 x float> %in1, i32 1
287   %out = frem nnan float %extract, 7.0
288   store float %out, float* %dest, align 4
289   ret void
290 }
291
292 ; Check that we use an undef mask for undefined behavior if the fast-math
293 ; flag is set.
294 ; IR-BOTH-LABEL: @undefVectorFRemCaseWithFastMath
295 ; IR-BOTH: [[LOAD:%[a-zA-Z_0-9-]+]] = load <2 x float>* %addr1
296 ; Scalar version:  
297 ; IR-NORMAL-NEXT: [[EXTRACT:%[a-zA-Z_0-9-]+]] = extractelement <2 x float> [[LOAD]], i32 1
298 ; IR-NORMAL-NEXT: [[RES:%[a-zA-Z_0-9-]+]] = frem nnan float 7.000000e+00, [[EXTRACT]]
299 ; Vector version:
300 ; IR-STRESS-NEXT: [[DIV:%[a-zA-Z_0-9-]+]] = frem nnan <2 x float> <float undef, float 7.000000e+00>, [[LOAD]]
301 ; IR-STRESS-NEXT: [[RES:%[a-zA-Z_0-9-]+]] = extractelement <2 x float> [[DIV]], i32 1
302 ;
303 ; IR-BOTH-NEXT: store float [[RES]], float* %dest
304 ; IR-BOTH-NEXT: ret
305 define void @undefVectorFRemCaseWithFastMath(<2 x float>* %addr1, float* %dest) {
306   %in1 = load <2 x float>* %addr1, align 8   
307   %extract = extractelement <2 x float> %in1, i32 1
308   %out = frem nnan float 7.0, %extract
309   store float %out, float* %dest, align 4
310   ret void
311 }
312
313 ; Check that we are able to promote floating point value.
314 ; This requires the STRESS mode, as floating point value are
315 ; not promote on armv7.
316 ; IR-BOTH-LABEL: @simpleOneInstructionPromotionFloat
317 ; IR-BOTH: [[LOAD:%[a-zA-Z_0-9-]+]] = load <2 x float>* %addr1
318 ; Scalar version: 
319 ; IR-NORMAL-NEXT: [[EXTRACT:%[a-zA-Z_0-9-]+]] = extractelement <2 x float> [[LOAD]], i32 1
320 ; IR-NORMAL-NEXT: [[RES:%[a-zA-Z_0-9-]+]] = fadd float [[EXTRACT]], 1.0
321 ; Vector version:
322 ; IR-STRESS-NEXT: [[DIV:%[a-zA-Z_0-9-]+]] = fadd <2 x float> [[LOAD]], <float undef, float 1.000000e+00>
323 ; IR-STRESS-NEXT: [[RES:%[a-zA-Z_0-9-]+]] = extractelement <2 x float> [[DIV]], i32 1
324 ;
325 ; IR-BOTH-NEXT: store float [[RES]], float* %dest
326 ; IR-BOTH-NEXT: ret
327 define void @simpleOneInstructionPromotionFloat(<2 x float>* %addr1, float* %dest) {
328   %in1 = load <2 x float>* %addr1, align 8
329   %extract = extractelement <2 x float> %in1, i32 1
330   %out = fadd float %extract, 1.0
331   store float %out, float* %dest, align 4
332   ret void
333 }
334
335 ; Check that we correctly use a splat constant when we cannot
336 ; determine at compile time the index of the extract.
337 ; This requires the STRESS modes, as variable index are expensive
338 ; to lower.
339 ; IR-BOTH-LABEL: @simpleOneInstructionPromotionVariableIdx
340 ; IR-BOTH: [[LOAD:%[a-zA-Z_0-9-]+]] = load <2 x i32>* %addr1
341 ; Scalar version:
342 ; IR-NORMAL-NEXT: [[EXTRACT:%[a-zA-Z_0-9-]+]] = extractelement <2 x i32> [[LOAD]], i32 %idx
343 ; IR-NORMAL-NEXT: [[RES:%[a-zA-Z_0-9-]+]] = or i32 [[EXTRACT]], 1
344 ; Vector version:
345 ; IR-STRESS-NEXT: [[OR:%[a-zA-Z_0-9-]+]] = or <2 x i32> [[LOAD]], <i32 1, i32 1>
346 ; IR-STRESS-NEXT: [[RES:%[a-zA-Z_0-9-]+]] = extractelement <2 x i32> [[OR]], i32 %idx
347 ;
348 ; IR-BOTH-NEXT: store i32 [[RES]], i32* %dest
349 ; IR-BOTH-NEXT: ret
350 define void @simpleOneInstructionPromotionVariableIdx(<2 x i32>* %addr1, i32* %dest, i32 %idx) {
351   %in1 = load <2 x i32>* %addr1, align 8
352   %extract = extractelement <2 x i32> %in1, i32 %idx
353   %out = or i32 %extract, 1
354   store i32 %out, i32* %dest, align 4
355   ret void
356 }
357
358 ; Check a vector with more than 2 elements.
359 ; This requires the STRESS mode because currently 'or v8i8' is not marked
360 ; as legal or custom, althought the actual assembly is better if we were
361 ; promoting it.
362 ; IR-BOTH-LABEL: @simpleOneInstructionPromotion8x8
363 ; IR-BOTH: [[LOAD:%[a-zA-Z_0-9-]+]] = load <8 x i8>* %addr1
364 ; Scalar version:  
365 ; IR-NORMAL-NEXT: [[EXTRACT:%[a-zA-Z_0-9-]+]] = extractelement <8 x i8> [[LOAD]], i32 1
366 ; IR-NORMAL-NEXT: [[RES:%[a-zA-Z_0-9-]+]] = or i8 [[EXTRACT]], 1
367 ; Vector version:  
368 ; IR-STRESS-NEXT: [[OR:%[a-zA-Z_0-9-]+]] = or <8 x i8> [[LOAD]], <i8 undef, i8 1, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef>
369 ; IR-STRESS-NEXT: [[RES:%[a-zA-Z_0-9-]+]] = extractelement <8 x i8> [[OR]], i32 1
370 ;
371 ; IR-BOTH-NEXT: store i8 [[RES]], i8* %dest
372 ; IR-BOTH-NEXT: ret
373 define void @simpleOneInstructionPromotion8x8(<8 x i8>* %addr1, i8* %dest) {
374   %in1 = load <8 x i8>* %addr1, align 8
375   %extract = extractelement <8 x i8> %in1, i32 1
376   %out = or i8 %extract, 1
377   store i8 %out, i8* %dest, align 4
378   ret void
379 }
380
381 ; Check that we optimized the sequence correctly when it can be
382 ; lowered on a Q register.
383 ; IR-BOTH-LABEL: @simpleOneInstructionPromotion
384 ; IR-BOTH: [[LOAD:%[a-zA-Z_0-9-]+]] = load <4 x i32>* %addr1
385 ; IR-BOTH-NEXT: [[VECTOR_OR:%[a-zA-Z_0-9-]+]] = or <4 x i32> [[LOAD]], <i32 undef, i32 1, i32 undef, i32 undef>
386 ; IR-BOTH-NEXT: [[EXTRACT:%[a-zA-Z_0-9-]+]] = extractelement <4 x i32> [[VECTOR_OR]], i32 1
387 ; IR-BOTH-NEXT: store i32 [[EXTRACT]], i32* %dest
388 ; IR-BOTH-NEXT: ret
389 ;
390 ; Make sure we got rid of any expensive vmov.32 instructions.
391 ; ASM-LABEL: simpleOneInstructionPromotion4x32:
392 ; ASM: vld1.64 {[[LOAD:d[0-9]+]], d{{[0-9]+}}}, [r0]
393 ; The Q register used here must be [[LOAD]] / 2, but we cannot express that.
394 ; ASM-NEXT: vorr.i32 q{{[[0-9]+}}, #0x1
395 ; ASM-NEXT: vst1.32 {[[LOAD]][1]}, [r1]
396 ; ASM-NEXT: bx
397 define void @simpleOneInstructionPromotion4x32(<4 x i32>* %addr1, i32* %dest) {
398   %in1 = load <4 x i32>* %addr1, align 8
399   %extract = extractelement <4 x i32> %in1, i32 1
400   %out = or i32 %extract, 1
401   store i32 %out, i32* %dest, align 1
402   ret void
403 }