Index: include/polly/ScopInfo.h =================================================================== --- include/polly/ScopInfo.h +++ include/polly/ScopInfo.h @@ -1111,6 +1111,9 @@ public: ScopStmt(const ScopStmt &) = delete; const ScopStmt &operator=(const ScopStmt &) = delete; + + /// Create the ScopStmt from another ScopStmt. + ScopStmt(ScopStmt *Original, int CopyNo); /// Create the ScopStmt from a BasicBlock. ScopStmt(Scop &parent, BasicBlock &bb, Loop *SurroundingLoop); @@ -2085,6 +2088,9 @@ /// @return The count of copy statements added to this Scop. unsigned getCopyStmtsNum() { return CopyStmtsNum; } + /// Create a new SCoP statement for @p ScopStmt. + void copyScopStmt(ScopStmt *NewStmt, int CopyNo); + /// Create a new copy statement. /// /// A new statement will be created and added to the statement vector. Index: lib/Analysis/ScopInfo.cpp =================================================================== --- lib/Analysis/ScopInfo.cpp +++ lib/Analysis/ScopInfo.cpp @@ -1573,6 +1573,16 @@ } } +ScopStmt::ScopStmt(ScopStmt *Original, int CopyNo) + : Parent(*(Original->getParent())), InvalidDomain(nullptr), Domain(nullptr), BB(Original->getBasicBlock()), + R(Original->getRegion()), Build(nullptr), SurroundingLoop(Original->getSurroundingLoop()){ + BaseName = getIslCompatibleName(Original->getBaseName(), "_copy_no_", std::to_string(CopyNo)); + Domain = Original->getDomain(); + Domain = isl_set_set_tuple_name(Domain, BaseName.c_str()); + isl_id *Id = isl_id_alloc(getIslCtx(), getBaseName(), this); + Domain = isl_set_set_tuple_id(Domain, Id); +} + ScopStmt::ScopStmt(Scop &parent, Region &R, Loop *SurroundingLoop) : Parent(parent), InvalidDomain(nullptr), Domain(nullptr), BB(nullptr), R(&R), Build(nullptr), SurroundingLoop(SurroundingLoop) { @@ -4441,6 +4451,11 @@ return isl_multi_union_pw_aff_from_union_pw_multi_aff(Data.Res); } +void Scop::copyScopStmt(ScopStmt *NewStmt, int CopyNo) { + assert(NewStmt && "Unexpected nullptr!"); + Stmts.emplace_back(NewStmt, CopyNo); +} + void Scop::addScopStmt(BasicBlock *BB, Loop *SurroundingLoop) { assert(BB && "Unexpected nullptr!"); Stmts.emplace_back(*this, *BB, SurroundingLoop); Index: lib/Exchange/JSONExporter.cpp =================================================================== --- lib/Exchange/JSONExporter.cpp +++ lib/Exchange/JSONExporter.cpp @@ -17,6 +17,7 @@ #include "polly/ScopInfo.h" #include "polly/ScopPass.h" #include "polly/Support/ScopLocation.h" +#include "polly/Support/GICHelper.h" #include "llvm/ADT/Statistic.h" #include "llvm/Analysis/RegionInfo.h" #include "llvm/IR/Module.h" @@ -29,6 +30,7 @@ #include "isl/printer.h" #include "isl/set.h" #include "isl/union_map.h" +#include "isl/union_set.h" #include "json/reader.h" #include "json/writer.h" #include @@ -287,6 +289,113 @@ return true; } +struct schedule_info{ + isl_union_map *OriginalUmap; + isl_union_map *NewUmap; + int CopyNo; +}; + +struct print_info { + Scop *S; + int CopyNo; +}; + +// Adds a copy of the map corresponding to the set to the user->NewMap. +static isl_stat copyScheduleStatements(__isl_take isl_set *set, void *user){ + struct schedule_info *data = (schedule_info*) user; + isl_union_map *umap; + isl_set *range, *domain; + isl_map *NewMap; + std::string name; + + umap = isl_union_map_copy(data->OriginalUmap); + umap = isl_union_map_intersect_domain(umap, + isl_union_set_from_set(isl_set_copy(set))); + + range = isl_set_from_union_set(isl_union_map_range(umap)); + name = getIslCompatibleName((std::string) isl_set_get_tuple_name(set), "_copy_no_", std::to_string(data->CopyNo)); + domain = isl_set_set_tuple_name(set, name.c_str()); + NewMap = isl_map_from_domain_and_range(domain, range); + data->NewUmap = isl_union_map_add_map(data->NewUmap, NewMap); + return isl_stat_ok; +} + +// adds a copy to the SCoP for every ScopStmt corresponding to the set. +static isl_stat copyScopStatements(__isl_take isl_set *set, void *user){ + struct print_info *data = (print_info*) user; + isl_set *scopset; + ScopStmt *NewStmt; + + for(ScopStmt &Stmt : *(data->S)) { + scopset = isl_map_domain(Stmt.getSchedule()); + if(isl_set_is_equal(scopset, set)){ + NewStmt = &Stmt; + isl_set_free(scopset); + break; + } + isl_set_free(scopset); + } + data->S->copyScopStmt(NewStmt, data->CopyNo); + + isl_set_free(set); + return isl_stat_ok; +} + +isl_union_map *makeScheduleSingleValued(isl_union_map *ScheduleMap, Scop &S){ + //create a printer for the printing of isl types. + isl_printer *P = isl_printer_to_str(S.getIslCtx()); + P = isl_printer_set_output_format(P, ISL_FORMAT_ISL); + P = isl_printer_flush(P); + + isl_union_map *universe, *ScheduleDup, *FinalSchedule; + isl_union_map *NewSchedule; + isl_union_set *domain; + + //create a schedule containing only duplicate elements. + FinalSchedule = isl_union_map_lexmin(isl_union_map_copy(ScheduleMap)); + ScheduleDup = isl_union_map_subtract(isl_union_map_copy(ScheduleMap), isl_union_map_copy(FinalSchedule)); + + // create struct to be used by the isl_union_set_foreach_set functions. + struct print_info ScopData = {&S}; + struct schedule_info ScheduleData; + ScheduleData.OriginalUmap = isl_union_map_copy(FinalSchedule); + ScheduleData.NewUmap = isl_union_map_copy(FinalSchedule); + int i = 1; + + while(!isl_union_map_is_empty(ScheduleDup)){ + assert(i < 11 && "More than 10 copies required!"); + + universe = isl_union_map_universe(isl_union_map_copy(ScheduleDup)); + domain = isl_union_map_domain(universe); + + //fix the Scop by duplicating statements which are executed multiple times. + ScopData.CopyNo = i; + assert(isl_union_set_foreach_set(domain, ©ScopStatements, &ScopData) >= 0 && + "error during foreach for copyScopStatements!"); + + // fix the schedule + ScheduleData.CopyNo = i; + if (isl_union_set_foreach_set(domain, ©ScheduleStatements, &ScheduleData) >= 0 && + "error during foreach for copyScheduleStatements!"); + + NewSchedule = isl_union_map_lexmin(isl_union_map_copy(ScheduleDup)); + isl_union_map_free(ScheduleData.OriginalUmap); + ScheduleData.OriginalUmap = isl_union_map_copy(NewSchedule); + ScheduleDup = isl_union_map_subtract(ScheduleDup, NewSchedule); + isl_union_set_free(domain); + i++; + } + + errs() << "\nNew Map:\n" << ScheduleData.NewUmap << "\n"; + + isl_printer_free(P); + isl_union_map_free(ScheduleMap); + isl_union_map_free(ScheduleDup); + isl_union_map_free(ScheduleData.OriginalUmap); + isl_union_map_free(ScheduleData.NewUmap); + return FinalSchedule; +} + bool JSONImporter::importSchedule(Scop &S, Json::Value &JScop, const Dependences &D) { StatementToIslMapTy NewSchedule; @@ -328,6 +437,16 @@ ScheduleMap = isl_union_map_add_map(ScheduleMap, Stmt.getSchedule()); } + // Check if the map is single valued. + if(!isl_union_map_is_single_valued(ScheduleMap)){ + DEBUG(dbgs() << "JScop file contains a schedule that is not single valued\n"); + + // Not Yet Finished, when ScheduleMap can be fixed by makeScheduleSingleValued, the new ScheduleMap will be passed. + ScheduleMap = makeScheduleSingleValued(ScheduleMap, S); + isl_union_map_free(ScheduleMap); + return false; + } + S.setSchedule(ScheduleMap); return true;