Repository navigation
Hot Path vCPU FP Control State Retention
Lifecycle: Performance - Unproven · Type: State-setup shortcut
State: Source-backed; runtime value is not established.
Status: Source-validated exact-shortcut candidate; not implemented or benchmarked.
Mechanism class: Guarded trust of already-prepared host floating-point control state.
Reviewed source:
322986f4c5502b3fa887a9605ac8cd88e9b2c579Primary files:
target/i386/tcg/translate.c,tcg/i386/tcg-target.c.inc,target/i386/ops_fpu.h.
The hard-x87 translator tracks whether it has already prepared the host floating-point control environment through DisasContext::flcr_set.
gen_flcr() is explicitly marked:
/* TODO: Oversynchronized */When control state is not considered valid, it:
- loads the guest x87 control word;
- extracts guest rounding bits;
- constructs an MXCSR value;
- stores that value to scratch memory;
- emits
LDMXCSR.
gen_flush_fp() always clears flcr_set, coupling two different questions:
Must cached guest x87 values be materialized?
Must the translator forget that host FP control remains suitable?
The proposed shortcut keeps those decisions separate and bypasses redundant control-state reloads at audited boundaries.
gen_flush_fp() currently performs:
flush cached x87 values
reset fpstt_delta
set flcr_set = false
The backend emits INDEX_op_flcr as:
store generated MXCSR value to scratch
ldmxcsr [scratch]Therefore a helper or boundary that triggers gen_flush_fp() may cause a later x87 operation to rebuild/reload control state even if nothing actually changed it.
flowchart TD
A[Hard-x87 operation] --> B[gen_flcr]
B --> C{flcr_set?}
C -->|No| D[Load guest fpuc and build MXCSR]
D --> E[Scratch store + LDMXCSR]
E --> F[flcr_set = true]
C -->|Yes| G[Reuse current host control]
F --> H[Execute native FP operation]
G --> H
H --> I[Helper or generic flush boundary]
I --> J[gen_flush_fp clears flcr_set]
J --> A
Introduce an explicit control-state validity contract independent of cached-value materialization:
flowchart TD
A[Boundary or helper requested] --> B{Must x87 values be materialized?}
B -->|Yes| C[Flush values]
B -->|No| D[Retain values]
C --> E{Can boundary alter required host FP control?}
D --> E
E -->|Yes or unknown| F[Invalidate control-state knowledge]
E -->|No, audited| G[Retain active FP-control generation]
F --> H[Next FP operation reloads control]
G --> I[Next FP operation bypasses LDMXCSR]
An implementation can track a small generation or enum rather than only a boolean:
/* Illustrative translator state. */
struct FPControlKnowledge {
bool valid;
uint32_t guest_control_generation;
uint32_t active_policy;
};A hit is valid only when the active host control policy still corresponds to the current guest control generation and no intervening operation may have changed it.
The local cost includes:
- loading guest
fpucfrom CPU state; - bit extraction and shifts;
- constructing the MXCSR value;
- a store to scratch memory;
-
LDMXCSRserialization/control-state cost; - possible surrounding register pressure.
The useful opportunity is:
executed FP-control loads
that follow boundaries which did not change control state
Count executed LDMXCSR operations in hot translated blocks. Counting gen_flcr() calls during translation alone does not establish runtime cost.
The candidate is equivalent only if it preserves all required boundaries:
- guest x87 control-word writes;
- guest MXCSR writes where relevant to the hard-FPU route;
- helper calls that may execute floating-point code or change host control;
- exceptions and exits into C code;
- transitions between translated code and the main loop;
- signal/exception handling;
- snapshot save/restore and CPU reset;
- changes between hard- and soft-FPU policies;
- mixed x87 and SSE execution;
- host code requiring its own floating-point environment.
A pure integer helper is a plausible retained-control boundary, but only after its implementation and ABI behavior are audited. Unknown helpers invalidate.
| Question | x87 cache retention | FP control retention |
|---|---|---|
| Values | Can live x87 values remain in TCG temporaries? | N/A |
| Canonical guest state | May skip st80f/ld80f around helper |
May still materialize values if required |
| Host control | May or may not remain valid | Central concern |
| Main avoided work | Value conversion/storage/reload | Guest control decode + scratch store + LDMXCSR
|
Test four configurations where possible:
reference values + reference control
retained values + reference control
reference values + retained control
retained values + retained control
This prevents double-counting savings.
| File/area | Role |
|---|---|
target/i386/tcg/translate.c::gen_flcr() |
Builds/loads host control state and sets flcr_set
|
target/i386/tcg/translate.c::gen_flush_fp() |
Currently invalidates control knowledge unconditionally |
target/i386/ops_fpu.h::get_stn()/get_ft0() |
Requests control setup before using cached hard-FPU values |
tcg/i386/tcg-target.c.inc::INDEX_op_flcr |
Scratch store and LDMXCSR emission |
guest fpuc / MXCSR state |
Architectural source of numerical policy |
| C-to-JIT boundary | Host-environment ownership and restoration |
| Counter | Unit | Meaning |
|---|---|---|
fp_control_requests |
requests | FP operations asking for prepared control |
fp_control_loads_emitted |
operations | Generated LDMXCSR paths |
fp_control_loads_executed |
operations | Dynamic cost |
fp_control_reuse_hits |
requests | Candidate bypass used |
fp_control_invalidations |
events | Control knowledge discarded |
fp_control_invalidation_reason_* |
events | Guest write, helper, exit, restore, policy, unknown |
redundant_loads_avoided |
operations | Local shortcut benefit |
fp_result_or_status_mismatches |
cases | Differential failures |
- Change guest x87 rounding mode between operations.
- Write guest control state through every supported instruction/path.
- Insert an audited integer helper; control knowledge should remain valid.
- Insert a helper that uses or changes floating-point state; it must invalidate.
- Raise a guest exception and exit translated code.
- Switch between x87 and SSE operations with differing requirements.
- Save and restore a snapshot while control knowledge is valid.
- Re-enter translated code after surrounding host C code intentionally changes MXCSR.
- Deliberately omit one invalidation in a test build; the oracle must fail.
The harness must verify both sides of the boundary:
Before entering JIT:
record host MXCSR/control
Inside translated execution:
apply required guest policy
run candidate sequence
After leaving JIT:
host environment matches its required restored value
guest results/status match reference
Improving guest execution while contaminating surrounding host code is not acceptable.
hot hard-x87 blocks execute
control reuse hits are nonzero
executed LDMXCSR operations fall
st80f/ld80f may remain unchanged in the isolated control experiment
x87 results, status, exceptions and host environment remain equal
vCPU time per fixed guest work improves or remains neutral
- Assuming value flush and control invalidation are the same event.
- Retaining control knowledge across arbitrary helpers.
- Ignoring host C code's required environment.
- Failing to invalidate after guest control writes or restore/reset.
- Counting emitted operations without dynamic execution weighting.
- Combining with helper-aware cache retention before isolated measurement.
- Introducing a fixed rounding policy without labeling it an approximation.
- Measuring only average FPS instead of vCPU time and frame tails.
- Instrument executed control loads and invalidation reasons.
- Identify hot blocks with repeated
LDMXCSRafter unchanged control state. - Introduce explicit control-validity state separate from value cache state.
- Admit only one audited pure-helper boundary initially.
- Build exact rounding/status/exception and host-environment differential tests.
- Inspect optimized Release disassembly and dynamic block execution counts.
- Test the candidate alone, then alongside x87 cache retention.
- Run CPU-heavy, PGR2, Morrowind, and applicable XISO coverage.
- Preserve conservative invalidation for every unknown boundary.
- vCPU Shortcut Candidates
- Helper-Aware x87 Cache Retention
- Native SSE Arithmetic
- CPU & vCPU Execution
- Debugging Lag & Hot-Path Analysis
Primary reference: This subject page is the design and research reference for FP Control-State Retention. Pull requests are implementation/test history only.
Lifecycle: Performance - Unproven · Mechanism: Guarded host floating-point environment shortcut
Reviewed source:322986f4c5502b3fa887a9605ac8cd88e9b2c579· Acceptance class: intended exact or behavior-preserving for its admitted scope
Keep known-valid host FP control state across audited boundaries instead of broadly clearing the translator's knowledge and re-emitting MXCSR setup.
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.
| File / function | Role |
|---|---|
target/i386/tcg/translate.c |
gen_flcr(), gen_flush_fp() and flcr_set tracking |
tcg/i386/tcg-target.c.inc |
LDMXCSR emission and host backend state |
flowchart TD
N0["FP operation needs control"]
N1["If flcr_set false, load guest control word"]
N0 --> N1
N2["Construct MXCSR"]
N1 --> N2
N3["Store scratch"]
N2 --> N3
N4["LDMXCSR"]
N3 --> N4
N5["Broad helper/flush clears flcr_set"]
N4 --> N5
N6["Repeat later"]
N5 --> N6
flowchart TD
N0["Classify boundary FP-control effects"]
N1["Retain control generation across audited preserving boundary"]
N0 --> N1
N2["Reload only on guest control change or clobbering boundary"]
N1 --> N2
N3["Restore host C environment on exit"]
N2 --> N3
The code itself labels control setup as oversynchronized. Materializing cached x87 values and invalidating host control knowledge are separate concerns. This candidate targets repeated setup, but only after identifying helpers/boundaries that cannot alter the environment.
- Redundant guest-control extraction
- Scratch store and LDMXCSR
- Repeated setup after unrelated integer helpers
- Reload after guest control change
- Reload after unknown/clobbering helper
- Guest exception/status behavior
- Host environment restoration
- Reference mode
if (boundary_preserves_host_fp_control(info)) {
/* retain flcr_generation */
} else {
s->flcr_valid = false;
}
if (!s->flcr_valid || s->flcr_generation != env->fpuc_generation)
gen_flcr(s);The sketch defines the intended boundary; it is not a complete patch and does not replace source review, ownership design, or focused tests.
- Audited preserving boundaries cannot change MXCSR/x87 control.
- Guest control-word changes invalidate immediately.
- Surrounding C code observes the expected host environment after JIT exit.
- Exception and rounding semantics match the stated exact/approximate policy.
Translator tracks a control generation/valid bit separately from cached values. JIT entry/exit owns saving/restoring the host environment. Unknown helpers, signals/exceptions, mode changes, and unsupported operations invalidate conservatively.
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.
- Removes expensive control-register loads
- Independent from value-cache retention
- Clear generated-code counters
- Can benefit mixed integer/FP blocks
- Host FP environment is process/thread-sensitive
- One misclassified helper can corrupt numerical behavior
- Savings may overlap with other patches
- Platform/backend-specific implementation
Counters must be cheap, subsystem-owned, and snapshotted outside the hot loop. Record at least:
- executed_LDMXCSR
- gen_flcr_emissions_weighted
- preserving_boundaries
- invalidations_by_reason
- FP_blocks_executed
- host_env_restore_checks
- vCPU samples
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.
- All guest rounding modes
- x87/SSE transitions
- Preserving and clobbering helpers
- Exceptions/signals
- JIT exit/reentry
- Host sentinel MXCSR around execution
- Independent A/B with value-cache retention disabled
Correctness runs may use validation layers, detailed comparisons, and fault injection. Performance acceptance must use optimized Release builds with matching symbols and minimal instrumentation.
Promote when boundary classification is proven, host/guest FP state remains correct, and executed control-load counts plus Release performance improve.
Reject if host-environment restoration is unreliable, helper effects cannot be audited, or savings disappear when measured independently.
CPU-and-vCPU-Execution · Performance-Unproven · Hot-Path-vCPU-Helper-Aware-x87-Cache-Retention · Hot-Path-vCPU-Native-SSE-Arithmetic
PR pages may be linked as supporting evidence, but they are not substitutes for this reference.
DSP tooling guide and navigation updated November 2, 2026 for experimental PR #384, source 8f51d237. Capture/replay usage and limits.
The earlier wiki-wide review was published November 1, 2026. Emulator source: b7140848. Reviewed wiki content: 1d2b671. Current status · Release availability · Publication process.
- Home
- Current status
- Stable versus main
- Implemented mechanisms
- Controls and defaults
- Measured results and limits
- Complete change register
- System
- CPU and vCPU
- Memory and DMA
- Graphics / NV2A
- APU and audio
- Timing and timers
- Platform and I/O
- Hardware observations
- Fidelity boundaries
- Methodology
- PGR2 routes
- Debugging lag / hot paths
- Tools and commands
- DSP capture, replay and fuzzing
- HLE readiness and public XISO proof
- Concurrent DSP shadow and OpenAL proof
- DSP HLE operation inventory
- DSP HLE fix examples and testing
- Development
- Upstream shortlist
- Wiki maintenance
- Research / retired work
- Optimization catalog
- Hot-path shortcuts
- Researched experiments
- Unproven proposal directory
- PR lessons
- September26 snapshot
Repository · PRs · Issues