summaryrefslogtreecommitdiffstats
path: root/Python
diff options
context:
space:
mode:
Diffstat (limited to 'Python')
-rw-r--r--Python/bytecodes.c8
-rw-r--r--Python/codegen.c6
-rw-r--r--Python/flowgraph.c73
3 files changed, 81 insertions, 6 deletions
diff --git a/Python/bytecodes.c b/Python/bytecodes.c
index 5f194ae..bf8f6af 100644
--- a/Python/bytecodes.c
+++ b/Python/bytecodes.c
@@ -2570,6 +2570,14 @@ dummy_func(
JUMP_BACKWARD_NO_INTERRUPT,
};
+ pseudo(JUMP_IF_FALSE, (cond -- cond)) = [
+ COPY, TO_BOOL, POP_JUMP_IF_FALSE,
+ ];
+
+ pseudo(JUMP_IF_TRUE, (cond -- cond)) = [
+ COPY, TO_BOOL, POP_JUMP_IF_TRUE,
+ ];
+
tier1 inst(ENTER_EXECUTOR, (--)) {
#ifdef _Py_TIER2
PyCodeObject *code = _PyFrame_GetCode(frame);
diff --git a/Python/codegen.c b/Python/codegen.c
index 0305f42..896c30c 100644
--- a/Python/codegen.c
+++ b/Python/codegen.c
@@ -3140,17 +3140,15 @@ codegen_boolop(compiler *c, expr_ty e)
location loc = LOC(e);
assert(e->kind == BoolOp_kind);
if (e->v.BoolOp.op == And)
- jumpi = POP_JUMP_IF_FALSE;
+ jumpi = JUMP_IF_FALSE;
else
- jumpi = POP_JUMP_IF_TRUE;
+ jumpi = JUMP_IF_TRUE;
NEW_JUMP_TARGET_LABEL(c, end);
s = e->v.BoolOp.values;
n = asdl_seq_LEN(s) - 1;
assert(n >= 0);
for (i = 0; i < n; ++i) {
VISIT(c, expr, (expr_ty)asdl_seq_GET(s, i));
- ADDOP_I(c, loc, COPY, 1);
- ADDOP(c, loc, TO_BOOL);
ADDOP_JUMP(c, loc, jumpi, end);
ADDOP(c, loc, POP_TOP);
}
diff --git a/Python/flowgraph.c b/Python/flowgraph.c
index f7d8efb..69d7e0a 100644
--- a/Python/flowgraph.c
+++ b/Python/flowgraph.c
@@ -1589,6 +1589,8 @@ basicblock_optimize_load_const(PyObject *const_cache, basicblock *bb, PyObject *
switch(nextop) {
case POP_JUMP_IF_FALSE:
case POP_JUMP_IF_TRUE:
+ case JUMP_IF_FALSE:
+ case JUMP_IF_TRUE:
{
/* Remove LOAD_CONST const; conditional jump */
PyObject* cnt = get_const_value(opcode, oparg, consts);
@@ -1600,8 +1602,11 @@ basicblock_optimize_load_const(PyObject *const_cache, basicblock *bb, PyObject *
if (is_true == -1) {
return ERROR;
}
- INSTR_SET_OP0(inst, NOP);
- int jump_if_true = nextop == POP_JUMP_IF_TRUE;
+ if (PyCompile_OpcodeStackEffect(nextop, 0) == -1) {
+ /* POP_JUMP_IF_FALSE or POP_JUMP_IF_TRUE */
+ INSTR_SET_OP0(inst, NOP);
+ }
+ int jump_if_true = (nextop == POP_JUMP_IF_TRUE || nextop == JUMP_IF_TRUE);
if (is_true == jump_if_true) {
bb->b_instr[i+1].i_opcode = JUMP;
}
@@ -1761,6 +1766,36 @@ optimize_basic_block(PyObject *const_cache, basicblock *bb, PyObject *consts)
i -= jump_thread(bb, inst, target, POP_JUMP_IF_TRUE);
}
break;
+ case JUMP_IF_FALSE:
+ switch (target->i_opcode) {
+ case JUMP:
+ case JUMP_IF_FALSE:
+ i -= jump_thread(bb, inst, target, JUMP_IF_FALSE);
+ continue;
+ case JUMP_IF_TRUE:
+ // No need to check for loops here, a block's b_next
+ // cannot point to itself.
+ assert(inst->i_target != inst->i_target->b_next);
+ inst->i_target = inst->i_target->b_next;
+ i--;
+ continue;
+ }
+ break;
+ case JUMP_IF_TRUE:
+ switch (target->i_opcode) {
+ case JUMP:
+ case JUMP_IF_TRUE:
+ i -= jump_thread(bb, inst, target, JUMP_IF_TRUE);
+ continue;
+ case JUMP_IF_FALSE:
+ // No need to check for loops here, a block's b_next
+ // cannot point to itself.
+ assert(inst->i_target != inst->i_target->b_next);
+ inst->i_target = inst->i_target->b_next;
+ i--;
+ continue;
+ }
+ break;
case JUMP:
case JUMP_NO_INTERRUPT:
switch (target->i_opcode) {
@@ -2368,6 +2403,38 @@ push_cold_blocks_to_end(cfg_builder *g) {
}
static int
+convert_pseudo_conditional_jumps(cfg_builder *g)
+{
+ basicblock *entryblock = g->g_entryblock;
+ for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
+ for (int i = 0; i < b->b_iused; i++) {
+ cfg_instr *instr = &b->b_instr[i];
+ if (instr->i_opcode == JUMP_IF_FALSE || instr->i_opcode == JUMP_IF_TRUE) {
+ assert(i == b->b_iused - 1);
+ instr->i_opcode = instr->i_opcode == JUMP_IF_FALSE ?
+ POP_JUMP_IF_FALSE : POP_JUMP_IF_TRUE;
+ location loc = instr->i_loc;
+ cfg_instr copy = {
+ .i_opcode = COPY,
+ .i_oparg = 1,
+ .i_loc = loc,
+ .i_target = NULL,
+ };
+ RETURN_IF_ERROR(basicblock_insert_instruction(b, i++, &copy));
+ cfg_instr to_bool = {
+ .i_opcode = TO_BOOL,
+ .i_oparg = 0,
+ .i_loc = loc,
+ .i_target = NULL,
+ };
+ RETURN_IF_ERROR(basicblock_insert_instruction(b, i++, &to_bool));
+ }
+ }
+ }
+ return SUCCESS;
+}
+
+static int
convert_pseudo_ops(cfg_builder *g)
{
basicblock *entryblock = g->g_entryblock;
@@ -2826,6 +2893,8 @@ _PyCfg_OptimizedCfgToInstructionSequence(cfg_builder *g,
int *stackdepth, int *nlocalsplus,
_PyInstructionSequence *seq)
{
+ RETURN_IF_ERROR(convert_pseudo_conditional_jumps(g));
+
*stackdepth = calculate_stackdepth(g);
if (*stackdepth < 0) {
return ERROR;