On Sat, Jun 19, 2021 at 9:50 AM Terry Reedy <tjre...@udel.edu> wrote: > > Why are there two separate bytecode blocks for the "raise Exception"? > > Because one block must POP_TOP and other must not. > > > I'd have thought that the double condition would still be evaluated as > > one thing, or at least that the jump destinations for both the > > early-abort and the main evaluation should be the same. > > To reuse the exception block with POP_TOP, could jump over it after the > 2nd compare.
Hmm, fair enough I guess. The compiler figured that it'd be faster to duplicate the executable code rather than have the jump. It made for a somewhat confusing disassembly, but I presume it's faster to run. > For the simplest and fasted bytecode, write normal logic and let x be > reloaded instead of duplicated and rotated. > > >>> import dis > >>> def f(x): > ... if x <= 0 or 10 <= x: raise Exception > ... > ... > >>> dis.dis(f) > 2 0 LOAD_FAST 0 (x) > 2 LOAD_CONST 1 (0) > 4 COMPARE_OP 1 (<=) > 6 POP_JUMP_IF_TRUE 8 (to 16) > 8 LOAD_CONST 2 (10) > 10 LOAD_FAST 0 (x) > 12 COMPARE_OP 1 (<=) > 14 POP_JUMP_IF_FALSE 10 (to 20) > >> 16 LOAD_GLOBAL 0 (Exception) > 18 RAISE_VARARGS 1 > >> 20 LOAD_CONST 0 (None) > 22 RETURN_VALUE > >>> > Makes sense. I'm not sure if this would actually run faster, but I can't really justify warping my code around the disassembly :) Thanks for the explanation. I guess I just assumed the interpreter would prefer a jump to the duplication, but that's a decision it's free to take! ChrisA -- https://mail.python.org/mailman/listinfo/python-list