@@ -235,78 +235,6 @@ def g(a):
235235 self .assertTrue (g (4 ))
236236 self .check_lnotab (g )
237237
238-
239- def test_folding_of_binops_on_constants (self ):
240- for line , elem in (
241- ('a = 2+3+4' , 9 ), # chained fold
242- ('"@"*4' , '@@@@' ), # check string ops
243- ('a="abc" + "def"' , 'abcdef' ), # check string ops
244- ('a = 3**4' , 81 ), # binary power
245- ('a = 3*4' , 12 ), # binary multiply
246- ('a = 13//4' , 3 ), # binary floor divide
247- ('a = 14%4' , 2 ), # binary modulo
248- ('a = 2+3' , 5 ), # binary add
249- ('a = 13-4' , 9 ), # binary subtract
250- ('a = (12,13)[1]' , 13 ), # binary subscr
251- ('a = 13 << 2' , 52 ), # binary lshift
252- ('a = 13 >> 2' , 3 ), # binary rshift
253- ('a = 13 & 7' , 5 ), # binary and
254- ('a = 13 ^ 7' , 10 ), # binary xor
255- ('a = 13 | 7' , 15 ), # binary or
256- ):
257- with self .subTest (line = line ):
258- code = compile (line , '' , 'single' )
259- if isinstance (elem , int ):
260- self .assertInBytecode (code , 'LOAD_SMALL_INT' , elem )
261- else :
262- self .assertInBytecode (code , 'LOAD_CONST' , elem )
263- for instr in dis .get_instructions (code ):
264- self .assertFalse (instr .opname .startswith ('BINARY_' ))
265- self .check_lnotab (code )
266-
267- # Verify that unfoldables are skipped
268- code = compile ('a=2+"b"' , '' , 'single' )
269- self .assertInBytecode (code , 'LOAD_SMALL_INT' , 2 )
270- self .assertInBytecode (code , 'LOAD_CONST' , 'b' )
271- self .check_lnotab (code )
272-
273- # Verify that large sequences do not result from folding
274- code = compile ('a="x"*10000' , '' , 'single' )
275- self .assertInBytecode (code , 'LOAD_CONST' , 10000 )
276- self .assertNotIn ("x" * 10000 , code .co_consts )
277- self .check_lnotab (code )
278- code = compile ('a=1<<1000' , '' , 'single' )
279- self .assertInBytecode (code , 'LOAD_CONST' , 1000 )
280- self .assertNotIn (1 << 1000 , code .co_consts )
281- self .check_lnotab (code )
282- code = compile ('a=2**1000' , '' , 'single' )
283- self .assertInBytecode (code , 'LOAD_CONST' , 1000 )
284- self .assertNotIn (2 ** 1000 , code .co_consts )
285- self .check_lnotab (code )
286-
287- def test_binary_subscr_on_unicode (self ):
288- # valid code get optimized
289- code = compile ('"foo"[0]' , '' , 'single' )
290- self .assertInBytecode (code , 'LOAD_CONST' , 'f' )
291- self .assertNotInBytecode (code , 'BINARY_OP' )
292- self .check_lnotab (code )
293- code = compile ('"\u0061 \uffff "[1]' , '' , 'single' )
294- self .assertInBytecode (code , 'LOAD_CONST' , '\uffff ' )
295- self .assertNotInBytecode (code ,'BINARY_OP' )
296- self .check_lnotab (code )
297-
298- # With PEP 393, non-BMP char get optimized
299- code = compile ('"\U00012345 "[0]' , '' , 'single' )
300- self .assertInBytecode (code , 'LOAD_CONST' , '\U00012345 ' )
301- self .assertNotInBytecode (code , 'BINARY_OP' )
302- self .check_lnotab (code )
303-
304- # invalid code doesn't get optimized
305- # out of range
306- code = compile ('"fuu"[10]' , '' , 'single' )
307- self .assertInBytecode (code , 'BINARY_OP' )
308- self .check_lnotab (code )
309-
310238 def test_elim_extra_return (self ):
311239 # RETURN LOAD_CONST None RETURN --> RETURN
312240 def f (x ):
@@ -523,73 +451,117 @@ def negzero():
523451
524452 def test_folding_binop (self ):
525453 tests = [
526- ('1 + 2' , False , 'NB_ADD' ),
527- ('1 + 2 + 3' , False , 'NB_ADD' ),
528- ('1 + ""' , True , 'NB_ADD' ),
529- ('1 - 2' , False , 'NB_SUBTRACT' ),
530- ('1 - 2 - 3' , False , 'NB_SUBTRACT' ),
531- ('1 - ""' , True , 'NB_SUBTRACT' ),
532- ('2 * 2' , False , 'NB_MULTIPLY' ),
533- ('2 * 2 * 2' , False , 'NB_MULTIPLY' ),
534- ('2 / 2' , False , 'NB_TRUE_DIVIDE' ),
535- ('2 / 2 / 2' , False , 'NB_TRUE_DIVIDE' ),
536- ('2 / ""' , True , 'NB_TRUE_DIVIDE' ),
537- ('2 // 2' , False , 'NB_FLOOR_DIVIDE' ),
538- ('2 // 2 // 2' , False , 'NB_FLOOR_DIVIDE' ),
539- ('2 // ""' , True , 'NB_FLOOR_DIVIDE' ),
540- ('2 % 2' , False , 'NB_REMAINDER' ),
541- ('2 % 2 % 2' , False , 'NB_REMAINDER' ),
542- ('2 % ()' , True , 'NB_REMAINDER' ),
543- ('2 ** 2' , False , 'NB_POWER' ),
544- ('2 ** 2 ** 2' , False , 'NB_POWER' ),
545- ('2 ** ""' , True , 'NB_POWER' ),
546- ('2 << 2' , False , 'NB_LSHIFT' ),
547- ('2 << 2 << 2' , False , 'NB_LSHIFT' ),
548- ('2 << ""' , True , 'NB_LSHIFT' ),
549- ('2 >> 2' , False , 'NB_RSHIFT' ),
550- ('2 >> 2 >> 2' , False , 'NB_RSHIFT' ),
551- ('2 >> ""' , True , 'NB_RSHIFT' ),
552- ('2 | 2' , False , 'NB_OR' ),
553- ('2 | 2 | 2' , False , 'NB_OR' ),
554- ('2 | ""' , True , 'NB_OR' ),
555- ('2 & 2' , False , 'NB_AND' ),
556- ('2 & 2 & 2' , False , 'NB_AND' ),
557- ('2 & ""' , True , 'NB_AND' ),
558- ('2 ^ 2' , False , 'NB_XOR' ),
559- ('2 ^ 2 ^ 2' , False , 'NB_XOR' ),
560- ('2 ^ ""' , True , 'NB_XOR' ),
561- ('(1, )[0]' , False , 'NB_SUBSCR' ),
562- ('(1, )[-1]' , False , 'NB_SUBSCR' ),
563- ('(1 + 2, )[0]' , False , 'NB_SUBSCR' ),
564- ('(1, (1, 2))[1][1]' , False , 'NB_SUBSCR' ),
565- ('(1, 2)[2-1]' , False , 'NB_SUBSCR' ),
566- ('(1, (1, 2))[1][2-1]' , False , 'NB_SUBSCR' ),
567- ('(1, (1, 2))[1:6][0][2-1]' , False , 'NB_SUBSCR' ),
568- ('"a"[0]' , False , 'NB_SUBSCR' ),
569- ('("a" + "b")[1]' , False , 'NB_SUBSCR' ),
570- ('("a" + "b", )[0][1]' , False , 'NB_SUBSCR' ),
571- ('("a" * 10)[9]' , False , 'NB_SUBSCR' ),
572- ('(1, )[1]' , True , 'NB_SUBSCR' ),
573- ('(1, )[-2]' , True , 'NB_SUBSCR' ),
574- ('"a"[1]' , True , 'NB_SUBSCR' ),
575- ('"a"[-2]' , True , 'NB_SUBSCR' ),
576- ('("a" + "b")[2]' , True , 'NB_SUBSCR' ),
577- ('("a" + "b", )[0][2]' , True , 'NB_SUBSCR' ),
578- ('("a" + "b", )[1][0]' , True , 'NB_SUBSCR' ),
579- ('("a" * 10)[10]' , True , 'NB_SUBSCR' ),
580- ('(1, (1, 2))[2:6][0][2-1]' , True , 'NB_SUBSCR' ),
581-
582- ]
583- for expr , has_error , nb_op in tests :
584- with self .subTest (expr = expr , has_error = has_error ):
454+ ('1 + 2' , 'NB_ADD' , True , 'LOAD_SMALL_INT' , 3 ),
455+ ('1 + 2 + 3' , 'NB_ADD' , True , 'LOAD_SMALL_INT' , 6 ),
456+ ('1 + ""' , 'NB_ADD' , False , None , None ),
457+ ('1 - 2' , 'NB_SUBTRACT' , True , 'LOAD_CONST' , - 1 ),
458+ ('1 - 2 - 3' , 'NB_SUBTRACT' , True , 'LOAD_CONST' , - 4 ),
459+ ('1 - ""' , 'NB_SUBTRACT' , False , None , None ),
460+ ('2 * 2' , 'NB_MULTIPLY' , True , 'LOAD_SMALL_INT' , 4 ),
461+ ('2 * 2 * 2' , 'NB_MULTIPLY' , True , 'LOAD_SMALL_INT' , 8 ),
462+ ('2 / 2' , 'NB_TRUE_DIVIDE' , True , 'LOAD_CONST' , 1.0 ),
463+ ('2 / 2 / 2' , 'NB_TRUE_DIVIDE' , True , 'LOAD_CONST' , 0.5 ),
464+ ('2 / ""' , 'NB_TRUE_DIVIDE' , False , None , None ),
465+ ('2 // 2' , 'NB_FLOOR_DIVIDE' , True , 'LOAD_SMALL_INT' , 1 ),
466+ ('2 // 2 // 2' , 'NB_FLOOR_DIVIDE' , True , 'LOAD_SMALL_INT' , 0 ),
467+ ('2 // ""' , 'NB_FLOOR_DIVIDE' , False , None , None ),
468+ ('2 % 2' , 'NB_REMAINDER' , True , 'LOAD_SMALL_INT' , 0 ),
469+ ('2 % 2 % 2' , 'NB_REMAINDER' , True , 'LOAD_SMALL_INT' , 0 ),
470+ ('2 % ()' , 'NB_REMAINDER' , False , None , None ),
471+ ('2 ** 2' , 'NB_POWER' , True , 'LOAD_SMALL_INT' , 4 ),
472+ ('2 ** 2 ** 2' , 'NB_POWER' , True , 'LOAD_SMALL_INT' , 16 ),
473+ ('2 ** ""' , 'NB_POWER' , False , None , None ),
474+ ('2 << 2' , 'NB_LSHIFT' , True , 'LOAD_SMALL_INT' , 8 ),
475+ ('2 << 2 << 2' , 'NB_LSHIFT' , True , 'LOAD_SMALL_INT' , 32 ),
476+ ('2 << ""' , 'NB_LSHIFT' , False , None , None ),
477+ ('2 >> 2' , 'NB_RSHIFT' , True , 'LOAD_SMALL_INT' , 0 ),
478+ ('2 >> 2 >> 2' , 'NB_RSHIFT' , True , 'LOAD_SMALL_INT' , 0 ),
479+ ('2 >> ""' , 'NB_RSHIFT' , False , None , None ),
480+ ('2 | 2' , 'NB_OR' , True , 'LOAD_SMALL_INT' , 2 ),
481+ ('2 | 2 | 2' , 'NB_OR' , True , 'LOAD_SMALL_INT' , 2 ),
482+ ('2 | ""' , 'NB_OR' , False , None , None ),
483+ ('2 & 2' , 'NB_AND' , True , 'LOAD_SMALL_INT' , 2 ),
484+ ('2 & 2 & 2' , 'NB_AND' , True , 'LOAD_SMALL_INT' , 2 ),
485+ ('2 & ""' , 'NB_AND' , False , None , None ),
486+ ('2 ^ 2' , 'NB_XOR' , True , 'LOAD_SMALL_INT' , 0 ),
487+ ('2 ^ 2 ^ 2' , 'NB_XOR' , True , 'LOAD_SMALL_INT' , 2 ),
488+ ('2 ^ ""' , 'NB_XOR' , False , None , None ),
489+ ('(1, )[0]' , 'NB_SUBSCR' , True , 'LOAD_SMALL_INT' , 1 ),
490+ ('(1, )[-1]' , 'NB_SUBSCR' , True , 'LOAD_SMALL_INT' , 1 ),
491+ ('(1 + 2, )[0]' , 'NB_SUBSCR' , True , 'LOAD_SMALL_INT' , 3 ),
492+ ('(1, (1, 2))[1][1]' , 'NB_SUBSCR' , True , 'LOAD_SMALL_INT' , 2 ),
493+ ('(1, 2)[2-1]' , 'NB_SUBSCR' , True , 'LOAD_SMALL_INT' , 2 ),
494+ ('(1, (1, 2))[1][2-1]' , 'NB_SUBSCR' , True , 'LOAD_SMALL_INT' , 2 ),
495+ ('(1, (1, 2))[1:6][0][2-1]' , 'NB_SUBSCR' , True , 'LOAD_SMALL_INT' , 2 ),
496+ ('"a"[0]' , 'NB_SUBSCR' , True , 'LOAD_CONST' , 'a' ),
497+ ('("a" + "b")[1]' , 'NB_SUBSCR' , True , 'LOAD_CONST' , 'b' ),
498+ ('("a" + "b", )[0][1]' , 'NB_SUBSCR' , True , 'LOAD_CONST' , 'b' ),
499+ ('("a" * 10)[9]' , 'NB_SUBSCR' , True , 'LOAD_CONST' , 'a' ),
500+ ('(1, )[1]' , 'NB_SUBSCR' , False , None , None ),
501+ ('(1, )[-2]' , 'NB_SUBSCR' , False , None , None ),
502+ ('"a"[1]' , 'NB_SUBSCR' , False , None , None ),
503+ ('"a"[-2]' , 'NB_SUBSCR' , False , None , None ),
504+ ('("a" + "b")[2]' , 'NB_SUBSCR' , False , None , None ),
505+ ('("a" + "b", )[0][2]' , 'NB_SUBSCR' , False , None , None ),
506+ ('("a" + "b", )[1][0]' , 'NB_SUBSCR' , False , None , None ),
507+ ('("a" * 10)[10]' , 'NB_SUBSCR' , False , None , None ),
508+ ('(1, (1, 2))[2:6][0][2-1]' , 'NB_SUBSCR' , False , None , None ),
509+ ]
510+ for (
511+ expr ,
512+ nb_op ,
513+ is_optimized ,
514+ optimized_opcode ,
515+ optimized_argval
516+ ) in tests :
517+ with self .subTest (expr = expr , is_optimized = is_optimized ):
585518 code = compile (expr , '' , 'single' )
586519 nb_op_val = get_binop_argval (nb_op )
587- if not has_error :
520+ if is_optimized :
588521 self .assertNotInBytecode (code , 'BINARY_OP' , argval = nb_op_val )
522+ self .assertInBytecode (code , optimized_opcode , argval = optimized_argval )
589523 else :
590524 self .assertInBytecode (code , 'BINARY_OP' , argval = nb_op_val )
591525 self .check_lnotab (code )
592526
527+ # Verify that large sequences do not result from folding
528+ code = compile ('"x"*10000' , '' , 'single' )
529+ self .assertInBytecode (code , 'LOAD_CONST' , 10000 )
530+ self .assertNotIn ("x" * 10000 , code .co_consts )
531+ self .check_lnotab (code )
532+ code = compile ('1<<1000' , '' , 'single' )
533+ self .assertInBytecode (code , 'LOAD_CONST' , 1000 )
534+ self .assertNotIn (1 << 1000 , code .co_consts )
535+ self .check_lnotab (code )
536+ code = compile ('2**1000' , '' , 'single' )
537+ self .assertInBytecode (code , 'LOAD_CONST' , 1000 )
538+ self .assertNotIn (2 ** 1000 , code .co_consts )
539+ self .check_lnotab (code )
540+
541+ # Test binary subscript on unicode
542+ # valid code get optimized
543+ code = compile ('"foo"[0]' , '' , 'single' )
544+ self .assertInBytecode (code , 'LOAD_CONST' , 'f' )
545+ self .assertNotInBytecode (code , 'BINARY_OP' )
546+ self .check_lnotab (code )
547+ code = compile ('"\u0061 \uffff "[1]' , '' , 'single' )
548+ self .assertInBytecode (code , 'LOAD_CONST' , '\uffff ' )
549+ self .assertNotInBytecode (code ,'BINARY_OP' )
550+ self .check_lnotab (code )
551+
552+ # With PEP 393, non-BMP char get optimized
553+ code = compile ('"\U00012345 "[0]' , '' , 'single' )
554+ self .assertInBytecode (code , 'LOAD_CONST' , '\U00012345 ' )
555+ self .assertNotInBytecode (code , 'BINARY_OP' )
556+ self .check_lnotab (code )
557+
558+ # invalid code doesn't get optimized
559+ # out of range
560+ code = compile ('"fuu"[10]' , '' , 'single' )
561+ self .assertInBytecode (code , 'BINARY_OP' )
562+ self .check_lnotab (code )
563+
564+
593565 def test_constant_folding_remove_nop_location (self ):
594566 sources = [
595567 """
0 commit comments