#pragma once #include #include #include #include #include #include #include "DvmhDirectiveBase.h" #include "../Utils/utils.h" #include "../Utils/errors.h" #include "../Utils/json.hpp" class Symbol; class Expression; struct FuncInfo; #define STRING std::string #define VECTOR std::vector #define PAIR std::pair #define MAP std::map #define SET std::set #define TO_STR std::to_string #define JSON nlohmann::json #if __SPF extern int sharedMemoryParallelization; #endif namespace Distribution { typedef enum distFlag : int { DISTR = 0, NO_DISTR, SPF_PRIV, IO_PRIV } distFlagType; typedef enum arrayLocation : int { l_LOCAL = 0, l_COMMON, l_MODULE, l_PARAMETER, l_STRUCT, l_LOCAL_SAVE } arrayLocType; class Array; class TemplateLink { private: VECTOR linkWithTemplate; VECTOR> alignRuleWithTemplate; Array *templateArray; public: TemplateLink(const int dimSize) { linkWithTemplate.resize(dimSize); alignRuleWithTemplate.resize(dimSize); for (int i = 0; i < dimSize; ++i) linkWithTemplate[i] = -1; templateArray = NULL; } TemplateLink(const TemplateLink ©) { linkWithTemplate = copy.linkWithTemplate; alignRuleWithTemplate = copy.alignRuleWithTemplate; templateArray = copy.templateArray; } Array* GetTemplateArray() const { return templateArray; } VECTOR> GetAlignRules() const; VECTOR GetLinks() const; void AddRule(const int dimNum, int value, const PAIR &rule, Array *templateArray_); STRING toString() const; }; class Array { private: unsigned id; STRING name; STRING shortName; int dimSize; int typeSize; // size of one element of array // calculated sizes VECTOR> sizes; // original sizes + shifts VECTOR>, PAIR>>> sizesExpr; VECTOR> orderedSizes; VECTOR>, PAIR>>> orderedSizesExpr; // template info by region MAP templateInfo; bool isTemplFlag; bool isLoopArrayFlag; distFlag isNonDistribute; Symbol *declSymbol; STRING uniqKey; // PAIR SET> declPlaces; MAP, Symbol*> declPlacesSymbol; //file-> map[incFile, line] -> symbol MAP, Symbol*>> declPlacesSymbolByFile; //TYPE: 0 - local, 1 - common, 2 - module, 3 - function parameter // PAIR PAIR locationPos; VECTOR>> allShadowSpecs; SET containsInRegions; // file -> lines MAP> usagePlaces; VECTOR mappedDims; VECTOR depracateToDistribute; bool ompThreadPrivate; bool privateInLoop; bool inEquivalence; private: TemplateLink* getTemlateInfo(const uint64_t regionId, bool withCheck = false) { auto it = templateInfo.find(regionId); TemplateLink *currLink = NULL; if (it == templateInfo.end()) { #if __SPF if (withCheck && sharedMemoryParallelization != 0) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); #endif currLink = new TemplateLink(dimSize); templateInfo[regionId] = currLink; } else currLink = it->second; return currLink; } void GenUniqKey() { uniqKey = shortName + locationPos.second + TO_STR(dimSize); for (auto &place : declPlaces) uniqKey += place.first + TO_STR(place.second); } //clones of template for realignes MAP, STRING> templateClones; VECTOR templateDimsOrder; public: Array() { isTemplFlag = false; isLoopArrayFlag = false; isNonDistribute = NO_DISTR; typeSize = 0; uniqKey = ""; dimSize = 0; id = -1; declSymbol = NULL; ompThreadPrivate = false; privateInLoop = false; inEquivalence = false; } Array(const STRING &name, const STRING &shortName, const int dimSize, const unsigned id, const STRING &declFile, const int declLine, const PAIR &locationPos, Symbol *declSymbol, bool inOmpThreadPriv, bool privateInLoop, bool inEquivalence, const VECTOR ®ions, const int typeSize, const distFlag flag = DISTR) : name(name), dimSize(dimSize), id(id), shortName(shortName), isTemplFlag(false), isNonDistribute(flag), isLoopArrayFlag(false), locationPos(locationPos), declSymbol(declSymbol), typeSize(typeSize), ompThreadPrivate(inOmpThreadPriv), privateInLoop(privateInLoop), inEquivalence(inEquivalence) { declPlaces.insert(std::make_pair(declFile, declLine)); sizes.resize(dimSize); sizesExpr.resize(dimSize); mappedDims.resize(dimSize); depracateToDistribute.resize(dimSize); for (int z = 0; z < dimSize; ++z) { sizes[z] = std::make_pair((int)INT_MAX, (int)INT_MIN); PAIR initVal = std::make_pair(0, 0); sizesExpr[z] = std::make_pair(std::make_pair((Expression*)NULL, initVal), std::make_pair((Expression*)NULL, initVal)); mappedDims[z] = false; depracateToDistribute[z] = false; } GenUniqKey(); for (auto ® : regions) containsInRegions.insert(reg); } Array(const Array ©) { id = copy.id; name = copy.name; shortName = copy.shortName; dimSize = copy.dimSize; typeSize = copy.typeSize; sizes = copy.sizes; sizesExpr = copy.sizesExpr; isTemplFlag = copy.isTemplFlag; isNonDistribute = copy.isNonDistribute; isLoopArrayFlag = copy.isLoopArrayFlag; declPlaces = copy.declPlaces; locationPos = copy.locationPos; allShadowSpecs = copy.allShadowSpecs; for (auto &elem : copy.templateInfo) templateInfo[elem.first] = new TemplateLink(*elem.second); declSymbol = copy.declSymbol; uniqKey = copy.uniqKey; containsInRegions = copy.containsInRegions; mappedDims = copy.mappedDims; depracateToDistribute = copy.depracateToDistribute; ompThreadPrivate = copy.ompThreadPrivate; privateInLoop = copy.privateInLoop; inEquivalence = copy.inEquivalence; } bool RemoveUnpammedDims() { bool needToRemove = false; int countToRem = 0; for (int z = 0; z < dimSize; ++z) { if (!mappedDims[z] || depracateToDistribute[z]) { needToRemove = true; countToRem++; //break; } } if (needToRemove == false) return false; if (countToRem == dimSize) return true; VECTOR> newSizes; VECTOR>, PAIR>>> newSizesExpr; VECTOR newMappedDims; VECTOR newDepr; for (int z = 0; z < dimSize; ++z) { if (mappedDims[z] && !depracateToDistribute[z]) { newSizes.push_back(sizes[z]); newSizesExpr.push_back(sizesExpr[z]); newMappedDims.push_back(mappedDims[z]); newDepr.push_back(depracateToDistribute[z]); } } sizes = newSizes; sizesExpr = newSizesExpr; mappedDims = newMappedDims; depracateToDistribute = newDepr; dimSize = (int)sizes.size(); return false; } int GetDimSize() const { return dimSize; } const STRING GetName() const { return name; } const STRING GetShortName() const { return shortName; } const STRING GetNameInLocation(void* location) const; void* GetNameInLocationS(void* location) const; unsigned GetId() const { return id; } void SetSizes(VECTOR> &_sizes, bool notCopyToExpr = false) { sizes = _sizes; if (!notCopyToExpr) { for (int i = 0; i < sizesExpr.size(); ++i) { sizesExpr[i].first.second.first = sizes[i].first; sizesExpr[i].second.second.first = sizes[i].second; } } } const VECTOR>& GetSizes(); const VECTOR>, PAIR>>>& GetSizesExpr(); void SetTemplateFlag(const bool templFlag) { isTemplFlag = templFlag; } bool IsTemplate() const { return isTemplFlag; } bool IsLoopArray() const { return isLoopArrayFlag; } bool IsArray() const { return !isTemplFlag && !isLoopArrayFlag; } void SetLoopArray(const bool flag) { isLoopArrayFlag = flag; } void SetSizesExpr(const VECTOR> &_sizesExpr) { for (int i = 0; i < _sizesExpr.size(); ++i) { sizesExpr[i].first.first = _sizesExpr[i].first; sizesExpr[i].second.first = _sizesExpr[i].second; } } int AddLinkWithTemplate(const int dimNum, const int dimTempl, Array *templateArray_, const PAIR &rule, const uint64_t regionId) { int err = 0; if (dimNum >= dimSize) err = -1; else { TemplateLink *currLink = getTemlateInfo(regionId, templateArray_ == NULL); currLink->AddRule(dimNum, dimTempl, rule, templateArray_); } return err; } VECTOR GetLinksWithTemplate(const uint64_t regionId) { TemplateLink *currLink = getTemlateInfo(regionId, true); return currLink->GetLinks(); } VECTOR> GetAlignRulesWithTemplate(const uint64_t regionId) { TemplateLink *currLink = getTemlateInfo(regionId, true); return currLink->GetAlignRules(); } bool HasTemplateInfo(const uint64_t regionId) const { auto it = templateInfo.find(regionId); return (it != templateInfo.end()); } void ChangeName(const STRING &newName) { auto pos = name.find(shortName); if (pos != STRING::npos) { name.erase(pos, shortName.size()); shortName = newName; name += newName; } GenUniqKey(); } void ExtendDimSize(const int dim, const PAIR &size) { /*if (size.first == size.second) return;*/ sizes[dim].first = std::min(sizes[dim].first, size.first); sizes[dim].second = std::max(sizes[dim].second, size.second); PAIR &left = sizesExpr[dim].first.second; PAIR &right = sizesExpr[dim].second.second; left.second = std::min(left.second, sizes[dim].first - left.first); right.second = std::max(right.second, sizes[dim].second - right.first); } void SetId(const unsigned newId) { id = newId; } const SET>& GetDeclInfo() const { return declPlaces; } const MAP, Symbol*>& GetDeclInfoWithSymb() const { return declPlacesSymbol; } void AddDeclInfo(const PAIR &declInfo, const SET& allFilesInProj, const STRING& currFile, Symbol* symb = NULL) { declPlaces.insert(declInfo); if (symb) { declPlacesSymbol[declInfo] = symb; if (allFilesInProj.find(declInfo.first) == allFilesInProj.end()) // from include declPlacesSymbolByFile[currFile][declInfo] = symb; } GenUniqKey(); } //save request of shadow spec void ExtendShadowSpec(const VECTOR> &newSpec) { if (allShadowSpecs.size() == 0) allShadowSpecs.resize(dimSize); const PAIR zeroPair(0, 0); for (int i = 0; i < newSpec.size(); ++i) if (newSpec[i] != zeroPair) allShadowSpecs[i].push_back(newSpec[i]); } //remove last requst of shadow spec void RemoveShadowSpec(const VECTOR> &delSpec) { int dimN = 0; for (auto &group : allShadowSpecs) { for (int i = 0; i < group.size(); ++i) { if (group[i] == delSpec[dimN]) { group.erase(group.begin() + i); break; } } ++dimN; } } //construct shadow spec from all requests const VECTOR> GetShadowSpec() const { VECTOR> shadowSpec; shadowSpec.resize(dimSize); for (int i = 0; i < dimSize; ++i) shadowSpec[i] = std::make_pair(0, 0); int dimN = 0; for (auto &group : allShadowSpecs) { for (auto &elem : group) { shadowSpec[dimN].first = std::max(shadowSpec[dimN].first, elem.first); shadowSpec[dimN].second = std::max(shadowSpec[dimN].second, elem.second); } ++dimN; } return shadowSpec; } void ClearShadowSpecs() { allShadowSpecs.clear(); } JSON toJson() { JSON retVal; retVal["id"] = (int64_t)id; retVal["name"] = name; retVal["shortName"] = shortName; retVal["packedAddress"] = std::to_string((long long)this); retVal["dimSize"] = dimSize; retVal["typeSize"] = typeSize; retVal["state"] = (int)isNonDistribute; retVal["location"] = (int)locationPos.first; retVal["locName"] = locationPos.second; retVal["isTemplFlag"] = (int)isTemplFlag; retVal["isLoopArrayFlag"] = (int)isLoopArrayFlag; JSON deprToDist = nlohmann::json::array(); for (int i = 0; i < depracateToDistribute.size(); ++i) deprToDist.push_back((int)depracateToDistribute[i]); retVal["depracateToDist"] = deprToDist; JSON mappedDimsJ = nlohmann::json::array(); for (int i = 0; i < mappedDims.size(); ++i) mappedDimsJ.push_back((int)mappedDims[i]); retVal["mappedDims"] = mappedDimsJ; JSON sizesJ = nlohmann::json::array(); for (int i = 0; i < sizes.size(); ++i) { JSON pair; pair["key"] = sizes[i].first; pair["value"] = sizes[i].second; sizesJ.push_back(pair); } retVal["sizes"] = sizesJ; JSON regions = nlohmann::json::array(); for (auto& reg : containsInRegions) regions.push_back(reg); retVal["regions"] = regions; JSON declPlacesJ = nlohmann::json::array(); for (auto& place : declPlaces) { JSON elem; elem["file"] = place.first; elem["line"] = place.second; declPlacesJ.push_back(elem); } retVal["declPlaces"] = declPlacesJ; return retVal; } Array* GetTemplateArray(const uint64_t regionId, bool withCheck = true) { TemplateLink *currLink = getTemlateInfo(regionId, withCheck); return currLink->GetTemplateArray(); } void SetDistributeFlag(const distFlag isNonDistribute_) { isNonDistribute = isNonDistribute_; } bool IsNotDistribute() const { return (isNonDistribute == DISTR) ? false : true; } distFlag GetDistributeFlagVal() const { return isNonDistribute; } void ChangeLocation(arrayLocation loc, const STRING &name) { locationPos = std::make_pair(loc, name); } void SetLocation(arrayLocation loc, const STRING &name) { ChangeLocation(loc, name); GenUniqKey(); } PAIR GetLocation() const { return locationPos; } Symbol* GetDeclSymbol(const STRING& file, const PAIR& range, const SET& allFilesInProj) const { if (!IsArray() || locationPos.first != l_COMMON) return declSymbol; for (auto& pos : declPlacesSymbol) { if (pos.first.first == file) { const int line = pos.first.second; if (range.first <= line && line <= range.second) return pos.second; } // may be in include? else if (allFilesInProj.find(pos.first.first) == allFilesInProj.end() && allFilesInProj.size()) { auto it = declPlacesSymbolByFile.find(file); if (it != declPlacesSymbolByFile.end() && it->second.find(pos.first) != it->second.end()) { auto s = it->second.find(pos.first); return s->second; } else #if __SPF printInternalError(convertFileName(__FILE__).c_str(), __LINE__); #else return NULL; #endif return NULL; } } #if __SPF printInternalError(convertFileName(__FILE__).c_str(), __LINE__); #endif return NULL; } Symbol* GetDeclSymbol() const { return declSymbol; } void SetDeclSymbol(Symbol *s) { declSymbol = s; } const STRING& GetArrayUniqKey() const { return uniqKey; } STRING GetIndepUniqName() const { return shortName + locationPos.second + TO_STR(dimSize); } const SET& GetRegionsName() const { return containsInRegions; } void SetRegionPlace(const STRING ®Name) { if (regName != "") containsInRegions.insert(regName); } const MAP>& GetUsagePlaces() const { return usagePlaces; } const SET GetUsagePlaces(const STRING& fileName, const PAIR* filter = NULL) const { auto it = usagePlaces.find(fileName); if (it == usagePlaces.end()) return SET(); if (!filter) return it->second; else { SET ret; int first = filter->first; int last = filter->second; for (auto& elem : it->second) if (first <= elem && elem <= last) ret.insert(elem); return ret; } } void AddUsagePlace(const STRING &fileName, int lineNumber) { auto it = usagePlaces.find(fileName); if (it == usagePlaces.end()) it = usagePlaces.insert(it, make_pair(fileName, SET())); it->second.insert(lineNumber); } void SetMappedDim(const int dim) { if (dim >= dimSize) return; mappedDims[dim] = true; } bool IsDimMapped(const int dim) const { if (dim >= dimSize) return false; else { if (templateDimsOrder.size() == 0) return mappedDims[dim]; else return mappedDims[templateDimsOrder[dim]]; } } void DeprecateDimension(const int dim, bool value = true) { if (dim >= dimSize) return; depracateToDistribute[dim] = value; } void DeprecateAllDims() { for (int dim = 0; dim < dimSize; ++dim) depracateToDistribute[dim] = true; } bool IsDimDepracated(const int dim) const { if (dim >= dimSize) return false; else { if (templateDimsOrder.size() == 0) return depracateToDistribute[dim]; else return depracateToDistribute[templateDimsOrder[dim]]; } } bool IsAllDeprecated() const { bool ret = true; for (int z = 0; z < dimSize; ++z) ret = ret && depracateToDistribute[z]; return ret; } const VECTOR& GetDeprecetedDims() const { return depracateToDistribute; } int GetTypeSize() const { return typeSize; } STRING AddTemplateClone(const VECTOR &newDist) { auto it = templateClones.find(newDist); if (it == templateClones.end()) it = templateClones.insert(it, std::make_pair(newDist, shortName + STRING("_r") + TO_STR(templateClones.size()))); return it->second; } void ClearTemplateClones() { templateClones.clear(); templateDimsOrder.clear(); orderedSizes.clear(); orderedSizesExpr.clear(); } const MAP, STRING>& GetAllClones() const { return templateClones; } void AddNewTemplateDimsOrder(const VECTOR &newOrder) { templateDimsOrder = newOrder; } VECTOR GetNewTemplateDimsOrder() const { return templateDimsOrder; } void SetDimSizesToMaxMin(bool notCopyToExpr = false) { for (int i = 0; i < dimSize; ++i) sizes[i] = std::make_pair((int)INT_MAX, (int)INT_MIN); if (!notCopyToExpr) { for (int i = 0; i < sizesExpr.size(); ++i) { sizesExpr[i].first.second.first = sizes[i].first; sizesExpr[i].second.second.first = sizes[i].second; } } } bool IsOmpThreadPrivate() const { return ompThreadPrivate; } bool IsSpfPrivate() const { return ((isNonDistribute == SPF_PRIV) || (isNonDistribute == IO_PRIV)); } bool IsInEquvalence() const { return inEquivalence; } void SetEquvalence(bool value) { inEquivalence = value; } bool IsPrivateInLoop() const { return privateInLoop; } void SetPrivateInLoopStatus(bool value) { privateInLoop = value; } bool IsModuleSymbol() const { return locationPos.first == l_MODULE; } ~Array() { for (auto &templ : templateInfo) delete templ.second; } }; struct ArrayComparator { bool operator()(const Array* left, const Array* right) const { return (left->GetArrayUniqKey() > right->GetArrayUniqKey()); } }; struct UnaryAccess { UnaryAccess() { line = -1; type = -1; underFunctionPar = -1; fName = ""; count = 0; } UnaryAccess(const PAIR& info) { line = info.first; type = info.second; underFunctionPar = -1; fName = ""; count = 1; } UnaryAccess(const PAIR& info, const STRING &f, const int parN) { line = info.first; type = info.second; underFunctionPar = parN; fName = f; count = 1; } STRING PrintInfo() const { STRING out = "#" + std::to_string(count) + " of "; if (type == 0) out += "READ "; else if(type == 1) out += "WRITE "; else out += "UNKN "; out += "on line " + std::to_string(line); if (underFunctionPar != -1) out += " in '#" + std::to_string(underFunctionPar + 1) + "' par of function call '" + fName + "'"; return out; } bool operator==(const UnaryAccess &left) const { return (line == left.line && type == left.type && underFunctionPar == left.underFunctionPar && fName == left.fName); } bool operator!=(const UnaryAccess& left) const { return !(*this == left); } int line; int type; // R/W -> 0, 1 int underFunctionPar; STRING fName; int count; }; class ArrayAccessInfo { private: MAP>> accessPatterns; // file -> MAP public: void AddAccessInfo(const STRING& file, const PAIR &info, const STRING fName = "", int underParN = -1) { auto it = accessPatterns.find(file); if (it == accessPatterns.end()) it = accessPatterns.insert(it, std::make_pair(file, MAP>())); bool found = false; UnaryAccess toAdd; if (underParN == -1) toAdd = UnaryAccess(info); else toAdd = UnaryAccess(info, fName, underParN); auto itMap = it->second.find(info.first); if (itMap == it->second.end()) it->second[info.first].push_back(toAdd); else { for (int z = 0; z < itMap->second.size(); ++z) { if (itMap->second[z] == toAdd) { found = true; itMap->second[z].count++; break; } } if (found == false) { if (underParN == -1) itMap->second.push_back(toAdd); else itMap->second.push_back(toAdd); } } } void checkAndUpdate(const MAP& allFuncs); const MAP>>& GetAllAccessInfo() const { return accessPatterns; } const MAP>* GetAccessInfoByFile(const STRING &file) const { auto it = accessPatterns.find(file); if (it == accessPatterns.end()) return NULL; else return &(it->second); } }; void printArrayInfo(const STRING &file, const MAP, PAIR> &declaredArrays); void fixTypeOfArrayInfoWithCallGraph(MAP, PAIR>& declaredArrays, const MAP& allFuncs); } #undef VECTOR #undef STRING #undef PAIR #undef MAP #undef SET #undef TO_STR