Path: csiph.com!eternal-september.org!feeder.eternal-september.org!news.iecc.com!.POSTED.news.iecc.com!nerds-end From: George Neuner Newsgroups: comp.compilers Subject: Re: Opcode handler dispatch in an interpreter: Implementing switch on OpCode. Date: Tue, 17 Oct 2017 15:55:29 -0400 (EDT) Organization: A noiseless patient Spider Lines: 62 Sender: news@iecc.com Approved: comp.compilers@iecc.com Message-ID: <17-10-026@comp.compilers> References: <17-10-001@comp.compilers> <17-10-004@comp.compilers> <17-10-009@comp.compilers> <17-10-011@comp.compilers> <17-10-014@comp.compilers> <17-10-020@comp.compilers> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 8bit Injection-Info: gal.iecc.com; posting-host="news.iecc.com:2001:470:1f07:1126:0:676f:7373:6970"; logging-data="27394"; mail-complaints-to="abuse@iecc.com" Keywords: optimize, architecture Posted-Date: 17 Oct 2017 15:55:29 EDT X-submission-address: compilers@iecc.com X-moderator-address: compilers-request@iecc.com X-FAQ-and-archives: http://compilers.iecc.com Xref: csiph.com comp.compilers:1933 On Wed, 11 Oct 2017 18:12:33 -0400 (EDT), Hans-Peter Diettrich wrote: >Am 08.10.2017 um 20:36 schrieb George Neuner: > >> Some of the things to come out of the discussions in c.l.a.x86 were >> that the fastest [simple] JIT sequence for an interpreter is a list of >> explicit call instructions: e.g., >> >> call >> call >> : >> >> rather than a list of function addresses with a dispatcher. This is >> because the call leverages the CPU branch predictor rather than >> fighting with it. > >I'm not sure about a single common instruction cache and branch >prediction architecture, the behaviour may differ amongst architectures. Branch prediction strategies vary considerably, but for the last ~25 year or so, most new CPUs have had separate L1 code and data caches. Very few carry the separation any deeper than L1, however. There are cached MPUs and DSPs that still use a shared L1, but CPUs migrated away from that structure long ago. [And, of course, CPUs increasingly are being used as MPUs.] >The memory bus interface instead should be similar in all architectures, >so that it should speed up execution if function code is aligned to the >machine's data bus width (size of a chache line). This will make >available the highest possible number of sequential instructions after >the first read at a non-sequential (jump/call) address. Yes and no. Remember that a cached CPU fetches from memory by lines, not by instructions, and modern decoders are wide: accepting and decoding whole cache lines at a time. On many machines there is no problem picking out an instruction from the middle of the cache line. That said, it is usually somewhat faster to _branch_ to a target address that is aligned to the beginning of a cache line. But many architectures do not actually require this even if there are other alignment requirements for instructions (e.g., even address, etc.). >Tail threading instead can benefit from micro code, if that instruction >sequence can be implemented in a single dedicated micro code sequence. >Again this behaviour depends heavily on the particular machine >architecture. Perhaps more instruction sequences in the emulator code >can be optimized this way? Yes. When the same sequence of interpreter functions [bytecode instructions] is used repeatedly, tail threading the functions will train the branch predictor to anticipate that sequence. This effectively turns the sequence into a single "macro" instruction from the point of view of the branch predictor. As long as the sequence is not varied too often, the tail threaded version will be the most performant. George