summaryrefslogtreecommitdiffstats
path: root/Python/flowgraph.c
diff options
context:
space:
mode:
Diffstat (limited to 'Python/flowgraph.c')
-rw-r--r--Python/flowgraph.c51
1 files changed, 51 insertions, 0 deletions
diff --git a/Python/flowgraph.c b/Python/flowgraph.c
index f8039a4..2fd9a85 100644
--- a/Python/flowgraph.c
+++ b/Python/flowgraph.c
@@ -1586,6 +1586,56 @@ optimize_cfg(cfg_builder *g, PyObject *consts, PyObject *const_cache)
return SUCCESS;
}
+static void
+make_super_instruction(cfg_instr *inst1, cfg_instr *inst2, int super_op)
+{
+ int32_t line1 = inst1->i_loc.lineno;
+ int32_t line2 = inst2->i_loc.lineno;
+ /* Skip if instructions are on different lines */
+ if (line1 >= 0 && line2 >= 0 && line1 != line2) {
+ return;
+ }
+ if (inst1->i_oparg >= 16 || inst2->i_oparg >= 16) {
+ return;
+ }
+ INSTR_SET_OP1(inst1, super_op, (inst1->i_oparg << 4) | inst2->i_oparg);
+ INSTR_SET_OP0(inst2, NOP);
+}
+
+static void
+insert_superinstructions(cfg_builder *g)
+{
+ for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
+
+ for (int i = 0; i < b->b_iused; i++) {
+ cfg_instr *inst = &b->b_instr[i];
+ int nextop = i+1 < b->b_iused ? b->b_instr[i+1].i_opcode : 0;
+ switch(inst->i_opcode) {
+ case LOAD_FAST:
+ if (nextop == LOAD_FAST) {
+ make_super_instruction(inst, &b->b_instr[i + 1], LOAD_FAST_LOAD_FAST);
+ }
+ break;
+ case STORE_FAST:
+ switch (nextop) {
+ case LOAD_FAST:
+ make_super_instruction(inst, &b->b_instr[i + 1], STORE_FAST_LOAD_FAST);
+ break;
+ case STORE_FAST:
+ make_super_instruction(inst, &b->b_instr[i + 1], STORE_FAST_STORE_FAST);
+ break;
+ }
+ break;
+ }
+ }
+ }
+ for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
+ remove_redundant_nops(b);
+ }
+ eliminate_empty_basic_blocks(g);
+ assert(no_redundant_nops(g));
+}
+
// helper functions for add_checks_for_loads_of_unknown_variables
static inline void
maybe_push(basicblock *b, uint64_t unsafe_mask, basicblock ***sp)
@@ -2181,6 +2231,7 @@ _PyCfg_OptimizeCodeUnit(cfg_builder *g, PyObject *consts, PyObject *const_cache,
RETURN_IF_ERROR(
add_checks_for_loads_of_uninitialized_variables(
g->g_entryblock, nlocals, nparams));
+ insert_superinstructions(g);
RETURN_IF_ERROR(push_cold_blocks_to_end(g, code_flags));
RETURN_IF_ERROR(resolve_line_numbers(g, firstlineno));