예제 #1
0
    // We redefine the visitor of Nodecl::FunctionCode because  we need to
    // visit first the internal functions and later the statements
    void LoweringVisitor::visit(const Nodecl::FunctionCode& function_code)
    {
        Nodecl::List stmts = function_code.get_statements().as<Nodecl::List>();

        // First, traverse nested functions
        for (Nodecl::List::iterator it = stmts.begin();
                it != stmts.end();
                it++)
        {
            if (it->is<Nodecl::FunctionCode>())
            {
                walk(*it);
            }
        }
        // Second, remaining statements
        for (Nodecl::List::iterator it = stmts.begin();
                it != stmts.end();
                it++)
        {
            if (!it->is<Nodecl::FunctionCode>())
            {
                walk(*it);
            }
        }
    }
예제 #2
0
    bool NodeclStaticInfo::is_constant_access( const Nodecl::NodeclBase& n ) const
    {
        bool result = true;
        
        if( n.is<Nodecl::ArraySubscript>( ) )
        {
            Nodecl::ArraySubscript array = n.as<Nodecl::ArraySubscript>( );

            //Check subscripted
            if ( !is_constant( array.get_subscripted( ) ))
            {
                return false;
            }

            // Check subscrips
            Nodecl::List subscript = array.get_subscripts( ).as<Nodecl::List>( );
            Nodecl::List::iterator it = subscript.begin( );
            for( ; it != subscript.end( ); ++it )
            {   // All dimensions must be constant
                if( !is_constant( *it ) )
                {
                    result = false;
                    break;
                }
            }
        }
        
        return result;
    }
        void VectorizerVisitorExpression::visit(const Nodecl::ArraySubscript& n)
        {
            // Computing new vector type
            TL::Type vector_type = n.get_type();
            if (vector_type.is_lvalue_reference())
            {
                vector_type = vector_type.references_to();
            }
            vector_type = get_qualified_vector_to(vector_type, _vector_length);

            TL::Type basic_type = n.get_type();
            if (basic_type.is_lvalue_reference())
            {
                basic_type = basic_type.references_to();
            }

            // Vector Load
            if (Vectorizer::_analysis_info->is_adjacent_access(
                        Vectorizer::_analysis_scopes->back(),
                        n))
            {
                const Nodecl::VectorLoad vector_load =
                    Nodecl::VectorLoad::make(
                            Nodecl::Reference::make(
                                Nodecl::ParenthesizedExpression::make(
                                    n.shallow_copy(),
                                    basic_type,
                                    n.get_locus()),
                                basic_type.get_pointer_to(),
                                n.get_locus()),
                            vector_type,
                            n.get_locus());

                n.replace(vector_load);
            }
            else // Vector Gather
            {
                const Nodecl::NodeclBase base = n.get_subscripted();
                const Nodecl::List subscripts = n.get_subscripts().as<Nodecl::List>();

                ERROR_CONDITION(subscripts.size() > 1,
                    "Vectorizer: Gather on multidimensional array is not supported yet!", 0);

                std::cerr << "Gather: " << n.prettyprint() << "\n";

                Nodecl::NodeclBase strides = *subscripts.begin();
                walk(strides);

                const Nodecl::VectorGather vector_gather =
                    Nodecl::VectorGather::make(
                            base.shallow_copy(),
                            strides,
                            vector_type,
                            n.get_locus());

                n.replace(vector_gather);
            }
        }
