// ===== REFERENCES =====
// [0] duck.ac 用户 **saffah_cc_v41_agg1**(本账号),提交 **#124209** <https://duck.ac/submission/124209>
// —— 本件正文 = 该提交正文的**逐字节副本**(md5 e948f3b317dc40fa8e37eb4cb3305c39),
// 唯一改动 = 本发对 `pending` 注入相 **C 象限读流**(该相唯一无预取覆盖的流)的单变量改动
// (见下「思路」;引擎其余每一行、每一常数均未改动)。上游引用链(#124155 / #124034 /
// #124021 / #120514 / #119223 / #118747 等)在文件内原样保留,本席未改动其中任何一行。
// [1] duck.ac 用户 **saffah_codex_6a_agg3**,提交 **#120514** <https://duck.ac/submission/120514>
// (265.772622 ms = 本题榜 1 / 现 T)—— 仅作判读口径引用,未改动其中任何一行。
// [2] 本队台账 `problems/mmmd2k/notes.md`:`pending` 注入相在册封条
// ((7264-d2zw-m4ws) 全引擎 hint 普查 + m 面剂量曲线 0/4/12/24 = +0.290/+0.092/0/+0.263 ms(**板面**)·
// `d2zr_` #124155「删 c 象限 4 条预取」**板面 −0.128 ms** · (2908-d2zk-q7v2) 逐类读账 ·
// (2910-d2zm-8v3n) 非 k 环互斥表(叶内桥 = 资产,删之更慢)· (2918-d2zp-pmlf) 参数族)
// [3] 量具:本席自写 `problems/mmmd2k/work/d3b__tmp/{d3b_mkprobe.py, d3b_probe.cpp, d3b_mkcg.py,
// d3b_mkcert.py, d3b_mkarm.py, d3b_mksub.py}`(判题机免费通道逐臂 rdtsc + 四档逐位锚
// `7235d94f`(512) / `f52f809d`(1024) / `7e1f2b18`(2048) / `26d81789`(4096);cachegrind 确定性流量账)。
// 引擎正文与量测件**逐 token 同**,量测件只在文件尾追加 harness。
// 许可证:以上均为 duck.ac 公开提交,未见许可证声明;本文件按 RULES §3 逐项署名引用。
// 本席未复用任何第三方代码(器械、证书仪、定价 harness、生成器均自写)。
//
// ===== 思路 =====
// [d3b_ 席] `pending` 注入相的「容量失配」逐项定价 + C 象限读流的等量再瞄准(唯一可动旋钮)
// 【本席的坐标】把「7 趟 × 8 MiB C 块」这条**结构量**(不是簿记)逐项定价,并找**不增总字节/不增流数**的重构。
// 【逐项账(判题机逐位证书 + 地址级证书,n=2048)】`pending_step` **7 趟 × 8192 步 = 57 344 步**
// (`pending_finish` 排空仅 512 步 = 0.9%);每步触达 = 4 C 象限读 32 B×8 + 4 C 象限写 32 B×8
// + 3 平面读 32 B×8 ⇒ **23.07 MB/趟 × 7 = 161.5 MB**(读 102.8 / 写 58.7)。
// ★ **地址级勘误**:7 趟的 C 目标是 **7 个互不相同的 8 MiB 块**(3 个真 C 象限 ldc=2048
// + 4 个 workspace 面板 ldc=1024,见 `d3b_cert` 的 c 指针表)⇒ **不存在「同一个 8 MB 块被
// 7 趟各读+写一次」**;每字节每趟恰被触达一次(读-改-写同址)。
// 【容量失配是真的,但它不是可兑现池】cachegrind(LL=6 MB/12 路,判题机口径):
// C 象限读 = **909 177 冷行 = 58.2 MB**(全 LL miss;产物由内核 `vmovntpd` 直落 DRAM ⇒ 必冷);
// C 象限**写 = D1 命中**(读-改-写命中刚载入的行 ⇒ 零 RFO,DLmw 差 −0.1 MB),写侧只有回写流量;
// m 三平面读 = 600 737 冷行 = 38.4 MB ⇒ **整个注入相 = 96.6 MB 冷读 = 全引擎 548 MB 冷读的 17.6%**。
// 【判题机实测上界(免费通道,n=2048,镜像定序 3+3 对)】把 C 目标整体改到 512 KB scratch
// (读+写全去)⇒ **−4.8~5.0 M 拍 = −0.53% = −1.35 ms**。★ 无位置对照的首发读数 −1.064% 是**伪影**
// (免费通道**每次调用内第一趟慢 ~0.5%**;本席用镜像臂定量:首趟 − 次趟 = 5.0~5.5 M 拍)。
// ⇒ **该轴的理论天花板(不可达)1.35 ms < 缺口 2.118585 ms ⇒ 结构性判死。**
// 【为什么不增字节/不增条数的重构不存在】逐元素**聚合(gather)已是最小**:7 读 + 4 写;
// 任何「分发(distribute)」形态都要 ≥12 次读-改-写(本席按四象限依赖图逐条算);
// 而「融合进产出趟以省下产物物化」需要 7 个 B 变换面板同时驻留(14.7 MB > L2/L3)——
// 现役 2.1 MB 的 B 包是 L2 驻留,融合会把它推到 DRAM ⇒ 净亏,且违三约束(环体字节/条数)。
// 【本发 = 该轴上唯一剩下的可变旋钮】C 象限读流**无预取覆盖**(`d2zr_` #124155 已删 4 条 c 预取,
// 板面 −0.128 ms 证实其**覆盖无效**)。本发做**等量再瞄准**:C 象限读流加回 4 条流、**距离 2 步**(= 64 个 pos ≈ 2 个核调用)——`d2zr_` 删掉的原形态距离仅 ≈1 步(无 lead time),本发测的是**距离轴**上未被板面定价的一点。 ★ 本发取值 = `cdist=2`(m 面 12 行不变 + C 象限 4 流×4 行、距离 2 步)。
// 值中性:`_mm_prefetch` 不写任何架构状态(四档闸门 512/1024/2048/4096 全中在册锚)。
// 【判据纪律】板面为唯一判据(律 352:预取类改动暖态可反号);绝不设比 (T*0.99+1µs) 更严的门槛(律 294)。
// ===== 引用(按 RULES §3;本文件正文的继承引用链在下方原样保留) =====
#pragma GCC optimize("O3,no-strict-aliasing,reorder-blocks-and-partition,peel-loops")
#pragma GCC target("arch=skylake")
#include <immintrin.h>
#include <stddef.h>
#include <sys/mman.h>
static constexpr int d2k_z7_p3 = (2 - 2);
#include <immintrin.h>
#define MD9_T2BASE 1
#include <stddef.h>
#include <sys/mman.h>
#ifndef BASE
#define BASE 512
#endif
#ifndef MC
#define MC (2+28)
#endif
#ifndef NTMIN
#define NTMIN 512
#endif
#ifndef UPPER_PAGE_PAD
#define UPPER_PAGE_PAD 15872
#endif
#ifndef LEAF_PAD
#define LEAF_PAD (384 * 3)
#endif
#ifndef SUMNT
#define SUMNT 2048
static int d2lz_root_last=0;
static const double *d2lz_acc=0;
#endif
static constexpr int MR=6,NR=8;
alignas(4096) static double workspace[48*1024*1024];
alignas(64) static double ap[(MC+MR)*(BASE+24)],ap2[(MC+MR)*(BASE+24)],bp[BASE*(BASE+24)];
alignas(64) static double pk_zero[BASE+8];
alignas(64) static double pk_mp[4]={0.0,0.0,0.0,0.0}, pk_mn[4]={-0.0,-0.0,-0.0,-0.0};
struct Mat { const double *x; int ld; const double *y=nullptr; int ly=0; int sign=0; };
static inline __m256d ld(Mat a,int i,int j) {
__m256d x=_mm256_load_pd(a.x+(size_t)i*a.ld+j);
if(a.sign) {
__m256d y=_mm256_load_pd(a.y+(size_t)i*a.ly+j);
x=a.sign>0?_mm256_add_pd(x,y):_mm256_sub_pd(x,y);
}
return x;
}
static inline double scalar(Mat a,int i,int k) {
double x=a.x[(size_t)i*a.ld+k];
if(a.sign)x+=a.sign>0?a.y[(size_t)i*a.ly+k]:-a.y[(size_t)i*a.ly+k];
return x;
}
template<int SG> static __attribute__((always_inline)) inline void kernel(int n,const double *a,const double *b,double *c,int ldc,int rows,
const double *pks,const double *pky,double *pkd) {
double *out=c;
ptrdiff_t stride=(ptrdiff_t)ldc*8;
int k=n; long ip=-(long)(n/8)*64; (void)k;
asm volatile (
"vxorpd %%ymm0, %%ymm0, %%ymm0\n\t"
"vxorpd %%ymm1, %%ymm1, %%ymm1\n\t"
"vxorpd %%ymm2, %%ymm2, %%ymm2\n\t"
"vxorpd %%ymm3, %%ymm3, %%ymm3\n\t"
"vxorpd %%ymm4, %%ymm4, %%ymm4\n\t"
"vxorpd %%ymm5, %%ymm5, %%ymm5\n\t"
"vxorpd %%ymm6, %%ymm6, %%ymm6\n\t"
"vxorpd %%ymm7, %%ymm7, %%ymm7\n\t"
"vxorpd %%ymm8, %%ymm8, %%ymm8\n\t"
"vxorpd %%ymm9, %%ymm9, %%ymm9\n\t"
"vxorpd %%ymm10, %%ymm10, %%ymm10\n\t"
"vxorpd %%ymm11, %%ymm11, %%ymm11\n\t"
".p2align 6\n\t"
"1:\n\t"
".if %c[sg] != 0\n\t"
"vmovapd 32768(%[b],%[i],8), %%ymm12\n\t"
"vmovapd 32800(%[b],%[i],8), %%ymm13\n\t"
"vbroadcastsd %c[o0]+4096(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm0\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm1\n\t"
"vbroadcastsd %c[o1]+4096(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm2\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm3\n\t"
"prefetcht0 33280(%[b],%[i],8)\n\t"
"vbroadcastsd %c[o2]+4096(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm4\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm5\n\t"
"vbroadcastsd %c[o3]+4096(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm6\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm7\n\t"
"vbroadcastsd %c[o4]+4096(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm8\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm9\n\t"
"vbroadcastsd %c[o5]+4096(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm10\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm11\n\t"
"vmovapd 32832(%[b],%[i],8), %%ymm12\n\t"
"vmovapd 32864(%[b],%[i],8), %%ymm13\n\t"
"vbroadcastsd %c[o0]+4104(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm0\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm1\n\t"
"vbroadcastsd %c[o1]+4104(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm2\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm3\n\t"
"prefetcht0 33344(%[b],%[i],8)\n\t"
"vbroadcastsd %c[o2]+4104(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm4\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm5\n\t"
"vbroadcastsd %c[o3]+4104(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm6\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm7\n\t"
"vbroadcastsd %c[o4]+4104(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm8\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm9\n\t"
"vbroadcastsd %c[o5]+4104(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm10\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm11\n\t"
"vmovapd 32896(%[b],%[i],8), %%ymm12\n\t"
"vmovapd 32928(%[b],%[i],8), %%ymm13\n\t"
"vbroadcastsd %c[o0]+4112(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm0\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm1\n\t"
"vbroadcastsd %c[o1]+4112(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm2\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm3\n\t"
"prefetcht0 33408(%[b],%[i],8)\n\t"
"vbroadcastsd %c[o2]+4112(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm4\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm5\n\t"
"vbroadcastsd %c[o3]+4112(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm6\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm7\n\t"
"vbroadcastsd %c[o4]+4112(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm8\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm9\n\t"
"vbroadcastsd %c[o5]+4112(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm10\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm11\n\t"
"vmovapd 32960(%[b],%[i],8), %%ymm12\n\t"
"vmovapd 32992(%[b],%[i],8), %%ymm13\n\t"
"vbroadcastsd %c[o0]+4120(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm0\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm1\n\t"
"vbroadcastsd %c[o1]+4120(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm2\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm3\n\t"
"prefetcht0 33472(%[b],%[i],8)\n\t"
"vbroadcastsd %c[o2]+4120(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm4\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm5\n\t"
"vbroadcastsd %c[o3]+4120(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm6\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm7\n\t"
"vbroadcastsd %c[o4]+4120(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm8\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm9\n\t"
"vbroadcastsd %c[o5]+4120(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm10\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm11\n\t"
"vmovapd 33024(%[b],%[i],8), %%ymm12\n\t"
"vmovapd 33056(%[b],%[i],8), %%ymm13\n\t"
"vbroadcastsd %c[o0]+4128(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm0\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm1\n\t"
"vbroadcastsd %c[o1]+4128(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm2\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm3\n\t"
"prefetcht0 33536(%[b],%[i],8)\n\t"
"vbroadcastsd %c[o2]+4128(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm4\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm5\n\t"
"vbroadcastsd %c[o3]+4128(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm6\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm7\n\t"
"vbroadcastsd %c[o4]+4128(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm8\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm9\n\t"
"vbroadcastsd %c[o5]+4128(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm10\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm11\n\t"
"vmovapd 33088(%[b],%[i],8), %%ymm12\n\t"
"vmovapd 33120(%[b],%[i],8), %%ymm13\n\t"
"vbroadcastsd %c[o0]+4136(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm0\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm1\n\t"
"vbroadcastsd %c[o1]+4136(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm2\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm3\n\t"
"prefetcht0 33600(%[b],%[i],8)\n\t"
"vbroadcastsd %c[o2]+4136(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm4\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm5\n\t"
"vbroadcastsd %c[o3]+4136(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm6\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm7\n\t"
"vbroadcastsd %c[o4]+4136(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm8\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm9\n\t"
"vbroadcastsd %c[o5]+4136(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm10\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm11\n\t"
"vmovapd 33152(%[b],%[i],8), %%ymm12\n\t"
"vmovapd 33184(%[b],%[i],8), %%ymm13\n\t"
"vbroadcastsd %c[o0]+4144(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm0\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm1\n\t"
"vbroadcastsd %c[o1]+4144(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm2\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm3\n\t"
"prefetcht0 33664(%[b],%[i],8)\n\t"
"vbroadcastsd %c[o2]+4144(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm4\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm5\n\t"
"vbroadcastsd %c[o3]+4144(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm6\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm7\n\t"
"vbroadcastsd %c[o4]+4144(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm8\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm9\n\t"
"vbroadcastsd %c[o5]+4144(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm10\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm11\n\t"
"vmovapd 33216(%[b],%[i],8), %%ymm12\n\t"
"vmovapd 33248(%[b],%[i],8), %%ymm13\n\t"
"vbroadcastsd %c[o0]+4152(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm0\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm1\n\t"
"vbroadcastsd %c[o1]+4152(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm2\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm3\n\t"
"prefetcht0 33728(%[b],%[i],8)\n\t"
"vbroadcastsd %c[o2]+4152(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm4\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm5\n\t"
"vbroadcastsd %c[o3]+4152(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm6\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm7\n\t"
"vbroadcastsd %c[o4]+4152(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm8\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm9\n\t"
"vbroadcastsd %c[o5]+4152(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm10\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm11\n\t"
"vmovupd 0(%[pks]), %%ymm15\n\t"
".if %c[sg] == 1\n\t"
"vaddpd 0(%[pky]), %%ymm15, %%ymm15\n\t"
".elseif %c[sg] == -1\n\t"
"vsubpd 0(%[pky]), %%ymm15, %%ymm15\n\t"
".endif\n\t"
"vmovupd %%ymm15, 0(%[pkd])\n\t"
"add $32, %[pks]\n\t"
"add $32, %[pky]\n\t"
"add $32, %[pkd]\n\t"
"add $64, %[i]\n\t"
".else\n\t"
"prefetcht0 512(%[b])\n\t"
"prefetcht0 576(%[b])\n\t"
"prefetcht0 640(%[b])\n\t"
"prefetcht0 704(%[b])\n\t"
"vmovapd 0(%[b]), %%ymm12\n\t"
"vmovapd 32(%[b]), %%ymm13\n\t"
"vbroadcastsd %c[o0]+0(%[a]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm0\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm1\n\t"
"vbroadcastsd %c[o1]+0(%[a]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm2\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm3\n\t"
"vbroadcastsd %c[o2]+0(%[a]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm4\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm5\n\t"
"vbroadcastsd %c[o3]+0(%[a]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm6\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm7\n\t"
"vbroadcastsd %c[o4]+0(%[a]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm8\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm9\n\t"
"vbroadcastsd %c[o5]+0(%[a]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm10\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm11\n\t"
"vmovapd 64(%[b]), %%ymm12\n\t"
"vmovapd 96(%[b]), %%ymm13\n\t"
"vbroadcastsd %c[o0]+8(%[a]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm0\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm1\n\t"
"vbroadcastsd %c[o1]+8(%[a]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm2\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm3\n\t"
"vbroadcastsd %c[o2]+8(%[a]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm4\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm5\n\t"
"vbroadcastsd %c[o3]+8(%[a]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm6\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm7\n\t"
"vbroadcastsd %c[o4]+8(%[a]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm8\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm9\n\t"
"vbroadcastsd %c[o5]+8(%[a]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm10\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm11\n\t"
"vmovapd 128(%[b]), %%ymm12\n\t"
"vmovapd 160(%[b]), %%ymm13\n\t"
"vbroadcastsd %c[o0]+16(%[a]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm0\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm1\n\t"
"vbroadcastsd %c[o1]+16(%[a]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm2\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm3\n\t"
"vbroadcastsd %c[o2]+16(%[a]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm4\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm5\n\t"
"vbroadcastsd %c[o3]+16(%[a]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm6\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm7\n\t"
"vbroadcastsd %c[o4]+16(%[a]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm8\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm9\n\t"
"vbroadcastsd %c[o5]+16(%[a]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm10\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm11\n\t"
"vmovapd 192(%[b]), %%ymm12\n\t"
"vmovapd 224(%[b]), %%ymm13\n\t"
"vbroadcastsd %c[o0]+24(%[a]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm0\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm1\n\t"
"vbroadcastsd %c[o1]+24(%[a]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm2\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm3\n\t"
"vbroadcastsd %c[o2]+24(%[a]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm4\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm5\n\t"
"vbroadcastsd %c[o3]+24(%[a]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm6\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm7\n\t"
"vbroadcastsd %c[o4]+24(%[a]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm8\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm9\n\t"
"vbroadcastsd %c[o5]+24(%[a]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm10\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm11\n\t"
"add $32, %[a]\n\t"
"add $256, %[b]\n\t"
"sub $4, %[k]\n\t"
".endif\n\t"
"jnz 1b\n\t"
"vmovntpd %%ymm0, (%[out])\n\t"
"vmovntpd %%ymm1, 32(%[out])\n\t"
"add %[stride], %[out]\n\t"
"vmovntpd %%ymm2, (%[out])\n\t"
"vmovntpd %%ymm3, 32(%[out])\n\t"
"add %[stride], %[out]\n\t"
"vmovntpd %%ymm4, (%[out])\n\t"
"vmovntpd %%ymm5, 32(%[out])\n\t"
"add %[stride], %[out]\n\t"
"vmovntpd %%ymm6, (%[out])\n\t"
"vmovntpd %%ymm7, 32(%[out])\n\t"
"add %[stride], %[out]\n\t"
"vmovntpd %%ymm8, (%[out])\n\t"
"vmovntpd %%ymm9, 32(%[out])\n\t"
"add %[stride], %[out]\n\t"
"vmovntpd %%ymm10, (%[out])\n\t"
"vmovntpd %%ymm11, 32(%[out])\n\t"
: [a] "+&r"(a), [b] "+&r"(b), [out] "+&r"(out), [k] "+&r"(k), [i] "+&r"(ip),
[pks] "+&r"(pks), [pky] "+&r"(pky), [pkd] "+&r"(pkd)
: [stride] "r"(stride), [sg] "i"(SG), [o0] "i"(0*(BASE+24)*8), [o1] "i"(1*(BASE+24)*8), [o2] "i"(2*(BASE+24)*8), [o3] "i"(3*(BASE+24)*8), [o4] "i"(4*(BASE+24)*8), [o5] "i"(5*(BASE+24)*8)
: "memory", "cc", "ymm0","ymm1","ymm2","ymm3","ymm4","ymm5","ymm6","ymm7","ymm8","ymm9","ymm10","ymm11","ymm12","ymm13","ymm14","ymm15");
}
static __attribute__((always_inline)) inline void kernel_plain(int n,const double *a,const double *b,double *c,int ldc,int rows) {
double *out=c;
ptrdiff_t stride=(ptrdiff_t)ldc*8;
int k=n; long ip=-(long)(n/8)*64; (void)k;
asm volatile (
"vxorpd %%ymm0, %%ymm0, %%ymm0\n\t"
"vxorpd %%ymm1, %%ymm1, %%ymm1\n\t"
"vxorpd %%ymm2, %%ymm2, %%ymm2\n\t"
"vxorpd %%ymm3, %%ymm3, %%ymm3\n\t"
"vxorpd %%ymm4, %%ymm4, %%ymm4\n\t"
"vxorpd %%ymm5, %%ymm5, %%ymm5\n\t"
"vxorpd %%ymm6, %%ymm6, %%ymm6\n\t"
"vxorpd %%ymm7, %%ymm7, %%ymm7\n\t"
"vxorpd %%ymm8, %%ymm8, %%ymm8\n\t"
"vxorpd %%ymm9, %%ymm9, %%ymm9\n\t"
"vxorpd %%ymm10, %%ymm10, %%ymm10\n\t"
"vxorpd %%ymm11, %%ymm11, %%ymm11\n\t"
".p2align 6\n\t"
"1:\n\t"
"vmovapd 32768(%[b],%[i],8), %%ymm12\n\t"
"vmovapd 32800(%[b],%[i],8), %%ymm13\n\t"
"vbroadcastsd %c[o0]+4096(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm0\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm1\n\t"
"vbroadcastsd %c[o1]+4096(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm2\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm3\n\t"
"prefetcht0 33280(%[b],%[i],8)\n\t"
"vbroadcastsd %c[o2]+4096(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm4\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm5\n\t"
"vbroadcastsd %c[o3]+4096(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm6\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm7\n\t"
"vbroadcastsd %c[o4]+4096(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm8\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm9\n\t"
"vbroadcastsd %c[o5]+4096(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm10\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm11\n\t"
"vmovapd 32832(%[b],%[i],8), %%ymm12\n\t"
"vmovapd 32864(%[b],%[i],8), %%ymm13\n\t"
"vbroadcastsd %c[o0]+4104(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm0\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm1\n\t"
"vbroadcastsd %c[o1]+4104(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm2\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm3\n\t"
"prefetcht0 33344(%[b],%[i],8)\n\t"
"vbroadcastsd %c[o2]+4104(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm4\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm5\n\t"
"vbroadcastsd %c[o3]+4104(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm6\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm7\n\t"
"vbroadcastsd %c[o4]+4104(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm8\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm9\n\t"
"vbroadcastsd %c[o5]+4104(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm10\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm11\n\t"
"vmovapd 32896(%[b],%[i],8), %%ymm12\n\t"
"vmovapd 32928(%[b],%[i],8), %%ymm13\n\t"
"vbroadcastsd %c[o0]+4112(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm0\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm1\n\t"
"vbroadcastsd %c[o1]+4112(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm2\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm3\n\t"
"prefetcht0 33408(%[b],%[i],8)\n\t"
"vbroadcastsd %c[o2]+4112(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm4\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm5\n\t"
"vbroadcastsd %c[o3]+4112(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm6\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm7\n\t"
"vbroadcastsd %c[o4]+4112(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm8\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm9\n\t"
"vbroadcastsd %c[o5]+4112(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm10\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm11\n\t"
"vmovapd 32960(%[b],%[i],8), %%ymm12\n\t"
"vmovapd 32992(%[b],%[i],8), %%ymm13\n\t"
"vbroadcastsd %c[o0]+4120(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm0\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm1\n\t"
"vbroadcastsd %c[o1]+4120(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm2\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm3\n\t"
"prefetcht0 33472(%[b],%[i],8)\n\t"
"vbroadcastsd %c[o2]+4120(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm4\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm5\n\t"
"vbroadcastsd %c[o3]+4120(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm6\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm7\n\t"
"vbroadcastsd %c[o4]+4120(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm8\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm9\n\t"
"vbroadcastsd %c[o5]+4120(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm10\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm11\n\t"
"vmovapd 33024(%[b],%[i],8), %%ymm12\n\t"
"vmovapd 33056(%[b],%[i],8), %%ymm13\n\t"
"vbroadcastsd %c[o0]+4128(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm0\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm1\n\t"
"vbroadcastsd %c[o1]+4128(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm2\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm3\n\t"
"prefetcht0 33536(%[b],%[i],8)\n\t"
"vbroadcastsd %c[o2]+4128(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm4\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm5\n\t"
"vbroadcastsd %c[o3]+4128(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm6\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm7\n\t"
"vbroadcastsd %c[o4]+4128(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm8\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm9\n\t"
"vbroadcastsd %c[o5]+4128(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm10\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm11\n\t"
"vmovapd 33088(%[b],%[i],8), %%ymm12\n\t"
"vmovapd 33120(%[b],%[i],8), %%ymm13\n\t"
"vbroadcastsd %c[o0]+4136(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm0\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm1\n\t"
"vbroadcastsd %c[o1]+4136(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm2\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm3\n\t"
"prefetcht0 33600(%[b],%[i],8)\n\t"
"vbroadcastsd %c[o2]+4136(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm4\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm5\n\t"
"vbroadcastsd %c[o3]+4136(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm6\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm7\n\t"
"vbroadcastsd %c[o4]+4136(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm8\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm9\n\t"
"vbroadcastsd %c[o5]+4136(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm10\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm11\n\t"
"vmovapd 33152(%[b],%[i],8), %%ymm12\n\t"
"vmovapd 33184(%[b],%[i],8), %%ymm13\n\t"
"vbroadcastsd %c[o0]+4144(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm0\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm1\n\t"
"vbroadcastsd %c[o1]+4144(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm2\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm3\n\t"
"prefetcht0 33664(%[b],%[i],8)\n\t"
"vbroadcastsd %c[o2]+4144(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm4\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm5\n\t"
"vbroadcastsd %c[o3]+4144(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm6\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm7\n\t"
"vbroadcastsd %c[o4]+4144(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm8\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm9\n\t"
"vbroadcastsd %c[o5]+4144(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm10\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm11\n\t"
"vmovapd 33216(%[b],%[i],8), %%ymm12\n\t"
"vmovapd 33248(%[b],%[i],8), %%ymm13\n\t"
"vbroadcastsd %c[o0]+4152(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm0\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm1\n\t"
"vbroadcastsd %c[o1]+4152(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm2\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm3\n\t"
"prefetcht0 33728(%[b],%[i],8)\n\t"
"vbroadcastsd %c[o2]+4152(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm4\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm5\n\t"
"vbroadcastsd %c[o3]+4152(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm6\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm7\n\t"
"vbroadcastsd %c[o4]+4152(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm8\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm9\n\t"
"vbroadcastsd %c[o5]+4152(%[a],%[i]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm10\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm11\n\t"
"add $64, %[i]\n\t"
"jnz 1b\n\t"
"vmovntpd %%ymm0, (%[out])\n\t"
"vmovntpd %%ymm1, 32(%[out])\n\t"
"add %[stride], %[out]\n\t"
"vmovntpd %%ymm2, (%[out])\n\t"
"vmovntpd %%ymm3, 32(%[out])\n\t"
"add %[stride], %[out]\n\t"
"vmovntpd %%ymm4, (%[out])\n\t"
"vmovntpd %%ymm5, 32(%[out])\n\t"
"add %[stride], %[out]\n\t"
"vmovntpd %%ymm6, (%[out])\n\t"
"vmovntpd %%ymm7, 32(%[out])\n\t"
"add %[stride], %[out]\n\t"
"vmovntpd %%ymm8, (%[out])\n\t"
"vmovntpd %%ymm9, 32(%[out])\n\t"
"add %[stride], %[out]\n\t"
"vmovntpd %%ymm10, (%[out])\n\t"
"vmovntpd %%ymm11, 32(%[out])\n\t"
: [a] "+&r"(a), [b] "+&r"(b), [out] "+&r"(out), [k] "+&r"(k), [i] "+&r"(ip)
: [stride] "r"(stride), [o0] "i"(0*(BASE+24)*8), [o1] "i"(1*(BASE+24)*8), [o2] "i"(2*(BASE+24)*8), [o3] "i"(3*(BASE+24)*8), [o4] "i"(4*(BASE+24)*8), [o5] "i"(5*(BASE+24)*8)
: "memory", "cc", "ymm0","ymm1","ymm2","ymm3","ymm4","ymm5","ymm6","ymm7","ymm8","ymm9","ymm10","ymm11","ymm12","ymm13","ymm14","ymm15");
}
struct Pend2 { double *c; int ldc; const double *m; const double *m2; const double *m3; int h; int pz; int pos; bool active; int i, j; };
static Pend2 pend2={0,0,0,0,0,0,0,0,false,0,0};
static constexpr int STEP2=16;
static inline void pend2_prefetch(void){
if(!pend2.active)return;
const int i=pend2.i, j=pend2.j;
const double *c=pend2.c+(size_t)i*pend2.ldc+j;
const double *m=pend2.m+pend2.pos;
for(int t=0;t<STEP2;t+=8) {
_mm_prefetch((const char*)(c+t),_MM_HINT_T1);
_mm_prefetch((const char*)(c+pend2.h+t),_MM_HINT_T1);
_mm_prefetch((const char*)(c+(size_t)pend2.h*pend2.ldc+t),_MM_HINT_T1);
_mm_prefetch((const char*)(c+(size_t)pend2.h*pend2.ldc+pend2.h+t),_MM_HINT_T1);
_mm_prefetch((const char*)(m+t),_MM_HINT_T1);
_mm_prefetch((const char*)(pend2.m2+pend2.pos+t),_MM_HINT_T1);
_mm_prefetch((const char*)(pend2.m3+pend2.pos+t),_MM_HINT_T1);
}
}
static inline void pend2_step(void){
const int i=pend2.i, j=pend2.j;
for(int t=0;t<STEP2;t+=4) {
double *c11=pend2.c+(size_t)i*pend2.ldc+j+t,*c12=c11+pend2.h,
*c21=c11+(size_t)pend2.h*pend2.ldc,*c22=c21+pend2.h;
const double *m=pend2.m+pend2.pos+t;
__m256d m1=_mm256_load_pd(c11),m2=_mm256_load_pd(c21),
m3=_mm256_load_pd(c12),m4=_mm256_load_pd(c22),
m5=_mm256_load_pd(m),m6=_mm256_load_pd(pend2.m2+pend2.pos+t),m7=_mm256_load_pd(pend2.m3+pend2.pos+t);
__m256d u2=_mm256_add_pd(m1,m6),u3=_mm256_add_pd(u2,m7),u4=_mm256_add_pd(u2,m5);
__m256d r11=_mm256_add_pd(m1,m2),r12=_mm256_add_pd(u4,m3),
r21=_mm256_sub_pd(u3,m4),r22=_mm256_add_pd(u3,m5);
_mm256_store_pd(c11,r11);_mm256_store_pd(c12,r12);
_mm256_store_pd(c21,r21);_mm256_store_pd(c22,r22);
}
pend2.pos+=STEP2;
pend2.j+=STEP2; if(pend2.j>=pend2.h){pend2.j-=pend2.h;pend2.i++;}
if(pend2.pos>=pend2.h*pend2.h)pend2.active=false;
}
static void pend2_finish(void){ while(pend2.active)pend2_step(); }
struct Pending { double *c; int ldc; const double *m; int pos=0; bool active=false; int rowlim=0; bool prog=false; };
static Pending pending;
/* [d3b_] runtime knobs (harness-set; zero effect on the hot path's shape) */
static int d3b_cflag=0, d3b_cdist=2, d3b_moff=0, d3b_ctyp=0, d3b_trade=0, d3b_dlz=0;
alignas(64) static double d3b_sc[65536];
alignas(4096) static double pending_work[3*(BASE*BASE+LEAF_PAD)+LEAF_PAD];
static unsigned pending_tick=0;
static constexpr int STEP=32, PERIOD=1;
static inline void pending_prefetch() {
if(!pending.active)return;
if(pending.prog && pending.pos/BASE>=pending.rowlim)return;
int i=pending.pos/BASE,j=pending.pos%BASE;
const double *c=pending.c+(size_t)i*pending.ldc+j;
const double *m=pending.m+pending.pos+STEP;
if(!d3b_moff) for(int t=0;t<STEP;t+=8) {
int np=3-d3b_trade; if(np<0)np=0;
_mm_prefetch((const char*)(m+t),_MM_HINT_T0);
if(np>1)_mm_prefetch((const char*)(m+(BASE*BASE+LEAF_PAD)+t),_MM_HINT_T0);
if(np>2)_mm_prefetch((const char*)(m+2*(BASE*BASE+LEAF_PAD)+t),_MM_HINT_T0);
}
if(d3b_trade){ /* same line count re-aimed at the C quadrants (merge = read-modify-write) */
const double *q=pending.c+(size_t)(pending.pos/BASE)*pending.ldc+(pending.pos%BASE);
const int nq=d3b_trade;
for(int t=0;t<STEP;t+=8) {
_mm_prefetch((const char*)(q+t),_MM_HINT_T0);
if(nq>1)_mm_prefetch((const char*)(q+BASE+t),_MM_HINT_T0);
if(nq>2)_mm_prefetch((const char*)(q+(size_t)BASE*pending.ldc+t),_MM_HINT_T0);
if(nq>3)_mm_prefetch((const char*)(q+(size_t)BASE*pending.ldc+BASE+t),_MM_HINT_T0);
}
}
if(d3b_cdist){
int p2=pending.pos+d3b_cdist*STEP;
if(p2<BASE*BASE){
const double *q=pending.c+(size_t)(p2/BASE)*pending.ldc+(p2%BASE);
for(int t=0;t<STEP;t+=8) {
if(d3b_ctyp==0){
_mm_prefetch((const char*)(q+t),_MM_HINT_T0);
_mm_prefetch((const char*)(q+BASE+t),_MM_HINT_T0);
_mm_prefetch((const char*)(q+(size_t)BASE*pending.ldc+t),_MM_HINT_T0);
_mm_prefetch((const char*)(q+(size_t)BASE*pending.ldc+BASE+t),_MM_HINT_T0);
} else {
_mm_prefetch((const char*)(q+t),_MM_HINT_NTA);
_mm_prefetch((const char*)(q+BASE+t),_MM_HINT_NTA);
_mm_prefetch((const char*)(q+(size_t)BASE*pending.ldc+t),_MM_HINT_NTA);
_mm_prefetch((const char*)(q+(size_t)BASE*pending.ldc+BASE+t),_MM_HINT_NTA);
}
}
}
}
}
static inline void pending_step() {
if(pending.prog && pending.pos/BASE>=pending.rowlim)return;
int i=pending.pos/BASE,j=pending.pos%BASE;
if(d2lz_acc){
const double *A=d2lz_acc+(size_t)i*(2*BASE)+j;
for(int t=0;t<STEP;t+=4) {
double *c11=pending.c+(size_t)i*pending.ldc+j+t,
*c12=c11+BASE,*c21=c11+(size_t)BASE*pending.ldc,*c22=c21+BASE;
const double *m=pending.m+pending.pos+t;
__m256d m1=_mm256_load_pd(c11),m2=_mm256_load_pd(c21),
m3=_mm256_load_pd(c12),m4=_mm256_load_pd(c22),
m5=_mm256_load_pd(m),m6=_mm256_load_pd(m+(BASE*BASE+LEAF_PAD)),m7=_mm256_load_pd(m+2*(BASE*BASE+LEAF_PAD));
__m256d r11=_mm256_add_pd(_mm256_sub_pd(_mm256_add_pd(m1,m4),m5),m7),
r12=_mm256_add_pd(m3,m5),r21=_mm256_add_pd(m2,m4),
r22=_mm256_add_pd(_mm256_add_pd(_mm256_sub_pd(m1,m2),m3),m6);
_mm256_store_pd(c11,_mm256_add_pd(r11,_mm256_load_pd(A+t)));
_mm256_store_pd(c12,_mm256_add_pd(r12,_mm256_load_pd(A+BASE+t)));
_mm256_store_pd(c21,_mm256_add_pd(r21,_mm256_load_pd(A+2*(size_t)BASE*BASE+t)));
_mm256_store_pd(c22,_mm256_add_pd(r22,_mm256_load_pd(A+2*(size_t)BASE*BASE+BASE+t)));
}
pending.pos+=STEP;
if(pending.pos==BASE*BASE)pending.active=false;
return;
}
for(int t=0;t<STEP;t+=4) {
double *c11=pending.c+(size_t)i*pending.ldc+j+t,
*c12=c11+BASE,*c21=c11+(size_t)BASE*pending.ldc,*c22=c21+BASE;
const double *m=pending.m+pending.pos+t;
__m256d m1=_mm256_load_pd(c11),m2=_mm256_load_pd(c21),
m3=_mm256_load_pd(c12),m4=_mm256_load_pd(c22),
m5=_mm256_load_pd(m),m6=_mm256_load_pd(m+(BASE*BASE+LEAF_PAD)),m7=_mm256_load_pd(m+2*(BASE*BASE+LEAF_PAD));
__m256d r11=_mm256_add_pd(_mm256_sub_pd(_mm256_add_pd(m1,m4),m5),m7),
r12=_mm256_add_pd(m3,m5),r21=_mm256_add_pd(m2,m4),
r22=_mm256_add_pd(_mm256_add_pd(_mm256_sub_pd(m1,m2),m3),m6);
_mm256_store_pd(c11,r11);_mm256_store_pd(c12,r12);
_mm256_store_pd(c21,r21);_mm256_store_pd(c22,r22);
}
pending.pos+=STEP;
if(pending.pos==BASE*BASE)pending.active=false;
}
static void pending_finish() {
pending.prog=false;
while(pending.active)pending_step();
}
static __attribute__((always_inline)) inline void kernel2(int n,const double *a,const double *b,double *c,int ldc) {
int k=n;
double *out=c;
ptrdiff_t stride=(ptrdiff_t)ldc*8;
asm volatile (
"vxorpd %%ymm0, %%ymm0, %%ymm0\n\t"
"vxorpd %%ymm1, %%ymm1, %%ymm1\n\t"
"vxorpd %%ymm2, %%ymm2, %%ymm2\n\t"
"vxorpd %%ymm3, %%ymm3, %%ymm3\n\t"
".p2align 6\n\t" "1:\n\t"
"prefetcht0 512(%[b])\n\t"
"prefetcht0 576(%[b])\n\t"
"prefetcht0 640(%[b])\n\t"
"prefetcht0 704(%[b])\n\t"
"vmovapd 0(%[b]), %%ymm12\n\t"
"vmovapd 32(%[b]), %%ymm13\n\t"
"vbroadcastsd %c[o0]+0(%[a]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm0\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm1\n\t"
"vbroadcastsd %c[o1]+0(%[a]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm2\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm3\n\t"
"vmovapd 64(%[b]), %%ymm12\n\t"
"vmovapd 96(%[b]), %%ymm13\n\t"
"vbroadcastsd %c[o0]+8(%[a]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm0\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm1\n\t"
"vbroadcastsd %c[o1]+8(%[a]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm2\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm3\n\t"
"vmovapd 128(%[b]), %%ymm12\n\t"
"vmovapd 160(%[b]), %%ymm13\n\t"
"vbroadcastsd %c[o0]+16(%[a]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm0\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm1\n\t"
"vbroadcastsd %c[o1]+16(%[a]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm2\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm3\n\t"
"vmovapd 192(%[b]), %%ymm12\n\t"
"vmovapd 224(%[b]), %%ymm13\n\t"
"vbroadcastsd %c[o0]+24(%[a]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm0\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm1\n\t"
"vbroadcastsd %c[o1]+24(%[a]), %%ymm14\n\t"
"vfmadd231pd %%ymm12, %%ymm14, %%ymm2\n\t"
"vfmadd231pd %%ymm13, %%ymm14, %%ymm3\n\t"
"add $32, %[a]\n\t"
"add $256, %[b]\n\t"
"sub $4, %[k]\n\t"
"jnz 1b\n\t"
"vmovntpd %%ymm0, (%[out])\n\t"
"vmovntpd %%ymm1, 32(%[out])\n\t"
"add %[stride], %[out]\n\t"
"vmovntpd %%ymm2, (%[out])\n\t"
"vmovntpd %%ymm3, 32(%[out])\n\t"
: [a] "+&r"(a), [b] "+&r"(b), [out] "+&r"(out), [k] "+&r"(k)
: [stride] "r"(stride), [o0] "i"(0*(BASE+24)*8), [o1] "i"(1*(BASE+24)*8)
: "memory", "cc", "ymm0","ymm1","ymm2","ymm3","ymm12","ymm13","ymm14");
}
static __attribute__((noinline)) void kernel_tail16(int n,const double *a,const double *b,double *out,int ldc) {
const double *b1=b+8*(n+1);
ptrdiff_t stride=(ptrdiff_t)ldc*8;
int kk=n;
asm volatile (
"vxorpd %%ymm0, %%ymm0, %%ymm0\n\t"
"vxorpd %%ymm1, %%ymm1, %%ymm1\n\t"
"vxorpd %%ymm2, %%ymm2, %%ymm2\n\t"
"vxorpd %%ymm3, %%ymm3, %%ymm3\n\t"
"vxorpd %%ymm4, %%ymm4, %%ymm4\n\t"
"vxorpd %%ymm5, %%ymm5, %%ymm5\n\t"
"vxorpd %%ymm6, %%ymm6, %%ymm6\n\t"
"vxorpd %%ymm7, %%ymm7, %%ymm7\n\t"
".p2align 6\n\t"
"1:\n\t"
"prefetcht0 512(%[b])\n\t"
"prefetcht0 512(%[b1])\n\t"
"vbroadcastsd %c[o0]+0(%[a]), %%ymm12\n\t"
"vbroadcastsd %c[o1]+0(%[a]), %%ymm13\n\t"
"vmovapd 0(%[b]), %%ymm14\n\t"
"vfmadd231pd %%ymm14, %%ymm12, %%ymm0\n\t"
"vfmadd231pd %%ymm14, %%ymm13, %%ymm4\n\t"
"vmovapd 32(%[b]), %%ymm14\n\t"
"vfmadd231pd %%ymm14, %%ymm12, %%ymm1\n\t"
"vfmadd231pd %%ymm14, %%ymm13, %%ymm5\n\t"
"vmovapd 0(%[b1]), %%ymm14\n\t"
"vfmadd231pd %%ymm14, %%ymm12, %%ymm2\n\t"
"vfmadd231pd %%ymm14, %%ymm13, %%ymm6\n\t"
"vmovapd 32(%[b1]), %%ymm14\n\t"
"vfmadd231pd %%ymm14, %%ymm12, %%ymm3\n\t"
"vfmadd231pd %%ymm14, %%ymm13, %%ymm7\n\t"
"prefetcht0 576(%[b])\n\t"
"prefetcht0 576(%[b1])\n\t"
"vbroadcastsd %c[o0]+8(%[a]), %%ymm12\n\t"
"vbroadcastsd %c[o1]+8(%[a]), %%ymm13\n\t"
"vmovapd 64(%[b]), %%ymm14\n\t"
"vfmadd231pd %%ymm14, %%ymm12, %%ymm0\n\t"
"vfmadd231pd %%ymm14, %%ymm13, %%ymm4\n\t"
"vmovapd 96(%[b]), %%ymm14\n\t"
"vfmadd231pd %%ymm14, %%ymm12, %%ymm1\n\t"
"vfmadd231pd %%ymm14, %%ymm13, %%ymm5\n\t"
"vmovapd 64(%[b1]), %%ymm14\n\t"
"vfmadd231pd %%ymm14, %%ymm12, %%ymm2\n\t"
"vfmadd231pd %%ymm14, %%ymm13, %%ymm6\n\t"
"vmovapd 96(%[b1]), %%ymm14\n\t"
"vfmadd231pd %%ymm14, %%ymm12, %%ymm3\n\t"
"vfmadd231pd %%ymm14, %%ymm13, %%ymm7\n\t"
"prefetcht0 640(%[b])\n\t"
"prefetcht0 640(%[b1])\n\t"
"vbroadcastsd %c[o0]+16(%[a]), %%ymm12\n\t"
"vbroadcastsd %c[o1]+16(%[a]), %%ymm13\n\t"
"vmovapd 128(%[b]), %%ymm14\n\t"
"vfmadd231pd %%ymm14, %%ymm12, %%ymm0\n\t"
"vfmadd231pd %%ymm14, %%ymm13, %%ymm4\n\t"
"vmovapd 160(%[b]), %%ymm14\n\t"
"vfmadd231pd %%ymm14, %%ymm12, %%ymm1\n\t"
"vfmadd231pd %%ymm14, %%ymm13, %%ymm5\n\t"
"vmovapd 128(%[b1]), %%ymm14\n\t"
"vfmadd231pd %%ymm14, %%ymm12, %%ymm2\n\t"
"vfmadd231pd %%ymm14, %%ymm13, %%ymm6\n\t"
"vmovapd 160(%[b1]), %%ymm14\n\t"
"vfmadd231pd %%ymm14, %%ymm12, %%ymm3\n\t"
"vfmadd231pd %%ymm14, %%ymm13, %%ymm7\n\t"
"prefetcht0 704(%[b])\n\t"
"prefetcht0 704(%[b1])\n\t"
"vbroadcastsd %c[o0]+24(%[a]), %%ymm12\n\t"
"vbroadcastsd %c[o1]+24(%[a]), %%ymm13\n\t"
"vmovapd 192(%[b]), %%ymm14\n\t"
"vfmadd231pd %%ymm14, %%ymm12, %%ymm0\n\t"
"vfmadd231pd %%ymm14, %%ymm13, %%ymm4\n\t"
"vmovapd 224(%[b]), %%ymm14\n\t"
"vfmadd231pd %%ymm14, %%ymm12, %%ymm1\n\t"
"vfmadd231pd %%ymm14, %%ymm13, %%ymm5\n\t"
"vmovapd 192(%[b1]), %%ymm14\n\t"
"vfmadd231pd %%ymm14, %%ymm12, %%ymm2\n\t"
"vfmadd231pd %%ymm14, %%ymm13, %%ymm6\n\t"
"vmovapd 224(%[b1]), %%ymm14\n\t"
"vfmadd231pd %%ymm14, %%ymm12, %%ymm3\n\t"
"vfmadd231pd %%ymm14, %%ymm13, %%ymm7\n\t"
"add $32, %[a]\n\t"
"add $256, %[b]\n\t"
"add $256, %[b1]\n\t"
"sub $4, %[kk]\n\t"
"jnz 1b\n\t"
"vmovntpd %%ymm0, 0(%[out])\n\t"
"vmovntpd %%ymm1, 32(%[out])\n\t"
"vmovntpd %%ymm2, 64(%[out])\n\t"
"vmovntpd %%ymm3, 96(%[out])\n\t"
"add %[stride], %[out]\n\t"
"vmovntpd %%ymm4, 0(%[out])\n\t"
"vmovntpd %%ymm5, 32(%[out])\n\t"
"vmovntpd %%ymm6, 64(%[out])\n\t"
"vmovntpd %%ymm7, 96(%[out])\n\t"
: [a] "+&r"(a),[b] "+&r"(b),[b1] "+&r"(b1),[out] "+&r"(out),[kk] "+&r"(kk)
: [stride] "r"(stride),[o0] "i"(0),[o1] "i"((BASE+24)*8)
: "memory","cc","ymm0","ymm1","ymm2","ymm3","ymm4","ymm5","ymm6","ymm7","ymm8","ymm9","ymm10","ymm11","ymm12","ymm13","ymm14","ymm15");
}
static bool d2lz_go=false;
static double *d2lz_c; static int d2lz_ldc,d2lz_h;
static const double *d2lz_m1,*d2lz_m5,*d2lz_m6,*d2lz_m7; static int d2lz_m1p;
static int d2lz_pos,d2lz_i,d2lz_j;
static constexpr int D2LZ_STEP=64;
static constexpr int D2LZ_NT=1;
static constexpr int D2LZ_NTALL=0;
static inline void d2lz_arm_pass(double *c,int ldc,const double *m1,int m1p,const double *m5,
const double *m6,const double *m7,int h){
d2lz_c=c; d2lz_ldc=ldc; d2lz_m1=m1; d2lz_m1p=m1p; d2lz_m5=m5; d2lz_m6=m6; d2lz_m7=m7; d2lz_h=h;
d2lz_pos=0; d2lz_i=0; d2lz_j=0; d2lz_go=true;
}
static constexpr int D2LZ_PF=0;
static inline void d2lz_prefetch(void){
if(D2LZ_PF==0) return;
if(!d2lz_go)return;
const int i=d2lz_i,j=d2lz_j;
const double *c=d2lz_c+(size_t)i*d2lz_ldc+j;
const size_t off=(size_t)i*d2lz_h+j,off1=(size_t)i*d2lz_m1p+j;
const int lead = (D2LZ_PF>=2)? D2LZ_STEP : 0;
const _mm_hint hint = (D2LZ_PF==3)? _MM_HINT_NTA : _MM_HINT_T1;
for(int t=lead;t<D2LZ_STEP+lead;t+=8){
_mm_prefetch((const char*)(c+d2lz_h+t),hint);
_mm_prefetch((const char*)(c+(size_t)d2lz_h*d2lz_ldc+t),hint);
_mm_prefetch((const char*)(c+(size_t)d2lz_h*d2lz_ldc+d2lz_h+t),hint);
_mm_prefetch((const char*)(d2lz_m1+off1+t),hint);
_mm_prefetch((const char*)(d2lz_m5+off+t),hint);
_mm_prefetch((const char*)(d2lz_m6+off+t),hint);
_mm_prefetch((const char*)(d2lz_m7+off+t),hint);
}
}
static inline void d2lz_step(void){
if(!d2lz_go)return;
const int i=d2lz_i,j=d2lz_j;
for(int t=0;t<D2LZ_STEP;t+=4){
double *c12=d2lz_c+(size_t)i*d2lz_ldc+d2lz_h+j+t,
*c21=d2lz_c+(size_t)(d2lz_h+i)*d2lz_ldc+j+t,*c22=c21+d2lz_h;
const size_t off=(size_t)i*d2lz_h+j+t,off1=(size_t)i*d2lz_m1p+j+t;
__m256d m1=_mm256_load_pd(d2lz_m1+off1),m3=_mm256_load_pd(c12),m4=_mm256_load_pd(c22),
m5=_mm256_load_pd(d2lz_m5+off),m6=_mm256_load_pd(d2lz_m6+off),m7=_mm256_load_pd(d2lz_m7+off);
__m256d u2=_mm256_add_pd(m1,m6),u3=_mm256_add_pd(u2,m7),u4=_mm256_add_pd(u2,m5);
if(D2LZ_NTALL){ _mm256_stream_pd(c12,_mm256_add_pd(u4,m3)); _mm256_stream_pd(c22,_mm256_add_pd(u3,m5)); }
else { _mm256_store_pd(c12,_mm256_add_pd(u4,m3)); _mm256_store_pd(c22,_mm256_add_pd(u3,m5)); }
if(D2LZ_NT) _mm256_stream_pd(c21,_mm256_sub_pd(u3,m4));
else _mm256_store_pd(c21,_mm256_sub_pd(u3,m4));
}
d2lz_pos+=D2LZ_STEP;
d2lz_j+=D2LZ_STEP; if(d2lz_j>=d2lz_h){d2lz_j-=d2lz_h;d2lz_i++;}
if(d2lz_pos>=d2lz_h*d2lz_h)d2lz_go=false;
}
static void d2lz_finish(void){ while(d2lz_go)d2lz_step(); }
static const int lperm[7]={4,0,1,3,2,5,6};
static int g_fuse_sd[7], g_fuse_sgn[7];
static int g_fuse_sd_cur=0, g_fuse_sgn_cur=0;
static const int d1a2_bi[7]={0,0,1,2,3,0,2}, d1a2_bj[7]={3,-1,3,0,-1,1,3}, d1a2_bs[7]={1,0,-1,-1,0,1,1};
static void d1a2_fuse_tab(void){
for(int r=0;r<7;r++){g_fuse_sd[r]=0;g_fuse_sgn[r]=0;}
for(int r=1;r<7;r++){
int q=lperm[r], pq=lperm[r-1];
if(d1a2_bs[pq]!=0) continue;
if(d1a2_bj[q]==d1a2_bi[pq]){ g_fuse_sd[r]=1; g_fuse_sgn[r]=d1a2_bs[q]; }
else if(d1a2_bi[q]==d1a2_bi[pq]){ g_fuse_sd[r]=2; g_fuse_sgn[r]=d1a2_bs[q]; }
}
}
__attribute__((noinline)) static void pk_fuse(int n,Mat b,double *BP,int sgn,int side){
const double *sx=b.x; const size_t sl=b.ld;
for(int k=0;k<n;k+=2)for(int j=0;j<n;j+=8) {
double *p=BP+(size_t)j*(n+1)+k*8;
__m256d q0=_mm256_load_pd(p+0),q1=_mm256_load_pd(p+4);
__m256d q2=_mm256_load_pd(p+8),q3=_mm256_load_pd(p+12);
__m256d s0=_mm256_load_pd(sx+(size_t)(k+0)*sl+j), s1=_mm256_load_pd(sx+(size_t)(k+0)*sl+j+4);
__m256d s2=_mm256_load_pd(sx+(size_t)(k+1)*sl+j), s3=_mm256_load_pd(sx+(size_t)(k+1)*sl+j+4);
if(side==1){
if(sgn>0){q0=_mm256_add_pd(s0,q0);q1=_mm256_add_pd(s1,q1);q2=_mm256_add_pd(s2,q2);q3=_mm256_add_pd(s3,q3);}
else {q0=_mm256_sub_pd(s0,q0);q1=_mm256_sub_pd(s1,q1);q2=_mm256_sub_pd(s2,q2);q3=_mm256_sub_pd(s3,q3);}
} else {
if(sgn>0){q0=_mm256_add_pd(q0,s0);q1=_mm256_add_pd(q1,s1);q2=_mm256_add_pd(q2,s2);q3=_mm256_add_pd(q3,s3);}
else {q0=_mm256_sub_pd(q0,s0);q1=_mm256_sub_pd(q1,s1);q2=_mm256_sub_pd(q2,s2);q3=_mm256_sub_pd(q3,s3);}
}
_mm256_store_pd(p+0,q0);_mm256_store_pd(p+4,q1);
_mm256_store_pd(p+8,q2);_mm256_store_pd(p+12,q3);
}
}
static void d1a2_pk(int n,Mat b,double *BP){
if(g_fuse_sd_cur) pk_fuse(n,b,BP,g_fuse_sgn_cur,g_fuse_sd_cur);
else for(int k=0;k<n;k+=2)for(int j=0;j<n;j+=8) {
double *p=BP+(size_t)j*(n+1)+k*8;
_mm256_store_pd(p+0,ld(b,k+0,j));_mm256_store_pd(p+4,ld(b,k+0,j+4));
_mm256_store_pd(p+8,ld(b,k+1,j));_mm256_store_pd(p+12,ld(b,k+1,j+4));
}
}
static void leaf(int n,Mat a,Mat b,double *c,int ldc) {
d1a2_pk(n,b,bp);
pending_prefetch();
double *pkb[2]={ap,ap2};
int cur=0;
{
int mc0=n<MC?n:MC;
for(int r=0;r<mc0;r+=MR) {
int rows=mc0-r<MR?mc0-r:MR;
for(int i=0;i<rows;i++)for(int k=0;k<n;k+=4)
_mm256_store_pd(pkb[0]+(size_t)(r+i)*(BASE+24)+k,ld(a,r+i,k));
for(int i=rows;i<MR;i++)for(int k=0;k<n;k+=4)
_mm256_store_pd(pkb[0]+(size_t)(r+i)*(BASE+24)+k,_mm256_setzero_pd());
}
}
for(int ic=0;ic<n;) {
int mc=n-ic<=MC+MR?n-ic:MC;
if(mc==MC+2) {
for(int j=0;j<n;j+=16) {
for(int jj=j;jj<j+16;jj+=NR)for(int r=0;r<MC;r+=MR) {
kernel_plain(n,pkb[cur]+(size_t)r*(BASE+24),bp+(size_t)jj*(n+1),c+(size_t)(ic+r)*ldc+jj,ldc,MR);
if(pending.active && (++pending_tick%PERIOD)==0) {pending_step();if(pending.prog)pending_step();pending_prefetch();}
if(pend2.active) {pend2_step();pend2_prefetch();}
if(d2lz_go && !pending.active) {d2lz_step();d2lz_prefetch();}
}
kernel_tail16(n,pkb[cur]+(size_t)MC*(BASE+24),bp+(size_t)j*(n+1),c+(size_t)(ic+MC)*ldc+j,ldc);
}
ic+=mc;
if(pending.prog)pending.rowlim=ic;
continue;
}
const int ic2=ic+mc;
const int nxt=(ic2<n)?(n-ic2<=MC+MR?n-ic2:MC):0;
const int rows2=((nxt+MR-1)/MR)*MR;
const int nch=rows2*2;
const int qd=n/2;
int ck=0; int skip=(n/NR)*((mc+MR-1)/MR)-nch;
if(pending.active||pend2.active||d2lz_go) {
for(int j=0;j<n;j+=NR)for(int r=0;r<mc;r+=MR) {
if(mc-r==2) {
kernel2(n,pkb[cur]+(size_t)r*(BASE+24),bp+(size_t)j*(n+1),c+(size_t)(ic+r)*ldc+j,ldc);
continue;
}
const double *pks=pk_zero,*pky=pk_zero,*pkm=pk_mp;
double *pkd=pk_zero;
int pkc=0;
if(ck<nch && --skip<0) {
const int row=ck/2, off=(ck%2)*qd;
if(row<nxt) {
pks=a.x+(size_t)(ic2+row)*a.ld+(size_t)off;
pky=a.sign?(a.y+(size_t)(ic2+row)*a.ly+(size_t)off):pk_zero;
pkm=a.sign>0?pk_mp:pk_mn;
}
pkd=pkb[cur^1]+(size_t)row*(BASE+24)+(size_t)off;
pkc=8;
ck++;
}
if(!pkc) kernel_plain(n,pkb[cur]+(size_t)r*(BASE+24),bp+(size_t)j*(n+1),c+(size_t)(ic+r)*ldc+j,ldc,mc-r<MR?mc-r:MR);
else if(a.sign==0) kernel<2>(n,pkb[cur]+(size_t)r*(BASE+24),bp+(size_t)j*(n+1),c+(size_t)(ic+r)*ldc+j,ldc,mc-r<MR?mc-r:MR,pks,pky,pkd);
else if(a.sign>0) kernel<1>(n,pkb[cur]+(size_t)r*(BASE+24),bp+(size_t)j*(n+1),c+(size_t)(ic+r)*ldc+j,ldc,mc-r<MR?mc-r:MR,pks,pky,pkd);
else kernel<-1>(n,pkb[cur]+(size_t)r*(BASE+24),bp+(size_t)j*(n+1),c+(size_t)(ic+r)*ldc+j,ldc,mc-r<MR?mc-r:MR,pks,pky,pkd);
if(pending.active && (++pending_tick%PERIOD)==0) {
pending_step(); if(pending.prog)pending_step(); pending_prefetch();
}
if(pend2.active) { pend2_step(); pend2_prefetch(); }
if(d2lz_go && !pending.active) { d2lz_step(); d2lz_prefetch(); }
}
} else {
for(int j=0;j<n;j+=NR)for(int r=0;r<mc;r+=MR) {
if(mc-r==2) {
kernel2(n,pkb[cur]+(size_t)r*(BASE+24),bp+(size_t)j*(n+1),c+(size_t)(ic+r)*ldc+j,ldc);
continue;
}
const double *pks=pk_zero,*pky=pk_zero,*pkm=pk_mp;
double *pkd=pk_zero;
int pkc=0;
if(ck<nch && --skip<0) {
const int row=ck/2, off=(ck%2)*qd;
if(row<nxt) {
pks=a.x+(size_t)(ic2+row)*a.ld+(size_t)off;
pky=a.sign?(a.y+(size_t)(ic2+row)*a.ly+(size_t)off):pk_zero;
pkm=a.sign>0?pk_mp:pk_mn;
}
pkd=pkb[cur^1]+(size_t)row*(BASE+24)+(size_t)off;
pkc=8;
ck++;
}
if(!pkc) kernel_plain(n,pkb[cur]+(size_t)r*(BASE+24),bp+(size_t)j*(n+1),c+(size_t)(ic+r)*ldc+j,ldc,mc-r<MR?mc-r:MR);
else if(a.sign==0) kernel<2>(n,pkb[cur]+(size_t)r*(BASE+24),bp+(size_t)j*(n+1),c+(size_t)(ic+r)*ldc+j,ldc,mc-r<MR?mc-r:MR,pks,pky,pkd);
else if(a.sign>0) kernel<1>(n,pkb[cur]+(size_t)r*(BASE+24),bp+(size_t)j*(n+1),c+(size_t)(ic+r)*ldc+j,ldc,mc-r<MR?mc-r:MR,pks,pky,pkd);
else kernel<-1>(n,pkb[cur]+(size_t)r*(BASE+24),bp+(size_t)j*(n+1),c+(size_t)(ic+r)*ldc+j,ldc,mc-r<MR?mc-r:MR,pks,pky,pkd);
}
}
for(int cc=ck;cc<nch;cc++) {
const int row=cc/2, off=(cc%2)*qd;
if(row<nxt) {
for(int k=off;k<off+qd;k+=4)
_mm256_store_pd(pkb[cur^1]+(size_t)row*(BASE+24)+k, ld(a,ic2+row,k));
} else {
for(int k=off;k<off+qd;k+=4)
_mm256_store_pd(pkb[cur^1]+(size_t)row*(BASE+24)+k, _mm256_setzero_pd());
}
}
cur^=1;
ic+=mc;
if(pending.prog)pending.rowlim=ic;
}
if(n>=NTMIN)_mm_sfence();
}
static void sum(int h,double *dst,Mat a,Mat b,int sign) {
for(int i=0;i<h;i++)for(int j=0;j<h;j+=8) {
__m256d v=sign>0?_mm256_add_pd(ld(a,i,j),ld(b,i,j)):_mm256_sub_pd(ld(a,i,j),ld(b,i,j));
__m256d w=sign>0?_mm256_add_pd(ld(a,i,j+4),ld(b,i,j+4)):_mm256_sub_pd(ld(a,i,j+4),ld(b,i,j+4));
asm volatile("" : "+x"(v), "+x"(w) : : "memory");
if(h>=SUMNT) {
_mm256_stream_pd(dst+(size_t)i*h+j,v);_mm256_stream_pd(dst+(size_t)i*h+j+4,w);
} else {
_mm256_store_pd(dst+(size_t)i*h+j,v);_mm256_store_pd(dst+(size_t)i*h+j+4,w);
}
}
if(h>=SUMNT)_mm_sfence();
}
static void combine(int h,double *c,int ldc,const double *m,bool wino=false) {
size_t z=(size_t)h*h+(wino?UPPER_PAGE_PAD:0);
for(int i=0;i<h;i++)for(int j=0;j<h;j+=4) {
size_t t=(size_t)i*h+j;
double *c11=c+(size_t)i*ldc+j,*c12=c11+h,*c21=c+(size_t)(i+h)*ldc+j,*c22=c21+h;
__m256d m1=_mm256_load_pd(c11),m2=_mm256_load_pd(c21),m3=_mm256_load_pd(c12),m4=_mm256_load_pd(c22),
m5=_mm256_load_pd(m+t),m6=_mm256_load_pd(m+z+t),m7=_mm256_load_pd(m+2*z+t);
__m256d r11,r12,r21,r22;
if(wino) {
__m256d u2=_mm256_add_pd(m1,m6),u3=_mm256_add_pd(u2,m7),u4=_mm256_add_pd(u2,m5);
r11=_mm256_add_pd(m1,m2);r12=_mm256_add_pd(u4,m3);r21=_mm256_sub_pd(u3,m4);r22=_mm256_add_pd(u3,m5);
} else {
r11=_mm256_add_pd(_mm256_sub_pd(_mm256_add_pd(m1,m4),m5),m7);r12=_mm256_add_pd(m3,m5);r21=_mm256_add_pd(m2,m4);
r22=_mm256_add_pd(_mm256_add_pd(_mm256_sub_pd(m1,m2),m3),m6);
}
_mm256_store_pd(c11,r11);_mm256_store_pd(c12,r12);_mm256_store_pd(c21,r21);_mm256_store_pd(c22,r22);
}
}
static void pre(int h,Mat a,double *s1,double *s2,double *s4,double *s3,int ld3,int ld12,int ld4,bool right) {
for(int i=0;i<h;i++)for(int j=0;j<h;j+=8) {
__m256d a0=ld(a,i,j),a1=ld(a,i,j+4),b0=ld(a,i,j+h),b1=ld(a,i,j+h+4),
c0=ld(a,i+h,j),c1=ld(a,i+h,j+4),d0=ld(a,i+h,j+h),d1=ld(a,i+h,j+h+4);
__m256d p0,p1,q0,q1,r0,r1,t0,t1;
if(!right) {
p0=_mm256_add_pd(c0,d0);p1=_mm256_add_pd(c1,d1);
q0=_mm256_sub_pd(p0,a0);q1=_mm256_sub_pd(p1,a1);
r0=_mm256_sub_pd(b0,q0);r1=_mm256_sub_pd(b1,q1);
t0=_mm256_sub_pd(a0,c0);t1=_mm256_sub_pd(a1,c1);
}else {
p0=_mm256_sub_pd(b0,a0);p1=_mm256_sub_pd(b1,a1);
q0=_mm256_sub_pd(d0,p0);q1=_mm256_sub_pd(d1,p1);
r0=_mm256_sub_pd(q0,c0);r1=_mm256_sub_pd(q1,c1);
t0=_mm256_sub_pd(d0,b0);t1=_mm256_sub_pd(d1,b1);
}
size_t off=(size_t)i*ld12+j,off4=(size_t)i*ld4+j,off3=(size_t)i*ld3+j;
_mm256_stream_pd(s1+off,p0);_mm256_stream_pd(s1+off+4,p1);
_mm256_stream_pd(s2+off,q0);_mm256_stream_pd(s2+off+4,q1);
_mm256_stream_pd(s4+off4,r0);_mm256_stream_pd(s4+off4+4,r1);
_mm256_stream_pd(s3+off3,t0);_mm256_stream_pd(s3+off3+4,t1);
}
_mm_sfence();
}
static void rec(int n,Mat a,Mat b,double *c,int ldc,double *work) {
if(n<=BASE){leaf(n,a,b,c,ldc);return;}
int h=n/2;size_t z=(size_t)h*h;
Mat aa[4]={{a.x,a.ld},{a.x+h,a.ld},{a.x+(size_t)h*a.ld,a.ld},{a.x+(size_t)h*a.ld+h,a.ld}};
Mat bb[4]={{b.x,b.ld},{b.x+h,b.ld},{b.x+(size_t)h*b.ld,b.ld},{b.x+(size_t)h*b.ld+h,b.ld}};
double *m=n==2*BASE?work+LEAF_PAD:work;
if(n==2*BASE && pending.active && pending.m==m)m=pending_work+LEAF_PAD;
size_t pz=z+(n==2*BASE?LEAF_PAD:UPPER_PAGE_PAD);
double *p=work+3*z,*q=p+z,*sub=q+z;
double *out[7]={c,c+(size_t)h*ldc,c+h,c+(size_t)h*ldc+h,m,m+pz,m+2*pz};
if(n>BASE*2) {
pending_finish();
double *pa0=m+3*pz,*pa1=pa0+pz,*pb0=pa1+pz,*pb1=pb0+pz,*pb2=pb1+pz;
double *pa2=c+(size_t)h*ldc+h;
sub=pb2+pz;
pre(h,a,pa0,pa1,pa2,c,ldc,h,ldc,false);
pre(h,b,pb0,pb1,pb2,c+(size_t)h*ldc,ldc,h,h,true);
rec(h,{pa2,ldc},bb[3],out[2],ldc,sub);
rec(h,aa[3],{pb2,h},out[3],ldc,sub);
pend2_finish();
rec(h,{pa0,h},{pb0,h},pb2,h,sub);
rec(h,{pa1,h},{pb1,h},pa0,h,sub);
rec(h,{c,ldc},{c+(size_t)h*ldc,ldc},pa1,h,sub);
rec(h,aa[0],bb[0],pb0,h,sub);
d2lz_arm_pass(c,d3b_dlz?8:ldc,pb0,h,pb2,pa0,pa1,h);
d2lz_root_last=1;
rec(h,aa[1],bb[2],c,ldc,sub);
d2lz_root_last=0;
d2lz_finish();
pending_finish();
pend2_finish();
d2lz_acc=0;
return;
}
const int ai[7]={0,2,0,3,0,2,1},aj[7]={3,3,-1,-1,1,0,3},as[7]={1,1,0,0,1,-1,-1};
const int bi[7]={0,0,1,2,3,0,2},bj[7]={3,-1,3,0,-1,1,3},bs[7]={1,0,-1,-1,0,1,1};
for(int r=0;r<7;r++) {
Mat x=aa[ai[r]],y=bb[bi[r]];
if(h<=BASE) {
const int q=lperm[r];
g_fuse_sd_cur=g_fuse_sd[r];g_fuse_sgn_cur=g_fuse_sgn[r];
Mat x=aa[ai[q]],y=bb[bi[q]];
if(as[q]){x.y=aa[aj[q]].x;x.ly=a.ld;x.sign=as[q];}
if(bs[q]){y.y=bb[bj[q]].x;y.ly=b.ld;y.sign=bs[q];}
if(r==6) {
pending_finish();
pending={d3b_cflag?d3b_sc:c,d3b_cflag?16:ldc,m,0,true,0,true};
if(d2lz_root_last) d2lz_acc=d2lz_m1;
leaf(h,x,y,out[q],q<4?ldc:h);
pending.prog=false;
} else leaf(h,x,y,out[q],q<4?ldc:h);
} else {
if(as[r]){sum(h,p,x,aa[aj[r]],as[r]);x={p,h};}
if(bs[r]){sum(h,q,y,bb[bj[r]],bs[r]);y={q,h};}
rec(h,x,y,out[r],r<4?ldc:h,sub);
}
}
if(h==BASE) {
} else {
pending_finish();
combine(h,c,ldc,m);
}
}
static void d2z6_thp(void *p,size_t bytes){
if(!p||!bytes) return;
unsigned long long pg=4096, a=(unsigned long long)p & ~(pg-1);
unsigned long long e=(unsigned long long)p+bytes;
if(madvise((void*)a,(size_t)(((e+pg-1)&~(pg-1))-a),MADV_HUGEPAGE))
madvise((void*)a,(size_t)((e&~(pg-1))-a),MADV_HUGEPAGE);
}
static bool d2z6_thp_done=false;
static void d2z6_thp_all(const double*A,const double*B,double*C,int n){
if(d2z6_thp_done) return; d2z6_thp_done=true;
size_t nn=(size_t)n*(size_t)n*8;
d2z6_thp((void*)A,nn); d2z6_thp((void*)B,nn); d2z6_thp((void*)C,nn);
d2z6_thp((void*)workspace,sizeof(workspace));
d2z6_thp((void*)pending_work,sizeof(pending_work));
}
static_assert(sizeof(char*)==8,"z6anc2");
void matrix_multiply(int n,const double *a,const double *b,double *c) {
d2z6_thp_all(a,b,c,n);d1a2_fuse_tab();
rec(n,{a,n},{b,n},c,n,workspace);
pending_finish();
pend2_finish();
_mm_sfence();
}
| Compilation | N/A | N/A | Compile OK | Score: N/A | 显示更多 |
| Testcase #1 | 266.255 ms | 86 MB + 336 KB | Accepted | Score: 100 | 显示更多 |