void VectorizerVisitorExpression::visit(const Nodecl::Neg& n) { Nodecl::NodeclBase rhs = n.get_rhs(); if (rhs.is<Nodecl::IntegerLiteral>() || // -1 rhs.is<Nodecl::FloatingLiteral>()) { const Nodecl::VectorPromotion vector_prom = Nodecl::VectorPromotion::make( n.shallow_copy(), get_qualified_vector_to(n.get_type(), _vector_length), n.get_locus()); n.replace(vector_prom); } else // -a { walk(rhs); const Nodecl::VectorNeg vector_neg = Nodecl::VectorNeg::make( n.get_rhs().shallow_copy(), get_qualified_vector_to(n.get_type(), _vector_length), n.get_locus()); n.replace(vector_neg); } }
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::FloatingLiteral& n) { const Nodecl::VectorPromotion vector_prom = Nodecl::VectorPromotion::make( n.shallow_copy(), get_qualified_vector_to(n.get_type(), _vector_length), n.get_locus()); n.replace(vector_prom); }
void VectorizerVisitorExpression::visit(const Nodecl::Cast& n) { walk(n.get_rhs()); const Nodecl::VectorConversion vector_conv = Nodecl::VectorConversion::make( n.get_rhs().shallow_copy(), get_qualified_vector_to(n.get_type(), _vector_length), n.get_locus()); n.replace(vector_conv); }
void VectorizerVisitorExpression::visit(const Nodecl::Mul& n) { walk(n.get_lhs()); walk(n.get_rhs()); const Nodecl::VectorMul vector_mul = Nodecl::VectorMul::make( n.get_lhs().shallow_copy(), n.get_rhs().shallow_copy(), get_qualified_vector_to(n.get_type(), _vector_length), n.get_locus()); n.replace(vector_mul); }
void VectorizerVisitorExpression::visit(const Nodecl::LogicalAnd& n) { walk(n.get_lhs()); walk(n.get_rhs()); const Nodecl::VectorLogicalAnd vector_lo = Nodecl::VectorLogicalAnd::make( n.get_lhs().shallow_copy(), n.get_rhs().shallow_copy(), get_qualified_vector_to(n.get_type(), _vector_length), n.get_locus()); n.replace(vector_lo); }
void VectorizerVisitorExpression::visit(const Nodecl::BitwiseOr& n) { walk(n.get_lhs()); walk(n.get_rhs()); const Nodecl::VectorBitwiseOr vector_bo = Nodecl::VectorBitwiseOr::make( n.get_lhs().shallow_copy(), n.get_rhs().shallow_copy(), get_qualified_vector_to(n.get_type(), _vector_length), n.get_locus()); n.replace(vector_bo); }
void VectorizerVisitorExpression::visit(const Nodecl::GreaterThan& n) { walk(n.get_lhs()); walk(n.get_rhs()); const Nodecl::VectorGreaterThan vector_gt = Nodecl::VectorGreaterThan::make( n.get_lhs().shallow_copy(), n.get_rhs().shallow_copy(), get_qualified_vector_to(n.get_type(), _vector_length), n.get_locus()); n.replace(vector_gt); }
void VectorizerVisitorExpression::visit(const Nodecl::ConditionalExpression& n) { walk(n.get_condition()); walk(n.get_true()); walk(n.get_false()); const Nodecl::VectorConditionalExpression vector_cond = Nodecl::VectorConditionalExpression::make( n.get_condition().shallow_copy(), n.get_true().shallow_copy(), n.get_false().shallow_copy(), get_qualified_vector_to(n.get_type(), _vector_length), n.get_locus()); n.replace(vector_cond); }
void VectorizerVisitorFunction::visit(const Nodecl::FunctionCode& function_code) { // Set up enviroment _environment._external_scope = function_code.retrieve_context(); _environment._local_scope_list.push_back( function_code.get_statements().retrieve_context()); // Get analysis info Vectorizer::initialize_analysis(function_code); // Push FunctionCode as scope for analysis _environment._analysis_scopes.push_back(function_code); //Vectorize function type and parameters TL::Symbol vect_func_sym = function_code.get_symbol(); TL::Type func_type = vect_func_sym.get_type(); TL::ObjectList<TL::Symbol> parameters = vect_func_sym.get_function_parameters(); TL::ObjectList<TL::Type> parameters_type = func_type.parameters(); TL::ObjectList<TL::Type> parameters_vector_type; TL::ObjectList<TL::Type>::iterator it_type; TL::ObjectList<TL::Symbol>::iterator it_param_sym; for(it_param_sym = parameters.begin(), it_type = parameters_type.begin(); it_type != parameters_type.end(); it_param_sym++, it_type++) { TL::Type sym_type = get_qualified_vector_to((*it_type), _environment._vector_length); // Set type to parameter TL::Symbol (*it_param_sym).set_type(sym_type); parameters_vector_type.append(sym_type); } if(_masked_version) { TL::Scope scope = vect_func_sym.get_related_scope(); // Create mask parameter TL::Symbol mask_sym = scope.new_symbol("__mask_param"); mask_sym.get_internal_symbol()->kind = SK_VARIABLE; mask_sym.get_internal_symbol()->entity_specs.is_user_declared = 1; mask_sym.set_type(TL::Type::get_mask_type(_environment._mask_size)); symbol_set_as_parameter_of_function(mask_sym.get_internal_symbol(), vect_func_sym.get_internal_symbol(), parameters.size()); // Add mask symbol and type to parameters parameters.append(mask_sym); parameters_vector_type.append(mask_sym.get_type()); vect_func_sym.set_related_symbols(parameters); // Take care of default_argument_info_t* //TODO: Move this into a function { int num_parameters = vect_func_sym.get_internal_symbol()->entity_specs.num_parameters; default_argument_info_t** default_argument_info = vect_func_sym.get_internal_symbol()->entity_specs.default_argument_info; num_parameters++; default_argument_info = (default_argument_info_t**)xrealloc(default_argument_info, num_parameters * sizeof(*default_argument_info)); default_argument_info[num_parameters-1] = NULL; vect_func_sym.get_internal_symbol()->entity_specs.default_argument_info = default_argument_info; vect_func_sym.get_internal_symbol()->entity_specs.num_parameters = num_parameters; } Nodecl::Symbol mask_nodecl_sym = mask_sym.make_nodecl(true, function_code.get_locus()); _environment._mask_list.push_back(mask_nodecl_sym); } else // Add MaskLiteral to mask_list { Nodecl::MaskLiteral all_one_mask = Nodecl::MaskLiteral::make( TL::Type::get_mask_type(_environment._mask_size), const_value_get_minus_one(_environment._mask_size, 1), make_locus("", 0, 0)); _environment._mask_list.push_back(all_one_mask); } vect_func_sym.set_type(get_qualified_vector_to(func_type.returns(), _environment._vector_length).get_function_returning(parameters_vector_type)); // Vectorize function statements VectorizerVisitorStatement visitor_stmt(_environment); visitor_stmt.walk(function_code.get_statements()); // Add final return if multi-return function if (_environment._function_return.is_valid()) { // Return value Nodecl::Symbol return_value= _environment._function_return.make_nodecl( false, function_code.get_locus()); // VectorizerVisitorExpression visitor_sym(_environment); // visitor_sym.walk(return_value); // Return value at the end of the Compound Statement Nodecl::ReturnStatement return_stmt = Nodecl::ReturnStatement::make(return_value, function_code.get_locus()); function_code.get_statements().as<Nodecl::Context>().get_in_context().as<Nodecl::List>() .front().as<Nodecl::CompoundStatement>().get_statements() .as<Nodecl::List>().append(return_stmt); } _environment._analysis_scopes.pop_back(); _environment._mask_list.pop_back(); // Analysis in functions won't be reused anywhere so it must be freed Vectorizer::finalize_analysis(); }
void VectorizerVisitorExpression::visit(const Nodecl::Symbol& n) { TL::Type sym_type = n.get_type(); //std::cerr << "scalar_type: " << n.prettyprint() << std::endl; if (!sym_type.is_vector()) { // Vectorize BASIC induction variable if (Vectorizer::_analysis_info->is_basic_induction_variable( Vectorizer::_analysis_scopes->back(), n)) { std::cerr << "Basic IV: " << n.prettyprint() << "\n"; // Computing IV offset {0, 1, 2, 3} TL::ObjectList<Nodecl::NodeclBase> literal_list; const_value_t *ind_var_increment = Vectorizer::_analysis_info->get_induction_variable_increment( Vectorizer::_analysis_scopes->back(), n); for(const_value_t *i = const_value_get_zero(4, 0); const_value_is_nonzero(const_value_lt(i, const_value_get_unsigned_int(_unroll_factor))); i = const_value_add(i, ind_var_increment)) { literal_list.prepend(const_value_to_nodecl(i)); } Nodecl::List offset = Nodecl::List::make(literal_list); // IV cannot be a reference TL::Type ind_var_type = get_qualified_vector_to(n.get_type(), _vector_length).no_ref(); TL::Type offset_type = ind_var_type; Nodecl::ParenthesizedExpression vector_induction_var = Nodecl::ParenthesizedExpression::make( Nodecl::VectorAdd::make( Nodecl::VectorPromotion::make( n.shallow_copy(), ind_var_type, n.get_locus()), Nodecl::VectorLiteral::make( offset, offset_type, n.get_locus()), get_qualified_vector_to(n.get_type(), _vector_length), n.get_locus()), get_qualified_vector_to(n.get_type(), _vector_length), n.get_locus()); n.replace(vector_induction_var); } // Vectorize symbols declared in the SIMD scope else if (is_declared_in_scope( _simd_inner_scope.get_decl_context().current_scope, n.get_symbol().get_scope().get_decl_context().current_scope)) { //std::cerr << "NS scalar_type: " << n.prettyprint() << std::endl; TL::Symbol tl_sym = n.get_symbol(); TL::Type tl_sym_type = tl_sym.get_type(); //TL::Symbol if (tl_sym_type.is_scalar_type()) { //std::cerr << "TS scalar_type: " << n.prettyprint() << std::endl; tl_sym.set_type(get_qualified_vector_to(tl_sym_type, _vector_length)); tl_sym_type = tl_sym.get_type(); } //Nodecl::Symbol Nodecl::Symbol new_sym = Nodecl::Symbol::make(tl_sym, n.get_locus()); new_sym.set_type(tl_sym_type.get_lvalue_reference_to()); n.replace(new_sym); } // Vectorize constants else if (Vectorizer::_analysis_info->is_constant( Vectorizer::_analysis_scopes->back(), n)) { const Nodecl::VectorPromotion vector_prom = Nodecl::VectorPromotion::make( n.shallow_copy(), get_qualified_vector_to(sym_type, _vector_length), n.get_locus()); n.replace(vector_prom); } else { //TODO: If you are from outside of the loop -> Vector local copy. running_error("Vectorizer: Loop is not vectorizable. '%s' is not IV or Constant or Local.", n.get_symbol().get_name().c_str()); } } }
void VectorizerVisitorExpression::visit(const Nodecl::FunctionCall& n) { Nodecl::NodeclBase called = n.get_called(); ERROR_CONDITION(!called.is<Nodecl::Symbol>(), "Vectorizer: %s found. This kind of function call is not supported yet", ast_print_node_type(called.get_kind())); Nodecl::Symbol called_sym = called.as<Nodecl::Symbol>(); // Vectorizing arguments walk(n.get_arguments()); // Special functions if (called_sym.get_symbol().get_name() == "fabsf") { const Nodecl::VectorFabs vector_fabs_call = Nodecl::VectorFabs::make( n.get_arguments().as<Nodecl::List>().front().shallow_copy(), get_qualified_vector_to(n.get_type(), _vector_length), n.get_locus()); n.replace(vector_fabs_call); } else //Common functions { // Get the best vector version of the function available Nodecl::NodeclBase best_version = TL::Vectorization::Vectorizer::_function_versioning.get_best_version( called_sym.get_symbol().get_name(), _device, _vector_length, _target_type); ERROR_CONDITION(best_version.is_null(), "Vectorizer: the best vector function for '%s' is null", called_sym.get_symbol().get_name().c_str()); // Create new called symbol Nodecl::Symbol new_called; if (best_version.is<Nodecl::FunctionCode>()) { new_called = best_version.as<Nodecl::FunctionCode>().get_symbol(). make_nodecl(n.get_locus()); } else if (best_version.is<Nodecl::Symbol>()) { new_called = best_version.as<Nodecl::Symbol>().get_symbol(). make_nodecl(n.get_locus()); } else { running_error("Vectorizer: %s found as vector function version in function versioning.", ast_print_node_type(best_version.get_kind())); } const Nodecl::VectorFunctionCall vector_function_call = Nodecl::VectorFunctionCall::make( new_called, n.get_arguments().shallow_copy(), n.get_alternate_name().shallow_copy(), n.get_function_form().shallow_copy(), get_qualified_vector_to(n.get_type(), _vector_length), n.get_locus()); n.replace(vector_function_call); } }
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); } }