예제 #4
0
void AutoScopeVisitor::visit( const Nodecl::OpenMP::Task& n )
{
    // Retrieve the results of the Auto-Scoping process to the user
    _analysis_info->print_auto_scoping_results( n );

    // Modify the Nodecl with the new variables' scope
    Analysis::Utils::AutoScopedVariables autosc_vars = _analysis_info->get_auto_scoped_variables( n );
    Analysis::Utils::ext_sym_set private_ext_syms, firstprivate_ext_syms, race_ext_syms,
             shared_ext_syms, undef_ext_syms;
    Nodecl::NodeclBase user_private_vars, user_firstprivate_vars, user_shared_vars;

    // Get actual environment
    Nodecl::List environ = n.get_environment().as<Nodecl::List>();
    for( Nodecl::List::iterator it = environ.begin( ); it != environ.end( ); )
    {
        if( it->is<Nodecl::OpenMP::Auto>( ) )
        {
            it = environ.erase( it );
        }
        else
        {
            if( it->is<Nodecl::OpenMP::Private>( ) )
            {
                user_private_vars = it->as<Nodecl::OpenMP::Private>( );
            }
            if( it->is<Nodecl::OpenMP::Firstprivate>( ) )
            {
                user_firstprivate_vars = it->as<Nodecl::OpenMP::Firstprivate>( );
            }
            if( it->is<Nodecl::OpenMP::Shared>( ) )
            {
                user_shared_vars = it->as<Nodecl::OpenMP::Shared>( );
            }
            ++it;
        }
    }

    // Remove user-scoped variables from auto-scoped variables and reset environment
    private_ext_syms = autosc_vars.get_private_vars( );
    if( !private_ext_syms.empty( ) )
    {
        ObjectList<Nodecl::NodeclBase> autosc_private_vars;
        for( Analysis::Utils::ext_sym_set::iterator it = private_ext_syms.begin( ); it != private_ext_syms.end( ); ++it )
        {
            autosc_private_vars.insert( it->get_nodecl( ) );
        }
        ObjectList<Nodecl::NodeclBase> purged_autosc_private_vars;
        for( ObjectList<Nodecl::NodeclBase>::iterator it = autosc_private_vars.begin( );
                it != autosc_private_vars.end( ); ++it )
        {
            if( !Nodecl::Utils::nodecl_is_in_nodecl_list( *it, user_firstprivate_vars.as<Nodecl::List>( ) )
                    && !Nodecl::Utils::nodecl_is_in_nodecl_list( *it, user_private_vars.as<Nodecl::List>( ) )
                    && !Nodecl::Utils::nodecl_is_in_nodecl_list( *it, user_shared_vars.as<Nodecl::List>( ) ) )
            {
                purged_autosc_private_vars.insert( it->shallow_copy() );
            }
        }
        if( !purged_autosc_private_vars.empty( ) )
        {
            Nodecl::OpenMP::Private private_node =
                Nodecl::OpenMP::Private::make( Nodecl::List::make( purged_autosc_private_vars ),
                                               n.get_locus( ) );
            environ.append( private_node );
        }
    }

    firstprivate_ext_syms = autosc_vars.get_firstprivate_vars( );
    if( !firstprivate_ext_syms.empty( ) )
    {
        ObjectList<Nodecl::NodeclBase> autosc_firstprivate_vars;
        for( Analysis::Utils::ext_sym_set::iterator it = firstprivate_ext_syms.begin( ); it != firstprivate_ext_syms.end( ); ++it )
        {
            autosc_firstprivate_vars.insert( it->get_nodecl( ) );
        }
        ObjectList<Nodecl::NodeclBase> purged_autosc_firstprivate_vars;
        for( ObjectList<Nodecl::NodeclBase>::iterator it = autosc_firstprivate_vars.begin( );
                it != autosc_firstprivate_vars.end( ); ++it )
        {
            if( !Nodecl::Utils::nodecl_is_in_nodecl_list( *it, user_firstprivate_vars.as<Nodecl::List>( ) )
                    && !Nodecl::Utils::nodecl_is_in_nodecl_list( *it, user_private_vars.as<Nodecl::List>( ) )
                    && !Nodecl::Utils::nodecl_is_in_nodecl_list( *it, user_shared_vars.as<Nodecl::List>( ) ) )
            {
                purged_autosc_firstprivate_vars.insert( it->shallow_copy() );
            }
        }
        if( !purged_autosc_firstprivate_vars.empty( ) )
        {
            Nodecl::OpenMP::Firstprivate firstprivate_node =
                Nodecl::OpenMP::Firstprivate::make( Nodecl::List::make( purged_autosc_firstprivate_vars ),
                                                    n.get_locus( ) );
            environ.append( firstprivate_node );
        }
    }

    shared_ext_syms = autosc_vars.get_shared_vars( );
    if( !shared_ext_syms.empty( ) )
    {
        ObjectList<Nodecl::NodeclBase> autosc_shared_vars;
        for( Analysis::Utils::ext_sym_set::iterator it = shared_ext_syms.begin( ); it != shared_ext_syms.end( ); ++it )
        {
            autosc_shared_vars.insert( it->get_nodecl( ) );
        }
        ObjectList<Nodecl::NodeclBase> purged_autosc_shared_vars;
        for( ObjectList<Nodecl::NodeclBase>::iterator it = autosc_shared_vars.begin( );
                it != autosc_shared_vars.end( ); ++it )
        {
            if( !Nodecl::Utils::nodecl_is_in_nodecl_list( *it, user_firstprivate_vars.as<Nodecl::List>( ) )
                    && !Nodecl::Utils::nodecl_is_in_nodecl_list( *it, user_private_vars.as<Nodecl::List>( ) )
                    && !Nodecl::Utils::nodecl_is_in_nodecl_list( *it, user_shared_vars.as<Nodecl::List>( ) ) )
            {
                purged_autosc_shared_vars.insert( it->shallow_copy() );
            }
        }
        if( !purged_autosc_shared_vars.empty( ) )
        {
            Nodecl::OpenMP::Shared shared_node =
                Nodecl::OpenMP::Shared::make( Nodecl::List::make( purged_autosc_shared_vars ),
                                              n.get_locus( ) );
            environ.append( shared_node );
        }
    }
}
예제 #5
0
    int SuitableAlignmentVisitor::visit( const Nodecl::ArraySubscript& n ) 
    {
        if( _nesting_level == 0 )  // Target access
        {
            _nesting_level++;
            
            int i;
            int alignment = 0;
            
            Nodecl::NodeclBase subscripted = n.get_subscripted( );
            TL::Type element_type = subscripted.get_type( );
            // TODO: subscript is aligned
            
            Nodecl::List subscripts = n.get_subscripts( ).as<Nodecl::List>( );
            int num_subscripts = subscripts.size( );
            
            // Get dimension sizes
            int *dimension_sizes = (int *)malloc( ( num_subscripts-1 ) * sizeof( int ) );
            
            for( i = 0; i < (num_subscripts-1); i++ ) // Skip the first one. It does not have size
            {
                // Iterate on array subscript type
                if( element_type.is_array( ) )
                {
                    element_type = element_type.array_element( );
                }
                else if( element_type.is_pointer( ) )
                {
                    element_type = element_type.points_to( );
                }
                else
                {
                    WARNING_MESSAGE( "Array subscript does not have array type or pointer to array type", 0 );
                    return -1;
                }
                
                if( !element_type.array_has_size( ) )
                {
                    WARNING_MESSAGE( "Array type does not have size", 0 );
                    return -1;
                }
                
                // Compute dimension alignment 
                Nodecl::NodeclBase dimension_size_node = element_type.array_get_size( );

                // If VLA, get the actual size
                if(dimension_size_node.is<Nodecl::Symbol>() &&
                        dimension_size_node.get_symbol().is_saved_expression())
                {
                    dimension_size_node = dimension_size_node.get_symbol().get_value();
                }
               
                int dimension_size = -1;
                if( dimension_size_node.is_constant( ) )
                {
                    dimension_size = const_value_cast_to_signed_int( dimension_size_node.get_constant( ) );
                    
                    if( is_suitable_constant( dimension_size * _type_size ) )
                        dimension_size = 0;
                }
                // If dimension size is suitable
                else if( is_suitable_expression( dimension_size_node ) )
                {
                    dimension_size = 0;
                }
                if( VERBOSE )
                    printf( "Dim %d, size %d\n", i, dimension_size );
                
                dimension_sizes[i] = dimension_size;
            }
            
            int it_alignment;
            Nodecl::List::iterator it = subscripts.begin( );
            // Multiply dimension sizes by indexes
            for( i=0; it != subscripts.end( ); i++ )
            {
                it_alignment = walk( *it );
                
                it++;
                if( it == subscripts.end( ) ) break; // Last dimmension does not have to be multiplied
                
                // a[i][j][k] -> i -> i*J*K
                for( int j = i; j < (num_subscripts-1); j++ )
                {
                    if( ( dimension_sizes[j] == 0 ) || ( it_alignment == 0 ) )
                    {
                        it_alignment = 0;
                    }
                    else if( ( dimension_sizes[j] < 0 ) || ( it_alignment < 0 ) )
                    {
                        it_alignment = -1;
                    }
                    else
                    {
                        it_alignment *= dimension_sizes[j];
                    }
                }
                
                if( it_alignment < 0 )
                {
                    return -1;
                }
                
                alignment += it_alignment;
            }
            // Add adjacent dimension
            alignment += it_alignment;
            
            free(dimension_sizes);
            
            _nesting_level--;
            
            return alignment;
        }
        // Nested array subscript
        else
        {
            if (is_suitable_expression(n))
            {
                return 0;
            }
            
            return -1;
        }
    }
        void VectorizerVisitorExpression::visit(const Nodecl::Assignment& n)
        {
            Nodecl::NodeclBase lhs = n.get_lhs();
            walk(n.get_rhs());

            // Computing new vector type
            TL::Type vector_type = n.get_type();
            /*
            if (vector_type.is_lvalue_reference())
            {
                vector_type = vector_type.references_to();
            }
            */
            vector_type = get_qualified_vector_to(vector_type, _vector_length);

            if(lhs.is<Nodecl::ArraySubscript>())
            {
                // Vector Store
                if(Vectorizer::_analysis_info->is_adjacent_access(
                            Vectorizer::_analysis_scopes->back(),
                            lhs))
                {
                    TL::Type basic_type = lhs.get_type();
                    if (basic_type.is_lvalue_reference())
                    {
                        basic_type = basic_type.references_to();
                    }

                    const Nodecl::VectorStore vector_store =
                        Nodecl::VectorStore::make(
                                Nodecl::Reference::make(
                                    Nodecl::ParenthesizedExpression::make(
                                        lhs.shallow_copy(),
                                        basic_type,
                                        n.get_locus()),
                                    basic_type.get_pointer_to(),
                                    n.get_locus()),
                                n.get_rhs().shallow_copy(),
                                vector_type,
                                n.get_locus());

                    n.replace(vector_store);
                }
                else // Vector Scatter
                {
                    const Nodecl::ArraySubscript lhs_array = lhs.as<Nodecl::ArraySubscript>();

                    const Nodecl::NodeclBase base = lhs_array.get_subscripted();
                    const Nodecl::List subscripts = lhs_array.get_subscripts().as<Nodecl::List>();

                    std::cerr << "Scatter: " << lhs_array.prettyprint() << "\n";

                    ERROR_CONDITION(subscripts.size() > 1,
                            "Vectorizer: Scatter on multidimensional array is not supported yet!", 0);

                    Nodecl::NodeclBase strides = *subscripts.begin();
                    walk(strides);

                    const Nodecl::VectorScatter vector_scatter =
                        Nodecl::VectorScatter::make(
                                base.shallow_copy(),
                                strides,
                                n.get_rhs().shallow_copy(),
                                vector_type,
                                n.get_locus());

                    n.replace(vector_scatter);
                }
            }
            else // Register
            {
                walk(lhs);

                const Nodecl::VectorAssignment vector_assignment =
                    Nodecl::VectorAssignment::make(
                            lhs.shallow_copy(),
                            n.get_rhs().shallow_copy(),
                            vector_type,
                            n.get_locus());

                n.replace(vector_assignment);
            }
        }