Nodecl::NodeclBase handle_task_statements(
          Nodecl::NodeclBase construct,
          Nodecl::NodeclBase task_statements,
          Nodecl::NodeclBase& task_placeholder, // Do not remove the reference
          TL::Source &new_stmts_src,            // It should be a const reference
          const std::map<TL::Symbol, std::string> &reduction_symbols_map)
    {
       if (IS_FORTRAN_LANGUAGE)
          Source::source_language = SourceLanguage::C;

       Nodecl::NodeclBase new_statements = new_stmts_src.parse_statement(construct);

       if (IS_FORTRAN_LANGUAGE)
          Source::source_language = SourceLanguage::Current;

       TL::Scope new_scope = ReferenceScope(task_placeholder).get_scope();
       std::map<TL::Symbol, Nodecl::NodeclBase> reduction_symbol_to_nodecl_map;
       for (std::map<TL::Symbol, std::string>::const_iterator it = reduction_symbols_map.begin();
             it != reduction_symbols_map.end();
             ++it)
       {
          TL::Symbol reduction_sym = it->first;
          std::string storage_name = it->second;
          TL::Symbol storage_sym = new_scope.get_symbol_from_name(storage_name);
          ERROR_CONDITION(!storage_sym.is_valid(), "This symbol is not valid", 0);

          Nodecl::NodeclBase deref_storage = Nodecl::Dereference::make(
                storage_sym.make_nodecl(/* set_ref_type */ true, storage_sym.get_locus()),
                storage_sym.get_type().points_to());

          reduction_symbol_to_nodecl_map[reduction_sym] = deref_storage;
       }

       ReplaceReductionSymbols visitor(reduction_symbol_to_nodecl_map);
       Nodecl::NodeclBase copied_statements = task_statements.shallow_copy();
       visitor.walk(copied_statements);
       task_placeholder.replace(copied_statements);

       return new_statements;
    }
Ejemplo n.º 2
0
    TL::Symbol LoweringVisitor::create_reduction_cleanup_function(OpenMP::Reduction* red, Nodecl::NodeclBase construct)
    {
        if (IS_C_LANGUAGE || IS_CXX_LANGUAGE)
        {
            internal_error("Currently only valid in Fortran", 0);
        }
        reduction_map_t::iterator it = _reduction_cleanup_map.find(red);
        if (it != _reduction_cleanup_map.end())
        {
            return it->second;
        }

        std::string fun_name;
        {
            std::stringstream ss;
            ss << "nanos_cleanup_" << red << "_" << simple_hash_str(construct.get_filename().c_str());
            fun_name = ss.str();
        }


        Source src;
        src << "SUBROUTINE " << fun_name << "(X)\n"
            <<     as_type(red->get_type()) << ", POINTER ::  X(:)\n"
            <<     "DEALLOCATE(X)\n"
            << "END SUBROUTINE\n"
            ;

        Nodecl::NodeclBase function_code = src.parse_global(construct);

        TL::Symbol function_sym = ReferenceScope(construct).get_scope().get_symbol_from_name(fun_name);
        ERROR_CONDITION(!function_sym.is_valid(), "Symbol %s not found", fun_name.c_str());

        _reduction_cleanup_map[red] = function_sym;

        Nodecl::Utils::append_to_enclosing_top_level_location(construct, function_code);

        Nodecl::Utils::Fortran::append_used_modules(construct.retrieve_context(), function_sym.get_related_scope());

        return function_sym;
    }
    static TL::Symbol create_initializer_function_c(
            OpenMP::Reduction* red,
            TL::Type reduction_type,
            Nodecl::NodeclBase construct)
    {
        std::string fun_name;
        {
            std::stringstream ss;
            ss << "nanos_ini_" << red << "_" << reduction_type.get_internal_type() << "_" << simple_hash_str(construct.get_filename().c_str());
            fun_name = ss.str();
        }

        Nodecl::NodeclBase function_body;
        Source src;
        src << "void " << fun_name << "("
            <<      as_type(reduction_type.no_ref().get_lvalue_reference_to()) << " omp_priv,"
            <<      as_type(reduction_type.no_ref().get_lvalue_reference_to()) << " omp_orig)"
            << "{"
            <<    statement_placeholder(function_body)
            << "}"
            ;

        Nodecl::NodeclBase function_code = src.parse_global(construct.retrieve_context().get_global_scope());

        TL::Scope inside_function = ReferenceScope(function_body).get_scope();
        TL::Symbol param_omp_priv = inside_function.get_symbol_from_name("omp_priv");
        ERROR_CONDITION(!param_omp_priv.is_valid(), "Symbol omp_priv not found", 0);

        TL::Symbol param_omp_orig = inside_function.get_symbol_from_name("omp_orig");
        ERROR_CONDITION(!param_omp_orig.is_valid(), "Symbol omp_orig not found", 0);

        TL::Symbol function_sym = inside_function.get_symbol_from_name(fun_name);
        ERROR_CONDITION(!function_sym.is_valid(), "Symbol %s not found", fun_name.c_str());

        Nodecl::NodeclBase initializer = red->get_initializer().shallow_copy();
        if (initializer.is<Nodecl::StructuredValue>())
        {
            Nodecl::StructuredValue structured_value = initializer.as<Nodecl::StructuredValue>();
            if (structured_value.get_form().is<Nodecl::StructuredValueBracedImplicit>())
            {
                structured_value.set_form(Nodecl::StructuredValueCompoundLiteral::make());
            }
        }

        Nodecl::Utils::SimpleSymbolMap translation_map;

        translation_map.add_map(red->get_omp_priv(), param_omp_priv);
        translation_map.add_map(red->get_omp_orig(), param_omp_orig);

        Nodecl::NodeclBase new_initializer = Nodecl::Utils::deep_copy(initializer, inside_function, translation_map);

        if (red->get_is_initialization())
        {
            // The original initializer was something like 'omp_priv = expr1', but the
            // new_initializer only represents the lhs expression (in our example, expr1).
            // For this reason we create manually an assignment expression.
            Nodecl::NodeclBase param_omp_priv_ref = Nodecl::Symbol::make(param_omp_priv);
            param_omp_priv_ref.set_type(param_omp_priv.get_type());

            function_body.replace(
                    Nodecl::List::make(
                        Nodecl::ExpressionStatement::make(
                            Nodecl::Assignment::make(
                                param_omp_priv_ref,
                                new_initializer,
                                param_omp_priv_ref.get_type().no_ref())
                            )));
        }
        else
        {
            function_body.replace(
                    Nodecl::List::make(Nodecl::ExpressionStatement::make(new_initializer)));
        }

        // As the initializer function is needed during the instantiation of
        // the task, this function should be inserted before the construct
        Nodecl::Utils::prepend_to_enclosing_top_level_location(construct,
                function_code);

        return function_sym;
    }
