Skip to content

vCPU x87 Comparison Flag Capture

github-actions[bot] edited this page Sep 14, 2026 · 3 revisions

x87 Comparison Flag Capture

Lifecycle: Performance - Unproven · Type: Instruction-selection optimization
State: Source-backed; runtime value is not established.

Status: Source-validated code-generation candidate; not implemented or benchmarked.

Mechanism class: Host instruction-selection optimization — not a shortcut.

Reviewed source: 322986f4c5502b3fa887a9605ac8cd88e9b2c579

Primary files: tcg/i386/tcg-target.c.inc, target/i386/ops_fpu.h.

Why this is not a shortcut

The proposal changes how the same host flags are captured after a native floating-point comparison. It does not bypass a general emulation route based on an assumption, retained state, or compatibility policy.

It is a focused backend micro-optimization and belongs in the broader Performance Optimization Catalog.

Current source behavior

The x86 TCG backend emits the hard-FPU comparison operation approximately as:

comiss/comisd sourceA, sourceB
pushf
pop    result_register

The x87 comparison consumer then retains only three flags:

res &= 0x45;  /* CF, PF, ZF */
res <<= 8;    /* map into guest C0/C2/C3 status positions */

Most of the captured host flags are discarded.

flowchart LR
    A[COMISS/COMISD] --> B[PUSHF to stack]
    B --> C[POP full flags into GPR]
    C --> D[Mask 0x45]
    D --> E[Shift into guest x87 status]
Loading

Candidate sequences

LAHF candidate

comisd xmmA, xmmB
lahf
movzx  result, ah
and    result, 0x45

LAHF captures the low status flags containing CF, PF, and ZF, but forces use of AH/RAX and may create extra moves, partial-register dependencies, or allocator constraints.

SETcc candidate

SETB  -> CF
SETP  -> PF
SETE  -> ZF
combine into 0x45 layout

This avoids stack traffic and AH but may require more instructions and temporaries.

Existing PUSHF/POP

The current route remains the reference. Modern cores may handle the pair efficiently enough that a replacement does not win after register-allocation effects.

Why it may help

Potentially removed work:

  • store/load through the architectural stack pointer;
  • full-flags capture when only three bits are needed;
  • stack-engine or dependency cost around PUSHF/POP;
  • code-size or scheduling constraints of the current pair.

Potentially added work:

  • forced RAX/AH allocation;
  • moves to/from the desired result register;
  • partial-register merging concerns;
  • several SETcc instructions and bit assembly;
  • additional spills under register pressure.

This is why source instruction count alone cannot select the winner.

Code and ownership map

Area Role
tcg/i386/tcg-target.c.inc::OP_f32_f64(com) Emits comparison and flags capture
target/i386/ops_fpu.h::gen_fcom_*() Masks 0x45 and maps flags to guest x87 status
TCG register allocator Determines RAX/result-register moves and spills
host capability setup Determines whether LAHF is admitted in the active mode

Correctness contract

For ordered greater-than, less-than, equal, and unordered comparisons, the candidate must produce the same three-bit mapping as the reference:

Relation ZF PF CF Guest result
greater 0 0 0 C3/C2/C0 = 000
less 0 0 1 001
equal 1 0 0 100
unordered 1 1 1 111

Also test:

  • positive/negative zero;
  • infinities;
  • quiet and signaling NaNs where supported by the current hard-FPU contract;
  • single and double precision;
  • destination register aliases and high register pressure;
  • surrounding code that uses RAX/AH;
  • exception/status behavior retained by the current comparison route.

Evidence required

Counter/measurement Purpose
dynamic hard-FPU comparison count Reachability
hot guest PCs/blocks Concentration
current vs candidate code bytes Code-size effect
spills/reloads and forced moves Allocator cost
stack-memory operations Work removed
host sample weight Runtime cost
exact guest status mismatches Correctness

Create a small generated-code benchmark with the same allocator constraints as TCG. A standalone hand-written instruction loop may hide the RAX pressure that determines the actual result.

Expected useful signature

comparisons execute frequently
candidate captures 0x45 exactly
stack flag round-trip disappears
additional RAX/temporary spills remain lower than removed cost
fixed guest work improves repeatably

Failure modes

  • Assuming fewer source instructions means faster generated code.
  • Ignoring LAHF availability/capability handling in 64-bit mode.
  • Forcing RAX and increasing spills in hot blocks.
  • Creating partial-register stalls or extra zero-extension work.
  • Mishandling unordered NaN comparisons.
  • Measuring only a synthetic loop without TCG register pressure.
  • Giving this micro-optimization priority over helper/conversion paths without dynamic evidence.

Qualification plan

  1. Count dynamic hard-FPU comparisons and identify hot blocks.
  2. Generate current, LAHF, and SETcc variants under realistic register pressure.
  3. Compare exact guest status bits across ordered/unordered inputs.
  4. Inspect code size, moves, spills, and host samples.
  5. Run Release ABBA/BAAB on a workload with verified reachability.
  6. Retain the current PUSHF/POP route if the result is neutral or host-dependent.

