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 Lower::lower_taskwait_with_dependences(const Nodecl::OpenMP::Taskwait& node) { Nodecl::List environment = node.get_environment().as<Nodecl::List>(); // Prepare if(0) task reusing environment and set TaskIsTaskwait flag Nodecl::NodeclBase zero_expr; if(IS_C_LANGUAGE || IS_CXX_LANGUAGE) { zero_expr = const_value_to_nodecl(const_value_get_unsigned_int(0)); } else // IS_FORTRAN_LANGUAGE { zero_expr = Nodecl::BooleanLiteral::make( TL::Type::get_bool_type(), const_value_get_zero(/* bytes */ 4, /* sign */0)); } environment.append(Nodecl::OpenMP::If::make(zero_expr)); environment.append(Nodecl::OpenMP::TaskIsTaskwait::make()); Nodecl::OpenMP::Task taskwait_task = Nodecl::OpenMP::Task::make( environment, Nodecl::List::make(Nodecl::EmptyStatement::make()), node.get_locus()); node.replace(taskwait_task); lower_task(node.as<Nodecl::OpenMP::Task>()); }
void Lower::lower_taskwait(const Nodecl::OpenMP::Taskwait& node) { TL::Symbol nanos_taskwait_sym = TL::Scope::get_global_scope().get_symbol_from_name("nanos_taskwait"); ERROR_CONDITION(!nanos_taskwait_sym.is_valid() || !nanos_taskwait_sym.is_function(), "Invalid symbol", 0); const char* locus = locus_to_str(node.get_locus()); Nodecl::NodeclBase taskwait_tree = Nodecl::ExpressionStatement::make( Nodecl::FunctionCall::make( nanos_taskwait_sym.make_nodecl(/* set_ref_type */ true, node.get_locus()), /* args */ Nodecl::List::make( const_value_to_nodecl( const_value_make_string_null_ended( locus, strlen(locus)))), /* alternate-name */ Nodecl::NodeclBase::null(), /* function-form */ Nodecl::NodeclBase::null(), TL::Type::get_void_type(), node.get_locus())); node.replace(taskwait_tree); }
TL::Type get_array_of_vector(TL::Type t) { ERROR_CONDITION(!t.is_vector(), "Invalid type", 0); return t.vector_element().get_array_to( const_value_to_nodecl( const_value_get_signed_int(t.vector_num_elements()) ), TL::Scope::get_global_scope()); }
TL::Type get_array_of_mask(TL::Type t) { ERROR_CONDITION(!t.is_mask(), "Invalid type", 0); int n = (t.get_mask_num_elements() / 8) + !!(t.get_mask_num_elements() % 8); return TL::Type::get_unsigned_char_type().get_array_to( const_value_to_nodecl( const_value_get_signed_int(n) ), TL::Scope::get_global_scope()); }
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 LoopNormalize::normalize() { Nodecl::ForStatement loop = this->_loop.as<Nodecl::ForStatement>(); TL::Scope orig_loop_scope = loop.retrieve_context(); TL::ForStatement for_stmt(loop); TL::Symbol induction_var = for_stmt.get_induction_variable(); Nodecl::NodeclBase orig_loop_lower = for_stmt.get_lower_bound(); Nodecl::NodeclBase orig_loop_upper = for_stmt.get_upper_bound(); Nodecl::NodeclBase orig_loop_step = for_stmt.get_step(); // Do nothing if the loop is already a normalized loop if ( orig_loop_lower.is_constant() && const_value_is_zero(orig_loop_lower.get_constant()) && orig_loop_step.is_constant() && const_value_is_one(orig_loop_step.get_constant())) { _transformation = _loop.shallow_copy(); return; } // DO I = L, U, S // A(I) // becomes // DO I1 = 0, (U-L)/S, 1 // A(S * I1 + L) // Nodecl::NodeclBase new_upper; if (orig_loop_upper.is_constant() && orig_loop_lower.is_constant()) { new_upper = const_value_to_nodecl( const_value_sub( orig_loop_upper.get_constant(), orig_loop_lower.get_constant())); if (orig_loop_step.is_constant()) { new_upper = const_value_to_nodecl( const_value_div( new_upper.get_constant(), orig_loop_step.get_constant())); } else { new_upper = Nodecl::Div::make( new_upper, orig_loop_step.shallow_copy(), new_upper.get_type()); } } else { new_upper = Nodecl::Div::make( Nodecl::Minus::make( orig_loop_upper.shallow_copy(), orig_loop_lower.shallow_copy(), orig_loop_upper.get_type()), orig_loop_step.shallow_copy(), orig_loop_upper.get_type()); } Nodecl::NodeclBase normalized_loop_body = loop.get_statement().shallow_copy(); ReplaceInductionVar replace_induction_var(induction_var, orig_loop_lower, orig_loop_step); replace_induction_var.walk(normalized_loop_body); Nodecl::NodeclBase normalized_loop_control; if (IS_FORTRAN_LANGUAGE) { normalized_loop_control = Nodecl::RangeLoopControl::make( induction_var.make_nodecl(), const_value_to_nodecl(const_value_get_signed_int(0)), new_upper, const_value_to_nodecl(const_value_get_signed_int(1))); } else // IS_C_LANGUAGE || IS_CXX_LANGUAGE { Nodecl::NodeclBase init; // i = 0 if (for_stmt.induction_variable_in_separate_scope()) { induction_var.set_value(const_value_to_nodecl(const_value_get_signed_int(0))); init = Nodecl::ObjectInit::make(induction_var); } else { init = Nodecl::Assignment::make( induction_var.make_nodecl(/* ref */ true), const_value_to_nodecl(const_value_get_signed_int(0)), induction_var.get_type().no_ref().get_lvalue_reference_to()); } // i <= new_upper Nodecl::NodeclBase cond = Nodecl::LowerOrEqualThan::make( induction_var.make_nodecl(/* set_ref_type */ true), new_upper, ::get_bool_type()); // i = i + 1 Nodecl::NodeclBase next = Nodecl::Assignment::make( induction_var.make_nodecl(/* set_ref_type */ true), Nodecl::Add::make( induction_var.make_nodecl(/* set_ref_type */ true), const_value_to_nodecl(const_value_get_signed_int(1)), induction_var.get_type().no_ref()), induction_var.get_type().no_ref().get_lvalue_reference_to()); normalized_loop_control = Nodecl::LoopControl::make( Nodecl::List::make(init), cond, next); } Nodecl::NodeclBase normalized_for = Nodecl::ForStatement::make( normalized_loop_control, normalized_loop_body, /* loop-name */ Nodecl::NodeclBase::null()); _transformation = normalized_for; // Compute what value the induction variable should take after the loop if (!for_stmt.induction_variable_in_separate_scope()) { Nodecl::NodeclBase induction_variable = for_stmt.get_induction_variable().make_nodecl(/* set_ref_type */ true); Nodecl::NodeclBase expr = HLT::Utils::compute_induction_variable_final_expr(_loop); _post_transformation_stmts.append( Nodecl::ExpressionStatement::make( Nodecl::Assignment::make( induction_variable, expr, induction_variable.get_type()))); } }
TL::Symbol LoweringVisitor::create_basic_reduction_function_fortran(OpenMP::Reduction* red, Nodecl::NodeclBase construct) { reduction_map_t::iterator it = _basic_reduction_map_openmp.find(red); if (it != _basic_reduction_map_openmp.end()) { return it->second; } std::string fun_name; { std::stringstream ss; ss << "nanos_red_" << red << "_" << simple_hash_str(construct.get_filename().c_str()); fun_name = ss.str(); } Nodecl::NodeclBase function_body; Source src; src << "SUBROUTINE " << fun_name << "(omp_out, omp_in, num_scalars)\n" << "IMPLICIT NONE\n" << as_type(red->get_type()) << " :: omp_out(num_scalars)\n" << as_type(red->get_type()) << " :: omp_in(num_scalars)\n" << "INTEGER, VALUE :: num_scalars\n" << "INTEGER :: I\n" << statement_placeholder(function_body) << "\n" << "END SUBROUTINE " << fun_name << "\n"; ; Nodecl::NodeclBase function_code = src.parse_global(construct); TL::Scope inside_function = ReferenceScope(function_body).get_scope(); TL::Symbol param_omp_in = inside_function.get_symbol_from_name("omp_in"); ERROR_CONDITION(!param_omp_in.is_valid(), "Symbol omp_in not found", 0); TL::Symbol param_omp_out = inside_function.get_symbol_from_name("omp_out"); ERROR_CONDITION(!param_omp_out.is_valid(), "Symbol omp_out not found", 0); TL::Symbol function_sym = inside_function.get_symbol_from_name(fun_name); ERROR_CONDITION(!function_sym.is_valid(), "Symbol %s not found", fun_name.c_str()); TL::Symbol index = inside_function.get_symbol_from_name("i"); ERROR_CONDITION(!index.is_valid(), "Symbol %s not found", "i"); TL::Symbol num_scalars = inside_function.get_symbol_from_name("num_scalars"); ERROR_CONDITION(!num_scalars.is_valid(), "Symbol %s not found", "num_scalars"); Nodecl::NodeclBase num_scalars_ref = Nodecl::Symbol::make(num_scalars); num_scalars_ref.set_type(num_scalars.get_type().no_ref().get_lvalue_reference_to()); Nodecl::Symbol nodecl_index = Nodecl::Symbol::make(index); nodecl_index.set_type(index.get_type().get_lvalue_reference_to()); Nodecl::NodeclBase loop_header = Nodecl::RangeLoopControl::make( nodecl_index, const_value_to_nodecl(const_value_get_signed_int(1)), num_scalars_ref, Nodecl::NodeclBase::null()); Nodecl::NodeclBase expanded_combiner = red->get_combiner().shallow_copy(); BasicReductionExpandVisitor expander_visitor( red->get_omp_in(), param_omp_in, red->get_omp_out(), param_omp_out, index); expander_visitor.walk(expanded_combiner); function_body.replace( Nodecl::ForStatement::make(loop_header, Nodecl::List::make( Nodecl::ExpressionStatement::make( expanded_combiner)), Nodecl::NodeclBase::null())); _basic_reduction_map_openmp[red] = function_sym; if (IS_FORTRAN_LANGUAGE) { Nodecl::Utils::Fortran::append_used_modules(construct.retrieve_context(), function_sym.get_related_scope()); } Nodecl::Utils::append_to_enclosing_top_level_location(construct, function_code); return function_sym; }