| Related articles |
|---|
| From: | George Neuner <gneuner2@comcast.net> |
| Newsgroups: | comp.compilers |
| Date: | Tue, 17 Oct 2017 15:55:29 -0400 (EDT) |
| Organization: | A noiseless patient Spider |
| References: | 17-10-001 17-10-004 17-10-009 17-10-011 17-10-014 17-10-020 |
| 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 |
On Wed, 11 Oct 2017 18:12:33 -0400 (EDT), Hans-Peter Diettrich
<DrDiettrich1@netscape.net> 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 <bytecode_function>
>> call <bytecode_function>
>> :
>>
>> 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
Return to the
comp.compilers page.
Search the
comp.compilers archives again.