xref: /aosp_15_r20/external/llvm/test/CodeGen/ARM/vector-DAGCombine.ll (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker; RUN: llc < %s -mtriple=armv7-apple-darwin | FileCheck %s
2*9880d681SAndroid Build Coastguard Worker
3*9880d681SAndroid Build Coastguard Worker; PR7158
4*9880d681SAndroid Build Coastguard Workerdefine i32 @test_pr7158() nounwind {
5*9880d681SAndroid Build Coastguard Workerbb.nph55.bb.nph55.split_crit_edge:
6*9880d681SAndroid Build Coastguard Worker  br label %bb3
7*9880d681SAndroid Build Coastguard Worker
8*9880d681SAndroid Build Coastguard Workerbb3:                                              ; preds = %bb3, %bb.nph55.bb.nph55.split_crit_edge
9*9880d681SAndroid Build Coastguard Worker  br i1 undef, label %bb.i19, label %bb3
10*9880d681SAndroid Build Coastguard Worker
11*9880d681SAndroid Build Coastguard Workerbb.i19:                                           ; preds = %bb.i19, %bb3
12*9880d681SAndroid Build Coastguard Worker  %0 = insertelement <4 x float> undef, float undef, i32 3 ; <<4 x float>> [#uses=3]
13*9880d681SAndroid Build Coastguard Worker  %1 = fmul <4 x float> %0, %0                    ; <<4 x float>> [#uses=1]
14*9880d681SAndroid Build Coastguard Worker  %2 = bitcast <4 x float> %1 to <2 x double>     ; <<2 x double>> [#uses=0]
15*9880d681SAndroid Build Coastguard Worker  %3 = fmul <4 x float> %0, undef                 ; <<4 x float>> [#uses=0]
16*9880d681SAndroid Build Coastguard Worker  br label %bb.i19
17*9880d681SAndroid Build Coastguard Worker}
18*9880d681SAndroid Build Coastguard Worker
19*9880d681SAndroid Build Coastguard Worker; Check that the DAG combiner does not arbitrarily modify BUILD_VECTORs
20*9880d681SAndroid Build Coastguard Worker; after legalization.
21*9880d681SAndroid Build Coastguard Workerdefine void @test_illegal_build_vector() nounwind {
22*9880d681SAndroid Build Coastguard Workerentry:
23*9880d681SAndroid Build Coastguard Worker  store <2 x i64> undef, <2 x i64>* undef, align 16
24*9880d681SAndroid Build Coastguard Worker  %0 = load <16 x i8>, <16 x i8>* undef, align 16            ; <<16 x i8>> [#uses=1]
25*9880d681SAndroid Build Coastguard Worker  %1 = or <16 x i8> zeroinitializer, %0           ; <<16 x i8>> [#uses=1]
26*9880d681SAndroid Build Coastguard Worker  store <16 x i8> %1, <16 x i8>* undef, align 16
27*9880d681SAndroid Build Coastguard Worker  ret void
28*9880d681SAndroid Build Coastguard Worker}
29*9880d681SAndroid Build Coastguard Worker
30*9880d681SAndroid Build Coastguard Worker; PR22678
31*9880d681SAndroid Build Coastguard Worker; Check CONCAT_VECTORS DAG combiner pass doesn't introduce illegal types.
32*9880d681SAndroid Build Coastguard Workerdefine void @test_pr22678() {
33*9880d681SAndroid Build Coastguard Worker  %1 = fptoui <16 x float> undef to <16 x i8>
34*9880d681SAndroid Build Coastguard Worker  store <16 x i8> %1, <16 x i8>* undef
35*9880d681SAndroid Build Coastguard Worker  ret void
36*9880d681SAndroid Build Coastguard Worker}
37*9880d681SAndroid Build Coastguard Worker
38*9880d681SAndroid Build Coastguard Worker; Radar 8407927: Make sure that VMOVRRD gets optimized away when the result is
39*9880d681SAndroid Build Coastguard Worker; converted back to be used as a vector type.
40*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: test_vmovrrd_combine:
41*9880d681SAndroid Build Coastguard Workerdefine <4 x i32> @test_vmovrrd_combine() nounwind {
42*9880d681SAndroid Build Coastguard Workerentry:
43*9880d681SAndroid Build Coastguard Worker  br i1 undef, label %bb1, label %bb2
44*9880d681SAndroid Build Coastguard Worker
45*9880d681SAndroid Build Coastguard Workerbb1:
46*9880d681SAndroid Build Coastguard Worker  %0 = bitcast <2 x i64> zeroinitializer to <2 x double>
47*9880d681SAndroid Build Coastguard Worker  %1 = extractelement <2 x double> %0, i32 0
48*9880d681SAndroid Build Coastguard Worker  %2 = bitcast double %1 to i64
49*9880d681SAndroid Build Coastguard Worker  %3 = insertelement <1 x i64> undef, i64 %2, i32 0
50*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: vmov s
51*9880d681SAndroid Build Coastguard Worker; CHECK: vext.8
52*9880d681SAndroid Build Coastguard Worker  %4 = shufflevector <1 x i64> %3, <1 x i64> undef, <2 x i32> <i32 0, i32 1>
53*9880d681SAndroid Build Coastguard Worker  %tmp2006.3 = bitcast <2 x i64> %4 to <16 x i8>
54*9880d681SAndroid Build Coastguard Worker  %5 = shufflevector <16 x i8> %tmp2006.3, <16 x i8> undef, <16 x i32> <i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19>
55*9880d681SAndroid Build Coastguard Worker  %tmp2004.3 = bitcast <16 x i8> %5 to <4 x i32>
56*9880d681SAndroid Build Coastguard Worker  br i1 undef, label %bb2, label %bb1
57*9880d681SAndroid Build Coastguard Worker
58*9880d681SAndroid Build Coastguard Workerbb2:
59*9880d681SAndroid Build Coastguard Worker  %result = phi <4 x i32> [ undef, %entry ], [ %tmp2004.3, %bb1 ]
60*9880d681SAndroid Build Coastguard Worker  ret <4 x i32> %result
61*9880d681SAndroid Build Coastguard Worker}
62*9880d681SAndroid Build Coastguard Worker
63*9880d681SAndroid Build Coastguard Worker; Test trying to do a ShiftCombine on illegal types.
64*9880d681SAndroid Build Coastguard Worker; The vector should be split first.
65*9880d681SAndroid Build Coastguard Workerdefine void @lshrIllegalType(<8 x i32>* %A) nounwind {
66*9880d681SAndroid Build Coastguard Worker       %tmp1 = load <8 x i32>, <8 x i32>* %A
67*9880d681SAndroid Build Coastguard Worker       %tmp2 = lshr <8 x i32> %tmp1, < i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3>
68*9880d681SAndroid Build Coastguard Worker       store <8 x i32> %tmp2, <8 x i32>* %A
69*9880d681SAndroid Build Coastguard Worker       ret void
70*9880d681SAndroid Build Coastguard Worker}
71*9880d681SAndroid Build Coastguard Worker
72*9880d681SAndroid Build Coastguard Worker; Test folding a binary vector operation with constant BUILD_VECTOR
73*9880d681SAndroid Build Coastguard Worker; operands with i16 elements.
74*9880d681SAndroid Build Coastguard Workerdefine void @test_i16_constant_fold() nounwind optsize {
75*9880d681SAndroid Build Coastguard Workerentry:
76*9880d681SAndroid Build Coastguard Worker  %0 = sext <4 x i1> zeroinitializer to <4 x i16>
77*9880d681SAndroid Build Coastguard Worker  %1 = add <4 x i16> %0, zeroinitializer
78*9880d681SAndroid Build Coastguard Worker  %2 = shufflevector <4 x i16> %1, <4 x i16> undef, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
79*9880d681SAndroid Build Coastguard Worker  %3 = add <8 x i16> %2, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1>
80*9880d681SAndroid Build Coastguard Worker  %4 = trunc <8 x i16> %3 to <8 x i8>
81*9880d681SAndroid Build Coastguard Worker  tail call void @llvm.arm.neon.vst1.p0i8.v8i8(i8* undef, <8 x i8> %4, i32 1)
82*9880d681SAndroid Build Coastguard Worker  unreachable
83*9880d681SAndroid Build Coastguard Worker}
84*9880d681SAndroid Build Coastguard Worker
85*9880d681SAndroid Build Coastguard Workerdeclare void @llvm.arm.neon.vst1.p0i8.v8i8(i8*, <8 x i8>, i32) nounwind
86*9880d681SAndroid Build Coastguard Worker
87*9880d681SAndroid Build Coastguard Worker; Test that loads and stores of i64 vector elements are handled as f64 values
88*9880d681SAndroid Build Coastguard Worker; so they are not split up into i32 values.  Radar 8755338.
89*9880d681SAndroid Build Coastguard Workerdefine void @i64_buildvector(i64* %ptr, <2 x i64>* %vp) nounwind {
90*9880d681SAndroid Build Coastguard Worker; CHECK: i64_buildvector
91*9880d681SAndroid Build Coastguard Worker; CHECK: vldr
92*9880d681SAndroid Build Coastguard Worker  %t0 = load i64, i64* %ptr, align 4
93*9880d681SAndroid Build Coastguard Worker  %t1 = insertelement <2 x i64> undef, i64 %t0, i32 0
94*9880d681SAndroid Build Coastguard Worker  store <2 x i64> %t1, <2 x i64>* %vp
95*9880d681SAndroid Build Coastguard Worker  ret void
96*9880d681SAndroid Build Coastguard Worker}
97*9880d681SAndroid Build Coastguard Worker
98*9880d681SAndroid Build Coastguard Workerdefine void @i64_insertelement(i64* %ptr, <2 x i64>* %vp) nounwind {
99*9880d681SAndroid Build Coastguard Worker; CHECK: i64_insertelement
100*9880d681SAndroid Build Coastguard Worker; CHECK: vldr
101*9880d681SAndroid Build Coastguard Worker  %t0 = load i64, i64* %ptr, align 4
102*9880d681SAndroid Build Coastguard Worker  %vec = load <2 x i64>, <2 x i64>* %vp
103*9880d681SAndroid Build Coastguard Worker  %t1 = insertelement <2 x i64> %vec, i64 %t0, i32 0
104*9880d681SAndroid Build Coastguard Worker  store <2 x i64> %t1, <2 x i64>* %vp
105*9880d681SAndroid Build Coastguard Worker  ret void
106*9880d681SAndroid Build Coastguard Worker}
107*9880d681SAndroid Build Coastguard Worker
108*9880d681SAndroid Build Coastguard Workerdefine void @i64_extractelement(i64* %ptr, <2 x i64>* %vp) nounwind {
109*9880d681SAndroid Build Coastguard Worker; CHECK: i64_extractelement
110*9880d681SAndroid Build Coastguard Worker; CHECK: vstr
111*9880d681SAndroid Build Coastguard Worker  %vec = load <2 x i64>, <2 x i64>* %vp
112*9880d681SAndroid Build Coastguard Worker  %t1 = extractelement <2 x i64> %vec, i32 0
113*9880d681SAndroid Build Coastguard Worker  store i64 %t1, i64* %ptr
114*9880d681SAndroid Build Coastguard Worker  ret void
115*9880d681SAndroid Build Coastguard Worker}
116*9880d681SAndroid Build Coastguard Worker
117*9880d681SAndroid Build Coastguard Worker; Test trying to do a AND Combine on illegal types.
118*9880d681SAndroid Build Coastguard Workerdefine void @andVec(<3 x i8>* %A) nounwind {
119*9880d681SAndroid Build Coastguard Worker  %tmp = load <3 x i8>, <3 x i8>* %A, align 4
120*9880d681SAndroid Build Coastguard Worker  %and = and <3 x i8> %tmp, <i8 7, i8 7, i8 7>
121*9880d681SAndroid Build Coastguard Worker  store <3 x i8> %and, <3 x i8>* %A
122*9880d681SAndroid Build Coastguard Worker  ret void
123*9880d681SAndroid Build Coastguard Worker}
124*9880d681SAndroid Build Coastguard Worker
125*9880d681SAndroid Build Coastguard Worker
126*9880d681SAndroid Build Coastguard Worker; Test trying to do an OR Combine on illegal types.
127*9880d681SAndroid Build Coastguard Workerdefine void @orVec(<3 x i8>* %A) nounwind {
128*9880d681SAndroid Build Coastguard Worker  %tmp = load <3 x i8>, <3 x i8>* %A, align 4
129*9880d681SAndroid Build Coastguard Worker  %or = or <3 x i8> %tmp, <i8 7, i8 7, i8 7>
130*9880d681SAndroid Build Coastguard Worker  store <3 x i8> %or, <3 x i8>* %A
131*9880d681SAndroid Build Coastguard Worker  ret void
132*9880d681SAndroid Build Coastguard Worker}
133*9880d681SAndroid Build Coastguard Worker
134*9880d681SAndroid Build Coastguard Worker; The following test was hitting an assertion in the DAG combiner when
135*9880d681SAndroid Build Coastguard Worker; constant folding the multiply because the "sext undef" was translated to
136*9880d681SAndroid Build Coastguard Worker; a BUILD_VECTOR with i32 0 operands, which did not match the i16 operands
137*9880d681SAndroid Build Coastguard Worker; of the other BUILD_VECTOR.
138*9880d681SAndroid Build Coastguard Workerdefine i16 @foldBuildVectors() {
139*9880d681SAndroid Build Coastguard Worker  %1 = sext <8 x i8> undef to <8 x i16>
140*9880d681SAndroid Build Coastguard Worker  %2 = mul <8 x i16> %1, <i16 255, i16 255, i16 255, i16 255, i16 255, i16 255, i16 255, i16 255>
141*9880d681SAndroid Build Coastguard Worker  %3 = extractelement <8 x i16> %2, i32 0
142*9880d681SAndroid Build Coastguard Worker  ret i16 %3
143*9880d681SAndroid Build Coastguard Worker}
144*9880d681SAndroid Build Coastguard Worker
145*9880d681SAndroid Build Coastguard Worker; Test that we are generating vrev and vext for reverse shuffles of v8i16
146*9880d681SAndroid Build Coastguard Worker; shuffles.
147*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: reverse_v8i16:
148*9880d681SAndroid Build Coastguard Workerdefine void @reverse_v8i16(<8 x i16>* %loadaddr, <8 x i16>* %storeaddr) {
149*9880d681SAndroid Build Coastguard Worker  %v0 = load <8 x i16>, <8 x i16>* %loadaddr
150*9880d681SAndroid Build Coastguard Worker  ; CHECK: vrev64.16
151*9880d681SAndroid Build Coastguard Worker  ; CHECK: vext.16
152*9880d681SAndroid Build Coastguard Worker  %v1 = shufflevector <8 x i16> %v0, <8 x i16> undef,
153*9880d681SAndroid Build Coastguard Worker              <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
154*9880d681SAndroid Build Coastguard Worker  store <8 x i16> %v1, <8 x i16>* %storeaddr
155*9880d681SAndroid Build Coastguard Worker  ret void
156*9880d681SAndroid Build Coastguard Worker}
157*9880d681SAndroid Build Coastguard Worker
158*9880d681SAndroid Build Coastguard Worker; Test that we are generating vrev and vext for reverse shuffles of v16i8
159*9880d681SAndroid Build Coastguard Worker; shuffles.
160*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: reverse_v16i8:
161*9880d681SAndroid Build Coastguard Workerdefine void @reverse_v16i8(<16 x i8>* %loadaddr, <16 x i8>* %storeaddr) {
162*9880d681SAndroid Build Coastguard Worker  %v0 = load <16 x i8>, <16 x i8>* %loadaddr
163*9880d681SAndroid Build Coastguard Worker  ; CHECK: vrev64.8
164*9880d681SAndroid Build Coastguard Worker  ; CHECK: vext.8
165*9880d681SAndroid Build Coastguard Worker  %v1 = shufflevector <16 x i8> %v0, <16 x i8> undef,
166*9880d681SAndroid Build Coastguard Worker       <16 x i32> <i32 15, i32 14, i32 13, i32 12, i32 11, i32 10, i32 9, i32 8,
167*9880d681SAndroid Build Coastguard Worker                   i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
168*9880d681SAndroid Build Coastguard Worker  store <16 x i8> %v1, <16 x i8>* %storeaddr
169*9880d681SAndroid Build Coastguard Worker  ret void
170*9880d681SAndroid Build Coastguard Worker}
171*9880d681SAndroid Build Coastguard Worker
172*9880d681SAndroid Build Coastguard Worker; <rdar://problem/14170854>.
173*9880d681SAndroid Build Coastguard Worker; vldr cannot handle unaligned loads.
174*9880d681SAndroid Build Coastguard Worker; Fall back to vld1.32, which can, instead of using the general purpose loads
175*9880d681SAndroid Build Coastguard Worker; followed by a costly sequence of instructions to build the vector register.
176*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: t3:
177*9880d681SAndroid Build Coastguard Worker; CHECK: vld1.32 {[[REG:d[0-9]+]][0]}
178*9880d681SAndroid Build Coastguard Worker; CHECK: vld1.32 {[[REG]][1]}
179*9880d681SAndroid Build Coastguard Worker; CHECK: vmull.u8 q{{[0-9]+}}, [[REG]], [[REG]]
180*9880d681SAndroid Build Coastguard Workerdefine <8 x i16> @t3(i8 zeroext %xf, i8* nocapture %sp0, i8* nocapture %sp1, i32* nocapture %outp) {
181*9880d681SAndroid Build Coastguard Workerentry:
182*9880d681SAndroid Build Coastguard Worker  %pix_sp0.0.cast = bitcast i8* %sp0 to i32*
183*9880d681SAndroid Build Coastguard Worker  %pix_sp0.0.copyload = load i32, i32* %pix_sp0.0.cast, align 1
184*9880d681SAndroid Build Coastguard Worker  %pix_sp1.0.cast = bitcast i8* %sp1 to i32*
185*9880d681SAndroid Build Coastguard Worker  %pix_sp1.0.copyload = load i32, i32* %pix_sp1.0.cast, align 1
186*9880d681SAndroid Build Coastguard Worker  %vecinit = insertelement <2 x i32> undef, i32 %pix_sp0.0.copyload, i32 0
187*9880d681SAndroid Build Coastguard Worker  %vecinit1 = insertelement <2 x i32> %vecinit, i32 %pix_sp1.0.copyload, i32 1
188*9880d681SAndroid Build Coastguard Worker  %0 = bitcast <2 x i32> %vecinit1 to <8 x i8>
189*9880d681SAndroid Build Coastguard Worker  %vmull.i = tail call <8 x i16> @llvm.arm.neon.vmullu.v8i16(<8 x i8> %0, <8 x i8> %0)
190*9880d681SAndroid Build Coastguard Worker  ret <8 x i16> %vmull.i
191*9880d681SAndroid Build Coastguard Worker}
192*9880d681SAndroid Build Coastguard Worker
193*9880d681SAndroid Build Coastguard Worker; Function Attrs: nounwind readnone
194*9880d681SAndroid Build Coastguard Workerdeclare <8 x i16> @llvm.arm.neon.vmullu.v8i16(<8 x i8>, <8 x i8>)
195*9880d681SAndroid Build Coastguard Worker
196*9880d681SAndroid Build Coastguard Worker; Check that (insert_vector_elt (load)) => (vector_load).
197*9880d681SAndroid Build Coastguard Worker; Thus, check that scalar_to_vector do not interfer with that.
198*9880d681SAndroid Build Coastguard Workerdefine <8 x i16> @t4(i8* nocapture %sp0) {
199*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: t4:
200*9880d681SAndroid Build Coastguard Worker; CHECK: vld1.32 {{{d[0-9]+}}[0]}, [r0]
201*9880d681SAndroid Build Coastguard Workerentry:
202*9880d681SAndroid Build Coastguard Worker  %pix_sp0.0.cast = bitcast i8* %sp0 to i32*
203*9880d681SAndroid Build Coastguard Worker  %pix_sp0.0.copyload = load i32, i32* %pix_sp0.0.cast, align 1
204*9880d681SAndroid Build Coastguard Worker  %vec = insertelement <2 x i32> undef, i32 %pix_sp0.0.copyload, i32 0
205*9880d681SAndroid Build Coastguard Worker  %0 = bitcast <2 x i32> %vec to <8 x i8>
206*9880d681SAndroid Build Coastguard Worker  %vmull.i = tail call <8 x i16> @llvm.arm.neon.vmullu.v8i16(<8 x i8> %0, <8 x i8> %0)
207*9880d681SAndroid Build Coastguard Worker  ret <8 x i16> %vmull.i
208*9880d681SAndroid Build Coastguard Worker}
209*9880d681SAndroid Build Coastguard Worker
210*9880d681SAndroid Build Coastguard Worker; Make sure vector load is used for all three loads.
211*9880d681SAndroid Build Coastguard Worker; Lowering to build vector was breaking the single use property of the load of
212*9880d681SAndroid Build Coastguard Worker;  %pix_sp0.0.copyload.
213*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: t5:
214*9880d681SAndroid Build Coastguard Worker; CHECK: vld1.32 {[[REG1:d[0-9]+]][1]}, [r0]
215*9880d681SAndroid Build Coastguard Worker; CHECK: vorr [[REG2:d[0-9]+]], [[REG1]], [[REG1]]
216*9880d681SAndroid Build Coastguard Worker; CHECK: vld1.32 {[[REG1]][0]}, [r1]
217*9880d681SAndroid Build Coastguard Worker; CHECK: vld1.32 {[[REG2]][0]}, [r2]
218*9880d681SAndroid Build Coastguard Worker; CHECK: vmull.u8 q{{[0-9]+}}, [[REG1]], [[REG2]]
219*9880d681SAndroid Build Coastguard Workerdefine <8 x i16> @t5(i8* nocapture %sp0, i8* nocapture %sp1, i8* nocapture %sp2) {
220*9880d681SAndroid Build Coastguard Workerentry:
221*9880d681SAndroid Build Coastguard Worker  %pix_sp0.0.cast = bitcast i8* %sp0 to i32*
222*9880d681SAndroid Build Coastguard Worker  %pix_sp0.0.copyload = load i32, i32* %pix_sp0.0.cast, align 1
223*9880d681SAndroid Build Coastguard Worker  %pix_sp1.0.cast = bitcast i8* %sp1 to i32*
224*9880d681SAndroid Build Coastguard Worker  %pix_sp1.0.copyload = load i32, i32* %pix_sp1.0.cast, align 1
225*9880d681SAndroid Build Coastguard Worker  %pix_sp2.0.cast = bitcast i8* %sp2 to i32*
226*9880d681SAndroid Build Coastguard Worker  %pix_sp2.0.copyload = load i32, i32* %pix_sp2.0.cast, align 1
227*9880d681SAndroid Build Coastguard Worker  %vec = insertelement <2 x i32> undef, i32 %pix_sp0.0.copyload, i32 1
228*9880d681SAndroid Build Coastguard Worker  %vecinit1 = insertelement <2 x i32> %vec, i32 %pix_sp1.0.copyload, i32 0
229*9880d681SAndroid Build Coastguard Worker  %vecinit2 = insertelement <2 x i32> %vec, i32 %pix_sp2.0.copyload, i32 0
230*9880d681SAndroid Build Coastguard Worker  %0 = bitcast <2 x i32> %vecinit1 to <8 x i8>
231*9880d681SAndroid Build Coastguard Worker  %1 = bitcast <2 x i32> %vecinit2 to <8 x i8>
232*9880d681SAndroid Build Coastguard Worker  %vmull.i = tail call <8 x i16> @llvm.arm.neon.vmullu.v8i16(<8 x i8> %0, <8 x i8> %1)
233*9880d681SAndroid Build Coastguard Worker  ret <8 x i16> %vmull.i
234*9880d681SAndroid Build Coastguard Worker}
235*9880d681SAndroid Build Coastguard Worker
236*9880d681SAndroid Build Coastguard Worker; <rdar://problem/14989896> Make sure we manage to truncate a vector from an
237*9880d681SAndroid Build Coastguard Worker; illegal type to a legal type.
238*9880d681SAndroid Build Coastguard Workerdefine <2 x i8> @test_truncate(<2 x i128> %in) {
239*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: test_truncate:
240*9880d681SAndroid Build Coastguard Worker; CHECK: mov [[BASE:r[0-9]+]], sp
241*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: vld1.32 {[[REG1:d[0-9]+]][0]}, {{\[}}[[BASE]]:32]
242*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: add [[BASE2:r[0-9]+]], [[BASE]], #4
243*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: vld1.32 {[[REG1]][1]}, {{\[}}[[BASE2]]:32]
244*9880d681SAndroid Build Coastguard Worker; REG2 Should map on the same Q register as REG1, i.e., REG2 = REG1 - 1, but we
245*9880d681SAndroid Build Coastguard Worker; cannot express that.
246*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: vmov.32 [[REG2:d[0-9]+]][0], r0
247*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: vmov.32 [[REG2]][1], r1
248*9880d681SAndroid Build Coastguard Worker; The Q register used here should match floor(REG1/2), but we cannot express that.
249*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: vmovn.i64 [[RES:d[0-9]+]], q{{[0-9]+}}
250*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: vmov r0, r1, [[RES]]
251*9880d681SAndroid Build Coastguard Workerentry:
252*9880d681SAndroid Build Coastguard Worker  %res = trunc <2 x i128> %in to <2 x i8>
253*9880d681SAndroid Build Coastguard Worker  ret <2 x i8> %res
254*9880d681SAndroid Build Coastguard Worker}
255