Пример #1
0
/* 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);
}
Пример #2
0
void cpp_from_isl::process_for(isl_ast_node *node)
{
    auto iter_expr = isl_ast_node_for_get_iterator(node);
    auto init_expr = isl_ast_node_for_get_init(node);
    auto cond_expr = isl_ast_node_for_get_cond(node);
    auto inc_expr = isl_ast_node_for_get_inc(node);
    auto body_node = isl_ast_node_for_get_body(node);

    auto iter = process_expr(iter_expr);
    auto init = process_expr(init_expr);
    auto cond = process_expr(cond_expr);
    auto inc = process_expr(inc_expr);

    auto iter_id = dynamic_pointer_cast<id_expression>(iter);
    if (!iter_id)
        throw error("Iterator expression is not an identifier.");
    auto iter_decl = decl_expr(make_shared<basic_type>("int"),
                               *iter_id, init);

    auto for_stmt = make_shared<for_statement>();

    for_stmt->initialization = iter_decl;

    for_stmt->condition = cond;

    for_stmt->update = binop(op::assign_add, iter, inc);

    {
        vector<statement_ptr> stmts;

        m_ctx->push(&stmts);
        process_node(body_node);
        m_ctx->pop();

        if (stmts.size() == 1)
            for_stmt->body = stmts.front();
        else
            for_stmt->body = block(stmts);
    }

    m_ctx->add(for_stmt);

    isl_ast_expr_free(iter_expr);
    isl_ast_expr_free(init_expr);
    isl_ast_expr_free(cond_expr);
    isl_ast_expr_free(inc_expr);
    isl_ast_node_free(body_node);
}
Пример #3
0
/* 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;
}
Пример #4
0
/* 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;
}
Пример #5
0
void cpp_from_isl::process_user(isl_ast_node *node)
{
    auto ast_expr = isl_ast_node_user_get_expr(node);

    m_is_user_stmt = true;
    auto expr = process_expr(ast_expr);
    m_is_user_stmt = false;

    if (expr)
        m_ctx->add(expr);

    isl_ast_expr_free(ast_expr);
}
Пример #6
0
void cpp_from_isl::process_if(isl_ast_node *node)
{
    auto cond_expr = isl_ast_node_if_get_cond(node);
    auto true_node = isl_ast_node_if_get_then(node);
    auto false_node = isl_ast_node_if_get_else(node);

    auto if_stmt = make_shared<if_statement>();

    if_stmt->condition = process_expr(cond_expr);

    {
        vector<statement_ptr> stmts;

        m_ctx->push(&stmts);
        process_node(true_node);
        m_ctx->pop();

        if (stmts.size() == 1)
            if_stmt->true_part = stmts.front();
        else
            if_stmt->true_part = block(stmts);
    }

    if (false_node)
    {
        vector<statement_ptr> stmts;

        m_ctx->push(&stmts);
        process_node(false_node);
        m_ctx->pop();

        if (stmts.size() == 1)
            if_stmt->false_part = stmts.front();
        else
            if_stmt->false_part = block(stmts);
    }

    m_ctx->add(if_stmt);

    isl_ast_expr_free(cond_expr);
    isl_ast_node_free(true_node);
    isl_ast_node_free(false_node);
}
Пример #7
0
isl_ast_node * ast_gen::after_for(isl_ast_node *node, isl_ast_build * builder)
{
    if (verbose<ast_gen>::enabled())
        cout << "-- After for" << endl;

    bool is_deepest_loop = m_deepest_loop == m_current_loop;

    bool is_requested_parallel = false;

    {
        auto iter_expr = isl_ast_node_for_get_iterator(node);
        auto id = isl_ast_expr_get_id(iter_expr);
        if (verbose<ast_gen>::enabled())
            cout << "   Loop iter: " << isl_id_get_name(id) << endl;
        auto data = isl_id_get_user(id);
        if (data == &m_parallel_loop_id)
        {
            if (verbose<ast_gen>::enabled())
                cout << "   Requested as parallel" << endl;
            is_requested_parallel = true;
        }
        id = isl_id_free(id);
        isl_ast_expr_free(iter_expr);
    }

    auto id = isl_ast_node_get_annotation(node);

    auto info = ast_node_info::get_from_id(id);

    // Mark loop parallel if parallelizable and
    // either requested by user or outermost parallizable.

    if (!m_options.parallel)
    {
        if (verbose<ast_gen>::enabled())
            cout << "   Explicit parallelization not enabled." << endl;
    }
    else if (!info->is_parallelizable)
    {
        if (verbose<ast_gen>::enabled())
            cout << "   Not parallelizable." << endl;
    }
    else if (m_options.parallel_dim < 0)
    {
        if (m_num_parallelizable_loops != 1)
        {
            if (verbose<ast_gen>::enabled())
                cout << "   Not the outermost parallelizable loop." << endl;
        }
        else
        {
            info->is_parallel = true;
        }
    }
    else
    {
        if (!is_requested_parallel)
        {
            if (verbose<ast_gen>::enabled())
                cout << "   Not the requested parallel loop." << endl;
        }
        else
        {
            if (verbose<ast_gen>::enabled())
                cout << "   Parallelized." << endl;

            info->is_parallel = true;
        }
    }

    // Mark loop vectorized if parallelizable and deepest.

    if (m_options.vectorize && is_deepest_loop && info->is_parallelizable)
    {
        if (verbose<ast_gen>::enabled())
            cout << "-- Loop vectorized." << endl;

        info->is_vector = true;
    }

    if (info->is_parallel || info->is_vector)
    {
        store_parallel_accesses_for_current_dimension(builder);
    }

    if (info->is_parallelizable)
        --m_num_parallelizable_loops;

    --m_current_loop;

    id = isl_id_free(id);

    return node;
}
Пример #8
0
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;
}