Merge commit '502ab21af0ca68f76d6112722c46d2f35c004053'
[ffmpeg.git] / libavutil / x86 / lls.asm
1 ;******************************************************************************
2 ;* linear least squares model
3 ;*
4 ;* Copyright (c) 2013 Loren Merritt
5 ;*
6 ;* This file is part of FFmpeg.
7 ;*
8 ;* FFmpeg is free software; you can redistribute it and/or
9 ;* modify it under the terms of the GNU Lesser General Public
10 ;* License as published by the Free Software Foundation; either
11 ;* version 2.1 of the License, or (at your option) any later version.
12 ;*
13 ;* FFmpeg is distributed in the hope that it will be useful,
14 ;* but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 ;* Lesser General Public License for more details.
17 ;*
18 ;* You should have received a copy of the GNU Lesser General Public
19 ;* License along with FFmpeg; if not, write to the Free Software
20 ;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 ;******************************************************************************
22
23 %include "x86util.asm"
24
25 SECTION .text
26
27 %define MAX_VARS 32
28 %define MAX_VARS_ALIGN (MAX_VARS+4)
29 %define COVAR_STRIDE MAX_VARS_ALIGN*8
30 %define COVAR(x,y) [covarq + (x)*8 + (y)*COVAR_STRIDE]
31
32 struc LLSModel
33     .covariance:  resq MAX_VARS_ALIGN*MAX_VARS_ALIGN
34     .coeff:       resq MAX_VARS*MAX_VARS
35     .variance:    resq MAX_VARS
36     .indep_count: resd 1
37 endstruc
38
39 %macro ADDPD_MEM 2
40 %if cpuflag(avx)
41     vaddpd %2, %1
42 %else
43     addpd  %2, %1
44 %endif
45     mova   %1, %2
46 %endmacro
47
48 INIT_XMM sse2
49 %define movdqa movaps
50 cglobal update_lls, 2,5,8, ctx, var, i, j, covar2
51     %define covarq ctxq
52     mov     id, [ctxq + LLSModel.indep_count]
53     lea   varq, [varq + iq*8]
54     neg     iq
55     mov covar2q, covarq
56 .loopi:
57     ; Compute all 3 pairwise products of a 2x2 block that lies on the diagonal
58     mova    m1, [varq + iq*8]
59     mova    m3, [varq + iq*8 + 16]
60     pshufd  m4, m1, q1010
61     pshufd  m5, m1, q3232
62     pshufd  m6, m3, q1010
63     pshufd  m7, m3, q3232
64     mulpd   m0, m1, m4
65     mulpd   m1, m1, m5
66     lea covarq, [covar2q + 16]
67     ADDPD_MEM COVAR(-2,0), m0
68     ADDPD_MEM COVAR(-2,1), m1
69     lea     jq, [iq + 2]
70     cmp     jd, -2
71     jg .skip4x4
72 .loop4x4:
73     ; Compute all 16 pairwise products of a 4x4 block
74     mulpd   m0, m4, m3
75     mulpd   m1, m5, m3
76     mulpd   m2, m6, m3
77     mulpd   m3, m3, m7
78     ADDPD_MEM COVAR(0,0), m0
79     ADDPD_MEM COVAR(0,1), m1
80     ADDPD_MEM COVAR(0,2), m2
81     ADDPD_MEM COVAR(0,3), m3
82     mova    m3, [varq + jq*8 + 16]
83     mulpd   m0, m4, m3
84     mulpd   m1, m5, m3
85     mulpd   m2, m6, m3
86     mulpd   m3, m3, m7
87     ADDPD_MEM COVAR(2,0), m0
88     ADDPD_MEM COVAR(2,1), m1
89     ADDPD_MEM COVAR(2,2), m2
90     ADDPD_MEM COVAR(2,3), m3
91     mova    m3, [varq + jq*8 + 32]
92     add covarq, 32
93     add     jq, 4
94     cmp     jd, -2
95     jle .loop4x4
96 .skip4x4:
97     test    jd, jd
98     jg .skip2x4
99     mulpd   m4, m3
100     mulpd   m5, m3
101     mulpd   m6, m3
102     mulpd   m7, m3
103     ADDPD_MEM COVAR(0,0), m4
104     ADDPD_MEM COVAR(0,1), m5
105     ADDPD_MEM COVAR(0,2), m6
106     ADDPD_MEM COVAR(0,3), m7
107 .skip2x4:
108     add     iq, 4
109     add covar2q, 4*COVAR_STRIDE+32
110     cmp     id, -2
111     jle .loopi
112     test    id, id
113     jg .ret
114     mov     jq, iq
115     %define covarq covar2q
116 .loop2x1:
117     movsd   m0, [varq + iq*8]
118     movlhps m0, m0
119     mulpd   m0, [varq + jq*8]
120     ADDPD_MEM COVAR(0,0), m0
121     inc     iq
122     add covarq, COVAR_STRIDE
123     test    id, id
124     jle .loop2x1
125 .ret:
126     REP_RET
127
128 INIT_YMM avx
129 cglobal update_lls, 3,6,8, ctx, var, count, i, j, count2
130     %define covarq ctxq
131     mov  countd, [ctxq + LLSModel.indep_count]
132     lea count2d, [countq-2]
133     xor     id, id
134 .loopi:
135     ; Compute all 10 pairwise products of a 4x4 block that lies on the diagonal
136     mova    ymm1, [varq + iq*8]
137     vbroadcastsd ymm4, [varq + iq*8]
138     vbroadcastsd ymm5, [varq + iq*8 + 8]
139     vbroadcastsd ymm6, [varq + iq*8 + 16]
140     vbroadcastsd ymm7, [varq + iq*8 + 24]
141     vextractf128 xmm3, ymm1, 1
142     vmulpd  ymm0, ymm1, ymm4
143     vmulpd  ymm1, ymm1, ymm5
144     vmulpd  xmm2, xmm3, xmm6
145     vmulpd  xmm3, xmm3, xmm7
146     ADDPD_MEM COVAR(iq  ,0), ymm0
147     ADDPD_MEM COVAR(iq  ,1), ymm1
148     ADDPD_MEM COVAR(iq+2,2), xmm2
149     ADDPD_MEM COVAR(iq+2,3), xmm3
150     lea     jd, [iq + 4]
151     cmp     jd, count2d
152     jg .skip4x4
153 .loop4x4:
154     ; Compute all 16 pairwise products of a 4x4 block
155     mova    ymm3, [varq + jq*8]
156     vmulpd  ymm0, ymm3, ymm4
157     vmulpd  ymm1, ymm3, ymm5
158     vmulpd  ymm2, ymm3, ymm6
159     vmulpd  ymm3, ymm3, ymm7
160     ADDPD_MEM COVAR(jq,0), ymm0
161     ADDPD_MEM COVAR(jq,1), ymm1
162     ADDPD_MEM COVAR(jq,2), ymm2
163     ADDPD_MEM COVAR(jq,3), ymm3
164     add     jd, 4
165     cmp     jd, count2d
166     jle .loop4x4
167 .skip4x4:
168     cmp     jd, countd
169     jg .skip2x4
170     mova    xmm3, [varq + jq*8]
171     vmulpd  xmm0, xmm3, xmm4
172     vmulpd  xmm1, xmm3, xmm5
173     vmulpd  xmm2, xmm3, xmm6
174     vmulpd  xmm3, xmm3, xmm7
175     ADDPD_MEM COVAR(jq,0), xmm0
176     ADDPD_MEM COVAR(jq,1), xmm1
177     ADDPD_MEM COVAR(jq,2), xmm2
178     ADDPD_MEM COVAR(jq,3), xmm3
179 .skip2x4:
180     add     id, 4
181     add covarq, 4*COVAR_STRIDE
182     cmp     id, count2d
183     jle .loopi
184     cmp     id, countd
185     jg .ret
186     mov     jd, id
187 .loop2x1:
188     vmovddup xmm0, [varq + iq*8]
189     vmulpd   xmm0, [varq + jq*8]
190     ADDPD_MEM COVAR(jq,0), xmm0
191     inc     id
192     add covarq, COVAR_STRIDE
193     cmp     id, countd
194     jle .loop2x1
195 .ret:
196     REP_RET