Skip to content

Commit 4603470

Browse files
committed
Prevent the compiler from merging computed-goto dispatches
When compiling the computed-goto interpreter, every opcode implementation ends with an identical chunk of code, generated by the `DISPATCH()` macro. In some cases, the compiler is able to notice this, and replaces the code in one or more opcodes with a jump into the tail portion of a different opcode. However, we specifically **don't** want that to happen; the entire premise of using computed gotos is to lift more information into the instruction pointer in order to give the hardware branch-target- predictor more information to work with! In my preliminary tests, this tail-merging of opcode implementations explains most of the performance improvement of the new tail-call interpreter (python#128718) -- compilers are much less willing to merge code across functions, and so the tail-call interpreter preserves all (or at least more) of the individual `DISPATCH` sites. This change attempts to prevent the merging of `DISPATCH` calls, by adding an (empty) `__asm__ volatile`, which acts as an opaque barrier to the optimizer, preventing it from considering all of these sequences as identical.
1 parent c1f352b commit 4603470

File tree

1 file changed

+1
-1
lines changed

1 file changed

+1
-1
lines changed

Python/ceval_macros.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@
9595
# define LABEL(name) TARGET(name)
9696
#elif USE_COMPUTED_GOTOS
9797
# define TARGET(op) TARGET_##op:
98-
# define DISPATCH_GOTO() goto *opcode_targets[opcode]
98+
# define DISPATCH_GOTO() do { __asm__ volatile (""); goto *opcode_targets[opcode]; } while (0)
9999
# define JUMP_TO_LABEL(name) goto name;
100100
# define JUMP_TO_PREDICTED(name) goto PREDICTED_##name;
101101
# define LABEL(name) name:

0 commit comments

Comments
 (0)