]> gitweb.factorcode.org Git - factor.git/blob - basis/compiler/cfg/intrinsics/simd/simd.factor
new intrinsic generators, pt1
[factor.git] / basis / compiler / cfg / intrinsics / simd / simd.factor
1 ! Copyright (C) 2009 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors alien byte-arrays fry classes.algebra
4 cpu.architecture kernel math sequences math.vectors
5 math.vectors.simd macros generalizations combinators
6 combinators.short-circuit arrays locals
7 compiler.tree.propagation.info compiler.cfg.builder.blocks
8 compiler.cfg.comparisons
9 compiler.cfg.stacks compiler.cfg.stacks.local compiler.cfg.hats
10 compiler.cfg.instructions compiler.cfg.registers
11 compiler.cfg.intrinsics.alien
12 specialized-arrays ;
13 FROM: alien.c-types => heap-size char short int longlong float double ;
14 SPECIALIZED-ARRAYS: char short int longlong float double ;
15 IN: compiler.cfg.intrinsics.simd
16
17 ! compound vector ops
18
19 : ^load-neg-zero-vector ( rep -- dst )
20     {
21         { float-4-rep [ float-array{ -0.0 -0.0 -0.0 -0.0 } underlying>> ^^load-constant ] }
22         { double-2-rep [ double-array{ -0.0 -0.0 } underlying>> ^^load-constant ] }
23     } case ;
24
25 : ^load-add-sub-vector ( rep -- dst )
26     unsign-rep {
27         { float-4-rep    [ float-array{ -0.0  0.0 -0.0  0.0 } underlying>> ^^load-constant ] }
28         { double-2-rep   [ double-array{ -0.0  0.0 } underlying>> ^^load-constant ] }
29         { char-16-rep    [ char-array{ -1 0 -1 0 -1 0 -1 0 -1 0 -1 0 -1 0 -1 0 } underlying>> ^^load-constant ] }
30         { short-8-rep    [ short-array{ -1 0 -1 0 -1 0 -1 0 } underlying>> ^^load-constant ] }
31         { int-4-rep      [ int-array{ -1 0 -1 0 } underlying>> ^^load-constant ] }
32         { longlong-2-rep [ longlong-array{ -1 0 } underlying>> ^^load-constant ] }
33     } case ;
34
35 : >variable-shuffle ( shuffle rep -- shuffle' )
36     rep-component-type heap-size
37     [ dup <repetition> >byte-array ]
38     [ iota >byte-array ] bi
39     '[ _ n*v _ v+ ] map concat ;
40
41 : ^load-immediate-shuffle ( shuffle rep -- dst )
42     >variable-shuffle ^^load-constant ;
43
44 :: ^blend-vector ( mask true false rep -- dst )
45     true mask rep ^^and-vector
46     mask false rep ^^andn-vector
47     rep ^^or-vector ;
48
49 : ^compare-vector ( src1 src2 rep cc -- dst )
50     ... ;
51
52 : ^widened-shr-vector-imm ( src shift rep -- dst )
53     widen-vector-rep ^^shr-vector-imm ;
54
55 ! intrinsic emitters
56
57 : emit-simd-v+ ( node -- )
58     {
59         [ ^^add-vector ]
60     } emit-vv-vector-op ;
61
62 : emit-simd-v- ( node -- )
63     {
64         [ ^^sub-vector ]
65     } emit-vv-vector-op ;
66
67 : emit-simd-vneg ( node -- )
68     {
69         { float-vector-rep [ [ ^load-neg-zero-vector ] [ ^^sub-vector ] bi ] }
70         { int-vector-rep   [ [ ^^zero-vector         ] [ ^^sub-vector ] bi ] }
71     } emit-v-vector-op ;
72
73 : emit-simd-v+- ( node -- )
74     {
75         [ ^^add-sub-vector ]
76         { float-vector-rep [| src1 src2 rep |
77             rep ^load-add-sub-vector :> signs
78             src2 signs rep ^^xor-vector :> src2'
79             src1 src2' rep ^^add-vector
80         ] }
81         { int-vector-rep   [| src1 src2 rep |
82             rep ^load-add-sub-vector :> signs
83             src2  signs rep ^^xor-vector :> src2'
84             src2' signs rep ^^sub-vector :> src2''
85             src1 src2'' rep ^^add-vector
86         ] }
87     } emit-vv-vector-op ;
88
89 : emit-simd-vs+ ( node -- )
90     {
91         { float-vector-rep [ ^^add-vector ] }
92         { int-vector-rep [ ^^saturated-add-vector ] }
93     } emit-vv-vector-op ;
94
95 : emit-simd-vs- ( node -- )
96     {
97         { float-vector-rep [ ^^sub-vector ] }
98         { int-vector-rep [ ^^saturated-sub-vector ] }
99     } emit-vv-vector-op ;
100
101 : emit-simd-vs* ( node -- )
102     {
103         { float-vector-rep [ ^^mul-vector ] }
104         { int-vector-rep [ ^^saturated-mul-vector ] }
105     } emit-vv-vector-op ;
106
107 : emit-simd-v* ( node -- )
108     {
109         [ ^^mul-vector ]
110     } emit-vv-vector-op ;
111
112 : emit-simd-v/ ( node -- )
113     {
114         [ ^^div-vector ]
115     } emit-vv-vector-op ;
116
117 : emit-simd-vmin ( node -- )
118     {
119         [ ^^min-vector ]
120         [
121             [ cc< ^compare-vector ]
122             [ ^blend-vector ] 3bi
123         ]
124     } emit-vv-vector-op ;
125
126 : emit-simd-vmax ( node -- )
127     {
128         [ ^^max-vector ]
129         [
130             [ cc> ^compare-vector ]
131             [ ^blend-vector ] 3bi
132         ]
133     } emit-vv-vector-op ;
134
135 : emit-simd-v. ( node -- )
136     {
137         [ ^^dot-vector ]
138         { float-vector-rep [| src1 src2 rep |
139             
140         ] }
141         { int-vector-rep [| src1 src2 rep |
142             ...
143         ] }
144     } emit-vv-vector-op ;
145
146 : emit-simd-vsqrt ( node -- )
147     {
148         [ ^^sqrt-vector ]
149     } emit-v-vector-op ;
150
151 : emit-simd-sum ( node -- )
152     ... ;
153
154 : emit-simd-vabs ( node -- )
155     {
156         { unsigned-int-vector-rep [ drop ] }
157         [ ^^abs-vector ]
158         { float-vector-rep [ [ ^load-neg-zero-vector ] [ swapd ^^andn-vector ] bi ] }
159         { int-vector-rep [| src rep |
160             rep ^^zero-vector :> zero
161             zero src rep ^^sub-vector :> -src
162             zero src rep cc> ^compare-vector :> sign
163             sign -src src rep ^blend-vector
164         ] }
165     } emit-v-vector-op ;
166
167 : emit-simd-vand ( node -- )
168     {
169         [ ^^and-vector ]
170     } emit-vv-vector-op ;
171
172 : emit-simd-vandn ( node -- )
173     {
174         [ ^^andn-vector ]
175     } emit-vv-vector-op ;
176
177 : emit-simd-vor ( node -- )
178     {
179         [ ^^or-vector ]
180     } emit-vv-vector-op ;
181
182 : emit-simd-vxor ( node -- )
183     {
184         [ ^^xor-vector ]
185     } emit-vv-vector-op ;
186
187 : emit-simd-vnot ( node -- )
188     {
189         [ ^^not-vector ]
190         [ [ ^^fill-vector ] [ ^^xor-vector ] bi ]
191     } emit-v-vector-op ;
192
193 : emit-simd-vlshift ( node -- )
194     {
195         [ ^^shl-vector ]
196     } {
197         [ ^^shl-vector-imm ]
198     } emit-vn-or-vl-vector-op ;
199
200 : emit-simd-vrshift ( node -- )
201     {
202         [ ^^shr-vector ]
203     } {
204         [ ^^shr-vector-imm ]
205     } emit-vn-or-vl-vector-op ;
206
207 : emit-simd-hlshift ( node -- )
208     {
209         [ ^^horizontal-shl-vector-imm ]
210     } emit-vl-vector-op ;
211
212 : emit-simd-hrshift ( node -- )
213     {
214         [ ^^horizontal-shr-vector-imm ]
215     } emit-vl-vector-op ;
216
217 : emit-simd-vshuffle-elements ( node -- )
218     {
219         [ ^^shuffle-vector-imm ]
220         [ [ ^load-immediate-shuffle ] [ ^^shuffle-vector ] ]
221     } emit-vl-vector-op ;
222
223 : emit-simd-vshuffle-bytes ( node -- )
224     {
225         [ ^^shuffle-vector ]
226     } emit-vv-vector-op ;
227
228 : emit-simd-vmerge-head ( node -- )
229     {
230         [ ^^merge-vector-head ]
231     } emit-vv-vector-op ;
232
233 : emit-simd-vmerge-tail ( node -- )
234     {
235         [ ^^merge-vector-tail ]
236     } emit-vv-vector-op ;
237
238 : emit-simd-v<= ( node -- )
239     [ cc<= ^compare-vector ] (emit-vv-vector-op) ;
240 : emit-simd-v< ( node -- )
241     [ cc< ^compare-vector ] (emit-vv-vector-op) ;
242 : emit-simd-v= ( node -- )
243     [ cc= ^compare-vector ] (emit-vv-vector-op) ;
244 : emit-simd-v> ( node -- )
245     [ cc> ^compare-vector ] (emit-vv-vector-op) ;
246 : emit-simd-v>= ( node -- )
247     [ cc>= ^compare-vector ] (emit-vv-vector-op) ;
248 : emit-simd-vunordered? ( node -- )
249     [ cc/<>= ^compare-vector ] (emit-vv-vector-op) ;
250
251 : emit-simd-vany? ( node -- )
252     [ vcc-any ^test-vector ] (emit-vv-vector-op) ;
253 : emit-simd-vall? ( node -- )
254     [ vcc-all ^test-vector ] (emit-vv-vector-op) ;
255 : emit-simd-vnone? ( node -- )
256     [ vcc-none ^test-vector ] (emit-vv-vector-op) ;
257
258 : emit-simd-v>float ( node -- )
259     {
260         { float-vector-rep [ drop ] }
261         { int-vector-rep [ ^^integer>float-vector ] }
262     } emit-vv-vector-op ;
263
264 : emit-simd-v>integer ( node -- )
265     {
266         { float-vector-rep [ ^^float>integer-vector ] }
267         { int-vector-rep [ dup ] }
268     } emit-vv-vector-op ;
269
270 : emit-simd-vpack-signed ( node -- )
271     {
272         [ ^^signed-pack-vector ]
273     } emit-vv-vector-op ;
274
275 : emit-simd-vpack-unsigned ( node -- )
276     {
277         [ ^^unsigned-pack-vector ]
278     } emit-vv-vector-op ;
279
280 ! XXX shr vector rep is widened!
281 : emit-simd-vunpack-head ( node -- )
282     {
283         [ ^^unpack-vector-head ]
284         { unsigned-int-vector-rep [ [ ^^zero-vector ] [ ^^merge-vector-head ] bi ] }
285         { signed-int-vector-rep [| src rep |
286             src src rep ^^merge-vector-head :> merged
287             rep rep-component-type heap-size 8 * :> bits
288             merged bits rep ^widened-shr-vector-imm
289         ] }
290         { signed-int-vector-rep [| src rep |
291             rep ^^zero-vector :> zero
292             zero src rep cc> ^compare-vector :> sign
293             src sign rep ^^merge-vector-head
294         ] }
295     } emit-v-vector-op ;
296
297 : emit-simd-vunpack-tail ( node -- )
298     {
299         [ ^^unpack-vector-tail ]
300         [ [ ^^tail>head-vector ] [ ^^unpack-vector-head ] bi ]
301         { unsigned-int-vector-rep [ [ ^^zero-vector ] [ ^^merge-vector-tail ] bi ] }
302         { signed-int-vector-rep [| src rep |
303             src src rep ^^merge-vector-tail :> merged
304             rep rep-component-type heap-size 8 * :> bits
305             merged bits rep widen-vector-rep ^widened-shr-vector-imm
306         ] }
307         { signed-int-vector-rep [| src rep |
308             rep ^^zero-vector :> zero
309             zero src rep cc> ^compare-vector :> sign
310             src sign rep ^^merge-vector-tail
311         ] }
312     } emit-v-vector-op ;
313
314 : emit-simd-with ( node -- )
315 : emit-simd-gather-2 ( node -- )
316 : emit-simd-gather-4 ( node -- )
317 : emit-simd-select ( node -- )
318 : emit-alien-vector ( node -- )
319 : emit-set-alien-vector ( node -- )
320 : emit-alien-vector-aligned ( node -- )
321 : emit-set-alien-vector-aligned ( node -- )
322
323 : enable-simd ( -- )
324     {
325         { (simd-v+)                [ emit-simd-v+                  ] }
326         { (simd-v-)                [ emit-simd-v-                  ] }
327         { (simd-vneg)              [ emit-simd-vneg                ] }
328         { (simd-v+-)               [ emit-simd-v+-                 ] }
329         { (simd-vs+)               [ emit-simd-vs+                 ] }
330         { (simd-vs-)               [ emit-simd-vs-                 ] }
331         { (simd-vs*)               [ emit-simd-vs*                 ] }
332         { (simd-v*)                [ emit-simd-v*                  ] }
333         { (simd-v/)                [ emit-simd-v/                  ] }
334         { (simd-vmin)              [ emit-simd-vmin                ] }
335         { (simd-vmax)              [ emit-simd-vmax                ] }
336         { (simd-v.)                [ emit-simd-v.                  ] }
337         { (simd-vsqrt)             [ emit-simd-vsqrt               ] }
338         { (simd-sum)               [ emit-simd-sum                 ] }
339         { (simd-vabs)              [ emit-simd-vabs                ] }
340         { (simd-vbitand)           [ emit-simd-vand                ] }
341         { (simd-vbitandn)          [ emit-simd-vandn               ] }
342         { (simd-vbitor)            [ emit-simd-vor                 ] }
343         { (simd-vbitxor)           [ emit-simd-vxor                ] }
344         { (simd-vbitnot)           [ emit-simd-vnot                ] }
345         { (simd-vand)              [ emit-simd-vand                ] }
346         { (simd-vandn)             [ emit-simd-vandn               ] }
347         { (simd-vor)               [ emit-simd-vor                 ] }
348         { (simd-vxor)              [ emit-simd-vxor                ] }
349         { (simd-vnot)              [ emit-simd-vnot                ] }
350         { (simd-vlshift)           [ emit-simd-vlshift             ] }
351         { (simd-vrshift)           [ emit-simd-vrshift             ] }
352         { (simd-hlshift)           [ emit-simd-hlshift             ] }
353         { (simd-hrshift)           [ emit-simd-hrshift             ] }
354         { (simd-vshuffle-elements) [ emit-simd-vshuffle-elements   ] }
355         { (simd-vshuffle-bytes)    [ emit-simd-vshuffle-bytes      ] }
356         { (simd-vmerge-head)       [ emit-simd-vmerge-head         ] }
357         { (simd-vmerge-tail)       [ emit-simd-vmerge-tail         ] }
358         { (simd-v<=)               [ emit-simd-v<=                 ] }
359         { (simd-v<)                [ emit-simd-v<                  ] }
360         { (simd-v=)                [ emit-simd-v=                  ] }
361         { (simd-v>)                [ emit-simd-v>                  ] }
362         { (simd-v>=)               [ emit-simd-v>=                 ] }
363         { (simd-vunordered?)       [ emit-simd-vunordered?         ] }
364         { (simd-vany?)             [ emit-simd-vany?               ] }
365         { (simd-vall?)             [ emit-simd-vall?               ] }
366         { (simd-vnone?)            [ emit-simd-vnone?              ] }
367         { (simd-v>float)           [ emit-simd-v>float             ] }
368         { (simd-v>integer)         [ emit-simd-v>integer           ] }
369         { (simd-vpack-signed)      [ emit-simd-vpack-signed        ] }
370         { (simd-vpack-unsigned)    [ emit-simd-vpack-unsigned      ] }
371         { (simd-vunpack-head)      [ emit-simd-vunpack-head        ] }
372         { (simd-vunpack-tail)      [ emit-simd-vunpack-tail        ] }
373         { (simd-with)              [ emit-simd-with                ] }
374         { (simd-gather-2)          [ emit-simd-gather-2            ] }
375         { (simd-gather-4)          [ emit-simd-gather-4            ] }
376         { (simd-select)            [ emit-simd-select              ] }
377         { alien-vector             [ emit-alien-vector             ] }
378         { set-alien-vector         [ emit-set-alien-vector         ] }
379         { alien-vector-aligned     [ emit-alien-vector             ] }
380         { set-alien-vector-aligned [ emit-set-alien-vector         ] }
381     } enable-intrinsics ;
382
383 enable-simd