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; }
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; }
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; }
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; }