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