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