From: Robert Bradshaw Date: Thu, 3 Mar 2011 04:23:08 +0000 (-0800) Subject: Allow pointer target in C array slice iteration to avoid expensive copying. X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=ed8aac8a1f9eac589561dcb07499dde85c3666fb;p=cython.git Allow pointer target in C array slice iteration to avoid expensive copying. --- diff --git a/Cython/Compiler/Nodes.py b/Cython/Compiler/Nodes.py index 337ae165..609489f1 100644 --- a/Cython/Compiler/Nodes.py +++ b/Cython/Compiler/Nodes.py @@ -4349,7 +4349,12 @@ class ForInStatNode(LoopNode, StatNode): self.target.analyse_target_types(env) self.iterator.analyse_expressions(env) self.item = ExprNodes.NextNode(self.iterator, env) - self.item = self.item.coerce_to(self.target.type, env) + if (self.iterator.type.is_ptr or self.iterator.type.is_array) and \ + self.target.type.assignable_from(self.iterator.type): + # C array slice optimization. + pass + else: + self.item = self.item.coerce_to(self.target.type, env) self.body.analyse_expressions(env) if self.else_clause: self.else_clause.analyse_expressions(env) diff --git a/Cython/Compiler/Optimize.py b/Cython/Compiler/Optimize.py index 48772ed3..ae3b2408 100644 --- a/Cython/Compiler/Optimize.py +++ b/Cython/Compiler/Optimize.py @@ -375,6 +375,9 @@ class IterationTransform(Visitor.VisitorTransform): base=counter_temp, type=Builtin.bytes_type, is_temp=1) + elif node.target.type.is_ptr and not node.target.type.assignable_from(ptr_type.base_type): + # Allow iteration with pointer target to avoid copy. + target_value = counter_temp else: target_value = ExprNodes.IndexNode( node.target.pos, diff --git a/tests/run/carray_slicing.pyx b/tests/run/carray_slicing.pyx index 589ff3d3..50d2984c 100644 --- a/tests/run/carray_slicing.pyx +++ b/tests/run/carray_slicing.pyx @@ -217,3 +217,19 @@ def iter_doublearray_for_loop_c(): """ cdef double d print [ d for d in cdoubles ] + + +cdef struct MyStruct: + int i + +def struct_ptr_iter(): + """ + >>> struct_ptr_iter() + ([0, 1, 2, 3, 4], [0, 1, 2, 3, 4]) + """ + cdef MyStruct my_structs[5] + for i in range(5): + my_structs[i].i = i + cdef MyStruct value + cdef MyStruct *ptr + return [ value.i for value in my_structs[:5] ], [ ptr.i for ptr in my_structs[:5] ]