Type Type::get_array_to_with_region(Nodecl::NodeclBase lower_bound,
            Nodecl::NodeclBase upper_bound,
            Nodecl::NodeclBase region_lower_bound,
            Nodecl::NodeclBase region_upper_bound,
            Scope sc)
    {
        type_t* result_type = this->_type_info;

        const decl_context_t* decl_context = sc.get_decl_context();

        // Make the range of the region
        Nodecl::NodeclBase range = Nodecl::Range::make(
                region_lower_bound,
                region_upper_bound,
                const_value_to_nodecl(const_value_get_one(4, 1)),
                region_lower_bound.get_type(),
                region_lower_bound.get_locus());

        type_t* array_to = get_array_type_bounds_with_regions(
                result_type,
                lower_bound.get_internal_nodecl(),
                upper_bound.get_internal_nodecl(),
                decl_context,
                range.get_internal_nodecl(),
                decl_context);

        return array_to;
    }
    void Lower::lower_taskwait_with_dependences(const Nodecl::OpenMP::Taskwait& node)
    {
        Nodecl::List environment = node.get_environment().as<Nodecl::List>();

        // Prepare if(0) task reusing environment and set TaskIsTaskwait flag
        Nodecl::NodeclBase zero_expr;
        if(IS_C_LANGUAGE || IS_CXX_LANGUAGE)
        {
            zero_expr = const_value_to_nodecl(const_value_get_unsigned_int(0));
        }
        else  // IS_FORTRAN_LANGUAGE
        {
            zero_expr = Nodecl::BooleanLiteral::make(
                    TL::Type::get_bool_type(),
                    const_value_get_zero(/* bytes */ 4, /* sign */0));
        }
        environment.append(Nodecl::OpenMP::If::make(zero_expr));
        environment.append(Nodecl::OpenMP::TaskIsTaskwait::make());

        Nodecl::OpenMP::Task taskwait_task = Nodecl::OpenMP::Task::make(
                environment,
                Nodecl::List::make(Nodecl::EmptyStatement::make()),
                node.get_locus());

        node.replace(taskwait_task);
        lower_task(node.as<Nodecl::OpenMP::Task>());
    }
    void Lower::lower_taskwait(const Nodecl::OpenMP::Taskwait& node)
    {
        TL::Symbol nanos_taskwait_sym =
            TL::Scope::get_global_scope().get_symbol_from_name("nanos_taskwait");
        ERROR_CONDITION(!nanos_taskwait_sym.is_valid()
                || !nanos_taskwait_sym.is_function(),
                "Invalid symbol", 0);
        const char* locus = locus_to_str(node.get_locus());

        Nodecl::NodeclBase taskwait_tree =
            Nodecl::ExpressionStatement::make(
                    Nodecl::FunctionCall::make(
                        nanos_taskwait_sym.make_nodecl(/* set_ref_type */ true, node.get_locus()),
                        /* args */ Nodecl::List::make(
                            const_value_to_nodecl(
                                const_value_make_string_null_ended(
                                    locus,
                                    strlen(locus)))),
                        /* alternate-name */ Nodecl::NodeclBase::null(),
                        /* function-form */ Nodecl::NodeclBase::null(),
                        TL::Type::get_void_type(),
                        node.get_locus()));

        node.replace(taskwait_tree);
    }
        TL::Type get_array_of_vector(TL::Type t)
        {
            ERROR_CONDITION(!t.is_vector(), "Invalid type", 0);

            return t.vector_element().get_array_to(
                    const_value_to_nodecl(
                        const_value_get_signed_int(t.vector_num_elements())
                        ),
                    TL::Scope::get_global_scope());
        }
        TL::Type get_array_of_mask(TL::Type t)
        {
            ERROR_CONDITION(!t.is_mask(), "Invalid type", 0);

            int n = (t.get_mask_num_elements() / 8)
                + !!(t.get_mask_num_elements() % 8);

            return TL::Type::get_unsigned_char_type().get_array_to(
                    const_value_to_nodecl(
                        const_value_get_signed_int(n)
                        ),
                    TL::Scope::get_global_scope());
        }
        void VectorizerVisitorExpression::visit(const Nodecl::Symbol& n)
        {
            TL::Type sym_type = n.get_type();

            //std::cerr << "scalar_type: " << n.prettyprint() << std::endl;

            if (!sym_type.is_vector())
            {
               // Vectorize BASIC induction variable
                if (Vectorizer::_analysis_info->is_basic_induction_variable(
                            Vectorizer::_analysis_scopes->back(),
                            n))
                {
                    std::cerr << "Basic IV: " << n.prettyprint() << "\n";

                    // Computing IV offset {0, 1, 2, 3}
                    TL::ObjectList<Nodecl::NodeclBase> literal_list;

                    const_value_t *ind_var_increment = Vectorizer::_analysis_info->get_induction_variable_increment(
                            Vectorizer::_analysis_scopes->back(), n);

                    for(const_value_t *i = const_value_get_zero(4, 0);
                            const_value_is_nonzero(const_value_lt(i, const_value_get_unsigned_int(_unroll_factor)));
                            i = const_value_add(i, ind_var_increment))
                    {
                        literal_list.prepend(const_value_to_nodecl(i));
                    }

                    Nodecl::List offset = Nodecl::List::make(literal_list);

                    // IV cannot be a reference
                    TL::Type ind_var_type = get_qualified_vector_to(n.get_type(), _vector_length).no_ref();

                    TL::Type offset_type = ind_var_type;

                    Nodecl::ParenthesizedExpression vector_induction_var =
                        Nodecl::ParenthesizedExpression::make(
                                Nodecl::VectorAdd::make(
                                    Nodecl::VectorPromotion::make(
                                        n.shallow_copy(),
                                        ind_var_type,
                                        n.get_locus()),
                                    Nodecl::VectorLiteral::make(
                                        offset,
                                        offset_type,
                                        n.get_locus()),
                                    get_qualified_vector_to(n.get_type(), _vector_length),
                                    n.get_locus()),
                                get_qualified_vector_to(n.get_type(), _vector_length),
                                n.get_locus());

                    n.replace(vector_induction_var);
                }
                // Vectorize symbols declared in the SIMD scope
                else if (is_declared_in_scope(
                            _simd_inner_scope.get_decl_context().current_scope,
                            n.get_symbol().get_scope().get_decl_context().current_scope))
                {
                    //std::cerr << "NS scalar_type: " << n.prettyprint() << std::endl;

                    TL::Symbol tl_sym = n.get_symbol();
                    TL::Type tl_sym_type = tl_sym.get_type();

                    //TL::Symbol
                    if (tl_sym_type.is_scalar_type())
                    {
                        //std::cerr << "TS scalar_type: " << n.prettyprint() << std::endl;
                        tl_sym.set_type(get_qualified_vector_to(tl_sym_type, _vector_length));
                        tl_sym_type = tl_sym.get_type();
                    }

                    //Nodecl::Symbol
                    Nodecl::Symbol new_sym =
                        Nodecl::Symbol::make(tl_sym,
                                n.get_locus());

                    new_sym.set_type(tl_sym_type.get_lvalue_reference_to());

                    n.replace(new_sym);
                }
                // Vectorize constants
                else if (Vectorizer::_analysis_info->is_constant(
                            Vectorizer::_analysis_scopes->back(),
                            n))
                {
                    const Nodecl::VectorPromotion vector_prom =
                        Nodecl::VectorPromotion::make(
                                n.shallow_copy(),
                                get_qualified_vector_to(sym_type, _vector_length),
                                n.get_locus());

                    n.replace(vector_prom);
                }
                else
                {
                    //TODO: If you are from outside of the loop -> Vector local copy.
                    running_error("Vectorizer: Loop is not vectorizable. '%s' is not IV or Constant or Local.",
                            n.get_symbol().get_name().c_str());
                }
            }
        }
    void LoopNormalize::normalize()
    {
        Nodecl::ForStatement loop = this->_loop.as<Nodecl::ForStatement>();
        TL::Scope orig_loop_scope = loop.retrieve_context();

        TL::ForStatement for_stmt(loop);

        TL::Symbol induction_var = for_stmt.get_induction_variable();
        Nodecl::NodeclBase orig_loop_lower = for_stmt.get_lower_bound();
        Nodecl::NodeclBase orig_loop_upper = for_stmt.get_upper_bound();
        Nodecl::NodeclBase orig_loop_step = for_stmt.get_step();

        // Do nothing if the loop is already a normalized loop
        if ( orig_loop_lower.is_constant()
                && const_value_is_zero(orig_loop_lower.get_constant())
                && orig_loop_step.is_constant()
                && const_value_is_one(orig_loop_step.get_constant()))
        {
            _transformation = _loop.shallow_copy();
            return;
        }


        //    DO I = L, U, S
        //      A(I)
        // becomes
        //    DO I1 = 0, (U-L)/S, 1
        //      A(S * I1 + L)
        //
        Nodecl::NodeclBase new_upper;
        if (orig_loop_upper.is_constant() && orig_loop_lower.is_constant())
        {
            new_upper = const_value_to_nodecl(
                    const_value_sub(
                        orig_loop_upper.get_constant(),
                        orig_loop_lower.get_constant()));

            if (orig_loop_step.is_constant())
            {
                new_upper = const_value_to_nodecl(
                        const_value_div(
                            new_upper.get_constant(),
                            orig_loop_step.get_constant()));
            }
            else
            {
                new_upper = Nodecl::Div::make(
                        new_upper,
                        orig_loop_step.shallow_copy(),
                        new_upper.get_type());
            }
        }
        else
        {
            new_upper = Nodecl::Div::make(
                    Nodecl::Minus::make(
                        orig_loop_upper.shallow_copy(),
                        orig_loop_lower.shallow_copy(),
                        orig_loop_upper.get_type()),
                    orig_loop_step.shallow_copy(),
                    orig_loop_upper.get_type());
        }

        Nodecl::NodeclBase normalized_loop_body = loop.get_statement().shallow_copy();

        ReplaceInductionVar replace_induction_var(induction_var, orig_loop_lower, orig_loop_step);
        replace_induction_var.walk(normalized_loop_body);

        Nodecl::NodeclBase normalized_loop_control;
        if (IS_FORTRAN_LANGUAGE)
        {
            normalized_loop_control =
                Nodecl::RangeLoopControl::make(
                        induction_var.make_nodecl(),
                        const_value_to_nodecl(const_value_get_signed_int(0)),
                        new_upper,
                        const_value_to_nodecl(const_value_get_signed_int(1)));
        }
        else // IS_C_LANGUAGE || IS_CXX_LANGUAGE
        {
            Nodecl::NodeclBase init;
            // i = 0
            if (for_stmt.induction_variable_in_separate_scope())
            {
                induction_var.set_value(const_value_to_nodecl(const_value_get_signed_int(0)));
                init = Nodecl::ObjectInit::make(induction_var);
            }
            else
            {
                init =
                    Nodecl::Assignment::make(
                            induction_var.make_nodecl(/* ref */ true),
                            const_value_to_nodecl(const_value_get_signed_int(0)),
                            induction_var.get_type().no_ref().get_lvalue_reference_to());
            }

            // i <= new_upper
            Nodecl::NodeclBase cond =
                Nodecl::LowerOrEqualThan::make(
                        induction_var.make_nodecl(/* set_ref_type */ true),
                        new_upper,
                        ::get_bool_type());

            // i = i + 1
            Nodecl::NodeclBase next =
                Nodecl::Assignment::make(
                        induction_var.make_nodecl(/* set_ref_type */ true),
                        Nodecl::Add::make(
                            induction_var.make_nodecl(/* set_ref_type */ true),
                            const_value_to_nodecl(const_value_get_signed_int(1)),
                            induction_var.get_type().no_ref()),
                        induction_var.get_type().no_ref().get_lvalue_reference_to());

            normalized_loop_control =
                Nodecl::LoopControl::make(
                        Nodecl::List::make(init),
                        cond,
                        next);
        }

        Nodecl::NodeclBase normalized_for =
            Nodecl::ForStatement::make(
                    normalized_loop_control,
                    normalized_loop_body,
                    /* loop-name */ Nodecl::NodeclBase::null());

        _transformation = normalized_for;

        // Compute what value the induction variable should take after the loop
        if (!for_stmt.induction_variable_in_separate_scope())
        {
            Nodecl::NodeclBase induction_variable =
                for_stmt.get_induction_variable().make_nodecl(/* set_ref_type */ true);

            Nodecl::NodeclBase expr =
                HLT::Utils::compute_induction_variable_final_expr(_loop);

            _post_transformation_stmts.append(
                    Nodecl::ExpressionStatement::make(
                        Nodecl::Assignment::make(
                            induction_variable,
                            expr,
                            induction_variable.get_type())));
        }
    }
Exemple #8
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;
    }