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;
    }
예제 #2
0
        void Core::collapse_check_loop(TL::PragmaCustomStatement construct)
        {
            TL::PragmaCustomClause collapse = construct.get_pragma_line().get_clause("collapse");
            if (!collapse.is_defined())
                return;

            TL::ObjectList<Nodecl::NodeclBase> expr_list = collapse.get_arguments_as_expressions(construct);

            if (expr_list.size() != 1)
            {
                error_printf("%s: error: collapse clause needs exactly one argument\n", 
                        locus_to_str(construct.get_locus()));
                return;
            }

            Nodecl::NodeclBase expr = expr_list[0];
            if (!expr.is_constant()
                    || !is_any_int_type(expr.get_type().get_internal_type()))
            {
                error_printf("%s: error: collapse clause requires an integer constant expression\n",
                        locus_to_str(construct.get_locus()));
                return;
            }

            const_value_t* cval = expr.get_constant();

            if (!const_value_is_one(cval))
            {
                error_printf("%s: error: only collapse(1) is supported\n",
                        locus_to_str(construct.get_locus()));
                return;
            }
        }
예제 #3
0
        Nodecl::NodeclVisitor<void>::Ret AVX2StrideVisitorConv::unhandled_node(const Nodecl::NodeclBase& node) 
        {
            //printf("Unsupported %d: %s\n", _vector_num_elements, node.prettyprint().c_str()); 
            
            if (node.get_type().is_vector())
            {

                Nodecl::NodeclBase new_node = node.shallow_copy().as<Nodecl::NodeclBase>();

                new_node.set_type(TL::Type::get_int_type().get_vector_of_elements(
                            _vector_num_elements));

                // TODO better
                node.replace(new_node);

                Nodecl::NodeclBase::Children children = node.children();
                for(Nodecl::NodeclBase::Children::iterator it = children.begin();
                        it != children.end();
                        it ++)
                {
                    walk(*it);
                }
            }
            return Ret(); 
        }
예제 #4
0
    bool NodeclStaticInfo::is_suitable_expression( const Nodecl::NodeclBase& n, 
            const TL::ObjectList<Nodecl::NodeclBase>* suitable_expressions, 
            int unroll_factor, int alignment, int& vector_size_module ) const
    {
        bool result = false;
        int type_size = n.get_type().basic_type().get_size();

        SuitableAlignmentVisitor sa_v( _induction_variables, suitable_expressions, unroll_factor, type_size, alignment );
        int subscript_alignment = sa_v.walk( n );

        printf("SUBSCRIPT ALIGNMENT %d\n", subscript_alignment);

        vector_size_module = ( ( subscript_alignment == -1 ) ? subscript_alignment : 
                                                               subscript_alignment % alignment );
        if( vector_size_module == 0 )
            result = true;

        return result;
    }
예제 #5
0
    bool NodeclStaticInfo::is_simd_aligned_access( const Nodecl::NodeclBase& n, 
            const TL::ObjectList<Nodecl::NodeclBase>* suitable_expressions, 
            int unroll_factor, int alignment ) const
    {
        if( !n.is<Nodecl::ArraySubscript>( ) )
        {
            std::cerr << "warning: returning false for is_simd_aligned_access when asking for nodecl '" 
                      << n.prettyprint( ) << "' which is not an array subscript" << std::endl;
            return false;
        }
        
        bool result = false;
        
        Nodecl::NodeclBase subscripted = n.as<Nodecl::ArraySubscript>( ).get_subscripted( );
        int type_size = subscripted.get_type().basic_type().get_size();

        SuitableAlignmentVisitor sa_v( _induction_variables, suitable_expressions, unroll_factor, type_size, alignment );
        int subscript_alignment = sa_v.walk( n );
        
        if( (subscript_alignment % alignment) == 0 )
            result = true;
        
        return result;
    }
예제 #6
0
    void loop_hlt_handler_post(TL::PragmaCustomStatement construct)
    {
        TL::PragmaCustomLine pragma_line = construct.get_pragma_line();
        TL::PragmaCustomClause collapse = construct.get_pragma_line().get_clause("collapse");
        if (!collapse.is_defined())
            return;

        TL::ObjectList<Nodecl::NodeclBase> expr_list = collapse.get_arguments_as_expressions(construct);
        if (expr_list.size() != 1)
        {
            error_printf_at(construct.get_locus(), "'collapse' clause needs exactly one argument\n");
            return;
        }

        Nodecl::NodeclBase expr = expr_list[0];
        if (!expr.is_constant()
                || !is_any_int_type(expr.get_type().get_internal_type()))
        {
            error_printf_at(construct.get_locus(),
                    "'collapse' clause requires an integer constant expression\n");
            return;
        }

        int collapse_factor = const_value_cast_to_signed_int(expr.get_constant());

        if (collapse_factor <= 0)
        {
            error_printf_at(
                    construct.get_locus(),
                    "Non-positive factor (%d) is not allowed in the 'collapse' clause\n",
                    collapse_factor);
        }
        else if (collapse_factor == 1)
        {
            // Removing the collapse clause from the pragma
            pragma_line.remove_clause("collapse");
        }
        else if (collapse_factor > 1)
        {
            Nodecl::NodeclBase loop = get_statement_from_pragma(construct);

            HLT::LoopCollapse loop_collapse;
            loop_collapse.set_loop(loop);
            loop_collapse.set_pragma_context(construct.retrieve_context());
            loop_collapse.set_collapse_factor(collapse_factor);

            loop_collapse.collapse();

            Nodecl::NodeclBase transformed_code = loop_collapse.get_whole_transformation();
            TL::ObjectList<TL::Symbol> capture_symbols = loop_collapse.get_omp_capture_symbols();

            // We may need to add some symbols that are used to implement the collapse clause to the pragma
            std::string names;
            for (TL::ObjectList<TL::Symbol>::iterator it = capture_symbols.begin();
                    it != capture_symbols.end();
                    it++)
            {
                if (it != capture_symbols.begin())
                    names += ",";
                names += it->get_name();
            }
            Nodecl::List clauses = pragma_line.get_clauses().as<Nodecl::List>();
            clauses.append(Nodecl::PragmaCustomClause::make(Nodecl::List::make(Nodecl::PragmaClauseArg::make(names)), "firstprivate"));

            // Removing the collapse clause from the pragma
            pragma_line.remove_clause("collapse");

            // Create a new pragma over the new for stmt
            ERROR_CONDITION(!transformed_code.is<Nodecl::Context>(), "Unexpected node\n", 0);
            Nodecl::NodeclBase compound_statement =
                transformed_code.as<Nodecl::Context>().get_in_context().as<Nodecl::List>().front();

            ERROR_CONDITION(!compound_statement.is<Nodecl::CompoundStatement>(), "Unexpected node\n", 0);
            Nodecl::Context context_for_stmt =
                compound_statement.as<Nodecl::CompoundStatement>().get_statements()
                .as<Nodecl::List>().find_first<Nodecl::Context>();

            Nodecl::Utils::remove_from_enclosing_list(context_for_stmt);

            Nodecl::List stmt_list =
                compound_statement.as<Nodecl::CompoundStatement>().get_statements().as<Nodecl::List>();
            ERROR_CONDITION(stmt_list.is_null(), "Unreachable code\n", 0);

            Nodecl::PragmaCustomStatement new_pragma =
                Nodecl::PragmaCustomStatement::make(pragma_line,
                        Nodecl::List::make(context_for_stmt),
                        construct.get_text(),
                        construct.get_locus());

            stmt_list.append(new_pragma);

            construct.replace(transformed_code);
        }
    }
예제 #7
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);
            }
        }