/* 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 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); }
/* 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; }
instruction_list * isl_user_to_noclock (isl_ast_node * user_node) { isl_ast_expr * expr = isl_ast_node_user_get_expr (user_node); instruction * user = instruction_alloc (); user->type = INSTR_CALL; user->content.call.identifier = strdup (isl_id_get_name ( isl_ast_expr_get_id (isl_ast_expr_get_op_arg (expr, 0)))); for (int i = 1; i < isl_ast_expr_get_op_n_arg (expr); ++i) { expression_list * e = expression_list_alloc (); e->element = isl_expr_to_noclock_expr (isl_ast_expr_get_op_arg (expr, i)); e->next = NULL; user->content.call.arguments = expression_list_cat ( user->content.call.arguments, e); } instruction_list * list = instruction_list_alloc (); list->element = user; list->next = NULL; return list; }
expression * isl_cond_to_expr (isl_ast_expr * expr) { expression * result; enum isl_ast_op_type t = isl_ast_expr_get_op_type (expr); result = isl_expr_to_noclock_expr (isl_ast_expr_get_op_arg (expr, 1)); if (t == isl_ast_op_lt) { expression * minus_one = expression_alloc (); minus_one->type = EXPR_NUMBER; minus_one->content.number = 1; expression * new_result = expression_sub (result, minus_one); result = new_result; } return result; }
expression * isl_expr_to_noclock_expr (isl_ast_expr * expr) { expression * e = NULL; enum isl_ast_expr_type expr_t = isl_ast_expr_get_type (expr); if (expr_t == isl_ast_expr_id) { e = expression_from_identifier (isl_id_get_name ( isl_ast_expr_get_id (expr))); return e; } else if (expr_t == isl_ast_expr_int) { e = expression_from_number ( isl_val_get_num_si (isl_ast_expr_get_val (expr))); return e; } bool binary = false; enum isl_ast_op_type t = isl_ast_expr_get_op_type (expr); switch (t) { case isl_ast_op_max: e = expression_alloc (); expression_set_type (e, EXPR_MAX); binary = true; break; case isl_ast_op_min: e = expression_alloc (); expression_set_type (e, EXPR_MIN); binary = true; break; case isl_ast_op_minus: e = expression_alloc (); expression_set_type (e, EXPR_NEG); break; case isl_ast_op_add: e = expression_alloc (); expression_set_type (e, EXPR_ADD); binary = true; break; case isl_ast_op_sub: e = expression_alloc (); expression_set_type (e, EXPR_SUB); binary = true; break; case isl_ast_op_mul: e = expression_alloc (); expression_set_type (e, EXPR_MULT); binary = true; break; case isl_ast_op_div: case isl_ast_op_fdiv_q: case isl_ast_op_pdiv_q: case isl_ast_op_pdiv_r: e = expression_alloc (); expression_set_type (e, EXPR_DIV); binary = true; break; case isl_ast_op_member: case isl_ast_op_cond: case isl_ast_op_select: return e; break; case isl_ast_op_eq: e = expression_alloc (); expression_set_type (e, EXPR_EQ); binary = true; break; case isl_ast_op_le: e = expression_alloc (); expression_set_type (e, EXPR_LE); binary = true; break; case isl_ast_op_lt: e = expression_alloc (); expression_set_type (e, EXPR_LT); binary = true; break; case isl_ast_op_ge: e = expression_alloc (); expression_set_type (e, EXPR_GE); binary = true; break; case isl_ast_op_gt: e = expression_alloc (); expression_set_type (e, EXPR_GT); binary = true; break; case isl_ast_op_and: case isl_ast_op_and_then: e = expression_alloc (); expression_set_type (e, EXPR_AND); binary = true; break; case isl_ast_op_or: case isl_ast_op_or_else: e = expression_alloc (); expression_set_type (e, EXPR_OR); binary = true; break; case isl_ast_op_call: case isl_ast_op_access: case isl_ast_op_address_of: default: return e; break; } if (binary) { expression_set_left_operand (e, isl_expr_to_noclock_expr (isl_ast_expr_get_op_arg (expr, 0))); expression_set_right_operand (e, isl_expr_to_noclock_expr (isl_ast_expr_get_op_arg (expr, 1))); } else { expression_set_left_operand (e, isl_expr_to_noclock_expr (isl_ast_expr_get_op_arg (expr, 0))); } return e; }
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; }