]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-106149: move unconditional jump direction resolution from optimizer to assembler...
authorIrit Katriel <1055913+iritkatriel@users.noreply.github.com>
Sat, 1 Jul 2023 10:28:07 +0000 (11:28 +0100)
committerGitHub <noreply@github.com>
Sat, 1 Jul 2023 10:28:07 +0000 (11:28 +0100)
Python/assemble.c
Python/flowgraph.c
Python/opcode_metadata.h
Tools/cases_generator/generate_cases.py

index 5d566a381b3988e7709a1fa65e2fdbd3e5f39cfa..ff7bca22286cd776abd0ecb3e2adddaded1f56d7 100644 (file)
@@ -674,11 +674,45 @@ resolve_jump_offsets(instr_sequence *instrs)
     return SUCCESS;
 }
 
+static int
+resolve_unconditional_jumps(instr_sequence *instrs)
+{
+    /* Resolve directions of unconditional jumps */
+
+    for (int i = 0; i < instrs->s_used; i++) {
+        instruction *instr = &instrs->s_instrs[i];
+        bool is_forward = (instr->i_oparg > i);
+        switch(instr->i_opcode) {
+            case JUMP:
+                assert(SAME_OPCODE_METADATA(JUMP, JUMP_FORWARD));
+                assert(SAME_OPCODE_METADATA(JUMP, JUMP_BACKWARD));
+                instr->i_opcode = is_forward ? JUMP_FORWARD : JUMP_BACKWARD;
+                break;
+            case JUMP_NO_INTERRUPT:
+                assert(SAME_OPCODE_METADATA(JUMP_NO_INTERRUPT, JUMP_FORWARD));
+                assert(SAME_OPCODE_METADATA(JUMP_NO_INTERRUPT, JUMP_BACKWARD_NO_INTERRUPT));
+                instr->i_opcode = is_forward ?
+                    JUMP_FORWARD : JUMP_BACKWARD_NO_INTERRUPT;
+                break;
+            default:
+                if (OPCODE_HAS_JUMP(instr->i_opcode) &&
+                    IS_PSEUDO_INSTR(instr->i_opcode)) {
+                    Py_UNREACHABLE();
+                }
+        }
+    }
+    return SUCCESS;
+}
+
 PyCodeObject *
 _PyAssemble_MakeCodeObject(_PyCompile_CodeUnitMetadata *umd, PyObject *const_cache,
                            PyObject *consts, int maxdepth, instr_sequence *instrs,
                            int nlocalsplus, int code_flags, PyObject *filename)
 {
+
+    if (resolve_unconditional_jumps(instrs) < 0) {
+        return NULL;
+    }
     if (resolve_jump_offsets(instrs) < 0) {
         return NULL;
     }
index 429109b74beab8345f4293ad493b539193a84690..213c993bb863a34ae23f8cf5d83096efcd3a49ab 100644 (file)
@@ -393,24 +393,17 @@ no_redundant_jumps(cfg_builder *g) {
 static int
 normalize_jumps_in_block(cfg_builder *g, basicblock *b) {
     cfg_instr *last = _PyCfg_BasicblockLastInstr(b);
-    if (last == NULL || !is_jump(last)) {
+    if (last == NULL || !is_jump(last) ||
+        IS_UNCONDITIONAL_JUMP_OPCODE(last->i_opcode)) {
         return SUCCESS;
     }
     assert(!IS_ASSEMBLER_OPCODE(last->i_opcode));
+
     bool is_forward = last->i_target->b_visited == 0;
-    switch(last->i_opcode) {
-        case JUMP:
-            assert(SAME_OPCODE_METADATA(JUMP, JUMP_FORWARD));
-            assert(SAME_OPCODE_METADATA(JUMP, JUMP_BACKWARD));
-            last->i_opcode = is_forward ? JUMP_FORWARD : JUMP_BACKWARD;
-            return SUCCESS;
-        case JUMP_NO_INTERRUPT:
-            assert(SAME_OPCODE_METADATA(JUMP_NO_INTERRUPT, JUMP_FORWARD));
-            assert(SAME_OPCODE_METADATA(JUMP_NO_INTERRUPT, JUMP_BACKWARD_NO_INTERRUPT));
-            last->i_opcode = is_forward ?
-                JUMP_FORWARD : JUMP_BACKWARD_NO_INTERRUPT;
-            return SUCCESS;
+    if (is_forward) {
+        return SUCCESS;
     }
+
     int reversed_opcode = 0;
     switch(last->i_opcode) {
         case POP_JUMP_IF_NOT_NONE:
@@ -426,9 +419,6 @@ normalize_jumps_in_block(cfg_builder *g, basicblock *b) {
             reversed_opcode = POP_JUMP_IF_FALSE;
             break;
     }
-    if (is_forward) {
-        return SUCCESS;
-    }
     /* transform 'conditional jump T' to
      * 'reversed_jump b_next' followed by 'jump_backwards T'
      */
index 5c7de77deba2d6bf1a013142057f0fdb47bf6ab7..6a42775e091208056570ae3717a4d83bdcc836e1 100644 (file)
@@ -4,7 +4,7 @@
 // Do not edit!
 
 
-#define IS_PSEUDO_INSTR(OP)  \
+#define IS_PSEUDO_INSTR(OP)  \
     ((OP) == LOAD_CLOSURE) || \
     ((OP) == STORE_FAST_MAYBE_NULL) || \
     ((OP) == LOAD_SUPER_METHOD) || \
@@ -17,7 +17,7 @@
     ((OP) == SETUP_CLEANUP) || \
     ((OP) == SETUP_WITH) || \
     ((OP) == POP_BLOCK) || \
-    0
+    0)
 
 #define EXIT_TRACE 300
 #define SET_IP 301
index 2332d12c6c0c68139a3c45734400d160dd43b506..38be98034e0d83a88a5f9a02cf552ec82ee024c2 100644 (file)
@@ -1310,10 +1310,10 @@ class Analyzer:
 
     def write_pseudo_instrs(self) -> None:
         """Write the IS_PSEUDO_INSTR macro"""
-        self.out.emit("\n\n#define IS_PSEUDO_INSTR(OP)  \\")
+        self.out.emit("\n\n#define IS_PSEUDO_INSTR(OP)  \\")
         for op in self.pseudos:
             self.out.emit(f"    ((OP) == {op}) || \\")
-        self.out.emit(f"    0")
+        self.out.emit(f"    0)")
 
     def write_uop_items(self, make_text: typing.Callable[[str, int], str]) -> None:
         """Write '#define XXX NNN' for each uop"""