Skip to content

LATX, opt: Avoid redundant JECXZ zero-extension - #522

Merged
LaurenIsACoder merged 1 commit into
lat-opensource:masterfrom
xiangzhai:opt
Oct 27, 2026
Merged

LaurenIsACoder merged 1 commit into
lat-opensource:masterfrom
xiangzhai:opt

Conversation

@xiangzhai

Copy link
Copy Markdown
Contributor

Summary / 变更说明

JECXZ 只检查 RCX 的低 32 位。原实现总是通过
load_ireg_from_ir1(&ecx_ir1_opnd, ZERO_EXTENSION, false) 生成
bstrpick.d 加临时寄存器,再与 0 比较。

本变更利用一个局部不变量:若 JECXZ 在同一个 TB 内、且紧邻的前一条指令以
32 位宽度完整写 ECX,则宿主寄存器高 32 位已经被清零,可以直接用 RCX 与 0
比较,省去 mask 指令和临时寄存器。

仅在可证明安全时启用快速路径:

  • 两种 guest 模式:MOV、MOVZX、MOVSX、LEA、ADC、SBB;
  • 仅 64 位 guest 模式:ADD、SUB、AND、OR、XOR、INC、DEC、
    NEG、NOT。

以下情况保持原 masked load:JECXZ 是 TB 首条指令、前一条是 64 位写、前一条
不是上述白名单指令、或前一条属于指令模式融合。

命中时每条 JECXZ 少一条宿主指令(bstrpick.d)和一个临时寄存器。

Validation / 验证

Builds / 构建

  • x86_64 guest 构建:latx-x86_64,-Werror 通过;候选二进制重建后哈希一致。
  • i386 guest 构建:latx-i386,-Werror 通过;候选二进制重建后哈希一致。
  • 基线与候选二进制隔离保存,避免混用。

Regression tests / 回归测试

meson test -C <build64> --suite lat-pr-fast --print-errorlogs
  Ok: 49  Fail: 0

meson test -C <build32> --no-rebuild test-latx-jecxz-opt
  Ok: 1   Fail: 0

新增 tests/unit/test-latx-jecxz-opt.py,覆盖快速/回退判定:ECX 目标、
32/64 位写、非白名单指令、模式融合标记、TB 首条指令等。

Semantics / 语义验证

  • x86-64 手工边界用例:覆盖 RCX 高 32 位非零但 ECX == 0、
    RCX = 0xffffffff00000000、ECX != 0、0x80000000、add/inc
    回绕等 9 个场景;基线与候选在 default、LATX_AOT=0 LATX_KZT=0、
    -d nochain 下均通过。
  • 2000 例 x86-64 随机差分测试:覆盖上述快速路径 writer、64 位写、
    CMP/TEST/SHL $0 等回退路径;基线、候选输出均与按 x86 语义
    独立计算的期望值 2000/2000 匹配,并在 default、LATX_AOT=0、
    -d nochain 三种模式下一致。
  • TB 边界用例:JECXZ 作为 TB 首条指令,且 RCX 高 32 位非零;基线与
    候选均通过。
  • i386 guest 16 例:覆盖快速路径与回退路径;基线与候选在 default 和
    LATX_AOT=0 下均通过。

Performance / 性能

JECXZ 密集微基准(8 亿次 JECXZ):

  • 机制:instructions:u 恰好减少 800,000,000 条(每条优化 JECXZ 少
    1 条),分支数不变。
  • 端到端:wall time 无统计显著变化(not-taken 中位数 0.4036 s → 0.4001 s,
    95% CI 跨 0;taken 变体在噪声范围内略慢)。

因此本 PR 只声明指令数/代码量减少,不声明产品级端到端加速。

Checklist / 检查项

  • I have read CONTRIBUTING.md. / 我已阅读 CONTRIBUTING.md。
  • Every commit contains a DCO sign-off (git commit -s). /
    每个提交都包含 DCO 签署(git commit -s)。
  • I have included relevant build or test results, or explained why they
    are not applicable. /
    我已提供相关构建或测试结果,或说明了不适用的原因。

@LaurenIsACoder LaurenIsACoder left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

translate_lea() 会调用 convert_mem_to_specific_gpr(),但 convert_mem_helper() 的 RIP-relative 分支在加载完整有效地址后就直接返回了,没有走到后面的 adjust_dest(),没有按 ECX 的 32 位宽度截断。

比如把下面两条指令放在 guest 地址 0x100001000:

lea ecx, [rip - 0x1006]   # 算出的有效地址是 0x100000000
jecxz taken

按理写入 ECX 时只保留低 32 位,ECX 为零,JECXZ 应跳转。但 LEA 翻译会让宿主寄存器保留完整的 0x100000000。原来的 JECXZ 先做 mask,得到零,分支结果正确;这个 PR 把 LEA 判为安全,省掉 mask 后直接比较整个寄存器,结果非零,就不会跳转。

JECXZ tests only the low 32 bits of RCX, so the generic path masks off the
upper half before the 64-bit compare.  When the immediately preceding
straight-line instruction fully writes ECX as 32 bits, the host register is
already zero-extended; test it directly and drop the mask and its temporary.

Restrict the fast path to writers that provably clear the upper half:
MOV/MOVZX/MOVSX/ADC/SBB in both modes, LEA except RIP-relative addressing,
and ADD/SUB/AND/OR/XOR/INC/DEC/NEG/NOT in 64-bit mode where the translator
emits the zero-extension and the following JECXZ keeps ECX live for HBR.
LEA reaches convert_mem_helper(), whose RIP-relative path returns the full
effective address without adjust_dest(), so a 32-bit LEA is not
zero-extended there.  All other cases keep the existing masked load.

Validated with lat-pr-fast (49/49), a focused decision unit test including
the RIP-relative LEA case, a runtime x86-64 case where
`lea ecx, [rip - 0x1006]` leaves ECX zero before JECXZ (wrong without this
fix, correct with it), 2000 randomized x86-64 differential cases covering the
fast and fallback paths, TB-boundary cases, and 32-bit guest cases on
latx-i386.  A JECXZ-dense microbenchmark removes exactly one host instruction
per optimized JECXZ; its wall-time result was neutral, so no product-level
gain is claimed.

Signed-off-by: Leslie Zhai <xiangzhai83@gmail.com>
@xiangzhai

Copy link
Copy Markdown
Contributor Author

感谢 review:

  • 修复:dt_X86_INS_LEA 仅在非 RIP-relative 时走 JECXZ 快路径;64 位 RIP-relative LEA 继续走带 mask 的回退路径。
  • 测试:tests/unit/test-latx-jecxz-opt.py 增加非 RIP / RIP-relative LEA 两个断言;修复前 RED,修复后 GREEN。
  • 运行时复现:lea ecx,[rip-0x1006]; jecxz 在旧提交构建上 exit 1,修复后 exit 0,pre-commit 构建 exit 0。
  • 回归:lat-pr-fast 49/49 通过;64 位与 32 位 tr-jcc.c 均编译通过。

请再次 review。

Thanks,
Leslie Zhai

@LaurenIsACoder
LaurenIsACoder merged commit 8479a8b into lat-opensource:master Oct 27, 2026
26 checks passed
@xiangzhai

Copy link
Copy Markdown
Contributor Author

Thanks!

@xiangzhai
xiangzhai deleted the opt branch October 27, 2026 12:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants