@@ -449,6 +449,15 @@ _PyCfgBuilder_Addop(cfg_builder *g, int opcode, int oparg, location loc)
449
449
}
450
450
451
451
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
+
452
461
/***** debugging helpers *****/
453
462
454
463
#ifndef NDEBUG
@@ -464,24 +473,16 @@ no_redundant_nops(cfg_builder *g) {
464
473
return true;
465
474
}
466
475
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
-
477
476
static bool
478
477
no_redundant_jumps (cfg_builder * g ) {
479
478
for (basicblock * b = g -> g_entryblock ; b != NULL ; b = b -> b_next ) {
480
479
cfg_instr * last = basicblock_last_instr (b );
481
480
if (last != NULL ) {
482
481
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 ) {
485
486
return false;
486
487
}
487
488
}
@@ -961,42 +962,6 @@ mark_reachable(basicblock *entryblock) {
961
962
return SUCCESS ;
962
963
}
963
964
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
-
1000
965
static int
1001
966
remove_redundant_nops (basicblock * bb ) {
1002
967
/* Remove NOPs when legal to do so. */
@@ -1025,10 +990,7 @@ remove_redundant_nops(basicblock *bb) {
1025
990
}
1026
991
}
1027
992
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 );
1032
994
/* or if last instruction in BB and next BB has same line number */
1033
995
if (next ) {
1034
996
location next_loc = NO_LOCATION ;
@@ -1112,36 +1074,29 @@ remove_redundant_jumps(cfg_builder *g) {
1112
1074
* can be deleted.
1113
1075
*/
1114
1076
1115
- assert (no_empty_basic_blocks (g ));
1116
-
1117
- bool remove_empty_blocks = false;
1118
1077
for (basicblock * b = g -> g_entryblock ; b != NULL ; b = b -> b_next ) {
1119
1078
cfg_instr * last = basicblock_last_instr (b );
1120
- assert (last != NULL );
1079
+ if (last == NULL ) {
1080
+ continue ;
1081
+ }
1121
1082
assert (!IS_ASSEMBLER_OPCODE (last -> i_opcode ));
1122
1083
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 ) {
1124
1086
PyErr_SetString (PyExc_SystemError , "jump with NULL target" );
1125
1087
return ERROR ;
1126
1088
}
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 ) {
1129
1091
if (last -> i_loc .lineno == NO_LOCATION .lineno ) {
1130
1092
b -> b_iused -- ;
1131
- if (b -> b_iused == 0 ) {
1132
- remove_empty_blocks = true;
1133
- }
1134
1093
}
1135
1094
else {
1136
1095
INSTR_SET_OP0 (last , NOP );
1137
1096
}
1138
1097
}
1139
1098
}
1140
1099
}
1141
- if (remove_empty_blocks ) {
1142
- eliminate_empty_basic_blocks (g );
1143
- }
1144
- assert (no_empty_basic_blocks (g ));
1145
1100
return SUCCESS ;
1146
1101
}
1147
1102
@@ -1749,11 +1704,9 @@ optimize_cfg(cfg_builder *g, PyObject *consts, PyObject *const_cache)
1749
1704
{
1750
1705
assert (PyDict_CheckExact (const_cache ));
1751
1706
RETURN_IF_ERROR (check_cfg (g ));
1752
- eliminate_empty_basic_blocks (g );
1753
1707
for (basicblock * b = g -> g_entryblock ; b != NULL ; b = b -> b_next ) {
1754
1708
RETURN_IF_ERROR (inline_small_exit_blocks (b ));
1755
1709
}
1756
- assert (no_empty_basic_blocks (g ));
1757
1710
for (basicblock * b = g -> g_entryblock ; b != NULL ; b = b -> b_next ) {
1758
1711
RETURN_IF_ERROR (optimize_basic_block (const_cache , b , consts ));
1759
1712
assert (b -> b_predecessors == 0 );
@@ -1768,14 +1721,21 @@ optimize_cfg(cfg_builder *g, PyObject *consts, PyObject *const_cache)
1768
1721
for (basicblock * b = g -> g_entryblock ; b != NULL ; b = b -> b_next ) {
1769
1722
if (b -> b_predecessors == 0 ) {
1770
1723
b -> b_iused = 0 ;
1724
+ b -> b_except_handler = 0 ;
1771
1725
}
1772
1726
}
1773
1727
for (basicblock * b = g -> g_entryblock ; b != NULL ; b = b -> b_next ) {
1774
1728
remove_redundant_nops (b );
1775
1729
}
1776
- eliminate_empty_basic_blocks (g );
1777
- assert (no_redundant_nops (g ));
1778
1730
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 ));
1779
1739
return SUCCESS ;
1780
1740
}
1781
1741
@@ -1825,7 +1785,6 @@ insert_superinstructions(cfg_builder *g)
1825
1785
for (basicblock * b = g -> g_entryblock ; b != NULL ; b = b -> b_next ) {
1826
1786
remove_redundant_nops (b );
1827
1787
}
1828
- eliminate_empty_basic_blocks (g );
1829
1788
assert (no_redundant_nops (g ));
1830
1789
}
1831
1790
@@ -2299,18 +2258,18 @@ is_exit_without_lineno(basicblock *b) {
2299
2258
static int
2300
2259
duplicate_exits_without_lineno (cfg_builder * g )
2301
2260
{
2302
- assert (no_empty_basic_blocks (g ));
2303
-
2304
2261
int next_lbl = get_max_label (g -> g_entryblock ) + 1 ;
2305
2262
2306
2263
/* Copy all exit blocks without line number that are targets of a jump.
2307
2264
*/
2308
2265
basicblock * entryblock = g -> g_entryblock ;
2309
2266
for (basicblock * b = entryblock ; b != NULL ; b = b -> b_next ) {
2310
2267
cfg_instr * last = basicblock_last_instr (b );
2311
- assert (last != NULL );
2268
+ if (last == NULL ) {
2269
+ continue ;
2270
+ }
2312
2271
if (is_jump (last )) {
2313
- basicblock * target = last -> i_target ;
2272
+ basicblock * target = next_nonempty_block ( last -> i_target ) ;
2314
2273
if (is_exit_without_lineno (target ) && target -> b_predecessors > 1 ) {
2315
2274
basicblock * new_target = copy_basicblock (g , target );
2316
2275
if (new_target == NULL ) {
@@ -2367,9 +2326,10 @@ propagate_line_numbers(basicblock *entryblock) {
2367
2326
}
2368
2327
}
2369
2328
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
+ }
2373
2333
}
2374
2334
}
2375
2335
if (is_jump (last )) {
0 commit comments