Ejemplo n.º 4
0
    static Symbol create_new_function_opencl_allocate(
            Nodecl::NodeclBase expr_stmt,
            Symbol subscripted_symbol,
            Type element_type,
            int num_dimensions,
            bool is_allocatable)
    {
        std::string alloca_or_pointer = is_allocatable ? "ALLOCATABLE" : "POINTER";

        TL::Source dummy_arguments_bounds, dimension_attr, allocate_dims;
        dimension_attr << "DIMENSION(";
        for (int i = 1; i <= num_dimensions; ++i)
        {
            if (i != 1)
            {
                allocate_dims << ", ";
                dummy_arguments_bounds <<", ";
                dimension_attr << ", ";
            }

            dummy_arguments_bounds <<"LB" << i <<", " << "UB" << i;
            dimension_attr << ":";
            allocate_dims << "LB" << i << ":" << "UB" << i;
        }
        dimension_attr << ")";

        size_t size_of_array_descriptor =
            fortran_size_of_array_descriptor(
                    fortran_get_rank0_type(subscripted_symbol.get_type().get_internal_type()),
                    fortran_get_rank_of_type(subscripted_symbol.get_type().get_internal_type()));

        TL::Source new_function_name;
        new_function_name
            << "NANOX_OPENCL_ALLOCATE_INTERNAL_"
            << (ptrdiff_t) subscripted_symbol.get_internal_symbol()
            ;

        Nodecl::NodeclBase nodecl_body;
        TL::Source new_function;
        new_function
            << "SUBROUTINE " << new_function_name << "(ARR, " << dummy_arguments_bounds  << ")\n"
            <<      as_type(element_type) << ", " << dimension_attr << ", " << alloca_or_pointer << " :: ARR\n"
            <<      as_type(element_type) << ", " << dimension_attr << ", ALLOCATABLE :: TMP\n"
            <<      "INTEGER :: " << dummy_arguments_bounds << "\n"
            <<      "INTEGER :: ERR \n"
            <<      "ALLOCATE(TMP(" << allocate_dims << "))\n"
            <<      statement_placeholder(nodecl_body)
            <<      "DEALLOCATE(TMP)\n"
            << "END SUBROUTINE " << new_function_name << "\n"
            ;

        Nodecl::NodeclBase function_code = new_function.parse_global(expr_stmt.retrieve_context().get_global_scope());

        TL::Scope inside_function = ReferenceScope(nodecl_body).get_scope();
        TL::Symbol new_function_sym = inside_function.get_symbol_from_name(strtolower(new_function_name.get_source().c_str()));
        TL::Symbol arr_sym = inside_function.get_symbol_from_name("arr");
        TL::Symbol tmp_sym = inside_function.get_symbol_from_name("tmp");
        TL::Symbol ptr_of_arr_sym = get_function_ptr_of(arr_sym, inside_function);
        TL::Symbol ptr_of_tmp_sym = get_function_ptr_of(tmp_sym, inside_function);

        TL::Source aux;
        aux
            <<  "ERR = NANOS_MEMCPY("
            <<          ptr_of_arr_sym.get_name() << "(ARR),"
            <<          ptr_of_tmp_sym.get_name() << "(TMP),"
            <<          "INT(" << size_of_array_descriptor << "," << type_get_size(get_ptrdiff_t_type()) << "))\n"

            <<  "CALL NANOS_OPENCL_ALLOCATE_FORTRAN("
            <<          "SIZEOF(TMP),"
            <<          ptr_of_arr_sym.get_name() << "(ARR))\n"
            ;

        nodecl_body.replace(aux.parse_statement(inside_function));
        Nodecl::Utils::prepend_to_enclosing_top_level_location(expr_stmt, function_code);

        return new_function_sym;
    }
