@@ -2432,6 +2432,168 @@ def test_list_to_tuple_get_iter_is_safe(self):
24322432 self .assertEqual (b , [3 , 2 , 1 , 0 ])
24332433 self .assertEqual (items , [])
24342434
2435+ def test_fold_constant_big_list_for_iter (self ):
2436+ # for x in [c1, c2, ..., cN] (N > 30) should fold to LOAD_CONST tuple
2437+ consts = 35
2438+ before = (
2439+ [("BUILD_LIST" , 0 , 1 )] +
2440+ [("LOAD_CONST" , 0 , 2 ), ("LIST_APPEND" , 1 , 3 )] * consts +
2441+ [("GET_ITER" , None , 4 ),
2442+ top := self .Label (),
2443+ ("FOR_ITER" , end := self .Label (), 5 ),
2444+ ("STORE_FAST" , 0 , 6 ),
2445+ ("JUMP" , top , 7 ),
2446+ end ,
2447+ ("END_FOR" , None , 8 ),
2448+ ("POP_ITER" , None , 9 ),
2449+ ("LOAD_CONST" , 0 , 10 ),
2450+ ("RETURN_VALUE" , None , 11 )]
2451+ )
2452+ after = [
2453+ ("LOAD_CONST" , 1 , 3 ),
2454+ ("GET_ITER" , None , 4 ),
2455+ top := self .Label (),
2456+ ("FOR_ITER" , end := self .Label (), 5 ),
2457+ ("STORE_FAST" , 0 , 6 ),
2458+ ("JUMP" , top , 7 ),
2459+ end ,
2460+ ("END_FOR" , None , 8 ),
2461+ ("POP_ITER" , None , 9 ),
2462+ ("LOAD_CONST" , 0 , 10 ),
2463+ ("RETURN_VALUE" , None , 11 ),
2464+ ]
2465+ result_const = tuple (["test" ] * consts )
2466+ self .cfg_optimization_test (before , after , consts = ["test" ],
2467+ expected_consts = ["test" , result_const ])
2468+
2469+ def test_fold_constant_big_set_for_iter (self ):
2470+ # for x in {c1, c2, ..., cN} (N > 30) should fold to LOAD_CONST frozenset
2471+ before = [
2472+ ("BUILD_SET" , 0 , 1 ),
2473+ ("LOAD_SMALL_INT" , 1 , 2 ), ("SET_ADD" , 1 , 3 ),
2474+ ("LOAD_SMALL_INT" , 2 , 4 ), ("SET_ADD" , 1 , 5 ),
2475+ ("LOAD_SMALL_INT" , 3 , 6 ), ("SET_ADD" , 1 , 7 ),
2476+ ("GET_ITER" , None , 8 ),
2477+ top := self .Label (),
2478+ ("FOR_ITER" , end := self .Label (), 9 ),
2479+ ("STORE_FAST" , 0 , 10 ),
2480+ ("JUMP" , top , 11 ),
2481+ end ,
2482+ ("END_FOR" , None , 12 ),
2483+ ("POP_ITER" , None , 13 ),
2484+ ("LOAD_CONST" , 0 , 14 ),
2485+ ("RETURN_VALUE" , None , 15 ),
2486+ ]
2487+ after = [
2488+ ("LOAD_CONST" , 1 , 7 ),
2489+ ("GET_ITER" , None , 8 ),
2490+ top := self .Label (),
2491+ ("FOR_ITER" , end := self .Label (), 9 ),
2492+ ("STORE_FAST" , 0 , 10 ),
2493+ ("JUMP" , top , 11 ),
2494+ end ,
2495+ ("END_FOR" , None , 12 ),
2496+ ("POP_ITER" , None , 13 ),
2497+ ("LOAD_CONST" , 0 , 14 ),
2498+ ("RETURN_VALUE" , None , 15 ),
2499+ ]
2500+ self .cfg_optimization_test (before , after , consts = ["test" ],
2501+ expected_consts = ["test" , frozenset ({1 , 2 , 3 })])
2502+
2503+ def test_fold_constant_list_to_tuple_for_iter (self ):
2504+ INTRINSIC_LIST_TO_TUPLE = 6
2505+ before = [
2506+ ("BUILD_LIST" , 0 , 1 ),
2507+ ("LOAD_SMALL_INT" , 1 , 2 ), ("LIST_APPEND" , 1 , 3 ),
2508+ ("LOAD_SMALL_INT" , 2 , 4 ), ("LIST_APPEND" , 1 , 5 ),
2509+ ("LOAD_SMALL_INT" , 3 , 6 ), ("LIST_APPEND" , 1 , 7 ),
2510+ ("CALL_INTRINSIC_1" , INTRINSIC_LIST_TO_TUPLE , 8 ),
2511+ ("GET_ITER" , None , 9 ),
2512+ top := self .Label (),
2513+ ("FOR_ITER" , end := self .Label (), 10 ),
2514+ ("STORE_FAST" , 0 , 11 ),
2515+ ("JUMP" , top , 12 ),
2516+ end ,
2517+ ("END_FOR" , None , 13 ),
2518+ ("POP_ITER" , None , 14 ),
2519+ ("LOAD_CONST" , 0 , 15 ),
2520+ ("RETURN_VALUE" , None , 16 ),
2521+ ]
2522+ after = [
2523+ ("LOAD_CONST" , 1 , 8 ),
2524+ ("GET_ITER" , None , 9 ),
2525+ top := self .Label (),
2526+ ("FOR_ITER" , end := self .Label (), 10 ),
2527+ ("STORE_FAST" , 0 , 11 ),
2528+ ("JUMP" , top , 12 ),
2529+ end ,
2530+ ("END_FOR" , None , 13 ),
2531+ ("POP_ITER" , None , 14 ),
2532+ ("LOAD_CONST" , 0 , 15 ),
2533+ ("RETURN_VALUE" , None , 16 ),
2534+ ]
2535+ self .cfg_optimization_test (before , after , consts = ["test" ],
2536+ expected_consts = ["test" , (1 , 2 , 3 )])
2537+
2538+ def test_fold_constant_big_list_contains_op (self ):
2539+ # x in [c1, c2, ..., cN] (N > 30) should fold to LOAD_CONST tuple
2540+ before = [
2541+ ("LOAD_FAST" , 0 , 1 ),
2542+ ("BUILD_LIST" , 0 , 2 ),
2543+ ("LOAD_SMALL_INT" , 1 , 3 ), ("LIST_APPEND" , 1 , 4 ),
2544+ ("LOAD_SMALL_INT" , 2 , 5 ), ("LIST_APPEND" , 1 , 6 ),
2545+ ("LOAD_SMALL_INT" , 3 , 7 ), ("LIST_APPEND" , 1 , 8 ),
2546+ ("CONTAINS_OP" , 0 , 9 ),
2547+ ("RETURN_VALUE" , None , 10 ),
2548+ ]
2549+ after = [
2550+ ("LOAD_FAST_BORROW" , 0 , 1 ),
2551+ ("LOAD_CONST" , 1 , 8 ),
2552+ ("CONTAINS_OP" , 0 , 9 ),
2553+ ("RETURN_VALUE" , None , 10 ),
2554+ ]
2555+ self .cfg_optimization_test (before , after , consts = [None ],
2556+ expected_consts = [None , (1 , 2 , 3 )])
2557+
2558+ def test_fold_constant_big_set_contains_op (self ):
2559+ # x in {c1, c2, ..., cN} (N > 30) should fold to LOAD_CONST frozenset
2560+ before = [
2561+ ("LOAD_FAST" , 0 , 1 ),
2562+ ("BUILD_SET" , 0 , 2 ),
2563+ ("LOAD_SMALL_INT" , 1 , 3 ), ("SET_ADD" , 1 , 4 ),
2564+ ("LOAD_SMALL_INT" , 2 , 5 ), ("SET_ADD" , 1 , 6 ),
2565+ ("LOAD_SMALL_INT" , 3 , 7 ), ("SET_ADD" , 1 , 8 ),
2566+ ("CONTAINS_OP" , 0 , 9 ),
2567+ ("RETURN_VALUE" , None , 10 ),
2568+ ]
2569+ after = [
2570+ ("LOAD_FAST_BORROW" , 0 , 1 ),
2571+ ("LOAD_CONST" , 1 , 8 ),
2572+ ("CONTAINS_OP" , 0 , 9 ),
2573+ ("RETURN_VALUE" , None , 10 ),
2574+ ]
2575+ self .cfg_optimization_test (before , after , consts = [None ],
2576+ expected_consts = [None , frozenset ({1 , 2 , 3 })])
2577+
2578+ def test_no_fold_big_list_for_iter_with_non_const (self ):
2579+ same = [
2580+ ("BUILD_LIST" , 0 , 1 ),
2581+ ("LOAD_SMALL_INT" , 1 , 2 ), ("LIST_APPEND" , 1 , 3 ),
2582+ ("LOAD_FAST_BORROW" , 0 , 4 ), ("LIST_APPEND" , 1 , 5 ),
2583+ ("LOAD_SMALL_INT" , 3 , 6 ), ("LIST_APPEND" , 1 , 7 ),
2584+ ("GET_ITER" , None , 8 ),
2585+ top := self .Label (),
2586+ ("FOR_ITER" , end := self .Label (), 9 ),
2587+ ("STORE_FAST" , 1 , 10 ),
2588+ ("JUMP" , top , 11 ),
2589+ end ,
2590+ ("END_FOR" , None , 12 ),
2591+ ("POP_ITER" , None , 13 ),
2592+ ("LOAD_CONST" , 0 , 14 ),
2593+ ("RETURN_VALUE" , None , 15 ),
2594+ ]
2595+ self .cfg_optimization_test (same , same , consts = ["test" ])
2596+
24352597
24362598class OptimizeLoadFastTestCase (DirectCfgOptimizerTests ):
24372599 def make_bb (self , insts ):
0 commit comments