[X86] Remove special validation for INT immediate operand from AsmParser. Instead...
[oota-llvm.git] / test / CodeGen / X86 / masked_gather_scatter.ll
1 ; RUN: llc -mtriple=x86_64-apple-darwin  -mcpu=knl < %s | FileCheck %s -check-prefix=KNL
2
3 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
4 target triple = "x86_64-unknown-linux-gnu"
5
6 ; KNL-LABEL: test1
7 ; KNL: kxnorw  %k1, %k1, %k1
8 ; KNL: vgatherdps      (%rdi,%zmm0,4), %zmm1 {%k1}
9 define <16 x float> @test1(float* %base, <16 x i32> %ind) {
10
11   %broadcast.splatinsert = insertelement <16 x float*> undef, float* %base, i32 0
12   %broadcast.splat = shufflevector <16 x float*> %broadcast.splatinsert, <16 x float*> undef, <16 x i32> zeroinitializer
13
14   %sext_ind = sext <16 x i32> %ind to <16 x i64>
15   %gep.random = getelementptr float, <16 x float*> %broadcast.splat, <16 x i64> %sext_ind
16   
17   %res = call <16 x float> @llvm.masked.gather.v16f32(<16 x float*> %gep.random, i32 4, <16 x i1> <i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true>, <16 x float> undef)
18   ret <16 x float>%res
19 }
20
21 declare <16 x i32> @llvm.masked.gather.v16i32(<16 x i32*>, i32, <16 x i1>, <16 x i32>)
22 declare <16 x float> @llvm.masked.gather.v16f32(<16 x float*>, i32, <16 x i1>, <16 x float>)
23 declare <8 x i32> @llvm.masked.gather.v8i32(<8 x i32*> , i32, <8 x i1> , <8 x i32> )
24   
25 ; KNL-LABEL: test2
26 ; KNL: kmovw %esi, %k1
27 ; KNL: vgatherdps      (%rdi,%zmm0,4), %zmm1 {%k1}
28 define <16 x float> @test2(float* %base, <16 x i32> %ind, i16 %mask) {
29
30   %broadcast.splatinsert = insertelement <16 x float*> undef, float* %base, i32 0
31   %broadcast.splat = shufflevector <16 x float*> %broadcast.splatinsert, <16 x float*> undef, <16 x i32> zeroinitializer
32
33   %sext_ind = sext <16 x i32> %ind to <16 x i64>
34   %gep.random = getelementptr float, <16 x float*> %broadcast.splat, <16 x i64> %sext_ind
35   %imask = bitcast i16 %mask to <16 x i1>
36   %res = call <16 x float> @llvm.masked.gather.v16f32(<16 x float*> %gep.random, i32 4, <16 x i1> %imask, <16 x float>undef)
37   ret <16 x float> %res
38 }
39
40 ; KNL-LABEL: test3
41 ; KNL: kmovw %esi, %k1
42 ; KNL: vpgatherdd      (%rdi,%zmm0,4), %zmm1 {%k1}
43 define <16 x i32> @test3(i32* %base, <16 x i32> %ind, i16 %mask) {
44
45   %broadcast.splatinsert = insertelement <16 x i32*> undef, i32* %base, i32 0
46   %broadcast.splat = shufflevector <16 x i32*> %broadcast.splatinsert, <16 x i32*> undef, <16 x i32> zeroinitializer
47
48   %sext_ind = sext <16 x i32> %ind to <16 x i64>
49   %gep.random = getelementptr i32, <16 x i32*> %broadcast.splat, <16 x i64> %sext_ind
50   %imask = bitcast i16 %mask to <16 x i1>
51   %res = call <16 x i32> @llvm.masked.gather.v16i32(<16 x i32*> %gep.random, i32 4, <16 x i1> %imask, <16 x i32>undef)
52   ret <16 x i32> %res
53 }
54
55 ; KNL-LABEL: test4
56 ; KNL: kmovw %esi, %k1
57 ; KNL: kmovw
58 ; KNL: vpgatherdd
59 ; KNL: vpgatherdd
60
61 define <16 x i32> @test4(i32* %base, <16 x i32> %ind, i16 %mask) {
62
63   %broadcast.splatinsert = insertelement <16 x i32*> undef, i32* %base, i32 0
64   %broadcast.splat = shufflevector <16 x i32*> %broadcast.splatinsert, <16 x i32*> undef, <16 x i32> zeroinitializer
65
66   %gep.random = getelementptr i32, <16 x i32*> %broadcast.splat, <16 x i32> %ind
67   %imask = bitcast i16 %mask to <16 x i1>
68   %gt1 = call <16 x i32> @llvm.masked.gather.v16i32(<16 x i32*> %gep.random, i32 4, <16 x i1> %imask, <16 x i32>undef)
69   %gt2 = call <16 x i32> @llvm.masked.gather.v16i32(<16 x i32*> %gep.random, i32 4, <16 x i1> %imask, <16 x i32>%gt1)
70   %res = add <16 x i32> %gt1, %gt2
71   ret <16 x i32> %res
72 }
73
74 ; KNL-LABEL: test5
75 ; KNL: kmovw %k1, %k2
76 ; KNL: vpscatterdd {{.*}}%k2
77 ; KNL: vpscatterdd {{.*}}%k1
78
79 define void @test5(i32* %base, <16 x i32> %ind, i16 %mask, <16 x i32>%val) {
80
81   %broadcast.splatinsert = insertelement <16 x i32*> undef, i32* %base, i32 0
82   %broadcast.splat = shufflevector <16 x i32*> %broadcast.splatinsert, <16 x i32*> undef, <16 x i32> zeroinitializer
83
84   %gep.random = getelementptr i32, <16 x i32*> %broadcast.splat, <16 x i32> %ind
85   %imask = bitcast i16 %mask to <16 x i1>
86   call void @llvm.masked.scatter.v16i32(<16 x i32>%val, <16 x i32*> %gep.random, i32 4, <16 x i1> %imask)
87   call void @llvm.masked.scatter.v16i32(<16 x i32>%val, <16 x i32*> %gep.random, i32 4, <16 x i1> %imask)
88   ret void
89 }
90
91 declare void @llvm.masked.scatter.v8i32(<8 x i32> , <8 x i32*> , i32 , <8 x i1> )
92 declare void @llvm.masked.scatter.v16i32(<16 x i32> , <16 x i32*> , i32 , <16 x i1> )
93
94 ; KNL-LABEL: test6
95 ; KNL: kxnorw  %k1, %k1, %k1
96 ; KNL: kxnorw  %k2, %k2, %k2
97 ; KNL: vpgatherqd      (,%zmm{{.*}}), %ymm{{.*}} {%k2}
98 ; KNL: vpscatterqd     %ymm{{.*}}, (,%zmm{{.*}}) {%k1}
99 define <8 x i32> @test6(<8 x i32>%a1, <8 x i32*> %ptr) {
100
101   %a = call <8 x i32> @llvm.masked.gather.v8i32(<8 x i32*> %ptr, i32 4, <8 x i1> <i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true>, <8 x i32> undef)
102
103   call void @llvm.masked.scatter.v8i32(<8 x i32> %a1, <8 x i32*> %ptr, i32 4, <8 x i1> <i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true>)
104   ret <8 x i32>%a
105 }
106
107 ; In this case the index should be promoted to <8 x i64> for KNL
108 ; KNL-LABEL: test7
109 ; KNL: vpmovsxdq %ymm0, %zmm0
110 ; KNL: kmovw   %k1, %k2
111 ; KNL: vpgatherqd {{.*}} {%k2}
112 ; KNL: vpgatherqd {{.*}} {%k1}
113 define <8 x i32> @test7(i32* %base, <8 x i32> %ind, i8 %mask) {
114
115   %broadcast.splatinsert = insertelement <8 x i32*> undef, i32* %base, i32 0
116   %broadcast.splat = shufflevector <8 x i32*> %broadcast.splatinsert, <8 x i32*> undef, <8 x i32> zeroinitializer
117
118   %gep.random = getelementptr i32, <8 x i32*> %broadcast.splat, <8 x i32> %ind
119   %imask = bitcast i8 %mask to <8 x i1>
120   %gt1 = call <8 x i32> @llvm.masked.gather.v8i32(<8 x i32*> %gep.random, i32 4, <8 x i1> %imask, <8 x i32>undef)
121   %gt2 = call <8 x i32> @llvm.masked.gather.v8i32(<8 x i32*> %gep.random, i32 4, <8 x i1> %imask, <8 x i32>%gt1)
122   %res = add <8 x i32> %gt1, %gt2
123   ret <8 x i32> %res
124 }
125
126 ; No uniform base in this case, index <8 x i64> contains addresses,
127 ; each gather call will be split into two
128 ; KNL-LABEL: test8
129 ; KNL: kshiftrw        $8, %k1, %k2
130 ; KNL: vpgatherqd
131 ; KNL: vpgatherqd
132 ; KNL: vinserti64x4
133 ; KNL: vpgatherqd
134 ; KNL: vpgatherqd
135 ; KNL: vinserti64x4
136 define <16 x i32> @test8(<16 x i32*> %ptr.random, <16 x i32> %ind, i16 %mask) {
137   %imask = bitcast i16 %mask to <16 x i1>
138   %gt1 = call <16 x i32> @llvm.masked.gather.v16i32(<16 x i32*> %ptr.random, i32 4, <16 x i1> %imask, <16 x i32>undef)
139   %gt2 = call <16 x i32> @llvm.masked.gather.v16i32(<16 x i32*> %ptr.random, i32 4, <16 x i1> %imask, <16 x i32>%gt1)
140   %res = add <16 x i32> %gt1, %gt2
141   ret <16 x i32> %res
142 }
143
144 %struct.RT = type { i8, [10 x [20 x i32]], i8 }
145 %struct.ST = type { i32, double, %struct.RT }
146
147 ; Masked gather for agregate types
148 ; Test9 and Test10 should give the same result (scalar and vector indices in GEP)
149
150 ; KNL-LABEL: test9
151 ; KNL: vpbroadcastq    %rdi, %zmm
152 ; KNL: vpmovsxdq
153 ; KNL: vpbroadcastq
154 ; KNL: vpmuludq
155 ; KNL: vpaddq
156 ; KNL: vpaddq
157 ; KNL: vpaddq
158 ; KNL: vpaddq
159 ; KNL: vpgatherqd      (,%zmm
160
161 define <8 x i32> @test9(%struct.ST* %base, <8 x i64> %ind1, <8 x i32>%ind5) {
162 entry:
163   %broadcast.splatinsert = insertelement <8 x %struct.ST*> undef, %struct.ST* %base, i32 0
164   %broadcast.splat = shufflevector <8 x %struct.ST*> %broadcast.splatinsert, <8 x %struct.ST*> undef, <8 x i32> zeroinitializer
165
166   %arrayidx = getelementptr  %struct.ST, <8 x %struct.ST*> %broadcast.splat, <8 x i64> %ind1, <8 x i32> <i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2>, <8 x i32><i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>, <8 x i32> %ind5, <8 x i64> <i64 13, i64 13, i64 13, i64 13, i64 13, i64 13, i64 13, i64 13>
167   %res = call <8 x i32 >  @llvm.masked.gather.v8i32(<8 x i32*>%arrayidx, i32 4, <8 x i1> <i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true>, <8 x i32> undef)
168   ret <8 x i32> %res
169 }
170
171 ; KNL-LABEL: test10
172 ; KNL: vpbroadcastq    %rdi, %zmm
173 ; KNL: vpmovsxdq
174 ; KNL: vpbroadcastq
175 ; KNL: vpmuludq
176 ; KNL: vpaddq
177 ; KNL: vpaddq
178 ; KNL: vpaddq
179 ; KNL: vpaddq
180 ; KNL: vpgatherqd      (,%zmm
181 define <8 x i32> @test10(%struct.ST* %base, <8 x i64> %i1, <8 x i32>%ind5) {
182 entry:
183   %broadcast.splatinsert = insertelement <8 x %struct.ST*> undef, %struct.ST* %base, i32 0
184   %broadcast.splat = shufflevector <8 x %struct.ST*> %broadcast.splatinsert, <8 x %struct.ST*> undef, <8 x i32> zeroinitializer
185
186   %arrayidx = getelementptr  %struct.ST, <8 x %struct.ST*> %broadcast.splat, <8 x i64> %i1, i32 2, i32 1, <8 x i32> %ind5, i64 13
187   %res = call <8 x i32 >  @llvm.masked.gather.v8i32(<8 x i32*>%arrayidx, i32 4, <8 x i1> <i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true>, <8 x i32> undef)
188   ret <8 x i32> %res
189 }
190
191 ; Splat index in GEP, requires broadcast
192 ; KNL-LABEL: test11
193 ; KNL: vpbroadcastd    %esi, %zmm
194 ; KNL: vgatherdps      (%rdi,%zmm
195 define <16 x float> @test11(float* %base, i32 %ind) {
196
197   %broadcast.splatinsert = insertelement <16 x float*> undef, float* %base, i32 0
198   %broadcast.splat = shufflevector <16 x float*> %broadcast.splatinsert, <16 x float*> undef, <16 x i32> zeroinitializer
199
200   %gep.random = getelementptr float, <16 x float*> %broadcast.splat, i32 %ind
201
202   %res = call <16 x float> @llvm.masked.gather.v16f32(<16 x float*> %gep.random, i32 4, <16 x i1> <i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true>, <16 x float> undef)
203   ret <16 x float>%res
204 }
205
206 ; We are checking the uniform base here. It is taken directly from input to vgatherdps
207 ; KNL-LABEL: test12
208 ; KNL: kxnorw  %k1, %k1, %k1
209 ; KNL: vgatherdps      (%rdi,%zmm
210 define <16 x float> @test12(float* %base, <16 x i32> %ind) {
211
212   %sext_ind = sext <16 x i32> %ind to <16 x i64>
213   %gep.random = getelementptr float, float *%base, <16 x i64> %sext_ind
214
215   %res = call <16 x float> @llvm.masked.gather.v16f32(<16 x float*> %gep.random, i32 4, <16 x i1> <i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true, i1 true>, <16 x float> undef)
216   ret <16 x float>%res
217 }
218
219 ; The same as the previous, but the mask is undefined
220 ; KNL-LABEL: test13
221 ; KNL-NOT: kxnorw
222 ; KNL: vgatherdps      (%rdi,%zmm
223 define <16 x float> @test13(float* %base, <16 x i32> %ind) {
224
225   %sext_ind = sext <16 x i32> %ind to <16 x i64>
226   %gep.random = getelementptr float, float *%base, <16 x i64> %sext_ind
227
228   %res = call <16 x float> @llvm.masked.gather.v16f32(<16 x float*> %gep.random, i32 4, <16 x i1> undef, <16 x float> undef)
229   ret <16 x float>%res
230 }
231
232 ; The base pointer is not splat, can't find unform base
233 ; KNL-LABEL: test14
234 ; KNL: vgatherqps      (,%zmm0)
235 ; KNL: vgatherqps      (,%zmm0)
236 define <16 x float> @test14(float* %base, i32 %ind, <16 x float*> %vec) {
237
238   %broadcast.splatinsert = insertelement <16 x float*> %vec, float* %base, i32 1
239   %broadcast.splat = shufflevector <16 x float*> %broadcast.splatinsert, <16 x float*> undef, <16 x i32> zeroinitializer
240
241   %gep.random = getelementptr float, <16 x float*> %broadcast.splat, i32 %ind
242
243   %res = call <16 x float> @llvm.masked.gather.v16f32(<16 x float*> %gep.random, i32 4, <16 x i1> undef, <16 x float> undef)
244   ret <16 x float>%res
245 }
246
247