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(); }
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 VectorizerVectorReduction::vectorize_reduction(const TL::Symbol& scalar_symbol, TL::Symbol& vector_symbol, const Nodecl::NodeclBase& reduction_initializer, const std::string& reduction_name, const TL::Type& reduction_type, Nodecl::List& pre_nodecls, Nodecl::List& post_nodecls) { // Step1: ADD REDUCTION SYMBOLS vector_symbol.set_value(Nodecl::VectorPromotion::make( reduction_initializer.shallow_copy(), vector_symbol.get_type())); // Add new ObjectInit with the initialization Nodecl::ObjectInit reduction_object_init = Nodecl::ObjectInit::make(vector_symbol); pre_nodecls.append(reduction_object_init); // Step2: ADD VECTOR REDUCTION INSTRUCTIONS if(reduction_name.compare("+") == 0) { Nodecl::ExpressionStatement post_reduction_stmt = Nodecl::ExpressionStatement::make( Nodecl::VectorReductionAdd::make( scalar_symbol.make_nodecl(true), vector_symbol.make_nodecl(true), scalar_symbol.get_type())); post_nodecls.append(post_reduction_stmt); } else if (reduction_name.compare("-") == 0) { Nodecl::ExpressionStatement post_reduction_stmt = Nodecl::ExpressionStatement::make( Nodecl::VectorReductionMinus::make( scalar_symbol.make_nodecl(true), vector_symbol.make_nodecl(true), scalar_symbol.get_type())); post_nodecls.append(post_reduction_stmt); } }
Nodecl::NodeclBase handle_task_statements( Nodecl::NodeclBase construct, Nodecl::NodeclBase task_statements, Nodecl::NodeclBase& task_placeholder, // Do not remove the reference TL::Source &new_stmts_src, // It should be a const reference const std::map<TL::Symbol, std::string> &reduction_symbols_map) { if (IS_FORTRAN_LANGUAGE) Source::source_language = SourceLanguage::C; Nodecl::NodeclBase new_statements = new_stmts_src.parse_statement(construct); if (IS_FORTRAN_LANGUAGE) Source::source_language = SourceLanguage::Current; TL::Scope new_scope = ReferenceScope(task_placeholder).get_scope(); std::map<TL::Symbol, Nodecl::NodeclBase> reduction_symbol_to_nodecl_map; for (std::map<TL::Symbol, std::string>::const_iterator it = reduction_symbols_map.begin(); it != reduction_symbols_map.end(); ++it) { TL::Symbol reduction_sym = it->first; std::string storage_name = it->second; TL::Symbol storage_sym = new_scope.get_symbol_from_name(storage_name); ERROR_CONDITION(!storage_sym.is_valid(), "This symbol is not valid", 0); Nodecl::NodeclBase deref_storage = Nodecl::Dereference::make( storage_sym.make_nodecl(/* set_ref_type */ true, storage_sym.get_locus()), storage_sym.get_type().points_to()); reduction_symbol_to_nodecl_map[reduction_sym] = deref_storage; } ReplaceReductionSymbols visitor(reduction_symbol_to_nodecl_map); Nodecl::NodeclBase copied_statements = task_statements.shallow_copy(); visitor.walk(copied_statements); task_placeholder.replace(copied_statements); return new_statements; }
static void handle_ompss_opencl_allocate_intrinsic( Nodecl::FunctionCall function_call, std::map<std::pair<TL::Type, std::pair<int, bool> > , Symbol> &declared_ocl_allocate_functions, Nodecl::NodeclBase expr_stmt) { Nodecl::List arguments = function_call.get_arguments().as<Nodecl::List>(); ERROR_CONDITION(arguments.size() != 1, "More than one argument in 'ompss_opencl_allocate' call\n", 0); Nodecl::NodeclBase actual_argument = arguments[0]; ERROR_CONDITION(!actual_argument.is<Nodecl::FortranActualArgument>(), "Unexpected tree\n", 0); Nodecl::NodeclBase arg = actual_argument.as<Nodecl::FortranActualArgument>().get_argument(); ERROR_CONDITION(!arg.is<Nodecl::ArraySubscript>(), "Unreachable code\n", 0); Nodecl::NodeclBase subscripted = arg.as<Nodecl::ArraySubscript>().get_subscripted(); TL::Symbol subscripted_symbol = ::fortran_data_ref_get_symbol(subscripted.get_internal_nodecl()); ERROR_CONDITION( !(subscripted_symbol.get_type().is_fortran_array() && subscripted_symbol.is_allocatable()) && !(subscripted_symbol.get_type().is_pointer() && subscripted_symbol.get_type().points_to().is_fortran_array()), "The argument of 'ompss_opencl_allocate' intrinsic must be " "an allocatable array or a pointer to an array with all its bounds specified\n", 0); TL::Type array_type; int num_dimensions; bool is_allocatable; if (subscripted_symbol.is_allocatable()) { array_type = subscripted_symbol.get_type(); num_dimensions = subscripted_symbol.get_type().get_num_dimensions(); is_allocatable = true; } else { array_type = subscripted_symbol.get_type().points_to(); num_dimensions = array_type.get_num_dimensions(); is_allocatable = false; } TL::Type element_type = array_type; while (element_type.is_array()) { element_type = element_type.array_element(); } ERROR_CONDITION(!array_type.is_array(), "This type should be an array type", 0); std::pair<TL::Type, std::pair<int, bool> > key = std::make_pair(element_type, std::make_pair(num_dimensions, is_allocatable)); std::map<std::pair<TL::Type, std::pair<int, bool> > , Symbol>::iterator it_new_fun = declared_ocl_allocate_functions.find(key); // Reuse the auxiliar function if it already exists Symbol new_function_sym; if (it_new_fun != declared_ocl_allocate_functions.end()) { new_function_sym = it_new_fun->second; } else { new_function_sym = create_new_function_opencl_allocate( expr_stmt, subscripted_symbol, element_type, num_dimensions, is_allocatable); declared_ocl_allocate_functions[key] = new_function_sym; } // Replace the current intrinsic call by a call to the new function TL::Source actual_arg_array; Nodecl::NodeclBase subscripted_lvalue = subscripted.shallow_copy(); subscripted_lvalue.set_type(subscripted_symbol.get_type().no_ref().get_lvalue_reference_to()); actual_arg_array << as_expression(subscripted_lvalue); TL::Source actual_arg_bounds; Nodecl::List subscripts = arg.as<Nodecl::ArraySubscript>().get_subscripts().as<Nodecl::List>(); for (Nodecl::List::reverse_iterator it = subscripts.rbegin(); it != subscripts.rend(); it++) { Nodecl::NodeclBase subscript = *it, lower, upper; if (it != subscripts.rbegin()) actual_arg_bounds << ", "; if (subscript.is<Nodecl::Range>()) { lower = subscript.as<Nodecl::Range>().get_lower(); upper = subscript.as<Nodecl::Range>().get_upper(); } else { lower = nodecl_make_integer_literal( fortran_get_default_integer_type(), const_value_get_signed_int(1), make_locus("", 0, 0)); upper = subscript; } actual_arg_bounds << as_expression(lower) << "," << as_expression(upper); } TL::Source new_function_call; new_function_call << "CALL " << as_symbol(new_function_sym) << "(" << actual_arg_array << ", " << actual_arg_bounds << ")\n" ; expr_stmt.replace(new_function_call.parse_statement(expr_stmt)); }
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); } }