// 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); } } }
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); } }
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 ); } } }
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); } }