mirror of
https://github.com/python/cpython.git
synced 2025-08-22 09:45:06 +00:00
gh-107901: duplicate blocks with no lineno that have an eval break and multiple predecessors (#113950)
This commit is contained in:
parent
e02c15b3f1
commit
8aa0088ea2
3 changed files with 38 additions and 10 deletions
|
@ -316,6 +316,16 @@ basicblock_exits_scope(const basicblock *b) {
|
|||
return last && IS_SCOPE_EXIT_OPCODE(last->i_opcode);
|
||||
}
|
||||
|
||||
static inline int
|
||||
basicblock_has_eval_break(const basicblock *b) {
|
||||
for (int i = 0; i < b->b_iused; i++) {
|
||||
if (OPCODE_HAS_EVAL_BREAK(b->b_instr[i].i_opcode)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
cfg_builder_current_block_is_terminated(cfg_builder *g)
|
||||
{
|
||||
|
@ -2246,16 +2256,18 @@ convert_pseudo_ops(basicblock *entryblock)
|
|||
}
|
||||
|
||||
static inline bool
|
||||
is_exit_without_lineno(basicblock *b) {
|
||||
if (!basicblock_exits_scope(b)) {
|
||||
is_exit_or_eval_check_without_lineno(basicblock *b) {
|
||||
if (basicblock_exits_scope(b) || basicblock_has_eval_break(b)) {
|
||||
for (int i = 0; i < b->b_iused; i++) {
|
||||
if (b->b_instr[i].i_loc.lineno >= 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < b->b_iused; i++) {
|
||||
if (b->b_instr[i].i_loc.lineno >= 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
@ -2283,7 +2295,7 @@ duplicate_exits_without_lineno(cfg_builder *g)
|
|||
}
|
||||
if (is_jump(last)) {
|
||||
basicblock *target = next_nonempty_block(last->i_target);
|
||||
if (is_exit_without_lineno(target) && target->b_predecessors > 1) {
|
||||
if (is_exit_or_eval_check_without_lineno(target) && target->b_predecessors > 1) {
|
||||
basicblock *new_target = copy_basicblock(g, target);
|
||||
if (new_target == NULL) {
|
||||
return ERROR;
|
||||
|
@ -2303,7 +2315,7 @@ duplicate_exits_without_lineno(cfg_builder *g)
|
|||
* fall through, and thus can only have a single predecessor */
|
||||
for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
|
||||
if (BB_HAS_FALLTHROUGH(b) && b->b_next && b->b_iused > 0) {
|
||||
if (is_exit_without_lineno(b->b_next)) {
|
||||
if (is_exit_or_eval_check_without_lineno(b->b_next)) {
|
||||
cfg_instr *last = basicblock_last_instr(b);
|
||||
assert(last != NULL);
|
||||
b->b_next->b_instr[0].i_loc = last->i_loc;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue