On Tue, Aug 18, 2026 at 12:38 PM Pierrick Bouvier
<[email protected]> wrote:
>
> Hi Matt,
>
> On 8/17/2026 12:00 PM, Matt Turner wrote:
> > For guests running large amounts of code, most of what TCG executes is not
> > translated guest work but the fixed overhead around it. Blocks are short and
> > there are a great many of them, so the constant cost at each end of a block
> > (the interrupt poll and the can_do_io stores on entry, the dispatch on
> > exit) ends up dominating everything else.
> >
> > The workload throughout is qemu-alpha running an emulated alpha gcc 16.2.0
> > compiling the SQLite 3.45.1 amalgamation (255k lines, -O2) on an x86-64
> > host, in a --static --enable-lto --target-list=alpha-linux-user build. It
> > executes 34.2 billion TBs at 6.04 guest instructions each, and 24.6% of its
> > TB exits cannot use goto_tb. That is a representative shape for any guest
> > whose text is much larger than a page: indirect calls and returns
> > everywhere, plus direct branches that merely crossed a page boundary.
> >
> > The first three patches are ordinary cleanups that stand on their own. The
> > remaining five are marked RFC individually and are where the interesting
> > questions are.
> >
> >   1  accel/tcg: cache the result of curr_cflags()
> >
> >      Recomputed on every one of the run's 8.4 billion dispatches, from
> >      state that changes only when gdb enables single-step or a log mask
> >      moves. Cache it in CPUState and recompute from the four places that
> >      can change an input.                                        -5.10%
> >
> >   2  accel/tcg: enlarge the TB jump cache to 64K entries
> >
> >      4096 entries is too small for a guest running a large program;
> >      tb_htable_lookup() is 5.73% of samples. 16 bits is the knee of the
> >      sizing curve, at 1 MiB per vCPU.                            -6.02%
> >
> >   3  accel/tcg: skip the can_do_io stores in user-only builds
> >
> >      Two stores per TB that nothing in a user-only build reads: 68 billion
> >      of them over the run.                              -4.55%, -4.32% wall
> >
> >   4  RFC: tcg: probe the TB jump cache inline instead of calling a helper
> >
> >      95.8% of those 8.4 billion helper_lookup_tb_ptr() calls hit the jump
> >      cache. Emit the probe inline (hash, three guarded loads, goto_ptr)
> >      and call the helper only on a miss.               -36.51%, -27.05% wall
> >
> >   5  RFC: accel/tcg: allow cross-page goto_tb chaining in user-only builds
> >
> >      translator_use_goto_tb() refuses to chain across a page. In user-only
> >      builds the invalidation path already covers what that was protecting
> >      against: every mmap/mprotect/munmap reaches page_set_flags(), which
> >      invalidates and unlinks. Lift it there, keep it for system mode.
> >                                                         -2.42%, -4.68% wall
> >
> >   6  RFC: accel/tcg: only poll for interrupts in blocks that can close a
> >      cycle
> >
> >      The icount_decr poll needs to happen once per cycle in the guest CFG,
> >      not once per block, and any cycle must contain either a backward edge
> >      or an indirect one. Record both during translation and emit the check
> >      only for blocks that have one.                     -6.81%, -3.10% wall
> >
> >   7  RFC: accel/tcg: poison the jump cache instead of polling for indirect
> >      exits
> >
> >      What patch 6 leaves behind is mostly blocks flagged for an indirect
> >      exit. Give the inline probe its own jump cache base pointer and point
> >      it at zeroes when an exit is requested: every dispatch then misses
> >      into the helper, which returns the epilogue. The poll becomes a
> >      pointer swap on the request path.                  -2.79%, -1.94% wall
> >
> >   8  RFC: tcg: fold a guest displacement into the host addressing mode
> >
> >      tcg_gen_qemu_ld/st cannot express a based access, so a target with a
> >      displacement in its encodings materializes the address with an lea
> >      that the host addressing mode would have done for free. Fold a
> >      preceding constant add into a new argument on the op, opt-in per
> >      backend, wired up for x86_64 user-only.            -6.29%, -3.29% wall
> >
> > Each percentage is against the patch before it. End to end, measuring an
> > unmodified build of the same base against the full series, five runs each,
> > interleaved in one session so that host clock drift is shared rather than
> > attributed (mean, with the run-to-run spread):
> >
> >     instructions retired: 1,646,129,294,236 -> 738,003,153,831   -55.17%
> >                                     (0.16%)           (0.03%)
> >     wall clock:                    134.934s ->          75.189s   -44.28%
> >                                     (0.30%)           (0.99%)
> >
> > Both endpoints ran at the same 4.782 GHz effective clock, and the .s files
> > they produced are identical.
> >
> > The two figures do not track each other, and that is the interesting part:
> > what the series removes is cheap, well-predicted, highly pipelined work, so
> > it retires far more instructions than it saves time. IPC falls from 2.55 to
> > 2.05 as the remaining work gets less regular. Patch 4 also cuts
> > L1-icache load misses by 39.1%, because a dispatch no longer jumps into
> > qemu's .text and evicts translated code; qemu's own .text falls from 38.9%
> > to 5.4% of profile samples over the series.
> >
> > Every revision was built and measured separately, so the series bisects, and
> > the emulated compiler produces byte-identical assembly output at every step,
> > which is the correctness check these patches most need. Two new alpha
> > tests cover the hazards the series creates: 
> > tests/tcg/alpha/test-xpage-chain.c
> > (patch 5) and test-indirect-irq.c (patch 7). Both fail or hang if the
> > mechanism they cover is removed, which is what makes them tests of the new
> > behavior rather than of the old.
> >
> > The RFC patches need eyes I cannot supply myself. In rough order of how much
> > I would like someone to look at them:
> >
> >   - Patch 5 reverses a deliberate decision made in d3a2a1d803 on the
> >     strength of an argument about the user-only invalidation paths.
> >
> >   - Patch 6 moves system-mode interrupt latency from "bounded by block
> >     count" to "bounded by guest control flow". The bound is one
> >     straight-line run between cycles, but timer-driven guests want a closer
> >     look than I can give them. Its soundness also assumes every goto_tb
> >     destination passes through translator_use_goto_tb(); no target in the
> >     tree bypasses it today, but nothing enforces that.
> >
> >   - Patch 4 treats cpu flags and cflags as translation-time constants in
> >     its guards, reads a jump cache entry without qatomic_read(), and puts
> >     knowledge of the CPUJumpCache layout in tcg/tcg-op.c, where it does not
> >     belong.
> >
> >   - Patch 7's restore in cpu_handle_interrupt() races a concurrent poison
> >     from another thread. I believe the existing barrier around
> >     icount_decr.u16.high covers it, but my testing was single-threaded user
> >     mode.
> >
> >   - Patch 8 only examines the immediately preceding op, refuses any access
> >     with a slow path (so user-only, and no alignment check), and leaves the
> >     i128 pairs alone.
> >
> >   - Patch 2's 1 MiB per vCPU is easy to justify for a single-vCPU
> >     linux-user process and less obvious for system emulation with many
> >     vCPUs. It may want to be sized per target or made tunable rather than
> >     raised unconditionally.
> >
> > Patches 4 and 8 are wired up for alpha and x86_64 respectively; everything
> > else is target-independent, and no other backend changes behavior or needs
> > touching.
> >
> > Matt Turner (8):
> >   accel/tcg: cache the result of curr_cflags()
> >   accel/tcg: enlarge the TB jump cache to 64K entries
> >   accel/tcg: skip the can_do_io stores in user-only builds
> >   RFC: tcg: probe the TB jump cache inline instead of calling a helper
> >   RFC: accel/tcg: allow cross-page goto_tb chaining in user-only builds
> >   RFC: accel/tcg: only poll for interrupts in blocks that can close a
> >     cycle
> >   RFC: accel/tcg: poison the jump cache instead of polling for indirect
> >     exits
> >   RFC: tcg: fold a guest displacement into the host addressing mode
> >
> >  accel/tcg/cpu-exec-common.c         |  48 +++++++++++-
> >  accel/tcg/cpu-exec.c                |  54 ++++++++++++++
> >  accel/tcg/internal-common.h         |  22 +++++-
> >  accel/tcg/tb-jmp-cache.h            |   2 +-
> >  accel/tcg/tcg-accel-ops.c           |   2 +
> >  accel/tcg/tcg-all.c                 |   1 +
> >  accel/tcg/translator.c              |  77 ++++++++++++++++++-
> >  cpu-target.c                        |   3 +
> >  include/exec/translation-block.h    |   6 ++
> >  include/exec/translator.h           |   2 +
> >  include/hw/core/cpu.h               |  23 +++++-
> >  include/system/tcg.h                |   9 +++
> >  include/tcg/tcg-op-common.h         |   2 +
> >  include/tcg/tcg-opc.h               |   9 ++-
> >  linux-user/main.c                   |   2 +-
> >  stubs/meson.build                   |   1 +
> >  stubs/tcg-cflags.c                  |  16 ++++
> >  target/alpha/cpu.c                  |   2 +-
> >  target/alpha/translate.c            |   6 +-
> >  tcg/tcg-op-ldst.c                   |   3 +-
> >  tcg/tcg-op.c                        |  86 +++++++++++++++++++++
> >  tcg/tcg.c                           |  86 ++++++++++++++++++++-
> >  tcg/x86_64/tcg-target.c.inc         |  61 +++++++++++++++
> >  tcg/x86_64/tcg-target.h             |   3 +
> >  tests/tcg/alpha/Makefile.target     |   3 +-
> >  tests/tcg/alpha/test-indirect-irq.c |  53 +++++++++++++
> >  tests/tcg/alpha/test-xpage-chain.c  | 111 ++++++++++++++++++++++++++++
> >  util/log.c                          |   4 +
> >  28 files changed, 676 insertions(+), 21 deletions(-)
> >  create mode 100644 stubs/tcg-cflags.c
> >  create mode 100644 tests/tcg/alpha/test-indirect-irq.c
> >  create mode 100644 tests/tcg/alpha/test-xpage-chain.c
> >
>
> I was curious to give it a try and see if everything works before
> helping on review, however series does not apply on master currently.
>
> Could you please rebase it and send a v2?

Odd, it's based on commit af06b5df26 ("Merge tag 'qom-qdev-20260814'
of https://gitlab.com/mcayland-ntx/qemu into staging") from just a
couple of days ago. I'll handle feedback received so far and send a v2
today.

Reply via email to