Пример #1
0
        // This function is invoked only for inline tasks (and some other
        // constructs though target info is unused for them)
        void Core::ompss_get_target_info(TL::PragmaCustomLine construct,
                DataEnvironment& data_sharing_environment)
        {
            if (_target_context.empty())
                return;

            TL::OmpSs::TargetInfo target_info;

            TL::Symbol enclosing_function = Nodecl::Utils::get_enclosing_function(construct);
            ERROR_CONDITION(!enclosing_function.is_valid(), "This symbol is not valid", 0);
            target_info.set_target_symbol(enclosing_function);
            OmpSs::TargetContext& target_ctx = _target_context.top();

            add_copy_items(construct, data_sharing_environment,
                    target_ctx.copy_in,
                    TL::OmpSs::COPY_DIR_IN,
                    target_info,
                    in_ompss_mode());

            add_copy_items(construct, data_sharing_environment,
                    target_ctx.copy_out,
                    TL::OmpSs::COPY_DIR_OUT,
                    target_info,
                    in_ompss_mode());

            add_copy_items(construct, data_sharing_environment,
                    target_ctx.copy_inout,
                    TL::OmpSs::COPY_DIR_INOUT,
                    target_info,
                    in_ompss_mode());

            target_info.set_file(target_ctx.file);
            target_info.set_name(target_ctx.name);
            target_info.append_to_ndrange(target_ctx.ndrange);
            target_info.append_to_shmem(target_ctx.shmem);
            target_info.append_to_onto(target_ctx.onto);
            target_info.append_to_device_list(target_ctx.device_list);

            // Set data sharings for referenced entities in copies
            if (target_ctx.copy_deps == OmpSs::TargetContext::COPY_DEPS)
            {
                // Copy the dependences, as well

                ObjectList<DependencyItem> dependences;
                data_sharing_environment.get_all_dependences(dependences);

                ObjectList<Nodecl::NodeclBase> dep_list_in;
                ObjectList<Nodecl::NodeclBase> dep_list_out;
                ObjectList<Nodecl::NodeclBase> dep_list_inout;
                ObjectList<Nodecl::NodeclBase> dep_list_weakin;
                ObjectList<Nodecl::NodeclBase> dep_list_weakout;
                ObjectList<Nodecl::NodeclBase> dep_list_weakinout;
                ObjectList<Nodecl::NodeclBase> dep_list_reductions;
                for (ObjectList<DependencyItem>::iterator it = dependences.begin();
                        it != dependences.end();
                        it++)
                {
                    ObjectList<Nodecl::NodeclBase>* p = NULL;
                    switch (it->get_kind())
                    {
                        case DEP_DIR_IN:
                        case DEP_OMPSS_DIR_IN_PRIVATE:
                            {
                                p = &dep_list_in;
                                break;
                            }
                        case DEP_DIR_OUT:
                            {
                                p = &dep_list_out;
                                break;
                            }
                        case DEP_DIR_INOUT:
                            // OmpSs
                        case DEP_OMPSS_CONCURRENT:
                        case DEP_OMPSS_COMMUTATIVE:
                        case DEP_OMPSS_REDUCTION:
                            {
                                p = &dep_list_inout;
                                break;
                            }
                        case DEP_OMPSS_WEAK_IN:
                            {
                                p = &dep_list_weakin;
                                break;
                            }
                        case DEP_OMPSS_WEAK_OUT:
                            {
                                p = &dep_list_weakout;
                                break;
                            }
                        case DEP_OMPSS_WEAK_INOUT:
                        case DEP_OMPSS_WEAK_COMMUTATIVE:
                            {
                                p = &dep_list_weakinout;
                                break;
                            }
                        default:
                            {
                                internal_error("Invalid dependency kind", 0);
                            }
                    }

                    p->append(*it);
                }

                add_copy_items(construct, data_sharing_environment,
                        dep_list_in,
                        TL::OmpSs::COPY_DIR_IN,
                        target_info,
                        in_ompss_mode());

                add_copy_items(construct, data_sharing_environment,
                        dep_list_out,
                        TL::OmpSs::COPY_DIR_OUT,
                        target_info,
                        in_ompss_mode());

                add_copy_items(construct, data_sharing_environment,
                        dep_list_inout,
                        TL::OmpSs::COPY_DIR_INOUT,
                        target_info,
                        in_ompss_mode());

                if (!dep_list_weakin.empty()
                        || !dep_list_weakout.empty()
                        || !dep_list_weakinout.empty())
                {
                    warn_printf_at(construct.get_locus(),
                            "weak dependences are not considered yet for copy_deps\n");
                }
            }

            if (this->in_ompss_mode()
                    && (target_ctx.copy_deps == OmpSs::TargetContext::COPY_DEPS
                        || !target_ctx.copy_in.empty()
                        || !target_ctx.copy_out.empty()
                        || !target_ctx.copy_inout.empty())
                    && !_allow_shared_without_copies)
            {
                ObjectList<TL::OmpSs::CopyItem> all_copies;
                all_copies.append(target_info.get_copy_in());
                all_copies.append(target_info.get_copy_out());
                all_copies.append(target_info.get_copy_inout());

                ObjectList<Symbol> all_copied_syms = all_copies.map<TL::Symbol>(&DataReference::get_base_symbol);

                // In devices with disjoint memory, it may be wrong to use a
                // global variables inside a pragma task without copying it.
                ObjectList<Symbol> ds_syms;
                data_sharing_environment.get_all_symbols(DS_SHARED, ds_syms);

                for(ObjectList<Symbol>::iterator io_it = ds_syms.begin(); 
                        io_it != ds_syms.end(); 
                        io_it++)
                {
                    // Ignore 'this'
                    if (IS_CXX_LANGUAGE
                            && io_it->get_name() == "this")
                    {
                        continue;
                    }

                    if (!all_copied_syms.contains(*io_it))
                    {
                        warn_printf_at(
                                construct.get_locus(),
                                "symbol '%s' has shared data-sharing but does not have"
                                " copy directionality. This may cause problems at run-time\n",
                                io_it->get_qualified_name().c_str());
                    }
                }
            }

            // Store the target information in the current data sharing
            data_sharing_environment.set_target_info(target_info);
        }
