123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310 |
- /*
- * Copyright 2012 Ecole Normale Superieure
- *
- * Use of this software is governed by the MIT license
- *
- * Written by Sven Verdoolaege,
- * Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
- */
- #include <string.h>
- #include <isl/aff.h>
- #include "gpu_print.h"
- #include "print.h"
- #include "schedule.h"
- /* Print declarations to "p" for arrays that are local to "prog"
- * but that are used on the host and therefore require a declaration.
- */
- __isl_give isl_printer *gpu_print_local_declarations(__isl_take isl_printer *p,
- struct gpu_prog *prog)
- {
- int i;
- if (!prog)
- return isl_printer_free(p);
- for (i = 0; i < prog->n_array; ++i) {
- struct gpu_array_info *array = &prog->array[i];
- isl_ast_expr *size;
- if (!array->declare_local)
- continue;
- size = array->declared_size;
- p = ppcg_print_declaration_with_size(p, array->type, size);
- }
- return p;
- }
- /* Print an expression for the size of "array" in bytes.
- */
- __isl_give isl_printer *gpu_array_info_print_size(__isl_take isl_printer *prn,
- struct gpu_array_info *array)
- {
- int i;
- for (i = 0; i < array->n_index; ++i) {
- isl_ast_expr *bound;
- prn = isl_printer_print_str(prn, "(");
- bound = isl_ast_expr_get_op_arg(array->bound_expr, 1 + i);
- prn = isl_printer_print_ast_expr(prn, bound);
- isl_ast_expr_free(bound);
- prn = isl_printer_print_str(prn, ") * ");
- }
- prn = isl_printer_print_str(prn, "sizeof(");
- prn = isl_printer_print_str(prn, array->type);
- prn = isl_printer_print_str(prn, ")");
- return prn;
- }
- /* Print the declaration of a non-linearized array argument.
- */
- static __isl_give isl_printer *print_non_linearized_declaration_argument(
- __isl_take isl_printer *p, struct gpu_array_info *array)
- {
- p = isl_printer_print_str(p, array->type);
- p = isl_printer_print_str(p, " ");
- p = isl_printer_print_ast_expr(p, array->bound_expr);
- return p;
- }
- /* Print the declaration of an array argument.
- * "memory_space" allows to specify a memory space prefix.
- */
- __isl_give isl_printer *gpu_array_info_print_declaration_argument(
- __isl_take isl_printer *p, struct gpu_array_info *array,
- const char *memory_space)
- {
- if (gpu_array_is_read_only_scalar(array)) {
- p = isl_printer_print_str(p, array->type);
- p = isl_printer_print_str(p, " ");
- p = isl_printer_print_str(p, array->name);
- return p;
- }
- if (memory_space) {
- p = isl_printer_print_str(p, memory_space);
- p = isl_printer_print_str(p, " ");
- }
- if (array->n_index != 0 && !array->linearize)
- return print_non_linearized_declaration_argument(p, array);
- p = isl_printer_print_str(p, array->type);
- p = isl_printer_print_str(p, " ");
- p = isl_printer_print_str(p, "*");
- p = isl_printer_print_str(p, array->name);
- return p;
- }
- /* Print the call of an array argument.
- */
- __isl_give isl_printer *gpu_array_info_print_call_argument(
- __isl_take isl_printer *p, struct gpu_array_info *array)
- {
- if (gpu_array_is_read_only_scalar(array))
- return isl_printer_print_str(p, array->name);
- p = isl_printer_print_str(p, "dev_");
- p = isl_printer_print_str(p, array->name);
- return p;
- }
- /* Print an access to the element in the private/shared memory copy
- * described by "stmt". The index of the copy is recorded in
- * stmt->local_index as an access to the array.
- */
- static __isl_give isl_printer *stmt_print_local_index(__isl_take isl_printer *p,
- struct ppcg_kernel_stmt *stmt)
- {
- return isl_printer_print_ast_expr(p, stmt->u.c.local_index);
- }
- /* Print an access to the element in the global memory copy
- * described by "stmt". The index of the copy is recorded in
- * stmt->index as an access to the array.
- */
- static __isl_give isl_printer *stmt_print_global_index(
- __isl_take isl_printer *p, struct ppcg_kernel_stmt *stmt)
- {
- struct gpu_array_info *array = stmt->u.c.array;
- isl_ast_expr *index;
- if (gpu_array_is_scalar(array)) {
- if (!gpu_array_is_read_only_scalar(array))
- p = isl_printer_print_str(p, "*");
- p = isl_printer_print_str(p, array->name);
- return p;
- }
- index = isl_ast_expr_copy(stmt->u.c.index);
- p = isl_printer_print_ast_expr(p, index);
- isl_ast_expr_free(index);
- return p;
- }
- /* Print a copy statement.
- *
- * A read copy statement is printed as
- *
- * local = global;
- *
- * while a write copy statement is printed as
- *
- * global = local;
- */
- __isl_give isl_printer *ppcg_kernel_print_copy(__isl_take isl_printer *p,
- struct ppcg_kernel_stmt *stmt)
- {
- p = isl_printer_start_line(p);
- if (stmt->u.c.read) {
- p = stmt_print_local_index(p, stmt);
- p = isl_printer_print_str(p, " = ");
- p = stmt_print_global_index(p, stmt);
- } else {
- p = stmt_print_global_index(p, stmt);
- p = isl_printer_print_str(p, " = ");
- p = stmt_print_local_index(p, stmt);
- }
- p = isl_printer_print_str(p, ";");
- p = isl_printer_end_line(p);
- return p;
- }
- __isl_give isl_printer *ppcg_kernel_print_domain(__isl_take isl_printer *p,
- struct ppcg_kernel_stmt *stmt)
- {
- return pet_stmt_print_body(stmt->u.d.stmt->stmt, p, stmt->u.d.ref2expr);
- }
- /* This function is called for each node in a GPU AST.
- * In case of a user node, print the macro definitions required
- * for printing the AST expressions in the annotation, if any.
- * For other nodes, return true such that descendants are also
- * visited.
- *
- * In particular, for a kernel launch, print the macro definitions
- * needed for the grid size.
- * For a copy statement, print the macro definitions needed
- * for the two index expressions.
- * For an original user statement, print the macro definitions
- * needed for the substitutions.
- */
- static isl_bool at_node(__isl_keep isl_ast_node *node, void *user)
- {
- const char *name;
- isl_id *id;
- int is_kernel;
- struct ppcg_kernel *kernel;
- struct ppcg_kernel_stmt *stmt;
- isl_printer **p = user;
- if (isl_ast_node_get_type(node) != isl_ast_node_user)
- return isl_bool_true;
- id = isl_ast_node_get_annotation(node);
- if (!id)
- return isl_bool_false;
- name = isl_id_get_name(id);
- if (!name)
- return isl_bool_error;
- is_kernel = !strcmp(name, "kernel");
- kernel = is_kernel ? isl_id_get_user(id) : NULL;
- stmt = is_kernel ? NULL : isl_id_get_user(id);
- isl_id_free(id);
- if ((is_kernel && !kernel) || (!is_kernel && !stmt))
- return isl_bool_error;
- if (is_kernel) {
- *p = ppcg_ast_expr_print_macros(kernel->grid_size_expr, *p);
- } else if (stmt->type == ppcg_kernel_copy) {
- *p = ppcg_ast_expr_print_macros(stmt->u.c.index, *p);
- *p = ppcg_ast_expr_print_macros(stmt->u.c.local_index, *p);
- } else if (stmt->type == ppcg_kernel_domain) {
- *p = ppcg_print_body_macros(*p, stmt->u.d.ref2expr);
- }
- if (!*p)
- return isl_bool_error;
- return isl_bool_false;
- }
- /* Print the required macros for the GPU AST "node" to "p",
- * including those needed for the user statements inside the AST.
- */
- __isl_give isl_printer *gpu_print_macros(__isl_take isl_printer *p,
- __isl_keep isl_ast_node *node)
- {
- if (isl_ast_node_foreach_descendant_top_down(node, &at_node, &p) < 0)
- return isl_printer_free(p);
- p = ppcg_print_macros(p, node);
- return p;
- }
- /* Was the definition of "type" printed before?
- * That is, does its name appear in the list of printed types "types"?
- */
- static int already_printed(struct gpu_types *types,
- struct pet_type *type)
- {
- int i;
- for (i = 0; i < types->n; ++i)
- if (!strcmp(types->name[i], type->name))
- return 1;
- return 0;
- }
- /* Print the definitions of all types prog->scop that have not been
- * printed before (according to "types") on "p".
- * Extend the list of printed types "types" with the newly printed types.
- */
- __isl_give isl_printer *gpu_print_types(__isl_take isl_printer *p,
- struct gpu_types *types, struct gpu_prog *prog)
- {
- int i, n;
- isl_ctx *ctx;
- char **name;
- n = prog->scop->pet->n_type;
- if (n == 0)
- return p;
- ctx = isl_printer_get_ctx(p);
- name = isl_realloc_array(ctx, types->name, char *, types->n + n);
- if (!name)
- return isl_printer_free(p);
- types->name = name;
- for (i = 0; i < n; ++i) {
- struct pet_type *type = prog->scop->pet->types[i];
- if (already_printed(types, type))
- continue;
- p = isl_printer_start_line(p);
- p = isl_printer_print_str(p, type->definition);
- p = isl_printer_print_str(p, ";");
- p = isl_printer_end_line(p);
- types->name[types->n++] = strdup(type->name);
- }
- return p;
- }
|