// ===== REFERENCES =====
// [1] duck.ac 用户 saffah_codex_6s_agg2,提交 #103362 <https://duck.ac/submission/103362>
// —— 本文件的引擎正文自该提交整份继承(= 我方 #102917 的正文 + 三处 hunk:
// `target(arch=skylake)` / `mk_s` 去掉两条 prefetcht0 / `MMS2` 行距 +128)。
// 本地归档件 problems/mmmc2k/ref2/rival_103362.cpp。
// [2] duck.ac 用户 saffah_cc_v41_agg1(本账号),提交 #103607 <https://duck.ac/submission/103607>
// (56.942818 ms,本题当前最好件)= [1] + 两个打包器各加软件预取 —— 本发的直接前驱;
// 除本发改动外,本文件与之逐字节相同。
// [3] duck.ac 用户 saffah_cc_v41_agg1(本账号),提交 #102917 <https://duck.ac/submission/102917>
// —— [1] 的直接来源(两层 Strassen + 四项带符号合成打包器)。
// [4] duck.ac 用户 saffah_cc_v41_260924,提交 #102282 <https://duck.ac/submission/102282>
// —— 本引擎的最终出处:`mk_s` 内联汇编内核、`epilogue2`、`corr512`、`cmb`、
// `build_A0A1`/`build_BI3Bp`、`strassen1` 的分块与 op 表(沿用其 `SAB_T`/`SBB_T`)。
// [5] 本代理(c2s_)自己的前置工件(本地路径,非引用来源,仅供复核):
// problems/mmmc2k/work/c2s_mk_wide.py(本文件的生成器)、
// problems/mmmc2k/work/c2s_ver1_gA.cpp(逐位闸门)、
// .cache/mmmc2k/c2s_pr1.cpp(判题机多臂探针)。
// ======================
// ===== 思路 =====
// 【本发的改动】**把 A 侧打包器 `buildA4` 从"每个 k2 叶各扫一遍源"改成"按 k1 融合的一次扫描"**
// (新函数 `bldAw0..6`,由 `strassen1` 在 k1 循环里调用一次)。
//
// 机理:固定 k1 时,7 个 k2 叶的 16 个源引用只落在 **8 个 distinct 的 512×512 块**上
// (A 侧 k1∈{0,1,4,5,6} 是 8 个;k1∈{2,3} 只有 4 个,因为该 k1 的 op=0 ⇒ 第 2/4 项不参与)。
// 旧写法每个叶把 4 个源块整块读一遍 ⇒ 每个源字节被读 ~3.5 遍(24 块读 / 8 个 distinct);
// 新写法按行推进:读 8 个 distinct 块的第 r 行(8×512 B),在同一趟里用带符号组合算出
// **7 个叶的第 r 行**,写进 7 份面板。⇒ A 侧源读 **每 k1 组 6 MB → 2 MB**。
//
// 面板:`A0b7[7][262144+512]` / `A1b7[7][4096+8]`(逐份保留 +512 的 4K-set pad,
// 与 `BI3b` 现有 pad 同理由)。消费侧(`mk_s`/`epilogue2`/`corr512`)**指令一字未改**,
// 只把面板基址变成参数(`corr512p(A1b,Bpb)` + 传指针)⇒ 本发不触碰内核形状
// (`mk_s` 已由五条否证钉死,见 notes)。
//
// 【闸门】`c2s_ver1_gA`:7 k1 × 7 k2 逐面板逐位对拍(262144 B 值 + 32768 B 符号位,
// 共 98 组)全部 OK;端到端 n=2048 全 4 194 304 元素与 [2] 相同;
// 独立素朴预言机 300 抽样 OK。**阳性对照**(把 k1=0 的第 0 个源块偏移 +64)
// ⇒ 面板 258029/262144 字节失配、端到端 78 抽样失配 ⇒ 闸门是活的。
//
// 【定价(判题机"立即体验"多臂探针 `.cache/mmmc2k/c2s_pr1.cpp`:同进程、臂序轮转、
// 逐臂 checksum 相同 `c46749be244f64b0`)】
// BASE 203676046(与该引擎历史五次读数 202.5~205.9 Mcyc 一致)
// FUSE 201353116 = **−1.1405%**
// ⚠ 该发探针的第三臂(去预取对照)**因臂选择宏写成 `g_mode>=1` 而与 FUSE 同路**,
// 故它读到的 −1.1474% 等于把 FUSE 量了第二遍(两遍差 0.007%,说明同进程重复性极好)。
// ⇒ 本发**缺阳性对照**,−1.14% 仍采信的理由:BASE 绝对值与历史一致 + 两遍 FUSE 一致。
// (下一发会把第三臂修成真对照:只改一行宏。)
// ================
#pragma GCC optimize("O3,unroll-loops,no-strict-aliasing")
#pragma GCC target("arch=skylake")
#include <immintrin.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#define AVX2 __attribute__((target("avx2")))
#define NMAX 4096
#define C2S_WA 1
#define C2S_WB 0
#define C2S_HASB 0
#define C2S_CFG "c2s-fuseA"
static int8_t A0b[NMAX*NMAX] __attribute__((aligned(64)));
static uint64_t A1b[NMAX*NMAX/8] __attribute__((aligned(64)));
static uint64_t Bpb[NMAX*NMAX/8] __attribute__((aligned(64)));
static uint64_t Pbb[NMAX*NMAX/8] __attribute__((aligned(64)));
static uint8_t PBb[NMAX*NMAX] __attribute__((aligned(64)));
/* ============ c2s: per-leaf ("wide") PANELS for the k1-fused packer ============
Seven copies of the A/B panels. Filled by bldAw<k1>()/bldBw<k1>() in ONE pass
over the distinct source blocks of that k1; consumed by the unchanged
mk_s/epilogue2/corr512 loop. The `+512` set-decorrelating pad of BI3b is kept
per leaf, and A0b7 gets the same pad for the same reason. */
#define LD(P) _mm256_load_si256((const __m256i*)(P))
static int8_t A0b7[7*(262144+512)] __attribute__((aligned(64)));
static uint64_t A1b7[7*(4096+8)] __attribute__((aligned(64)));
static void generic_mm(int n, const int8_t*A, const int8_t*B, int8_t*C){
for (int i=0;i<n;i++) for (int j=0;j<n;j++){
int s=0; for(int k=0;k<n;k++) s += (int)A[(size_t)i*n+k]*(int)B[(size_t)k*n+j];
C[(size_t)i*n+j]=(int8_t)s;
}
}
AVX2 static inline __m256i bcast16(const int8_t*p){
__m256i v; __asm__("vpbroadcastw %1, %0" : "=x"(v) : "m"(*(const short*)p)); return v;
}
AVX2 static inline __m256i packlo8(__m256i a, __m256i b){
const __m256i m=_mm256_set1_epi16(0x00FF);
return _mm256_permute4x64_epi64(
_mm256_packus_epi16(_mm256_and_si256(a,m), _mm256_and_si256(b,m)), 0xD8);
}
AVX2 static void build_A0(int n, const int8_t*A){
const __m256i m=_mm256_set1_epi8(0x7F);
size_t tot=(size_t)n*n;
for (size_t i=0;i<tot;i+=32)
_mm256_store_si256((__m256i*)(A0b+i),
_mm256_and_si256(_mm256_load_si256((const __m256i*)(A+i)), m));
}
AVX2 static void build_A1bits(int n, const int8_t*A){
int W=n/64;
for (int i=0;i<n;i++){
const int8_t*row=A+(size_t)i*n; uint64_t*w=A1b+(size_t)i*W;
for (int k=0;k<n;k+=64){
uint32_t lo=(uint32_t)_mm256_movemask_epi8(_mm256_load_si256((const __m256i*)(row+k)));
uint32_t hi=(uint32_t)_mm256_movemask_epi8(_mm256_load_si256((const __m256i*)(row+k+32)));
w[k>>6]=(uint64_t)lo|((uint64_t)hi<<32);
}
}
}
AVX2 static void build_Bpbits(int n, const int8_t*B){
const __m256i one=_mm256_set1_epi8(1);
int W=n/64;
for (int k=0;k<n;k++){
const int8_t*row=B+(size_t)k*n; uint64_t*w=Bpb+(size_t)k*W;
for (int j=0;j<n;j+=64){
__m256i a=_mm256_slli_epi16(_mm256_and_si256(_mm256_load_si256((const __m256i*)(row+j)),one),7);
__m256i b=_mm256_slli_epi16(_mm256_and_si256(_mm256_load_si256((const __m256i*)(row+j+32)),one),7);
uint32_t lo=(uint32_t)_mm256_movemask_epi8(a);
uint32_t hi=(uint32_t)_mm256_movemask_epi8(b);
w[j>>6]=(uint64_t)lo|((uint64_t)hi<<32);
}
}
}
/* P[i] = XOR of Bp[k] over k with A1[i][k] set. NY = n/256 ymm per row. */
AVX2 static void corr_bits(int n){
int W=n/64, NY=W>>2;
for (int i=0;i<n;i++){
__m256i acc[16];
for(int t=0;t<NY;t++) acc[t]=_mm256_setzero_si256();
const uint64_t*row=A1b+(size_t)i*W;
for(int w=0;w<W;w++){
uint64_t b=row[w];
while(b){
int t=__builtin_ctzll(b); b&=b-1;
const uint64_t*br=Bpb+(size_t)(w*64+t)*W;
for(int q=0;q<NY;q++)
acc[q]=_mm256_xor_si256(acc[q],_mm256_load_si256((const __m256i*)(br+4*q)));
}
}
uint64_t*o=Pbb+(size_t)i*W;
for(int q=0;q<NY;q++) _mm256_store_si256((__m256i*)(o+4*q),acc[q]);
}
}
static uint64_t A1T[NMAX*NMAX/8] __attribute__((aligned(64)));
AVX2 static void transpose64(uint64_t *a){
int j,k; uint64_t m,t;
for (j=32,m=0xFFFFFFFF00000000ULL; j; j>>=1, m^=m>>j)
for (k=0;k<64;k=(k+j+1)&~j){
t=(a[k]^(a[k+j]<<j))&m;
a[k]^=t; a[k+j]^=(t>>j);
}
}
AVX2 static void build_A1T(int n){
int W=n/64;
for (int kb=0; kb<n; kb+=64)
for (int ib=0; ib<n; ib+=64){
uint64_t blk[64];
for (int i=0;i<64;i++) blk[i]=A1b[(size_t)(ib+i)*W+(kb>>6)];
transpose64(blk);
for (int k=0;k<64;k++) A1T[(size_t)(kb+k)*W+(ib>>6)]=blk[k];
}
}
/* P[i][j] = XOR over k with A1[i][k] set of Bp[k][j].
Per-output-row bit scan (dense 64-bit words -> predictable), K-BLOCKED so the
Bp slice stays in L2. P accumulated in memory across k-blocks. */
AVX2 static void corr_pass3(int n){
int W=n/64, NY=W>>2;
memset(Pbb,0,(size_t)n*W*8);
const int KB=128;
for (int kb=0; kb<n; kb+=KB){
int w0=kb>>6, w1=w0+(KB>>6);
for (int i=0;i<n;i++){
__m256i acc[16];
for (int q=0;q<NY;q++) acc[q]=_mm256_setzero_si256();
const uint64_t*row=A1b+(size_t)i*W;
for (int w=w0;w<w1;w++){
uint64_t b=row[w];
while(b){
int t=__builtin_ctzll(b); b&=b-1;
const uint64_t*br=Bpb+(size_t)(w*64+t)*W;
for (int q=0;q<NY;q++) acc[q]=_mm256_xor_si256(acc[q],_mm256_load_si256((const __m256i*)(br+4*q)));
}
}
uint64_t*o=Pbb+(size_t)i*W;
for (int q=0;q<NY;q++){
__m256i*po=(__m256i*)(o+4*q);
_mm256_store_si256(po,_mm256_xor_si256(_mm256_load_si256((const __m256i*)po),acc[q]));
}
}
}
}
/* specialized for n=4096 (W=64, NY=16): fully unrolled XOR loops */
AVX2 static void corr16(void){
const int n=4096, W=64;
memset(Pbb,0,(size_t)n*W*8);
const int KB=256;
for (int kb=0; kb<n; kb+=KB){
int w0=kb>>6, w1=w0+4;
for (int i=0;i<n;i++){
__m256i acc0,acc1,acc2,acc3,acc4,acc5,acc6,acc7,acc8,acc9,acc10,acc11,acc12,acc13,acc14,acc15;
acc0=acc1=acc2=acc3=acc4=acc5=acc6=acc7=_mm256_setzero_si256();
acc8=acc9=acc10=acc11=acc12=acc13=acc14=acc15=_mm256_setzero_si256();
const uint64_t*row=A1b+(size_t)i*W;
for (int w=w0;w<w1;w++){
uint64_t b=row[w];
while(b){
int t=__builtin_ctzll(b); b&=b-1;
const uint64_t*br=Bpb+(size_t)(w*64+t)*W;
acc0 =_mm256_xor_si256(acc0 ,_mm256_load_si256((const __m256i*)(br+0)));
acc1 =_mm256_xor_si256(acc1 ,_mm256_load_si256((const __m256i*)(br+4)));
acc2 =_mm256_xor_si256(acc2 ,_mm256_load_si256((const __m256i*)(br+8)));
acc3 =_mm256_xor_si256(acc3 ,_mm256_load_si256((const __m256i*)(br+12)));
acc4 =_mm256_xor_si256(acc4 ,_mm256_load_si256((const __m256i*)(br+16)));
acc5 =_mm256_xor_si256(acc5 ,_mm256_load_si256((const __m256i*)(br+20)));
acc6 =_mm256_xor_si256(acc6 ,_mm256_load_si256((const __m256i*)(br+24)));
acc7 =_mm256_xor_si256(acc7 ,_mm256_load_si256((const __m256i*)(br+28)));
acc8 =_mm256_xor_si256(acc8 ,_mm256_load_si256((const __m256i*)(br+32)));
acc9 =_mm256_xor_si256(acc9 ,_mm256_load_si256((const __m256i*)(br+36)));
acc10=_mm256_xor_si256(acc10,_mm256_load_si256((const __m256i*)(br+40)));
acc11=_mm256_xor_si256(acc11,_mm256_load_si256((const __m256i*)(br+44)));
acc12=_mm256_xor_si256(acc12,_mm256_load_si256((const __m256i*)(br+48)));
acc13=_mm256_xor_si256(acc13,_mm256_load_si256((const __m256i*)(br+52)));
acc14=_mm256_xor_si256(acc14,_mm256_load_si256((const __m256i*)(br+56)));
acc15=_mm256_xor_si256(acc15,_mm256_load_si256((const __m256i*)(br+60)));
}
}
uint64_t*o=Pbb+(size_t)i*W;
#define RMW(q,a) { __m256i*po=(__m256i*)(o+4*(q)); _mm256_store_si256(po,_mm256_xor_si256(_mm256_load_si256((const __m256i*)po),a)); }
RMW(0,acc0) RMW(1,acc1) RMW(2,acc2) RMW(3,acc3) RMW(4,acc4) RMW(5,acc5) RMW(6,acc6) RMW(7,acc7)
RMW(8,acc8) RMW(9,acc9) RMW(10,acc10) RMW(11,acc11) RMW(12,acc12) RMW(13,acc13) RMW(14,acc14) RMW(15,acc15)
#undef RMW
}
}
}
static void expand_bits(int n){
static uint8_t T[256*8]; static int ti=0;
if(!ti){ for(int v=0;v<256;v++) for(int b=0;b<8;b++) T[v*8+b]=((v>>b)&1)?0x80:0x00; ti=1; }
int W=n/64;
for(int i=0;i<n;i++){
const uint64_t*w=Pbb+(size_t)i*W; uint8_t*o=PBb+(size_t)i*n;
for(int q=0;q<W;q++){
uint64_t v=w[q];
for(int s=0;s<8;s++) memcpy(o+(q*8+s)*8, T+(((uint8_t)(v>>(8*s)))*8), 8);
}
}
}
#define NIB 2
#define NJ 4
static const int16_t W0FF[16] __attribute__((aligned(32))) =
{0x00FF,0x00FF,0x00FF,0x00FF,0x00FF,0x00FF,0x00FF,0x00FF,
0x00FF,0x00FF,0x00FF,0x00FF,0x00FF,0x00FF,0x00FF,0x00FF};
static int8_t BI3b[NMAX*NMAX] __attribute__((aligned(64)));
AVX2 static void build_BI3(int n, const int8_t*B){
int ng=n/64;
for (int p=0;p<n/2;p++){
const int8_t *r0=B+(size_t)(2*p)*n, *r1=r0+n;
for (int g=0;g<ng;g++){
const int8_t *a=r0+64*g, *b=r1+64*g;
int8_t *o=BI3b+((size_t)g*(n/2)+p)*128;
for (int t=0;t<64;t+=32){
__m256i va=_mm256_load_si256((const __m256i*)(a+t));
__m256i vb=_mm256_load_si256((const __m256i*)(b+t));
__m256i lo=_mm256_unpacklo_epi8(va,vb), hi=_mm256_unpackhi_epi8(va,vb);
_mm256_store_si256((__m256i*)(o+2*t), _mm256_permute2x128_si256(lo,hi,0x20));
_mm256_store_si256((__m256i*)(o+2*t+32), _mm256_permute2x128_si256(lo,hi,0x31));
}
}
}
}
static int8_t mscr[128] __attribute__((aligned(64)));
AVX2 static void epilogue(int n, int8_t*C, const uint64_t*P, int jb, int i){
const __m128i bitm=_mm_setr_epi8(1,2,4,8,16,32,64,(char)0x80,1,2,4,8,16,32,64,(char)0x80);
const __m128i hi=_mm_set1_epi8((char)0x80), zero=_mm_setzero_si128();
const uint64_t*pw=P+((size_t)i*(n>>3)+(jb>>3))/8;
for(int r=0;r<2;r++){
const uint64_t*qa=pw+(size_t)r*(n>>6);
for(int t=0;t<2;t++){
__m256i v=_mm256_load_si256((const __m256i*)(mscr+r*64+t*32));
uint64_t w=qa[t>>1];
__m128i e0=_mm_setzero_si128(),e1=_mm_setzero_si128();
int sh=(t&1)?32:0;
for(int s=0;s<4;s++){
__m128i bb=_mm_set1_epi8((char)((w>>(sh+8*s))&0xFF));
__m128i z=_mm_andnot_si128(_mm_cmpeq_epi8(_mm_and_si128(bb,bitm),zero),hi);
if(s==0) e0=z; else if(s==1) e0=_mm_unpacklo_epi64(e0,z);
else if(s==2) e1=z; else e1=_mm_unpacklo_epi64(e1,z);
}
__m256i msk=_mm256_set_m128i(e1,e0);
int8_t*c=C+(size_t)(i+r)*n+jb+t*32;
_mm256_storeu_si256((__m256i*)c,_mm256_xor_si256(v,msk));
}
}
}
AVX2 static void mk_s(int n, const int8_t*A0, const int8_t*BI, int8_t*C, const uint8_t*PB, int jb){ (void)PB;
const int8_t *x0=A0, *x1=A0+n, *bi=BI; long cnt=n>>3;
asm volatile(
"vpxor %%xmm8,%%xmm8,%%xmm8\n\t"
"vpxor %%xmm9,%%xmm9,%%xmm9\n\t"
"vpxor %%xmm10,%%xmm10,%%xmm10\n\t"
"vpxor %%xmm11,%%xmm11,%%xmm11\n\t"
"vpxor %%xmm12,%%xmm12,%%xmm12\n\t"
"vpxor %%xmm13,%%xmm13,%%xmm13\n\t"
"vpxor %%xmm14,%%xmm14,%%xmm14\n\t"
"vpxor %%xmm15,%%xmm15,%%xmm15\n\t"
".p2align 5\n\t" "1:\n\t"
"vpbroadcastw (%[x0]), %%ymm0\n\t"
"vpbroadcastw (%[x1]), %%ymm1\n\t"
"vmovdqa 0(%[bi]), %%ymm4\n\t"
"vpmaddubsw %%ymm4, %%ymm0, %%ymm5\n\t"
"vpmaddubsw %%ymm4, %%ymm1, %%ymm6\n\t"
"vpaddw %%ymm5, %%ymm8, %%ymm8\n\t"
"vpaddw %%ymm6, %%ymm12, %%ymm12\n\t"
"vmovdqa 32(%[bi]), %%ymm4\n\t"
"vpmaddubsw %%ymm4, %%ymm0, %%ymm5\n\t"
"vpmaddubsw %%ymm4, %%ymm1, %%ymm6\n\t"
"vpaddw %%ymm5, %%ymm9, %%ymm9\n\t"
"vpaddw %%ymm6, %%ymm13, %%ymm13\n\t"
"vmovdqa 64(%[bi]), %%ymm4\n\t"
"vpmaddubsw %%ymm4, %%ymm0, %%ymm5\n\t"
"vpmaddubsw %%ymm4, %%ymm1, %%ymm6\n\t"
"vpaddw %%ymm5, %%ymm10, %%ymm10\n\t"
"vpaddw %%ymm6, %%ymm14, %%ymm14\n\t"
"vmovdqa 96(%[bi]), %%ymm4\n\t"
"vpmaddubsw %%ymm4, %%ymm0, %%ymm5\n\t"
"vpmaddubsw %%ymm4, %%ymm1, %%ymm6\n\t"
"vpaddw %%ymm5, %%ymm11, %%ymm11\n\t"
"vpaddw %%ymm6, %%ymm15, %%ymm15\n\t"
"vpbroadcastw 2(%[x0]), %%ymm0\n\t"
"vpbroadcastw 2(%[x1]), %%ymm1\n\t"
"vmovdqa 128(%[bi]), %%ymm4\n\t"
"vpmaddubsw %%ymm4, %%ymm0, %%ymm5\n\t"
"vpmaddubsw %%ymm4, %%ymm1, %%ymm6\n\t"
"vpaddw %%ymm5, %%ymm8, %%ymm8\n\t"
"vpaddw %%ymm6, %%ymm12, %%ymm12\n\t"
"vmovdqa 160(%[bi]), %%ymm4\n\t"
"vpmaddubsw %%ymm4, %%ymm0, %%ymm5\n\t"
"vpmaddubsw %%ymm4, %%ymm1, %%ymm6\n\t"
"vpaddw %%ymm5, %%ymm9, %%ymm9\n\t"
"vpaddw %%ymm6, %%ymm13, %%ymm13\n\t"
"vmovdqa 192(%[bi]), %%ymm4\n\t"
"vpmaddubsw %%ymm4, %%ymm0, %%ymm5\n\t"
"vpmaddubsw %%ymm4, %%ymm1, %%ymm6\n\t"
"vpaddw %%ymm5, %%ymm10, %%ymm10\n\t"
"vpaddw %%ymm6, %%ymm14, %%ymm14\n\t"
"vmovdqa 224(%[bi]), %%ymm4\n\t"
"vpmaddubsw %%ymm4, %%ymm0, %%ymm5\n\t"
"vpmaddubsw %%ymm4, %%ymm1, %%ymm6\n\t"
"vpaddw %%ymm5, %%ymm11, %%ymm11\n\t"
"vpaddw %%ymm6, %%ymm15, %%ymm15\n\t"
"vpbroadcastw 4(%[x0]), %%ymm0\n\t"
"vpbroadcastw 4(%[x1]), %%ymm1\n\t"
"vmovdqa 256(%[bi]), %%ymm4\n\t"
"vpmaddubsw %%ymm4, %%ymm0, %%ymm5\n\t"
"vpmaddubsw %%ymm4, %%ymm1, %%ymm6\n\t"
"vpaddw %%ymm5, %%ymm8, %%ymm8\n\t"
"vpaddw %%ymm6, %%ymm12, %%ymm12\n\t"
"vmovdqa 288(%[bi]), %%ymm4\n\t"
"vpmaddubsw %%ymm4, %%ymm0, %%ymm5\n\t"
"vpmaddubsw %%ymm4, %%ymm1, %%ymm6\n\t"
"vpaddw %%ymm5, %%ymm9, %%ymm9\n\t"
"vpaddw %%ymm6, %%ymm13, %%ymm13\n\t"
"vmovdqa 320(%[bi]), %%ymm4\n\t"
"vpmaddubsw %%ymm4, %%ymm0, %%ymm5\n\t"
"vpmaddubsw %%ymm4, %%ymm1, %%ymm6\n\t"
"vpaddw %%ymm5, %%ymm10, %%ymm10\n\t"
"vpaddw %%ymm6, %%ymm14, %%ymm14\n\t"
"vmovdqa 352(%[bi]), %%ymm4\n\t"
"vpmaddubsw %%ymm4, %%ymm0, %%ymm5\n\t"
"vpmaddubsw %%ymm4, %%ymm1, %%ymm6\n\t"
"vpaddw %%ymm5, %%ymm11, %%ymm11\n\t"
"vpaddw %%ymm6, %%ymm15, %%ymm15\n\t"
"vpbroadcastw 6(%[x0]), %%ymm0\n\t"
"vpbroadcastw 6(%[x1]), %%ymm1\n\t"
"vmovdqa 384(%[bi]), %%ymm4\n\t"
"vpmaddubsw %%ymm4, %%ymm0, %%ymm5\n\t"
"vpmaddubsw %%ymm4, %%ymm1, %%ymm6\n\t"
"vpaddw %%ymm5, %%ymm8, %%ymm8\n\t"
"vpaddw %%ymm6, %%ymm12, %%ymm12\n\t"
"vmovdqa 416(%[bi]), %%ymm4\n\t"
"vpmaddubsw %%ymm4, %%ymm0, %%ymm5\n\t"
"vpmaddubsw %%ymm4, %%ymm1, %%ymm6\n\t"
"vpaddw %%ymm5, %%ymm9, %%ymm9\n\t"
"vpaddw %%ymm6, %%ymm13, %%ymm13\n\t"
"vmovdqa 448(%[bi]), %%ymm4\n\t"
"vpmaddubsw %%ymm4, %%ymm0, %%ymm5\n\t"
"vpmaddubsw %%ymm4, %%ymm1, %%ymm6\n\t"
"vpaddw %%ymm5, %%ymm10, %%ymm10\n\t"
"vpaddw %%ymm6, %%ymm14, %%ymm14\n\t"
"vmovdqa 480(%[bi]), %%ymm4\n\t"
"vpmaddubsw %%ymm4, %%ymm0, %%ymm5\n\t"
"vpmaddubsw %%ymm4, %%ymm1, %%ymm6\n\t"
"vpaddw %%ymm5, %%ymm11, %%ymm11\n\t"
"vpaddw %%ymm6, %%ymm15, %%ymm15\n\t"
"addq $8, %[x0]\n\t"
"addq $8, %[x1]\n\t"
"addq $512, %[bi]\n\t"
"decq %[cnt]\n\t"
"jnz 1b\n\t"
"vpand %[mask], %%ymm8, %%ymm2\n\t"
"vpand %[mask], %%ymm9, %%ymm3\n\t"
"vpackuswb %%ymm3, %%ymm2, %%ymm2\n\t"
"vpermq $0xD8, %%ymm2, %%ymm2\n\t"
"vmovdqu %%ymm2, 0(%[scr])\n\t"
"vpand %[mask], %%ymm10, %%ymm2\n\t"
"vpand %[mask], %%ymm11, %%ymm3\n\t"
"vpackuswb %%ymm3, %%ymm2, %%ymm2\n\t"
"vpermq $0xD8, %%ymm2, %%ymm2\n\t"
"vmovdqu %%ymm2, 32(%[scr])\n\t"
"vpand %[mask], %%ymm12, %%ymm2\n\t"
"vpand %[mask], %%ymm13, %%ymm3\n\t"
"vpackuswb %%ymm3, %%ymm2, %%ymm2\n\t"
"vpermq $0xD8, %%ymm2, %%ymm2\n\t"
"vmovdqu %%ymm2, 64(%[scr])\n\t"
"vpand %[mask], %%ymm14, %%ymm2\n\t"
"vpand %[mask], %%ymm15, %%ymm3\n\t"
"vpackuswb %%ymm3, %%ymm2, %%ymm2\n\t"
"vpermq $0xD8, %%ymm2, %%ymm2\n\t"
"vmovdqu %%ymm2, 96(%[scr])\n\t"
: [x0]"+r"(x0),[x1]"+r"(x1),[bi]"+r"(bi),[cnt]"+r"(cnt)
: [mask]"m"(W0FF), [scr]"r"(mscr)
: "ymm0","ymm1","ymm2","ymm3","ymm4","ymm5","ymm6","ymm7","ymm8","ymm9","ymm10","ymm11","ymm12","ymm13","ymm14","ymm15","cc","memory");
}
/* ---- corr16 ported to n=2048: W=32, NY=8, 8 accumulators ---- */
#define AVX2BMI __attribute__((target("avx2,bmi")))
static __m256i XT[16][16][8] __attribute__((aligned(64)));
AVX2BMI static void corr16k(int n){
const int W=32;
memset(Pbb,0,(size_t)n*W*8);
const int KB=64;
for (int kb=0; kb<n; kb+=KB){
int w0=kb>>6;
const uint64_t *bw = Bpb + (size_t)w0*(size_t)W*64; /* 64 rows, global bit w0*64+ */
for (int g=0; g<16; g++){
uint64_t *z=(uint64_t*)XT[g][0];
for (int q=0;q<32;q++) z[q]=0;
for (int t=1;t<16;t++){
uint64_t *dst=(uint64_t*)XT[g][t];
int lb=__builtin_ctz(t), t2=t&(t-1);
const uint64_t *src=(const uint64_t*)XT[g][t2];
const uint64_t *row=bw+(size_t)(4*g+lb)*W;
if (t2) for (int q=0;q<32;q++) dst[q]=src[q]^row[q];
else for (int q=0;q<32;q++) dst[q]=row[q];
}
}
for (int i=0;i<n;i++){
uint64_t b0 = A1b[(size_t)i*W + w0];
__m256i a0,a1,a2,a3,a4,a5,a6,a7;
a0=a1=a2=a3=a4=a5=a6=a7=_mm256_setzero_si256();
for (int g=0; g<16; g++){
const __m256i *p = (const __m256i *)XT[g][(b0>>(4*g))&15];
p+=8;
a0=_mm256_xor_si256(a0,_mm256_load_si256(p-8));
a1=_mm256_xor_si256(a1,_mm256_load_si256(p-7));
a2=_mm256_xor_si256(a2,_mm256_load_si256(p-6));
a3=_mm256_xor_si256(a3,_mm256_load_si256(p-5));
a4=_mm256_xor_si256(a4,_mm256_load_si256(p-4));
a5=_mm256_xor_si256(a5,_mm256_load_si256(p-3));
a6=_mm256_xor_si256(a6,_mm256_load_si256(p-2));
a7=_mm256_xor_si256(a7,_mm256_load_si256(p-1));
}
__m256i *o=(__m256i*)(Pbb+(size_t)i*W);
_mm256_store_si256(o+0,_mm256_xor_si256(_mm256_load_si256(o+0),a0));
_mm256_store_si256(o+1,_mm256_xor_si256(_mm256_load_si256(o+1),a1));
_mm256_store_si256(o+2,_mm256_xor_si256(_mm256_load_si256(o+2),a2));
_mm256_store_si256(o+3,_mm256_xor_si256(_mm256_load_si256(o+3),a3));
_mm256_store_si256(o+4,_mm256_xor_si256(_mm256_load_si256(o+4),a4));
_mm256_store_si256(o+5,_mm256_xor_si256(_mm256_load_si256(o+5),a5));
_mm256_store_si256(o+6,_mm256_xor_si256(_mm256_load_si256(o+6),a6));
_mm256_store_si256(o+7,_mm256_xor_si256(_mm256_load_si256(o+7),a7));
}
}
}
/* ---- table-driven epilogue: 4 x (movq table load) instead of the scalar
set1/cmpeq/andnot chain; byte-identical mask, verified by gate. ---- */
static uint8_t EXPT[256*8] __attribute__((aligned(64)));
AVX2 static void epilogue2(int n, int8_t*C, const uint64_t*P, int jb, int i){
static int ei=0;
if(!ei){ for(int v=0;v<256;v++) for(int b=0;b<8;b++) EXPT[v*8+b]=((v>>b)&1)?(uint8_t)0x80:0; ei=1; }
const uint64_t*pw=P+((size_t)i*(n>>3)+(jb>>3))/8;
for(int r=0;r<2;r++){
uint64_t w=pw[(size_t)r*(n>>6)];
for(int t=0;t<2;t++){
uint32_t v=(uint32_t)(w>>(32*t));
__m128i e0=_mm_loadl_epi64((const __m128i*)(EXPT+8*( v &0xFF)));
__m128i e1=_mm_loadl_epi64((const __m128i*)(EXPT+8*((v>>8 )&0xFF)));
__m128i e2=_mm_loadl_epi64((const __m128i*)(EXPT+8*((v>>16)&0xFF)));
__m128i e3=_mm_loadl_epi64((const __m128i*)(EXPT+8*((v>>24)&0xFF)));
__m256i msk=_mm256_set_m128i(_mm_unpacklo_epi64(e2,e3),_mm_unpacklo_epi64(e0,e1));
__m256i vv=_mm256_load_si256((const __m256i*)(mscr+r*64+t*32));
int8_t*c=C+(size_t)(i+r)*n+jb+t*32;
_mm256_stream_si256((__m256i*)c,_mm256_xor_si256(vv,msk));
}
}
}
AVX2 static void epilogue(int n, int8_t*C, const uint64_t*P, int jb, int i);
/* ---- fused builders: read A once (A0b+A1b) and B once (BI3b+Bpb) ---- */
AVX2 static void build_A0A1(int n, const int8_t*A){
const __m256i m=_mm256_set1_epi8(0x7F);
int W=n/64;
for (int i=0;i<n;i++){
const int8_t*row=A+(size_t)i*n;
int8_t*dst=A0b+(size_t)i*n;
uint64_t*w1=A1b+(size_t)i*W;
for (int k=0;k<n;k+=64){
__m256i v0=_mm256_load_si256((const __m256i*)(row+k));
__m256i v1=_mm256_load_si256((const __m256i*)(row+k+32));
_mm256_store_si256((__m256i*)(dst+k), _mm256_and_si256(v0,m));
_mm256_store_si256((__m256i*)(dst+k+32), _mm256_and_si256(v1,m));
w1[k>>6]=(uint64_t)(uint32_t)_mm256_movemask_epi8(v0)
|((uint64_t)(uint32_t)_mm256_movemask_epi8(v1)<<32);
}
}
}
AVX2 static void build_BI3Bp(int n, const int8_t*B){
const __m256i one=_mm256_set1_epi8(1);
int ng=n/64, W=n/64;
for (int p=0;p<n/2;p++){
const int8_t *r0=B+(size_t)(2*p)*n, *r1=r0+n;
uint64_t *w0p=Bpb+(size_t)(2*p)*W, *w1p=Bpb+(size_t)(2*p+1)*W;
for (int g=0;g<ng;g++){
const int8_t *a=r0+64*g, *b=r1+64*g;
int8_t *o=BI3b+((size_t)g*(n/2)+p)*128;
for (int t=0;t<64;t+=32){
__m256i va=_mm256_load_si256((const __m256i*)(a+t));
__m256i vb=_mm256_load_si256((const __m256i*)(b+t));
__m256i lo=_mm256_unpacklo_epi8(va,vb), hi=_mm256_unpackhi_epi8(va,vb);
_mm256_store_si256((__m256i*)(o+2*t), _mm256_permute2x128_si256(lo,hi,0x20));
_mm256_store_si256((__m256i*)(o+2*t+32), _mm256_permute2x128_si256(lo,hi,0x31));
uint32_t m0=(uint32_t)_mm256_movemask_epi8(_mm256_slli_epi16(_mm256_and_si256(va,one),7));
uint32_t m1=(uint32_t)_mm256_movemask_epi8(_mm256_slli_epi16(_mm256_and_si256(vb,one),7));
if(t==0) { w0p[g]=(uint64_t)m0; w1p[g]=(uint64_t)m1; }
else { w0p[g]|=(uint64_t)m0<<32; w1p[g]|=(uint64_t)m1<<32; }
}
}
}
}
/* forward decls */
AVX2 static void build_A0(int n,const int8_t*A);
AVX2 static void build_BI3(int n,const int8_t*B);
/* ================= STRASSEN LEVEL 1 (n = 2048) ================= */
static int8_t MMS[7][1024*1024] __attribute__((aligned(64)));
/* ★ 本发新增:一个"子块描述符" = 从 X 取块 A(r0,c0) 与 Y 取块 B(r1,c1) 按 op 组合
(0 copy / 1 add / 2 sub,mod 256),行列都以 `nn` 为跨距。
★ 它替换掉的正是 [1] 里 `blk()` 写到 SA/SB 再被 `build_*` 读回来的那两步。 */
struct SBLK { const int8_t *X, *Y; int r0, c0, r1, c1, op; };
AVX2 static inline __m256i sblk_cmb(__m256i v, const int8_t *ya, int op){
if (!op) return v;
__m256i u = _mm256_load_si256((const __m256i*)ya);
return (op==1) ? _mm256_add_epi8(v,u) : _mm256_sub_epi8(v,u);
}
/* bld_A = `blk` + `build_A0A1` 融合:一趟产出 A0b(=v&0x7F) 与 A1b(=符号位)。 */
AVX2 static void bld_A(int m, int nn, const SBLK*b){
const __m256i msk=_mm256_set1_epi8(0x7F);
int W=m/64;
for (int i=0;i<m;i++){
const int8_t*xa=b->X+(size_t)(b->r0+i)*nn+b->c0;
const int8_t*ya=b->Y+(size_t)(b->r1+i)*nn+b->c1;
int8_t*dst=A0b+(size_t)i*m;
uint64_t*w1=A1b+(size_t)i*W;
for (int k=0;k<m;k+=64){
__m256i v0=_mm256_load_si256((const __m256i*)(xa+k));
__m256i v1=_mm256_load_si256((const __m256i*)(xa+k+32));
v0=sblk_cmb(v0,ya+k, b->op);
v1=sblk_cmb(v1,ya+k+32,b->op);
_mm256_store_si256((__m256i*)(dst+k), _mm256_and_si256(v0,msk));
_mm256_store_si256((__m256i*)(dst+k+32), _mm256_and_si256(v1,msk));
w1[k>>6]=(uint64_t)(uint32_t)_mm256_movemask_epi8(v0)
|((uint64_t)(uint32_t)_mm256_movemask_epi8(v1)<<32);
}
}
}
/* bld_B = `blk` + `build_BI3Bp` 融合:一趟产出 BI3b(交织对) 与 Bpb(=B&1)。 */
AVX2 static void bld_B(int m, int nn, const SBLK*b){
const __m256i one=_mm256_set1_epi8(1);
int ng=m/64, W=m/64;
for (int p=0;p<m/2;p++){
const int8_t *ax=b->X+(size_t)(b->r0+2*p)*nn+b->c0;
const int8_t *bx=ax+nn;
const int8_t *ay=b->Y+(size_t)(b->r1+2*p)*nn+b->c1;
const int8_t *by=ay+nn;
uint64_t *w0p=Bpb+(size_t)(2*p)*W, *w1p=Bpb+(size_t)(2*p+1)*W;
for (int g=0;g<ng;g++){
const int8_t *a=ax+64*g, *c=bx+64*g;
const int8_t *d=ay+64*g, *e=by+64*g;
int8_t *o=BI3b+((size_t)g*(m/2)+p)*128;
for (int t=0;t<64;t+=32){
__m256i va=sblk_cmb(_mm256_load_si256((const __m256i*)(a+t)), d+t, b->op);
__m256i vb=sblk_cmb(_mm256_load_si256((const __m256i*)(c+t)), e+t, b->op);
__m256i lo=_mm256_unpacklo_epi8(va,vb), hi=_mm256_unpackhi_epi8(va,vb);
_mm256_store_si256((__m256i*)(o+2*t), _mm256_permute2x128_si256(lo,hi,0x20));
_mm256_store_si256((__m256i*)(o+2*t+32), _mm256_permute2x128_si256(lo,hi,0x31));
uint32_t m0=(uint32_t)_mm256_movemask_epi8(_mm256_slli_epi16(_mm256_and_si256(va,one),7));
uint32_t m1=(uint32_t)_mm256_movemask_epi8(_mm256_slli_epi16(_mm256_and_si256(vb,one),7));
if(t==0) { w0p[g]=(uint64_t)m0; w1p[g]=(uint64_t)m1; }
else { w0p[g]|=(uint64_t)m0<<32; w1p[g]|=(uint64_t)m1<<32; }
}
}
}
}
/* GF(2) correction for m=1024: W=16, NY=4, 4 accumulators (corr16k hardcodes W=32) */
#define AVX2BMI3 __attribute__((target("avx2,bmi")))
static __m256i XT4[16][16][4] __attribute__((aligned(64)));
AVX2BMI3 static void corr1024(void){
const int n=1024, W=16;
memset(Pbb,0,(size_t)n*W*8);
const int KB=64;
for (int kb=0; kb<n; kb+=KB){
int w0=kb>>6;
const uint64_t *bw = Bpb + (size_t)w0*(size_t)W*64;
for (int g=0; g<16; g++){
uint64_t *z=(uint64_t*)XT4[g][0];
for (int q=0;q<16;q++) z[q]=0;
for (int t=1;t<16;t++){
uint64_t *dst=(uint64_t*)XT4[g][t];
int lb=__builtin_ctz(t), t2=t&(t-1);
const uint64_t *src=(const uint64_t*)XT4[g][t2];
const uint64_t *row=bw+(size_t)(4*g+lb)*W;
if (t2) for (int q=0;q<16;q++) dst[q]=src[q]^row[q];
else for (int q=0;q<16;q++) dst[q]=row[q];
}
}
for (int i=0;i<n;i++){
uint64_t b0 = A1b[(size_t)i*W + w0];
__m256i a0,a1,a2,a3;
a0=a1=a2=a3=_mm256_setzero_si256();
for (int g=0; g<16; g++){
const __m256i *p = (const __m256i *)XT4[g][(b0>>(4*g))&15];
p+=4;
a0=_mm256_xor_si256(a0,_mm256_load_si256(p-4));
a1=_mm256_xor_si256(a1,_mm256_load_si256(p-3));
a2=_mm256_xor_si256(a2,_mm256_load_si256(p-2));
a3=_mm256_xor_si256(a3,_mm256_load_si256(p-1));
}
__m256i *o=(__m256i*)(Pbb+(size_t)i*W);
_mm256_store_si256(o+0,_mm256_xor_si256(_mm256_load_si256(o+0),a0));
_mm256_store_si256(o+1,_mm256_xor_si256(_mm256_load_si256(o+1),a1));
_mm256_store_si256(o+2,_mm256_xor_si256(_mm256_load_si256(o+2),a2));
_mm256_store_si256(o+3,_mm256_xor_si256(_mm256_load_si256(o+3),a3));
}
}
}
/* one 1024x1024 sub-product through the SHIPPED pipeline, result to Cp.
★ 本发:入口从 (SA,SB) 改成两个子块描述符,面板由 `bld_A`/`bld_B` 直接建出。 */
AVX2 static void submm1024(const SBLK*ba, const SBLK*bb, int nn, int8_t*Cp){
const int m=1024;
bld_A(m,nn,ba); bld_B(m,nn,bb); corr1024();
for (int g=0, jbg=0; g<m; g+=64, jbg=g)
for (int i=0; i<m; i+=2){
mk_s(m, A0b+(size_t)i*m, BI3b+(size_t)(g>>6)*(m/2)*128, Cp, PBb, g);
epilogue2(m, Cp, (const uint64_t*)Pbb, g, i);
}
}
static const int SAB_T[7][5] = {
{0,0, 1,1, 1}, /* A11+A22 */
{1,0, 1,1, 1}, /* A21+A22 */
{0,0, 0,0, 0}, /* A11 */
{1,1, 1,1, 0}, /* A22 */
{0,0, 0,1, 1}, /* A11+A12 */
{1,0, 0,0, 2}, /* A21-A11 */
{0,1, 1,1, 2}, /* A12-A22 */
};
static const int SBB_T[7][5] = {
{0,0, 1,1, 1}, /* B11+B22 */
{0,0, 0,0, 0}, /* B11 */
{0,1, 1,1, 2}, /* B12-B22 */
{1,0, 0,0, 2}, /* B21-B11 */
{1,1, 1,1, 0}, /* B22 */
{0,0, 0,1, 1}, /* B11+B12 */
{1,0, 1,1, 1}, /* B21+B22 */
};
/* Cblk += sum_k s_k * M_k (k over the up-to-4 pointers; NULL skips a term) */
AVX2 static void cmb(int8_t*C, int n, int r0, int c0, int m,
const int8_t*M0,int s0,const int8_t*M1,int s1,
const int8_t*M2,int s2,const int8_t*M3,int s3){
for (int i=0;i<m;i++){
int8_t *d = C + (size_t)(r0+i)*n + c0;
const int8_t *p0 = M0 ? M0+(size_t)i*m : 0;
const int8_t *p1 = M1 ? M1+(size_t)i*m : 0;
const int8_t *p2 = M2 ? M2+(size_t)i*m : 0;
const int8_t *p3 = M3 ? M3+(size_t)i*m : 0;
for (int j=0;j<m;j+=32){
__m256i v;
if (p0) v = s0>0 ? _mm256_load_si256((const __m256i*)(p0+j)) : _mm256_sub_epi8(_mm256_setzero_si256(),_mm256_load_si256((const __m256i*)(p0+j)));
else v = _mm256_setzero_si256();
if (p1){ __m256i t=_mm256_load_si256((const __m256i*)(p1+j));
v = _mm256_add_epi8(v, s1>0?t:_mm256_sub_epi8(_mm256_setzero_si256(),t)); }
if (p2){ __m256i t=_mm256_load_si256((const __m256i*)(p2+j));
v = _mm256_add_epi8(v, s2>0?t:_mm256_sub_epi8(_mm256_setzero_si256(),t)); }
if (p3){ __m256i t=_mm256_load_si256((const __m256i*)(p3+j));
v = _mm256_add_epi8(v, s3>0?t:_mm256_sub_epi8(_mm256_setzero_si256(),t)); }
_mm256_stream_si256((__m256i*)(d+j), v);
}
}
}
/* ★ 本发:把 [1] 的 switch 逐条改写成"子块对"表(同一组 (r0,c0,r1,c1,op),单位 = o = m)。
第 i 行与 [1] 的 case i 一一对应(右侧注释保留原文的分块名)。 */
/* ================= mc4_: TWO-LEVEL STRASSEN, (c) 4-TERM SIGNED-COMPOSE PACKER ===========
Leaf (k1,k2) of the second level needs, on the A side,
S2A = (A1 op1 A2) op2 (A3 op1 A4)
where op1 is the LEVEL-1 case k1 and op2 the LEVEL-2 case k2. Writing s1/s2 for the
op -> sign map (op 0 -> 0, 1 -> +1, 2 -> -1),
S2A = A1 + s1*A2 + s2*A3 + s2*s1*A4
so the packer reads A's four blocks DIRECTLY. Nothing is materialised: no SA/SB and
no S2A/S2B (BRIEF 2.18.590, DIF -- never write it out and read it back).
h = leaf size (512), n = A's row stride (2048), o1 = level-1 block size (1024). */
static __m256i XT4s[16][16][2] __attribute__((aligned(64))); /* corr table for n = 512 */
static inline int sgn_of(int op){ return op==0 ? 0 : (op==1 ? 1 : -1); }
AVX2 static void buildA4(int h, int n, const int8_t*A, int k1, int k2){
const __m256i msk=_mm256_set1_epi8(0x7F);
const int o1 = 1024;
const int *t1=SAB_T[k1], *t2=SAB_T[k2];
const int s1=sgn_of(t1[4]), s2=sgn_of(t2[4]), s12=s1*s2;
const size_t R1=(size_t)(t1[0]*o1+t2[0]*h)*n + t1[1]*o1+t2[1]*h;
const size_t R2=(size_t)(t1[2]*o1+t2[0]*h)*n + t1[3]*o1+t2[1]*h;
const size_t R3=(size_t)(t1[0]*o1+t2[2]*h)*n + t1[1]*o1+t2[3]*h;
const size_t R4=(size_t)(t1[2]*o1+t2[2]*h)*n + t1[3]*o1+t2[3]*h;
int W=h/64;
for (int i=0;i<h;i++){
const int8_t*p1=A+R1+(size_t)i*n;
const int8_t*p2=A+R2+(size_t)i*n;
const int8_t*p3=A+R3+(size_t)i*n;
const int8_t*p4=A+R4+(size_t)i*n;
int8_t*dst=A0b+(size_t)i*h;
uint64_t*w1=A1b+(size_t)i*W;
for (int k=0;k<h;k+=64){
_mm_prefetch((const char*)(p1+k+4096), _MM_HINT_T0);
_mm_prefetch((const char*)(p1+k+32+4096), _MM_HINT_T0);
_mm_prefetch((const char*)(p2+k+4096), _MM_HINT_T0);
_mm_prefetch((const char*)(p3+k+4096), _MM_HINT_T0);
_mm_prefetch((const char*)(p4+k+4096), _MM_HINT_T0);
__m256i v0=_mm256_load_si256((const __m256i*)(p1+k));
__m256i v1=_mm256_load_si256((const __m256i*)(p1+k+32));
if(s1){ __m256i u0=_mm256_load_si256((const __m256i*)(p2+k));
__m256i u1=_mm256_load_si256((const __m256i*)(p2+k+32));
if(s1>0){v0=_mm256_add_epi8(v0,u0);v1=_mm256_add_epi8(v1,u1);}
else {v0=_mm256_sub_epi8(v0,u0);v1=_mm256_sub_epi8(v1,u1);} }
if(s2){ __m256i u0=_mm256_load_si256((const __m256i*)(p3+k));
__m256i u1=_mm256_load_si256((const __m256i*)(p3+k+32));
if(s2>0){v0=_mm256_add_epi8(v0,u0);v1=_mm256_add_epi8(v1,u1);}
else {v0=_mm256_sub_epi8(v0,u0);v1=_mm256_sub_epi8(v1,u1);} }
if(s12){__m256i u0=_mm256_load_si256((const __m256i*)(p4+k));
__m256i u1=_mm256_load_si256((const __m256i*)(p4+k+32));
if(s12>0){v0=_mm256_add_epi8(v0,u0);v1=_mm256_add_epi8(v1,u1);}
else {v0=_mm256_sub_epi8(v0,u0);v1=_mm256_sub_epi8(v1,u1);} }
_mm256_store_si256((__m256i*)(dst+k), _mm256_and_si256(v0,msk));
_mm256_store_si256((__m256i*)(dst+k+32), _mm256_and_si256(v1,msk));
w1[k>>6]=(uint64_t)(uint32_t)_mm256_movemask_epi8(v0)
|((uint64_t)(uint32_t)_mm256_movemask_epi8(v1)<<32);
}
}
}
AVX2 static void buildB4(int h, int n, const int8_t*B, int k1, int k2){
const __m256i one=_mm256_set1_epi8(1);
const int o1 = 1024;
const int *t1=SBB_T[k1], *t2=SBB_T[k2];
const int s1=sgn_of(t1[4]), s2=sgn_of(t2[4]), s12=s1*s2;
const size_t R1=(size_t)(t1[0]*o1+t2[0]*h)*n + t1[1]*o1+t2[1]*h;
const size_t R2=(size_t)(t1[2]*o1+t2[0]*h)*n + t1[3]*o1+t2[1]*h;
const size_t R3=(size_t)(t1[0]*o1+t2[2]*h)*n + t1[1]*o1+t2[3]*h;
const size_t R4=(size_t)(t1[2]*o1+t2[2]*h)*n + t1[3]*o1+t2[3]*h;
int ng=h/64, W=h/64;
for (int p=0;p<h/2;p++){
const int8_t *a1=B+R1+(size_t)(2*p)*n, *b1=B+R1+(size_t)(2*p+1)*n;
const int8_t *a2=B+R2+(size_t)(2*p)*n, *b2=B+R2+(size_t)(2*p+1)*n;
const int8_t *a3=B+R3+(size_t)(2*p)*n, *b3=B+R3+(size_t)(2*p+1)*n;
const int8_t *a4=B+R4+(size_t)(2*p)*n, *b4=B+R4+(size_t)(2*p+1)*n;
uint64_t *w0p=Bpb+(size_t)(2*p)*W, *w1p=Bpb+(size_t)(2*p+1)*W;
for (int g=0;g<ng;g++){
int8_t *o=BI3b+((size_t)g*((h/2)*128+512)+p*128);
for (int t=0;t<64;t+=32){
_mm_prefetch((const char*)(a1+64*g+t+4096), _MM_HINT_T0);
_mm_prefetch((const char*)(b1+64*g+t+4096), _MM_HINT_T0);
_mm_prefetch((const char*)(a2+64*g+t+4096), _MM_HINT_T0);
_mm_prefetch((const char*)(a3+64*g+t+4096), _MM_HINT_T0);
_mm_prefetch((const char*)(a4+64*g+t+4096), _MM_HINT_T0);
_mm_prefetch((const char*)(b2+64*g+t+4096), _MM_HINT_T0);
_mm_prefetch((const char*)(b3+64*g+t+4096), _MM_HINT_T0);
_mm_prefetch((const char*)(b4+64*g+t+4096), _MM_HINT_T0);
__m256i va=_mm256_load_si256((const __m256i*)(a1+64*g+t));
__m256i vb=_mm256_load_si256((const __m256i*)(b1+64*g+t));
if(s1){ __m256i ua=_mm256_load_si256((const __m256i*)(a2+64*g+t));
__m256i ub=_mm256_load_si256((const __m256i*)(b2+64*g+t));
if(s1>0){va=_mm256_add_epi8(va,ua);vb=_mm256_add_epi8(vb,ub);}
else {va=_mm256_sub_epi8(va,ua);vb=_mm256_sub_epi8(vb,ub);} }
if(s2){ __m256i ua=_mm256_load_si256((const __m256i*)(a3+64*g+t));
__m256i ub=_mm256_load_si256((const __m256i*)(b3+64*g+t));
if(s2>0){va=_mm256_add_epi8(va,ua);vb=_mm256_add_epi8(vb,ub);}
else {va=_mm256_sub_epi8(va,ua);vb=_mm256_sub_epi8(vb,ub);} }
if(s12){__m256i ua=_mm256_load_si256((const __m256i*)(a4+64*g+t));
__m256i ub=_mm256_load_si256((const __m256i*)(b4+64*g+t));
if(s12>0){va=_mm256_add_epi8(va,ua);vb=_mm256_add_epi8(vb,ub);}
else {va=_mm256_sub_epi8(va,ua);vb=_mm256_sub_epi8(vb,ub);} }
__m256i lo=_mm256_unpacklo_epi8(va,vb), hi=_mm256_unpackhi_epi8(va,vb);
_mm256_store_si256((__m256i*)(o+2*t), _mm256_permute2x128_si256(lo,hi,0x20));
_mm256_store_si256((__m256i*)(o+2*t+32), _mm256_permute2x128_si256(lo,hi,0x31));
uint32_t m0=(uint32_t)_mm256_movemask_epi8(_mm256_slli_epi16(_mm256_and_si256(va,one),7));
uint32_t m1=(uint32_t)_mm256_movemask_epi8(_mm256_slli_epi16(_mm256_and_si256(vb,one),7));
if(t==0) { w0p[g]=(uint64_t)m0; w1p[g]=(uint64_t)m1; }
else { w0p[g]|=(uint64_t)m0<<32; w1p[g]|=(uint64_t)m1<<32; }
}
}
}
}
/* k1=0: 8 distinct A blocks -> all 7 A panels in one pass */
AVX2 static void bldAw0(int h, const int8_t*A){
const __m256i msk=_mm256_set1_epi8(0x7F);
const int W=h>>6;
for (int r=0;r<h;r++){
const int8_t*ap=A+(size_t)r*2048;
int8_t*d=A0b7+(size_t)r*h;
uint64_t*wp=A1b7+(size_t)r*W;
for (int k=0;k<h;k+=64){
_mm_prefetch((const char*)(ap+k+4096+0), _MM_HINT_T0);
_mm_prefetch((const char*)(ap+k+4096+2098176), _MM_HINT_T0);
_mm_prefetch((const char*)(ap+k+4096+1049088), _MM_HINT_T0);
_mm_prefetch((const char*)(ap+k+4096+3147264), _MM_HINT_T0);
_mm_prefetch((const char*)(ap+k+4096+1048576), _MM_HINT_T0);
_mm_prefetch((const char*)(ap+k+4096+3146752), _MM_HINT_T0);
_mm_prefetch((const char*)(ap+k+4096+512), _MM_HINT_T0);
_mm_prefetch((const char*)(ap+k+4096+2098688), _MM_HINT_T0);
__m256i a0=LD(ap+k+0),a1=LD(ap+k+2098176),a2=LD(ap+k+1049088),a3=LD(ap+k+3147264),a4=LD(ap+k+1048576),a5=LD(ap+k+3146752),a6=LD(ap+k+512),a7=LD(ap+k+2098688);
uint32_t m0,m1,m2,m3,m4,m5,m6;
{ __m256i v=_mm256_add_epi8(_mm256_add_epi8(_mm256_add_epi8(a0,a1),a2),a3); _mm256_store_si256((__m256i*)(d+0+k),_mm256_and_si256(v,msk)); m0=(uint32_t)_mm256_movemask_epi8(v); }
{ __m256i v=_mm256_add_epi8(_mm256_add_epi8(_mm256_add_epi8(a4,a5),a2),a3); _mm256_store_si256((__m256i*)(d+262656+k),_mm256_and_si256(v,msk)); m1=(uint32_t)_mm256_movemask_epi8(v); }
{ __m256i v=_mm256_add_epi8(a0,a1); _mm256_store_si256((__m256i*)(d+525312+k),_mm256_and_si256(v,msk)); m2=(uint32_t)_mm256_movemask_epi8(v); }
{ __m256i v=_mm256_add_epi8(a2,a3); _mm256_store_si256((__m256i*)(d+787968+k),_mm256_and_si256(v,msk)); m3=(uint32_t)_mm256_movemask_epi8(v); }
{ __m256i v=_mm256_add_epi8(_mm256_add_epi8(_mm256_add_epi8(a0,a1),a6),a7); _mm256_store_si256((__m256i*)(d+1050624+k),_mm256_and_si256(v,msk)); m4=(uint32_t)_mm256_movemask_epi8(v); }
{ __m256i v=_mm256_sub_epi8(_mm256_sub_epi8(_mm256_add_epi8(a4,a5),a0),a1); _mm256_store_si256((__m256i*)(d+1313280+k),_mm256_and_si256(v,msk)); m5=(uint32_t)_mm256_movemask_epi8(v); }
{ __m256i v=_mm256_sub_epi8(_mm256_sub_epi8(_mm256_add_epi8(a6,a7),a2),a3); _mm256_store_si256((__m256i*)(d+1575936+k),_mm256_and_si256(v,msk)); m6=(uint32_t)_mm256_movemask_epi8(v); }
__m256i b0=LD(ap+k+32+0),b1=LD(ap+k+32+2098176),b2=LD(ap+k+32+1049088),b3=LD(ap+k+32+3147264),b4=LD(ap+k+32+1048576),b5=LD(ap+k+32+3146752),b6=LD(ap+k+32+512),b7=LD(ap+k+32+2098688);
{ __m256i v=_mm256_add_epi8(_mm256_add_epi8(_mm256_add_epi8(b0,b1),b2),b3); _mm256_store_si256((__m256i*)(d+0+k+32),_mm256_and_si256(v,msk)); wp[0+(k>>6)]=m0|((uint64_t)(uint32_t)_mm256_movemask_epi8(v)<<32); }
{ __m256i v=_mm256_add_epi8(_mm256_add_epi8(_mm256_add_epi8(b4,b5),b2),b3); _mm256_store_si256((__m256i*)(d+262656+k+32),_mm256_and_si256(v,msk)); wp[4104+(k>>6)]=m1|((uint64_t)(uint32_t)_mm256_movemask_epi8(v)<<32); }
{ __m256i v=_mm256_add_epi8(b0,b1); _mm256_store_si256((__m256i*)(d+525312+k+32),_mm256_and_si256(v,msk)); wp[8208+(k>>6)]=m2|((uint64_t)(uint32_t)_mm256_movemask_epi8(v)<<32); }
{ __m256i v=_mm256_add_epi8(b2,b3); _mm256_store_si256((__m256i*)(d+787968+k+32),_mm256_and_si256(v,msk)); wp[12312+(k>>6)]=m3|((uint64_t)(uint32_t)_mm256_movemask_epi8(v)<<32); }
{ __m256i v=_mm256_add_epi8(_mm256_add_epi8(_mm256_add_epi8(b0,b1),b6),b7); _mm256_store_si256((__m256i*)(d+1050624+k+32),_mm256_and_si256(v,msk)); wp[16416+(k>>6)]=m4|((uint64_t)(uint32_t)_mm256_movemask_epi8(v)<<32); }
{ __m256i v=_mm256_sub_epi8(_mm256_sub_epi8(_mm256_add_epi8(b4,b5),b0),b1); _mm256_store_si256((__m256i*)(d+1313280+k+32),_mm256_and_si256(v,msk)); wp[20520+(k>>6)]=m5|((uint64_t)(uint32_t)_mm256_movemask_epi8(v)<<32); }
{ __m256i v=_mm256_sub_epi8(_mm256_sub_epi8(_mm256_add_epi8(b6,b7),b2),b3); _mm256_store_si256((__m256i*)(d+1575936+k+32),_mm256_and_si256(v,msk)); wp[24624+(k>>6)]=m6|((uint64_t)(uint32_t)_mm256_movemask_epi8(v)<<32); }
}
}
}
/* k1=1: 8 distinct A blocks -> all 7 A panels in one pass */
AVX2 static void bldAw1(int h, const int8_t*A){
const __m256i msk=_mm256_set1_epi8(0x7F);
const int W=h>>6;
for (int r=0;r<h;r++){
const int8_t*ap=A+(size_t)r*2048;
int8_t*d=A0b7+(size_t)r*h;
uint64_t*wp=A1b7+(size_t)r*W;
for (int k=0;k<h;k+=64){
_mm_prefetch((const char*)(ap+k+4096+2097152), _MM_HINT_T0);
_mm_prefetch((const char*)(ap+k+4096+2098176), _MM_HINT_T0);
_mm_prefetch((const char*)(ap+k+4096+3146240), _MM_HINT_T0);
_mm_prefetch((const char*)(ap+k+4096+3147264), _MM_HINT_T0);
_mm_prefetch((const char*)(ap+k+4096+3145728), _MM_HINT_T0);
_mm_prefetch((const char*)(ap+k+4096+3146752), _MM_HINT_T0);
_mm_prefetch((const char*)(ap+k+4096+2097664), _MM_HINT_T0);
_mm_prefetch((const char*)(ap+k+4096+2098688), _MM_HINT_T0);
__m256i a0=LD(ap+k+2097152),a1=LD(ap+k+2098176),a2=LD(ap+k+3146240),a3=LD(ap+k+3147264),a4=LD(ap+k+3145728),a5=LD(ap+k+3146752),a6=LD(ap+k+2097664),a7=LD(ap+k+2098688);
uint32_t m0,m1,m2,m3,m4,m5,m6;
{ __m256i v=_mm256_add_epi8(_mm256_add_epi8(_mm256_add_epi8(a0,a1),a2),a3); _mm256_store_si256((__m256i*)(d+0+k),_mm256_and_si256(v,msk)); m0=(uint32_t)_mm256_movemask_epi8(v); }
{ __m256i v=_mm256_add_epi8(_mm256_add_epi8(_mm256_add_epi8(a4,a5),a2),a3); _mm256_store_si256((__m256i*)(d+262656+k),_mm256_and_si256(v,msk)); m1=(uint32_t)_mm256_movemask_epi8(v); }
{ __m256i v=_mm256_add_epi8(a0,a1); _mm256_store_si256((__m256i*)(d+525312+k),_mm256_and_si256(v,msk)); m2=(uint32_t)_mm256_movemask_epi8(v); }
{ __m256i v=_mm256_add_epi8(a2,a3); _mm256_store_si256((__m256i*)(d+787968+k),_mm256_and_si256(v,msk)); m3=(uint32_t)_mm256_movemask_epi8(v); }
{ __m256i v=_mm256_add_epi8(_mm256_add_epi8(_mm256_add_epi8(a0,a1),a6),a7); _mm256_store_si256((__m256i*)(d+1050624+k),_mm256_and_si256(v,msk)); m4=(uint32_t)_mm256_movemask_epi8(v); }
{ __m256i v=_mm256_sub_epi8(_mm256_sub_epi8(_mm256_add_epi8(a4,a5),a0),a1); _mm256_store_si256((__m256i*)(d+1313280+k),_mm256_and_si256(v,msk)); m5=(uint32_t)_mm256_movemask_epi8(v); }
{ __m256i v=_mm256_sub_epi8(_mm256_sub_epi8(_mm256_add_epi8(a6,a7),a2),a3); _mm256_store_si256((__m256i*)(d+1575936+k),_mm256_and_si256(v,msk)); m6=(uint32_t)_mm256_movemask_epi8(v); }
__m256i b0=LD(ap+k+32+2097152),b1=LD(ap+k+32+2098176),b2=LD(ap+k+32+3146240),b3=LD(ap+k+32+3147264),b4=LD(ap+k+32+3145728),b5=LD(ap+k+32+3146752),b6=LD(ap+k+32+2097664),b7=LD(ap+k+32+2098688);
{ __m256i v=_mm256_add_epi8(_mm256_add_epi8(_mm256_add_epi8(b0,b1),b2),b3); _mm256_store_si256((__m256i*)(d+0+k+32),_mm256_and_si256(v,msk)); wp[0+(k>>6)]=m0|((uint64_t)(uint32_t)_mm256_movemask_epi8(v)<<32); }
{ __m256i v=_mm256_add_epi8(_mm256_add_epi8(_mm256_add_epi8(b4,b5),b2),b3); _mm256_store_si256((__m256i*)(d+262656+k+32),_mm256_and_si256(v,msk)); wp[4104+(k>>6)]=m1|((uint64_t)(uint32_t)_mm256_movemask_epi8(v)<<32); }
{ __m256i v=_mm256_add_epi8(b0,b1); _mm256_store_si256((__m256i*)(d+525312+k+32),_mm256_and_si256(v,msk)); wp[8208+(k>>6)]=m2|((uint64_t)(uint32_t)_mm256_movemask_epi8(v)<<32); }
{ __m256i v=_mm256_add_epi8(b2,b3); _mm256_store_si256((__m256i*)(d+787968+k+32),_mm256_and_si256(v,msk)); wp[12312+(k>>6)]=m3|((uint64_t)(uint32_t)_mm256_movemask_epi8(v)<<32); }
{ __m256i v=_mm256_add_epi8(_mm256_add_epi8(_mm256_add_epi8(b0,b1),b6),b7); _mm256_store_si256((__m256i*)(d+1050624+k+32),_mm256_and_si256(v,msk)); wp[16416+(k>>6)]=m4|((uint64_t)(uint32_t)_mm256_movemask_epi8(v)<<32); }
{ __m256i v=_mm256_sub_epi8(_mm256_sub_epi8(_mm256_add_epi8(b4,b5),b0),b1); _mm256_store_si256((__m256i*)(d+1313280+k+32),_mm256_and_si256(v,msk)); wp[20520+(k>>6)]=m5|((uint64_t)(uint32_t)_mm256_movemask_epi8(v)<<32); }
{ __m256i v=_mm256_sub_epi8(_mm256_sub_epi8(_mm256_add_epi8(b6,b7),b2),b3); _mm256_store_si256((__m256i*)(d+1575936+k+32),_mm256_and_si256(v,msk)); wp[24624+(k>>6)]=m6|((uint64_t)(uint32_t)_mm256_movemask_epi8(v)<<32); }
}
}
}
/* k1=2: 4 distinct A blocks -> all 7 A panels in one pass */
AVX2 static void bldAw2(int h, const int8_t*A){
const __m256i msk=_mm256_set1_epi8(0x7F);
const int W=h>>6;
for (int r=0;r<h;r++){
const int8_t*ap=A+(size_t)r*2048;
int8_t*d=A0b7+(size_t)r*h;
uint64_t*wp=A1b7+(size_t)r*W;
for (int k=0;k<h;k+=64){
_mm_prefetch((const char*)(ap+k+4096+0), _MM_HINT_T0);
_mm_prefetch((const char*)(ap+k+4096+1049088), _MM_HINT_T0);
_mm_prefetch((const char*)(ap+k+4096+1048576), _MM_HINT_T0);
_mm_prefetch((const char*)(ap+k+4096+512), _MM_HINT_T0);
__m256i a0=LD(ap+k+0),a1=LD(ap+k+1049088),a2=LD(ap+k+1048576),a3=LD(ap+k+512);
uint32_t m0,m1,m2,m3,m4,m5,m6;
{ __m256i v=_mm256_add_epi8(a0,a1); _mm256_store_si256((__m256i*)(d+0+k),_mm256_and_si256(v,msk)); m0=(uint32_t)_mm256_movemask_epi8(v); }
{ __m256i v=_mm256_add_epi8(a2,a1); _mm256_store_si256((__m256i*)(d+262656+k),_mm256_and_si256(v,msk)); m1=(uint32_t)_mm256_movemask_epi8(v); }
{ __m256i v=a0; _mm256_store_si256((__m256i*)(d+525312+k),_mm256_and_si256(v,msk)); m2=(uint32_t)_mm256_movemask_epi8(v); }
{ __m256i v=a1; _mm256_store_si256((__m256i*)(d+787968+k),_mm256_and_si256(v,msk)); m3=(uint32_t)_mm256_movemask_epi8(v); }
{ __m256i v=_mm256_add_epi8(a0,a3); _mm256_store_si256((__m256i*)(d+1050624+k),_mm256_and_si256(v,msk)); m4=(uint32_t)_mm256_movemask_epi8(v); }
{ __m256i v=_mm256_sub_epi8(a2,a0); _mm256_store_si256((__m256i*)(d+1313280+k),_mm256_and_si256(v,msk)); m5=(uint32_t)_mm256_movemask_epi8(v); }
{ __m256i v=_mm256_sub_epi8(a3,a1); _mm256_store_si256((__m256i*)(d+1575936+k),_mm256_and_si256(v,msk)); m6=(uint32_t)_mm256_movemask_epi8(v); }
__m256i b0=LD(ap+k+32+0),b1=LD(ap+k+32+1049088),b2=LD(ap+k+32+1048576),b3=LD(ap+k+32+512);
{ __m256i v=_mm256_add_epi8(b0,b1); _mm256_store_si256((__m256i*)(d+0+k+32),_mm256_and_si256(v,msk)); wp[0+(k>>6)]=m0|((uint64_t)(uint32_t)_mm256_movemask_epi8(v)<<32); }
{ __m256i v=_mm256_add_epi8(b2,b1); _mm256_store_si256((__m256i*)(d+262656+k+32),_mm256_and_si256(v,msk)); wp[4104+(k>>6)]=m1|((uint64_t)(uint32_t)_mm256_movemask_epi8(v)<<32); }
{ __m256i v=b0; _mm256_store_si256((__m256i*)(d+525312+k+32),_mm256_and_si256(v,msk)); wp[8208+(k>>6)]=m2|((uint64_t)(uint32_t)_mm256_movemask_epi8(v)<<32); }
{ __m256i v=b1; _mm256_store_si256((__m256i*)(d+787968+k+32),_mm256_and_si256(v,msk)); wp[12312+(k>>6)]=m3|((uint64_t)(uint32_t)_mm256_movemask_epi8(v)<<32); }
{ __m256i v=_mm256_add_epi8(b0,b3); _mm256_store_si256((__m256i*)(d+1050624+k+32),_mm256_and_si256(v,msk)); wp[16416+(k>>6)]=m4|((uint64_t)(uint32_t)_mm256_movemask_epi8(v)<<32); }
{ __m256i v=_mm256_sub_epi8(b2,b0); _mm256_store_si256((__m256i*)(d+1313280+k+32),_mm256_and_si256(v,msk)); wp[20520+(k>>6)]=m5|((uint64_t)(uint32_t)_mm256_movemask_epi8(v)<<32); }
{ __m256i v=_mm256_sub_epi8(b3,b1); _mm256_store_si256((__m256i*)(d+1575936+k+32),_mm256_and_si256(v,msk)); wp[24624+(k>>6)]=m6|((uint64_t)(uint32_t)_mm256_movemask_epi8(v)<<32); }
}
}
}
/* k1=3: 4 distinct A blocks -> all 7 A panels in one pass */
AVX2 static void bldAw3(int h, const int8_t*A){
const __m256i msk=_mm256_set1_epi8(0x7F);
const int W=h>>6;
for (int r=0;r<h;r++){
const int8_t*ap=A+(size_t)r*2048;
int8_t*d=A0b7+(size_t)r*h;
uint64_t*wp=A1b7+(size_t)r*W;
for (int k=0;k<h;k+=64){
_mm_prefetch((const char*)(ap+k+4096+2098176), _MM_HINT_T0);
_mm_prefetch((const char*)(ap+k+4096+3147264), _MM_HINT_T0);
_mm_prefetch((const char*)(ap+k+4096+3146752), _MM_HINT_T0);
_mm_prefetch((const char*)(ap+k+4096+2098688), _MM_HINT_T0);
__m256i a0=LD(ap+k+2098176),a1=LD(ap+k+3147264),a2=LD(ap+k+3146752),a3=LD(ap+k+2098688);
uint32_t m0,m1,m2,m3,m4,m5,m6;
{ __m256i v=_mm256_add_epi8(a0,a1); _mm256_store_si256((__m256i*)(d+0+k),_mm256_and_si256(v,msk)); m0=(uint32_t)_mm256_movemask_epi8(v); }
{ __m256i v=_mm256_add_epi8(a2,a1); _mm256_store_si256((__m256i*)(d+262656+k),_mm256_and_si256(v,msk)); m1=(uint32_t)_mm256_movemask_epi8(v); }
{ __m256i v=a0; _mm256_store_si256((__m256i*)(d+525312+k),_mm256_and_si256(v,msk)); m2=(uint32_t)_mm256_movemask_epi8(v); }
{ __m256i v=a1; _mm256_store_si256((__m256i*)(d+787968+k),_mm256_and_si256(v,msk)); m3=(uint32_t)_mm256_movemask_epi8(v); }
{ __m256i v=_mm256_add_epi8(a0,a3); _mm256_store_si256((__m256i*)(d+1050624+k),_mm256_and_si256(v,msk)); m4=(uint32_t)_mm256_movemask_epi8(v); }
{ __m256i v=_mm256_sub_epi8(a2,a0); _mm256_store_si256((__m256i*)(d+1313280+k),_mm256_and_si256(v,msk)); m5=(uint32_t)_mm256_movemask_epi8(v); }
{ __m256i v=_mm256_sub_epi8(a3,a1); _mm256_store_si256((__m256i*)(d+1575936+k),_mm256_and_si256(v,msk)); m6=(uint32_t)_mm256_movemask_epi8(v); }
__m256i b0=LD(ap+k+32+2098176),b1=LD(ap+k+32+3147264),b2=LD(ap+k+32+3146752),b3=LD(ap+k+32+2098688);
{ __m256i v=_mm256_add_epi8(b0,b1); _mm256_store_si256((__m256i*)(d+0+k+32),_mm256_and_si256(v,msk)); wp[0+(k>>6)]=m0|((uint64_t)(uint32_t)_mm256_movemask_epi8(v)<<32); }
{ __m256i v=_mm256_add_epi8(b2,b1); _mm256_store_si256((__m256i*)(d+262656+k+32),_mm256_and_si256(v,msk)); wp[4104+(k>>6)]=m1|((uint64_t)(uint32_t)_mm256_movemask_epi8(v)<<32); }
{ __m256i v=b0; _mm256_store_si256((__m256i*)(d+525312+k+32),_mm256_and_si256(v,msk)); wp[8208+(k>>6)]=m2|((uint64_t)(uint32_t)_mm256_movemask_epi8(v)<<32); }
{ __m256i v=b1; _mm256_store_si256((__m256i*)(d+787968+k+32),_mm256_and_si256(v,msk)); wp[12312+(k>>6)]=m3|((uint64_t)(uint32_t)_mm256_movemask_epi8(v)<<32); }
{ __m256i v=_mm256_add_epi8(b0,b3); _mm256_store_si256((__m256i*)(d+1050624+k+32),_mm256_and_si256(v,msk)); wp[16416+(k>>6)]=m4|((uint64_t)(uint32_t)_mm256_movemask_epi8(v)<<32); }
{ __m256i v=_mm256_sub_epi8(b2,b0); _mm256_store_si256((__m256i*)(d+1313280+k+32),_mm256_and_si256(v,msk)); wp[20520+(k>>6)]=m5|((uint64_t)(uint32_t)_mm256_movemask_epi8(v)<<32); }
{ __m256i v=_mm256_sub_epi8(b3,b1); _mm256_store_si256((__m256i*)(d+1575936+k+32),_mm256_and_si256(v,msk)); wp[24624+(k>>6)]=m6|((uint64_t)(uint32_t)_mm256_movemask_epi8(v)<<32); }
}
}
}
/* k1=4: 8 distinct A blocks -> all 7 A panels in one pass */
AVX2 static void bldAw4(int h, const int8_t*A){
const __m256i msk=_mm256_set1_epi8(0x7F);
const int W=h>>6;
for (int r=0;r<h;r++){
const int8_t*ap=A+(size_t)r*2048;
int8_t*d=A0b7+(size_t)r*h;
uint64_t*wp=A1b7+(size_t)r*W;
for (int k=0;k<h;k+=64){
_mm_prefetch((const char*)(ap+k+4096+0), _MM_HINT_T0);
_mm_prefetch((const char*)(ap+k+4096+1024), _MM_HINT_T0);
_mm_prefetch((const char*)(ap+k+4096+1049088), _MM_HINT_T0);
_mm_prefetch((const char*)(ap+k+4096+1050112), _MM_HINT_T0);
_mm_prefetch((const char*)(ap+k+4096+1048576), _MM_HINT_T0);
_mm_prefetch((const char*)(ap+k+4096+1049600), _MM_HINT_T0);
_mm_prefetch((const char*)(ap+k+4096+512), _MM_HINT_T0);
_mm_prefetch((const char*)(ap+k+4096+1536), _MM_HINT_T0);
__m256i a0=LD(ap+k+0),a1=LD(ap+k+1024),a2=LD(ap+k+1049088),a3=LD(ap+k+1050112),a4=LD(ap+k+1048576),a5=LD(ap+k+1049600),a6=LD(ap+k+512),a7=LD(ap+k+1536);
uint32_t m0,m1,m2,m3,m4,m5,m6;
{ __m256i v=_mm256_add_epi8(_mm256_add_epi8(_mm256_add_epi8(a0,a1),a2),a3); _mm256_store_si256((__m256i*)(d+0+k),_mm256_and_si256(v,msk)); m0=(uint32_t)_mm256_movemask_epi8(v); }
{ __m256i v=_mm256_add_epi8(_mm256_add_epi8(_mm256_add_epi8(a4,a5),a2),a3); _mm256_store_si256((__m256i*)(d+262656+k),_mm256_and_si256(v,msk)); m1=(uint32_t)_mm256_movemask_epi8(v); }
{ __m256i v=_mm256_add_epi8(a0,a1); _mm256_store_si256((__m256i*)(d+525312+k),_mm256_and_si256(v,msk)); m2=(uint32_t)_mm256_movemask_epi8(v); }
{ __m256i v=_mm256_add_epi8(a2,a3); _mm256_store_si256((__m256i*)(d+787968+k),_mm256_and_si256(v,msk)); m3=(uint32_t)_mm256_movemask_epi8(v); }
{ __m256i v=_mm256_add_epi8(_mm256_add_epi8(_mm256_add_epi8(a0,a1),a6),a7); _mm256_store_si256((__m256i*)(d+1050624+k),_mm256_and_si256(v,msk)); m4=(uint32_t)_mm256_movemask_epi8(v); }
{ __m256i v=_mm256_sub_epi8(_mm256_sub_epi8(_mm256_add_epi8(a4,a5),a0),a1); _mm256_store_si256((__m256i*)(d+1313280+k),_mm256_and_si256(v,msk)); m5=(uint32_t)_mm256_movemask_epi8(v); }
{ __m256i v=_mm256_sub_epi8(_mm256_sub_epi8(_mm256_add_epi8(a6,a7),a2),a3); _mm256_store_si256((__m256i*)(d+1575936+k),_mm256_and_si256(v,msk)); m6=(uint32_t)_mm256_movemask_epi8(v); }
__m256i b0=LD(ap+k+32+0),b1=LD(ap+k+32+1024),b2=LD(ap+k+32+1049088),b3=LD(ap+k+32+1050112),b4=LD(ap+k+32+1048576),b5=LD(ap+k+32+1049600),b6=LD(ap+k+32+512),b7=LD(ap+k+32+1536);
{ __m256i v=_mm256_add_epi8(_mm256_add_epi8(_mm256_add_epi8(b0,b1),b2),b3); _mm256_store_si256((__m256i*)(d+0+k+32),_mm256_and_si256(v,msk)); wp[0+(k>>6)]=m0|((uint64_t)(uint32_t)_mm256_movemask_epi8(v)<<32); }
{ __m256i v=_mm256_add_epi8(_mm256_add_epi8(_mm256_add_epi8(b4,b5),b2),b3); _mm256_store_si256((__m256i*)(d+262656+k+32),_mm256_and_si256(v,msk)); wp[4104+(k>>6)]=m1|((uint64_t)(uint32_t)_mm256_movemask_epi8(v)<<32); }
{ __m256i v=_mm256_add_epi8(b0,b1); _mm256_store_si256((__m256i*)(d+525312+k+32),_mm256_and_si256(v,msk)); wp[8208+(k>>6)]=m2|((uint64_t)(uint32_t)_mm256_movemask_epi8(v)<<32); }
{ __m256i v=_mm256_add_epi8(b2,b3); _mm256_store_si256((__m256i*)(d+787968+k+32),_mm256_and_si256(v,msk)); wp[12312+(k>>6)]=m3|((uint64_t)(uint32_t)_mm256_movemask_epi8(v)<<32); }
{ __m256i v=_mm256_add_epi8(_mm256_add_epi8(_mm256_add_epi8(b0,b1),b6),b7); _mm256_store_si256((__m256i*)(d+1050624+k+32),_mm256_and_si256(v,msk)); wp[16416+(k>>6)]=m4|((uint64_t)(uint32_t)_mm256_movemask_epi8(v)<<32); }
{ __m256i v=_mm256_sub_epi8(_mm256_sub_epi8(_mm256_add_epi8(b4,b5),b0),b1); _mm256_store_si256((__m256i*)(d+1313280+k+32),_mm256_and_si256(v,msk)); wp[20520+(k>>6)]=m5|((uint64_t)(uint32_t)_mm256_movemask_epi8(v)<<32); }
{ __m256i v=_mm256_sub_epi8(_mm256_sub_epi8(_mm256_add_epi8(b6,b7),b2),b3); _mm256_store_si256((__m256i*)(d+1575936+k+32),_mm256_and_si256(v,msk)); wp[24624+(k>>6)]=m6|((uint64_t)(uint32_t)_mm256_movemask_epi8(v)<<32); }
}
}
}
/* k1=5: 8 distinct A blocks -> all 7 A panels in one pass */
AVX2 static void bldAw5(int h, const int8_t*A){
const __m256i msk=_mm256_set1_epi8(0x7F);
const int W=h>>6;
for (int r=0;r<h;r++){
const int8_t*ap=A+(size_t)r*2048;
int8_t*d=A0b7+(size_t)r*h;
uint64_t*wp=A1b7+(size_t)r*W;
for (int k=0;k<h;k+=64){
_mm_prefetch((const char*)(ap+k+4096+2097152), _MM_HINT_T0);
_mm_prefetch((const char*)(ap+k+4096+0), _MM_HINT_T0);
_mm_prefetch((const char*)(ap+k+4096+3146240), _MM_HINT_T0);
_mm_prefetch((const char*)(ap+k+4096+1049088), _MM_HINT_T0);
_mm_prefetch((const char*)(ap+k+4096+3145728), _MM_HINT_T0);
_mm_prefetch((const char*)(ap+k+4096+1048576), _MM_HINT_T0);
_mm_prefetch((const char*)(ap+k+4096+2097664), _MM_HINT_T0);
_mm_prefetch((const char*)(ap+k+4096+512), _MM_HINT_T0);
__m256i a0=LD(ap+k+2097152),a1=LD(ap+k+0),a2=LD(ap+k+3146240),a3=LD(ap+k+1049088),a4=LD(ap+k+3145728),a5=LD(ap+k+1048576),a6=LD(ap+k+2097664),a7=LD(ap+k+512);
uint32_t m0,m1,m2,m3,m4,m5,m6;
{ __m256i v=_mm256_sub_epi8(_mm256_add_epi8(_mm256_sub_epi8(a0,a1),a2),a3); _mm256_store_si256((__m256i*)(d+0+k),_mm256_and_si256(v,msk)); m0=(uint32_t)_mm256_movemask_epi8(v); }
{ __m256i v=_mm256_sub_epi8(_mm256_add_epi8(_mm256_sub_epi8(a4,a5),a2),a3); _mm256_store_si256((__m256i*)(d+262656+k),_mm256_and_si256(v,msk)); m1=(uint32_t)_mm256_movemask_epi8(v); }
{ __m256i v=_mm256_sub_epi8(a0,a1); _mm256_store_si256((__m256i*)(d+525312+k),_mm256_and_si256(v,msk)); m2=(uint32_t)_mm256_movemask_epi8(v); }
{ __m256i v=_mm256_sub_epi8(a2,a3); _mm256_store_si256((__m256i*)(d+787968+k),_mm256_and_si256(v,msk)); m3=(uint32_t)_mm256_movemask_epi8(v); }
{ __m256i v=_mm256_sub_epi8(_mm256_add_epi8(_mm256_sub_epi8(a0,a1),a6),a7); _mm256_store_si256((__m256i*)(d+1050624+k),_mm256_and_si256(v,msk)); m4=(uint32_t)_mm256_movemask_epi8(v); }
{ __m256i v=_mm256_add_epi8(_mm256_sub_epi8(_mm256_sub_epi8(a4,a5),a0),a1); _mm256_store_si256((__m256i*)(d+1313280+k),_mm256_and_si256(v,msk)); m5=(uint32_t)_mm256_movemask_epi8(v); }
{ __m256i v=_mm256_add_epi8(_mm256_sub_epi8(_mm256_sub_epi8(a6,a7),a2),a3); _mm256_store_si256((__m256i*)(d+1575936+k),_mm256_and_si256(v,msk)); m6=(uint32_t)_mm256_movemask_epi8(v); }
__m256i b0=LD(ap+k+32+2097152),b1=LD(ap+k+32+0),b2=LD(ap+k+32+3146240),b3=LD(ap+k+32+1049088),b4=LD(ap+k+32+3145728),b5=LD(ap+k+32+1048576),b6=LD(ap+k+32+2097664),b7=LD(ap+k+32+512);
{ __m256i v=_mm256_sub_epi8(_mm256_add_epi8(_mm256_sub_epi8(b0,b1),b2),b3); _mm256_store_si256((__m256i*)(d+0+k+32),_mm256_and_si256(v,msk)); wp[0+(k>>6)]=m0|((uint64_t)(uint32_t)_mm256_movemask_epi8(v)<<32); }
{ __m256i v=_mm256_sub_epi8(_mm256_add_epi8(_mm256_sub_epi8(b4,b5),b2),b3); _mm256_store_si256((__m256i*)(d+262656+k+32),_mm256_and_si256(v,msk)); wp[4104+(k>>6)]=m1|((uint64_t)(uint32_t)_mm256_movemask_epi8(v)<<32); }
{ __m256i v=_mm256_sub_epi8(b0,b1); _mm256_store_si256((__m256i*)(d+525312+k+32),_mm256_and_si256(v,msk)); wp[8208+(k>>6)]=m2|((uint64_t)(uint32_t)_mm256_movemask_epi8(v)<<32); }
{ __m256i v=_mm256_sub_epi8(b2,b3); _mm256_store_si256((__m256i*)(d+787968+k+32),_mm256_and_si256(v,msk)); wp[12312+(k>>6)]=m3|((uint64_t)(uint32_t)_mm256_movemask_epi8(v)<<32); }
{ __m256i v=_mm256_sub_epi8(_mm256_add_epi8(_mm256_sub_epi8(b0,b1),b6),b7); _mm256_store_si256((__m256i*)(d+1050624+k+32),_mm256_and_si256(v,msk)); wp[16416+(k>>6)]=m4|((uint64_t)(uint32_t)_mm256_movemask_epi8(v)<<32); }
{ __m256i v=_mm256_add_epi8(_mm256_sub_epi8(_mm256_sub_epi8(b4,b5),b0),b1); _mm256_store_si256((__m256i*)(d+1313280+k+32),_mm256_and_si256(v,msk)); wp[20520+(k>>6)]=m5|((uint64_t)(uint32_t)_mm256_movemask_epi8(v)<<32); }
{ __m256i v=_mm256_add_epi8(_mm256_sub_epi8(_mm256_sub_epi8(b6,b7),b2),b3); _mm256_store_si256((__m256i*)(d+1575936+k+32),_mm256_and_si256(v,msk)); wp[24624+(k>>6)]=m6|((uint64_t)(uint32_t)_mm256_movemask_epi8(v)<<32); }
}
}
}
/* k1=6: 8 distinct A blocks -> all 7 A panels in one pass */
AVX2 static void bldAw6(int h, const int8_t*A){
const __m256i msk=_mm256_set1_epi8(0x7F);
const int W=h>>6;
for (int r=0;r<h;r++){
const int8_t*ap=A+(size_t)r*2048;
int8_t*d=A0b7+(size_t)r*h;
uint64_t*wp=A1b7+(size_t)r*W;
for (int k=0;k<h;k+=64){
_mm_prefetch((const char*)(ap+k+4096+1024), _MM_HINT_T0);
_mm_prefetch((const char*)(ap+k+4096+2098176), _MM_HINT_T0);
_mm_prefetch((const char*)(ap+k+4096+1050112), _MM_HINT_T0);
_mm_prefetch((const char*)(ap+k+4096+3147264), _MM_HINT_T0);
_mm_prefetch((const char*)(ap+k+4096+1049600), _MM_HINT_T0);
_mm_prefetch((const char*)(ap+k+4096+3146752), _MM_HINT_T0);
_mm_prefetch((const char*)(ap+k+4096+1536), _MM_HINT_T0);
_mm_prefetch((const char*)(ap+k+4096+2098688), _MM_HINT_T0);
__m256i a0=LD(ap+k+1024),a1=LD(ap+k+2098176),a2=LD(ap+k+1050112),a3=LD(ap+k+3147264),a4=LD(ap+k+1049600),a5=LD(ap+k+3146752),a6=LD(ap+k+1536),a7=LD(ap+k+2098688);
uint32_t m0,m1,m2,m3,m4,m5,m6;
{ __m256i v=_mm256_sub_epi8(_mm256_add_epi8(_mm256_sub_epi8(a0,a1),a2),a3); _mm256_store_si256((__m256i*)(d+0+k),_mm256_and_si256(v,msk)); m0=(uint32_t)_mm256_movemask_epi8(v); }
{ __m256i v=_mm256_sub_epi8(_mm256_add_epi8(_mm256_sub_epi8(a4,a5),a2),a3); _mm256_store_si256((__m256i*)(d+262656+k),_mm256_and_si256(v,msk)); m1=(uint32_t)_mm256_movemask_epi8(v); }
{ __m256i v=_mm256_sub_epi8(a0,a1); _mm256_store_si256((__m256i*)(d+525312+k),_mm256_and_si256(v,msk)); m2=(uint32_t)_mm256_movemask_epi8(v); }
{ __m256i v=_mm256_sub_epi8(a2,a3); _mm256_store_si256((__m256i*)(d+787968+k),_mm256_and_si256(v,msk)); m3=(uint32_t)_mm256_movemask_epi8(v); }
{ __m256i v=_mm256_sub_epi8(_mm256_add_epi8(_mm256_sub_epi8(a0,a1),a6),a7); _mm256_store_si256((__m256i*)(d+1050624+k),_mm256_and_si256(v,msk)); m4=(uint32_t)_mm256_movemask_epi8(v); }
{ __m256i v=_mm256_add_epi8(_mm256_sub_epi8(_mm256_sub_epi8(a4,a5),a0),a1); _mm256_store_si256((__m256i*)(d+1313280+k),_mm256_and_si256(v,msk)); m5=(uint32_t)_mm256_movemask_epi8(v); }
{ __m256i v=_mm256_add_epi8(_mm256_sub_epi8(_mm256_sub_epi8(a6,a7),a2),a3); _mm256_store_si256((__m256i*)(d+1575936+k),_mm256_and_si256(v,msk)); m6=(uint32_t)_mm256_movemask_epi8(v); }
__m256i b0=LD(ap+k+32+1024),b1=LD(ap+k+32+2098176),b2=LD(ap+k+32+1050112),b3=LD(ap+k+32+3147264),b4=LD(ap+k+32+1049600),b5=LD(ap+k+32+3146752),b6=LD(ap+k+32+1536),b7=LD(ap+k+32+2098688);
{ __m256i v=_mm256_sub_epi8(_mm256_add_epi8(_mm256_sub_epi8(b0,b1),b2),b3); _mm256_store_si256((__m256i*)(d+0+k+32),_mm256_and_si256(v,msk)); wp[0+(k>>6)]=m0|((uint64_t)(uint32_t)_mm256_movemask_epi8(v)<<32); }
{ __m256i v=_mm256_sub_epi8(_mm256_add_epi8(_mm256_sub_epi8(b4,b5),b2),b3); _mm256_store_si256((__m256i*)(d+262656+k+32),_mm256_and_si256(v,msk)); wp[4104+(k>>6)]=m1|((uint64_t)(uint32_t)_mm256_movemask_epi8(v)<<32); }
{ __m256i v=_mm256_sub_epi8(b0,b1); _mm256_store_si256((__m256i*)(d+525312+k+32),_mm256_and_si256(v,msk)); wp[8208+(k>>6)]=m2|((uint64_t)(uint32_t)_mm256_movemask_epi8(v)<<32); }
{ __m256i v=_mm256_sub_epi8(b2,b3); _mm256_store_si256((__m256i*)(d+787968+k+32),_mm256_and_si256(v,msk)); wp[12312+(k>>6)]=m3|((uint64_t)(uint32_t)_mm256_movemask_epi8(v)<<32); }
{ __m256i v=_mm256_sub_epi8(_mm256_add_epi8(_mm256_sub_epi8(b0,b1),b6),b7); _mm256_store_si256((__m256i*)(d+1050624+k+32),_mm256_and_si256(v,msk)); wp[16416+(k>>6)]=m4|((uint64_t)(uint32_t)_mm256_movemask_epi8(v)<<32); }
{ __m256i v=_mm256_add_epi8(_mm256_sub_epi8(_mm256_sub_epi8(b4,b5),b0),b1); _mm256_store_si256((__m256i*)(d+1313280+k+32),_mm256_and_si256(v,msk)); wp[20520+(k>>6)]=m5|((uint64_t)(uint32_t)_mm256_movemask_epi8(v)<<32); }
{ __m256i v=_mm256_add_epi8(_mm256_sub_epi8(_mm256_sub_epi8(b6,b7),b2),b3); _mm256_store_si256((__m256i*)(d+1575936+k+32),_mm256_and_si256(v,msk)); wp[24624+(k>>6)]=m6|((uint64_t)(uint32_t)_mm256_movemask_epi8(v)<<32); }
}
}
}
AVX2 static void bldAw(int h, const int8_t*A, int k1){
switch(k1){
case 0: bldAw0(h,A); break;
case 1: bldAw1(h,A); break;
case 2: bldAw2(h,A); break;
case 3: bldAw3(h,A); break;
case 4: bldAw4(h,A); break;
case 5: bldAw5(h,A); break;
case 6: bldAw6(h,A); break;
}
}
/* corr for the n = 512 leaf: same nibble-table scheme as corr1024, W = 8. */
AVX2BMI3 static void corr512p(const uint64_t*Ab, const uint64_t*Bb){
const int n=512, W=8;
memset(Pbb,0,(size_t)n*W*8);
const int KB=64;
for (int kb=0; kb<n; kb+=KB){
int w0=kb>>6;
const uint64_t *bw = Bb + (size_t)w0*(size_t)W*64;
for (int g=0; g<16; g++){
uint64_t *z=(uint64_t*)XT4s[g][0];
for (int q=0;q<8;q++) z[q]=0;
for (int t=1;t<16;t++){
uint64_t *dst=(uint64_t*)XT4s[g][t];
int lb=__builtin_ctz(t), t2=t&(t-1);
const uint64_t *src=(const uint64_t*)XT4s[g][t2];
const uint64_t *row=bw+(size_t)(4*g+lb)*W;
if (t2) for (int q=0;q<8;q++) dst[q]=src[q]^row[q];
else for (int q=0;q<8;q++) dst[q]=row[q];
}
}
for (int i=0;i<n;i++){
uint64_t b0 = Ab[(size_t)i*W + w0];
__m256i a0,a1;
a0=a1=_mm256_setzero_si256();
for (int g=0; g<16; g++){
const __m256i *p = (const __m256i *)XT4s[g][(b0>>(4*g))&15];
a0=_mm256_xor_si256(a0,_mm256_load_si256(p));
a1=_mm256_xor_si256(a1,_mm256_load_si256(p+1));
}
__m256i *o=(__m256i*)(Pbb+(size_t)i*W);
_mm256_store_si256(o+0,_mm256_xor_si256(_mm256_load_si256(o+0),a0));
_mm256_store_si256(o+1,_mm256_xor_si256(_mm256_load_si256(o+1),a1));
}
}
}
/* level-2 scratch: 7 leaves of h x h = 512 x 512 */
static int8_t MMS2[7][512*512+128] __attribute__((aligned(64)));
/* one h x h leaf through the SHIPPED pipeline, result NT-stored to Cp */
AVX2 static void strassen1(int n, const int8_t*A, const int8_t*B, int8_t*C){
const int m = n>>1; /* 1024 */
const int o = m;
const int h = m>>1; /* 512: the level-2 leaf */
for (int k1=0;k1<7;k1++){
if (C2S_WA) bldAw(h,A,k1);
#if C2S_HASB
if (C2S_WB) bldBw(h,B,k1);
#endif
for (int k2=0;k2<7;k2++){
const int8_t *AP; const uint64_t *A1P;
const int8_t *BP; const uint64_t *BpP;
if (C2S_WA) { AP=A0b7+(size_t)k2*262656; A1P=A1b7+(size_t)k2*4104; }
else { buildA4(h,n,A,k1,k2); AP=A0b; A1P=A1b; }
{ buildB4(h,n,B,k1,k2); BP=BI3b; BpP=Bpb; }
corr512p(A1P,BpP);
for (int g=0; g<h; g+=64)
for (int i=0; i<h; i+=2){
mk_s(h, AP+(size_t)i*h, BP+(size_t)(g>>6)*((h/2)*128+512), MMS2[k2], PBb, g);
epilogue2(h, MMS2[k2], (const uint64_t*)Pbb, g, i);
}
}
_mm_sfence(); /* MMS2[k] were written with NT stores */
cmb(MMS[k1],m,0,0,h, MMS2[0],1,MMS2[3],1,MMS2[4],-1,MMS2[6],1);
cmb(MMS[k1],m,0,h,h, MMS2[2],1,MMS2[4],1,0,0,0,0);
cmb(MMS[k1],m,h,0,h, MMS2[1],1,MMS2[3],1,0,0,0,0);
cmb(MMS[k1],m,h,h,h, MMS2[0],1,MMS2[2],1,MMS2[1],-1,MMS2[5],1);
_mm_sfence();
}
/* C11=M0+M3-M4+M6 C12=M2+M4 C21=M1+M3 C22=M0+M2-M1+M5 (CLRS P-form) */
cmb(C,n, 0,0, m, MMS[0],+1, MMS[3],+1, MMS[4],-1, MMS[6],+1);
cmb(C,n, 0,o, m, MMS[2],+1, MMS[4],+1, 0,0, 0,0);
cmb(C,n, o,0, m, MMS[1],+1, MMS[3],+1, 0,0, 0,0);
cmb(C,n, o,o, m, MMS[0],+1, MMS[2],+1, MMS[1],-1, MMS[5],+1);
}
AVX2 void matrix_multiply(int n, const int8_t *A, const int8_t *B, int8_t *C){
if (n<=0 || (n&255) || n>NMAX) { generic_mm(n,A,B,C); return; }
if (n==2048) { strassen1(n,A,B,C); return; }
/* x4: A1T is WRITTEN by build_A1T and NEVER READ -- dead NMAX*NMAX/8 bytes + its transpose pass. */
build_A0A1(n,A); build_BI3Bp(n,B);
if(n==4096) corr16(); else if(n==2048) corr16k(n); else corr_pass3(n);
for (int g=0, jbg=0; g<n; g+=64, jbg=g)
for (int i=0; i<n; i+=2)
{ mk_s(n, A0b+(size_t)i*n, BI3b+(size_t)(g>>6)*(n/2)*128, C, PBb, g);
epilogue2(n, C, (const uint64_t*)Pbb, g, i); }
}
| Compilation | N/A | N/A | Compile OK | Score: N/A | 显示更多 |
| Testcase #1 | 57.233 ms | 15 MB + 80 KB | Accepted | Score: 100 | 显示更多 |