Пример #2
0
        void Core::ompss_common_target_handler_pre(TL::PragmaCustomLine pragma_line,
                OmpSs::TargetContext& target_ctx,
                TL::Scope scope,
                bool is_pragma_task)
        {
            PragmaCustomClause onto = pragma_line.get_clause("onto");
            if (onto.is_defined())
            {
                target_ctx.onto = onto.get_arguments_as_expressions(scope);
            }

            PragmaCustomClause device = pragma_line.get_clause("device");
            if (device.is_defined())
            {
                ObjectList<std::string> device_list =
                    device.get_tokenized_arguments()
                          .map<const char *>(&std::string::c_str)
                          .map<std::string>(&strtolower);

                target_ctx.device_list.insert(device_list);
            }
            else
            {
                // In #pragma omp target a device is mandatory, for #pragma omp task
                // add it only if not empty
                std::string default_device = "smp";
                bool set_default_device = false;
                if (!is_pragma_task)
                {
                    warn_printf_at(pragma_line.get_locus(),
                            "'#pragma omp target' without 'device' clause. Assuming 'device(smp)'\n");
                    set_default_device = true;
                }
                else if (target_ctx.device_list.empty())
                {
                    set_default_device = true;
                    //If onto is defined and there is no device, default device is MPI
                    if (onto.is_defined()) default_device = "mpi";
                }

                if (set_default_device)
                {
                    target_ctx.device_list.clear();
                    target_ctx.device_list.append(default_device);
                }
            }

            PragmaCustomClause copy_in = pragma_line.get_clause("copy_in");
            if (copy_in.is_defined())
            {
                target_ctx.copy_in = parse_dependences_ompss_clause(copy_in, scope);
            }

            PragmaCustomClause copy_out = pragma_line.get_clause("copy_out");
            if (copy_out.is_defined())
            {
                target_ctx.copy_out = parse_dependences_ompss_clause(copy_out, scope);
            }

            PragmaCustomClause copy_inout = pragma_line.get_clause("copy_inout");
            if (copy_inout.is_defined())
            {
                target_ctx.copy_inout = parse_dependences_ompss_clause(copy_inout, scope);
            }

            PragmaCustomClause ndrange = pragma_line.get_clause("ndrange");
            if (ndrange.is_defined())
            {
                target_ctx.ndrange = ndrange.get_arguments_as_expressions(scope);
            }

            PragmaCustomClause shmem = pragma_line.get_clause("shmem");
            if (shmem.is_defined())
            {
                if (ndrange.is_defined())
                {
                    target_ctx.shmem = shmem.get_arguments_as_expressions(scope);
                }
                else
                {
                    warn_printf_at(pragma_line.get_locus(), "'shmem' clause cannot be used without the 'ndrange' clause, skipping\n");
                }
            }

            PragmaCustomClause file = pragma_line.get_clause("file");
            if (file.is_defined())
            {
                ObjectList<std::string> file_list = file.get_tokenized_arguments();
                if (file_list.size() != 1)
                {
                    warn_printf_at(pragma_line.get_locus(), "clause 'file' expects one identifier, skipping\n");
                }
                else
                {
                    target_ctx.file = file_list[0];
                }
            }

            PragmaCustomClause name = pragma_line.get_clause("name");
            if (name.is_defined())
            {
                ObjectList<std::string> name_list = name.get_tokenized_arguments();
                if (name_list.size() != 1)
                {
                    warn_printf_at(pragma_line.get_locus(), "clause 'name' expects one identifier, skipping\n");
                }
                else
                {
                    target_ctx.name = name_list[0];
                }
            }

            PragmaCustomClause copy_deps = pragma_line.get_clause("copy_deps");
            PragmaCustomClause no_copy_deps = pragma_line.get_clause("no_copy_deps");

            if (target_ctx.copy_deps == OmpSs::TargetContext::UNDEF_COPY_DEPS)
            {
                target_ctx.copy_deps = OmpSs::TargetContext::NO_COPY_DEPS;

                if (!copy_deps.is_defined()
                        && !no_copy_deps.is_defined())
                {
                    if (this->in_ompss_mode()
                            && _copy_deps_by_default)
                    {
                        // Copy deps is true only if there is no copy_in, copy_out
                        // or copy_inout
                        if ( !copy_in.is_defined()
                                && !copy_out.is_defined()
                                && !copy_inout.is_defined())
                        {
                            target_ctx.copy_deps = OmpSs::TargetContext::COPY_DEPS;

                            if (!_already_informed_new_ompss_copy_deps)
                            {
                                info_printf_at(pragma_line.get_locus(),
                                        "unless 'no_copy_deps' is specified, "
                                        "the default in OmpSs is now 'copy_deps'\n");
                                info_printf_at(pragma_line.get_locus(),
                                        "this diagnostic is only shown for the "
                                        "first task found\n");

                                _already_informed_new_ompss_copy_deps = true;
                            }
                        }
                    }
                }
                else if (copy_deps.is_defined())
                {
                    target_ctx.copy_deps = OmpSs::TargetContext::COPY_DEPS;
                }
                else if (no_copy_deps.is_defined())
                {
                    target_ctx.copy_deps = OmpSs::TargetContext::NO_COPY_DEPS;
                }
                else
                {
                    internal_error("Code unreachable", 0);
                }
            }
            else if (target_ctx.copy_deps == OmpSs::TargetContext::NO_COPY_DEPS
                    || target_ctx.copy_deps == OmpSs::TargetContext::COPY_DEPS)
            {
                if (copy_deps.is_defined())
                {
                    warn_printf_at(pragma_line.get_locus(),
                            "ignoring 'copy_deps' clause because this context is already '%s'\n",
                            target_ctx.copy_deps == OmpSs::TargetContext::NO_COPY_DEPS ? "no_copy_deps" : "copy_deps");
                }
                if (no_copy_deps.is_defined())
                {
                    warn_printf_at(pragma_line.get_locus(),
                            "ignoring 'no_copy_deps' clause because this context is already '%s'\n",
                            target_ctx.copy_deps == OmpSs::TargetContext::NO_COPY_DEPS ? "no_copy_deps" : "copy_deps");
                }
            }
            else
            {
                internal_error("Code unreachable", 0);
            }
            ERROR_CONDITION(target_ctx.copy_deps == OmpSs::TargetContext::UNDEF_COPY_DEPS,
                    "Invalid value for copy_deps at this point", 0)

            PragmaCustomClause implements = pragma_line.get_clause("implements");
            if (implements.is_defined())
            {
                Symbol function_symbol (NULL);
                if (IS_C_LANGUAGE
                        || IS_CXX_LANGUAGE)
                {
                    ObjectList<Nodecl::NodeclBase> implements_list = implements.get_arguments_as_expressions(scope);

                    ERROR_CONDITION(implements_list.size() != 1, "clause 'implements' expects one identifier", 0);

                    Nodecl::NodeclBase implements_name = implements_list[0];

                    if (implements_name.is<Nodecl::Symbol>())
                    {
                        function_symbol = implements_name.get_symbol();
                    }
                    else if (implements_name.is<Nodecl::CxxDepNameSimple>())
                    {
                        ObjectList<TL::Symbol> symbols = scope.get_symbols_from_name(implements_name.get_text());

                        ERROR_CONDITION(symbols.size() != 1,
                                "The argument of the clause 'implements' cannot be an overloaded function identifier", 0);

                        function_symbol = symbols[0];
                    }
                    else
                    {
                        internal_error("Unexpected node", 0);
                    }
                }
                else if (IS_FORTRAN_LANGUAGE)
                {
                    ObjectList<std::string> implements_list = implements.get_tokenized_arguments();

                    ERROR_CONDITION(implements_list.size() != 1, "clause 'implements' expects one identifier", 0);

                    // Restore the scope chain we broke in an INTERFACE block
                    const decl_context_t* decl_context = scope.get_decl_context();
                    TL::Symbol current_procedure = scope.get_related_symbol();
                    decl_context->current_scope->contained_in = current_procedure.get_internal_symbol()->decl_context->current_scope;

                    TL::Scope fixed_scope = TL::Scope(decl_context);

                    ObjectList<TL::Symbol> symbols = fixed_scope.get_symbols_from_name(strtolower(implements_list[0].c_str()));

                    ERROR_CONDITION(symbols.size() != 1,"Unreachable code", 0);

                    function_symbol = symbols[0];
                }
                else
                {
                    internal_error("Unreachable code", 0);
                }

                if (function_symbol.is_valid()
                        && function_symbol.is_function())
                {
                    target_ctx.has_implements = true;
                    target_ctx.implements = function_symbol;
                }
                else
                {
                    warn_printf_at(pragma_line.get_locus(), "the argument of the clause 'implements' is not a valid identifier, skipping\n");
                }
            }
        }