def visit_If(self, node): test = self.visit(node.test) body = cpp.Block([self.visit(x) for x in node.body]) if node.orelse == []: orelse = None else: orelse = cpp.Block([self.visit(x) for x in node.orelse]) return cpp.IfConv(test, body, orelse)
def visit_Block(self, node): #print "visiting Block...." if self.inside_for: old_scope = self.in_new_scope self.in_new_scope = True #print "visiting block in ", node contents = [self.visit(x) for x in node.contents] retnode = cpp.Block(contents=[x for x in contents if x != None]) self.in_new_scope = old_scope else: self.inside_for = True contents = [self.visit(x) for x in node.contents] retnode = cpp.Block(contents=[x for x in contents if x != None]) return retnode
def visit_FunctionDef(self, node): debug_print("In FunctionDef:") debug_print(ast.dump(node)) debug_print("----") return cpp.FunctionBody(cpp.FunctionDeclaration(cpp.Value("void", node.name), self.visit(node.args)), cpp.Block([self.visit(x) for x in node.body]))
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 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