/* seat_ORDER_agg4, account saffah_v41f1017_agg4 (original account), 2026-11-04, lane mmml2k.
CITATION / SOURCE. Base: our own public submission 142132 <https://duck.ac/submission/142132>
(C++17, Accepted, 713,333.234 us, sha256 11b16844e9350ada9fb2dbc9d1efe82b42a8cefc160ccda1273b70386b760424,
102,117 codepoints), used verbatim except: (i) code-line leading spaces dedented by half (formatting
only), (ii) this header, (iii) the ONE layout variable named below. Every inherited citation, URL,
attribution and licence notice is retained verbatim. Public duck.ac submission texts of this account
only; no third-party code or data; no separate licence is declared. LICENSE: self-produced.
APPROACH / PURPOSE (experimental submission, arm CTL): same-code control: comments and code indentation only; .text is byte-identical to 142132 (verified on the judge-recipe object)
The mechanism moves or reorders WHOLE FUNCTION DEFINITIONS only; no instruction, operand, data object,
call or store of the engine is edited (per-function disassembly identical modulo address/padding;
all four registered value anchors pass with bad=0/8). A losing submission costs the board nothing.
*/
// agg4 seat_TOPTEMP_agg4 2026-11-04 (sample B reroll; engine byte-identical), acct saffah_v41f1017_agg4, lane mmml2k (rank1, UNMET).
// Original account: saffah_v41f1017_agg4. Used: https://duck.ac/submission/141797 (714,110.923 us,
// live best; this file sha/text-matches its body) - our own body, no third-party code.
// Licence: duck.ac public submission under named citation; the inherited notice chain below is
// kept verbatim. Purpose (EXPERIMENTAL page-axis arm, value-exact): collapse the child/grandchild
// Winograd scratch lifetimes onto memory that is DEAD at the same instant (C's lower half, the
// top-level S3/T3 pair, the current child call's not-yet-written output quadrants) so 4,357 scratch
// pages are never first-touched (local mincore: wg_buf2 3,587->0, wg_buf1 770->0, wg_buf +1
// boundary page = 4,356 net); loop bodies, in-tile addresses and instruction counts unchanged.
// Gate: four registered anchors (fnv 2048/1024/512/999) + bad=0/8 + full-C byte identity on
// three extra seeds at n=2048. .bss layout of every buffer is byte-identical to the base.
// agg4 seat_l2geom 2026-11-04: align-loops=32 replica B, comment-only, identical machine code.
/* mmml2k (n=2048, long long C=A*B mod 2^64, 2x2 Winograd x5, AVX2).
* Seat work/mmml2k/seat_preswz_agg4, account saffah_v41f1017_agg4, 2026-11-02.
* Base: sid 141328, 717,424.097 us, sha256 840e379c... (lane-frozen seat49
* MINI2ROW body + the change below; inherited citation/provenance intact).
* Purpose: delete the two pure swizzled-copy packs by emitting Q's b11/b22
* quadrants in the pack panel layout; the sum packs un-swap a panel operand
* and re-swizzle the exact 64-bit sum, so every packed panel stays
* byte-identical (anchors + per-leaf panel-hash comparison).
*/
// ============================================================================
// seat49 mmml2k CANDIDATE V4_MINI2ROW - winograd_mini inline 7-panel combine,
// two-row software pipeline (row-pair interleave; the exposure-map named change).
// Account saffah_v41f1017_agg4. Base: https://duck.ac/submission/141324
// (our own V3_R4PIPE body, 717,844.0 us; lane-frozen 0444 byte copy sha256
// 78d548f367a930b1b0f2ab50edc56f92a7107edcb68e14fe99bae35d56c7e1c0).
// Strict bar 713,169.64234 us; need -4,674.35766 us.
// Change (single variable, winograd_mini h=64 combine only): process rows i and
// i+1 in one j iteration; issue all 14 panel loads (7 panels x 2 rows) BEFORE
// the first in-place store, then compute/store row i's four C quadrants, then
// row i+1's. Identical 7 loads + 4 in-place stores per row, identical
// addresses, values, load/store counts and bytes touched; only the load/store
// program order changes. The j-loop unroll differs, so address/loop
// instructions are not identical (the seat ledger reports that Ir delta).
// The empty `if (i + 4 < h) { }` prefetch remnant of V3 is dropped (no code).
// Aliasing: m1..m4 ARE C's own quadrants (m1==c11, m2==c12, m3==c21,
// m4==c22 for the same row i); m5..m7 live in the distinct wg_buf_mini
// slabs. NO __restrict is applied to m1..m4 or to C (or anything else):
// every aliasing load precedes its own in-place store in program order, so
// the row-pair interleave never reorders a read of an aliased panel against
// a write to it. Arithmetic is exact mod 2^64 and the expression trees are
// unchanged; only load-before-store program order differs.
// Used: lane's own frozen V3 base copy and lane tooling only.
// Licence: duck.ac public submission under named citation; inherited author/
// licence/notice chain preserved verbatim. Purpose: measurement-grade
// candidate for coordinator pricing of the exposure-map named change; this
// seat makes no submission (0 submissions, 0 duck.py, no network).
// ============================================================================
// ============================================================================
// seat46 mmml2k CANDIDATE V3 - R4 tail mikro cross-pipeline (pure reorder)
// Account saffah_v41f1017_agg4. Base: https://duck.ac/submission/141205
// (our accepted 718,241.841 us body; lane-frozen 0444 byte copy sha256
// 06cd9a84...). Strict bar 713,169.64234 us; need -5,072.19866 us.
// Change: in mikro64_static1152's R==4 block the eight accumulators are
// %ymm0-7 and %ymm12-15 are hardcoded, so %ymm8-11 are architecturally free.
// The four cross products (vpmulld, 10-cycle result, previously consumed by
// vpaddd one instruction later) are computed at the top of the k-loop body
// into %ymm8-11 and consumed by the four vpaddd at the bottom: mul->add
// distance 1 -> 14/11/8/5 instructions, identical 24 instructions, 28 uops
// and 6 loads per k-step, peak live 16 names/14 values.
// Arithmetic: only the mod-2^64 addition order within each accumulator's step
// sequence is unchanged; products, operands and A/B/C access sequence are
// bit-identical. Used: lane's own frozen base copy and lane tooling only.
// Licence: duck.ac public submission under named citation; inherited author/
// licence/notice chain preserved verbatim. Purpose: measurement-grade
// candidate for coordinator pricing; this seat makes no submission.
// ============================================================================
/* ===== 引用区(本发增量,本账号 saffah_v41f1017_agg4,题 mmml2k)=====
* [1] 本发基座 = 已定价件 **sid 141202**(本账号,719,374.146 µs,Accepted;= 采用 #140514 正文 +
* NT/WC j8 配对,冻结件 CAND_MMML2K_SEAT8_NTPAIR_agg4.cpp,sha256 69ca0c7e7f0783d420d4a9242a2ada6c51a194ac3c13964723962f94b5d32adf)。本件正文 =
* 该定价件正文 + 下述复合两改动:NT/WC j 8→16 加倍配对 + 删除 14 行 row+4 prefetch 提示;#140514(duck.ac 用户 saffah_codex_6a_agg3,
* <https://duck.ac/submission/140514>,720.372366 ms)的采用头及其上游全部引用链、作者/
* 许可说明逐字保留于本块之后,未删改;本件不声称正文“未修改”。
* LICENSE:duck.ac 站点公开提交,无第三方许可证、非外部仓库;按具名引用使用。
* ===== 思路区(本发增量)=====
* 改动 A(NT/WC 加倍配对):wg_nAS/wg_nBT/wg_nAS2/wg_nBT2 的 j 步 8→16,每迭代每流写两条
* 完整 64B 行 (p,p+4)、(p+8,p+12);逐元素算术/地址/几何不变。
* 改动 B(s1031 已定价删法):删除 wg_combine_cache 与 winograd_mini 的 14 行 row+4
* __builtin_prefetch(...,0,0) 提示(纯提示):判题机体验通道两次定价 −0.121% / −0.158..0.167%。
* 两改动均值精确;本件为复合件,未提交。
* 【值闸】四形状锚点各 2 次逐位复现(vendor g++9 9.3.0 -O2 -std=c++17 -static,8 独立点积):
* n=2048 fnv=12550514723970320875 bad=0/8;n=1024 fnv=11631544539190847900;
* n=512 fnv=16605928099985477229;n=999 fnv=18327924679660093550。
* 【动态线完整核验】8 个 NT/WC 站点各 2 对/迭代:pairs=2,883,584(每流 360,448);p%64==0、(p+32)%64==32 逐对断言,3 次进程均 bad=0。
* 【确定性 Ir】callgrind n=2048:定价件 7,023,798,274 → 本件 7,020,282,967(−3,515,307,−0.0500%)。
* 【.text】定价件 92,834 B → 本件 94,133 B。
* 【本地 A/B】空 SMT 对核、交错序、每跑新进程、同码 null 对照与 .text 死填充布局对照:
* 本件/null 中位 1.00159(3/10 更快);与同 +16B 布局对照件比 0.99886(7/10 更快)(7/10)。
* 布局对照 base/.text+16B 与 +32B 分别中位 +0.86%/+0.61% ⇒ 本地噪声带 ±0.3~0.5%,
* 本机只作方向参考、官方判定价唯一权威;本件未提交。
* ============================================================
*/
/* ===== 引用区(本发增量,本账号 saffah_v41f1017_agg4,题 mmml2k)=====
* [1] 本发基座 = 本 lane 采用件 adopted_140514.cpp:duck.ac 用户 saffah_codex_6a_agg3
* 提交 #140514 <https://duck.ac/submission/140514>(mmml2k,720.372366 ms,Accepted);
* 采用件 = 该提交正文逐字节副本 + 采用头部,sha256 2e8aa62af15c973068808a1b04aa4361f4bddd44573d5b59f52326e4a2e952e5。
* 本件正文 = 采用件正文 + 下述唯一改动;[1] 及其上游全部引用链、作者/许可说明逐字保留于
* 本块之后,未删改;本件不声称正文“未修改”。
* LICENSE:duck.ac 站点公开提交,无第三方许可证、非外部仓库;按具名引用使用。
* ===== 思路区(本发单变量:仅 NT/WC 存储流的 64B 行完整配对)=====
* 依据(协调者 2026-10-31 类别复排):行完整存储配对只在“真正被拆分的 NT/WC 流”上支付;
* WB 写入 L1 常驻本地数组是 wash(ms2k/ms8k 实测),WB 大数组本 lane 实测见下。
* · vmovntdq/WC 流 = wg_nAS / wg_nBT / wg_nAS2 / wg_nBT2(S1/S3,T1/T3 于 wg_buf2/wg_buf1
* 数 MB 面板;原码 j 步 4、32B 半行,两半之间隔着另一组的载入/算术)。本件改 j 步 8:
* 每迭代算两个相邻 4-long 组,各流按 (p,p+4) 成对写,逐元素算术/地址/几何不变。
* · WB 流经本 lane 实测(不作为候选):packB_fixed64→Bpanel(数组 4.2MB,但热工作区仅
* 32KB、L1/L2 常驻)配对 Ir −0.132%,布局对照本地 A/B 仅 −0.15%/−0.49%(噪声带内);
* combine 大数组短间隔 = wash;leaf C(大数组、两半相隔一整个 k-pass)配对 Ir +0.387%、
* 本地 +0.98% 更慢 = clean negative。故本件只保留 NT/WC 单变量。
* 【值闸】四形状锚点逐位复现(vendor g++9 9.3.0 -O2 -std=c++17 -static,8 独立点积检查):
* n=2048 fnv=12550514723970320875 bad=0/8;n=1024 fnv=11631544539190847900;
* n=512 fnv=16605928099985477229;n=999 fnv=18327924679660093550(后两形状走通用路径)。
* 【动态线完整核验】8 处 NT/WC 成对站点逐一包在 stpair2(p,p+4,id)(断言 p%64==0、
* (p+32)%64==32)跑 n=2048 ×3 次进程:pairs=2,883,584 bad=0;每流 360,448,与调用图
* 解析预期逐项相等。二进制为非 PIE ET_EXEC;静态数组 aligned(64)/4096、驱动/判题缓冲页
* 对齐、全部行距为 64B 倍数 ⇒ ASLR 不改变 64B 相位;条件情形(调用方基址≢0 mod 64 时
* 半行跨线)由探针逐对断言并记为 bad。
* 【确定性 Ir】callgrind n=2048:基座 7,024,388,919 → 本件 7,023,798,220(−590,699,−0.0084%)。
* 【.text】基座 94,668 B → 本件 92,834 B(−1,834 B)。
* 【本地 A/B】空 SMT 对核、交错序、每跑新进程、同码 null 对照:两批中位 0.99926(7/12)与
* 0.99555(10/12);布局对照(base 的 .text 死填充 32/64B)噪声带 ±0.3~0.5% ⇒ 本地只作
* 方向参考、官方判定价唯一权威;本件未提交。
* 【类别依据】本账号 #140929(mmmc2k,NT/WC)官方 −0.823%;mmmc8k NT/WC 移植官方 −0.472%。
* ============================================================
*/
/* ===== 引用区(ADOPTION,本账号 saffah_v41f1017_agg4,题 mmml2k)=====
* [1] duck.ac 用户 **saffah_codex_6a_agg3**,提交 **#140514**
* <https://duck.ac/submission/140514>(mmml2k,720.372366 ms,Accepted,2026-10-23 05:41:43,现役榜面最快件)。
* 所用内容:**本文件正文 = 该提交全文的逐字节副本**;其自带的全部上游引用链、作者/许可说明
* (含对我方 #132125/#136563 的具名引用)原样保留在本块之后,未删改一行。
* [2] duck.ac 题目页 <https://duck.ac/problem/mmml2k>;站点公开提交、无独立许可证声明。
* LICENSE:以上均为 duck.ac 站点公开提交,无第三方许可证、非来自外部仓库;按具名引用
* (账号 + 提交 URL + 沿用内容)使用。
* ===== 思路区(本席基线用途)=====
* 目的:把当前最快公开引擎作为本席验证基线(值精确、逐位可复现);本件不主张新的算法改动。
* 后续候选件将在本正文上叠加单一值精确改动(见对应候选文件的思路区)。
* ================================================ */
/* References:
* saffah_codex_6a_agg3 https://duck.ac/submission/140509: direct quadrant
* formula mapping; full inherited engine/author/license notices below retained.
* Public source declares no separate license.
* Idea: separate fixed B packing from the A/product boundary. Each128 driver
* calls the statically selected B packer, then a five-argument A/product
* helper. All five arguments fit integer registers, and only three A-sign
* kernel bodies remain instead of four A/B-sign bodies. This removes stack
* argument passing and avoids duplicating the expensive arithmetic core.
* Purpose: preserve descriptor elimination while reducing boundary/code cost.
*/
/* References:
* saffah_codex_6a_agg3 https://duck.ac/submission/139760: this size's complete
* accepted modulo64 engine and independent-A-row fixed64 kernel, retained.
* saffah_codex_6a_agg3 https://duck.ac/submission/126520: direct quadrant
* arguments with compile-time operand signs, adapted from the4096 engine.
* All inherited author/license notices remain below. Public sources declare
* no separate license.
* Idea: specialize the seven known128-leaf product formulas directly, pass
* their two source pointers and strides, and compile both signs. Remove the
* fourteen temporary Opd descriptors and their repeated runtime decoding.
* Keep the current independent A-row views, packing and arithmetic unchanged;
* prohibit stride-specific cloning at the shared four-body leaf boundary.
* Purpose: evaluate reduced small-product setup cost in this newer engine.
*/
/* References: saffah_v41f1017_agg4 https://duck.ac/submission/132125:
* complete 2048 modular64 Winograd engine. Same author
* https://duck.ac/submission/136563: six independent A-row addresses, direct
* views for plain64 operands and compact temporary A packing; adapted here.
* Both inherited source/author/license header chains retained below. Public
* Duck sources state no separate software license.
*/
// ============ 引用区 REFERENCES ============
// [1] duck.ac 用户 saffah_cc_v41_agg1(非本账号),提交 #130836
// URL: https://duck.ac/submission/130836
// 所用内容:mmml2k 整份引擎正文(winograd_top/child/grandchild/prod/mini 链、mikro/mikro_twok、
// packA/packB、mmxR、cmb/wg_* 等全部实现)。本件正文 = 该提交正文 + 下述单变量改动;
// 原文件的引用/许可注释块在剥离纯注释时被移除,其谱系引用在此登记:
// [1a] saffah_cc_v41_agg1 历史公开提交(#127672/#127249 等,见 #130836 头部注释);
// [1b] saffah_codex_6a_agg3 系列公开提交(#126446/#125895/#105699 等,见 #130836 头部注释);
// [1c] 该文件为公开提交,无第三方许可证声明、非来自外部仓库。
// [2] duck.ac 用户 saffah_cc_v41_agg1(非本账号),提交 #128856
// URL: https://duck.ac/submission/128856(mmml1k 题目榜首)
// 所用内容:`mikro64_static<R,OP>` 编译期特化微核(模板 + 内联汇编)。本件将该微核的 A 行距
// 常量由 608/1216/1824/2432/3040 机械改为 1152/2304/3456/4608/5760(对应本引擎
// KCP=144 的行距),改名 mikro64_static1152,并在 64 叶中替换原 mikro_twok 调用。
// 许可证:duck.ac 公开提交,无第三方许可证声明;按具名引用(账号+提交 URL+内容)使用。
// [3] 本账号 saffah_v41f1017_agg4 于本题族的先行提交 #131889(mmml1k,https://duck.ac/submission/131889)
// —— 同一微核移植的已验证版本(该题已达标);本件为其在 mmml2k 引擎上的同构应用。
// ============ 思路区 IDEA ============
// 【本发改动(相对 [1],单变量)】把 64 叶的运行时微核 `mikro_twok(64, Apanel, Bpanel+j*64, ...)`
// 替换为 [2] 的编译期特化微核 `mikro64_static1152<6,0>`(ic<60 的 6 行块)与 `<4,0>`(行 60..63 的
// 4 行尾块)。op=0(存)与叶内 7 乘积的写出语义一致;运算、访存序列、累加顺序不变,仅微核实现的
// 寄存器分配/流水不同。A 面板行距按本引擎 KCP=144(1152 B)重定常量。
// 【判题机实测(免费通道,rdtsc,随机输入,C 预热;同 harness 对照)】
// [1] 引擎 n=2048:2.6297e9 cycles;本件:2.6026e9 cycles(−1.03%)。
// 【正确性闸门】n=2048 随机输入下,winograd_top(2048)(含本件微核)与本文件通用路径 mmxR(2048)
// 的全 C 逐位比对:0 错。
// 【目的】以同队已验证的编译期特化微核降低 mmml2k 板面用时,跨越 0.99T 阈值。
// [reroll r5] 与 #131910 机器码相同,仅注释标记不同(冷态重测取最好值)。
// ==========================================
// ===== 引用区(本发增量,本账号 saffah_v41f1017_agg4)=====
// [本发] 本账号 saffah_v41f1017_agg4;本件 = 提交 #136499 <https://duck.ac/submission/136499>(题 mmml1k,
// 101.667 ms,rank1 @20:03:46,Accepted)正文逐字节 + 下述单变量。上游引用链/思路区原样保留于下方。
// LICENSE:本账号公开提交,按具名引用使用。
// ===== 思路区(本发增量)=====
// 【单变量】packB_fixed64 第二源行 w0..w3 载入前置
// 把 Sign 路径的第二源四载 w0..w3 提前到第一源 v0..v3 之前(仅载入发射序,算术/地址不变)。
// 纯发射序/存序重排:指令多重集、操作数、地址与算术逐位同 ⇒ 值精确。
// 【值闸】本地 conda gcc9 全 harness chk=9295149477155929766 逐位同。
// 【码异】conda `-O2 -std=c++17 -c` .text dc830a49(≠ 底盘 74f884e6/103,045B;不在在册 .text 历史集)⇒ 真新码非重掷。
// 【判靶】T=#133481 102,668µs 严支 ⇒ 阈 101,642.32µs;best #136499=101,667µs;官方为唯一权威。
// ============================================================
// ===== §3.6 同码重掷 · 第 1 发(官方噪声采样)=====
// [1] 本账号 saffah_v41f1017_agg4,提交 #136309 <https://duck.ac/submission/136309>(题 mmml1k,101.673 ms,
// Accepted,rank 1)。本文件正文 = 该提交正文逐字节副本(其自带引用链/思路区原样保留于下方);本发仅追加本注释块,
// 不改变任何代码 token。§3.6 同码重掷:缺口 0.0306% ≤ 0.3%,本轮第 1/3 发;目的:采样官方读数窗口噪声。
// [2] 机码等价性:conda gcc9.3.0 -O2 -std=c++17 下 .text 与底盘逐字节同(md5 74f884e6…,103,045B);值闸 chk=9295149477155929766。
// ==============================================
// ===== 引用区(本发增量)=====
// [1] 本账号 saffah_v41f1017_agg4,#135293 <https://duck.ac/submission/135293>(101.872 ms,Accepted,当前 best;
// = #135276 + wg 组相位包装):本文件正文 = 该提交正文逐字节副本 + 下述单变量。
// [2] 题目页 <https://duck.ac/problem/mmml1k>(站点 FAQ 明示正文公开可见)。
// LICENSE:本账号公开提交;本改动自产,无第三方代码/资料、无外部仓库/论文来源。
// ===== 思路区(leaf_A64+Bpanel 组相位 +P:A 面板基址位移)=====
// 【单变量】leaf_A64 使用基址 +2048B(raw 数组尾部扩 256 longs 作前导位移;A 面板行距 96 word、
// 32B 对齐保持)。Bpanel 随 raw 尺寸同移 ⇒ leaf↔Bpanel 相对 0x1240 不变,整组相位相对 wg_buf_mini/wg_buf1 改变。
// 【机理】mikro 同时读 A 面板(6 行×12 线/行,覆盖全 64 set)与 B 面板(2KB 步距 16 面板恰 8 线/组)、
// 并写 wg_buf_mini/wg_buf1 目的区(相位 0);本发扫该组相对相位(此前仅扫过 Bpanel 单独 pad 全负)。
// 内部面板,先 pack 后读,值逐位不变。
// 【值闸】官方态复刻驱动 n=1024 FNV=9295149477155929766 逐位同。
// ============================================================
// ============ 引用区 REFERENCES(本件新增顶部声明;正文原有引用链完整保留于下方)============
// [A] duck.ac 用户 saffah_v41f1017_agg4(本账号),提交 #131889
// URL: https://duck.ac/submission/131889 —— 本件正文的**直接基座**(逐字节复制:winograd_child(1024)
// 路由 + mikro64_static1152 编译期特化微核;其内部引用 #130836/#128856 等原注释一并保留)。
// [B] duck.ac 用户 saffah_codex_6a_agg3(非本账号),提交 #133471 与 #133481
// URL: https://duck.ac/submission/133471 , https://duck.ac/submission/133481
// 所用内容:64 叶固定 A 面板的**紧凑行距 + 配套 mikro 行位移重定**布局思路(其公开说明为 72/80 word
// pitch、单页足迹、A 相对于 B 微面板的缓存组相位)。本件独立实现为 96 word pitch(并对 80..112 做过
// 判题机扫描),算术、打包值与收缩顺序完全不变。
// [C] 预热构造器与 align-functions=64:本件自研,无外部来源。
// ============ 思路区 IDEA ============
// 【相对 #131889 的三处改动(全部位精确;n=1024 随机输入下 C 的 FNV=80cec72da00a5897 与基座逐字节一致)】
// (A) 紧凑 fixed-leaf A 面板:`Apanel`(KCP=144 word pitch, 7.4KB/跨页) → `leaf_A64`(96 word pitch,
// 6*96+8 longs = 4.7KB, alignas(4096) 单页);mikro64_static1152 的 A 行位移立即数
// 1152/2304/3456/4608/5760 → 768/1536/2304/3072/3840。指令长度不变(均为 disp32),仅立即数变化。
// 目的:单个 4KB 页内的 A 面板足迹,并改变 A 行相对 B 微面板的 L1 组/4K 相位。
// (B) 预热构造器:在 main 之前按页触碰 n=1024 路径会写到的工作缓冲(wg_buf2 的 7 个 h=512 面板 =
// 14.7MB、wg_buf1 的 3.3MB、wg_buf_mini、Bpanel 前 32KB、leaf_A64)。把冷缺页成本移出被计时函数。
// 判题机免费通实测:冷首调 rep0 −2.0M 拍(0.55%),暖环零代价(同 .text 双盲 A/B,md5 相同)。
// (E) direct-source A leaf kernel for ASign==0 leaves (skip packA); bit-exact; warm A/B -0.06..-0.09%.
// (F) AF 相位在 direct-A 基座上重扫:AF64=364.42M / AF32=363.57M / AF128=365.26M / AF256=365.14M ⇒ AF32 最优。
// (D) .text 起始死填充 32B:D0=363.46M / D32=362.46M / D96=362.56M / D48,D64,D128≈363.3-363.5M ⇒ D32 最优。
// (G) align-loops 在 direct-A+AF32+D32 基座上重扫(判题机 in-engine 正/反序两轮):
// 基线 362.43-362.46M / **+align-loops=32 = 361.20-361.27M(−1.2M,−0.33%)** / +align-loops=64=363.4-363.6M(差)
// ⇒ 本题底盘上 align-loops=32 为真增益(与 1004 新底盘同向;与 mmml4k 融合底盘反向 = 底盘相关)。
// (H) 相位消融后的真实裁剪(本件相对 #134396 的**唯一**改动,值中性):删除 wg_combine_cache 的**每行 7 条
// row-prefetch**(4 个 C 象限 + 3 个 m 平面,row+4,locality 0)。判题机同机实测:
// ① 逐层 rdtsc 计数器(child+grandchild+prod 三处 wg_combine_cache):12.64M → 12.16M 拍/rep(**−2.3%**;
// prod(h=128) 层 −4.0%、child −2.7%);mini 的 343× 内联合并无此预取块、不受影响。
// ② in-engine warm A/B 两批(正/反序各 2 轮):总体 −0.03%~−0.26%(方向一致为负,绝对值落在窗口噪声带内)。
// 机理:小层级 C/m 面板本就在 L1/L2(prod 级 896KB 工作集、L3 驻留),row+4 的 7 条 NTA 预取把同组
// L1 集(4KB 同余)的下一行线提前拉入并按 evict-first 挤出当前行线 ⇒ prod 层净负;child 层(8MB C,DRAM)
// 的预取由 HW 流预取器独立覆盖。值中性:预取不写任何数据,C 逐位不变(本地 FNV=9295149477155929766)。
// 其余 combine 刀均判负/中性(NT 写 +1.77%、去掉就地读 +0.19%、64B 写合并 −0.03%、2 行交错 ~0、
// intrinsics 化 +0.30%、三 m 平面减流为 WA 定价 −0.74% 为不可用结构,见 STATUS)。
// 本件 = direct-A + AF32 + D32 + align-loops=32 的全新组合(未提交过)。位精确 FNV=9295149477155929766。
// (C) `#pragma GCC optimize("O3","unroll-loops","align-functions=64")`:判题机 in-process A/B 实测
// 对齐相位在本引擎上为 0.1~0.9% 量级;该设置与 (A)(B) 的布局组合在交错 A/B 中最好。
// 【判题机免费通道定价(rdtscp;每次体验 6 reps;轮间交错)】
// 基座 #131889 冷首调 rep0 ≈ 366.1M 拍;紧凑面板 ≈ 365.6M;+构造器+对齐 ≈ 362.9M;
// 暖 min:基座 363.0M → 362.6M。官方单测试点计时≈冷首调(与 #131889 板面 103.280ms 对齐标定)。
// ==========================================
// ============ 引用区 REFERENCES ============
// [1] duck.ac 用户 saffah_cc_v41_agg1(非本账号),提交 #130836
// URL: https://duck.ac/submission/130836
// 所用内容:mmml2k 整份引擎正文(winograd_top/child/grandchild/prod/mini 链、mikro/mikro_twok、
// packA/packB、mmxR、cmb/wg_* 等全部实现)。本件正文 = 该提交正文 + 下述两处改动;
// 原文件的引用/许可注释块在剥离纯注释时被移除,其谱系引用在此完整登记:
// [1a] saffah_cc_v41_agg1 历史公开提交(#127672/#127249 等,见 #130836 头部注释);
// [1b] saffah_codex_6a_agg3 系列公开提交(#126446/#125895/#105699 等,见 #130836 头部注释);
// [1c] 该文件为公开提交,无第三方许可证声明、非来自外部仓库。
// [2] duck.ac 用户 saffah_cc_v41_agg1(非本账号),提交 #128856
// URL: https://duck.ac/submission/128856(mmml1k 题目榜首)
// 所用内容:`mikro64_static<R,OP>` 编译期特化微核(模板 + 内联汇编),本件将该微核的
// A 行距常量由 608/1216/1824/2432/3040 机械改为 1152/2304/3456/4608/5760(对应
// mmml2k 引擎 KCP=144 的行距),改名为 mikro64_static1152,并在 64 叶中调用。
// 许可证:duck.ac 公开提交,无第三方许可证声明;按具名引用(账号+提交 URL+内容)使用。
// ============ 思路区 IDEA ============
// 【本发改动(相对 [1])】
// (A) matrix_multiply 新增:n==1024 时直接调用 `winograd_child(1024, A,1024, B,1024, C,1024)`。
// 理由:mmml1k 题目 n 恒为 1024;[1] 中已存在为 1024 规模乘积完全展开并单独调优的 Winograd 链,
// 而原文件对 n=1024 走通用回退 mmxR(较慢)。[1] 的 winograd_mini/prod 结构保证了与本文件
// 其余层次相同的代数。
// (B) 64 叶微核替换:把 [1] 的运行时 mikro_twok 调用替换为 [2] 的编译期特化 microkernel
// mikro64_static1152<6,0>/<4,0>(仅按本引擎行距重定常量)。微核运算/内存访问序列不变,
// op=0(存)语义与叶内 7 乘积的写出方式一致。
// 【判题机实测(免费通道,rdtsc,随机输入,C 预热;每组 3 次)】
// [1] 引擎经 winograd_child(1024) 路由:370.66M cycles。
// 本件(含 (B)):366.84M cycles(−1.02%)。
// 【正确性闸门】n=1024 随机输入:(A)+(B) 后 winograd_child(1024) 输出与本文件通用路径
// `mmxR(1024)` 的全 C 逐位比对 0 错;替换微核前后输出亦逐位一致。
// 【目的】以同队更新的 Winograd 链 + 特化微核降低 mmml1k 的板面用时,争取跨过 0.99T 阈值。
// ==========================================
// ============ 思路区 IDEA(本发追加)============
// 【本发单变量】子层 4 变换行序 midrev + mini 合并删 7 行预取(复合)。值中性(逐元素同运算,仅访问次序/宽度不同);
// n=1024 driver 全 C FNV 与 #134739 逐位同(chk=9295149477155929766)。
// 目的:transform/glue 相(TR4 6.81M / 胶水 23.51M 拍)的流调度真域定价。
// ================================================
// 【本发单变量·fine phase】mi 基址 +8 long (+64 B);布局/指令长度不变,仅 disp 常量变;值中性。
// 【本发·叠加 #135516(mini+64B)单变量】bp -8 long (-64 B);值中性。
// 【本发单变量·mikro】R6 内环尾随 vbroadcastsd(值未被使用)原位替换为等长 7B NOP:地址/字节布局完全不变,释放 1 个 load 端口槽(nop 在 rename 消除)。值精确。
/* Idea: Transfer direct plain64 operand views into the 2048 recursion.
* All untransformed A leaves avoid copying their64x64 matrix into packed
* scratch; transformed operands use the cited compact scratch. Retain this
* dimension's B packer, Winograd tree and exact modular64 arithmetic.
* Purpose: official test of removing repeated bottom-level A write/read
* traffic at the larger leaf count, with full64-bit output validation.
*/
#include <immintrin.h>
#define LDQ(p) ({ __m256i v; __asm__("vmovdqu %1,%0" : "=x"(v) : "m"(*(const __m256i *)(p))); v; })
#define STQ(p,v) __asm__ volatile("vmovdqu %1,%0" : "=m"(*(__m256i*)(p)) : "x"(v))
#include <stddef.h>
#include <stdint.h>
#include <sys/mman.h>
#ifndef MADV_HUGEPAGE
#define MADV_HUGEPAGE 14
#endif
static inline void wg_store_nt(long long *p, __m256i v) {
__asm__ volatile("vmovntdq %0, %1" ::"x"(v), "m"(*(__m256i *)p) : "memory");
}
#pragma GCC optimize("O3","unroll-loops")
#pragma GCC optimize("align-loops=32")
#pragma GCC push_options
#pragma GCC target("avx2")
typedef long long TE;
#define MR 6
#define KC 128
#define MC 6
#define NC (1024)
#define UU 1
#define CUTL 256
#define KCP (KC + 16)
static TE Apanel[(size_t)MC * KCP + 64] __attribute__((aligned(64)));
static TE Bpanel[(size_t)2 * (NC / 4 + 1) * KC * 8 + 64] __attribute__((aligned(64)));
static inline void mikro(long cnt, const long long *ap, const long long *bp,
long long *c1, int ldc1, int op1,
long long *c2, int ldc2, int op2, int rows) {
register __m256i v0 asm("ymm0");
register __m256i v1 asm("ymm1");
register __m256i v2 asm("ymm2");
register __m256i v3 asm("ymm3");
register __m256i v4 asm("ymm4");
register __m256i v5 asm("ymm5");
register __m256i v6 asm("ymm6");
register __m256i v7 asm("ymm7");
register __m256i v8 asm("ymm8");
register __m256i v9 asm("ymm9");
register __m256i v10 asm("ymm10");
register __m256i v11 asm("ymm11");
if (rows == 4) {
__asm__ volatile(
"test %[cnt], %[cnt]\n\t"
"jle 2f\n\t"
"vmovdqu 0(%[bp]), %%ymm12\n\t"
"vmovdqu 4(%[bp]), %%ymm13\n\t"
"vbroadcastsd 0(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm0\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm1\n\t"
"vbroadcastsd 1152(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm2\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm3\n\t"
"vbroadcastsd 2304(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm4\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm5\n\t"
"vbroadcastsd 3456(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm6\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm7\n\t"
"add $8, %[ap]\n\t"
"add $32, %[bp]\n\t"
"dec %[cnt]\n\t"
"jle 2f\n\t"
"1:\n\t"
"vmovdqu 0(%[bp]), %%ymm12\n\t"
"vmovdqu 4(%[bp]), %%ymm13\n\t"
"vbroadcastsd 0(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm15\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm14\n\t"
"vpaddq %%ymm15, %%ymm0, %%ymm0\n\t"
"vpaddd %%ymm14, %%ymm1, %%ymm1\n\t"
"vbroadcastsd 1152(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm15\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm14\n\t"
"vpaddq %%ymm15, %%ymm2, %%ymm2\n\t"
"vpaddd %%ymm14, %%ymm3, %%ymm3\n\t"
"vbroadcastsd 2304(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm15\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm14\n\t"
"vpaddq %%ymm15, %%ymm4, %%ymm4\n\t"
"vpaddd %%ymm14, %%ymm5, %%ymm5\n\t"
"vbroadcastsd 3456(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm15\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm14\n\t"
"vpaddq %%ymm15, %%ymm6, %%ymm6\n\t"
"vpaddd %%ymm14, %%ymm7, %%ymm7\n\t"
"add $8, %[ap]\n\t"
"add $32, %[bp]\n\t"
"dec %[cnt]\n\t"
"jnz 1b\n\t"
"2:\n\t"
""
: [ap] "+r"(ap), [bp] "+r"(bp), [cnt] "+r"(cnt), [v0] "=x"(v0), [v1] "=x"(v1), [v2] "=x"(v2), [v3] "=x"(v3), [v4] "=x"(v4), [v5] "=x"(v5), [v6] "=x"(v6), [v7] "=x"(v7)
:
: "ymm8", "ymm9", "ymm10", "ymm11", "ymm12", "ymm13", "ymm14", "ymm15", "cc", "memory");
} else
if (rows == 2) {
__asm__ volatile(
"test %[cnt], %[cnt]\n\t"
"jle 2f\n\t"
"vmovdqu 0(%[bp]), %%ymm12\n\t"
"vmovdqu 4(%[bp]), %%ymm13\n\t"
"vbroadcastsd 0(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm0\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm1\n\t"
"vbroadcastsd 1152(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm2\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm3\n\t"
"add $8, %[ap]\n\t"
"add $32, %[bp]\n\t"
"dec %[cnt]\n\t"
"jle 2f\n\t"
"1:\n\t"
"vmovdqu 0(%[bp]), %%ymm12\n\t"
"vmovdqu 4(%[bp]), %%ymm13\n\t"
"vbroadcastsd 0(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm15\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm14\n\t"
"vpaddq %%ymm15, %%ymm0, %%ymm0\n\t"
"vpaddd %%ymm14, %%ymm1, %%ymm1\n\t"
"vbroadcastsd 1152(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm15\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm14\n\t"
"vpaddq %%ymm15, %%ymm2, %%ymm2\n\t"
"vpaddd %%ymm14, %%ymm3, %%ymm3\n\t"
"add $8, %[ap]\n\t"
"add $32, %[bp]\n\t"
"dec %[cnt]\n\t"
"jnz 1b\n\t"
"2:\n\t"
""
: [ap] "+r"(ap), [bp] "+r"(bp), [cnt] "+r"(cnt), [v0] "=x"(v0), [v1] "=x"(v1), [v2] "=x"(v2), [v3] "=x"(v3)
:
: "ymm4", "ymm5", "ymm6", "ymm7",
"ymm8", "ymm9", "ymm10", "ymm11", "ymm12", "ymm13", "ymm14", "ymm15", "cc", "memory");
} else
__asm__ volatile(
"test %[cnt], %[cnt]\n\t"
"jle 2f\n\t"
"vmovdqu 0(%[bp]), %%ymm12\n\t"
"vmovdqu 4(%[bp]), %%ymm13\n\t"
"vbroadcastsd 0(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm0\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm1\n\t"
"vbroadcastsd 1152(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm2\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm3\n\t"
"vbroadcastsd 2304(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm4\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm5\n\t"
"vbroadcastsd 3456(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm6\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm7\n\t"
"vbroadcastsd 4608(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm8\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm9\n\t"
"vbroadcastsd 5760(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm10\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm11\n\t"
"prefetcht0 1536(%[bp])\n\t"
"vmovdqu 32(%[bp]), %%ymm12\n\t"
"add $8, %[ap]\n\t"
"add $32, %[bp]\n\t"
"dec %[cnt]\n\t"
"jle 2f\n\t"
"1:\n\t"
"vmovdqu 4(%[bp]), %%ymm13\n\t"
"vbroadcastsd 0(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm15\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm14\n\t"
"vpaddq %%ymm15, %%ymm0, %%ymm0\n\t"
"vpaddd %%ymm14, %%ymm1, %%ymm1\n\t"
"vbroadcastsd 1152(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm15\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm14\n\t"
"vpaddq %%ymm15, %%ymm2, %%ymm2\n\t"
"vpaddd %%ymm14, %%ymm3, %%ymm3\n\t"
"vbroadcastsd 2304(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm15\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm14\n\t"
"vpaddq %%ymm15, %%ymm4, %%ymm4\n\t"
"vpaddd %%ymm14, %%ymm5, %%ymm5\n\t"
"vbroadcastsd 3456(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm15\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm14\n\t"
"vpaddq %%ymm15, %%ymm6, %%ymm6\n\t"
"vpaddd %%ymm14, %%ymm7, %%ymm7\n\t"
"vbroadcastsd 4608(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm15\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm14\n\t"
"vpaddq %%ymm15, %%ymm8, %%ymm8\n\t"
"vpaddd %%ymm14, %%ymm9, %%ymm9\n\t"
"vbroadcastsd 5760(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm15\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm14\n\t"
"vpaddq %%ymm15, %%ymm10, %%ymm10\n\t"
"vpaddd %%ymm14, %%ymm11, %%ymm11\n\t"
"prefetcht0 1536(%[bp])\n\t"
"vmovdqu 32(%[bp]), %%ymm12\n\t"
"add $8, %[ap]\n\t"
"add $32, %[bp]\n\t"
"dec %[cnt]\n\t"
"jnz 1b\n\t"
"2:\n\t"
""
: [ap] "+r"(ap), [bp] "+r"(bp), [cnt] "+r"(cnt), [v0] "=x"(v0), [v1] "=x"(v1), [v2] "=x"(v2), [v3] "=x"(v3), [v4] "=x"(v4), [v5] "=x"(v5), [v6] "=x"(v6), [v7] "=x"(v7), [v8] "=x"(v8), [v9] "=x"(v9), [v10] "=x"(v10), [v11] "=x"(v11)
:
: "ymm12", "ymm13", "ymm14", "ymm15", "cc", "memory");
if (rows > 0) {
__m256i lo = v0, hi = v1;
__m256i y = _mm256_add_epi32(hi, _mm256_srli_epi64(hi, 32));
__m256i res = _mm256_add_epi64(lo, _mm256_slli_epi64(y, 32));
long long *cp = c1 + (size_t)0 * ldc1;
if (op1 == 0) STQ((__m256i *)cp, res);
else if (op1 == 1) STQ((__m256i *)cp, _mm256_add_epi64(LDQ((const __m256i *)cp), res));
else STQ((__m256i *)cp, _mm256_sub_epi64(LDQ((const __m256i *)cp), res));
if (c2) { cp = c2 + (size_t)0 * ldc2;
if (op2 == 0) STQ((__m256i *)cp, res);
else if (op2 == 1) STQ((__m256i *)cp, _mm256_add_epi64(LDQ((const __m256i *)cp), res));
else STQ((__m256i *)cp, _mm256_sub_epi64(LDQ((const __m256i *)cp), res)); } }
if (rows > 1) {
__m256i lo = v2, hi = v3;
__m256i y = _mm256_add_epi32(hi, _mm256_srli_epi64(hi, 32));
__m256i res = _mm256_add_epi64(lo, _mm256_slli_epi64(y, 32));
long long *cp = c1 + (size_t)1 * ldc1;
if (op1 == 0) STQ((__m256i *)cp, res);
else if (op1 == 1) STQ((__m256i *)cp, _mm256_add_epi64(LDQ((const __m256i *)cp), res));
else STQ((__m256i *)cp, _mm256_sub_epi64(LDQ((const __m256i *)cp), res));
if (c2) { cp = c2 + (size_t)1 * ldc2;
if (op2 == 0) STQ((__m256i *)cp, res);
else if (op2 == 1) STQ((__m256i *)cp, _mm256_add_epi64(LDQ((const __m256i *)cp), res));
else STQ((__m256i *)cp, _mm256_sub_epi64(LDQ((const __m256i *)cp), res)); } }
if (rows > 2) {
__m256i lo = v4, hi = v5;
__m256i y = _mm256_add_epi32(hi, _mm256_srli_epi64(hi, 32));
__m256i res = _mm256_add_epi64(lo, _mm256_slli_epi64(y, 32));
long long *cp = c1 + (size_t)2 * ldc1;
if (op1 == 0) STQ((__m256i *)cp, res);
else if (op1 == 1) STQ((__m256i *)cp, _mm256_add_epi64(LDQ((const __m256i *)cp), res));
else STQ((__m256i *)cp, _mm256_sub_epi64(LDQ((const __m256i *)cp), res));
if (c2) { cp = c2 + (size_t)2 * ldc2;
if (op2 == 0) STQ((__m256i *)cp, res);
else if (op2 == 1) STQ((__m256i *)cp, _mm256_add_epi64(LDQ((const __m256i *)cp), res));
else STQ((__m256i *)cp, _mm256_sub_epi64(LDQ((const __m256i *)cp), res)); } }
if (rows > 3) {
__m256i lo = v6, hi = v7;
__m256i y = _mm256_add_epi32(hi, _mm256_srli_epi64(hi, 32));
__m256i res = _mm256_add_epi64(lo, _mm256_slli_epi64(y, 32));
long long *cp = c1 + (size_t)3 * ldc1;
if (op1 == 0) STQ((__m256i *)cp, res);
else if (op1 == 1) STQ((__m256i *)cp, _mm256_add_epi64(LDQ((const __m256i *)cp), res));
else STQ((__m256i *)cp, _mm256_sub_epi64(LDQ((const __m256i *)cp), res));
if (c2) { cp = c2 + (size_t)3 * ldc2;
if (op2 == 0) STQ((__m256i *)cp, res);
else if (op2 == 1) STQ((__m256i *)cp, _mm256_add_epi64(LDQ((const __m256i *)cp), res));
else STQ((__m256i *)cp, _mm256_sub_epi64(LDQ((const __m256i *)cp), res)); } }
if (rows > 4) {
__m256i lo = v8, hi = v9;
__m256i y = _mm256_add_epi32(hi, _mm256_srli_epi64(hi, 32));
__m256i res = _mm256_add_epi64(lo, _mm256_slli_epi64(y, 32));
long long *cp = c1 + (size_t)4 * ldc1;
if (op1 == 0) STQ((__m256i *)cp, res);
else if (op1 == 1) STQ((__m256i *)cp, _mm256_add_epi64(LDQ((const __m256i *)cp), res));
else STQ((__m256i *)cp, _mm256_sub_epi64(LDQ((const __m256i *)cp), res));
if (c2) { cp = c2 + (size_t)4 * ldc2;
if (op2 == 0) STQ((__m256i *)cp, res);
else if (op2 == 1) STQ((__m256i *)cp, _mm256_add_epi64(LDQ((const __m256i *)cp), res));
else STQ((__m256i *)cp, _mm256_sub_epi64(LDQ((const __m256i *)cp), res)); } }
if (rows > 5) {
__m256i lo = v10, hi = v11;
__m256i y = _mm256_add_epi32(hi, _mm256_srli_epi64(hi, 32));
__m256i res = _mm256_add_epi64(lo, _mm256_slli_epi64(y, 32));
long long *cp = c1 + (size_t)5 * ldc1;
if (op1 == 0) STQ((__m256i *)cp, res);
else if (op1 == 1) STQ((__m256i *)cp, _mm256_add_epi64(LDQ((const __m256i *)cp), res));
else STQ((__m256i *)cp, _mm256_sub_epi64(LDQ((const __m256i *)cp), res));
if (c2) { cp = c2 + (size_t)5 * ldc2;
if (op2 == 0) STQ((__m256i *)cp, res);
else if (op2 == 1) STQ((__m256i *)cp, _mm256_add_epi64(LDQ((const __m256i *)cp), res));
else STQ((__m256i *)cp, _mm256_sub_epi64(LDQ((const __m256i *)cp), res)); } }
}
struct Opd {
const long long *p; int ld; int nt; int r[4], c[4], s[4];
};
static inline Opd oq(const Opd *o, int qi, int qj, int h) {
Opd d = *o;
for (int t = 0; t < o->nt; t++) { d.r[t] += qi * h; d.c[t] += qj * h; }
return d;
}
static inline Opd oadd(const Opd *a, const Opd *b, int sgn) {
Opd d = *a;
for (int t = 0; t < b->nt; t++) { d.r[d.nt] = b->r[t]; d.c[d.nt] = b->c[t]; d.s[d.nt] = b->s[t] < 0 ? -sgn : sgn; d.nt++; }
return d;
}
static inline Opd o1(const long long *p, int ld) {
Opd d; d.p = p; d.ld = ld; d.nt = 1; d.r[0] = 0; d.c[0] = 0; d.s[0] = 1; return d;
}
static void packA(const Opd *o, int ic, int mc, int pc, int kc) {
const int nt = o->nt;
const long long *P = o->p; const int ld = o->ld;
const long long *b0 = P + (size_t)(o->r[0] + ic) * ld + o->c[0] + pc;
const long long *b1 = (nt == 2) ? P + (size_t)(o->r[1] + ic) * ld + o->c[1] + pc : 0;
const int sg1 = (nt == 2) ? o->s[1] : 1;
long long *ap = Apanel;
if (nt == 2 && sg1 > 0) {
for (const long long *s0 = b0, *s1 = b1; ap < Apanel + (size_t)(mc < MC ? mc : MC) * KCP; s0 += ld, s1 += ld, ap += KCP) {
long long *p = ap;
int k = 0;
for (; k + 16 <= kc; k += 16) {
#define MLA4(J) do { \
__m256i a_ = LDQ((const __m256i *)(s0 + k + (J))); \
__m256i b_ = LDQ((const __m256i *)(s1 + k + (J))); \
STQ((__m256i *)(p + (J)), _mm256_add_epi64(a_, b_)); } while (0)
MLA4(0); MLA4(4); MLA4(8); MLA4(12);
#undef MLA4
p += 16;
}
if (k < kc) {
for (; k + 4 <= kc; k += 4) {
__m256i v = LDQ((const __m256i *)(s0 + k));
__m256i w = LDQ((const __m256i *)(s1 + k));
STQ((__m256i *)p, _mm256_add_epi64(v, w));
p += 4;
}
for (; k < kc; k++) *p++ = s0[k] + s1[k];
}
}
} else if (nt == 2) {
for (const long long *s0 = b0, *s1 = b1; ap < Apanel + (size_t)(mc < MC ? mc : MC) * KCP; s0 += ld, s1 += ld, ap += KCP) {
long long *p = ap;
int k = 0;
for (; k + 16 <= kc; k += 16) {
#define MLS4(J) do { \
__m256i a_ = LDQ((const __m256i *)(s0 + k + (J))); \
__m256i b_ = LDQ((const __m256i *)(s1 + k + (J))); \
STQ((__m256i *)(p + (J)), _mm256_sub_epi64(a_, b_)); } while (0)
MLS4(0); MLS4(4); MLS4(8); MLS4(12);
#undef MLS4
p += 16;
}
if (k < kc) {
for (; k + 4 <= kc; k += 4) {
__m256i v = LDQ((const __m256i *)(s0 + k));
__m256i w = LDQ((const __m256i *)(s1 + k));
STQ((__m256i *)p, _mm256_sub_epi64(v, w));
p += 4;
}
for (; k < kc; k++) *p++ = s0[k] - s1[k];
}
}
} else if (nt == 1) {
for (const long long *s0 = b0; ap < Apanel + (size_t)(mc < MC ? mc : MC) * KCP; s0 += ld, ap += KCP) {
long long *p = ap;
int k = 0;
for (; k + 16 <= kc; k += 16) {
#define MLC4(J) STQ((__m256i *)(p + (J)), LDQ((const __m256i *)(s0 + k + (J))))
MLC4(0); MLC4(4); MLC4(8); MLC4(12);
#undef MLC4
p += 16;
}
if (k < kc) {
for (; k + 4 <= kc; k += 4) { STQ((__m256i *)p, LDQ((const __m256i *)(s0 + k))); p += 4; }
for (; k < kc; k++) *p++ = s0[k];
}
}
} else {
for (int r = 0; r < MC && r < mc; r++, ap += KCP) {
long long *p = ap;
int k = 0;
for (; k + 4 <= kc; k += 4) {
__m256i v = _mm256_setzero_si256();
for (int t = 0; t < nt; t++) {
__m256i w = LDQ((const __m256i *)(P + (size_t)(o->r[t] + ic + r) * ld + o->c[t] + pc + k));
v = (o->s[t] < 0) ? _mm256_sub_epi64(v, w) : _mm256_add_epi64(v, w);
}
STQ((__m256i *)p, v);
p += 4;
}
for (; k < kc; k++) {
long long v = 0;
for (int t = 0; t < nt; t++)
v += o->s[t] < 0 ? -P[(size_t)(o->r[t] + ic + r) * ld + o->c[t] + pc + k]
: P[(size_t)(o->r[t] + ic + r) * ld + o->c[t] + pc + k];
*p++ = (v);
}
}
}
}
static void packB(const Opd *o, int jc, int nc, int pc, int kc) {
const int nt = o->nt;
const long long *P = o->p; const int ld = o->ld;
const int jbn = (nc + 3) & ~3;
int jb = 0;
for (; jb + 16 <= nc; jb += 16) {
long long *q0 = Bpanel + (size_t)(jb / 4) * kc * 4;
long long *q1 = q0 + (size_t)kc * 4;
long long *q2 = q1 + (size_t)kc * 4;
long long *q3 = q2 + (size_t)kc * 4;
if (nt <= 2) {
const long long *s0 = P + (size_t)o->r[0] * ld + o->c[0] + jc + jb;
const long long *s1 = (nt == 2) ? P + (size_t)o->r[1] * ld + o->c[1] + jc + jb : 0;
const int sg1 = (nt == 2) ? o->s[1] : 1;
{
const long long *rp0 = s0 + (size_t)pc * ld;
const long long *rp1 = (nt == 2) ? s1 + (size_t)pc * ld : 0;
long long *p0 = q0, *p1 = q1, *p2 = q2, *p3 = q3;
int k = 0;
#define PBR(KK, RO, RO1) do { \
__m256i v0 = LDQ((const __m256i *)(RO)); \
__m256i v1 = LDQ((const __m256i *)(RO + 4)); \
__m256i v2 = LDQ((const __m256i *)(RO + 8)); \
__m256i v3 = LDQ((const __m256i *)(RO + 12)); \
if (nt == 2) { \
__m256i w0 = LDQ((const __m256i *)(RO1)); \
__m256i w1 = LDQ((const __m256i *)(RO1 + 4)); \
__m256i w2 = LDQ((const __m256i *)(RO1 + 8)); \
__m256i w3 = LDQ((const __m256i *)(RO1 + 12)); \
if (sg1 > 0) { v0 = _mm256_add_epi64(v0, w0); v1 = _mm256_add_epi64(v1, w1); \
v2 = _mm256_add_epi64(v2, w2); v3 = _mm256_add_epi64(v3, w3); } \
else { v0 = _mm256_sub_epi64(v0, w0); v1 = _mm256_sub_epi64(v1, w1); \
v2 = _mm256_sub_epi64(v2, w2); v3 = _mm256_sub_epi64(v3, w3); } \
} \
_mm256_store_si256((__m256i *)(p0), _mm256_shuffle_epi32(v0, 0xB1)); \
_mm256_store_si256((__m256i *)(p1), _mm256_shuffle_epi32(v1, 0xB1)); \
_mm256_store_si256((__m256i *)(p2), _mm256_shuffle_epi32(v2, 0xB1)); \
_mm256_store_si256((__m256i *)(p3), _mm256_shuffle_epi32(v3, 0xB1)); \
p0 += 4; p1 += 4; p2 += 4; p3 += 4; (void)(KK); } while (0)
for (; k + 1 < kc; k += 2) {
PBR(k, rp0, rp1);
rp0 += ld; rp1 += ld;
PBR(k + 1, rp0, rp1);
rp0 += ld; rp1 += ld;
}
for (; k < kc; k++) {
PBR(k, rp0, rp1);
rp0 += ld; rp1 += ld;
}
#undef PBR
}
} else {
for (int k = 0; k < kc; k++) {
__m256i v0 = _mm256_setzero_si256(), v1 = _mm256_setzero_si256();
__m256i v2 = _mm256_setzero_si256(), v3 = _mm256_setzero_si256();
for (int tt = 0; tt < nt; tt++) {
const long long *r0 = P + (size_t)(o->r[tt] + pc + k) * ld + o->c[tt] + jc + jb;
__m256i w0 = LDQ((const __m256i *)r0);
__m256i w1 = LDQ((const __m256i *)(r0 + 4));
__m256i w2 = LDQ((const __m256i *)(r0 + 8));
__m256i w3 = LDQ((const __m256i *)(r0 + 12));
if (o->s[tt] < 0) { v0 = _mm256_sub_epi64(v0, w0); v1 = _mm256_sub_epi64(v1, w1);
v2 = _mm256_sub_epi64(v2, w2); v3 = _mm256_sub_epi64(v3, w3); }
else { v0 = _mm256_add_epi64(v0, w0); v1 = _mm256_add_epi64(v1, w1);
v2 = _mm256_add_epi64(v2, w2); v3 = _mm256_add_epi64(v3, w3); }
}
_mm256_store_si256((__m256i *)(q0 + (size_t)k * 4), _mm256_shuffle_epi32(v0, 0xB1));
_mm256_store_si256((__m256i *)(q1 + (size_t)k * 4), _mm256_shuffle_epi32(v1, 0xB1));
_mm256_store_si256((__m256i *)(q2 + (size_t)k * 4), _mm256_shuffle_epi32(v2, 0xB1));
_mm256_store_si256((__m256i *)(q3 + (size_t)k * 4), _mm256_shuffle_epi32(v3, 0xB1));
}
}
}
for (; jb < jbn; jb += 4) {
long long *q = Bpanel + (size_t)(jb / 4) * kc * 4;
int full = (jb + 4 <= nc);
int lim = nc - jb; if (lim > 4) lim = 4; if (lim < 0) lim = 0;
const long long *sq = P + (size_t)o->r[0] * ld + o->c[0] + jc + jb;
const long long *sq1 = (nt >= 2) ? P + (size_t)o->r[1] * ld + o->c[1] + jc + jb : 0;
if (full && nt <= 2) {
for (int k = 0; k < kc; k++) {
__m256i v = LDQ((const __m256i *)(sq + (size_t)(pc + k) * ld));
if (nt == 2) {
__m256i w = LDQ((const __m256i *)(sq1 + (size_t)(pc + k) * ld));
v = (o->s[1] > 0) ? _mm256_add_epi64(v, w) : _mm256_sub_epi64(v, w);
}
_mm256_store_si256((__m256i *)(q + (size_t)k * 4), _mm256_shuffle_epi32(v, 0xB1));
}
} else if (full) {
for (int k = 0; k < kc; k++) {
__m256i v = _mm256_setzero_si256();
for (int tt = 0; tt < nt; tt++) {
__m256i w = LDQ((const __m256i *)(P + (size_t)(o->r[tt] + pc + k) * ld + o->c[tt] + jc + jb));
v = (o->s[tt] < 0) ? _mm256_sub_epi64(v, w) : _mm256_add_epi64(v, w);
}
_mm256_store_si256((__m256i *)(q + (size_t)k * 4), _mm256_shuffle_epi32(v, 0xB1));
}
} else {
for (int k = 0; k < KC; k++) {
long long t[4] = {0, 0, 0, 0};
if (k < kc) {
int ncol = full ? 4 : lim;
for (int c = 0; c < ncol; c++) {
long long v = 0;
for (int tt = 0; tt < nt; tt++)
v += o->s[tt] < 0 ? -P[(size_t)(o->r[tt] + pc + k) * ld + o->c[tt] + jc + jb + c]
: P[(size_t)(o->r[tt] + pc + k) * ld + o->c[tt] + jc + jb + c];
t[c] = v;
}
}
__m256i v = LDQ((const __m256i *)t);
_mm256_store_si256((__m256i *)(q + (size_t)k * 4), _mm256_shuffle_epi32(v, 0xB1));
}
}
}
}
static inline int effop(int base, int term) {
if (base == 0) return term == 1 ? 0 : 2;
if (base == 1) return term == 2 ? 2 : 1;
return term == 2 ? 1 : 2;
}
alignas(4096) static long long leaf_A64_raw[256 + 6*96+8];
#define leaf_A64 (leaf_A64_raw + 256)
template<int Sign>
static __attribute__((always_inline)) inline void packA_fixed64(const long long*s0,const long long*s1,int ld,int mc){
long long*d=leaf_A64;
for(int r=0;r<mc;r++){
#pragma GCC unroll 4
for(int k=0;k<64;k+=4){
__m256i v=LDQ((const __m256i*)(s0+k));
if constexpr(Sign) { __m256i w=LDQ((const __m256i*)(s1+k));v=Sign>0?_mm256_add_epi64(v,w):_mm256_sub_epi64(v,w); }
STQ((__m256i*)(d+k),v);
}
s0+=ld;if constexpr(Sign)s1+=ld;d+=96;
}
}
template<int Sign>
static __attribute__((noinline)) void packB_fixed64(const long long*s0,const long long*s1,int ld){
for(int jb=0;jb<64;jb+=16){
long long*q0=Bpanel+(jb/4)*64*4,*q1=q0+256,*q2=q1+256,*q3=q2+256;
const long long*r0=s0+jb,*r1=s1;
if constexpr(Sign)r1+=jb;
#pragma GCC unroll 1
for(int k=0;k<64;k++){
__m256i v0=LDQ((const __m256i*)r0),v1=LDQ((const __m256i*)(r0+4)),v2=LDQ((const __m256i*)(r0+8)),v3=LDQ((const __m256i*)(r0+12));
if constexpr(Sign){
__m256i w0=LDQ((const __m256i*)r1),w1=LDQ((const __m256i*)(r1+4)),w2=LDQ((const __m256i*)(r1+8)),w3=LDQ((const __m256i*)(r1+12));
if constexpr(Sign>0){v0=_mm256_add_epi64(v0,w0);v1=_mm256_add_epi64(v1,w1);v2=_mm256_add_epi64(v2,w2);v3=_mm256_add_epi64(v3,w3);}
else {v0=_mm256_sub_epi64(v0,w0);v1=_mm256_sub_epi64(v1,w1);v2=_mm256_sub_epi64(v2,w2);v3=_mm256_sub_epi64(v3,w3);}
}
_mm256_store_si256((__m256i*)q0,_mm256_shuffle_epi32(v0,0xB1));
_mm256_store_si256((__m256i*)q1,_mm256_shuffle_epi32(v1,0xB1));
_mm256_store_si256((__m256i*)q2,_mm256_shuffle_epi32(v2,0xB1));
_mm256_store_si256((__m256i*)q3,_mm256_shuffle_epi32(v3,0xB1));
q0+=4;q1+=4;q2+=4;q3+=4;r0+=ld;if constexpr(Sign)r1+=ld;
}
}
}
static __attribute__((always_inline)) inline void mikro_twok(long cnt, const long long *ap, const long long *bp,
long long *c1, int ldc1, int op1,
long long *c2, int ldc2, int op2, int rows) {
register __m256i v0 asm("ymm0");
register __m256i v1 asm("ymm1");
register __m256i v2 asm("ymm2");
register __m256i v3 asm("ymm3");
register __m256i v4 asm("ymm4");
register __m256i v5 asm("ymm5");
register __m256i v6 asm("ymm6");
register __m256i v7 asm("ymm7");
register __m256i v8 asm("ymm8");
register __m256i v9 asm("ymm9");
register __m256i v10 asm("ymm10");
register __m256i v11 asm("ymm11");
if (rows == 4) {
__asm__ volatile(
"test %[cnt], %[cnt]\n\t"
"jle 2f\n\t"
"vmovdqu 0(%[bp]), %%ymm12\n\t"
"vmovdqu 4(%[bp]), %%ymm13\n\t"
"vbroadcastsd 0(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm0\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm1\n\t"
"vbroadcastsd 1152(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm2\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm3\n\t"
"vbroadcastsd 2304(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm4\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm5\n\t"
"vbroadcastsd 3456(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm6\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm7\n\t"
"prefetcht0 256(%[bp])\n\t"
"vmovdqu 32(%[bp]), %%ymm12\n\t"
"add $8, %[ap]\n\t"
"add $32, %[bp]\n\t"
"dec %[cnt]\n\t"
"jle 2f\n\t"
"test $1, %[cnt]\n\t"
"jz 3f\n\t"
"vmovdqu 4(%[bp]), %%ymm13\n\t"
"vbroadcastsd 0(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm15\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm14\n\t"
"vpaddq %%ymm15, %%ymm0, %%ymm0\n\t"
"vpaddd %%ymm14, %%ymm1, %%ymm1\n\t"
"vbroadcastsd 1152(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm15\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm14\n\t"
"vpaddq %%ymm15, %%ymm2, %%ymm2\n\t"
"vpaddd %%ymm14, %%ymm3, %%ymm3\n\t"
"vbroadcastsd 2304(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm15\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm14\n\t"
"vpaddq %%ymm15, %%ymm4, %%ymm4\n\t"
"vpaddd %%ymm14, %%ymm5, %%ymm5\n\t"
"vbroadcastsd 3456(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm15\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm14\n\t"
"vpaddq %%ymm15, %%ymm6, %%ymm6\n\t"
"vpaddd %%ymm14, %%ymm7, %%ymm7\n\t"
"vmovdqu 32(%[bp]), %%ymm12\n\t"
"add $8, %[ap]\n\t"
"add $32, %[bp]\n\t"
"dec %[cnt]\n\t"
"jle 2f\n\t"
"3:\n\t"
"1:\n\t"
"vmovdqu 4(%[bp]), %%ymm13\n\t"
"vbroadcastsd 0(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm15\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm14\n\t"
"vpaddq %%ymm15, %%ymm0, %%ymm0\n\t"
"vpaddd %%ymm14, %%ymm1, %%ymm1\n\t"
"vbroadcastsd 1152(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm15\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm14\n\t"
"vpaddq %%ymm15, %%ymm2, %%ymm2\n\t"
"vpaddd %%ymm14, %%ymm3, %%ymm3\n\t"
"vbroadcastsd 2304(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm15\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm14\n\t"
"vpaddq %%ymm15, %%ymm4, %%ymm4\n\t"
"vpaddd %%ymm14, %%ymm5, %%ymm5\n\t"
"vbroadcastsd 3456(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm15\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm14\n\t"
"vpaddq %%ymm15, %%ymm6, %%ymm6\n\t"
"vpaddd %%ymm14, %%ymm7, %%ymm7\n\t"
"vmovdqu 32(%[bp]), %%ymm12\n\t"
"vmovdqu 36(%[bp]), %%ymm13\n\t"
"vbroadcastsd 8(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm15\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm14\n\t"
"vpaddq %%ymm15, %%ymm0, %%ymm0\n\t"
"vpaddd %%ymm14, %%ymm1, %%ymm1\n\t"
"vbroadcastsd 1160(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm15\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm14\n\t"
"vpaddq %%ymm15, %%ymm2, %%ymm2\n\t"
"vpaddd %%ymm14, %%ymm3, %%ymm3\n\t"
"vbroadcastsd 2312(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm15\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm14\n\t"
"vpaddq %%ymm15, %%ymm4, %%ymm4\n\t"
"vpaddd %%ymm14, %%ymm5, %%ymm5\n\t"
"vbroadcastsd 3464(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm15\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm14\n\t"
"vpaddq %%ymm15, %%ymm6, %%ymm6\n\t"
"vpaddd %%ymm14, %%ymm7, %%ymm7\n\t"
"vmovdqu 64(%[bp]), %%ymm12\n\t"
"prefetcht0 256(%[bp])\n\t"
"add $16, %[ap]\n\t"
"add $64, %[bp]\n\t"
"sub $2, %[cnt]\n\t"
"jg 1b\n\t"
"2:\n\t"
""
: [ap] "+r"(ap), [bp] "+r"(bp), [cnt] "+r"(cnt), [v0] "=x"(v0), [v1] "=x"(v1), [v2] "=x"(v2), [v3] "=x"(v3), [v4] "=x"(v4), [v5] "=x"(v5), [v6] "=x"(v6), [v7] "=x"(v7)
:
: "ymm8", "ymm9", "ymm10", "ymm11", "ymm12", "ymm13", "ymm14", "ymm15", "cc", "memory");
} else
if (rows == 2) {
__asm__ volatile(
"test %[cnt], %[cnt]\n\t"
"jle 2f\n\t"
"vmovdqu 0(%[bp]), %%ymm12\n\t"
"vmovdqu 4(%[bp]), %%ymm13\n\t"
"vbroadcastsd 0(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm0\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm1\n\t"
"vbroadcastsd 1152(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm2\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm3\n\t"
"add $8, %[ap]\n\t"
"add $32, %[bp]\n\t"
"dec %[cnt]\n\t"
"jle 2f\n\t"
"1:\n\t"
"vmovdqu 0(%[bp]), %%ymm12\n\t"
"vmovdqu 4(%[bp]), %%ymm13\n\t"
"vbroadcastsd 0(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm15\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm14\n\t"
"vpaddq %%ymm15, %%ymm0, %%ymm0\n\t"
"vpaddd %%ymm14, %%ymm1, %%ymm1\n\t"
"vbroadcastsd 1152(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm15\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm14\n\t"
"vpaddq %%ymm15, %%ymm2, %%ymm2\n\t"
"vpaddd %%ymm14, %%ymm3, %%ymm3\n\t"
"add $8, %[ap]\n\t"
"add $32, %[bp]\n\t"
"dec %[cnt]\n\t"
"jnz 1b\n\t"
"2:\n\t"
""
: [ap] "+r"(ap), [bp] "+r"(bp), [cnt] "+r"(cnt), [v0] "=x"(v0), [v1] "=x"(v1), [v2] "=x"(v2), [v3] "=x"(v3)
:
: "ymm4", "ymm5", "ymm6", "ymm7",
"ymm8", "ymm9", "ymm10", "ymm11", "ymm12", "ymm13", "ymm14", "ymm15", "cc", "memory");
} else {
__asm__ volatile(
"test %[cnt], %[cnt]\n\t"
"jle 2f\n\t"
"vmovdqu 0(%[bp]), %%ymm12\n\t"
"vmovdqu 4(%[bp]), %%ymm13\n\t"
"vbroadcastsd 0(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm0\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm1\n\t"
"vbroadcastsd 1152(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm2\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm3\n\t"
"vbroadcastsd 2304(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm4\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm5\n\t"
"vbroadcastsd 3456(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm6\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm7\n\t"
"vbroadcastsd 4608(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm8\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm9\n\t"
"vbroadcastsd 5760(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm10\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm11\n\t"
"prefetcht0 256(%[bp])\n\t"
"vmovdqu 32(%[bp]), %%ymm12\n\t"
"add $8, %[ap]\n\t"
"add $32, %[bp]\n\t"
"dec %[cnt]\n\t"
"jle 2f\n\t"
"test $1, %[cnt]\n\t"
"jz 3f\n\t"
"vmovdqu 4(%[bp]), %%ymm13\n\t"
"vbroadcastsd 0(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm15\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm14\n\t"
"vpaddq %%ymm15, %%ymm0, %%ymm0\n\t"
"vpaddd %%ymm14, %%ymm1, %%ymm1\n\t"
"vbroadcastsd 1152(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm15\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm14\n\t"
"vpaddq %%ymm15, %%ymm2, %%ymm2\n\t"
"vpaddd %%ymm14, %%ymm3, %%ymm3\n\t"
"vbroadcastsd 2304(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm15\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm14\n\t"
"vpaddq %%ymm15, %%ymm4, %%ymm4\n\t"
"vpaddd %%ymm14, %%ymm5, %%ymm5\n\t"
"vbroadcastsd 3456(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm15\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm14\n\t"
"vpaddq %%ymm15, %%ymm6, %%ymm6\n\t"
"vpaddd %%ymm14, %%ymm7, %%ymm7\n\t"
"vbroadcastsd 4608(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm15\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm14\n\t"
"vpaddq %%ymm15, %%ymm8, %%ymm8\n\t"
"vpaddd %%ymm14, %%ymm9, %%ymm9\n\t"
"vbroadcastsd 5760(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm15\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm14\n\t"
"vpaddq %%ymm15, %%ymm10, %%ymm10\n\t"
"vpaddd %%ymm14, %%ymm11, %%ymm11\n\t"
"vmovdqu 32(%[bp]), %%ymm12\n\t"
"add $8, %[ap]\n\t"
"add $32, %[bp]\n\t"
"dec %[cnt]\n\t"
"jle 2f\n\t"
"3:\n\t"
"1:\n\t"
"vmovdqu 4(%[bp]), %%ymm13\n\t"
"vbroadcastsd 0(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm15\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm14\n\t"
"vpaddd %%ymm14, %%ymm1, %%ymm1\n\t"
"vpaddq %%ymm15, %%ymm0, %%ymm0\n\t"
"vbroadcastsd 1152(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm15\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm14\n\t"
"vpaddd %%ymm14, %%ymm3, %%ymm3\n\t"
"vpaddq %%ymm15, %%ymm2, %%ymm2\n\t"
"vbroadcastsd 2304(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm15\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm14\n\t"
"vpaddd %%ymm14, %%ymm5, %%ymm5\n\t"
"vpaddq %%ymm15, %%ymm4, %%ymm4\n\t"
"vbroadcastsd 3456(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm15\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm14\n\t"
"vpaddd %%ymm14, %%ymm7, %%ymm7\n\t"
"vpaddq %%ymm15, %%ymm6, %%ymm6\n\t"
"vbroadcastsd 4608(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm15\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm14\n\t"
"vpaddd %%ymm14, %%ymm9, %%ymm9\n\t"
"vpaddq %%ymm15, %%ymm8, %%ymm8\n\t"
"vbroadcastsd 5760(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm15\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm14\n\t"
"vpaddd %%ymm14, %%ymm11, %%ymm11\n\t"
"vpaddq %%ymm15, %%ymm10, %%ymm10\n\t"
"vmovdqu 32(%[bp]), %%ymm12\n\t"
"vmovdqu 36(%[bp]), %%ymm13\n\t"
"vbroadcastsd 8(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm15\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm14\n\t"
"vpaddd %%ymm14, %%ymm1, %%ymm1\n\t"
"vpaddq %%ymm15, %%ymm0, %%ymm0\n\t"
"vbroadcastsd 1160(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm15\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm14\n\t"
"vpaddd %%ymm14, %%ymm3, %%ymm3\n\t"
"vpaddq %%ymm15, %%ymm2, %%ymm2\n\t"
"vbroadcastsd 2312(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm15\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm14\n\t"
"vpaddd %%ymm14, %%ymm5, %%ymm5\n\t"
"vpaddq %%ymm15, %%ymm4, %%ymm4\n\t"
"vbroadcastsd 3464(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm15\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm14\n\t"
"vpaddd %%ymm14, %%ymm7, %%ymm7\n\t"
"vpaddq %%ymm15, %%ymm6, %%ymm6\n\t"
"vbroadcastsd 4616(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm15\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm14\n\t"
"vpaddd %%ymm14, %%ymm9, %%ymm9\n\t"
"vpaddq %%ymm15, %%ymm8, %%ymm8\n\t"
"vbroadcastsd 5768(%[ap]), %%ymm14\n\t"
"vpmuludq %%ymm14, %%ymm13, %%ymm15\n\t"
"vpmulld %%ymm12, %%ymm14, %%ymm14\n\t"
"vpaddd %%ymm14, %%ymm11, %%ymm11\n\t"
"vpaddq %%ymm15, %%ymm10, %%ymm10\n\t"
"prefetcht0 256(%[bp])\n\t"
"vmovdqu 64(%[bp]), %%ymm12\n\t"
"add $16, %[ap]\n\t"
"add $64, %[bp]\n\t"
"sub $2, %[cnt]\n\t"
"jg 1b\n\t"
"2:\n\t"
""
: [ap] "+r"(ap), [bp] "+r"(bp), [cnt] "+r"(cnt), [v0] "=x"(v0), [v1] "=x"(v1), [v2] "=x"(v2), [v3] "=x"(v3), [v4] "=x"(v4), [v5] "=x"(v5), [v6] "=x"(v6), [v7] "=x"(v7), [v8] "=x"(v8), [v9] "=x"(v9), [v10] "=x"(v10), [v11] "=x"(v11)
:
: "ymm12", "ymm13", "ymm14", "ymm15", "cc", "memory");
}
if (rows > 0) {
__m256i lo = v0, hi = v1;
__m256i y = _mm256_add_epi32(hi, _mm256_srli_epi64(hi, 32));
__m256i res = _mm256_add_epi64(lo, _mm256_slli_epi64(y, 32));
long long *cp = c1 + (size_t)0 * ldc1;
if (op1 == 0) STQ((__m256i *)cp, res);
else if (op1 == 1) STQ((__m256i *)cp, _mm256_add_epi64(LDQ((const __m256i *)cp), res));
else STQ((__m256i *)cp, _mm256_sub_epi64(LDQ((const __m256i *)cp), res));
if (c2) { cp = c2 + (size_t)0 * ldc2;
if (op2 == 0) STQ((__m256i *)cp, res);
else if (op2 == 1) STQ((__m256i *)cp, _mm256_add_epi64(LDQ((const __m256i *)cp), res));
else STQ((__m256i *)cp, _mm256_sub_epi64(LDQ((const __m256i *)cp), res)); } }
if (rows > 1) {
__m256i lo = v2, hi = v3;
__m256i y = _mm256_add_epi32(hi, _mm256_srli_epi64(hi, 32));
__m256i res = _mm256_add_epi64(lo, _mm256_slli_epi64(y, 32));
long long *cp = c1 + (size_t)1 * ldc1;
if (op1 == 0) STQ((__m256i *)cp, res);
else if (op1 == 1) STQ((__m256i *)cp, _mm256_add_epi64(LDQ((const __m256i *)cp), res));
else STQ((__m256i *)cp, _mm256_sub_epi64(LDQ((const __m256i *)cp), res));
if (c2) { cp = c2 + (size_t)1 * ldc2;
if (op2 == 0) STQ((__m256i *)cp, res);
else if (op2 == 1) STQ((__m256i *)cp, _mm256_add_epi64(LDQ((const __m256i *)cp), res));
else STQ((__m256i *)cp, _mm256_sub_epi64(LDQ((const __m256i *)cp), res)); } }
if (rows > 2) {
__m256i lo = v4, hi = v5;
__m256i y = _mm256_add_epi32(hi, _mm256_srli_epi64(hi, 32));
__m256i res = _mm256_add_epi64(lo, _mm256_slli_epi64(y, 32));
long long *cp = c1 + (size_t)2 * ldc1;
if (op1 == 0) STQ((__m256i *)cp, res);
else if (op1 == 1) STQ((__m256i *)cp, _mm256_add_epi64(LDQ((const __m256i *)cp), res));
else STQ((__m256i *)cp, _mm256_sub_epi64(LDQ((const __m256i *)cp), res));
if (c2) { cp = c2 + (size_t)2 * ldc2;
if (op2 == 0) STQ((__m256i *)cp, res);
else if (op2 == 1) STQ((__m256i *)cp, _mm256_add_epi64(LDQ((const __m256i *)cp), res));
else STQ((__m256i *)cp, _mm256_sub_epi64(LDQ((const __m256i *)cp), res)); } }
if (rows > 3) {
__m256i lo = v6, hi = v7;
__m256i y = _mm256_add_epi32(hi, _mm256_srli_epi64(hi, 32));
__m256i res = _mm256_add_epi64(lo, _mm256_slli_epi64(y, 32));
long long *cp = c1 + (size_t)3 * ldc1;
if (op1 == 0) STQ((__m256i *)cp, res);
else if (op1 == 1) STQ((__m256i *)cp, _mm256_add_epi64(LDQ((const __m256i *)cp), res));
else STQ((__m256i *)cp, _mm256_sub_epi64(LDQ((const __m256i *)cp), res));
if (c2) { cp = c2 + (size_t)3 * ldc2;
if (op2 == 0) STQ((__m256i *)cp, res);
else if (op2 == 1) STQ((__m256i *)cp, _mm256_add_epi64(LDQ((const __m256i *)cp), res));
else STQ((__m256i *)cp, _mm256_sub_epi64(LDQ((const __m256i *)cp), res)); } }
if (rows > 4) {
__m256i lo = v8, hi = v9;
__m256i y = _mm256_add_epi32(hi, _mm256_srli_epi64(hi, 32));
__m256i res = _mm256_add_epi64(lo, _mm256_slli_epi64(y, 32));
long long *cp = c1 + (size_t)4 * ldc1;
if (op1 == 0) STQ((__m256i *)cp, res);
else if (op1 == 1) STQ((__m256i *)cp, _mm256_add_epi64(LDQ((const __m256i *)cp), res));
else STQ((__m256i *)cp, _mm256_sub_epi64(LDQ((const __m256i *)cp), res));
if (c2) { cp = c2 + (size_t)4 * ldc2;
if (op2 == 0) STQ((__m256i *)cp, res);
else if (op2 == 1) STQ((__m256i *)cp, _mm256_add_epi64(LDQ((const __m256i *)cp), res));
else STQ((__m256i *)cp, _mm256_sub_epi64(LDQ((const __m256i *)cp), res)); } }
if (rows > 5) {
__m256i lo = v10, hi = v11;
__m256i y = _mm256_add_epi32(hi, _mm256_srli_epi64(hi, 32));
__m256i res = _mm256_add_epi64(lo, _mm256_slli_epi64(y, 32));
long long *cp = c1 + (size_t)5 * ldc1;
if (op1 == 0) STQ((__m256i *)cp, res);
else if (op1 == 1) STQ((__m256i *)cp, _mm256_add_epi64(LDQ((const __m256i *)cp), res));
else STQ((__m256i *)cp, _mm256_sub_epi64(LDQ((const __m256i *)cp), res));
if (c2) { cp = c2 + (size_t)5 * ldc2;
if (op2 == 0) STQ((__m256i *)cp, res);
else if (op2 == 1) STQ((__m256i *)cp, _mm256_add_epi64(LDQ((const __m256i *)cp), res));
else STQ((__m256i *)cp, _mm256_sub_epi64(LDQ((const __m256i *)cp), res)); } }
}
template<int R,int OP> static inline __attribute__((always_inline)) void mikro64_static1152(const long long* p0,const long long* p1,const long long* p2,const long long* p3,const long long* p4,const long long* p5,const long long* bp,long long*c,int ldc){
__m256i AC[2*R]; long idx=-512; const long long*e0=p0+64,*e1=p1+64,*e2=p2+64,*e3=p3+64,*e4=p4+64,*e5=p5+64,*bpE=bp+256;
if constexpr(R==6){
__asm__ volatile(
"vmovdqu (%[bp],%[idx],4), %%ymm12\n"
"\tvmovdqu 4(%[bp],%[idx],4), %%ymm13\n"
"\tvbroadcastsd (%[e0],%[idx],1), %%ymm14\n"
"\tvpmuludq %%ymm14, %%ymm13, %[c0]\n"
"\tvpmulld %%ymm12, %%ymm14, %[c1]\n"
"\tvbroadcastsd (%[e1],%[idx],1), %%ymm14\n"
"\tvpmuludq %%ymm14, %%ymm13, %[c2]\n"
"\tvpmulld %%ymm12, %%ymm14, %[c3]\n"
"\tvbroadcastsd (%[e2],%[idx],1), %%ymm14\n"
"\tvpmuludq %%ymm14, %%ymm13, %[c4]\n"
"\tvpmulld %%ymm12, %%ymm14, %[c5]\n"
"\tvbroadcastsd (%[e3],%[idx],1), %%ymm14\n"
"\tvpmuludq %%ymm14, %%ymm13, %[c6]\n"
"\tvpmulld %%ymm12, %%ymm14, %[c7]\n"
"\tvbroadcastsd (%[e4],%[idx],1), %%ymm14\n"
"\tvpmuludq %%ymm14, %%ymm13, %[c8]\n"
"\tvpmulld %%ymm12, %%ymm14, %[c9]\n"
"\tvbroadcastsd (%[e5],%[idx],1), %%ymm14\n"
"\tvpmuludq %%ymm14, %%ymm13, %[c10]\n"
"\tvpmulld %%ymm12, %%ymm14, %[c11]\n"
"\tvmovdqu 32(%[bp],%[idx],4), %%ymm12\n"
"\tvmovdqu 36(%[bp],%[idx],4), %%ymm13\n"
"\tadd $8, %[idx]\n"
"\t1:\n"
"\tvbroadcastsd (%[e0],%[idx],1), %%ymm14\n"
"\tvpmuludq %%ymm14, %%ymm13, %%ymm15\n"
"\tvpmulld %%ymm12, %%ymm14, %%ymm14\n"
"\tvpaddd %%ymm14, %[c1], %[c1]\n"
"\tvbroadcastsd (%[e1],%[idx],1), %%ymm14\n"
"\tvpaddq %%ymm15, %[c0], %[c0]\n"
"\tvpmuludq %%ymm14, %%ymm13, %%ymm15\n"
"\tvpmulld %%ymm12, %%ymm14, %%ymm14\n"
"\tvpaddd %%ymm14, %[c3], %[c3]\n"
"\tvbroadcastsd (%[e2],%[idx],1), %%ymm14\n"
"\tvpaddq %%ymm15, %[c2], %[c2]\n"
"\tvpmuludq %%ymm14, %%ymm13, %%ymm15\n"
"\tvpmulld %%ymm12, %%ymm14, %%ymm14\n"
"\tvpaddd %%ymm14, %[c5], %[c5]\n"
"\tvbroadcastsd (%[e3],%[idx],1), %%ymm14\n"
"\tvpaddq %%ymm15, %[c4], %[c4]\n"
"\tvpmuludq %%ymm14, %%ymm13, %%ymm15\n"
"\tvpmulld %%ymm12, %%ymm14, %%ymm14\n"
"\tvpaddd %%ymm14, %[c7], %[c7]\n"
"\tvbroadcastsd (%[e4],%[idx],1), %%ymm14\n"
"\tvpaddq %%ymm15, %[c6], %[c6]\n"
"\tvpmuludq %%ymm14, %%ymm13, %%ymm15\n"
"\tvpmulld %%ymm12, %%ymm14, %%ymm14\n"
"\tvpaddd %%ymm14, %[c9], %[c9]\n"
"\tvbroadcastsd (%[e5],%[idx],1), %%ymm14\n"
"\tvpaddq %%ymm15, %[c8], %[c8]\n"
"\tvpmuludq %%ymm14, %%ymm13, %%ymm15\n"
"\tvpmulld %%ymm12, %%ymm14, %%ymm14\n"
"\tvpaddd %%ymm14, %[c11], %[c11]\n"
"\t.byte 0x0f,0x1f,0x80,0,0,0,0\n"
"\tvpaddq %%ymm15, %[c10], %[c10]\n"
"\tvmovdqu 32(%[bp],%[idx],4), %%ymm12\n"
"\tvmovdqu 36(%[bp],%[idx],4), %%ymm13\n"
"\tadd $8, %[idx]\n"
"\tjnz 1b\n"
"\t"
: [e0] "+r"(e0), [e1] "+r"(e1), [e2] "+r"(e2), [e3] "+r"(e3), [e4] "+r"(e4), [e5] "+r"(e5), [bp] "+r"(bpE), [idx] "+r"(idx), [c0] "=x"(AC[0]), [c1] "=x"(AC[1]), [c2] "=x"(AC[2]), [c3] "=x"(AC[3]), [c4] "=x"(AC[4]), [c5] "=x"(AC[5]), [c6] "=x"(AC[6]), [c7] "=x"(AC[7]), [c8] "=x"(AC[8]), [c9] "=x"(AC[9]), [c10] "=x"(AC[10]), [c11] "=x"(AC[11])
: : "ymm12","ymm13","ymm14","ymm15","cc","memory");
}
else{
__asm__ volatile(
"vmovdqu (%[bp],%[idx],4), %%ymm12\n"
"\tvmovdqu 4(%[bp],%[idx],4), %%ymm13\n"
"\tvbroadcastsd (%[e0],%[idx],1), %%ymm14\n"
"\tvpmuludq %%ymm14, %%ymm13, %[c0]\n"
"\tvpmulld %%ymm12, %%ymm14, %[c1]\n"
"\tvbroadcastsd (%[e1],%[idx],1), %%ymm14\n"
"\tvpmuludq %%ymm14, %%ymm13, %[c2]\n"
"\tvpmulld %%ymm12, %%ymm14, %[c3]\n"
"\tvbroadcastsd (%[e2],%[idx],1), %%ymm14\n"
"\tvpmuludq %%ymm14, %%ymm13, %[c4]\n"
"\tvpmulld %%ymm12, %%ymm14, %[c5]\n"
"\tvbroadcastsd (%[e3],%[idx],1), %%ymm14\n"
"\tvpmuludq %%ymm14, %%ymm13, %[c6]\n"
"\tvpmulld %%ymm12, %%ymm14, %[c7]\n"
"\tvmovdqu 32(%[bp],%[idx],4), %%ymm12\n"
"\tvmovdqu 36(%[bp],%[idx],4), %%ymm13\n"
"\tadd $8, %[idx]\n"
"\t5:\n"
"\tvbroadcastsd (%[e0],%[idx],1), %%ymm14\n"
"\tvpmuludq %%ymm14, %%ymm13, %%ymm15\n"
"\tvpmulld %%ymm12, %%ymm14, %%ymm8\n"
"\tvpaddq %%ymm15, %[c0], %[c0]\n"
"\tvbroadcastsd (%[e1],%[idx],1), %%ymm14\n"
"\tvpmuludq %%ymm14, %%ymm13, %%ymm15\n"
"\tvpmulld %%ymm12, %%ymm14, %%ymm9\n"
"\tvpaddq %%ymm15, %[c2], %[c2]\n"
"\tvbroadcastsd (%[e2],%[idx],1), %%ymm14\n"
"\tvpmuludq %%ymm14, %%ymm13, %%ymm15\n"
"\tvpmulld %%ymm12, %%ymm14, %%ymm10\n"
"\tvpaddq %%ymm15, %[c4], %[c4]\n"
"\tvbroadcastsd (%[e3],%[idx],1), %%ymm14\n"
"\tvpmuludq %%ymm14, %%ymm13, %%ymm15\n"
"\tvpmulld %%ymm12, %%ymm14, %%ymm11\n"
"\tvpaddq %%ymm15, %[c6], %[c6]\n"
"\tvpaddd %%ymm8, %[c1], %[c1]\n"
"\tvpaddd %%ymm9, %[c3], %[c3]\n"
"\tvpaddd %%ymm10, %[c5], %[c5]\n"
"\tvpaddd %%ymm11, %[c7], %[c7]\n"
"\tvmovdqu 32(%[bp],%[idx],4), %%ymm12\n"
"\tvmovdqu 36(%[bp],%[idx],4), %%ymm13\n"
"\tadd $8, %[idx]\n"
"\tjnz 5b\n"
"\t"
: [e0] "+r"(e0), [e1] "+r"(e1), [e2] "+r"(e2), [e3] "+r"(e3), [e4] "+r"(e4), [e5] "+r"(e5), [bp] "+r"(bpE), [idx] "+r"(idx), [c0] "=x"(AC[0]), [c1] "=x"(AC[1]), [c2] "=x"(AC[2]), [c3] "=x"(AC[3]), [c4] "=x"(AC[4]), [c5] "=x"(AC[5]), [c6] "=x"(AC[6]), [c7] "=x"(AC[7])
: : "ymm8","ymm9","ymm10","ymm11","ymm12","ymm13","ymm14","ymm15","cc","memory");
}
#pragma GCC unroll 6
for(int r=0;r<R;r++){
__m256i hi=AC[2*r+1],lo=AC[2*r];
__m256i y=_mm256_add_epi32(hi,_mm256_srli_epi64(hi,32));
__m256i z=_mm256_add_epi64(lo,_mm256_slli_epi64(y,32));
long long*d=c+(size_t)r*ldc;
if constexpr(OP==1) z=_mm256_add_epi64(LDQ((const __m256i*)d),z);
if constexpr(OP==2) z=_mm256_sub_epi64(LDQ((const __m256i*)d),z);
STQ((__m256i*)d,z);
}
}
template<int ASign>
static __attribute__((noinline)) void leaf64_by_sign(const Opd*ao,const Opd*bo,long long*c,int ldc){
const long long *a0=ao->p+(size_t)ao->r[0]*ao->ld+ao->c[0];
const long long *a1=ao->nt==2?ao->p+(size_t)ao->r[1]*ao->ld+ao->c[1]:a0;
const long long *b0=bo->p+(size_t)bo->r[0]*bo->ld+bo->c[0];
const long long *b1=bo->nt==2?bo->p+(size_t)bo->r[1]*bo->ld+bo->c[1]:b0;
if(bo->nt==1)packB_fixed64<0>(b0,b1,bo->ld);
else if(bo->s[1]>0)packB_fixed64<1>(b0,b1,bo->ld);else packB_fixed64<-1>(b0,b1,bo->ld);
if constexpr(ASign==0){
for(int ic=0;ic<60;ic+=6){
const long long* q0=a0+(size_t)ic*ao->ld, *q1=q0+ao->ld, *q2=q1+ao->ld, *q3=q2+ao->ld, *q4=q3+ao->ld, *q5=q4+ao->ld;
for(int j=0;j<64;j+=4) mikro64_static1152<6,0>(q0,q1,q2,q3,q4,q5,Bpanel+(size_t)j*64,c+(size_t)ic*ldc+j,ldc);
}
const long long* q0=a0+(size_t)60*ao->ld, *q1=q0+ao->ld, *q2=q1+ao->ld, *q3=q2+ao->ld;
for(int j=0;j<64;j+=4) mikro64_static1152<4,0>(q0,q1,q2,q3,q0,q0,Bpanel+(size_t)j*64,c+(size_t)60*ldc+j,ldc);
} else {
for(int ic=0;ic<60;ic+=6){
packA_fixed64<ASign>(a0+(size_t)ic*ao->ld,a1+(size_t)ic*ao->ld,ao->ld,6);
for(int j=0;j<64;j+=4) mikro64_static1152<6,0>(leaf_A64,leaf_A64+96,leaf_A64+192,leaf_A64+288,leaf_A64+384,leaf_A64+480,Bpanel+(size_t)j*64,c+(size_t)ic*ldc+j,ldc);
}
packA_fixed64<ASign>(a0+(size_t)60*ao->ld,a1+(size_t)60*ao->ld,ao->ld,4);
for(int j=0;j<64;j+=4) mikro64_static1152<4,0>(leaf_A64,leaf_A64+96,leaf_A64+192,leaf_A64+288,leaf_A64,leaf_A64,Bpanel+(size_t)j*64,c+(size_t)60*ldc+j,ldc);
}
}
template<int ASign>
static __attribute__((noinline,noclone)) void direct_a_leaf64_arguments(
const long long*a0,const long long*a1,int lda,long long*c,int ldc){
if constexpr(ASign==0){
for(int ic=0;ic<60;ic+=6){
const long long* q0=a0+(size_t)ic*lda, *q1=q0+lda, *q2=q1+lda, *q3=q2+lda, *q4=q3+lda, *q5=q4+lda;
for(int j=0;j<64;j+=4) mikro64_static1152<6,0>(q0,q1,q2,q3,q4,q5,Bpanel+(size_t)j*64,c+(size_t)ic*ldc+j,ldc);
}
const long long* q0=a0+(size_t)60*lda, *q1=q0+lda, *q2=q1+lda, *q3=q2+lda;
for(int j=0;j<64;j+=4) mikro64_static1152<4,0>(q0,q1,q2,q3,q0,q0,Bpanel+(size_t)j*64,c+(size_t)60*ldc+j,ldc);
} else {
for(int ic=0;ic<60;ic+=6){
packA_fixed64<ASign>(a0+(size_t)ic*lda,a1+(size_t)ic*lda,lda,6);
for(int j=0;j<64;j+=4) mikro64_static1152<6,0>(leaf_A64,leaf_A64+96,leaf_A64+192,leaf_A64+288,leaf_A64+384,leaf_A64+480,Bpanel+(size_t)j*64,c+(size_t)ic*ldc+j,ldc);
}
packA_fixed64<ASign>(a0+(size_t)60*lda,a1+(size_t)60*lda,lda,4);
for(int j=0;j<64;j+=4) mikro64_static1152<4,0>(leaf_A64,leaf_A64+96,leaf_A64+192,leaf_A64+288,leaf_A64,leaf_A64,Bpanel+(size_t)j*64,c+(size_t)60*ldc+j,ldc);
}
}
static void fixed_leaf64_product(const Opd*ao,const Opd*bo,long long*c,int ldc){
if(ao->nt==1)leaf64_by_sign<0>(ao,bo,c,ldc);
else if(ao->s[1]>0)leaf64_by_sign<1>(ao,bo,c,ldc);
else leaf64_by_sign<-1>(ao,bo,c,ldc);
}
static void leaf(int n, const Opd *Ao, const Opd *Bo,
long long *C1, int ldc1, int op1, long long *C2, int ldc2, int op2) {
int nb4 = n - (n & 3);
for (int jc = 0; jc < nb4; jc += NC) {
int nc = (nb4 - jc < NC) ? (nb4 - jc) : NC;
for (int pc = 0; pc < n; pc += KC) {
int kc = (n - pc < KC) ? (n - pc) : KC;
packB(Bo, jc, nc, pc, kc);
int e1 = (pc == 0) ? op1 : (op1 == 2 ? 2 : 1);
int e2 = (pc == 0) ? op2 : (op2 == 2 ? 2 : 1);
for (int ic = 0; ic < n; ic += MC) {
int mc = (n - ic < MC) ? (n - ic) : MC;
packA(Ao, ic, mc, pc, kc);
for (int ir = 0; ir < mc; ir += MR) {
int rows = (mc - ir < MR) ? (mc - ir) : MR;
const long long *ap = Apanel + (size_t)ir * KCP * 1;
for (int jg = 0; jg < nc; jg += 4) {
const long long *bp = Bpanel + (size_t)(jg / 4) * kc * 4;
mikro(kc / UU, ap, bp, C1 + (size_t)(ic + ir) * ldc1 + jc + jg, ldc1, e1,
C2 ? C2 + (size_t)(ic + ir) * ldc2 + jc + jg : 0, ldc2, e2, rows);
}
}
}
}
}
for (int j = nb4; j < n; j++)
for (int i = 0; i < n; i++) {
unsigned long long acc = 0;
for (int k = 0; k < n; k++) {
long long av = 0, bv = 0;
for (int t = 0; t < Ao->nt; t++)
av += Ao->s[t] < 0 ? -Ao->p[(size_t)(Ao->r[t] + i) * Ao->ld + Ao->c[t] + k]
: Ao->p[(size_t)(Ao->r[t] + i) * Ao->ld + Ao->c[t] + k];
for (int t = 0; t < Bo->nt; t++)
bv += Bo->s[t] < 0 ? -Bo->p[(size_t)(Bo->r[t] + k) * Bo->ld + Bo->c[t] + j]
: Bo->p[(size_t)(Bo->r[t] + k) * Bo->ld + Bo->c[t] + j];
acc += (unsigned long long)av * (unsigned long long)bv;
}
long long *cp = C1 + (size_t)i * ldc1 + j;
if (op1 == 0) *cp = (long long)acc;
else if (op1 == 1) *cp += (long long)acc;
else *cp -= (long long)acc;
if (C2) {
long long *cq = C2 + (size_t)i * ldc2 + j;
if (op2 == 0) *cq = (long long)acc;
else if (op2 == 1) *cq += (long long)acc;
else *cq -= (long long)acc;
}
}
}
static long long g_scratch[6u * 1024u * 1024u] __attribute__((aligned(64)));
static void cmb(long long *dst, int ldd, const long long *T, int ldt, int h, int sign, int op) {
__m256i sgn = _mm256_set1_epi64x(sign < 0 ? -1 : 0);
for (int i = 0; i < h; i++) {
const long long *t = T + (size_t)i * ldt;
long long *c = dst + (size_t)i * ldd;
int j = 0;
if (op == 0) {
for (; j + 4 <= h; j += 4) {
__m256i v = LDQ((const __m256i *)(t + j));
if (sign < 0) v = _mm256_sub_epi64(_mm256_setzero_si256(), v);
STQ((__m256i *)(c + j), v);
}
for (; j < h; j++) c[j] = sign < 0 ? -t[j] : t[j];
} else {
for (; j + 4 <= h; j += 4) {
__m256i v = LDQ((const __m256i *)(t + j));
__m256i w = LDQ((const __m256i *)(c + j));
if ((op == 1) != (sign < 0)) STQ((__m256i *)(c + j), _mm256_add_epi64(w, v));
else STQ((__m256i *)(c + j), _mm256_sub_epi64(w, v));
}
for (; j < h; j++) { if ((op == 1) != (sign < 0)) c[j] += t[j]; else c[j] -= t[j]; }
}
}
}
static long long material_A[1024u * 1024u] __attribute__((aligned(1 << 21)));
__attribute__((constructor)) static void l1n_huge_material_A(void) {
long long *a = material_A; uintptr_t p = (uintptr_t)a;
uintptr_t e = p + sizeof(material_A);
uintptr_t ha = (p + ((uintptr_t)1 << 21) - 1) & ~(((uintptr_t)1 << 21) - 1);
uintptr_t he = e & ~(((uintptr_t)1 << 21) - 1);
if (he > ha) madvise((void *)ha, (size_t)(he - ha), MADV_HUGEPAGE);
}
static long long material_B[1024u * 1'024u] __attribute__((aligned(1 << 21)));
__attribute__((constructor)) static void l1n_huge_material_B(void) {
long long *a = material_B; uintptr_t p = (uintptr_t)a;
uintptr_t e = p + sizeof(material_B);
uintptr_t ha = (p + ((uintptr_t)1 << 21) - 1) & ~(((uintptr_t)1 << 21) - 1);
uintptr_t he = e & ~(((uintptr_t)1 << 21) - 1);
if (he > ha) madvise((void *)ha, (size_t)(he - ha), MADV_HUGEPAGE);
}
static long long material_C[512u * 512u] __attribute__((aligned(1 << 21)));
__attribute__((constructor)) static void l1n_huge_material_C(void) {
long long *a = material_C; uintptr_t p = (uintptr_t)a;
uintptr_t e = p + sizeof(material_C);
uintptr_t ha = (p + ((uintptr_t)1 << 21) - 1) & ~(((uintptr_t)1 << 21) - 1);
uintptr_t he = e & ~(((uintptr_t)1 << 21) - 1);
if (he > ha) madvise((void *)ha, (size_t)(he - ha), MADV_HUGEPAGE);
}
static long long material_D[512u * 512u] __attribute__((aligned(1 << 21)));
__attribute__((constructor)) static void l1n_huge_material_D(void) {
long long *a = material_D; uintptr_t p = (uintptr_t)a;
uintptr_t e = p + sizeof(material_D);
uintptr_t ha = (p + ((uintptr_t)1 << 21) - 1) & ~(((uintptr_t)1 << 21) - 1);
uintptr_t he = e & ~(((uintptr_t)1 << 21) - 1);
if (he > ha) madvise((void *)ha, (size_t)(he - ha), MADV_HUGEPAGE);
}
static void materializeN(const Opd *o, long long *dst, const int n) {
for (int i = 0; i < n; i++) {
long long *out = dst + (size_t)i * n;
int j = 0;
for (; j + 4 <= n; j += 4) {
__m256i value = _mm256_setzero_si256();
for (int t = 0; t < o->nt; t++) {
const long long *src = o->p + (size_t)(o->r[t] + i) * o->ld + o->c[t] + j;
__m256i part = LDQ((const __m256i *)src);
value = o->s[t] < 0 ? _mm256_sub_epi64(value, part) : _mm256_add_epi64(value, part);
}
STQ((__m256i *)(out + j), value);
}
for (; j < n; j++) {
unsigned long long value = 0;
for (int t = 0; t < o->nt; t++) {
unsigned long long part = (unsigned long long)o->p[(size_t)(o->r[t] + i) * o->ld + o->c[t] + j];
value = o->s[t] < 0 ? value - part : value + part;
}
out[j] = (long long)value;
}
}
}
static void mmxR(int n, const Opd *Ao, const Opd *Bo, long long *d, int ld, int op,
long long *T) {
if (n == 1024 && (Ao->nt > 1 || Bo->nt > 1)) {
Opd am, bm; const Opd *a = Ao, *b = Bo;
if (Ao->nt > 1) { materializeN(Ao, material_A, 1024); am = o1(material_A, n); a = &am; }
if (Bo->nt > 1) { materializeN(Bo, material_B, 1024); bm = o1(material_B, n); b = &bm; }
mmxR(n, a, b, d, ld, op, T);
return;
}
if (n <= CUTL || (n & 1) || Ao->nt > 2 || Bo->nt > 2) {
leaf(n, Ao, Bo, d, ld, op, 0, 0, 0); return; }
if (n == 512 && (Ao->nt > 1 || Bo->nt > 1)) {
Opd am, bm; const Opd *a = Ao, *b = Bo;
if (Ao->nt > 1) { materializeN(Ao, material_C, 512); am = o1(material_C, 512); a = &am; }
if (Bo->nt > 1) { materializeN(Bo, material_D, 512); bm = o1(material_D, 512); b = &bm; }
mmxR(n, a, b, d, ld, op, T);
return;
}
const int h = n >> 1;
Opd A11 = oq(Ao, 0, 0, h), A12 = oq(Ao, 0, 1, h), A21 = oq(Ao, 1, 0, h), A22 = oq(Ao, 1, 1, h);
Opd B11 = oq(Bo, 0, 0, h), B12 = oq(Bo, 0, 1, h), B21 = oq(Bo, 1, 0, h), B22 = oq(Bo, 1, 1, h);
long long *Q[4];
Q[0] = d; Q[1] = d + h; Q[2] = d + (size_t)h * ld; Q[3] = Q[2] + h;
long long *T2 = T + (size_t)h * h;
int wr[4] = {0, 0, 0, 0};
#define MK(qi, si, qj, sj, Ma, Mb) do { \
int oa = wr[qi] ? effop(1, (si)) : effop(op, (si)); \
int ob = wr[qj] ? effop(1, (sj)) : effop(op, (sj)); \
wr[qi] = 1; wr[qj] = 1; \
if (oa == 0) { \
mmxR(h, &(Ma), &(Mb), Q[qi], ld, 0, T); \
cmb(Q[qj], ld, Q[qi], ld, h, (sj), ob); \
} else { \
mmxR(h, &(Ma), &(Mb), T, h, 0, T2); \
cmb(Q[qi], ld, T, h, h, (si), oa); \
cmb(Q[qj], ld, T, h, h, (sj), ob); \
} \
} while (0) \
#define MK1(qi, si, Ma, Mb) do { \
int oa = wr[qi] ? effop(1, (si)) : effop(op, (si)); \
wr[qi] = 1; \
mmxR(h, &(Ma), &(Mb), Q[qi], ld, oa, T); \
} while (0)
{
Opd Ma = oadd(&A11, &A22, 1), Mb = oadd(&B11, &B22, 1);
MK(0, 1, 3, 1, Ma, Mb);
}
{
Opd Ma = oadd(&A21, &A22, 1), Mb = B11;
MK(2, 1, 3, 2, Ma, Mb);
}
{
Opd Ma = A11, Mb = oadd(&B12, &B22, -1);
MK(1, 1, 3, 1, Ma, Mb);
}
{
Opd Ma = A22, Mb = oadd(&B21, &B11, -1);
MK(0, 1, 2, 1, Ma, Mb);
}
{
Opd Ma = oadd(&A11, &A12, 1), Mb = B22;
MK(0, 2, 1, 1, Ma, Mb);
}
{
Opd Ma = oadd(&A21, &A11, -1), Mb = oadd(&B11, &B12, 1);
MK1(3, 1, Ma, Mb);
}
{
Opd Ma = oadd(&A12, &A22, -1), Mb = oadd(&B21, &B22, 1);
MK1(0, 1, Ma, Mb);
}
#undef MK
#undef MK1
}
static inline __m256i wg_load(const long long *p) { return LDQ((const __m256i *)p); }
static inline void wg_store(long long *p, __m256i v) { STQ((__m256i *)p, v); }
static long long *g_sc,*g_sg,*g_sgo;
static long long wg_buf[5 * 2048 * 2048] __attribute__((aligned(64)));
static void wg_nAS(int h, long long *S1, long long *S3, const long long *A11,
const long long *A21, const long long *A22, int lda) {
for (int i = 0; i < h; i++) {
const long long *c = A11 + (size_t)i*lda, *a = A21 + (size_t)i*lda, *b = A22 + (size_t)i*lda;
long long *s1 = S1 + (size_t)i*h, *s3 = S3 + (size_t)i*h;
for (int j = 0; j < h; j += 16) {
__m256i va = wg_load(a+j), vb = wg_load(b+j), vc = wg_load(c+j);
__m256i x0 = _mm256_add_epi64(va, vb);
__m256i x1 = _mm256_sub_epi64(vc, va);
__m256i wa = wg_load(a+j+4), wb = wg_load(b+j+4), wc2 = wg_load(c+j+4);
__m256i x2 = _mm256_add_epi64(wa, wb);
__m256i x3 = _mm256_sub_epi64(wc2, wa);
__m256i ua = wg_load(a+j+8), ub = wg_load(b+j+8), uc = wg_load(c+j+8);
__m256i x4 = _mm256_add_epi64(ua, ub);
__m256i x5 = _mm256_sub_epi64(uc, ua);
__m256i za = wg_load(a+j+12), zb = wg_load(b+j+12), zc = wg_load(c+j+12);
__m256i x6 = _mm256_add_epi64(za, zb);
__m256i x7 = _mm256_sub_epi64(zc, za);
wg_store_nt(s1+j, x0);
wg_store_nt(s1+j+4, x2);
wg_store_nt(s1+j+8, x4);
wg_store_nt(s1+j+12, x6);
wg_store_nt(s3+j, x1);
wg_store_nt(s3+j+4, x3);
wg_store_nt(s3+j+8, x5);
wg_store_nt(s3+j+12, x7);
}
}
}
static void wg_nBT(int h, long long *T1, long long *T3, const long long *B11,
const long long *B12, const long long *B22, int ldb) {
for (int i = 0; i < h; i++) {
const long long *c = B11 + (size_t)i*ldb, *a = B12 + (size_t)i*ldb, *b = B22 + (size_t)i*ldb;
long long *t1 = T1 + (size_t)i*h, *t3 = T3 + (size_t)i*h;
for (int j = 0; j < h; j += 16) {
__m256i va = wg_load(a+j), vb = wg_load(b+j), vc = wg_load(c+j);
__m256i x0 = _mm256_sub_epi64(va, vc);
__m256i x1 = _mm256_sub_epi64(vb, va);
__m256i wa = wg_load(a+j+4), wb = wg_load(b+j+4), wc2 = wg_load(c+j+4);
__m256i x2 = _mm256_sub_epi64(wa, wc2);
__m256i x3 = _mm256_sub_epi64(wb, wa);
__m256i ua = wg_load(a+j+8), ub = wg_load(b+j+8), uc = wg_load(c+j+8);
__m256i x4 = _mm256_sub_epi64(ua, uc);
__m256i x5 = _mm256_sub_epi64(ub, ua);
__m256i za = wg_load(a+j+12), zb = wg_load(b+j+12), zc = wg_load(c+j+12);
__m256i x6 = _mm256_sub_epi64(za, zc);
__m256i x7 = _mm256_sub_epi64(zb, za);
wg_store_nt(t1+j, x0);
wg_store_nt(t1+j+4, x2);
wg_store_nt(t1+j+8, x4);
wg_store_nt(t1+j+12, x6);
wg_store_nt(t3+j, x1);
wg_store_nt(t3+j+4, x3);
wg_store_nt(t3+j+8, x5);
wg_store_nt(t3+j+12, x7);
}
}
}
static void wg_nAS2(int h, long long *S2, long long *S4, const long long *S1,
const long long *A11, const long long *A12, int lda) {
for (int i = 0; i < h; i++) {
const long long *p = S1 + (size_t)i*h, *c = A11 + (size_t)i*lda, *d = A12 + (size_t)i*lda;
long long *s2 = S2 + (size_t)i*h, *s4 = S4 + (size_t)i*h;
for (int j = 0; j < h; j += 16) {
__m256i v0 = _mm256_sub_epi64(wg_load(p+j), wg_load(c+j));
__m256i v1 = _mm256_sub_epi64(wg_load(p+j+4), wg_load(c+j+4));
__m256i v2 = _mm256_sub_epi64(wg_load(p+j+8), wg_load(c+j+8));
__m256i v3 = _mm256_sub_epi64(wg_load(p+j+12), wg_load(c+j+12));
wg_store_nt(s2+j, v0);
wg_store_nt(s2+j+4, v1);
wg_store_nt(s2+j+8, v2);
wg_store_nt(s2+j+12, v3);
wg_store(s4+j, _mm256_sub_epi64(wg_load(d+j), v0));
wg_store(s4+j+4, _mm256_sub_epi64(wg_load(d+j+4), v1));
wg_store(s4+j+8, _mm256_sub_epi64(wg_load(d+j+8), v2));
wg_store(s4+j+12, _mm256_sub_epi64(wg_load(d+j+12), v3));
}
}
}
static void wg_nBT2(int h, long long *T2, long long *T4, const long long *T1,
const long long *B22, const long long *B21, int ldb) {
for (int i = 0; i < h; i++) {
const long long *p = T1 + (size_t)i*h, *c = B22 + (size_t)i*ldb, *d = B21 + (size_t)i*ldb;
long long *t2 = T2 + (size_t)i*h, *t4 = T4 + (size_t)i*h;
for (int j = 0; j < h; j += 16) {
__m256i v0 = _mm256_sub_epi64(wg_load(c+j), wg_load(p+j));
__m256i v1 = _mm256_sub_epi64(wg_load(c+j+4), wg_load(p+j+4));
__m256i v2 = _mm256_sub_epi64(wg_load(c+j+8), wg_load(p+j+8));
__m256i v3 = _mm256_sub_epi64(wg_load(c+j+12), wg_load(p+j+12));
wg_store_nt(t2+j, v0);
wg_store_nt(t2+j+4, v1);
wg_store_nt(t2+j+8, v2);
wg_store_nt(t2+j+12, v3);
wg_store(t4+j, _mm256_sub_epi64(v0, wg_load(d+j)));
wg_store(t4+j+4, _mm256_sub_epi64(v1, wg_load(d+j+4)));
wg_store(t4+j+8, _mm256_sub_epi64(v2, wg_load(d+j+8)));
wg_store(t4+j+12, _mm256_sub_epi64(v3, wg_load(d+j+12)));
}
}
}
static void wg_add(int h, long long *dst, const long long *a, int lda,
const long long *b, int ldb, int sg) {
for (int i = 0; i < h; i++) {
long long *d = dst + (size_t)i*h;
const long long *x = a + (size_t)i*lda, *y = b + (size_t)i*ldb;
for (int j = 0; j < h; j += 4) {
__m256i vx=wg_load(x+j), vy=wg_load(y+j);
wg_store(d+j, sg > 0 ? _mm256_add_epi64(vx,vy) : _mm256_sub_epi64(vx,vy));
}
}
}
static void wg_mutate(int h, long long *dst, const long long *b, int ldb, int reverse) {
for (int i = 0; i < h; i++) {
long long *d = dst + (size_t)i*h; const long long *y=b+(size_t)i*ldb;
for (int j=0; j<h; j+=4) {
__m256i vd=wg_load(d+j),vy=wg_load(y+j);
wg_store(d+j, reverse ? _mm256_sub_epi64(vy,vd) : _mm256_sub_epi64(vd,vy));
}
}
}
static void wg_combine(int h, long long *C, int ldc, const long long *M1,
const long long *M2, const long long *M3, const long long *M4,
const long long *M5, const long long *M6, const long long *M7) {
for (int i=0; i<h; i++) {
const long long *a=M1+(size_t)i*ldc,*b=M2+(size_t)i*ldc,*c=M3+(size_t)i*ldc;
const long long *d=M4+(size_t)i*ldc,*e=M5+(size_t)i*h,*f=M6+(size_t)i*h,*g=M7+(size_t)i*h;
long long *c11=C+(size_t)i*ldc,*c12=c11+h,*c21=c11+(size_t)h*ldc,*c22=c21+h;
if (i + 4 < h) {
__builtin_prefetch((const void *)(a+(size_t)4*ldc),0,0);
__builtin_prefetch((const void *)(b+(size_t)4*ldc),0,0);
__builtin_prefetch((const void *)(c+(size_t)4*ldc),0,0);
__builtin_prefetch((const void *)(d+(size_t)4*ldc),0,0);
__builtin_prefetch((const void *)(e+(size_t)4*h),0,0);
__builtin_prefetch((const void *)(f+(size_t)4*h),0,0);
__builtin_prefetch((const void *)(g+(size_t)4*h),0,0);
}
for (int j=0; j<h; j+=4) {
__m256i p1=wg_load(a+j),p2=wg_load(b+j),p3=wg_load(c+j),p4=wg_load(d+j);
__m256i p5=wg_load(e+j),p6=wg_load(f+j),p7=wg_load(g+j);
__m256i u2=_mm256_add_epi64(p1,p6),u3=_mm256_add_epi64(u2,p7);
__m256i u4=_mm256_add_epi64(u2,p5);
wg_store_nt(c11+j,_mm256_add_epi64(p1,p2));
wg_store_nt(c12+j,_mm256_add_epi64(u4,p3));
wg_store_nt(c21+j,_mm256_sub_epi64(u3,p4));
wg_store_nt(c22+j,_mm256_add_epi64(u3,p5));
}
}
_mm_sfence();
}
static void wg_combine_cache(int h, long long *C, int ldc, const long long *M1,
const long long *M2, const long long *M3, const long long *M4,
const long long *M5, const long long *M6, const long long *M7) {
for (int i=0; i<h; i++) {
const long long *a=M1+(size_t)i*ldc,*b=M2+(size_t)i*ldc,*c=M3+(size_t)i*ldc;
const long long *d=M4+(size_t)i*ldc,*e=M5+(size_t)i*h,*f=M6+(size_t)i*h,*g=M7+(size_t)i*h;
long long *c11=C+(size_t)i*ldc,*c12=c11+h,*c21=c11+(size_t)h*ldc,*c22=c21+h;
if (i + 4 < h) {
}
for (int j=0; j<h; j+=4) {
__m256i p1=wg_load(a+j),p2=wg_load(b+j),p3=wg_load(c+j),p4=wg_load(d+j);
__m256i p5=wg_load(e+j),p6=wg_load(f+j),p7=wg_load(g+j);
__m256i u2=_mm256_add_epi64(p1,p6),u3=_mm256_add_epi64(u2,p7);
__m256i u4=_mm256_add_epi64(u2,p5);
wg_store(c11+j,_mm256_add_epi64(p1,p2));
wg_store(c12+j,_mm256_add_epi64(u4,p3));
wg_store(c21+j,_mm256_sub_epi64(u3,p4));
wg_store(c22+j,_mm256_add_epi64(u3,p5));
}
}
}
static long long wg_buf2[5 * 1024 * 1024] __attribute__((aligned(64),used));
static long long wg_buf1[5 * 512 * 512] __attribute__((aligned(64)));
static long long *wleaf = wg_buf1 + 5*(256*256) + 512;
static long long wg_buf_mini[5*64*64 + 4*256] __attribute__((aligned(2097152)));
__attribute__((constructor)) static void ml2a2v5_chk(void) {
if (wg_buf1 + 5*512*512 < wleaf + 7*((size_t)(128*128) + 64)) __builtin_trap();
}
static long long *const m5_base = wg_buf_mini;
static void winograd_mini(int n, const long long *A, int lda, const long long *B, int ldb,
long long *C, int ldc) {
const int h=n/2; const size_t sz=(size_t)h*h;
long long *M1=C,*M2=C+h,*M3=C+(size_t)h*ldc,*M4=M3+h;
long long *M5=m5_base,*M6=M5+sz+256,*M7=M6+sz+256;
const long long *a11=A,*a12=A+h,*a21=A+(size_t)h*lda,*a22=a21+h;
const long long *b11=B,*b12=B+h,*b21=B+(size_t)h*ldb,*b22=b21+h;
packB_fixed64<1>(b11,b12,ldb);
direct_a_leaf64_arguments<-1>(a21,a11,lda,M6,h);
packB_fixed64<0>(b11,b11,ldb);
direct_a_leaf64_arguments<1>(a21,a22,lda,M2,ldc);
packB_fixed64<-1>(b21,b11,ldb);
direct_a_leaf64_arguments<0>(a22,a22,lda,M4,ldc);
packB_fixed64<1>(b11,b22,ldb);
direct_a_leaf64_arguments<1>(a11,a22,lda,M1,ldc);
packB_fixed64<-1>(b12,b22,ldb);
direct_a_leaf64_arguments<0>(a11,a11,lda,M3,ldc);
packB_fixed64<0>(b22,b22,ldb);
direct_a_leaf64_arguments<1>(a11,a12,lda,M5,h);
packB_fixed64<1>(b21,b22,ldb);
direct_a_leaf64_arguments<-1>(a12,a22,lda,M7,h);
for (int i=0;i+1<h;i+=2) {
const long long *m1=M1+(size_t)i*ldc,*m2=M2+(size_t)i*ldc;
const long long *m3=M3+(size_t)i*ldc,*m4=M4+(size_t)i*ldc;
const long long *m5=M5+(size_t)i*h,*m6=M6+(size_t)i*h,*m7=M7+(size_t)i*h;
const long long *n1=M1+(size_t)(i+1)*ldc,*n2=M2+(size_t)(i+1)*ldc;
const long long *n3=M3+(size_t)(i+1)*ldc,*n4=M4+(size_t)(i+1)*ldc;
const long long *n5=M5+(size_t)(i+1)*h,*n6=M6+(size_t)(i+1)*h,*n7=M7+(size_t)(i+1)*h;
long long *c11=C+(size_t)i*ldc,*c12=c11+h,*c21=c11+(size_t)h*ldc,*c22=c21+h;
long long *d11=C+(size_t)(i+1)*ldc,*d12=d11+h,*d21=d11+(size_t)h*ldc,*d22=d21+h;
for (int j=0;j<h;j+=4) {
__m256i p1=wg_load(m1+j),p2=wg_load(m2+j),p3=wg_load(m3+j),p4=wg_load(m4+j);
__m256i p5=wg_load(m5+j),p6=wg_load(m6+j),p7=wg_load(m7+j);
__m256i q1=wg_load(n1+j),q2=wg_load(n2+j),q3=wg_load(n3+j),q4=wg_load(n4+j);
__m256i q5=wg_load(n5+j),q6=wg_load(n6+j),q7=wg_load(n7+j);
wg_store(c11+j,_mm256_add_epi64(_mm256_sub_epi64(_mm256_add_epi64(p1,p4),p5),p7));
wg_store(c12+j,_mm256_add_epi64(p3,p5));
wg_store(c21+j,_mm256_add_epi64(p2,p4));
wg_store(c22+j,_mm256_add_epi64(_mm256_add_epi64(_mm256_sub_epi64(p1,p2),p3),p6));
wg_store(d11+j,_mm256_add_epi64(_mm256_sub_epi64(_mm256_add_epi64(q1,q4),q5),q7));
wg_store(d12+j,_mm256_add_epi64(q3,q5));
wg_store(d21+j,_mm256_add_epi64(q2,q4));
wg_store(d22+j,_mm256_add_epi64(_mm256_add_epi64(_mm256_sub_epi64(q1,q2),q3),q6));
}
}
if (h & 1) {
const int i=h-1;
const long long *m1=M1+(size_t)i*ldc,*m2=M2+(size_t)i*ldc;
const long long *m3=M3+(size_t)i*ldc,*m4=M4+(size_t)i*ldc;
const long long *m5=M5+(size_t)i*h,*m6=M6+(size_t)i*h,*m7=M7+(size_t)i*h;
long long *c11=C+(size_t)i*ldc,*c12=c11+h,*c21=c11+(size_t)h*ldc,*c22=c21+h;
for (int j=0;j<h;j+=4) {
__m256i p1=wg_load(m1+j),p2=wg_load(m2+j),p3=wg_load(m3+j),p4=wg_load(m4+j);
__m256i p5=wg_load(m5+j),p6=wg_load(m6+j),p7=wg_load(m7+j);
wg_store(c11+j,_mm256_add_epi64(_mm256_sub_epi64(_mm256_add_epi64(p1,p4),p5),p7));
wg_store(c12+j,_mm256_add_epi64(p3,p5));
wg_store(c21+j,_mm256_add_epi64(p2,p4));
wg_store(c22+j,_mm256_add_epi64(_mm256_add_epi64(_mm256_sub_epi64(p1,p2),p3),p6));
}
}
}
/* PRESWZ-B: Q's b11/b22 quadrants are emitted in the pack panel layout
(16 column-groups x 64 rows x 4 dword-swapped longs); b12/b21 stay row-major.
The two pure-copy packs vanish. The swap does not commute with 64-bit add,
so each sum pack un-swaps a panel operand (vpshufd is an involution), does the
exact add/sub, and re-swizzles: every packed panel stays byte-identical. */
static long long Qblk[4*4096] __attribute__((aligned(64)));
static __attribute__((noinline))void wg_add_q(long long*Qb,const long long*x,int ldx,const long long*y,int ldy){
for(int bi=0;bi<2;bi++)for(int bj=0;bj<2;bj++){
const long long*xp=x+(size_t)bi*64*ldx+bj*64;
const long long*yp=y+(size_t)bi*64*ldy+bj*64;
long long*q=Qb+(size_t)(bi*2+bj)*4096;
if(bi==bj){
for(int k=0;k<64;k+=2)for(int g=0;g<16;g++){
__m256i x0=LDQ((const __m256i*)(xp+(size_t)k*ldx+4*g)),x1=LDQ((const __m256i*)(xp+(size_t)(k+1)*ldx+4*g));
__m256i y0=LDQ((const __m256i*)(yp+(size_t)k*ldy+4*g)),y1=LDQ((const __m256i*)(yp+(size_t)(k+1)*ldy+4*g));
__m256i v0=_mm256_sub_epi64(x0,y0);
__m256i v1=_mm256_sub_epi64(x1,y1);
STQ((__m256i*)(q+g*256+4*k),_mm256_shuffle_epi32(v0,0xB1));
STQ((__m256i*)(q+g*256+4*k+4),_mm256_shuffle_epi32(v1,0xB1));
}
}else{
for(int k=0;k<64;k++)for(int g=0;g<16;g++){
__m256i xv=LDQ((const __m256i*)(xp+(size_t)k*ldx+4*g)),yv=LDQ((const __m256i*)(yp+(size_t)k*ldy+4*g));
STQ((__m256i*)(q+(size_t)k*64+4*g),_mm256_sub_epi64(xv,yv));
}
}
}
}
static __attribute__((noinline))void wg_mutate_q(long long*Qb,const long long*y,int ldy,int reverse){
for(int bi=0;bi<2;bi++)for(int bj=0;bj<2;bj++){
const long long*yp=y+(size_t)bi*64*ldy+bj*64;
long long*q=Qb+(size_t)(bi*2+bj)*4096;
if(bi==bj){
for(int k=0;k<64;k+=2)for(int g=0;g<16;g++){
__m256i q0=_mm256_shuffle_epi32(LDQ((const __m256i*)(q+g*256+4*k)),0xB1);
__m256i q1=_mm256_shuffle_epi32(LDQ((const __m256i*)(q+g*256+4*k+4)),0xB1);
__m256i y0=LDQ((const __m256i*)(yp+(size_t)k*ldy+4*g)),y1=LDQ((const __m256i*)(yp+(size_t)(k+1)*ldy+4*g));
__m256i v0=reverse?_mm256_sub_epi64(y0,q0):_mm256_sub_epi64(q0,y0);
__m256i v1=reverse?_mm256_sub_epi64(y1,q1):_mm256_sub_epi64(q1,y1);
STQ((__m256i*)(q+g*256+4*k),_mm256_shuffle_epi32(v0,0xB1));
STQ((__m256i*)(q+g*256+4*k+4),_mm256_shuffle_epi32(v1,0xB1));
}
}else{
for(int k=0;k<64;k++)for(int g=0;g<16;g++){
__m256i qv=LDQ((const __m256i*)(q+(size_t)k*64+4*g)),yv=LDQ((const __m256i*)(yp+(size_t)k*ldy+4*g));
STQ((__m256i*)(q+(size_t)k*64+4*g),reverse?_mm256_sub_epi64(yv,qv):_mm256_sub_epi64(qv,yv));
}
}
}
}
template<int Sign,int PX,int PY>
static __attribute__((noinline))void packQ(const long long*x,const long long*y){
#pragma GCC unroll 1
for(int jb=0;jb<64;jb+=16){
long long*q0=Bpanel+(jb/4)*64*4,*q1=q0+256,*q2=q1+256,*q3=q2+256;
const long long*xp=x+(size_t)(jb/4)*256,*yp=y+(size_t)(jb/4)*256,*xr=x+jb,*yr=y+jb;
for(int k=0;k<64;k++){
__m256i a0,a1,a2,a3,b0,b1,b2,b3;
if(PX){
a0=LDQ((const __m256i*)(xp+4*k));a1=LDQ((const __m256i*)(xp+256+4*k));
a2=LDQ((const __m256i*)(xp+512+4*k));a3=LDQ((const __m256i*)(xp+768+4*k));
a0=_mm256_shuffle_epi32(a0,0xB1);a1=_mm256_shuffle_epi32(a1,0xB1);
a2=_mm256_shuffle_epi32(a2,0xB1);a3=_mm256_shuffle_epi32(a3,0xB1);
}else{
const long long*p=xr+(size_t)k*64;
a0=LDQ((const __m256i*)p);a1=LDQ((const __m256i*)(p+4));
a2=LDQ((const __m256i*)(p+8));a3=LDQ((const __m256i*)(p+12));
}
if(PY){
b0=LDQ((const __m256i*)(yp+4*k));b1=LDQ((const __m256i*)(yp+256+4*k));
b2=LDQ((const __m256i*)(yp+512+4*k));b3=LDQ((const __m256i*)(yp+768+4*k));
b0=_mm256_shuffle_epi32(b0,0xB1);b1=_mm256_shuffle_epi32(b1,0xB1);
b2=_mm256_shuffle_epi32(b2,0xB1);b3=_mm256_shuffle_epi32(b3,0xB1);
}else{
const long long*p=yr+(size_t)k*64;
b0=LDQ((const __m256i*)p);b1=LDQ((const __m256i*)(p+4));
b2=LDQ((const __m256i*)(p+8));b3=LDQ((const __m256i*)(p+12));
}
__m256i v0,v1,v2,v3;
if(Sign>0){v0=_mm256_add_epi64(a0,b0);v1=_mm256_add_epi64(a1,b1);v2=_mm256_add_epi64(a2,b2);v3=_mm256_add_epi64(a3,b3);}
else{v0=_mm256_sub_epi64(a0,b0);v1=_mm256_sub_epi64(a1,b1);v2=_mm256_sub_epi64(a2,b2);v3=_mm256_sub_epi64(a3,b3);}
STQ((__m256i*)q0,_mm256_shuffle_epi32(v0,0xB1));
STQ((__m256i*)q1,_mm256_shuffle_epi32(v1,0xB1));
STQ((__m256i*)q2,_mm256_shuffle_epi32(v2,0xB1));
STQ((__m256i*)q3,_mm256_shuffle_epi32(v3,0xB1));
q0+=4;q1+=4;q2+=4;q3+=4;
}
}
}
static __attribute__((noinline,noclone))void direct_a_leaf64_panel(const long long*a0,const long long*a1,int lda,long long*c,int ldc,const long long*bp){
for(int ic=0;ic<60;ic+=6){
packA_fixed64<1>(a0+(size_t)ic*lda,a1+(size_t)ic*lda,lda,6);
for(int j=0;j<64;j+=4)mikro64_static1152<6,0>(leaf_A64,leaf_A64+96,leaf_A64+192,leaf_A64+288,leaf_A64+384,leaf_A64+480,bp+(size_t)j*64,c+(size_t)ic*ldc+j,ldc);
}
packA_fixed64<1>(a0+(size_t)60*lda,a1+(size_t)60*lda,lda,4);
for(int j=0;j<64;j+=4)mikro64_static1152<4,0>(leaf_A64,leaf_A64+96,leaf_A64+192,leaf_A64+288,leaf_A64,leaf_A64,bp+(size_t)j*64,c+(size_t)60*ldc+j,ldc);
}
static void winograd_mini_q(int n,const long long*A,int lda,const long long*Qb,long long*C,int ldc){
const int h=n/2;const size_t sz=(size_t)h*h;
long long*M1=C,*M2=C+h,*M3=C+(size_t)h*ldc,*M4=M3+h;
long long*M5=m5_base,*M6=M5+sz+256,*M7=M6+sz+256;
const long long*a11=A,*a12=A+h,*a21=A+(size_t)h*lda,*a22=a21+h;
const long long*q0=Qb,*q1=Qb+4096,*q2=Qb+8192,*q3=Qb+12288;
packQ<1,1,0>(q0,q1);
direct_a_leaf64_arguments<-1>(a21,a11,lda,M6,h);
direct_a_leaf64_panel(a21,a22,lda,M2,ldc,q0);
packQ<-1,0,1>(q2,q0);
direct_a_leaf64_arguments<0>(a22,a22,lda,M4,ldc);
packQ<1,1,1>(q0,q3);
direct_a_leaf64_arguments<1>(a11,a22,lda,M1,ldc);
packQ<-1,0,1>(q1,q3);
direct_a_leaf64_arguments<0>(a11,a11,lda,M3,ldc);
direct_a_leaf64_panel(a11,a12,lda,M5,h,q3);
packQ<1,0,1>(q2,q3);
direct_a_leaf64_arguments<-1>(a12,a22,lda,M7,h);
for(int i=0;i+1<h;i+=2){
const long long*m1=M1+(size_t)i*ldc,*m2=M2+(size_t)i*ldc;
const long long*m3=M3+(size_t)i*ldc,*m4=M4+(size_t)i*ldc;
const long long*m5=M5+(size_t)i*h,*m6=M6+(size_t)i*h,*m7=M7+(size_t)i*h;
const long long*n1=M1+(size_t)(i+1)*ldc,*n2=M2+(size_t)(i+1)*ldc;
const long long*n3=M3+(size_t)(i+1)*ldc,*n4=M4+(size_t)(i+1)*ldc;
const long long*n5=M5+(size_t)(i+1)*h,*n6=M6+(size_t)(i+1)*h,*n7=M7+(size_t)(i+1)*h;
long long*c11=C+(size_t)i*ldc,*c12=c11+h,*c21=c11+(size_t)h*ldc,*c22=c21+h;
long long*d11=C+(size_t)(i+1)*ldc,*d12=d11+h,*d21=d11+(size_t)h*ldc,*d22=d21+h;
for(int j=0;j<h;j+=4){
__m256i p1=wg_load(m1+j),p2=wg_load(m2+j),p3=wg_load(m3+j),p4=wg_load(m4+j);
__m256i p5=wg_load(m5+j),p6=wg_load(m6+j),p7=wg_load(m7+j);
__m256i r1=wg_load(n1+j),r2=wg_load(n2+j),r3=wg_load(n3+j),r4=wg_load(n4+j);
__m256i r5=wg_load(n5+j),r6=wg_load(n6+j),r7=wg_load(n7+j);
wg_store(c11+j,_mm256_add_epi64(_mm256_sub_epi64(_mm256_add_epi64(p1,p4),p5),p7));
wg_store(c12+j,_mm256_add_epi64(p3,p5));
wg_store(c21+j,_mm256_add_epi64(p2,p4));
wg_store(c22+j,_mm256_add_epi64(_mm256_add_epi64(_mm256_sub_epi64(p1,p2),p3),p6));
wg_store(d11+j,_mm256_add_epi64(_mm256_sub_epi64(_mm256_add_epi64(r1,r4),r5),r7));
wg_store(d12+j,_mm256_add_epi64(r3,r5));
wg_store(d21+j,_mm256_add_epi64(r2,r4));
wg_store(d22+j,_mm256_add_epi64(_mm256_add_epi64(_mm256_sub_epi64(r1,r2),r3),r6));
}
}
}
static void winograd_prod(int n, const long long *A, int lda, const long long *B, int ldb,
long long *C, int ldc) {
const int h=n/2; const size_t sz=(size_t)h*h;
long long *M1=C,*M2=C+h,*M3=C+(size_t)h*ldc,*M4=M3+h;
long long *M5=wleaf,*M6=M5+sz+64,*M7=M6+sz+64,*P=M7+sz+64,*Q=P+sz+64;
const long long *A11=A,*A12=A+h,*A21=A+(size_t)h*lda,*A22=A21+h;
const long long *B11=B,*B12=B+h,*B21=B+(size_t)h*ldb,*B22=B21+h;
#define PR(X,Y,Z,LX,LY,LZ) do { winograd_mini(h,(X),(LX),(Y),(LY),(Z),(LZ)); } while(0)
PR(A11,B11,M1,lda,ldb,ldc);
PR(A12,B21,M2,lda,ldb,ldc);
wg_add(h,P,A21,lda,A22,lda,+1);
wg_add_q(Qblk,B12,ldb,B11,ldb); winograd_mini_q(h,P,h,Qblk,M5,h);
wg_mutate(h,P,A11,lda,0);
wg_mutate_q(Qblk,B22,ldb,1); winograd_mini_q(h,P,h,Qblk,M6,h);
wg_mutate(h,P,A12,lda,1);
PR(P,B22,M3,h,ldb,ldc);
wg_mutate_q(Qblk,B21,ldb,0); winograd_mini_q(h,A22,lda,Qblk,M4,ldc);
wg_add(h,P,A11,lda,A21,lda,-1);
wg_add_q(Qblk,B22,ldb,B12,ldb); winograd_mini_q(h,P,h,Qblk,M7,h);
#undef PR
wg_combine_cache(h,C,ldc,M1,M2,M3,M4,M5,M6,M7);
}
static void winograd_grandchild(int n, const long long *A, int lda, const long long *B, int ldb,
long long *C, int ldc) {
const int h=n/2; const size_t sz=(size_t)h*h;
long long *M1=C,*M2=C+h,*M3=C+(size_t)h*ldc,*M4=M3+h;
long long *M5=g_sg,*M6=M5+sz+128,*M7=M6+sz+128,*P=M7+sz+128,*Q=P+sz+128;
wleaf=M5+328192;
const long long *A11=A,*A12=A+h,*A21=A+(size_t)h*lda,*A22=A21+h;
const long long *B11=B,*B12=B+h,*B21=B+(size_t)h*ldb,*B22=B21+h;
#define PROD3(X,Y,Z,LX,LY,LZ) do { winograd_prod(h,(X),(LX),(Y),(LY),(Z),(LZ)); } while(0)
PROD3(A11,B11,M1,lda,ldb,ldc);
PROD3(A12,B21,M2,lda,ldb,ldc);
wg_add(h,P,A21,lda,A22,lda,+1);
wg_add(h,Q,B12,ldb,B11,ldb,-1);
PROD3(P,Q,M5,h,h,h);
wg_mutate(h,P,A11,lda,0);
wg_mutate(h,Q,B22,ldb,1);
PROD3(P,Q,M6,h,h,h);
wg_mutate(h,P,A12,lda,1);
PROD3(P,B22,M3,h,ldb,ldc);
wg_mutate(h,Q,B21,ldb,0);
PROD3(A22,Q,M4,lda,h,ldc);
wg_add(h,P,A11,lda,A21,lda,-1);
wg_add(h,Q,B22,ldb,B12,ldb,-1);
PROD3(P,Q,M7,h,h,h);
#undef PROD3
wg_combine_cache(h,C,ldc,M1,M2,M3,M4,M5,M6,M7);
}
static void winograd_child(int n, const long long *A, int lda, const long long *B, int ldb,
long long *C, int ldc) {
const int h=n/2; const size_t sz=(size_t)h*h;
long long *M1=C,*M2=C+h,*M3=C+(size_t)h*ldc,*M4=M3+h;
long long *M5=g_sc,*M6=M5+sz+256,*M7=M6+sz+256,*P=M7+sz+256,*Q=P+sz+256;
long long *S3=Q+sz+256,*T3=S3+sz+256;
g_sg=g_sgo?g_sgo:M3; long long *CS=M3;
const long long *A11=A,*A12=A+h,*A21=A+(size_t)h*lda,*A22=A21+h;
const long long *B11=B,*B12=B+h,*B21=B+(size_t)h*ldb,*B22=B21+h;
#define PROD2(X,Y,Z,LX,LY,LZ,SC) do { g_sc=SC; winograd_grandchild(h,(X),(LX),(Y),(LY),(Z),(LZ)); } while(0)
PROD2(A11,B11,M1,lda,ldb,ldc,CS);
PROD2(A12,B21,M2,lda,ldb,ldc,CS);
wg_nAS(h,P,S3,A11,A21,A22,lda);
wg_nBT(h,Q,T3,B11,B12,B22,ldb);
PROD2(P,Q,M5,h,h,h,CS);
PROD2(S3,T3,M7,h,h,h,CS);
wg_nAS2(h,S3,P,P,A11,A12,lda);
wg_nBT2(h,T3,Q,Q,B22,B21,ldb);
PROD2(S3,T3,M6,h,h,h,CS);
g_sg=S3;
PROD2(P,B22,M3,h,ldb,ldc,S3);
PROD2(A22,Q,M4,lda,h,ldc,S3);
#undef PROD2
wg_combine_cache(h,C,ldc,M1,M2,M3,M4,M5,M6,M7);
}
static void winograd_top(int n, const long long *A, const long long *B, long long *C) {
const int h=n/2; const size_t sz=(size_t)h*h;
long long *M1=C,*M2=C+h,*M3=C+(size_t)h*n,*M4=M3+h;
long long *M5=wg_buf,*M6=M5+sz+512,*M7=M6+sz+512,*P=M7+sz+512,*Q=P+sz+512;
long long *S3=Q+sz+512,*T3=S3+sz+512,*CS=C+(size_t)h*n;
g_sgo=0;
const long long *A11=A,*A12=A+h,*A21=A+(size_t)h*n,*A22=A21+h;
const long long *B11=B,*B12=B+h,*B21=B+(size_t)h*n,*B22=B21+h;
#define PROD(X,Y,Z,LX,LY,LZ,SC) do { g_sc=SC; winograd_child(h,(X),(LX),(Y),(LY),(Z),(LZ)); } while(0)
PROD(A11,B11,M1,n,n,n,CS);
g_sgo=M6;
PROD(A12,B21,M2,n,n,n,CS);
g_sgo=0;
wg_nAS(h,P,S3,A11,A21,A22,n);
wg_nBT(h,Q,T3,B11,B12,B22,n);
PROD(P,Q,M5,h,h,h,CS);
PROD(S3,T3,M7,h,h,h,CS);
wg_nAS2(h,S3,P,P,A11,A12,n);
wg_nBT2(h,T3,Q,Q,B22,B21,n);
PROD(S3,T3,M6,h,h,h,CS);
PROD(P,B22,M3,h,n,n,S3);
g_sgo=P;
PROD(A22,Q,M4,n,h,n,S3);
#undef PROD
wg_combine_cache(h,C,n,M1,M2,M3,M4,M5,M6,M7);
}
void matrix_multiply(int n, const long long *A, const long long *B, long long *C) {
if (n == 2048) { winograd_top(2048, A, B, C); return; }
Opd Ao = o1(A, n), Bo = o1(B, n);
if (n <= CUTL || (n & 1)) { leaf(n, &Ao, &Bo, C, n, 0, 0, 0, 0); return; }
mmxR(n, &Ao, &Bo, C, n, 0, g_scratch);
}
#pragma GCC pop_options
| Compilation | N/A | N/A | Compile OK | Score: N/A | 显示更多 |
| Testcase #1 | 713.384 ms | 88 MB + 292 KB | Accepted | Score: 100 | 显示更多 |