Source OpenMPTransform::get_loop_distribution_in_sections( int num_sections, Statement construct_body, ReplaceIdExpression replace_references) { Source loop_distribution; // Replace references using set "replace_references" over construct body Statement modified_parallel_body_stmt = replace_references.replace(construct_body); // FIXME - 'int' might no be enough for some loops! loop_distribution << "int nth_low;" << "int nth_upper;" << "int nth_step;" << "int nth_chunk;" << "int nth_schedule;" << "int intone_start;" << "int intone_end;" << "int intone_last;" << "int nth_barrier;" << "int nth_i;" << "nth_low = 0;" << "nth_upper = " << num_sections << ";" << "nth_step = 1;" << "nth_schedule = INTONE_SCH_DYNAMIC;" // Dynamic << "nth_chunk = 1;" << "in__tone_begin_for_ (&nth_low, &nth_upper, &nth_step, &nth_chunk, &nth_schedule);" << "while (in__tone_next_iters_ (&intone_start, &intone_end, &intone_last) != 0)" << "{" << "for (nth_i = intone_start; nth_i <= intone_end; nth_i += nth_step)" << "{" << "switch (nth_i)" << "{" << modified_parallel_body_stmt.prettyprint() << "default: break;" << "}" << "}" << "}" ; return loop_distribution; }
AST_t OpenMPTransform::get_outline_parallel_single( OpenMP::Construct &construct, FunctionDefinition function_definition, Source outlined_function_name, Statement construct_body, ReplaceIdExpression replace_references, ObjectList<ParameterInfo> parameter_info, ObjectList<Symbol> private_references, ObjectList<Symbol> firstprivate_references, ObjectList<Symbol> lastprivate_references, ObjectList<OpenMP::ReductionSymbol> reduction_references, ObjectList<Symbol> copyin_references, ObjectList<Symbol> /* copyprivate_references --?? */ ) { ObjectList<IdExpression> pass_by_value; Source outline_parallel; Source parallel_body; Source empty; outline_parallel = get_outline_common( function_definition, parallel_body, // The body of the outline outlined_function_name, parameter_info); // Replace references using set "replace_references" over construct body Statement modified_parallel_body_stmt = replace_references.replace(construct_body); Source private_declarations = get_privatized_declarations( construct, private_references, firstprivate_references, lastprivate_references, reduction_references, copyin_references, parameter_info ); Source reduction_update = get_reduction_update(reduction_references); Source single_source; Source barrier_code; Source instrumentation_code_before, instrumentation_code_after; single_source << "{" << "int nth_low;" << "int nth_upper;" << "int nth_step;" << "int nth_chunk;" << "int nth_schedule;" << "int nth_dummy1;" << "int nth_dummy2;" << "int nth_dummy3;" << "int nth_barrier; " << "nth_low = 0;" << "nth_upper = 0;" << "nth_step = 1;" << "nth_schedule = 2;" // Dynamic << "nth_chunk = 1;" // << "extern void in__tone_begin_for_(int*, int*, int*, int*, int*);" // << "extern int in__tone_next_iters_(int*, int*, int*);" // << "extern void in__tone_end_for_(int*);" << "in__tone_begin_for_ (&nth_low, &nth_upper, &nth_step, &nth_chunk, &nth_schedule);" << "while (in__tone_next_iters_ (&nth_dummy1, &nth_dummy2, &nth_dummy3) != 0)" << "{" << instrumentation_code_before << modified_parallel_body_stmt.prettyprint() << instrumentation_code_after << "}" << barrier_code << "}" ; barrier_code << "nth_barrier = 1;"; barrier_code << "in__tone_end_for_(&nth_barrier);"; instrumentation_outline(instrumentation_code_before, instrumentation_code_after, function_definition, construct_body); Source task_block_code; parallel_body << private_declarations << single_source << task_block_code ; task_block_code = get_task_block_code(); return finish_outline(function_definition, outline_parallel, parameter_info); }
Source OpenMPTransform::get_loop_distribution_code( ForStatement for_statement, PragmaCustomConstruct &for_construct, ReplaceIdExpression replace_references, FunctionDefinition function_definition) { Source parallel_for_body; Source loop_initialization; Source schedule_decisions; Source distributed_loop_body; Source loop_reductions; Source reduction_initialization; parallel_for_body << reduction_initialization << loop_initialization << schedule_decisions << distributed_loop_body << loop_reductions ; Statement loop_body = for_statement.get_loop_body(); IdExpression induction_var = for_statement.get_induction_variable(); Source induction_var_name; // Induction var name is handled specially. We check that only in 'for' it will be private, not in // any enclosing data environment OpenMP::DataSharingEnvironment& data_sharing = openmp_info->get_data_sharing(for_construct.get_ast()); if ((data_sharing.get_data_sharing(induction_var.get_symbol()) & OpenMP::DS_PRIVATE) == OpenMP::DS_PRIVATE) { induction_var_name << "p_" << induction_var.mangle_id_expression(); } else { induction_var_name << induction_var.mangle_id_expression(); } Expression lower_bound = for_statement.get_lower_bound(); Expression upper_bound = for_statement.get_upper_bound(); Expression step = for_statement.get_step(); lower_bound = replace_references.replace(lower_bound); upper_bound = replace_references.replace(upper_bound); step = replace_references.replace(step); // Define here the bounds of the loop loop_initialization // Iterator type, normally an integer type // but it can be a random_access_iterator << induction_var.get_symbol().get_type().get_declaration(induction_var.get_scope(),"nth_low") << ";" << induction_var.get_symbol().get_type().get_declaration(induction_var.get_scope(),"nth_upper") << ";" << "int nth_step;" << "int intone_start;" << "int intone_end;" << "int intone_last;" << "int nth_barrier;" << "nth_low = " << lower_bound.prettyprint() << ";" << "nth_upper = " << upper_bound.prettyprint() << ";" << "nth_step = " << step.prettyprint() << ";" ; // Schedule decisions Source schedule_const; Source schedule_chunk; schedule_decisions << "int nth_schedule;" << "int nth_chunk;" << "nth_schedule = " << schedule_const << ";" << "nth_chunk = " << schedule_chunk << ";" ; PragmaCustomClause schedule_clause = for_construct.get_clause("schedule"); if (schedule_clause.is_defined()) { ObjectList<std::string> args = schedule_clause.get_arguments(ExpressionTokenizer()); schedule_const << schedule_constant_name(args[0]); if (args.size() > 1) { schedule_chunk << args[1]; } else { schedule_chunk << "0"; } } else { schedule_const << "INTONE_SCH_DEFAULT"; schedule_chunk << "0"; } // Loop distribution Source modified_loop_body; Source instrument_code_before, instrument_code_after; distributed_loop_body // << "extern void in__tone_begin_for_(int*, int*, int*, int*, int*);" // << "extern int in__tone_next_iters_(int*, int*, int*);" // << "extern void in__tone_end_for_(int*);" << "int nth_zero = 0;" << "int nth_iters;" << "if ( nth_step > 0 ) nth_iters = (nth_upper - nth_low);" << "else {" << "nth_iters = 0;" << "nth_zero = (nth_low - nth_upper);" << "nth_low = nth_upper;" << "}" << "in__tone_begin_for_(&nth_zero, &nth_iters, &nth_step, &nth_chunk, &nth_schedule);" // Get a slice of the iteration space << "while (in__tone_next_iters_(&intone_start, &intone_end, &intone_last) != 0)" << "{" // And do something with it << instrument_code_before << " for (" << induction_var_name << " = nth_low+intone_start; " << " nth_step >= 1 ? " << induction_var_name << " <= nth_low+intone_end : " << induction_var_name << ">= nth_low+intone_end;" << " " << induction_var_name << " += nth_step)" << " {" << modified_loop_body << " }" << instrument_code_after << "}" ; // Replace references using set "replace_references" over loop body Statement modified_loop_body_stmt = replace_references.replace(loop_body); // and get the source of the modified tree modified_loop_body << modified_loop_body_stmt.prettyprint() ; return parallel_for_body; }