Beispiel #1
0
    static bool nodecl_is_zero( const Nodecl::NodeclBase& n )
    {
        bool res = false;

        if( n.is<Nodecl::IntegerLiteral>( ) )
            res = const_value_is_zero( n.as<Nodecl::IntegerLiteral>( ).get_constant( ) );
        else if( n.is<Nodecl::FloatingLiteral>( ) )
            res = const_value_is_zero( n.as<Nodecl::FloatingLiteral>( ).get_constant( ) );
        
        return res;
    }
    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())));
        }
    }