From d982432948367e130ac50efac720b821db177e5f Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Fri, 23 Jan 2015 23:31:40 +0100 Subject: [PATCH] opencl: replace calls to mathf functions by overloaded function and cast OpenCL does not have any expf, powf or sqrtf functions but instead provides overloaded exp, pow and sqrt functions. If the *f functions appear in the input code, then they need to be replaced by a cast to float and a call to the corresponding overloaded function. This is needed for the upcoming PolyBench/C 4.0. We currently only handle those functions used by PolyBench. Other functions can be added later. Signed-off-by: Sven Verdoolaege --- opencl.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 72 insertions(+), 1 deletion(-) diff --git a/opencl.c b/opencl.c index bc0392f..3af7990 100644 --- a/opencl.c +++ b/opencl.c @@ -647,6 +647,77 @@ static __isl_give isl_printer *opencl_print_sync(__isl_take isl_printer *p, return p; } +/* Data structure containing function names for which the calls + * should be changed from + * + * name(arg) + * + * to + * + * opencl_name((type) (arg)) + */ +static struct ppcg_opencl_fn { + const char *name; + const char *opencl_name; + const char *type; +} opencl_fn[] = { + { "expf", "exp", "float" }, + { "powf", "pow", "float" }, + { "sqrtf", "sqrt", "float" }, +}; + +#define ARRAY_SIZE(array) (sizeof(array)/sizeof(*array)) + +/* If the name of function called by "expr" matches any of those + * in ppcg_opencl_fn, then replace the call by a cast to the corresponding + * type in ppcg_opencl_fn and a call to corresponding OpenCL function. + */ +static __isl_give pet_expr *map_opencl_call(__isl_take pet_expr *expr, + void *user) +{ + const char *name; + int i; + + name = pet_expr_call_get_name(expr); + for (i = 0; i < ARRAY_SIZE(opencl_fn); ++i) { + pet_expr *arg; + + if (strcmp(name, opencl_fn[i].name)) + continue; + expr = pet_expr_call_set_name(expr, opencl_fn[i].opencl_name); + arg = pet_expr_get_arg(expr, 0); + arg = pet_expr_new_cast(opencl_fn[i].type, arg); + expr = pet_expr_set_arg(expr, 0, arg); + } + return expr; +} + +/* Print the body of a statement from the input program, + * for use in OpenCL code. + * + * Before calling ppcg_kernel_print_domain to print the actual statement body, + * we first modify this body to take into account that the output code + * is OpenCL code. In particular, if the statement calls any function + * with a "f" suffix, then it needs to be replaced by a call to + * the corresponding function without suffix after casting the argument + * to a float. + */ +static __isl_give isl_printer *print_opencl_kernel_domain( + __isl_take isl_printer *p, struct ppcg_kernel_stmt *stmt) +{ + struct pet_stmt *ps; + pet_tree *tree; + + ps = stmt->u.d.stmt->stmt; + tree = pet_tree_copy(ps->body); + ps->body = pet_tree_map_call_expr(ps->body, &map_opencl_call, NULL); + p = ppcg_kernel_print_domain(p, stmt); + pet_tree_free(ps->body); + ps->body = tree; + + return p; +} + /* This function is called for each user statement in the AST, * i.e., for each kernel body statement, copy statement or sync statement. */ @@ -670,7 +741,7 @@ static __isl_give isl_printer *opencl_print_kernel_stmt( case ppcg_kernel_sync: return opencl_print_sync(p, stmt); case ppcg_kernel_domain: - return ppcg_kernel_print_domain(p, stmt); + return print_opencl_kernel_domain(p, stmt); } return p; -- 2.11.4.GIT