@@ -212,14 +212,14 @@ basicblock_add_jump(basicblock *b, int opcode, basicblock *target, location loc)
212212}
213213
214214static inline int
215- basicblock_append_instructions (basicblock * target ,basicblock * source )
215+ basicblock_append_instructions (basicblock * to ,basicblock * from )
216216{
217- for (int i = 0 ;i < source -> b_iused ;i ++ ) {
218- int n = basicblock_next_instr (target );
217+ for (int i = 0 ;i < from -> b_iused ;i ++ ) {
218+ int n = basicblock_next_instr (to );
219219if (n < 0 ) {
220220return ERROR ;
221221 }
222- target -> b_instr [n ]= source -> b_instr [i ];
222+ to -> b_instr [n ]= from -> b_instr [i ];
223223 }
224224return SUCCESS ;
225225}
@@ -292,9 +292,9 @@ static void
292292dump_basicblock (const basicblock * b )
293293{
294294const char * b_return = basicblock_returns (b ) ?"return " :"" ;
295- fprintf (stderr ,"%d: [EH=%d CLD=%d WRM=%d NO_FT=%d %p] used: %d, depth: %d, %s\n" ,
295+ fprintf (stderr ,"%d: [EH=%d CLD=%d WRM=%d NO_FT=%d %p] used: %d, depth: %d,preds: %d %s\n" ,
296296b -> b_label .id ,b -> b_except_handler ,b -> b_cold ,b -> b_warm ,BB_NO_FALLTHROUGH (b ),b ,b -> b_iused ,
297- b -> b_startdepth ,b_return );
297+ b -> b_startdepth ,b -> b_predecessors , b_return );
298298if (b -> b_instr ) {
299299int i ;
300300for (i = 0 ;i < b -> b_iused ;i ++ ) {
@@ -1165,15 +1165,26 @@ remove_redundant_jumps(cfg_builder *g) {
11651165return changes ;
11661166}
11671167
1168+ static inline bool
1169+ basicblock_has_no_lineno (basicblock * b ) {
1170+ for (int i = 0 ;i < b -> b_iused ;i ++ ) {
1171+ if (b -> b_instr [i ].i_loc .lineno >=0 ) {
1172+ return false;
1173+ }
1174+ }
1175+ return true;
1176+ }
1177+
11681178/* Maximum size of basic block that should be copied in optimizer */
11691179#define MAX_COPY_SIZE 4
11701180
1171- /* If this block ends with an unconditional jump to a small exit block, then
1181+ /* If this block ends with an unconditional jump to a small exit block or
1182+ * a block that has no line numbers (and no fallthrough), then
11721183 * remove the jump and extend this block with the target.
11731184 * Returns 1 if extended, 0 if no change, and -1 on error.
11741185 */
11751186static int
1176- inline_small_exit_blocks (basicblock * bb ) {
1187+ basicblock_inline_small_or_no_lineno_blocks (basicblock * bb ) {
11771188cfg_instr * last = basicblock_last_instr (bb );
11781189if (last == NULL ) {
11791190return 0 ;
@@ -1182,14 +1193,46 @@ inline_small_exit_blocks(basicblock *bb) {
11821193return 0 ;
11831194 }
11841195basicblock * target = last -> i_target ;
1185- if (basicblock_exits_scope (target )&& target -> b_iused <=MAX_COPY_SIZE ) {
1196+ bool small_exit_block = (basicblock_exits_scope (target )&&
1197+ target -> b_iused <=MAX_COPY_SIZE );
1198+ bool no_lineno_no_fallthrough = (basicblock_has_no_lineno (target )&&
1199+ !BB_HAS_FALLTHROUGH (target ));
1200+ if (small_exit_block || no_lineno_no_fallthrough ) {
1201+ assert (is_jump (last ));
1202+ int removed_jump_opcode = last -> i_opcode ;
11861203INSTR_SET_OP0 (last ,NOP );
11871204RETURN_IF_ERROR (basicblock_append_instructions (bb ,target ));
1205+ if (no_lineno_no_fallthrough ) {
1206+ last = basicblock_last_instr (bb );
1207+ if (IS_UNCONDITIONAL_JUMP_OPCODE (last -> i_opcode )&&
1208+ removed_jump_opcode == JUMP )
1209+ {
1210+ /* Make sure we don't lose eval breaker checks */
1211+ last -> i_opcode = JUMP ;
1212+ }
1213+ }
1214+ target -> b_predecessors -- ;
11881215return 1 ;
11891216 }
11901217return 0 ;
11911218}
11921219
1220+ static int
1221+ inline_small_or_no_lineno_blocks (basicblock * entryblock ) {
1222+ bool changes ;
1223+ do {
1224+ changes = false;
1225+ for (basicblock * b = entryblock ;b != NULL ;b = b -> b_next ) {
1226+ int res = basicblock_inline_small_or_no_lineno_blocks (b );
1227+ RETURN_IF_ERROR (res );
1228+ if (res ) {
1229+ changes = true;
1230+ }
1231+ }
1232+ }while (changes );/* every change removes a jump, ensuring convergence */
1233+ return changes ;
1234+ }
1235+
11931236// Attempt to eliminate jumps to jumps by updating inst to jump to
11941237// target->i_target using the provided opcode. Return whether or not the
11951238// optimization was successful.
@@ -1804,19 +1847,14 @@ optimize_cfg(cfg_builder *g, PyObject *consts, PyObject *const_cache, int firstl
18041847{
18051848assert (PyDict_CheckExact (const_cache ));
18061849RETURN_IF_ERROR (check_cfg (g ));
1807- for (basicblock * b = g -> g_entryblock ;b != NULL ;b = b -> b_next ) {
1808- RETURN_IF_ERROR (inline_small_exit_blocks (b ));
1809- }
1850+ RETURN_IF_ERROR (inline_small_or_no_lineno_blocks (g -> g_entryblock ));
18101851RETURN_IF_ERROR (remove_unreachable (g -> g_entryblock ));
18111852RETURN_IF_ERROR (resolve_line_numbers (g ,firstlineno ));
18121853RETURN_IF_ERROR (optimize_load_const (const_cache ,g ,consts ));
18131854for (basicblock * b = g -> g_entryblock ;b != NULL ;b = b -> b_next ) {
18141855RETURN_IF_ERROR (optimize_basic_block (const_cache ,b ,consts ));
18151856 }
18161857RETURN_IF_ERROR (remove_redundant_nops_and_pairs (g -> g_entryblock ));
1817- for (basicblock * b = g -> g_entryblock ;b != NULL ;b = b -> b_next ) {
1818- RETURN_IF_ERROR (inline_small_exit_blocks (b ));
1819- }
18201858RETURN_IF_ERROR (remove_unreachable (g -> g_entryblock ));
18211859
18221860int removed_nops ,removed_jumps ;
@@ -2333,12 +2371,7 @@ convert_pseudo_ops(cfg_builder *g)
23332371static inline bool
23342372is_exit_or_eval_check_without_lineno (basicblock * b ) {
23352373if (basicblock_exits_scope (b )|| basicblock_has_eval_break (b )) {
2336- for (int i = 0 ;i < b -> b_iused ;i ++ ) {
2337- if (b -> b_instr [i ].i_loc .lineno >=0 ) {
2338- return false;
2339- }
2340- }
2341- return true;
2374+ return basicblock_has_no_lineno (b );
23422375 }
23432376else {
23442377return false;