TL::Source LoopUnroll::do_unroll() { if (!_for_stmt.regular_loop()) { return silly_unroll(); } // Get parts of the loop IdExpression induction_var = _for_stmt.get_induction_variable(); Expression lower_bound = _for_stmt.get_lower_bound(); Expression upper_bound = _for_stmt.get_upper_bound(); Expression step = _for_stmt.get_step(); TL::Source operator_bound = _for_stmt.get_bound_operator(); Statement loop_body = _for_stmt.get_loop_body(); TL::Source result, epilogue, main, induction_var_decl, before_main, after_main; std::stringstream ss; ss << _factor; result << "{" << induction_var_decl << before_main << main << after_main << epilogue << "}" ; Source replicated_body; Source epilogue_body; if (_factor > 1) { AST_t init = _for_stmt.get_iterating_init(); if (Declaration::predicate(init)) { TL::Symbol sym = induction_var.get_symbol(); TL::Type type = sym.get_type(); // Declare it since it will have local scope induction_var_decl << type.get_declaration(sym.get_scope(), sym.get_name()) << ";" ; } main << "for (" << induction_var << " = " << lower_bound << ";" << induction_var << operator_bound << "((" << upper_bound << ") - (" << _factor << " - 1)* (" << step << "));" << induction_var << "+= (" << step << ") * " << _factor << ")" << "{" << replicated_body << "}" ; // FIXME - It could help to initialize here another variable and make both loops independent epilogue << "for ( ; " // No initialization, keep using the old induction var << induction_var << operator_bound << upper_bound << ";" << induction_var << "+= (" << step << "))" << epilogue_body ; if (!_remove_tasks) { epilogue_body << loop_body; } else { std::cerr << "Do not create task " << __FILE__ << ":" << __LINE__ << std::endl; running_error("Path not supported yet", 0); // epilogue_body << loop_body.get_ast().prettyprint_with_callback(functor(ignore_tasks)); } } else { // Leave it as is main << "for(" << _for_stmt.get_iterating_init().prettyprint() << _for_stmt.get_iterating_condition() << ";" << _for_stmt.get_iterating_expression() << ")" << "{" << replicated_body << "}" ; } // Replicate the body bool consider_omp = false; if (TaskAggregation::contains_relevant_openmp(loop_body)) { consider_omp = true; } if (_ignore_omp || !consider_omp) { simple_replication(_factor, replicated_body, epilogue_body, induction_var, loop_body); } else { omp_replication(_factor, replicated_body, epilogue_body, induction_var, loop_body, before_main, after_main); } return result; }
TL::Source LoopBlocking::do_blocking() { Source result, block_loops; result << block_loops ; ObjectList<ForStatement> nest_loops = _for_nest_info.get_nest_list(); _nesting = std::min(_nest_factors.size(), nest_loops.size()); TL::Source *current_innermost_part = &block_loops; // For every loop declare its block loop variable and the inter-block loop ObjectList<TL::Expression>::iterator current_factor = _nest_factors.begin(); ObjectList<TL::ForStatement>::iterator current_for = nest_loops.begin(); for (int current_nest = 0; current_nest < _nesting; current_nest++, current_for++, current_factor++) { TL::IdExpression induction_var = current_for->get_induction_variable(); TL::Symbol sym = induction_var.get_symbol(); TL::Type type = sym.get_type(); std::string var = "_blk_" + sym.get_name(); TL::Source *new_innermost_part = new TL::Source(); (*current_innermost_part) << "for(" << type.get_declaration(sym.get_scope(), var) << " = " << current_for->get_lower_bound() << ";" << var << current_for->get_bound_operator() << current_for->get_upper_bound() << ";" << var << "+= ( " << current_for->get_step() << ") * " << current_factor->prettyprint() << ")" << (*new_innermost_part) ; current_innermost_part = new_innermost_part; } // Now for every loop, declare the intra-loop current_factor = _nest_factors.begin(); current_for = nest_loops.begin(); for (int current_nest = 0; current_nest < _nesting; current_nest++, current_for++, current_factor++) { TL::IdExpression induction_var = current_for->get_induction_variable(); TL::Symbol sym = induction_var.get_symbol(); TL::Type type = sym.get_type(); std::string var = induction_var.prettyprint(); std::string init_var = var; // If the loop declares the iterator in the for statement // declare it again AST_t loop_init = current_for->get_iterating_init(); if (Declaration::predicate(loop_init)) { // Fix init_var to be a declaration init_var = type.get_declaration(sym.get_scope(), var); } std::string blk_var = "_blk_" + sym.get_name(); TL::Source min_code; TL::Source *new_innermost_part = new TL::Source(); (*current_innermost_part) << "for(" << init_var << " = " << blk_var << ";" << var << current_for->get_bound_operator() << min_code << ";" << var << "+= ( " << current_for->get_step() << "))" << (*new_innermost_part) ; TL::Source a, b; min_code << "((" << a << ") < (" << b << ") ? (" << a << ") : (" << b << "))" ; a << blk_var << " + (" << current_for->get_step() << ") * (" << current_factor->prettyprint() << " - 1 )"; b << current_for->get_upper_bound(); current_innermost_part = new_innermost_part; } // And now the innermost loop (*current_innermost_part) << nest_loops[_nesting - 1].get_loop_body() ; return result; }
TL::Symbol new_function_symbol( TL::Symbol current_function, const std::string& name, TL::Type return_type, TL::ObjectList<std::string> parameter_names, TL::ObjectList<TL::Type> parameter_types) { if (IS_FORTRAN_LANGUAGE && current_function.is_nested_function()) { // Get the enclosing function current_function = current_function.get_scope().get_related_symbol(); } decl_context_t decl_context = current_function.get_scope().get_decl_context(); ERROR_CONDITION(parameter_names.size() != parameter_types.size(), "Mismatch between names and types", 0); decl_context_t function_context; if (IS_FORTRAN_LANGUAGE) { function_context = new_program_unit_context(decl_context); } else { function_context = new_function_context(decl_context); function_context = new_block_context(function_context); } // Build the function type int num_parameters = 0; scope_entry_t** parameter_list = NULL; parameter_info_t* p_types = new parameter_info_t[parameter_types.size()]; parameter_info_t* it_ptypes = &(p_types[0]); TL::ObjectList<TL::Type>::iterator type_it = parameter_types.begin(); for (TL::ObjectList<std::string>::iterator it = parameter_names.begin(); it != parameter_names.end(); it++, it_ptypes++, type_it++) { scope_entry_t* param = new_symbol(function_context, function_context.current_scope, it->c_str()); param->entity_specs.is_user_declared = 1; param->kind = SK_VARIABLE; param->locus = make_locus("", 0, 0); param->defined = 1; param->type_information = get_unqualified_type(type_it->get_internal_type()); P_LIST_ADD(parameter_list, num_parameters, param); it_ptypes->is_ellipsis = 0; it_ptypes->nonadjusted_type_info = NULL; it_ptypes->type_info = get_indirect_type(param); } type_t *function_type = get_new_function_type( return_type.get_internal_type(), p_types, parameter_types.size()); delete[] p_types; // Now, we can create the new function symbol scope_entry_t* new_function_sym = NULL; if (!current_function.get_type().is_template_specialized_type()) { new_function_sym = new_symbol(decl_context, decl_context.current_scope, name.c_str()); new_function_sym->entity_specs.is_user_declared = 1; new_function_sym->kind = SK_FUNCTION; new_function_sym->locus = make_locus("", 0, 0); new_function_sym->type_information = function_type; } else { scope_entry_t* new_template_sym = new_symbol( decl_context, decl_context.current_scope, name.c_str()); new_template_sym->kind = SK_TEMPLATE; new_template_sym->locus = make_locus("", 0, 0); new_template_sym->type_information = get_new_template_type( decl_context.template_parameters, function_type, uniquestr(name.c_str()), decl_context, make_locus("", 0, 0)); template_type_set_related_symbol(new_template_sym->type_information, new_template_sym); // The new function is the primary template specialization new_function_sym = named_type_get_symbol( template_type_get_primary_type( new_template_sym->type_information)); } function_context.function_scope->related_entry = new_function_sym; function_context.block_scope->related_entry = new_function_sym; new_function_sym->related_decl_context = function_context; new_function_sym->entity_specs.related_symbols = parameter_list; new_function_sym->entity_specs.num_related_symbols = num_parameters; for (int i = 0; i < new_function_sym->entity_specs.num_related_symbols; ++i) { symbol_set_as_parameter_of_function( new_function_sym->entity_specs.related_symbols[i], new_function_sym, /* parameter position */ i); } // Make it static new_function_sym->entity_specs.is_static = 1; // Make it member if the enclosing function is member if (current_function.is_member()) { new_function_sym->entity_specs.is_member = 1; new_function_sym->entity_specs.class_type = current_function.get_class_type().get_internal_type(); new_function_sym->entity_specs.access = AS_PUBLIC; ::class_type_add_member(new_function_sym->entity_specs.class_type, new_function_sym); } if (current_function.is_inline()) new_function_sym->entity_specs.is_inline = 1; // new_function_sym->entity_specs.is_defined_inside_class_specifier = // current_function.get_internal_symbol()->entity_specs.is_defined_inside_class_specifier; if (IS_FORTRAN_LANGUAGE && current_function.is_in_module()) { scope_entry_t* module_sym = current_function.in_module().get_internal_symbol(); new_function_sym->entity_specs.in_module = module_sym; P_LIST_ADD( module_sym->entity_specs.related_symbols, module_sym->entity_specs.num_related_symbols, new_function_sym); new_function_sym->entity_specs.is_module_procedure = 1; } return new_function_sym; }