/* Print a statement for copying an array to or from the device, * or for initializing or clearing the device. * The statement identifier of a copying node is called * "to_device_<array name>" or "from_device_<array name>" and * its user pointer points to the gpu_array_info of the array * that needs to be copied. * The node for initializing the device is called "init_device". * The node for clearing the device is called "clear_device". * * Extract the array (if any) from the identifier and call * init_device, clear_device, copy_array_to_device or copy_array_from_device. */ static __isl_give isl_printer *print_device_node(__isl_take isl_printer *p, __isl_keep isl_ast_node *node, struct gpu_prog *prog) { isl_ast_expr *expr, *arg; isl_id *id; const char *name; struct gpu_array_info *array; expr = isl_ast_node_user_get_expr(node); arg = isl_ast_expr_get_op_arg(expr, 0); id = isl_ast_expr_get_id(arg); name = isl_id_get_name(id); array = isl_id_get_user(id); isl_id_free(id); isl_ast_expr_free(arg); isl_ast_expr_free(expr); if (!name) return isl_printer_free(p); if (!strcmp(name, "init_device")) return init_device(p, prog); if (!strcmp(name, "clear_device")) return clear_device(p, prog); if (!array) return isl_printer_free(p); if (!prefixcmp(name, "to_device")) return copy_array_to_device(p, array); else return copy_array_from_device(p, array); }
void cpp_from_isl::process_for(isl_ast_node *node) { auto iter_expr = isl_ast_node_for_get_iterator(node); auto init_expr = isl_ast_node_for_get_init(node); auto cond_expr = isl_ast_node_for_get_cond(node); auto inc_expr = isl_ast_node_for_get_inc(node); auto body_node = isl_ast_node_for_get_body(node); auto iter = process_expr(iter_expr); auto init = process_expr(init_expr); auto cond = process_expr(cond_expr); auto inc = process_expr(inc_expr); auto iter_id = dynamic_pointer_cast<id_expression>(iter); if (!iter_id) throw error("Iterator expression is not an identifier."); auto iter_decl = decl_expr(make_shared<basic_type>("int"), *iter_id, init); auto for_stmt = make_shared<for_statement>(); for_stmt->initialization = iter_decl; for_stmt->condition = cond; for_stmt->update = binop(op::assign_add, iter, inc); { vector<statement_ptr> stmts; m_ctx->push(&stmts); process_node(body_node); m_ctx->pop(); if (stmts.size() == 1) for_stmt->body = stmts.front(); else for_stmt->body = block(stmts); } m_ctx->add(for_stmt); isl_ast_expr_free(iter_expr); isl_ast_expr_free(init_expr); isl_ast_expr_free(cond_expr); isl_ast_expr_free(inc_expr); isl_ast_node_free(body_node); }
/* Print a declaration for the device array corresponding to "array" on "p". */ static __isl_give isl_printer *declare_device_array(__isl_take isl_printer *p, struct gpu_array_info *array) { int i; if(print_device_arrays_or_not(array)) { p = isl_printer_start_line(p); p = isl_printer_print_str(p, array->type); p = isl_printer_print_str(p, " "); if (!array->linearize && array->n_index > 1) p = isl_printer_print_str(p, "("); p = isl_printer_print_str(p, "*dev_"); p = isl_printer_print_str(p, array->name); if (!array->linearize && array->n_index > 1) { p = isl_printer_print_str(p, ")"); for (i = 1; i < array->n_index; i++) { isl_ast_expr *bound; bound = isl_ast_expr_get_op_arg(array->bound_expr, 1 + i); p = isl_printer_print_str(p, "["); p = isl_printer_print_ast_expr(p, bound); p = isl_printer_print_str(p, "]"); isl_ast_expr_free(bound); } } p = isl_printer_print_str(p, ";"); p = isl_printer_end_line(p); } return p; }
/* Print the effective grid size as a list of the sizes in each * dimension, from innermost to outermost. */ static __isl_give isl_printer *print_grid_size(__isl_take isl_printer *p, struct ppcg_kernel *kernel) { int i; int dim; dim = isl_multi_pw_aff_dim(kernel->grid_size, isl_dim_set); if (dim == 0) return p; p = isl_printer_print_str(p, "("); for (i = dim - 1; i >= 0; --i) { isl_ast_expr *bound; bound = isl_ast_expr_get_op_arg(kernel->grid_size_expr, 1 + i); p = isl_printer_print_ast_expr(p, bound); isl_ast_expr_free(bound); if (i > 0) p = isl_printer_print_str(p, ", "); } p = isl_printer_print_str(p, ")"); return p; }
void cpp_from_isl::process_user(isl_ast_node *node) { auto ast_expr = isl_ast_node_user_get_expr(node); m_is_user_stmt = true; auto expr = process_expr(ast_expr); m_is_user_stmt = false; if (expr) m_ctx->add(expr); isl_ast_expr_free(ast_expr); }
void cpp_from_isl::process_if(isl_ast_node *node) { auto cond_expr = isl_ast_node_if_get_cond(node); auto true_node = isl_ast_node_if_get_then(node); auto false_node = isl_ast_node_if_get_else(node); auto if_stmt = make_shared<if_statement>(); if_stmt->condition = process_expr(cond_expr); { vector<statement_ptr> stmts; m_ctx->push(&stmts); process_node(true_node); m_ctx->pop(); if (stmts.size() == 1) if_stmt->true_part = stmts.front(); else if_stmt->true_part = block(stmts); } if (false_node) { vector<statement_ptr> stmts; m_ctx->push(&stmts); process_node(false_node); m_ctx->pop(); if (stmts.size() == 1) if_stmt->false_part = stmts.front(); else if_stmt->false_part = block(stmts); } m_ctx->add(if_stmt); isl_ast_expr_free(cond_expr); isl_ast_node_free(true_node); isl_ast_node_free(false_node); }
isl_ast_node * ast_gen::after_for(isl_ast_node *node, isl_ast_build * builder) { if (verbose<ast_gen>::enabled()) cout << "-- After for" << endl; bool is_deepest_loop = m_deepest_loop == m_current_loop; bool is_requested_parallel = false; { auto iter_expr = isl_ast_node_for_get_iterator(node); auto id = isl_ast_expr_get_id(iter_expr); if (verbose<ast_gen>::enabled()) cout << " Loop iter: " << isl_id_get_name(id) << endl; auto data = isl_id_get_user(id); if (data == &m_parallel_loop_id) { if (verbose<ast_gen>::enabled()) cout << " Requested as parallel" << endl; is_requested_parallel = true; } id = isl_id_free(id); isl_ast_expr_free(iter_expr); } auto id = isl_ast_node_get_annotation(node); auto info = ast_node_info::get_from_id(id); // Mark loop parallel if parallelizable and // either requested by user or outermost parallizable. if (!m_options.parallel) { if (verbose<ast_gen>::enabled()) cout << " Explicit parallelization not enabled." << endl; } else if (!info->is_parallelizable) { if (verbose<ast_gen>::enabled()) cout << " Not parallelizable." << endl; } else if (m_options.parallel_dim < 0) { if (m_num_parallelizable_loops != 1) { if (verbose<ast_gen>::enabled()) cout << " Not the outermost parallelizable loop." << endl; } else { info->is_parallel = true; } } else { if (!is_requested_parallel) { if (verbose<ast_gen>::enabled()) cout << " Not the requested parallel loop." << endl; } else { if (verbose<ast_gen>::enabled()) cout << " Parallelized." << endl; info->is_parallel = true; } } // Mark loop vectorized if parallelizable and deepest. if (m_options.vectorize && is_deepest_loop && info->is_parallelizable) { if (verbose<ast_gen>::enabled()) cout << "-- Loop vectorized." << endl; info->is_vector = true; } if (info->is_parallel || info->is_vector) { store_parallel_accesses_for_current_dimension(builder); } if (info->is_parallelizable) --m_num_parallelizable_loops; --m_current_loop; id = isl_id_free(id); return node; }
expression_ptr cpp_from_isl::process_op(isl_ast_expr * ast_op) { int arg_count = isl_ast_expr_get_op_n_arg(ast_op); vector<expression_ptr> args; args.reserve(arg_count); for(int i = 0; i < arg_count; ++i) { auto ast_arg = isl_ast_expr_get_op_arg(ast_op, i); auto arg = process_expr(ast_arg); isl_ast_expr_free(ast_arg); args.push_back(arg); } expression_ptr expr; auto type = isl_ast_expr_get_op_type(ast_op); switch(type) { case isl_ast_op_and: expr = binop(op::logic_and, args[0], args[1]); break; case isl_ast_op_or: expr = binop(op::logic_or, args[0], args[1]); break; case isl_ast_op_max: expr = make_shared<call_expression>("max", args[0], args[1]); break; case isl_ast_op_min: expr = make_shared<call_expression>("min", args[0], args[1]); break; case isl_ast_op_minus: expr = unop(op::u_minus, args[0]); break; case isl_ast_op_add: expr = binop(op::add, args[0], args[1]); break; case isl_ast_op_sub: expr = binop(op::sub, args[0], args[1]); break; case isl_ast_op_mul: expr = binop(op::mult, args[0], args[1]); break; case isl_ast_op_div: expr = binop(op::div, args[0], args[1]); break; case isl_ast_op_eq: expr = binop(op::equal, args[0], args[1]); break; case isl_ast_op_le: expr = binop(op::lesser_or_equal, args[0], args[1]); break; case isl_ast_op_lt: expr = binop(op::lesser, args[0], args[1]); break; case isl_ast_op_ge: expr = binop(op::greater_or_equal, args[0], args[1]); break; case isl_ast_op_gt: expr = binop(op::greater, args[0], args[1]); break; case isl_ast_op_call: { auto id = dynamic_pointer_cast<id_expression>(args[0]); if (!id) throw error("Function identifier expression is not an identifier."); vector<expression_ptr> func_args(++args.begin(), args.end()); if (m_is_user_stmt && m_stmt_func) m_stmt_func(id->name, func_args, m_ctx); else expr = make_shared<call_expression>(id->name, func_args); break; } case isl_ast_op_zdiv_r: { // "Equal to zero iff the remainder on integer division is zero." expr = binop(op::rem, args[0], args[1]); break; } case isl_ast_op_pdiv_r: { //Remainder of integer division, where dividend is known to be non-negative. expr = binop(op::rem, args[0], args[1]); break; } case isl_ast_op_pdiv_q: { // Result of integer division, where dividend is known to be non-negative. expr = binop(op::div, args[0], args[1]); break; } case isl_ast_op_or_else: // not implemented case isl_ast_op_and_then: // not implemented case isl_ast_op_fdiv_q: // Not implemented // Result of integer division, rounded towards negative infinity. case isl_ast_op_cond: // Not implemented. case isl_ast_op_select: // Not implemented. case isl_ast_op_access: // Not implemented case isl_ast_op_member: // Not implemented default: throw error("Unsupported AST expression type."); } return expr; }