static void handle_ompss_opencl_deallocate_intrinsic(
            Nodecl::FunctionCall function_call,
            Nodecl::NodeclBase expr_stmt)
    {
        Nodecl::List arguments = function_call.get_arguments().as<Nodecl::List>();
        ERROR_CONDITION(arguments.size() != 1, "More than one argument in ompss_opencl_deallocate call", 0);

        Nodecl::NodeclBase actual_argument = arguments[0];
        ERROR_CONDITION(!actual_argument.is<Nodecl::FortranActualArgument>(), "Unexpected tree", 0);

        Nodecl::NodeclBase arg = actual_argument.as<Nodecl::FortranActualArgument>().get_argument();
        TL::Symbol array_sym = ::fortran_data_ref_get_symbol(arg.get_internal_nodecl());

        ERROR_CONDITION(
                !(array_sym.get_type().is_fortran_array()
                    && array_sym.is_allocatable())
                &&
                !(array_sym.get_type().is_pointer()
                    && array_sym.get_type().points_to().is_fortran_array()),
                "The argument of 'ompss_opencl_deallocate' intrinsic must be "
                "an allocatable array or a pointer to an array\n", 0);

        // Replace the current intrinsic call by a call to the Nanos++ API
        TL::Symbol ptr_of_arr_sym = get_function_ptr_of(array_sym, expr_stmt.retrieve_context());

        TL::Source new_function_call;
        new_function_call
            << "CALL NANOS_OPENCL_DEALLOCATE_FORTRAN("
            <<      ptr_of_arr_sym.get_name() << "("<< as_expression(arg) << "))\n"
            ;

        expr_stmt.replace(new_function_call.parse_statement(expr_stmt));
    }
