def loop_block(self, node, block_size): outer_incr_name = cpp.CName(node.loopvar + node.loopvar) new_inner_for = cpp.For( node.loopvar, outer_incr_name, cpp.FunctionCall("min", [cpp.BinOp(outer_incr_name, "+", cpp.CNumber(block_size-1)), node.end]), cpp.CNumber(1), node.body) new_outer_for = cpp.For( node.loopvar + node.loopvar, node.initial, node.end, cpp.BinOp(node.increment, "*", cpp.CNumber(block_size)), cpp.Block(contents=[new_inner_for])) debug_print(new_outer_for) return new_outer_for
def visit_CName(self, node): #print "node.name is ", node.name if node.name == self.loopvar: return cpp.BinOp(cpp.CName(self.loopvar), "+", cpp.CNumber(self.increment)) else: return node
def unroll(self, node, factor): """Given a For node, unrolls the loop with a given factor. If the number of iterations in the given loop is not a multiple of the unroll factor, a 'leftover' loop will be generated to run the remaining iterations. """ import copy # we can't precalculate the number of leftover iterations in the case that # the number of iterations are not known a priori, so we build an Expression # and let the compiler deal with it #leftover_begin = cpp.BinOp(cpp.CNumber(factor), # "*", # cpp.BinOp(cpp.BinOp(node.end, "+", 1), "/", cpp.CNumber(factor))) # we begin leftover iterations at factor*( (end-initial+1) / factor ) + initial # note that this works due to integer division leftover_begin = cpp.BinOp(cpp.BinOp(cpp.BinOp(cpp.BinOp(cpp.BinOp(node.end, "-", node.initial), "+", cpp.CNumber(1)), "/", cpp.CNumber(factor)), "*", cpp.CNumber(factor)), "+", node.initial) new_limit = cpp.BinOp(node.end, "-", cpp.CNumber(factor-1)) # debug_print("Loop unroller called with ", node.loopvar) # debug_print("Number of iterations: ", num_iterations) # debug_print("Number of unrolls: ", num_unrolls) # debug_print("Leftover iterations: ", leftover) new_increment = cpp.BinOp(node.increment, "*", cpp.CNumber(factor)) new_block = cpp.Block(contents=node.body.contents) for x in xrange(1, factor): new_extension = copy.deepcopy(node.body) new_extension = LoopUnroller.UnrollReplacer(node.loopvar, x).visit(new_extension) new_block.extend(new_extension.contents) return_block = cpp.UnbracedBlock() unrolled_for_node = cpp.For( node.loopvar, node.initial, new_limit, #node.end, new_increment, new_block) leftover_for_node = cpp.For( node.loopvar, leftover_begin, node.end, node.increment, node.body) return_block.append(unrolled_for_node) # if we *know* this loop has no leftover iterations, then # we return without the leftover loop if not (isinstance(node.initial, cpp.CNumber) and isinstance(node.end, cpp.CNumber) and ((node.end.num - node.initial.num + 1) % factor == 0)): return_block.append(leftover_for_node) return return_block
def visit_BinOp(self, node): return cpp.BinOp(self.visit(node.left), self.visit(node.op), self.visit(node.right))