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; }
bool ArrayAccessInfoVisitor::visit( const Nodecl::ArraySubscript& n ) { // Collect information about the induction variables contained in the node bool n_is_iv = variable_is_iv( n ); walk( n.get_subscripted( ) ); walk( n.get_subscripts( ) ); _is_adjacent_access = ( n_is_iv && _ivs.back( )->is_increment_one( ) ); return !Utils::ext_sym_set_contains_nodecl( n, _killed ); }
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::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 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); } }
void visit_pre(const Nodecl::ArraySubscript &node) { _extra_data_sharing.walk(node.get_subscripts()); }
ObjectList<Nodecl::NodeclBase> ExtendedSymbol::get_nodecls_base( const Nodecl::NodeclBase& n ) { if (n.is<Nodecl::Symbol>() || n.is<Nodecl::PointerToMember>() || n.is<Nodecl::ObjectInit>() || n.is<Nodecl::FunctionCall>()) { return ObjectList<Nodecl::NodeclBase>(1, n); } else if (n.is<Nodecl::IntegerLiteral>() || n.is<Nodecl::FloatingLiteral>() || n.is<Nodecl::ComplexLiteral>() || n.is<Nodecl::StringLiteral>() || n.is<Nodecl::BooleanLiteral>()) { return ObjectList<Nodecl::NodeclBase>(); } else if (n.is<Nodecl::ClassMemberAccess>()) { Nodecl::ClassMemberAccess aux = n.as<Nodecl::ClassMemberAccess>(); return get_nodecls_base(aux.get_lhs()); } else if (n.is<Nodecl::ArraySubscript>()) { Nodecl::ArraySubscript aux = n.as<Nodecl::ArraySubscript>(); return get_nodecls_base(aux.get_subscripted()); } else if (n.is<Nodecl::Reference>()) { Nodecl::Reference aux = n.as<Nodecl::Reference>(); return get_nodecls_base(aux.get_rhs()); } else if (n.is<Nodecl::Dereference>()) { Nodecl::Dereference aux = n.as<Nodecl::Dereference>(); return get_nodecls_base(aux.get_rhs()); } else if (n.is<Nodecl::Conversion>()) { Nodecl::Conversion aux = n.as<Nodecl::Conversion>(); return get_nodecls_base(aux.get_nest()); } else if (n.is<Nodecl::Cast>()) { Nodecl::Cast aux = n.as<Nodecl::Cast>(); return get_nodecls_base(aux.get_rhs()); } /*! * We can have (pre- post-) in- de-crements and other arithmetic operations * Example: * T *curr_high = ...; * *curr_high-- = l; * "*curr_high--" is a _KILLED_VAR */ else if (n.is<Nodecl::Predecrement>()) { Nodecl::Predecrement aux = n.as<Nodecl::Predecrement>(); return get_nodecls_base(aux.get_rhs()); } else if (n.is<Nodecl::Postdecrement>()) { Nodecl::Postdecrement aux = n.as<Nodecl::Postdecrement>(); return get_nodecls_base(aux.get_rhs()); } else if (n.is<Nodecl::Preincrement>()) { Nodecl::Preincrement aux = n.as<Nodecl::Preincrement>(); return get_nodecls_base(aux.get_rhs()); } else if (n.is<Nodecl::Postincrement>()) { Nodecl::Postincrement aux = n.as<Nodecl::Postincrement>(); return get_nodecls_base(aux.get_rhs()); } else if (n.is<Nodecl::Add>()) { Nodecl::Add aux = n.as<Nodecl::Add>(); ObjectList<Nodecl::NodeclBase> rhs = get_nodecls_base(aux.get_rhs()); ObjectList<Nodecl::NodeclBase> lhs = get_nodecls_base(aux.get_lhs()); return rhs.append(lhs); } else { internal_error("Unexpected type of nodecl '%s' contained in an ExtendedSymbol '%s'", ast_print_node_type(n.get_kind()), n.prettyprint().c_str()); } }