Beispiel #2
0
 bool ArrayAccessInfoVisitor::visit( const Nodecl::FunctionCall& n )
 {
     // Traverse arguments to find induction variables
     walk( n.get_arguments( ) );
     
     _is_adjacent_access = false;    // Reset this value
     
     return false; // Conservatively assume the result of the function call is not constant
 }
    static void handle_ompss_opencl_allocate_intrinsic(
            Nodecl::FunctionCall function_call,
            std::map<std::pair<TL::Type, std::pair<int, bool> > , Symbol> &declared_ocl_allocate_functions,
            Nodecl::NodeclBase expr_stmt)
    {
        Nodecl::List arguments = function_call.get_arguments().as<Nodecl::List>();
        ERROR_CONDITION(arguments.size() != 1, "More than one argument in 'ompss_opencl_allocate' call\n", 0);

        Nodecl::NodeclBase actual_argument = arguments[0];
        ERROR_CONDITION(!actual_argument.is<Nodecl::FortranActualArgument>(), "Unexpected tree\n", 0);

        Nodecl::NodeclBase arg = actual_argument.as<Nodecl::FortranActualArgument>().get_argument();
        ERROR_CONDITION(!arg.is<Nodecl::ArraySubscript>(), "Unreachable code\n", 0);

        Nodecl::NodeclBase subscripted = arg.as<Nodecl::ArraySubscript>().get_subscripted();
        TL::Symbol subscripted_symbol = ::fortran_data_ref_get_symbol(subscripted.get_internal_nodecl());

        ERROR_CONDITION(
                !(subscripted_symbol.get_type().is_fortran_array()
                    && subscripted_symbol.is_allocatable())
                &&
                !(subscripted_symbol.get_type().is_pointer()
                    && subscripted_symbol.get_type().points_to().is_fortran_array()),
                "The argument of 'ompss_opencl_allocate' intrinsic must be "
                "an allocatable array or a pointer to an array with all its bounds specified\n", 0);

        TL::Type array_type;
        int num_dimensions;
        bool is_allocatable;
        if (subscripted_symbol.is_allocatable())
        {
            array_type = subscripted_symbol.get_type();
            num_dimensions = subscripted_symbol.get_type().get_num_dimensions();
            is_allocatable = true;
        }
        else
        {
            array_type = subscripted_symbol.get_type().points_to();
            num_dimensions = array_type.get_num_dimensions();
            is_allocatable = false;
        }

        TL::Type element_type = array_type;
        while (element_type.is_array())
        {
            element_type = element_type.array_element();
        }

        ERROR_CONDITION(!array_type.is_array(), "This type should be an array type", 0);

        std::pair<TL::Type, std::pair<int, bool> > key =
            std::make_pair(element_type, std::make_pair(num_dimensions, is_allocatable));

        std::map<std::pair<TL::Type, std::pair<int, bool> > , Symbol>::iterator it_new_fun =
            declared_ocl_allocate_functions.find(key);

        // Reuse the auxiliar function if it already exists
        Symbol new_function_sym;
        if (it_new_fun != declared_ocl_allocate_functions.end())
        {
            new_function_sym = it_new_fun->second;
        }
        else
        {
            new_function_sym = create_new_function_opencl_allocate(
                    expr_stmt, subscripted_symbol, element_type, num_dimensions, is_allocatable);

            declared_ocl_allocate_functions[key] = new_function_sym;
        }

        // Replace the current intrinsic call by a call to the new function
        TL::Source actual_arg_array;
        Nodecl::NodeclBase subscripted_lvalue = subscripted.shallow_copy();
        subscripted_lvalue.set_type(subscripted_symbol.get_type().no_ref().get_lvalue_reference_to());

        actual_arg_array << as_expression(subscripted_lvalue);

        TL::Source actual_arg_bounds;
        Nodecl::List subscripts = arg.as<Nodecl::ArraySubscript>().get_subscripts().as<Nodecl::List>();
        for (Nodecl::List::reverse_iterator it = subscripts.rbegin();
                it != subscripts.rend();
                it++)
        {
            Nodecl::NodeclBase subscript = *it, lower, upper;

            if (it != subscripts.rbegin())
                actual_arg_bounds << ", ";

            if (subscript.is<Nodecl::Range>())
            {
                lower = subscript.as<Nodecl::Range>().get_lower();
                upper = subscript.as<Nodecl::Range>().get_upper();
            }
            else
            {
                lower = nodecl_make_integer_literal(
                        fortran_get_default_integer_type(),
                        const_value_get_signed_int(1), make_locus("", 0, 0));
                upper = subscript;
            }
            actual_arg_bounds << as_expression(lower) << "," << as_expression(upper);
        }

        TL::Source new_function_call;
        new_function_call
            << "CALL " << as_symbol(new_function_sym) << "("
            <<  actual_arg_array  << ", "
            <<  actual_arg_bounds << ")\n"
            ;

        expr_stmt.replace(new_function_call.parse_statement(expr_stmt));

    }
        void VectorizerVisitorExpression::visit(const Nodecl::FunctionCall& n)
        {
            Nodecl::NodeclBase called = n.get_called();
            ERROR_CONDITION(!called.is<Nodecl::Symbol>(),
                    "Vectorizer: %s found. This kind of function call is not supported yet",
                    ast_print_node_type(called.get_kind()));

            Nodecl::Symbol called_sym = called.as<Nodecl::Symbol>();

            // Vectorizing arguments
            walk(n.get_arguments());

            // Special functions
            if (called_sym.get_symbol().get_name() == "fabsf")
            {
                const Nodecl::VectorFabs vector_fabs_call =
                    Nodecl::VectorFabs::make(
                            n.get_arguments().as<Nodecl::List>().front().shallow_copy(),
                            get_qualified_vector_to(n.get_type(), _vector_length),
                            n.get_locus());

                n.replace(vector_fabs_call);
            }
            else //Common functions
            {
                // Get the best vector version of the function available
                Nodecl::NodeclBase best_version =
                    TL::Vectorization::Vectorizer::_function_versioning.get_best_version(
                            called_sym.get_symbol().get_name(), _device, _vector_length, _target_type);

                ERROR_CONDITION(best_version.is_null(), "Vectorizer: the best vector function for '%s' is null",
                        called_sym.get_symbol().get_name().c_str());

                // Create new called symbol
                Nodecl::Symbol new_called;
                if (best_version.is<Nodecl::FunctionCode>())
                {
                    new_called = best_version.as<Nodecl::FunctionCode>().get_symbol().
                        make_nodecl(n.get_locus());
                }
                else if (best_version.is<Nodecl::Symbol>())
                {
                    new_called = best_version.as<Nodecl::Symbol>().get_symbol().
                        make_nodecl(n.get_locus());
                }
                else
                {
                    running_error("Vectorizer: %s found as vector function version in function versioning.",
                            ast_print_node_type(best_version.get_kind()));
                }

                const Nodecl::VectorFunctionCall vector_function_call =
                    Nodecl::VectorFunctionCall::make(
                            new_called,
                            n.get_arguments().shallow_copy(),
                            n.get_alternate_name().shallow_copy(),
                            n.get_function_form().shallow_copy(),
                            get_qualified_vector_to(n.get_type(), _vector_length),
                            n.get_locus());

                n.replace(vector_function_call);
            }
        }