@@ -449,6 +449,15 @@ _PyCfgBuilder_Addop(cfg_builder *g, int opcode, int oparg, location loc)
449449}
450450
451451
452+ static basicblock *
453+ next_nonempty_block (basicblock * b )
454+ {
455+ while (b && b -> b_iused == 0 ) {
456+ b = b -> b_next ;
457+ }
458+ return b ;
459+ }
460+
452461/***** debugging helpers *****/
453462
454463#ifndef NDEBUG
@@ -464,24 +473,16 @@ no_redundant_nops(cfg_builder *g) {
464473 return true;
465474}
466475
467- static bool
468- no_empty_basic_blocks (cfg_builder * g ) {
469- for (basicblock * b = g -> g_entryblock ; b != NULL ; b = b -> b_next ) {
470- if (b -> b_iused == 0 ) {
471- return false;
472- }
473- }
474- return true;
475- }
476-
477476static bool
478477no_redundant_jumps (cfg_builder * g ) {
479478 for (basicblock * b = g -> g_entryblock ; b != NULL ; b = b -> b_next ) {
480479 cfg_instr * last = basicblock_last_instr (b );
481480 if (last != NULL ) {
482481 if (IS_UNCONDITIONAL_JUMP_OPCODE (last -> i_opcode )) {
483- assert (last -> i_target != b -> b_next );
484- if (last -> i_target == b -> b_next ) {
482+ basicblock * next = next_nonempty_block (b -> b_next );
483+ basicblock * jump_target = next_nonempty_block (last -> i_target );
484+ assert (jump_target != next );
485+ if (jump_target == next ) {
485486 return false;
486487 }
487488 }
@@ -961,42 +962,6 @@ mark_reachable(basicblock *entryblock) {
961962 return SUCCESS ;
962963}
963964
964- static void
965- eliminate_empty_basic_blocks (cfg_builder * g ) {
966- /* Eliminate empty blocks */
967- for (basicblock * b = g -> g_entryblock ; b != NULL ; b = b -> b_next ) {
968- basicblock * next = b -> b_next ;
969- while (next && next -> b_iused == 0 ) {
970- next = next -> b_next ;
971- }
972- b -> b_next = next ;
973- }
974- while (g -> g_entryblock && g -> g_entryblock -> b_iused == 0 ) {
975- g -> g_entryblock = g -> g_entryblock -> b_next ;
976- }
977- int next_lbl = get_max_label (g -> g_entryblock ) + 1 ;
978- for (basicblock * b = g -> g_entryblock ; b != NULL ; b = b -> b_next ) {
979- assert (b -> b_iused > 0 );
980- for (int i = 0 ; i < b -> b_iused ; i ++ ) {
981- cfg_instr * instr = & b -> b_instr [i ];
982- if (HAS_TARGET (instr -> i_opcode )) {
983- basicblock * target = instr -> i_target ;
984- while (target -> b_iused == 0 ) {
985- target = target -> b_next ;
986- }
987- if (instr -> i_target != target ) {
988- if (!IS_LABEL (target -> b_label )) {
989- target -> b_label .id = next_lbl ++ ;
990- }
991- instr -> i_target = target ;
992- instr -> i_oparg = target -> b_label .id ;
993- }
994- assert (instr -> i_target && instr -> i_target -> b_iused > 0 );
995- }
996- }
997- }
998- }
999-
1000965static int
1001966remove_redundant_nops (basicblock * bb ) {
1002967 /* Remove NOPs when legal to do so. */
@@ -1025,10 +990,7 @@ remove_redundant_nops(basicblock *bb) {
1025990 }
1026991 }
1027992 else {
1028- basicblock * next = bb -> b_next ;
1029- while (next && next -> b_iused == 0 ) {
1030- next = next -> b_next ;
1031- }
993+ basicblock * next = next_nonempty_block (bb -> b_next );
1032994 /* or if last instruction in BB and next BB has same line number */
1033995 if (next ) {
1034996 location next_loc = NO_LOCATION ;
@@ -1112,36 +1074,29 @@ remove_redundant_jumps(cfg_builder *g) {
11121074 * can be deleted.
11131075 */
11141076
1115- assert (no_empty_basic_blocks (g ));
1116-
1117- bool remove_empty_blocks = false;
11181077 for (basicblock * b = g -> g_entryblock ; b != NULL ; b = b -> b_next ) {
11191078 cfg_instr * last = basicblock_last_instr (b );
1120- assert (last != NULL );
1079+ if (last == NULL ) {
1080+ continue ;
1081+ }
11211082 assert (!IS_ASSEMBLER_OPCODE (last -> i_opcode ));
11221083 if (IS_UNCONDITIONAL_JUMP_OPCODE (last -> i_opcode )) {
1123- if (last -> i_target == NULL ) {
1084+ basicblock * jump_target = next_nonempty_block (last -> i_target );
1085+ if (jump_target == NULL ) {
11241086 PyErr_SetString (PyExc_SystemError , "jump with NULL target" );
11251087 return ERROR ;
11261088 }
1127- if ( last -> i_target == b -> b_next ) {
1128- assert ( b -> b_next -> b_iused );
1089+ basicblock * next = next_nonempty_block ( b -> b_next );
1090+ if ( jump_target == next ) {
11291091 if (last -> i_loc .lineno == NO_LOCATION .lineno ) {
11301092 b -> b_iused -- ;
1131- if (b -> b_iused == 0 ) {
1132- remove_empty_blocks = true;
1133- }
11341093 }
11351094 else {
11361095 INSTR_SET_OP0 (last , NOP );
11371096 }
11381097 }
11391098 }
11401099 }
1141- if (remove_empty_blocks ) {
1142- eliminate_empty_basic_blocks (g );
1143- }
1144- assert (no_empty_basic_blocks (g ));
11451100 return SUCCESS ;
11461101}
11471102
@@ -1749,11 +1704,9 @@ optimize_cfg(cfg_builder *g, PyObject *consts, PyObject *const_cache)
17491704{
17501705 assert (PyDict_CheckExact (const_cache ));
17511706 RETURN_IF_ERROR (check_cfg (g ));
1752- eliminate_empty_basic_blocks (g );
17531707 for (basicblock * b = g -> g_entryblock ; b != NULL ; b = b -> b_next ) {
17541708 RETURN_IF_ERROR (inline_small_exit_blocks (b ));
17551709 }
1756- assert (no_empty_basic_blocks (g ));
17571710 for (basicblock * b = g -> g_entryblock ; b != NULL ; b = b -> b_next ) {
17581711 RETURN_IF_ERROR (optimize_basic_block (const_cache , b , consts ));
17591712 assert (b -> b_predecessors == 0 );
@@ -1768,14 +1721,21 @@ optimize_cfg(cfg_builder *g, PyObject *consts, PyObject *const_cache)
17681721 for (basicblock * b = g -> g_entryblock ; b != NULL ; b = b -> b_next ) {
17691722 if (b -> b_predecessors == 0 ) {
17701723 b -> b_iused = 0 ;
1724+ b -> b_except_handler = 0 ;
17711725 }
17721726 }
17731727 for (basicblock * b = g -> g_entryblock ; b != NULL ; b = b -> b_next ) {
17741728 remove_redundant_nops (b );
17751729 }
1776- eliminate_empty_basic_blocks (g );
1777- assert (no_redundant_nops (g ));
17781730 RETURN_IF_ERROR (remove_redundant_jumps (g ));
1731+
1732+ for (basicblock * b = g -> g_entryblock ; b != NULL ; b = b -> b_next ) {
1733+ remove_redundant_nops (b );
1734+ }
1735+
1736+ RETURN_IF_ERROR (remove_redundant_jumps (g ));
1737+
1738+ assert (no_redundant_jumps (g ));
17791739 return SUCCESS ;
17801740}
17811741
@@ -1825,7 +1785,6 @@ insert_superinstructions(cfg_builder *g)
18251785 for (basicblock * b = g -> g_entryblock ; b != NULL ; b = b -> b_next ) {
18261786 remove_redundant_nops (b );
18271787 }
1828- eliminate_empty_basic_blocks (g );
18291788 assert (no_redundant_nops (g ));
18301789}
18311790
@@ -2299,18 +2258,18 @@ is_exit_without_lineno(basicblock *b) {
22992258static int
23002259duplicate_exits_without_lineno (cfg_builder * g )
23012260{
2302- assert (no_empty_basic_blocks (g ));
2303-
23042261 int next_lbl = get_max_label (g -> g_entryblock ) + 1 ;
23052262
23062263 /* Copy all exit blocks without line number that are targets of a jump.
23072264 */
23082265 basicblock * entryblock = g -> g_entryblock ;
23092266 for (basicblock * b = entryblock ; b != NULL ; b = b -> b_next ) {
23102267 cfg_instr * last = basicblock_last_instr (b );
2311- assert (last != NULL );
2268+ if (last == NULL ) {
2269+ continue ;
2270+ }
23122271 if (is_jump (last )) {
2313- basicblock * target = last -> i_target ;
2272+ basicblock * target = next_nonempty_block ( last -> i_target ) ;
23142273 if (is_exit_without_lineno (target ) && target -> b_predecessors > 1 ) {
23152274 basicblock * new_target = copy_basicblock (g , target );
23162275 if (new_target == NULL ) {
@@ -2367,9 +2326,10 @@ propagate_line_numbers(basicblock *entryblock) {
23672326 }
23682327 }
23692328 if (BB_HAS_FALLTHROUGH (b ) && b -> b_next -> b_predecessors == 1 ) {
2370- assert (b -> b_next -> b_iused );
2371- if (b -> b_next -> b_instr [0 ].i_loc .lineno < 0 ) {
2372- b -> b_next -> b_instr [0 ].i_loc = prev_location ;
2329+ if (b -> b_next -> b_iused > 0 ) {
2330+ if (b -> b_next -> b_instr [0 ].i_loc .lineno < 0 ) {
2331+ b -> b_next -> b_instr [0 ].i_loc = prev_location ;
2332+ }
23732333 }
23742334 }
23752335 if (is_jump (last )) {
0 commit comments