def p_expression_statement(p): 'expression_statement : expression_opt SEMI' p[0] = ast.ExpStmt(p[1], p.lineno(1) + __start_line_no - 1)
def p_expression_statement(p): "expression_statement : expression_opt SEMI" p[0] = ast.ExpStmt(p[1])
def __getLoopBoundScanningStmts(self, stmts, tile_level, outer_loop_inames, loop_info_table): ''' Generate an explicit loop-bound scanning code used at runtime to determine the latest start and the earliest end of scanning full tiles. ''' # (optimization) generate code that determines the loop bounds of full tiles at compile time if self.affine_lbound_exps: return self.__staticLoopBoundScanning(stmts, tile_level, outer_loop_inames, loop_info_table) # initialize all returned variables scan_stmts = [] lbound_info_seq = [] int_vars = [] # iterate over each statement to find loop bounds that are functions of outer loop iterators min_int = ast.NumLitExp(-2147483648, ast.NumLitExp.INT) max_int = ast.NumLitExp(2147483647, ast.NumLitExp.INT) lb_exps_table = {} ub_exps_table = {} pre_scan_stmts = [] post_scan_stmts = [] scan_loops = SimpleLoops() for stmt in stmts: # skip all non loop statements if not isinstance(stmt, ast.ForStmt): lbound_info_seq.append(None) continue # extract this loop structure id, lb_exp, ub_exp, st_exp, lbody = self.ast_util.getForLoopInfo( stmt) # see if the loop bound expressions are bound/free of outer loop iterators lb_inames = filter( lambda i: self.ast_util.containIdentName(lb_exp, i), outer_loop_inames) ub_inames = filter( lambda i: self.ast_util.containIdentName(ub_exp, i), outer_loop_inames) # skip loops with bound expressions that are free of outer loop iterators if not lb_inames and not ub_inames: lbound_info_seq.append(None) continue # check if this loop runs only once is_one_time_loop = str(lb_exp) == str(ub_exp) # generate booleans to indicate the needs of prolog, epilog, and orio.main.tiled loop if is_one_time_loop: need_tiled_loop = False need_prolog = False need_epilog = False else: need_tiled_loop = True need_prolog = len(lb_inames) > 0 need_epilog = len(ub_inames) > 0 # generate new variable names for both the new lower and upper loop bounds if need_tiled_loop: lb_name, ub_name = self.__getLoopBoundNames() int_vars.extend([lb_name, ub_name]) else: lb_name = '' ub_name = '' # append information about the new loop bounds lbinfo = (lb_name, ub_name, need_prolog, need_epilog, need_tiled_loop) lbound_info_seq.append(lbinfo) # skip generating loop-bound scanning code (if it's a one-time loop) if not need_tiled_loop: continue # generate loop-bound scanning code for the prolog if str(lb_exp) in lb_exps_table: lb_var = lb_exps_table[str(lb_exp)] a = ast.BinOpExp(ast.IdentExp(lb_name), lb_var.replicate(), ast.BinOpExp.EQ_ASGN) post_scan_stmts.append(ast.ExpStmt(a)) else: if need_prolog: a = ast.BinOpExp(ast.IdentExp(lb_name), min_int.replicate(), ast.BinOpExp.EQ_ASGN) pre_scan_stmts.append(ast.ExpStmt(a)) a = ast.BinOpExp( ast.IdentExp(lb_name), ast.FunCallExp( ast.IdentExp('max'), [ast.IdentExp(lb_name), lb_exp.replicate()]), ast.BinOpExp.EQ_ASGN) scan_loops.insertLoop(lb_inames, ast.ExpStmt(a)) else: a = ast.BinOpExp(ast.IdentExp(lb_name), lb_exp.replicate(), ast.BinOpExp.EQ_ASGN) pre_scan_stmts.append(ast.ExpStmt(a)) lb_exps_table[str(lb_exp)] = ast.IdentExp(lb_name) # generate loop-bound scaning code for the epilog if str(ub_exp) in ub_exps_table: ub_var = ub_exps_table[str(ub_exp)] a = ast.BinOpExp(ast.IdentExp(ub_name), ub_var.replicate(), ast.BinOpExp.EQ_ASGN) post_scan_stmts.append(ast.ExpStmt(a)) else: if need_epilog: a = ast.BinOpExp(ast.IdentExp(ub_name), max_int.replicate(), ast.BinOpExp.EQ_ASGN) pre_scan_stmts.append(ast.ExpStmt(a)) a = ast.BinOpExp( ast.IdentExp(ub_name), ast.FunCallExp( ast.IdentExp('min'), [ast.IdentExp(ub_name), ub_exp.replicate()]), ast.BinOpExp.EQ_ASGN) scan_loops.insertLoop(ub_inames, ast.ExpStmt(a)) else: a = ast.BinOpExp(ast.IdentExp(ub_name), ub_exp.replicate(), ast.BinOpExp.EQ_ASGN) pre_scan_stmts.append(ast.ExpStmt(a)) ub_exps_table[str(ub_exp)] = ast.IdentExp(ub_name) # build a new loop information tabe for generating the loop-bound scanning code n_loop_info_table = {} for iname, linfo in loop_info_table.items(): _, _, _, st_exp, _ = linfo n_loop_info_table[iname] = (self.__getTileSizeName( iname, tile_level), self.__getTileIterName(iname, tile_level), st_exp) # convert the "SimpleLoop" abstractions into loop ASTs scan_loop_stmts = scan_loops.convertToASTs(tile_level, n_loop_info_table) # merge all scanning statements scan_stmts = pre_scan_stmts + scan_loop_stmts + post_scan_stmts # return all necessary information return (scan_stmts, lbound_info_seq, int_vars)
def __staticLoopBoundScanning(self, stmts, tile_level, outer_loop_inames, loop_info_table): ''' Assuming that the loop-bound expressions are affine functions of outer loop iterators and global parameters, we can determine the loop bounds of full tiles in compile time. This is an optimization strategy to produce more efficient code. Assumptions: 1. Lower bound expression must be in the form of: max(e_1,e_2,e_3,...,e_n) 2. Upper bound expression must be in the form of: min(e_1,e_2,e_3,...,e_n) where e_i is an affine function of outer loop iterators and global parameters Note that max(x,y,z) is implemented as nested binary max functions: max(z,max(y,z)). The same condition applies for min function. When n=1, max/min function is not needed. ''' # initialize all returned variables scan_stmts = [] lbound_info_seq = [] int_vars = [] # generate the lower and upper values of each inter-tile loop val_table = {} for iname in outer_loop_inames: _, _, _, st_exp, _ = loop_info_table[iname] lval = ast.IdentExp(self.__getTileIterName(iname, tile_level)) t = ast.BinOpExp( ast.IdentExp(self.__getTileSizeName(iname, tile_level)), ast.ParenthExp(st_exp.replicate()), ast.BinOpExp.SUB) uval = ast.BinOpExp(lval.replicate(), ast.ParenthExp(t), ast.BinOpExp.ADD) val_table[iname] = (lval, uval) # iterate over each statement to determine loop bounds that are affine functions # of outer loop iterators lb_exps_table = {} ub_exps_table = {} for stmt in stmts: # skip all non loop statements if not isinstance(stmt, ast.ForStmt): lbound_info_seq.append(None) continue # extract this loop structure id, lb_exp, ub_exp, st_exp, lbody = self.ast_util.getForLoopInfo( stmt) # see if the loop bound expressions are bound/free of outer loop iterators lb_inames = filter( lambda i: self.ast_util.containIdentName(lb_exp, i), outer_loop_inames) ub_inames = filter( lambda i: self.ast_util.containIdentName(ub_exp, i), outer_loop_inames) # skip loops with bound expressions that are free of outer loop iterators if not lb_inames and not ub_inames: lbound_info_seq.append(None) continue # check if this loop runs only once is_one_time_loop = str(lb_exp) == str(ub_exp) # generate booleans to indicate the needs of prolog, epilog, and orio.main.tiled loop if is_one_time_loop: need_tiled_loop = False need_prolog = False need_epilog = False else: need_tiled_loop = True need_prolog = len(lb_inames) > 0 need_epilog = len(ub_inames) > 0 # generate new variable names for both the new lower and upper loop bounds if need_tiled_loop: lb_name, ub_name = self.__getLoopBoundNames() int_vars.extend([lb_name, ub_name]) else: lb_name = '' ub_name = '' # append information about the new loop bounds lbinfo = (lb_name, ub_name, need_prolog, need_epilog, need_tiled_loop) lbound_info_seq.append(lbinfo) # skip generating loop-bound scanning code (if it's a one-time loop) if not need_tiled_loop: continue # determine the value of the new lower loop bound if str(lb_exp) in lb_exps_table: lb_var = lb_exps_table[str(lb_exp)] a = ast.BinOpExp(ast.IdentExp(lb_name), lb_var.replicate(), ast.BinOpExp.EQ_ASGN) else: if need_prolog: t = self.__findMinMaxVal('max', lb_exp.replicate(), lb_inames, val_table) a = ast.BinOpExp(ast.IdentExp(lb_name), t.replicate(), ast.BinOpExp.EQ_ASGN) else: a = ast.BinOpExp(ast.IdentExp(lb_name), lb_exp.replicate(), ast.BinOpExp.EQ_ASGN) lb_exps_table[str(lb_exp)] = ast.IdentExp(lb_name) scan_stmts.append(ast.ExpStmt(a)) # determine the value of the new upper loop bound if str(ub_exp) in ub_exps_table: ub_var = ub_exps_table[str(ub_exp)] a = ast.BinOpExp(ast.IdentExp(ub_name), ub_var.replicate(), ast.BinOpExp.EQ_ASGN) else: if need_epilog: t = self.__findMinMaxVal('min', ub_exp.replicate(), ub_inames, val_table) a = ast.BinOpExp(ast.IdentExp(ub_name), t.replicate(), ast.BinOpExp.EQ_ASGN) else: a = ast.BinOpExp(ast.IdentExp(ub_name), ub_exp.replicate(), ast.BinOpExp.EQ_ASGN) ub_exps_table[str(ub_exp)] = ast.IdentExp(ub_name) scan_stmts.append(ast.ExpStmt(a)) # return all necessary information return (scan_stmts, lbound_info_seq, int_vars)
def p_expression_statement(p): "expression_statement : expression_opt SEMI" p[0] = ast.ExpStmt(p[1], getLineNumber(p.lineno(1)))
def p_expression_statement(p): "expression_statement : expression_opt SEMI" p[0] = ast.ExpStmt(p[1], line_no=str(p.lineno(1) + __start_line_no - 1))