void Core::collapse_check_loop(TL::PragmaCustomStatement construct) { TL::PragmaCustomClause collapse = construct.get_pragma_line().get_clause("collapse"); if (!collapse.is_defined()) return; TL::ObjectList<Nodecl::NodeclBase> expr_list = collapse.get_arguments_as_expressions(construct); if (expr_list.size() != 1) { error_printf("%s: error: collapse clause needs exactly one argument\n", locus_to_str(construct.get_locus())); return; } Nodecl::NodeclBase expr = expr_list[0]; if (!expr.is_constant() || !is_any_int_type(expr.get_type().get_internal_type())) { error_printf("%s: error: collapse clause requires an integer constant expression\n", locus_to_str(construct.get_locus())); return; } const_value_t* cval = expr.get_constant(); if (!const_value_is_one(cval)) { error_printf("%s: error: only collapse(1) is supported\n", locus_to_str(construct.get_locus())); return; } }
void loop_hlt_handler_post(TL::PragmaCustomStatement construct) { TL::PragmaCustomLine pragma_line = construct.get_pragma_line(); TL::PragmaCustomClause collapse = construct.get_pragma_line().get_clause("collapse"); if (!collapse.is_defined()) return; TL::ObjectList<Nodecl::NodeclBase> expr_list = collapse.get_arguments_as_expressions(construct); if (expr_list.size() != 1) { error_printf_at(construct.get_locus(), "'collapse' clause needs exactly one argument\n"); return; } Nodecl::NodeclBase expr = expr_list[0]; if (!expr.is_constant() || !is_any_int_type(expr.get_type().get_internal_type())) { error_printf_at(construct.get_locus(), "'collapse' clause requires an integer constant expression\n"); return; } int collapse_factor = const_value_cast_to_signed_int(expr.get_constant()); if (collapse_factor <= 0) { error_printf_at( construct.get_locus(), "Non-positive factor (%d) is not allowed in the 'collapse' clause\n", collapse_factor); } else if (collapse_factor == 1) { // Removing the collapse clause from the pragma pragma_line.remove_clause("collapse"); } else if (collapse_factor > 1) { Nodecl::NodeclBase loop = get_statement_from_pragma(construct); HLT::LoopCollapse loop_collapse; loop_collapse.set_loop(loop); loop_collapse.set_pragma_context(construct.retrieve_context()); loop_collapse.set_collapse_factor(collapse_factor); loop_collapse.collapse(); Nodecl::NodeclBase transformed_code = loop_collapse.get_whole_transformation(); TL::ObjectList<TL::Symbol> capture_symbols = loop_collapse.get_omp_capture_symbols(); // We may need to add some symbols that are used to implement the collapse clause to the pragma std::string names; for (TL::ObjectList<TL::Symbol>::iterator it = capture_symbols.begin(); it != capture_symbols.end(); it++) { if (it != capture_symbols.begin()) names += ","; names += it->get_name(); } Nodecl::List clauses = pragma_line.get_clauses().as<Nodecl::List>(); clauses.append(Nodecl::PragmaCustomClause::make(Nodecl::List::make(Nodecl::PragmaClauseArg::make(names)), "firstprivate")); // Removing the collapse clause from the pragma pragma_line.remove_clause("collapse"); // Create a new pragma over the new for stmt ERROR_CONDITION(!transformed_code.is<Nodecl::Context>(), "Unexpected node\n", 0); Nodecl::NodeclBase compound_statement = transformed_code.as<Nodecl::Context>().get_in_context().as<Nodecl::List>().front(); ERROR_CONDITION(!compound_statement.is<Nodecl::CompoundStatement>(), "Unexpected node\n", 0); Nodecl::Context context_for_stmt = compound_statement.as<Nodecl::CompoundStatement>().get_statements() .as<Nodecl::List>().find_first<Nodecl::Context>(); Nodecl::Utils::remove_from_enclosing_list(context_for_stmt); Nodecl::List stmt_list = compound_statement.as<Nodecl::CompoundStatement>().get_statements().as<Nodecl::List>(); ERROR_CONDITION(stmt_list.is_null(), "Unreachable code\n", 0); Nodecl::PragmaCustomStatement new_pragma = Nodecl::PragmaCustomStatement::make(pragma_line, Nodecl::List::make(context_for_stmt), construct.get_text(), construct.get_locus()); stmt_list.append(new_pragma); construct.replace(transformed_code); } }
void Core::get_dependences_info_std_clause( TL::PragmaCustomLine construct, TL::PragmaCustomClause clause, DataSharingEnvironment& data_sharing) { if (!clause.is_defined()) return; ObjectList<std::string> arguments = clause.get_tokenized_arguments(); // Since we coalesce all the arguments of a clauses with the same name // in a case like depend(in : a, b) depend(out : c, d) will be a list // containing "in:a", "b", "out:c", "d" int cflags = REG_EXTENDED; if (IS_FORTRAN_LANGUAGE) { cflags |= REG_ICASE; } regex_t preg; if (regcomp(&preg, "^[[:blank:]]*((in)|(out)|(inout))[[:blank:]]*:(.*)$", cflags) != 0) { internal_error("Invalid regular expression", 0); } const int num_matches = 6; regmatch_t pmatch[num_matches] = { }; DependencyDirection dep_attr = DEP_DIR_UNDEFINED; for (ObjectList<std::string>::iterator it = arguments.begin(); it != arguments.end(); it++) { int match = regexec(&preg, it->c_str(), num_matches, pmatch, 0); std::string current_dep_expr = *it; if (match == 0) { // Zero-th match is the whole regular expression ERROR_CONDITION(pmatch[1].rm_so == -1, "Invalid match", 0); std::string dependency_type; for (int i = pmatch[1].rm_so; i < pmatch[1].rm_eo; i++) { dependency_type += tolower((*it)[i]); } if (dependency_type == "in") { dep_attr = DEP_DIR_IN; } else if (dependency_type == "out") { dep_attr = DEP_DIR_OUT; } else if (dependency_type == "inout") { dep_attr = DEP_DIR_INOUT; } else { internal_error("Code unreachable", 0); } // Now compute the proper dependence expression current_dep_expr.clear(); ERROR_CONDITION(pmatch[5].rm_so == -1, "Invalid match", 0); for (int i = pmatch[5].rm_so; i < pmatch[5].rm_eo; i++) { current_dep_expr += (*it)[i]; } } else if (match == REG_NOMATCH) ; // Do nothing else { internal_error("Unexpected result %d from regexec\n", match); } // FIXME: Only accepting "in:" not "in :" if (dep_attr == DEP_DIR_UNDEFINED) { error_printf("%s: error: skipping item '%s' in 'depend' clause since it does not have any associated dependence-type\n", clause.get_locus_str().c_str(), it->c_str()); continue; } Source src; src << current_dep_expr; // Now, parse a single OpenMP list item and hand it to the usual dependency routines Nodecl::NodeclBase expr; if (IS_C_LANGUAGE || IS_CXX_LANGUAGE) { expr = src.parse_generic(construct, /* ParseFlags */ Source::DEFAULT, "@OMP-DEPEND-ITEM@", Source::c_cxx_check_expression_adapter, decl_context_map_id); } else if (IS_FORTRAN_LANGUAGE) { expr = src.parse_generic(construct, /* ParseFlags */ Source::DEFAULT, "@OMP-DEPEND-ITEM@", Source::fortran_check_expression_adapter, decl_context_map_id); } // Singleton ObjectList<Nodecl::NodeclBase> expr_list; expr_list.append(expr); add_data_sharings(expr_list, data_sharing, dep_attr); } regfree(&preg); }