From 36056016561bdd76698d526d730b720a499dccfe Mon Sep 17 00:00:00 2001 From: Stefan Behnel Date: Sat, 11 Dec 2010 01:46:05 +0100 Subject: [PATCH] optimise away redundant ref-counting of unused yield result values --- Cython/Compiler/ExprNodes.py | 23 ++++++++++++++++------- Cython/Compiler/Nodes.py | 1 + 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/Cython/Compiler/ExprNodes.py b/Cython/Compiler/ExprNodes.py index d81ae282..544a04b4 100755 --- a/Cython/Compiler/ExprNodes.py +++ b/Cython/Compiler/ExprNodes.py @@ -77,12 +77,15 @@ class ExprNode(Node): # [ExprNode or [ExprNode or None] or None] # Cached result of subexpr_nodes() # use_managed_ref boolean use ref-counted temps/assignments/etc. - + # result_is_used boolean indicates that the result will be dropped and the + # result_code/temp_result can safely be set to None + result_ctype = None type = None temp_code = None old_temp = None # error checker for multiple frees etc. use_managed_ref = True # can be set by optimisation transforms + result_is_used = True # The Analyse Expressions phase for expressions is split # into two sub-phases: @@ -447,6 +450,9 @@ class ExprNode(Node): def release_temp_result(self, code): if not self.temp_code: + if not self.result_is_used: + # not used anyway, so ignore if not set up + return if self.old_temp: raise RuntimeError("temp %s released multiple times in %s" % ( self.old_temp, self.__class__.__name__)) @@ -492,7 +498,7 @@ class ExprNode(Node): def generate_disposal_code(self, code): if self.is_temp: - if self.type.is_pyobject: + if self.type.is_pyobject and self.result(): code.put_decref_clear(self.result(), self.ctype()) else: # Already done if self.is_temp @@ -5018,11 +5024,14 @@ class YieldExprNode(ExprNode): code.putln('%s = %s->%s;' % (cname, Naming.cur_scope_cname, save_cname)) if type.is_pyobject: code.putln('%s->%s = 0;' % (Naming.cur_scope_cname, save_cname)) - self.allocate_temp_result(code) - code.putln('%s = %s; %s' % - (self.result(), Naming.sent_value_cname, - code.error_goto_if_null(self.result(), self.pos))) - code.put_incref(self.result(), py_object_type) + if self.result_is_used: + self.allocate_temp_result(code) + code.putln('%s = %s; %s' % + (self.result(), Naming.sent_value_cname, + code.error_goto_if_null(self.result(), self.pos))) + code.put_incref(self.result(), py_object_type) + else: + code.putln(code.error_goto_if_null(Naming.sent_value_cname, self.pos)) class StopIterationNode(Node): # XXX: is it okay? diff --git a/Cython/Compiler/Nodes.py b/Cython/Compiler/Nodes.py index eacaf569..eaae0351 100644 --- a/Cython/Compiler/Nodes.py +++ b/Cython/Compiler/Nodes.py @@ -3450,6 +3450,7 @@ class ExprStatNode(StatNode): self.__class__ = PassStatNode def analyse_expressions(self, env): + self.expr.result_is_used = False # hint that .result() may safely be left empty self.expr.analyse_expressions(env) def generate_execution_code(self, code): -- 2.26.2