@@ -464,14 +464,13 @@ no_redundant_nops(cfg_builder *g) {
464
464
return true;
465
465
}
466
466
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
- }
467
+ static basicblock *
468
+ next_nonempty_block (basicblock * b )
469
+ {
470
+ while (b && b -> b_iused == 0 ) {
471
+ b = b -> b_next ;
473
472
}
474
- return true ;
473
+ return b ;
475
474
}
476
475
477
476
static bool
@@ -480,8 +479,10 @@ no_redundant_jumps(cfg_builder *g) {
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 );
@@ -1773,9 +1726,15 @@ optimize_cfg(cfg_builder *g, PyObject *consts, PyObject *const_cache)
1773
1726
for (basicblock * b = g -> g_entryblock ; b != NULL ; b = b -> b_next ) {
1774
1727
remove_redundant_nops (b );
1775
1728
}
1776
- eliminate_empty_basic_blocks (g );
1777
- assert (no_redundant_nops (g ));
1778
1729
RETURN_IF_ERROR (remove_redundant_jumps (g ));
1730
+
1731
+ for (basicblock * b = g -> g_entryblock ; b != NULL ; b = b -> b_next ) {
1732
+ remove_redundant_nops (b );
1733
+ }
1734
+
1735
+ RETURN_IF_ERROR (remove_redundant_jumps (g ));
1736
+
1737
+ assert (no_redundant_jumps (g ));
1779
1738
return SUCCESS ;
1780
1739
}
1781
1740
@@ -1825,7 +1784,6 @@ insert_superinstructions(cfg_builder *g)
1825
1784
for (basicblock * b = g -> g_entryblock ; b != NULL ; b = b -> b_next ) {
1826
1785
remove_redundant_nops (b );
1827
1786
}
1828
- eliminate_empty_basic_blocks (g );
1829
1787
assert (no_redundant_nops (g ));
1830
1788
}
1831
1789
@@ -2299,18 +2257,18 @@ is_exit_without_lineno(basicblock *b) {
2299
2257
static int
2300
2258
duplicate_exits_without_lineno (cfg_builder * g )
2301
2259
{
2302
- assert (no_empty_basic_blocks (g ));
2303
-
2304
2260
int next_lbl = get_max_label (g -> g_entryblock ) + 1 ;
2305
2261
2306
2262
/* Copy all exit blocks without line number that are targets of a jump.
2307
2263
*/
2308
2264
basicblock * entryblock = g -> g_entryblock ;
2309
2265
for (basicblock * b = entryblock ; b != NULL ; b = b -> b_next ) {
2310
2266
cfg_instr * last = basicblock_last_instr (b );
2311
- assert (last != NULL );
2267
+ if (last == NULL ) {
2268
+ continue ;
2269
+ }
2312
2270
if (is_jump (last )) {
2313
- basicblock * target = last -> i_target ;
2271
+ basicblock * target = next_nonempty_block ( last -> i_target ) ;
2314
2272
if (is_exit_without_lineno (target ) && target -> b_predecessors > 1 ) {
2315
2273
basicblock * new_target = copy_basicblock (g , target );
2316
2274
if (new_target == NULL ) {
@@ -2367,9 +2325,10 @@ propagate_line_numbers(basicblock *entryblock) {
2367
2325
}
2368
2326
}
2369
2327
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 ;
2328
+ if (b -> b_next -> b_iused > 0 ) {
2329
+ if (b -> b_next -> b_instr [0 ].i_loc .lineno < 0 ) {
2330
+ b -> b_next -> b_instr [0 ].i_loc = prev_location ;
2331
+ }
2373
2332
}
2374
2333
}
2375
2334
if (is_jump (last )) {
0 commit comments