Ejemplo n.º 5
0
    TL::Symbol LoweringVisitor::create_basic_reduction_function_fortran(OpenMP::Reduction* red, Nodecl::NodeclBase construct)
    {
        reduction_map_t::iterator it = _basic_reduction_map_openmp.find(red);
        if (it != _basic_reduction_map_openmp.end())
        {
            return it->second;
        }

        std::string fun_name;
        {
            std::stringstream ss;
            ss << "nanos_red_" << red << "_" << simple_hash_str(construct.get_filename().c_str());
            fun_name = ss.str();
        }

        Nodecl::NodeclBase function_body;
        Source src;

        src << "SUBROUTINE " << fun_name << "(omp_out, omp_in, num_scalars)\n"
            <<    "IMPLICIT NONE\n"
            <<    as_type(red->get_type()) << " :: omp_out(num_scalars)\n" 
            <<    as_type(red->get_type()) << " :: omp_in(num_scalars)\n"
            <<    "INTEGER, VALUE :: num_scalars\n"
            <<    "INTEGER :: I\n"
            <<    statement_placeholder(function_body) << "\n"
            << "END SUBROUTINE " << fun_name << "\n";
        ;

        Nodecl::NodeclBase function_code = src.parse_global(construct);

        TL::Scope inside_function = ReferenceScope(function_body).get_scope();
        TL::Symbol param_omp_in = inside_function.get_symbol_from_name("omp_in");
        ERROR_CONDITION(!param_omp_in.is_valid(), "Symbol omp_in not found", 0);
        TL::Symbol param_omp_out = inside_function.get_symbol_from_name("omp_out");
        ERROR_CONDITION(!param_omp_out.is_valid(), "Symbol omp_out not found", 0);

        TL::Symbol function_sym = inside_function.get_symbol_from_name(fun_name);
        ERROR_CONDITION(!function_sym.is_valid(), "Symbol %s not found", fun_name.c_str());

        TL::Symbol index = inside_function.get_symbol_from_name("i");
        ERROR_CONDITION(!index.is_valid(), "Symbol %s not found", "i");
        TL::Symbol num_scalars = inside_function.get_symbol_from_name("num_scalars");
        ERROR_CONDITION(!num_scalars.is_valid(), "Symbol %s not found", "num_scalars");

        Nodecl::NodeclBase num_scalars_ref = Nodecl::Symbol::make(num_scalars);

        num_scalars_ref.set_type(num_scalars.get_type().no_ref().get_lvalue_reference_to());

        Nodecl::Symbol nodecl_index = Nodecl::Symbol::make(index);
        nodecl_index.set_type(index.get_type().get_lvalue_reference_to());

        Nodecl::NodeclBase loop_header = Nodecl::RangeLoopControl::make(
                nodecl_index,
                const_value_to_nodecl(const_value_get_signed_int(1)),
                num_scalars_ref,
                Nodecl::NodeclBase::null());

        Nodecl::NodeclBase expanded_combiner =
            red->get_combiner().shallow_copy();
        BasicReductionExpandVisitor expander_visitor(
                red->get_omp_in(),
                param_omp_in,
                red->get_omp_out(),
                param_omp_out,
                index);
        expander_visitor.walk(expanded_combiner);

        function_body.replace(
                Nodecl::ForStatement::make(loop_header,
                    Nodecl::List::make(
                        Nodecl::ExpressionStatement::make(
                            expanded_combiner)),
                    Nodecl::NodeclBase::null()));

        _basic_reduction_map_openmp[red] = function_sym;

        if (IS_FORTRAN_LANGUAGE)
        {
            Nodecl::Utils::Fortran::append_used_modules(construct.retrieve_context(),
                    function_sym.get_related_scope());
        }

        Nodecl::Utils::append_to_enclosing_top_level_location(construct, function_code);

        return function_sym;
    }