From a4318f38a853c70f5524af657264fc8baba8cf0d Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Tue, 21 Jun 2022 12:04:27 +0100 Subject: [PATCH 1/6] fix two obsolete comments --- Python/compile.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Python/compile.c b/Python/compile.c index 427fb2a369481f..ba5e5dd3e2b478 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -9323,8 +9323,8 @@ clean_basic_block(basicblock *bb) { static int normalize_basic_block(basicblock *bb) { - /* Mark blocks as exit and/or nofallthrough. - Raise SystemError if CFG is malformed. */ + /* Skip over empty blocks. + * Raise SystemError if jump or exit is not last instruction in the block. */ for (int i = 0; i < bb->b_iused; i++) { int opcode = bb->b_instr[i].i_opcode; assert(!IS_ASSEMBLER_OPCODE(opcode)); @@ -9461,8 +9461,7 @@ propagate_line_numbers(basicblock *entryblock) { The consts object should still be in list form to allow new constants to be appended. - All transformations keep the code size the same or smaller. - For those that reduce size, the gaps are initially filled with + Code trasnformations that reduce code size initially fill the gaps with NOPs. Later those NOPs are removed. */ From 5ee8651f8918942c64f7eb9ffad7a43440e10533 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Tue, 21 Jun 2022 13:24:36 +0100 Subject: [PATCH 2/6] move normalize_basic_block and extend_block into optimize_cfg, nased on b_next links. Group lineno stuff together --- Python/compile.c | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/Python/compile.c b/Python/compile.c index ba5e5dd3e2b478..3a07550db7138a 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -8553,18 +8553,6 @@ assemble(struct compiler *c, int addNone) ADDOP(c, RETURN_VALUE); } - for (basicblock *b = c->u->u_blocks; b != NULL; b = b->b_list) { - if (normalize_basic_block(b)) { - return NULL; - } - } - - for (basicblock *b = c->u->u_blocks; b != NULL; b = b->b_list) { - if (extend_block(b)) { - return NULL; - } - } - assert(PyDict_GET_SIZE(c->u->u_varnames) < INT_MAX); assert(PyDict_GET_SIZE(c->u->u_cellvars) < INT_MAX); assert(PyDict_GET_SIZE(c->u->u_freevars) < INT_MAX); @@ -8622,12 +8610,12 @@ assemble(struct compiler *c, int addNone) if (optimize_cfg(entryblock, consts, c->c_const_cache)) { goto error; } - if (duplicate_exits_without_lineno(entryblock)) { - return NULL; - } if (trim_unused_consts(entryblock, consts)) { goto error; } + if (duplicate_exits_without_lineno(entryblock)) { + return NULL; + } propagate_line_numbers(entryblock); guarantee_lineno_for_exits(entryblock, c->u->u_firstlineno); @@ -9469,6 +9457,16 @@ static int optimize_cfg(basicblock *entryblock, PyObject *consts, PyObject *const_cache) { assert(PyDict_CheckExact(const_cache)); + for (basicblock *b = entryblock; b != NULL; b = b->b_next) { + if (normalize_basic_block(b)) { + return -1; + } + } + for (basicblock *b = entryblock; b != NULL; b = b->b_next) { + if (extend_block(b)) { + return -1; + } + } for (basicblock *b = entryblock; b != NULL; b = b->b_next) { if (optimize_basic_block(const_cache, b, consts)) { return -1; From 68abebf2e2b28227b12c5440f8776743f77a92d6 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Tue, 21 Jun 2022 17:47:04 +0100 Subject: [PATCH 3/6] is_end_of_basic_block --> IS_END_OF_BASICBLOCK_OPCODE --- Python/compile.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/Python/compile.c b/Python/compile.c index 3a07550db7138a..725fd3645242b9 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -85,6 +85,9 @@ (opcode) == SETUP_WITH || \ (opcode) == SETUP_CLEANUP) +#define IS_END_OF_BASICBLOCK_OPCODE(opcode) \ + (IS_JUMP_OPCODE(opcode) || IS_SCOPE_EXIT_OPCODE(opcode)) + /* opcodes which are not emitted in codegen stage, only by the assembler */ #define IS_ASSEMBLER_OPCODE(opcode) \ ((opcode) == JUMP_FORWARD || \ @@ -1243,18 +1246,12 @@ PyCompile_OpcodeStackEffect(int opcode, int oparg) return stack_effect(opcode, oparg, -1); } -static int -is_end_of_basic_block(struct instr *instr) -{ - int opcode = instr->i_opcode; - return IS_JUMP_OPCODE(opcode) || IS_SCOPE_EXIT_OPCODE(opcode); -} - static int compiler_use_new_implicit_block_if_needed(struct compiler *c) { basicblock *b = c->u->u_curblock; - if (b->b_iused && is_end_of_basic_block(basicblock_last_instr(b))) { + struct instr *last = basicblock_last_instr(b); + if (last && IS_END_OF_BASICBLOCK_OPCODE(last->i_opcode)) { basicblock *b = compiler_new_block(c); if (b == NULL) { return -1; From a0b64b8a3e2cc775bec3b2a9964b159fc650791f Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Tue, 19 Jul 2022 11:23:30 +0100 Subject: [PATCH 4/6] IS_END_OF_BASICBLOCK_OPCODE -> IS_TERMINTATOR_OPCODE --- Python/compile.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Python/compile.c b/Python/compile.c index 725fd3645242b9..e46a8fde6ef9db 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -85,7 +85,8 @@ (opcode) == SETUP_WITH || \ (opcode) == SETUP_CLEANUP) -#define IS_END_OF_BASICBLOCK_OPCODE(opcode) \ +/* opcodes that must be last in the basicblock */ +#define IS_TERMINTATOR_OPCODE(opcode) \ (IS_JUMP_OPCODE(opcode) || IS_SCOPE_EXIT_OPCODE(opcode)) /* opcodes which are not emitted in codegen stage, only by the assembler */ @@ -1251,7 +1252,7 @@ compiler_use_new_implicit_block_if_needed(struct compiler *c) { basicblock *b = c->u->u_curblock; struct instr *last = basicblock_last_instr(b); - if (last && IS_END_OF_BASICBLOCK_OPCODE(last->i_opcode)) { + if (last && IS_TERMINTATOR_OPCODE(last->i_opcode)) { basicblock *b = compiler_new_block(c); if (b == NULL) { return -1; From ba398ecb6e9c9762d0dfaffe160de84184ed89a0 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Tue, 19 Jul 2022 13:06:01 +0100 Subject: [PATCH 5/6] add a few missing const qualifiers --- Python/compile.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Python/compile.c b/Python/compile.c index e46a8fde6ef9db..ad1031f90f6f34 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -266,7 +266,7 @@ typedef struct basicblock_ { static struct instr * -basicblock_last_instr(basicblock *b) { +basicblock_last_instr(const basicblock *b) { if (b->b_iused) { return &b->b_instr[b->b_iused - 1]; } @@ -274,19 +274,19 @@ basicblock_last_instr(basicblock *b) { } static inline int -basicblock_returns(basicblock *b) { +basicblock_returns(const basicblock *b) { struct instr *last = basicblock_last_instr(b); return last && last->i_opcode == RETURN_VALUE; } static inline int -basicblock_exits_scope(basicblock *b) { +basicblock_exits_scope(const basicblock *b) { struct instr *last = basicblock_last_instr(b); return last && IS_SCOPE_EXIT_OPCODE(last->i_opcode); } static inline int -basicblock_nofallthrough(basicblock *b) { +basicblock_nofallthrough(const basicblock *b) { struct instr *last = basicblock_last_instr(b); return (last && (IS_SCOPE_EXIT_OPCODE(last->i_opcode) || From 8fb9d541e0f79059a028660b7fea5a25e22f1208 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Tue, 19 Jul 2022 15:48:35 +0100 Subject: [PATCH 6/6] IS_TERMINTATOR_OPCODE --> IS_TERMINATOR_OPCODE --- Python/compile.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Python/compile.c b/Python/compile.c index ad1031f90f6f34..30d8fdbb969ba3 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -86,7 +86,7 @@ (opcode) == SETUP_CLEANUP) /* opcodes that must be last in the basicblock */ -#define IS_TERMINTATOR_OPCODE(opcode) \ +#define IS_TERMINATOR_OPCODE(opcode) \ (IS_JUMP_OPCODE(opcode) || IS_SCOPE_EXIT_OPCODE(opcode)) /* opcodes which are not emitted in codegen stage, only by the assembler */ @@ -1252,7 +1252,7 @@ compiler_use_new_implicit_block_if_needed(struct compiler *c) { basicblock *b = c->u->u_curblock; struct instr *last = basicblock_last_instr(b); - if (last && IS_TERMINTATOR_OPCODE(last->i_opcode)) { + if (last && IS_TERMINATOR_OPCODE(last->i_opcode)) { basicblock *b = compiler_new_block(c); if (b == NULL) { return -1;