@@ -912,6 +912,19 @@ cfg_builder_use_label(cfg_builder *g, jump_target_label lbl)
912912 return cfg_builder_maybe_start_new_block (g );
913913}
914914
915+ static inline int
916+ basicblock_append_instructions (basicblock * target , basicblock * source )
917+ {
918+ for (int i = 0 ; i < source -> b_iused ; i ++ ) {
919+ int n = basicblock_next_instr (target );
920+ if (n < 0 ) {
921+ return -1 ;
922+ }
923+ target -> b_instr [n ] = source -> b_instr [i ];
924+ }
925+ return 0 ;
926+ }
927+
915928static basicblock *
916929copy_basicblock (cfg_builder * g , basicblock * block )
917930{
@@ -923,12 +936,8 @@ copy_basicblock(cfg_builder *g, basicblock *block)
923936 if (result == NULL ) {
924937 return NULL ;
925938 }
926- for (int i = 0 ; i < block -> b_iused ; i ++ ) {
927- int n = basicblock_next_instr (result );
928- if (n < 0 ) {
929- return NULL ;
930- }
931- result -> b_instr [n ] = block -> b_instr [i ];
939+ if (basicblock_append_instructions (result , block ) < 0 ) {
940+ return NULL ;
932941 }
933942 return result ;
934943}
@@ -7080,15 +7089,14 @@ stackdepth(basicblock *entryblock, int code_flags)
70807089 if (new_depth > maxdepth ) {
70817090 maxdepth = new_depth ;
70827091 }
7083- assert (depth >= 0 ); /* invalid code or bug in stackdepth() */
70847092 if (HAS_TARGET (instr -> i_opcode )) {
70857093 effect = stack_effect (instr -> i_opcode , instr -> i_oparg , 1 );
70867094 assert (effect != PY_INVALID_STACK_EFFECT );
70877095 int target_depth = depth + effect ;
7096+ assert (target_depth >= 0 ); /* invalid code or bug in stackdepth() */
70887097 if (target_depth > maxdepth ) {
70897098 maxdepth = target_depth ;
70907099 }
7091- assert (target_depth >= 0 ); /* invalid code or bug in stackdepth() */
70927100 stackdepth_push (& sp , instr -> i_target , target_depth );
70937101 }
70947102 depth = new_depth ;
@@ -7487,6 +7495,9 @@ convert_exception_handlers_to_nops(basicblock *entryblock) {
74877495 }
74887496 }
74897497 }
7498+ for (basicblock * b = entryblock ; b != NULL ; b = b -> b_next ) {
7499+ remove_redundant_nops (b );
7500+ }
74907501}
74917502
74927503static inline void
@@ -7964,8 +7975,8 @@ scan_block_for_local(int target, basicblock *b, bool unsafe_to_start,
79647975#undef MAYBE_PUSH
79657976
79667977static int
7967- add_checks_for_loads_of_unknown_variables (basicblock * entryblock ,
7968- struct compiler * c )
7978+ add_checks_for_loads_of_uninitialized_variables (basicblock * entryblock ,
7979+ struct compiler * c )
79697980{
79707981 basicblock * * stack = make_cfg_traversal_stack (entryblock );
79717982 if (stack == NULL ) {
@@ -8291,7 +8302,7 @@ dump_basicblock(const basicblock *b)
82918302
82928303
82938304static int
8294- calculate_jump_targets (basicblock * entryblock );
8305+ translate_jump_labels_to_targets (basicblock * entryblock );
82958306
82968307static int
82978308optimize_cfg (cfg_builder * g , PyObject * consts , PyObject * const_cache );
@@ -8628,11 +8639,9 @@ assemble(struct compiler *c, int addNone)
86288639 }
86298640 nlocalsplus -= numdropped ;
86308641
8631- consts = consts_dict_keys_inorder (c -> u -> u_consts );
8632- if (consts == NULL ) {
8633- goto error ;
8634- }
8635- if (calculate_jump_targets (g -> g_entryblock )) {
8642+ /** Preprocessing **/
8643+ /* Map labels to targets and mark exception handlers */
8644+ if (translate_jump_labels_to_targets (g -> g_entryblock )) {
86368645 goto error ;
86378646 }
86388647 if (mark_except_handlers (g -> g_entryblock ) < 0 ) {
@@ -8641,18 +8650,31 @@ assemble(struct compiler *c, int addNone)
86418650 if (label_exception_targets (g -> g_entryblock )) {
86428651 goto error ;
86438652 }
8653+
8654+ /** Optimization **/
8655+ consts = consts_dict_keys_inorder (c -> u -> u_consts );
8656+ if (consts == NULL ) {
8657+ goto error ;
8658+ }
86448659 if (optimize_cfg (g , consts , c -> c_const_cache )) {
86458660 goto error ;
86468661 }
8647- if (trim_unused_consts (g -> g_entryblock , consts ) ) {
8662+ if (add_checks_for_loads_of_uninitialized_variables (g -> g_entryblock , c ) < 0 ) {
86488663 goto error ;
86498664 }
8665+
8666+ /** line numbers (TODO: move this before optimization stage) */
86508667 if (duplicate_exits_without_lineno (g ) < 0 ) {
86518668 goto error ;
86528669 }
86538670 propagate_line_numbers (g -> g_entryblock );
86548671 guarantee_lineno_for_exits (g -> g_entryblock , c -> u -> u_firstlineno );
86558672
8673+ if (push_cold_blocks_to_end (g , code_flags ) < 0 ) {
8674+ goto error ;
8675+ }
8676+
8677+ /** Assembly **/
86568678 int maxdepth = stackdepth (g -> g_entryblock , code_flags );
86578679 if (maxdepth < 0 ) {
86588680 goto error ;
@@ -8661,27 +8683,19 @@ assemble(struct compiler *c, int addNone)
86618683
86628684 convert_exception_handlers_to_nops (g -> g_entryblock );
86638685
8664- if (push_cold_blocks_to_end (g , code_flags ) < 0 ) {
8665- goto error ;
8666- }
8667- for (basicblock * b = g -> g_entryblock ; b != NULL ; b = b -> b_next ) {
8668- remove_redundant_nops (b );
8669- }
8670-
86718686 /* Order of basic blocks must have been determined by now */
86728687 if (normalize_jumps (g ) < 0 ) {
86738688 goto error ;
86748689 }
86758690
8676- if (add_checks_for_loads_of_unknown_variables (g -> g_entryblock , c ) < 0 ) {
8677- goto error ;
8678- }
8679-
86808691 assert (no_redundant_jumps (g ));
86818692
86828693 /* Can't modify the bytecode after computing jump offsets. */
86838694 assemble_jump_offsets (g -> g_entryblock );
86848695
8696+ if (trim_unused_consts (g -> g_entryblock , consts )) {
8697+ goto error ;
8698+ }
86858699
86868700 /* Create assembler */
86878701 if (!assemble_init (& a , c -> u -> u_firstlineno ))
@@ -9265,12 +9279,8 @@ inline_small_exit_blocks(basicblock *bb) {
92659279 basicblock * target = last -> i_target ;
92669280 if (basicblock_exits_scope (target ) && target -> b_iused <= MAX_COPY_SIZE ) {
92679281 last -> i_opcode = NOP ;
9268- for (int i = 0 ; i < target -> b_iused ; i ++ ) {
9269- int index = basicblock_next_instr (bb );
9270- if (index < 0 ) {
9271- return -1 ;
9272- }
9273- bb -> b_instr [index ] = target -> b_instr [i ];
9282+ if (basicblock_append_instructions (bb , target ) < 0 ) {
9283+ return -1 ;
92749284 }
92759285 return 1 ;
92769286 }
@@ -9456,7 +9466,7 @@ propagate_line_numbers(basicblock *entryblock) {
94569466
94579467/* Calculate the actual jump target from the target_label */
94589468static int
9459- calculate_jump_targets (basicblock * entryblock )
9469+ translate_jump_labels_to_targets (basicblock * entryblock )
94609470{
94619471 int max_label = -1 ;
94629472 for (basicblock * b = entryblock ; b != NULL ; b = b -> b_next ) {
@@ -9599,12 +9609,14 @@ is_exit_without_lineno(basicblock *b) {
95999609static int
96009610duplicate_exits_without_lineno (cfg_builder * g )
96019611{
9612+ assert (no_empty_basic_blocks (g ));
96029613 /* Copy all exit blocks without line number that are targets of a jump.
96039614 */
96049615 basicblock * entryblock = g -> g_entryblock ;
96059616 for (basicblock * b = entryblock ; b != NULL ; b = b -> b_next ) {
96069617 struct instr * last = basicblock_last_instr (b );
9607- if (last != NULL && is_jump (last )) {
9618+ assert (last != NULL );
9619+ if (is_jump (last )) {
96089620 basicblock * target = last -> i_target ;
96099621 if (is_exit_without_lineno (target ) && target -> b_predecessors > 1 ) {
96109622 basicblock * new_target = copy_basicblock (g , target );
@@ -9621,8 +9633,6 @@ duplicate_exits_without_lineno(cfg_builder *g)
96219633 }
96229634 }
96239635
9624- assert (no_empty_basic_blocks (g ));
9625-
96269636 /* Any remaining reachable exit blocks without line number can only be reached by
96279637 * fall through, and thus can only have a single predecessor */
96289638 for (basicblock * b = entryblock ; b != NULL ; b = b -> b_next ) {
@@ -9775,7 +9785,7 @@ _PyCompile_OptimizeCfg(PyObject *instructions, PyObject *consts)
97759785 if (const_cache == NULL ) {
97769786 goto error ;
97779787 }
9778- if (calculate_jump_targets (g .g_entryblock )) {
9788+ if (translate_jump_labels_to_targets (g .g_entryblock )) {
97799789 goto error ;
97809790 }
97819791 if (optimize_cfg (& g , consts , const_cache ) < 0 ) {
0 commit comments