summaryrefslogtreecommitdiffstats
path: root/polly/lib/External/ppcg/gpu_print.c
diff options
context:
space:
mode:
Diffstat (limited to 'polly/lib/External/ppcg/gpu_print.c')
-rw-r--r--polly/lib/External/ppcg/gpu_print.c255
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;
+}
OpenPOWER on IntegriCloud