[Python-checkins] r64916 - python/branches/tlee-ast-optimize/Python/optimize.c

thomas.lee python-checkins at python.org
Sun Jul 13 17:11:55 CEST 2008


Author: thomas.lee
Date: Sun Jul 13 17:11:54 2008
New Revision: 64916

Log:
Include a hack for jump injection that doesn't break quite so many tests. Need to fix lnotab breakage due to if/else swappage (and possibly other optimizations).

Modified:
   python/branches/tlee-ast-optimize/Python/optimize.c

Modified: python/branches/tlee-ast-optimize/Python/optimize.c
==============================================================================
--- python/branches/tlee-ast-optimize/Python/optimize.c	(original)
+++ python/branches/tlee-ast-optimize/Python/optimize.c	Sun Jul 13 17:11:54 2008
@@ -6,6 +6,8 @@
 #include "node.h"
 #include "ast.h"
 
+#define NEXTLINE(lineno) (lineno+1)
+
 typedef struct _optimizer_block {
     struct _optimizer_block* b_next; /* next block on the stack */
     PySTEntryObject*         b_ste;  /* symtable entry */
@@ -258,7 +260,7 @@
     asdl_seq* seq = *seq_ptr;
     stmt_ty stmt = asdl_seq_GET(seq, n);
 
-    /* eliminate unreachable branches in an "if" statement? */
+    /* eliminate unreachable branches in an "if" statement */
     if (stmt->kind == If_kind) {
         PyObject* test = _expr_constant_value(stmt->v.If.test);
         if (test != NULL) {
@@ -376,13 +378,14 @@
     if (retseq == NULL)
         return NULL;
     last = asdl_seq_GET(seq, asdl_seq_LEN(seq)-1);
-    ret = Return(value, last->lineno, last->col_offset, arena);
+    ret = Return(value, NEXTLINE(last->lineno), last->col_offset, arena);
     if (ret == NULL)
         return NULL;
     asdl_seq_SET(retseq, 0, ret);
     return _asdl_seq_append(seq, 0, retseq, 0, arena);
 }
 
+#if 0
 static void
 _expr_incref(expr_ty expr)
 {
@@ -395,19 +398,21 @@
             Py_INCREF(expr->v.Const.value);
     }
 }
+#endif
 
 static int
 _inject_compound_stmt_return(stmt_ty stmt, stmt_ty next, PyArena* arena)
 {
-#if 0
+    expr_ty value = NULL;
+    if (next != NULL)
+        value = next->v.Return.value;
+
     /* if the else body is not present, there will be no jump anyway */
     if (stmt->kind == If_kind && stmt->v.If.orelse != NULL) {
         stmt_ty inner = asdl_seq_GET(stmt->v.If.body,
                                     LAST_IN_SEQ(stmt->v.If.body));
         
         if (inner->kind != Return_kind) {
-            expr_ty value = next->v.Return.value;
-            _expr_incref(value);
             stmt->v.If.body =
                 _asdl_seq_append_return(stmt->v.If.body, value, arena);
 
@@ -422,8 +427,6 @@
         stmt_ty inner = asdl_seq_GET(stmt->v.TryExcept.body,
                             LAST_IN_SEQ(stmt->v.TryExcept.body));
         if (inner->kind != Return_kind && inner->kind != Raise_kind) {
-            expr_ty value = next->v.Return.value;
-            _expr_incref(value);
             /* if we inject a return into the "try" body of a
              * "try..except..else", we will miss the "else"!
              * We need to take a different path if the "else" is
@@ -449,15 +452,12 @@
         stmt_ty inner = asdl_seq_GET(stmt->v.TryFinally.body,
                             LAST_IN_SEQ(stmt->v.TryFinally.body));
         if (inner->kind != Return_kind && inner->kind != Raise_kind) {
-            expr_ty value = next->v.Return.value;
-            _expr_incref(value);
             stmt->v.TryFinally.body =
                 _asdl_seq_append_return(stmt->v.TryFinally.body, value, arena);
             if (stmt->v.TryFinally.body == NULL)
                 return 0;
         }
     }
-#endif
 
     return 1;
 }
@@ -467,32 +467,19 @@
  * they immediately return rather than jump.
  */
 static int
-_simplify_jumps(optimizer* opt, asdl_seq* seq)
+_simplify_jumps(optimizer* opt, asdl_seq* seq, int top)
 {
     int n, len;
 
     len = asdl_seq_LEN(seq);
 
     for (n = 0; n < len; n++) {
-        stmt_ty stmt;
-        stmt_ty next;
-        
-        stmt = asdl_seq_GET(seq, n);
-
-        /* on the last iteration, the target is an implicit `return None' */
-        if (n == len-1) {
-            /* if a "return" is already present, we have nothing left to do */
-            if (stmt->kind == Return_kind)
-                break;
-
-            next = Return(NULL, stmt->lineno, stmt->col_offset, opt->opt_arena);
-            if (next == NULL)
-                return 0;
-        }
-        else
+        stmt_ty stmt = asdl_seq_GET(seq, n);
+        stmt_ty next = NULL;
+        if (n < len-1)
             next = asdl_seq_GET(seq, n+1);
-        
-        if (next->kind == Return_kind)
+        /* XXX: handle the implicit return only if top-level function seq */
+        if ((top && next == NULL) || (next && next->kind == Return_kind))
             if (!_inject_compound_stmt_return(stmt, next, opt->opt_arena))
                 return 0;
     }
@@ -515,7 +502,7 @@
             if (!_eliminate_unreachable_code(opt, seq_ptr, n))
                 return 0;
         if (opt->opt_current->b_ste->ste_type == FunctionBlock)
-            if (!_simplify_jumps(opt, *seq_ptr))
+            if (!_simplify_jumps(opt, *seq_ptr, 0))
                 return 0;
     }
     return 1;
@@ -1166,15 +1153,43 @@
 }
 
 static int
+_contains_return(asdl_seq* seq)
+{
+    int i;
+    int len = asdl_seq_LEN(seq);
+    for (i = 0; i < len; i++)
+        if (((stmt_ty)asdl_seq_GET(seq, i))->kind == Return_kind)
+            return 1;
+    return 0;
+}
+
+static int
 optimize_function_def(optimizer* opt, stmt_ty* stmt_ptr)
 {
     stmt_ty stmt = *stmt_ptr;
+    
+    /* XXX: this breaks a bunch of tests. For now we use a second pass. */
+#if 0
+    /* Make any implicit returns explicit */
+    if (!_contains_return(stmt->v.FunctionDef.body)) {
+        stmt->v.FunctionDef.body =
+            _asdl_seq_append_return(stmt->v.FunctionDef.body, NULL,
+                                    opt->opt_arena);
+        if (stmt->v.FunctionDef.body == NULL)
+            return 0;
+    }
+#endif
+
     if (!optimize_arguments(opt, &stmt->v.FunctionDef.args))
         return 0;
     if (!optimize_expr_seq(opt, &stmt->v.FunctionDef.decorator_list))
         return 0;
     if (!optimize_stmt_seq(opt, &stmt->v.FunctionDef.body))
         return 0;
+    /* XXX: shallow second pass for implicit returns */
+    if (!_contains_return(stmt->v.FunctionDef.body))
+        if (!_simplify_jumps(opt, stmt->v.FunctionDef.body, 1))
+            return 0;
     return 1;
 }
 


More information about the Python-checkins mailing list