Allow pointer target in C array slice iteration to avoid expensive copying.
authorRobert Bradshaw <robertwb@math.washington.edu>
Thu, 3 Mar 2011 04:23:08 +0000 (20:23 -0800)
committerRobert Bradshaw <robertwb@math.washington.edu>
Thu, 3 Mar 2011 04:23:08 +0000 (20:23 -0800)
Cython/Compiler/Nodes.py
Cython/Compiler/Optimize.py
tests/run/carray_slicing.pyx

index 337ae1656f59273ec6511c89cb4d663f7cc44cb5..609489f1758a09bde72f7a7476c64ed54c8d809f 100644 (file)
@@ -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)
index 48772ed3a78ad122a1bd4c3b7468048804d3ee80..ae3b2408ab53e92fce63ab5bf984e7d7979d3a02 100644 (file)
@@ -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,
index 589ff3d386df1908d89f621820e4ae79f964574b..50d2984c59d52671c5ec7afb0526dac01a4901d0 100644 (file)
@@ -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] ]