Related pages

Full technical reference

Primary reference: This subject page is the design and research reference for x87 Comparison Flag Capture. Pull requests are implementation/test history only.
Lifecycle: Performance - Unproven · Mechanism: Host instruction-selection experiment
Reviewed source: 322986f4c5502b3fa887a9605ac8cd88e9b2c579 · Acceptance class: intended exact or behavior-preserving for its admitted scope

1. Scope

Replace the current COMISD/COMISS plus PUSHF/POP full-flag capture with a smaller sequence that extracts only CF, PF and ZF if it is measurably better on the target host.

This entry remains Unproven: the source path and opportunity are concrete, but no accepted xemu runtime result has established that the candidate improves representative workloads. The page defines what must be bypassed, what remains mandatory, and how the hypothesis can be rejected.

2. Source seams

File / function Role
tcg/i386/tcg-target.c.inc floating comparison emission and flag capture
target/i386/ops_fpu.h consumer mask 0x45 and guest x87 status mapping

3. Current execution path

flowchart TD
    N0["Host floating compare"]
    N1["pushfq"]
    N0 --> N1
    N2["pop general register"]
    N1 --> N2
    N3["Mask CF/PF/ZF"]
    N2 --> N3
    N4["Map to guest x87 status"]
    N3 --> N4
Loading

4. Candidate execution path

flowchart TD
    N0["Host floating compare"]
    N1["lahf or setcc sequence"]
    N0 --> N1
    N2["Extract only CF/PF/ZF"]
    N1 --> N2
    N3["Map to guest status"]
    N2 --> N3
    N4["Reference sequence when not profitable"]
    N3 --> N4
Loading

5. Why it may help

The consumer only needs three condition bits, so round-tripping the complete flags register through the stack may be unnecessary. However, LAHF constrains RAX/AH and SETcc uses several instructions, so the alternative can lose through moves, spills or dependencies. This is a focused assembly benchmark, not a redesign.

6. Work removed

  • Stack push/pop of full flags if an alternative is cheaper

7. Work that remains mandatory

  • Exact ordered/equal/unordered flag semantics
  • Guest status mapping
  • Register allocation constraints
  • Reference emission

8. Implementation sketch

; Current shape
comisd xmm0, xmm1
pushfq
pop    r10
and    r10d, 0x45

; Candidate A
comisd xmm0, xmm1
lahf
movzx  r10d, ah
and    r10d, 0x45

; Candidate B uses SETB/SETP/SETE and combines bits.

The sketch defines the intended boundary; it is not a complete patch and does not replace source review, ownership design, or focused tests.

9. Correctness contract

  • CF/PF/ZF match for ordered less/greater/equal and unordered NaN cases.
  • No unwanted dependency on RAX/AH corrupts surrounding allocation.
  • Stack pointer/unwind behavior remains valid in current route.
  • Choose by measured generated code, not instruction count alone.

10. State, ownership, invalidation, and fallback

No persistent state. The backend selector may use host-feature/microarchitecture policy if evidence supports it. Register allocator constraints are part of the candidate cost.

The maintained reference path remains the fallback whenever admission, capability, lifetime, or validation is uncertain. A fast result with an unproven dependency is not acceptable as an exact optimization.

11. Advantages

  • Small isolated change
  • Exact differential oracle
  • May remove memory/stack traffic
  • Easy microarchitecture comparison

12. Costs and failure modes

  • LAHF partial-register/RAX pressure
  • SETcc sequence may be longer
  • Modern CPUs may optimize PUSHF/POP adequately
  • Likely small whole-workload effect

13. Evidence counters

Counters must be cheap, subsystem-owned, and snapshotted outside the hot loop. Record at least:

  • comparison_dynamic_count
  • current_vs_candidate_uops/latency
  • extra_moves/spills
  • host_code_bytes
  • x87_compare_samples
  • whole-vCPU change

A local reduction is not enough. Evidence must connect route reachability and removed work to fixed guest progress, CPU/GPU time where applicable, and p95/p99 behavior.

14. Qualification matrix

  • Ordered less/greater/equal
  • Quiet/signaling NaNs as supported
  • Signed zeros
  • Register-pressure fixtures
  • Disassembly/uop benchmark
  • Weighted guest block frequency
  • Release A/B if dynamic count is meaningful

Correctness runs may use validation layers, detailed comparisons, and fault injection. Performance acceptance must use optimized Release builds with matching symbols and minimal instrumentation.

15. Acceptance rule

Promote only if exact status bits match and weighted generated-code/runtime evidence beats the existing sequence on supported hosts.

16. Rejection rule

Reject if register pressure or uops are worse, dynamic frequency is low, or gains vanish outside a microbenchmark.

17. Related architecture and history

CPU-and-vCPU-Execution · Performance-Unproven · Debugging-Tools-and-Commands · vCPU-Shortcut-Candidates

PR pages may be linked as supporting evidence, but they are not substitutes for this reference.

Clone this wiki locally