diff options
Diffstat (limited to 'polly/lib/External/ppcg/gpu_print.c')
-rw-r--r-- | polly/lib/External/ppcg/gpu_print.c | 255 |
1 files changed, 255 insertions, 0 deletions
diff --git a/polly/lib/External/ppcg/gpu_print.c b/polly/lib/External/ppcg/gpu_print.c new file mode 100644 index 00000000000..d7c83f6fbab --- /dev/null +++ b/polly/lib/External/ppcg/gpu_print.c @@ -0,0 +1,255 @@ +/* + * 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; + isl_ast_build *build; + + if (!prog) + return isl_printer_free(p); + + build = isl_ast_build_from_context(isl_set_copy(prog->scop->context)); + for (i = 0; i < prog->n_array; ++i) { + if (!prog->array[i].declare_local) + continue; + p = ppcg_print_declaration(p, prog->scop->pet->arrays[i], + build); + } + isl_ast_build_free(build); + + 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) { + prn = isl_printer_print_str(prn, "("); + prn = isl_printer_print_pw_aff(prn, array->bound[i]); + 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) +{ + int i; + + p = isl_printer_print_str(p, array->type); + p = isl_printer_print_str(p, " "); + + p = isl_printer_print_str(p, array->name); + + for (i = 0; i < array->n_index; i++) { + p = isl_printer_print_str(p, "["); + p = isl_printer_print_pw_aff(p, array->bound[i]); + p = isl_printer_print_str(p, "]"); + } + + 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. + * + * The copy in global memory has been linearized, so we need to take + * the array size into account. + */ +static __isl_give isl_printer *stmt_print_global_index( + __isl_take isl_printer *p, struct ppcg_kernel_stmt *stmt) +{ + int i; + struct gpu_array_info *array = stmt->u.c.array; + struct gpu_local_array_info *local = stmt->u.c.local_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); + if (array->linearize) + index = gpu_local_array_info_linearize_index(local, 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); +} + +/* 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; +} |